mlxsw: spectrum_flower: Add ability to match on layer 2 miss
[platform/kernel/linux-starfive.git] / drivers / net / ethernet / mellanox / mlxsw / core_acl_flex_keys.h
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
12 enum 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_MSB,
37         MLXSW_AFK_ELEMENT_VIRT_ROUTER_LSB,
38         MLXSW_AFK_ELEMENT_FDB_MISS,
39         MLXSW_AFK_ELEMENT_MAX,
40 };
41
42 enum mlxsw_afk_element_type {
43         MLXSW_AFK_ELEMENT_TYPE_U32,
44         MLXSW_AFK_ELEMENT_TYPE_BUF,
45 };
46
47 struct mlxsw_afk_element_info {
48         enum mlxsw_afk_element element; /* element ID */
49         enum mlxsw_afk_element_type type;
50         struct mlxsw_item item; /* element geometry in internal storage */
51 };
52
53 #define MLXSW_AFK_ELEMENT_INFO(_type, _element, _offset, _shift, _size)         \
54         [MLXSW_AFK_ELEMENT_##_element] = {                                      \
55                 .element = MLXSW_AFK_ELEMENT_##_element,                        \
56                 .type = _type,                                                  \
57                 .item = {                                                       \
58                         .offset = _offset,                                      \
59                         .shift = _shift,                                        \
60                         .size = {.bits = _size},                                \
61                         .name = #_element,                                      \
62                 },                                                              \
63         }
64
65 #define MLXSW_AFK_ELEMENT_INFO_U32(_element, _offset, _shift, _size)            \
66         MLXSW_AFK_ELEMENT_INFO(MLXSW_AFK_ELEMENT_TYPE_U32,                      \
67                                _element, _offset, _shift, _size)
68
69 #define MLXSW_AFK_ELEMENT_INFO_BUF(_element, _offset, _size)                    \
70         MLXSW_AFK_ELEMENT_INFO(MLXSW_AFK_ELEMENT_TYPE_BUF,                      \
71                                _element, _offset, 0, _size)
72
73 #define MLXSW_AFK_ELEMENT_STORAGE_SIZE 0x44
74
75 struct mlxsw_afk_element_inst { /* element instance in actual block */
76         enum mlxsw_afk_element element;
77         enum mlxsw_afk_element_type type;
78         struct mlxsw_item item; /* element geometry in block */
79         int u32_key_diff; /* in case value needs to be adjusted before write
80                            * this diff is here to handle that
81                            */
82         bool avoid_size_check;
83 };
84
85 #define MLXSW_AFK_ELEMENT_INST(_type, _element, _offset,                        \
86                                _shift, _size, _u32_key_diff, _avoid_size_check) \
87         {                                                                       \
88                 .element = MLXSW_AFK_ELEMENT_##_element,                        \
89                 .type = _type,                                                  \
90                 .item = {                                                       \
91                         .offset = _offset,                                      \
92                         .shift = _shift,                                        \
93                         .size = {.bits = _size},                                \
94                         .name = #_element,                                      \
95                 },                                                              \
96                 .u32_key_diff = _u32_key_diff,                                  \
97                 .avoid_size_check = _avoid_size_check,                          \
98         }
99
100 #define MLXSW_AFK_ELEMENT_INST_U32(_element, _offset, _shift, _size)            \
101         MLXSW_AFK_ELEMENT_INST(MLXSW_AFK_ELEMENT_TYPE_U32,                      \
102                                _element, _offset, _shift, _size, 0, false)
103
104 #define MLXSW_AFK_ELEMENT_INST_EXT_U32(_element, _offset,                       \
105                                        _shift, _size, _key_diff,                \
106                                        _avoid_size_check)                       \
107         MLXSW_AFK_ELEMENT_INST(MLXSW_AFK_ELEMENT_TYPE_U32,                      \
108                                _element, _offset, _shift, _size,                \
109                                _key_diff, _avoid_size_check)
110
111 #define MLXSW_AFK_ELEMENT_INST_BUF(_element, _offset, _size)                    \
112         MLXSW_AFK_ELEMENT_INST(MLXSW_AFK_ELEMENT_TYPE_BUF,                      \
113                                _element, _offset, 0, _size, 0, false)
114
115 struct mlxsw_afk_block {
116         u16 encoding; /* block ID */
117         struct mlxsw_afk_element_inst *instances;
118         unsigned int instances_count;
119 };
120
121 #define MLXSW_AFK_BLOCK(_encoding, _instances)                                  \
122         {                                                                       \
123                 .encoding = _encoding,                                          \
124                 .instances = _instances,                                        \
125                 .instances_count = ARRAY_SIZE(_instances),                      \
126         }
127
128 struct mlxsw_afk_element_usage {
129         DECLARE_BITMAP(usage, MLXSW_AFK_ELEMENT_MAX);
130 };
131
132 #define mlxsw_afk_element_usage_for_each(element, elusage)                      \
133         for_each_set_bit(element, (elusage)->usage, MLXSW_AFK_ELEMENT_MAX)
134
135 static inline void
136 mlxsw_afk_element_usage_add(struct mlxsw_afk_element_usage *elusage,
137                             enum mlxsw_afk_element element)
138 {
139         __set_bit(element, elusage->usage);
140 }
141
142 static inline void
143 mlxsw_afk_element_usage_zero(struct mlxsw_afk_element_usage *elusage)
144 {
145         bitmap_zero(elusage->usage, MLXSW_AFK_ELEMENT_MAX);
146 }
147
148 static inline void
149 mlxsw_afk_element_usage_fill(struct mlxsw_afk_element_usage *elusage,
150                              const enum mlxsw_afk_element *elements,
151                              unsigned int elements_count)
152 {
153         int i;
154
155         mlxsw_afk_element_usage_zero(elusage);
156         for (i = 0; i < elements_count; i++)
157                 mlxsw_afk_element_usage_add(elusage, elements[i]);
158 }
159
160 static inline bool
161 mlxsw_afk_element_usage_subset(struct mlxsw_afk_element_usage *elusage_small,
162                                struct mlxsw_afk_element_usage *elusage_big)
163 {
164         int i;
165
166         for (i = 0; i < MLXSW_AFK_ELEMENT_MAX; i++)
167                 if (test_bit(i, elusage_small->usage) &&
168                     !test_bit(i, elusage_big->usage))
169                         return false;
170         return true;
171 }
172
173 struct mlxsw_afk;
174
175 struct mlxsw_afk_ops {
176         const struct mlxsw_afk_block *blocks;
177         unsigned int blocks_count;
178         void (*encode_block)(char *output, int block_index, char *block);
179         void (*clear_block)(char *output, int block_index);
180 };
181
182 struct mlxsw_afk *mlxsw_afk_create(unsigned int max_blocks,
183                                    const struct mlxsw_afk_ops *ops);
184 void mlxsw_afk_destroy(struct mlxsw_afk *mlxsw_afk);
185
186 struct mlxsw_afk_key_info;
187
188 struct mlxsw_afk_key_info *
189 mlxsw_afk_key_info_get(struct mlxsw_afk *mlxsw_afk,
190                        struct mlxsw_afk_element_usage *elusage);
191 void mlxsw_afk_key_info_put(struct mlxsw_afk_key_info *key_info);
192 bool mlxsw_afk_key_info_subset(struct mlxsw_afk_key_info *key_info,
193                                struct mlxsw_afk_element_usage *elusage);
194
195 u16
196 mlxsw_afk_key_info_block_encoding_get(const struct mlxsw_afk_key_info *key_info,
197                                       int block_index);
198 unsigned int
199 mlxsw_afk_key_info_blocks_count_get(const struct mlxsw_afk_key_info *key_info);
200
201 struct mlxsw_afk_element_values {
202         struct mlxsw_afk_element_usage elusage;
203         struct {
204                 char key[MLXSW_AFK_ELEMENT_STORAGE_SIZE];
205                 char mask[MLXSW_AFK_ELEMENT_STORAGE_SIZE];
206         } storage;
207 };
208
209 void mlxsw_afk_values_add_u32(struct mlxsw_afk_element_values *values,
210                               enum mlxsw_afk_element element,
211                               u32 key_value, u32 mask_value);
212 void mlxsw_afk_values_add_buf(struct mlxsw_afk_element_values *values,
213                               enum mlxsw_afk_element element,
214                               const char *key_value, const char *mask_value,
215                               unsigned int len);
216 void mlxsw_afk_encode(struct mlxsw_afk *mlxsw_afk,
217                       struct mlxsw_afk_key_info *key_info,
218                       struct mlxsw_afk_element_values *values,
219                       char *key, char *mask);
220 void mlxsw_afk_clear(struct mlxsw_afk *mlxsw_afk, char *key,
221                      int block_start, int block_end);
222
223 #endif