aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.h
blob: 10c62b09491484b313a79af9202f4301fd2f0cec (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
/* Broadcom NetXtreme-C/E network driver.
 *
 * Copyright (c) 2017 Broadcom Limited
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation.
 */

#ifndef BNXT_TC_H
#define BNXT_TC_H

#ifdef CONFIG_BNXT_FLOWER_OFFLOAD

#include <net/ip_tunnels.h>

/* Structs used for storing the filter/actions of the TC cmd.
 */
struct bnxt_tc_l2_key {
	u8		dmac[ETH_ALEN];
	u8		smac[ETH_ALEN];
	__be16		inner_vlan_tpid;
	__be16		inner_vlan_tci;
	__be16		ether_type;
	u8		num_vlans;
	u8		dir;
#define BNXT_DIR_RX	1
#define BNXT_DIR_TX	0
};

struct bnxt_tc_l3_key {
	union {
		struct {
			struct in_addr daddr;
			struct in_addr saddr;
		} ipv4;
		struct {
			struct in6_addr daddr;
			struct in6_addr saddr;
		} ipv6;
	};
};

struct bnxt_tc_l4_key {
	u8  ip_proto;
	union {
		struct {
			__be16 sport;
			__be16 dport;
		} ports;
		struct {
			u8 type;
			u8 code;
		} icmp;
	};
};

struct bnxt_tc_tunnel_key {
	struct bnxt_tc_l2_key	l2;
	struct bnxt_tc_l3_key	l3;
	struct bnxt_tc_l4_key	l4;
	__be32			id;
};

#define bnxt_eth_addr_key_mask_invalid(eth_addr, eth_addr_mask)		\
	((is_wildcard(&(eth_addr)[0], ETH_ALEN) &&			\
	 is_wildcard(&(eth_addr)[ETH_ALEN / 2], ETH_ALEN)) ||		\
	(is_wildcard(&(eth_addr_mask)[0], ETH_ALEN) &&			\
	 is_wildcard(&(eth_addr_mask)[ETH_ALEN / 2], ETH_ALEN)))

struct bnxt_tc_actions {
	u32				flags;
#define BNXT_TC_ACTION_FLAG_FWD			BIT(0)
#define BNXT_TC_ACTION_FLAG_FWD_VXLAN		BIT(1)
#define BNXT_TC_ACTION_FLAG_PUSH_VLAN		BIT(3)
#define BNXT_TC_ACTION_FLAG_POP_VLAN		BIT(4)
#define BNXT_TC_ACTION_FLAG_DROP		BIT(5)
#define BNXT_TC_ACTION_FLAG_TUNNEL_ENCAP	BIT(6)
#define BNXT_TC_ACTION_FLAG_TUNNEL_DECAP	BIT(7)
#define BNXT_TC_ACTION_FLAG_L2_REWRITE		BIT(8)
#define BNXT_TC_ACTION_FLAG_NAT_XLATE		BIT(9)

	u16				dst_fid;
	struct net_device		*dst_dev;
	__be16				push_vlan_tpid;
	__be16				push_vlan_tci;

	/* tunnel encap */
	struct ip_tunnel_key		tun_encap_key;
#define	PEDIT_OFFSET_SMAC_LAST_4_BYTES		0x8
	__be16				l2_rewrite_dmac[3];
	__be16				l2_rewrite_smac[3];
	struct {
		bool src_xlate;  /* true => translate src,
				  * false => translate dst
				  * Mutually exclusive, i.e cannot set both
				  */
		bool l3_is_ipv4; /* false means L3 is ipv6 */
		struct bnxt_tc_l3_key l3;
		struct bnxt_tc_l4_key l4;
	} nat;
};

struct bnxt_tc_flow {
	u32				flags;
#define BNXT_TC_FLOW_FLAGS_ETH_ADDRS		BIT(1)
#define BNXT_TC_FLOW_FLAGS_IPV4_ADDRS		BIT(2)
#define BNXT_TC_FLOW_FLAGS_IPV6_ADDRS		BIT(3)
#define BNXT_TC_FLOW_FLAGS_PORTS		BIT(4)
#define BNXT_TC_FLOW_FLAGS_ICMP			BIT(5)
#define BNXT_TC_FLOW_FLAGS_TUNL_ETH_ADDRS	BIT(6)
#define BNXT_TC_FLOW_FLAGS_TUNL_IPV4_ADDRS	BIT(7)
#define BNXT_TC_FLOW_FLAGS_TUNL_IPV6_ADDRS	BIT(8)
#define BNXT_TC_FLOW_FLAGS_TUNL_PORTS		BIT(9)
#define BNXT_TC_FLOW_FLAGS_TUNL_ID		BIT(10)
#define BNXT_TC_FLOW_FLAGS_TUNNEL	(BNXT_TC_FLOW_FLAGS_TUNL_ETH_ADDRS | \
					 BNXT_TC_FLOW_FLAGS_TUNL_IPV4_ADDRS | \
					 BNXT_TC_FLOW_FLAGS_TUNL_IPV6_ADDRS |\
					 BNXT_TC_FLOW_FLAGS_TUNL_PORTS |\
					 BNXT_TC_FLOW_FLAGS_TUNL_ID)

	/* flow applicable to pkts ingressing on this fid */
	u16				src_fid;
	struct bnxt_tc_l2_key		l2_key;
	struct bnxt_tc_l2_key		l2_mask;
	struct bnxt_tc_l3_key		l3_key;
	struct bnxt_tc_l3_key		l3_mask;
	struct bnxt_tc_l4_key		l4_key;
	struct bnxt_tc_l4_key		l4_mask;
	struct ip_tunnel_key		tun_key;
	struct ip_tunnel_key		tun_mask;

	struct bnxt_tc_actions		actions;

	/* updated stats accounting for hw-counter wrap-around */
	struct bnxt_tc_flow_stats	stats;
	/* previous snap-shot of stats */
	struct bnxt_tc_flow_stats	prev_stats;
	unsigned long			lastused; /* jiffies */
	/* for calculating delta from prev_stats and
	 * updating prev_stats atomically.
	 */
	spinlock_t			stats_lock;
};

