1/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 */
2/* Copyright (c) 2017-2018 Mellanox Technologies. All rights reserved */
3
4#ifndef _MLXSW_CORE_ACL_FLEX_KEYS_H
5#define _MLXSW_CORE_ACL_FLEX_KEYS_H
6
7#include <linux/types.h>
8#include <linux/bitmap.h>
9
10#include "item.h"
11
12enum mlxsw_afk_element {
13 MLXSW_AFK_ELEMENT_SRC_SYS_PORT,
14 MLXSW_AFK_ELEMENT_DMAC_32_47,
15 MLXSW_AFK_ELEMENT_DMAC_0_31,
16 MLXSW_AFK_ELEMENT_SMAC_32_47,
17 MLXSW_AFK_ELEMENT_SMAC_0_31,
18 MLXSW_AFK_ELEMENT_ETHERTYPE,
19 MLXSW_AFK_ELEMENT_IP_PROTO,
20 MLXSW_AFK_ELEMENT_SRC_IP_96_127,
21 MLXSW_AFK_ELEMENT_SRC_IP_64_95,
22 MLXSW_AFK_ELEMENT_SRC_IP_32_63,
23 MLXSW_AFK_ELEMENT_SRC_IP_0_31,
24 MLXSW_AFK_ELEMENT_DST_IP_96_127,
25 MLXSW_AFK_ELEMENT_DST_IP_64_95,
26 MLXSW_AFK_ELEMENT_DST_IP_32_63,
27 MLXSW_AFK_ELEMENT_DST_IP_0_31,
28 MLXSW_AFK_ELEMENT_DST_L4_PORT,
29 MLXSW_AFK_ELEMENT_SRC_L4_PORT,
30 MLXSW_AFK_ELEMENT_VID,
31 MLXSW_AFK_ELEMENT_PCP,
32 MLXSW_AFK_ELEMENT_TCP_FLAGS,
33 MLXSW_AFK_ELEMENT_IP_TTL_,
34 MLXSW_AFK_ELEMENT_IP_ECN,
35 MLXSW_AFK_ELEMENT_IP_DSCP,
36 MLXSW_AFK_ELEMENT_VIRT_ROUTER,
37 MLXSW_AFK_ELEMENT_FDB_MISS,
38 MLXSW_AFK_ELEMENT_L4_PORT_RANGE,
39 MLXSW_AFK_ELEMENT_VIRT_ROUTER_0_3,
40 MLXSW_AFK_ELEMENT_VIRT_ROUTER_4_7,
41 MLXSW_AFK_ELEMENT_VIRT_ROUTER_MSB,
42 MLXSW_AFK_ELEMENT_MAX,
43};
44
45enum mlxsw_afk_element_type {
46 MLXSW_AFK_ELEMENT_TYPE_U32,
47 MLXSW_AFK_ELEMENT_TYPE_BUF,
48};
49
50struct mlxsw_afk_element_info {
51 enum mlxsw_afk_element element; /* element ID */
52 enum mlxsw_afk_element_type type;
53 struct mlxsw_item item; /* element geometry in internal storage */
54};
55
56#define MLXSW_AFK_ELEMENT_INFO(_type, _element, _offset, _shift, _size) \
57 [MLXSW_AFK_ELEMENT_##_element] = { \
58 .element = MLXSW_AFK_ELEMENT_##_element, \
59 .type = _type, \
60 .item = { \
61 .offset = _offset, \
62 .shift = _shift, \
63 .size = {.bits = _size}, \
64 .name = #_element, \
65 }, \
66 }
67
68#define MLXSW_AFK_ELEMENT_INFO_U32(_element, _offset, _shift, _size) \
69 MLXSW_AFK_ELEMENT_INFO(MLXSW_AFK_ELEMENT_TYPE_U32, \
70 _element, _offset, _shift, _size)
71
72#define MLXSW_AFK_ELEMENT_INFO_BUF(_element, _offset, _size) \
73 MLXSW_AFK_ELEMENT_INFO(MLXSW_AFK_ELEMENT_TYPE_BUF, \
74 _element, _offset, 0, _size)
75
76#define MLXSW_AFK_ELEMENT_STORAGE_SIZE 0x44
77
78struct mlxsw_afk_element_inst { /* element instance in actual block */
79 enum mlxsw_afk_element element;
80 enum mlxsw_afk_element_type type;
81 struct mlxsw_item item; /* element geometry in block */
82 int u32_key_diff; /* in case value needs to be adjusted before write
83 * this diff is here to handle that
84 */
85 bool avoid_size_check;
86};
87
88#define MLXSW_AFK_ELEMENT_INST(_type, _element, _offset, \
89 _shift, _size, _u32_key_diff, _avoid_size_check) \
90 { \
91 .element = MLXSW_AFK_ELEMENT_##_element, \
92 .type = _type, \
93 .item = { \
94 .offset = _offset, \
95 .shift = _shift, \
96 .size = {.bits = _size}, \
97 .name = #_element, \
98 }, \
99 .u32_key_diff = _u32_key_diff, \
100 .avoid_size_check = _avoid_size_check, \
101 }
102
103#define MLXSW_AFK_ELEMENT_INST_U32(_element, _offset, _shift, _size) \
104 MLXSW_AFK_ELEMENT_INST(MLXSW_AFK_ELEMENT_TYPE_U32, \
105 _element, _offset, _shift, _size, 0, false)
106
107#define MLXSW_AFK_ELEMENT_INST_EXT_U32(_element, _offset, \
108 _shift, _size, _key_diff, \
109 _avoid_size_check) \
110 MLXSW_AFK_ELEMENT_INST(MLXSW_AFK_ELEMENT_TYPE_U32, \
111 _element, _offset, _shift, _size, \
112 _key_diff, _avoid_size_check)
113
114#define MLXSW_AFK_ELEMENT_INST_BUF(_element, _offset, _size) \
115 MLXSW_AFK_ELEMENT_INST(MLXSW_AFK_ELEMENT_TYPE_BUF, \
116 _element, _offset, 0, _size, 0, false)
117
118struct mlxsw_afk_block {
119 u16 encoding; /* block ID */
120 struct mlxsw_afk_element_inst *instances;
121 unsigned int instances_count;
122 bool high_entropy;
123};
124
125#define MLXSW_AFK_BLOCK(_encoding, _instances) \
126 { \
127 .encoding = _encoding, \
128 .instances = _instances, \
129 .instances_count = ARRAY_SIZE(_instances), \
130 }
131
132#define MLXSW_AFK_BLOCK_HIGH_ENTROPY(_encoding, _instances) \
133 { \
134 .encoding = _encoding, \
135 .instances = _instances, \
136 .instances_count = ARRAY_SIZE(_instances), \
137 .high_entropy = true, \
138 }
139
140struct mlxsw_afk_element_usage {
141 DECLARE_BITMAP(usage, MLXSW_AFK_ELEMENT_MAX);
142};
143
144#define mlxsw_afk_element_usage_for_each(element, elusage) \
145 for_each_set_bit(element, (elusage)->usage, MLXSW_AFK_ELEMENT_MAX)
146
147static inline void
148mlxsw_afk_element_usage_add(struct mlxsw_afk_element_usage *elusage,
149 enum mlxsw_afk_element element)
150{
151 __set_bit(element, elusage->usage);
152}
153
154static inline void
155mlxsw_afk_element_usage_zero(struct mlxsw_afk_element_usage *elusage)
156{
157 bitmap_zero(dst: elusage->usage, nbits: MLXSW_AFK_ELEMENT_MAX);
158}
159
160static inline void
161mlxsw_afk_element_usage_fill(struct mlxsw_afk_element_usage *elusage,
162 const enum mlxsw_afk_element *elements,
163 unsigned int elements_count)
164{
165 int i;
166
167 mlxsw_afk_element_usage_zero(elusage);
168 for (i = 0; i < elements_count; i++)
169 mlxsw_afk_element_usage_add(elusage, element: elements[i]);
170}
171
172static inline bool
173mlxsw_afk_element_usage_subset(struct mlxsw_afk_element_usage *elusage_small,
174 struct mlxsw_afk_element_usage *elusage_big)
175{
176 int i;
177
178 for (i = 0; i < MLXSW_AFK_ELEMENT_MAX; i++)
179 if (test_bit(i, elusage_small->usage) &&
180 !test_bit(i, elusage_big->usage))
181 return false;
182 return true;
183}
184
185struct mlxsw_afk;
186
187struct mlxsw_afk_ops {
188 const struct mlxsw_afk_block *blocks;
189 unsigned int blocks_count;
190 void (*encode_block)(char *output, int block_index, char *block);
191 void (*clear_block)(char *output, int block_index);
192};
193
194struct mlxsw_afk *mlxsw_afk_create(unsigned int max_blocks,
195 const struct mlxsw_afk_ops *ops);
196void mlxsw_afk_destroy(struct mlxsw_afk *mlxsw_afk);
197
198struct mlxsw_afk_key_info;
199
200struct mlxsw_afk_key_info *
201mlxsw_afk_key_info_get(struct mlxsw_afk *mlxsw_afk,
202 struct mlxsw_afk_element_usage *elusage);
203void mlxsw_afk_key_info_put(struct mlxsw_afk_key_info *key_info);
204bool mlxsw_afk_key_info_subset(struct mlxsw_afk_key_info *key_info,
205 struct mlxsw_afk_element_usage *elusage);
206
207u16
208mlxsw_afk_key_info_block_encoding_get(const struct mlxsw_afk_key_info *key_info,
209 int block_index);
210unsigned int
211mlxsw_afk_key_info_blocks_count_get(const struct mlxsw_afk_key_info *key_info);
212
213struct mlxsw_afk_element_values {
214 struct mlxsw_afk_element_usage elusage;
215 struct {
216 char key[MLXSW_AFK_ELEMENT_STORAGE_SIZE];
217 char mask[MLXSW_AFK_ELEMENT_STORAGE_SIZE];
218 } storage;
219};
220
221void mlxsw_afk_values_add_u32(struct mlxsw_afk_element_values *values,
222 enum mlxsw_afk_element element,
223 u32 key_value, u32 mask_value);
224void mlxsw_afk_values_add_buf(struct mlxsw_afk_element_values *values,
225 enum mlxsw_afk_element element,
226 const char *key_value, const char *mask_value,
227 unsigned int len);
228void mlxsw_afk_encode(struct mlxsw_afk *mlxsw_afk,
229 struct mlxsw_afk_key_info *key_info,
230 struct mlxsw_afk_element_values *values,
231 char *key, char *mask);
232void mlxsw_afk_clear(struct mlxsw_afk *mlxsw_afk, char *key,
233 int block_start, int block_end);
234
235#endif
236

source code of linux/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.h