1c8b034fbSLouis Peens /* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
2c8b034fbSLouis Peens /* Copyright (C) 2021 Corigine, Inc. */
3c8b034fbSLouis Peens 
4c8b034fbSLouis Peens #ifndef __NFP_FLOWER_CONNTRACK_H__
5c8b034fbSLouis Peens #define __NFP_FLOWER_CONNTRACK_H__ 1
6c8b034fbSLouis Peens 
762268e78SLouis Peens #include <net/netfilter/nf_flow_table.h>
8c8b034fbSLouis Peens #include "main.h"
9c8b034fbSLouis Peens 
10072c089cSLouis Peens #define NFP_FL_CT_NO_TUN	0xff
11072c089cSLouis Peens 
12c698e2adSLouis Peens #define COMPARE_UNMASKED_FIELDS(__match1, __match2, __out)	\
13c698e2adSLouis Peens 	do {							\
14c698e2adSLouis Peens 		typeof(__match1) _match1 = (__match1);		\
15c698e2adSLouis Peens 		typeof(__match2) _match2 = (__match2);		\
16c698e2adSLouis Peens 		bool *_out = (__out);		\
17c698e2adSLouis Peens 		int i, size = sizeof(*(_match1).key);		\
18c698e2adSLouis Peens 		char *k1, *m1, *k2, *m2;			\
19c698e2adSLouis Peens 		*_out = false;					\
20c698e2adSLouis Peens 		k1 = (char *)_match1.key;			\
21c698e2adSLouis Peens 		m1 = (char *)_match1.mask;			\
22c698e2adSLouis Peens 		k2 = (char *)_match2.key;			\
23c698e2adSLouis Peens 		m2 = (char *)_match2.mask;			\
24c698e2adSLouis Peens 		for (i = 0; i < size; i++)			\
25c698e2adSLouis Peens 			if ((k1[i] & m1[i] & m2[i]) ^		\
26c698e2adSLouis Peens 			    (k2[i] & m1[i] & m2[i])) {		\
27c698e2adSLouis Peens 				*_out = true;			\
28c698e2adSLouis Peens 				break;				\
29c698e2adSLouis Peens 			}					\
30c698e2adSLouis Peens 	} while (0)						\
31c698e2adSLouis Peens 
32e236e484SLouis Peens extern const struct rhashtable_params nfp_zone_table_params;
33fa81d6d2SLouis Peens extern const struct rhashtable_params nfp_ct_map_params;
34f7ae12e2SLouis Peens extern const struct rhashtable_params nfp_tc_ct_merge_params;
35b5e30c61SLouis Peens extern const struct rhashtable_params nfp_nft_ct_merge_params;
36e236e484SLouis Peens 
37e236e484SLouis Peens /**
38e236e484SLouis Peens  * struct nfp_fl_ct_zone_entry - Zone entry containing conntrack flow information
39e236e484SLouis Peens  * @zone:	The zone number, used as lookup key in hashtable
40e236e484SLouis Peens  * @hash_node:	Used by the hashtable
41e236e484SLouis Peens  * @priv:	Pointer to nfp_flower_priv data
42e236e484SLouis Peens  * @nft:	Pointer to nf_flowtable for this zone
43072c089cSLouis Peens  *
44072c089cSLouis Peens  * @pre_ct_list:	The pre_ct_list of nfp_fl_ct_flow_entry entries
45072c089cSLouis Peens  * @pre_ct_count:	Keep count of the number of pre_ct entries
46072c089cSLouis Peens  *
47072c089cSLouis Peens  * @post_ct_list:	The post_ct_list of nfp_fl_ct_flow_entry entries
48072c089cSLouis Peens  * @post_ct_count:	Keep count of the number of post_ct entries
49f7ae12e2SLouis Peens  *
50f7ae12e2SLouis Peens  * @tc_merge_tb:	The table of merged tc flows
51f7ae12e2SLouis Peens  * @tc_merge_count:	Keep count of the number of merged tc entries
5295255017SLouis Peens  *
5395255017SLouis Peens  * @nft_flows_list:	The list of nft relatednfp_fl_ct_flow_entry entries
5495255017SLouis Peens  * @nft_flows_count:	Keep count of the number of nft_flow entries
55b5e30c61SLouis Peens  *
56b5e30c61SLouis Peens  * @nft_merge_tb:	The table of merged tc+nft flows
57b5e30c61SLouis Peens  * @nft_merge_count:	Keep count of the number of merged tc+nft entries
58e236e484SLouis Peens  */
59e236e484SLouis Peens struct nfp_fl_ct_zone_entry {
60e236e484SLouis Peens 	u16 zone;
61e236e484SLouis Peens 	struct rhash_head hash_node;
62e236e484SLouis Peens 
63e236e484SLouis Peens 	struct nfp_flower_priv *priv;
64e236e484SLouis Peens 	struct nf_flowtable *nft;
65072c089cSLouis Peens 
66072c089cSLouis Peens 	struct list_head pre_ct_list;
67072c089cSLouis Peens 	unsigned int pre_ct_count;
68072c089cSLouis Peens 
69072c089cSLouis Peens 	struct list_head post_ct_list;
70072c089cSLouis Peens 	unsigned int post_ct_count;
71f7ae12e2SLouis Peens 
72f7ae12e2SLouis Peens 	struct rhashtable tc_merge_tb;
73f7ae12e2SLouis Peens 	unsigned int tc_merge_count;
7495255017SLouis Peens 
7595255017SLouis Peens 	struct list_head nft_flows_list;
7695255017SLouis Peens 	unsigned int nft_flows_count;
77b5e30c61SLouis Peens 
78b5e30c61SLouis Peens 	struct rhashtable nft_merge_tb;
79b5e30c61SLouis Peens 	unsigned int nft_merge_count;
80072c089cSLouis Peens };
81072c089cSLouis Peens 
82072c089cSLouis Peens enum ct_entry_type {
83072c089cSLouis Peens 	CT_TYPE_PRE_CT,
84072c089cSLouis Peens 	CT_TYPE_NFT,
85072c089cSLouis Peens 	CT_TYPE_POST_CT,
8671e88cfbSLouis Peens 	_CT_TYPE_MAX,
8771e88cfbSLouis Peens };
8871e88cfbSLouis Peens 
89*a87ceb3dSWentao Jia #define NFP_MAX_RECIRC_CT_ZONES 4
90*a87ceb3dSWentao Jia #define NFP_MAX_ENTRY_RULES  (NFP_MAX_RECIRC_CT_ZONES * 2 + 1)
91*a87ceb3dSWentao Jia 
9271e88cfbSLouis Peens enum nfp_nfp_layer_name {
9371e88cfbSLouis Peens 	FLOW_PAY_META_TCI =    0,
9471e88cfbSLouis Peens 	FLOW_PAY_INPORT,
9571e88cfbSLouis Peens 	FLOW_PAY_EXT_META,
9671e88cfbSLouis Peens 	FLOW_PAY_MAC_MPLS,
9771e88cfbSLouis Peens 	FLOW_PAY_L4,
9871e88cfbSLouis Peens 	FLOW_PAY_IPV4,
9971e88cfbSLouis Peens 	FLOW_PAY_IPV6,
10071e88cfbSLouis Peens 	FLOW_PAY_CT,
10171e88cfbSLouis Peens 	FLOW_PAY_GRE,
10271e88cfbSLouis Peens 	FLOW_PAY_QINQ,
10371e88cfbSLouis Peens 	FLOW_PAY_UDP_TUN,
10471e88cfbSLouis Peens 	FLOW_PAY_GENEVE_OPT,
10571e88cfbSLouis Peens 
10671e88cfbSLouis Peens 	_FLOW_PAY_LAYERS_MAX
107072c089cSLouis Peens };
108072c089cSLouis Peens 
1095cee92c6SHui Zhou /* NFP flow entry flags. */
1105cee92c6SHui Zhou #define NFP_FL_ACTION_DO_NAT		BIT(0)
1115cee92c6SHui Zhou #define NFP_FL_ACTION_DO_MANGLE		BIT(1)
1125cee92c6SHui Zhou 
113072c089cSLouis Peens /**
114072c089cSLouis Peens  * struct nfp_fl_ct_flow_entry - Flow entry containing conntrack flow information
115072c089cSLouis Peens  * @cookie:	Flow cookie, same as original TC flow, used as key
116072c089cSLouis Peens  * @list_node:	Used by the list
117072c089cSLouis Peens  * @chain_index:	Chain index of the original flow
1183e44d199SWentao Jia  * @goto_chain_index:	goto chain index of the flow
119072c089cSLouis Peens  * @netdev:	netdev structure.
120072c089cSLouis Peens  * @zt:		Reference to the zone table this belongs to
121072c089cSLouis Peens  * @children:	List of tc_merge flows this flow forms part of
122072c089cSLouis Peens  * @rule:	Reference to the original TC flow rule
123072c089cSLouis Peens  * @stats:	Used to cache stats for updating
124*a87ceb3dSWentao Jia  * @prev_m_entries:	Array of all previous nft_tc_merge entries
125*a87ceb3dSWentao Jia  * @num_prev_m_entries:	The number of all previous nft_tc_merge entries
126072c089cSLouis Peens  * @tun_offset: Used to indicate tunnel action offset in action list
1275cee92c6SHui Zhou  * @flags:	Used to indicate flow flag like NAT which used by merge.
128*a87ceb3dSWentao Jia  * @type:	Type of ct-entry from enum ct_entry_type
129072c089cSLouis Peens  */
130072c089cSLouis Peens struct nfp_fl_ct_flow_entry {
131072c089cSLouis Peens 	unsigned long cookie;
132072c089cSLouis Peens 	struct list_head list_node;
133072c089cSLouis Peens 	u32 chain_index;
1343e44d199SWentao Jia 	u32 goto_chain_index;
135072c089cSLouis Peens 	struct net_device *netdev;
136072c089cSLouis Peens 	struct nfp_fl_ct_zone_entry *zt;
137072c089cSLouis Peens 	struct list_head children;
138072c089cSLouis Peens 	struct flow_rule *rule;
139072c089cSLouis Peens 	struct flow_stats stats;
140*a87ceb3dSWentao Jia 	struct nfp_fl_nft_tc_merge *prev_m_entries[NFP_MAX_RECIRC_CT_ZONES - 1];
141*a87ceb3dSWentao Jia 	u8 num_prev_m_entries;
142072c089cSLouis Peens 	u8 tun_offset;		// Set to NFP_FL_CT_NO_TUN if no tun
1435cee92c6SHui Zhou 	u8 flags;
144*a87ceb3dSWentao Jia 	u8 type;
145e236e484SLouis Peens };
146e236e484SLouis Peens 
147fa81d6d2SLouis Peens /**
148f7ae12e2SLouis Peens  * struct nfp_fl_ct_tc_merge - Merge of two flows from tc
149f7ae12e2SLouis Peens  * @cookie:		Flow cookie, combination of pre and post ct cookies
150f7ae12e2SLouis Peens  * @hash_node:		Used by the hashtable
151f7ae12e2SLouis Peens  * @pre_ct_list:	This entry is part of a pre_ct_list
152f7ae12e2SLouis Peens  * @post_ct_list:	This entry is part of a post_ct_list
153f7ae12e2SLouis Peens  * @zt:			Reference to the zone table this belongs to
154f7ae12e2SLouis Peens  * @pre_ct_parent:	The pre_ct_parent
155f7ae12e2SLouis Peens  * @post_ct_parent:	The post_ct_parent
156f7ae12e2SLouis Peens  * @children:		List of nft merged entries
157f7ae12e2SLouis Peens  */
158f7ae12e2SLouis Peens struct nfp_fl_ct_tc_merge {
159f7ae12e2SLouis Peens 	unsigned long cookie[2];
160f7ae12e2SLouis Peens 	struct rhash_head hash_node;
161f7ae12e2SLouis Peens 	struct list_head pre_ct_list;
162f7ae12e2SLouis Peens 	struct list_head post_ct_list;
163f7ae12e2SLouis Peens 	struct nfp_fl_ct_zone_entry *zt;
164f7ae12e2SLouis Peens 	struct nfp_fl_ct_flow_entry *pre_ct_parent;
165f7ae12e2SLouis Peens 	struct nfp_fl_ct_flow_entry *post_ct_parent;
166f7ae12e2SLouis Peens 	struct list_head children;
167f7ae12e2SLouis Peens };
168f7ae12e2SLouis Peens 
169f7ae12e2SLouis Peens /**
170b5e30c61SLouis Peens  * struct nfp_fl_nft_tc_merge - Merge of tc_merge flows with nft flow
171b5e30c61SLouis Peens  * @netdev:		Ingress netdev name
172b5e30c61SLouis Peens  * @cookie:		Flow cookie, combination of tc_merge and nft cookies
173b5e30c61SLouis Peens  * @hash_node:		Used by the hashtable
174b5e30c61SLouis Peens  * @zt:	Reference to the zone table this belongs to
175b5e30c61SLouis Peens  * @nft_flow_list:	This entry is part of a nft_flows_list
176b5e30c61SLouis Peens  * @tc_merge_list:	This entry is part of a ct_merge_list
177b5e30c61SLouis Peens  * @tc_m_parent:	The tc_merge parent
178b5e30c61SLouis Peens  * @nft_parent:	The nft_entry parent
179b5e30c61SLouis Peens  * @tc_flower_cookie:	The cookie of the flow offloaded to the nfp
180b5e30c61SLouis Peens  * @flow_pay:	Reference to the offloaded flow struct
181*a87ceb3dSWentao Jia  * @next_pre_ct_entry:	Reference to the next ct zone pre ct entry
182b5e30c61SLouis Peens  */
183b5e30c61SLouis Peens struct nfp_fl_nft_tc_merge {
184b5e30c61SLouis Peens 	struct net_device *netdev;
185b5e30c61SLouis Peens 	unsigned long cookie[3];
186b5e30c61SLouis Peens 	struct rhash_head hash_node;
187b5e30c61SLouis Peens 	struct nfp_fl_ct_zone_entry *zt;
188b5e30c61SLouis Peens 	struct list_head nft_flow_list;
189b5e30c61SLouis Peens 	struct list_head tc_merge_list;
190b5e30c61SLouis Peens 	struct nfp_fl_ct_tc_merge *tc_m_parent;
191b5e30c61SLouis Peens 	struct nfp_fl_ct_flow_entry *nft_parent;
192b5e30c61SLouis Peens 	unsigned long tc_flower_cookie;
193b5e30c61SLouis Peens 	struct nfp_fl_payload *flow_pay;
194*a87ceb3dSWentao Jia 	struct nfp_fl_ct_flow_entry *next_pre_ct_entry;
195b5e30c61SLouis Peens };
196b5e30c61SLouis Peens 
197b5e30c61SLouis Peens /**
198fa81d6d2SLouis Peens  * struct nfp_fl_ct_map_entry - Map between flow cookie and specific ct_flow
199fa81d6d2SLouis Peens  * @cookie:	Flow cookie, same as original TC flow, used as key
200fa81d6d2SLouis Peens  * @hash_node:	Used by the hashtable
201fa81d6d2SLouis Peens  * @ct_entry:	Pointer to corresponding ct_entry
202fa81d6d2SLouis Peens  */
203fa81d6d2SLouis Peens struct nfp_fl_ct_map_entry {
204fa81d6d2SLouis Peens 	unsigned long cookie;
205fa81d6d2SLouis Peens 	struct rhash_head hash_node;
206fa81d6d2SLouis Peens 	struct nfp_fl_ct_flow_entry *ct_entry;
207fa81d6d2SLouis Peens };
208fa81d6d2SLouis Peens 
209c8b034fbSLouis Peens bool is_pre_ct_flow(struct flow_cls_offload *flow);
210c8b034fbSLouis Peens bool is_post_ct_flow(struct flow_cls_offload *flow);
211c8b034fbSLouis Peens 
212c8b034fbSLouis Peens /**
213c8b034fbSLouis Peens  * nfp_fl_ct_handle_pre_ct() - Handles -trk conntrack rules
214c8b034fbSLouis Peens  * @priv:	Pointer to app priv
215c8b034fbSLouis Peens  * @netdev:	netdev structure.
216c8b034fbSLouis Peens  * @flow:	TC flower classifier offload structure.
217c8b034fbSLouis Peens  * @extack:	Extack pointer for errors
218*a87ceb3dSWentao Jia  * @m_entry:previous nfp_fl_nft_tc_merge entry
219c8b034fbSLouis Peens  *
220c8b034fbSLouis Peens  * Adds a new entry to the relevant zone table and tries to
221c8b034fbSLouis Peens  * merge with other +trk+est entries and offload if possible.
222c8b034fbSLouis Peens  *
223c8b034fbSLouis Peens  * Return: negative value on error, 0 if configured successfully.
224c8b034fbSLouis Peens  */
225c8b034fbSLouis Peens int nfp_fl_ct_handle_pre_ct(struct nfp_flower_priv *priv,
226c8b034fbSLouis Peens 			    struct net_device *netdev,
227c8b034fbSLouis Peens 			    struct flow_cls_offload *flow,
228*a87ceb3dSWentao Jia 			    struct netlink_ext_ack *extack,
229*a87ceb3dSWentao Jia 			    struct nfp_fl_nft_tc_merge *m_entry);
230c8b034fbSLouis Peens /**
231c8b034fbSLouis Peens  * nfp_fl_ct_handle_post_ct() - Handles +trk+est conntrack rules
232c8b034fbSLouis Peens  * @priv:	Pointer to app priv
233c8b034fbSLouis Peens  * @netdev:	netdev structure.
234c8b034fbSLouis Peens  * @flow:	TC flower classifier offload structure.
235c8b034fbSLouis Peens  * @extack:	Extack pointer for errors
236c8b034fbSLouis Peens  *
237c8b034fbSLouis Peens  * Adds a new entry to the relevant zone table and tries to
238c8b034fbSLouis Peens  * merge with other -trk entries and offload if possible.
239c8b034fbSLouis Peens  *
240c8b034fbSLouis Peens  * Return: negative value on error, 0 if configured successfully.
241c8b034fbSLouis Peens  */
242c8b034fbSLouis Peens int nfp_fl_ct_handle_post_ct(struct nfp_flower_priv *priv,
243c8b034fbSLouis Peens 			     struct net_device *netdev,
244c8b034fbSLouis Peens 			     struct flow_cls_offload *flow,
245c8b034fbSLouis Peens 			     struct netlink_ext_ack *extack);
246c8b034fbSLouis Peens 
247072c089cSLouis Peens /**
248*a87ceb3dSWentao Jia  * nfp_fl_create_new_pre_ct() - create next ct_zone -trk conntrack rules
249*a87ceb3dSWentao Jia  * @m_entry:previous nfp_fl_nft_tc_merge entry
250*a87ceb3dSWentao Jia  *
251*a87ceb3dSWentao Jia  * Create a new pre_ct entry from previous nfp_fl_nft_tc_merge entry
252*a87ceb3dSWentao Jia  * to the next relevant zone table. Try to merge with other +trk+est
253*a87ceb3dSWentao Jia  * entries and offload if possible. The created new pre_ct entry is
254*a87ceb3dSWentao Jia  * linked to the previous nfp_fl_nft_tc_merge entry.
255*a87ceb3dSWentao Jia  *
256*a87ceb3dSWentao Jia  * Return: negative value on error, 0 if configured successfully.
257*a87ceb3dSWentao Jia  */
258*a87ceb3dSWentao Jia int nfp_fl_create_new_pre_ct(struct nfp_fl_nft_tc_merge *m_entry);
259*a87ceb3dSWentao Jia 
260*a87ceb3dSWentao Jia /**
261072c089cSLouis Peens  * nfp_fl_ct_clean_flow_entry() - Free a nfp_fl_ct_flow_entry
262072c089cSLouis Peens  * @entry:	Flow entry to cleanup
263072c089cSLouis Peens  */
264072c089cSLouis Peens void nfp_fl_ct_clean_flow_entry(struct nfp_fl_ct_flow_entry *entry);
265d33d24a7SLouis Peens 
266d33d24a7SLouis Peens /**
267d33d24a7SLouis Peens  * nfp_fl_ct_del_flow() - Handle flow_del callbacks for conntrack
268d33d24a7SLouis Peens  * @ct_map_ent:	ct map entry for the flow that needs deleting
269d33d24a7SLouis Peens  */
270d33d24a7SLouis Peens int nfp_fl_ct_del_flow(struct nfp_fl_ct_map_entry *ct_map_ent);
27162268e78SLouis Peens 
27262268e78SLouis Peens /**
27362268e78SLouis Peens  * nfp_fl_ct_handle_nft_flow() - Handle flower flow callbacks for nft table
27462268e78SLouis Peens  * @type:	Type provided by callback
27562268e78SLouis Peens  * @type_data:	Callback data
27662268e78SLouis Peens  * @cb_priv:	Pointer to data provided when registering the callback, in this
27762268e78SLouis Peens  *		case it's the zone table.
27862268e78SLouis Peens  */
27962268e78SLouis Peens int nfp_fl_ct_handle_nft_flow(enum tc_setup_type type, void *type_data,
28062268e78SLouis Peens 			      void *cb_priv);
28140c10bd9SLouis Peens 
28240c10bd9SLouis Peens /**
28340c10bd9SLouis Peens  * nfp_fl_ct_stats() - Handle flower stats callbacks for ct flows
28440c10bd9SLouis Peens  * @flow:	TC flower classifier offload structure.
28540c10bd9SLouis Peens  * @ct_map_ent:	ct map entry for the flow that needs deleting
28640c10bd9SLouis Peens  */
28740c10bd9SLouis Peens int nfp_fl_ct_stats(struct flow_cls_offload *flow,
28840c10bd9SLouis Peens 		    struct nfp_fl_ct_map_entry *ct_map_ent);
289c8b034fbSLouis Peens #endif
290