/* Tunnel encap/decap hash table
 * This table is used to maintain a list of flows that use
 * the same tunnel encap/decap params (ip_daddrs, vni, udp_dport)
 * and the FW returned handle.
 * A separate table is maintained for encap and decap
 */
struct bnxt_tc_tunnel_node {
	struct ip_tunnel_key		key;
	struct rhash_head		node;

	/* tunnel l2 info */
	struct bnxt_tc_l2_key		l2_info;

#define	INVALID_TUNNEL_HANDLE		cpu_to_le32(0xffffffff)
	/* tunnel handle returned by FW */
	__le32				tunnel_handle;

	u32				refcount;
	struct rcu_head			rcu;
};

/* L2 hash table
 * The same data-struct is used for L2-flow table and L2-tunnel table.
 * The L2 part of a flow or tunnel is stored in a hash table.
 * A flow that shares the same L2 key/mask with an
 * already existing flow/tunnel must refer to it's flow handle or
 * decap_filter_id respectively.
 */
struct bnxt_tc_l2_node {
	/* hash key: first 16b of key */
#define BNXT_TC_L2_KEY_LEN			16
	struct bnxt_tc_l2_key	key;
	struct rhash_head	node;

	/* a linked list of flows that share the same l2 key */
	struct list_head	common_l2_flows;

	/* number of flows/tunnels sharing the l2 key */
	u16			refcount;

	struct rcu_head		rcu;
};

struct bnxt_tc_flow_node {
	/* hash key: provided by TC */
	unsigned long			cookie;
	struct rhash_head		node;

	struct bnxt_tc_flow		flow;

	__le64				ext_flow_handle;
	__le16				flow_handle;
	__le32				flow_id;

	/* L2 node in l2 hashtable that shares flow's l2 key */
	struct bnxt_tc_l2_node		*l2_node;
	/* for the shared_flows list maintained in l2_node */
	struct list_head		l2_list_node;

	/* tunnel encap related */
	struct bnxt_tc_tunnel_node	*encap_node;

	/* tunnel decap related */
	struct bnxt_tc_tunnel_node	*decap_node;
	/* L2 node in tunnel-l2 hashtable that shares flow's tunnel l2 key */
	struct bnxt_tc_l2_node		*decap_l2_node;
	/* for the shared_flows list maintained in tunnel decap l2_node */
	struct list_head		decap_l2_list_node;

	struct rcu_head			rcu;
};

int bnxt_tc_setup_flower(struct bnxt *bp, u16 src_fid,
			 struct flow_cls_offload *cls_flower);
int bnxt_init_tc(struct bnxt *bp);
void bnxt_shutdown_tc(struct bnxt *bp);
void bnxt_tc_flow_stats_work(struct bnxt *bp);

static inline bool bnxt_tc_flower_enabled(struct bnxt *bp)
{
	return bp->tc_info && bp->tc_info->enabled;
}

#else /* CONFIG_BNXT_FLOWER_OFFLOAD */

static inline int bnxt_tc_setup_flower(struct bnxt *bp, u16 src_fid,
				       struct flow_cls_offload *cls_flower)
{
	return -EOPNOTSUPP;
}

static inline int bnxt_init_tc(struct bnxt *bp)
{
	return 0;
}

static inline void bnxt_shutdown_tc(struct bnxt *bp)
{
}

static inline void bnxt_tc_flow_stats_work(struct bnxt *bp)
{
}

static inline bool bnxt_tc_flower_enabled(struct bnxt *bp)
{
	return false;
}
#endif /* CONFIG_BNXT_FLOWER_OFFLOAD */
#endif /* BNXT_TC_H */