aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/netronome/nfp/flower/conntrack.h
blob: beb6cceff9d8e88cbd1246beacca61f7368d4b2c (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
/* Copyright (C) 2021 Corigine, Inc. */

#ifndef __NFP_FLOWER_CONNTRACK_H__
#define __NFP_FLOWER_CONNTRACK_H__ 1

#include <net/netfilter/nf_flow_table.h>
#include "main.h"

#define NFP_FL_CT_NO_TUN	0xff

#define COMPARE_UNMASKED_FIELDS(__match1, __match2, __out)	\
	do {							\
		typeof(__match1) _match1 = (__match1);		\
		typeof(__match2) _match2 = (__match2);		\
		bool *_out = (__out);		\
		int i, size = sizeof(*(_match1).key);		\
		char *k1, *m1, *k2, *m2;			\
		*_out = false;					\
		k1 = (char *)_match1.key;			\
		m1 = (char *)_match1.mask;			\
		k2 = (char *)_match2.key;			\
		m2 = (char *)_match2.mask;			\
		for (i = 0; i < size; i++)			\
			if ((k1[i] & m1[i] & m2[i]) ^		\
			    (k2[i] & m1[i] & m2[i])) {		\
				*_out = true;			\
				break;				\
			}					\
	} while (0)						\

extern const struct rhashtable_params nfp_zone_table_params;
extern const struct rhashtable_params nfp_ct_map_params;
extern const struct rhashtable_params nfp_tc_ct_merge_params;
extern const struct rhashtable_params nfp_nft_ct_merge_params;

/**
 * struct nfp_fl_ct_zone_entry - Zone entry containing conntrack flow information
 * @zone:	The zone number, used as lookup key in hashtable
 * @hash_node:	Used by the hashtable
 * @priv:	Pointer to nfp_flower_priv data
 * @nft:	Pointer to nf_flowtable for this zone
 *
 * @pre_ct_list:	The pre_ct_list of nfp_fl_ct_flow_entry entries
 * @pre_ct_count:	Keep count of the number of pre_ct entries
 *
 * @post_ct_list:	The post_ct_list of nfp_fl_ct_flow_entry entries
 * @post_ct_count:	Keep count of the number of post_ct entries
 *
 * @tc_merge_tb:	The table of merged tc flows
 * @tc_merge_count:	Keep count of the number of merged tc entries
 *
 * @nft_flows_list:	The list of nft relatednfp_fl_ct_flow_entry entries
 * @nft_flows_count:	Keep count of the number of nft_flow entries
 *
 * @nft_merge_tb:	The table of merged tc+nft flows
 * @nft_merge_count:	Keep count of the number of merged tc+nft entries
 */
struct nfp_fl_ct_zone_entry {
	u16 zone;
	struct rhash_head hash_node;

	struct nfp_flower_priv *priv;
	struct nf_flowtable *nft;

	struct list_head pre_ct_list;
	unsigned int pre_ct_count;

	struct list_head post_ct_list;
	unsigned int post_ct_count;

	struct rhashtable tc_merge_tb;
	unsigned int tc_merge_count;

	struct list_head nft_flows_list;
	unsigned int nft_flows_count;

	struct rhashtable nft_merge_tb;
	unsigned int nft_merge_count;
};

enum ct_entry_type {
	CT_TYPE_PRE_CT,
	CT_TYPE_NFT,
	CT_TYPE_POST_CT,
	_CT_TYPE_MAX,
};

enum nfp_nfp_layer_name {
	FLOW_PAY_META_TCI =    0,
	FLOW_PAY_INPORT,
	FLOW_PAY_EXT_META,
	FLOW_PAY_MAC_MPLS,
	FLOW_PAY_L4,
	FLOW_PAY_IPV4,
	FLOW_PAY_IPV6,
	FLOW_PAY_CT,
	FLOW_PAY_GRE,
	FLOW_PAY_QINQ,
	FLOW_PAY_UDP_TUN,
	FLOW_PAY_GENEVE_OPT,

	_FLOW_PAY_LAYERS_MAX
};

/**
 * struct nfp_fl_ct_flow_entry - Flow entry containing conntrack flow information
 * @cookie:	Flow cookie, same as original TC flow, used as key
 * @list_node:	Used by the list
 * @chain_index:	Chain index of the original flow
 * @netdev:	netdev structure.
 * @type:	Type of pre-entry from enum ct_entry_type
 * @zt:		Reference to the zone table this belongs to
 * @children:	List of tc_merge flows this flow forms part of
 * @rule:	Reference to the original TC flow rule
 * @stats:	Used to cache stats for updating
 * @tun_offset: Used to indicate tunnel action offset in action list
 */
struct nfp_fl_ct_flow_entry {
	unsigned long cookie;
	struct list_head list_node;
	u32 chain_index;
	enum ct_entry_type type;
	struct net_device *netdev;
	struct nfp_fl_ct_zone_entry *zt;
	struct list_head children;
	struct flow_rule *rule;
	struct flow_stats stats;
	u8 tun_offset;		// Set to NFP_FL_CT_NO_TUN if no tun
};

/**
 * struct nfp_fl_ct_tc_merge - Merge of two flows from tc
 * @cookie:		Flow cookie, combination of pre and post ct cookies
 * @hash_node:		Used by the hashtable
 * @pre_ct_list:	This entry is part of a pre_ct_list
 * @post_ct_list:	This entry is part of a post_ct_list
 * @zt:			Reference to the zone table this belongs to
 * @pre_ct_parent:	The pre_ct_parent
 * @post_ct_parent:	The post_ct_parent
 * @children:		List of nft merged entries
 */
struct nfp_fl_ct_tc_merge {
	unsigned long cookie[2];
	struct rhash_head hash_node;
	struct list_head pre_ct_list;
	struct list_head post_ct_list;
	struct nfp_fl_ct_zone_entry *zt;
	struct nfp_fl_ct_flow_entry *pre_ct_parent;
	struct nfp_fl_ct_flow_entry *post_ct_parent;
	struct list_head children;
};

/**
 * struct nfp_fl_nft_tc_merge - Merge of tc_merge flows with nft flow
 * @netdev:		Ingress netdev name
 * @cookie:		Flow cookie, combination of tc_merge and nft cookies
 * @hash_node:		Used by the hashtable
 * @zt:	Reference to the zone table this belongs to
 * @nft_flow_list:	This entry is part of a nft_flows_list
 * @tc_merge_list:	This entry is part of a ct_merge_list
 * @tc_m_parent:	The tc_merge parent
 * @nft_parent:	The nft_entry parent
 * @tc_flower_cookie:	The cookie of the flow offloaded to the nfp
 * @flow_pay:	Reference to the offloaded flow struct
 */
struct nfp_fl_nft_tc_merge {
	struct net_device *netdev;
	unsigned long cookie[3];
	struct rhash_head hash_node;
	struct nfp_fl_ct_zone_entry *zt;
	struct list_head nft_flow_list;
	struct list_head tc_merge_list;
	struct nfp_fl_ct_tc_merge *tc_m_parent;
	struct nfp_fl_ct_flow_entry *nft_parent;
	unsigned long tc_flower_cookie;
	struct nfp_fl_payload *flow_pay;
};

/**
 * struct nfp_fl_ct_map_entry - Map between flow cookie and specific ct_flow
 * @cookie:	Flow cookie, same as original TC flow, used as key
 * @hash_node:	Used by the hashtable
 * @ct_entry:	Pointer to corresponding ct_entry
 */
struct nfp_fl_ct_map_entry {
	unsigned long cookie;
	struct rhash_head hash_node;
	struct nfp_fl_ct_flow_entry *ct_entry;
};

bool is_pre_ct_flow(struct flow_cls_offload *flow);
bool is_post_ct_flow(struct flow_cls_offload *flow);

/**
 * nfp_fl_ct_handle_pre_ct() - Handles -trk conntrack rules
 * @priv:	Pointer to app priv
 * @netdev:	netdev structure.
 * @flow:	TC flower classifier offload structure.
 * @extack:	Extack pointer for errors
 *
 * Adds a new entry to the relevant zone table and tries to
 * merge with other +trk+est entries and offload if possible.
 *
 * Return: negative value on error, 0 if configured successfully.
 */
int nfp_fl_ct_handle_pre_ct(struct nfp_flower_priv *priv,
			    struct net_device *netdev,
			    struct flow_cls_offload *flow,
			    struct netlink_ext_ack *extack);
/**
 * nfp_fl_ct_handle_post_ct() - Handles +trk+est conntrack rules
 * @priv:	Pointer to app priv
 * @netdev:	netdev structure.
 * @flow:	TC flower classifier offload structure.
 * @extack:	Extack pointer for errors
 *
 * Adds a new entry to the relevant zone table and tries to
 * merge with other -trk entries and offload if possible.
 *
 * Return: negative value on error, 0 if configured successfully.
 */
int nfp_fl_ct_handle_post_ct(struct nfp_flower_priv *priv,
			     struct net_device *netdev,
			     struct flow_cls_offload *flow,
			     struct netlink_ext_ack *extack);

/**
 * nfp_fl_ct_clean_flow_entry() - Free a nfp_fl_ct_flow_entry
 * @entry:	Flow entry to cleanup
 */
void nfp_fl_ct_clean_flow_entry(struct nfp_fl_ct_flow_entry *entry);

/**
 * nfp_fl_ct_del_flow() - Handle flow_del callbacks for conntrack
 * @ct_map_ent:	ct map entry for the flow that needs deleting
 */
int nfp_fl_ct_del_flow(struct nfp_fl_ct_map_entry *ct_map_ent);

/**
 * nfp_fl_ct_handle_nft_flow() - Handle flower flow callbacks for nft table
 * @type:	Type provided by callback
 * @type_data:	Callback data
 * @cb_priv:	Pointer to data provided when registering the callback, in this
 *		case it's the zone table.
 */
int nfp_fl_ct_handle_nft_flow(enum tc_setup_type type, void *type_data,
			      void *cb_priv);

/**
 * nfp_fl_ct_stats() - Handle flower stats callbacks for ct flows
 * @flow:	TC flower classifier offload structure.
 * @ct_map_ent:	ct map entry for the flow that needs deleting
 */
int nfp_fl_ct_stats(struct flow_cls_offload *flow,
		    struct nfp_fl_ct_map_entry *ct_map_ent);
#endif