hc
2024-11-01 7e970c18f85f99acc678d90128b6e01dce1bf273
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 */