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(elusage->usage, 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, 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