Skip to content

Commit 90f9062

Browse files
venkatkumarduvvurudavem330
authored andcommitted
bnxt_en: Add support for L2 rewrite
This patch adds support for packet edit offload of L2 fields (src mac & dst mac, also referred as L2 rewrite). Only when the mask is fully exact match for a field, the command is sent down to the adapter to offload such a flow. Otherwise, an error is returned. v2: Fix pointer alignment issue in bnxt_fill_l2_rewrite_fields() [MChan] Signed-off-by: Venkat Duvvuru <[email protected]> Signed-off-by: Michael Chan <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent e43ea83 commit 90f9062

File tree

2 files changed

+143
-0
lines changed

2 files changed

+143
-0
lines changed

drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include <net/tc_act/tc_skbedit.h>
1717
#include <net/tc_act/tc_mirred.h>
1818
#include <net/tc_act/tc_vlan.h>
19+
#include <net/tc_act/tc_pedit.h>
1920
#include <net/tc_act/tc_tunnel_key.h>
2021

2122
#include "bnxt_hsi.h"
@@ -36,6 +37,8 @@
3637
#define is_vid_exactmatch(vlan_tci_mask) \
3738
((ntohs(vlan_tci_mask) & VLAN_VID_MASK) == VLAN_VID_MASK)
3839

40+
static bool is_wildcard(void *mask, int len);
41+
static bool is_exactmatch(void *mask, int len);
3942
/* Return the dst fid of the func for flow forwarding
4043
* For PFs: src_fid is the fid of the PF
4144
* For VF-reps: src_fid the fid of the VF
@@ -111,10 +114,115 @@ static int bnxt_tc_parse_tunnel_set(struct bnxt *bp,
111114
return 0;
112115
}
113116

117+
/* Key & Mask from the stack comes unaligned in multiple iterations.
118+
* This routine consolidates such multiple unaligned values into one
119+
* field each for Key & Mask (for src and dst macs separately)
120+
* For example,
121+
* Mask/Key Offset Iteration
122+
* ========== ====== =========
123+
* dst mac 0xffffffff 0 1
124+
* dst mac 0x0000ffff 4 2
125+
*
126+
* src mac 0xffff0000 4 1
127+
* src mac 0xffffffff 8 2
128+
*
129+
* The above combination coming from the stack will be consolidated as
130+
* Mask/Key
131+
* ==============
132+
* src mac: 0xffffffffffff
133+
* dst mac: 0xffffffffffff
134+
*/
135+
static void bnxt_set_l2_key_mask(u32 part_key, u32 part_mask,
136+
u8 *actual_key, u8 *actual_mask)
137+
{
138+
u32 key = get_unaligned((u32 *)actual_key);
139+
u32 mask = get_unaligned((u32 *)actual_mask);
140+
141+
part_key &= part_mask;
142+
part_key |= key & ~part_mask;
143+
144+
put_unaligned(mask | part_mask, (u32 *)actual_mask);
145+
put_unaligned(part_key, (u32 *)actual_key);
146+
}
147+
148+
static int
149+
bnxt_fill_l2_rewrite_fields(struct bnxt_tc_actions *actions,
150+
u16 *eth_addr, u16 *eth_addr_mask)
151+
{
152+
u16 *p;
153+
int j;
154+
155+
if (unlikely(bnxt_eth_addr_key_mask_invalid(eth_addr, eth_addr_mask)))
156+
return -EINVAL;
157+
158+
if (!is_wildcard(&eth_addr_mask[0], ETH_ALEN)) {
159+
if (!is_exactmatch(&eth_addr_mask[0], ETH_ALEN))
160+
return -EINVAL;
161+
/* FW expects dmac to be in u16 array format */
162+
p = eth_addr;
163+
for (j = 0; j < 3; j++)
164+
actions->l2_rewrite_dmac[j] = cpu_to_be16(*(p + j));
165+
}
166+
167+
if (!is_wildcard(&eth_addr_mask[ETH_ALEN], ETH_ALEN)) {
168+
if (!is_exactmatch(&eth_addr_mask[ETH_ALEN], ETH_ALEN))
169+
return -EINVAL;
170+
/* FW expects smac to be in u16 array format */
171+
p = &eth_addr[ETH_ALEN / 2];
172+
for (j = 0; j < 3; j++)
173+
actions->l2_rewrite_smac[j] = cpu_to_be16(*(p + j));
174+
}
175+
176+
return 0;
177+
}
178+
179+
static int
180+
bnxt_tc_parse_pedit(struct bnxt *bp, struct bnxt_tc_actions *actions,
181+
struct flow_action_entry *act, u8 *eth_addr,
182+
u8 *eth_addr_mask)
183+
{
184+
u32 mask, val, offset;
185+
u8 htype;
186+
187+
offset = act->mangle.offset;
188+
htype = act->mangle.htype;
189+
switch (htype) {
190+
case FLOW_ACT_MANGLE_HDR_TYPE_ETH:
191+
if (offset > PEDIT_OFFSET_SMAC_LAST_4_BYTES) {
192+
netdev_err(bp->dev,
193+
"%s: eth_hdr: Invalid pedit field\n",
194+
__func__);
195+
return -EINVAL;
196+
}
197+
actions->flags |= BNXT_TC_ACTION_FLAG_L2_REWRITE;
198+
mask = ~act->mangle.mask;
199+
val = act->mangle.val;
200+
201+
bnxt_set_l2_key_mask(val, mask, &eth_addr[offset],
202+
&eth_addr_mask[offset]);
203+
break;
204+
default:
205+
netdev_err(bp->dev, "%s: Unsupported pedit hdr type\n",
206+
__func__);
207+
return -EINVAL;
208+
}
209+
return 0;
210+
}
211+
114212
static int bnxt_tc_parse_actions(struct bnxt *bp,
115213
struct bnxt_tc_actions *actions,
116214
struct flow_action *flow_action)
117215
{
216+
/* Used to store the L2 rewrite mask for dmac (6 bytes) followed by
217+
* smac (6 bytes) if rewrite of both is specified, otherwise either
218+
* dmac or smac
219+
*/
220+
u16 eth_addr_mask[ETH_ALEN] = { 0 };
221+
/* Used to store the L2 rewrite key for dmac (6 bytes) followed by
222+
* smac (6 bytes) if rewrite of both is specified, otherwise either
223+
* dmac or smac
224+
*/
225+
u16 eth_addr[ETH_ALEN] = { 0 };
118226
struct flow_action_entry *act;
119227
int i, rc;
120228

@@ -148,11 +256,26 @@ static int bnxt_tc_parse_actions(struct bnxt *bp,
148256
case FLOW_ACTION_TUNNEL_DECAP:
149257
actions->flags |= BNXT_TC_ACTION_FLAG_TUNNEL_DECAP;
150258
break;
259+
/* Packet edit: L2 rewrite, NAT, NAPT */
260+
case FLOW_ACTION_MANGLE:
261+
rc = bnxt_tc_parse_pedit(bp, actions, act,
262+
(u8 *)eth_addr,
263+
(u8 *)eth_addr_mask);
264+
if (rc)
265+
return rc;
266+
break;
151267
default:
152268
break;
153269
}
154270
}
155271

272+
if (actions->flags & BNXT_TC_ACTION_FLAG_L2_REWRITE) {
273+
rc = bnxt_fill_l2_rewrite_fields(actions, eth_addr,
274+
eth_addr_mask);
275+
if (rc)
276+
return rc;
277+
}
278+
156279
if (actions->flags & BNXT_TC_ACTION_FLAG_FWD) {
157280
if (actions->flags & BNXT_TC_ACTION_FLAG_TUNNEL_ENCAP) {
158281
/* dst_fid is PF's fid */
@@ -401,6 +524,15 @@ static int bnxt_hwrm_cfa_flow_alloc(struct bnxt *bp, struct bnxt_tc_flow *flow,
401524
req.src_fid = cpu_to_le16(flow->src_fid);
402525
req.ref_flow_handle = ref_flow_handle;
403526

527+
if (actions->flags & BNXT_TC_ACTION_FLAG_L2_REWRITE) {
528+
memcpy(req.l2_rewrite_dmac, actions->l2_rewrite_dmac,
529+
ETH_ALEN);
530+
memcpy(req.l2_rewrite_smac, actions->l2_rewrite_smac,
531+
ETH_ALEN);
532+
action_flags |=
533+
CFA_FLOW_ALLOC_REQ_ACTION_FLAGS_L2_HEADER_REWRITE;
534+
}
535+
404536
if (actions->flags & BNXT_TC_ACTION_FLAG_TUNNEL_DECAP ||
405537
actions->flags & BNXT_TC_ACTION_FLAG_TUNNEL_ENCAP) {
406538
req.tunnel_handle = tunnel_handle;

drivers/net/ethernet/broadcom/bnxt/bnxt_tc.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,12 @@ struct bnxt_tc_tunnel_key {
6262
__be32 id;
6363
};
6464

65+
#define bnxt_eth_addr_key_mask_invalid(eth_addr, eth_addr_mask) \
66+
((is_wildcard(&(eth_addr)[0], ETH_ALEN) && \
67+
is_wildcard(&(eth_addr)[ETH_ALEN], ETH_ALEN)) || \
68+
(is_wildcard(&(eth_addr_mask)[0], ETH_ALEN) && \
69+
is_wildcard(&(eth_addr_mask)[ETH_ALEN], ETH_ALEN)))
70+
6571
struct bnxt_tc_actions {
6672
u32 flags;
6773
#define BNXT_TC_ACTION_FLAG_FWD BIT(0)
@@ -71,6 +77,7 @@ struct bnxt_tc_actions {
7177
#define BNXT_TC_ACTION_FLAG_DROP BIT(5)
7278
#define BNXT_TC_ACTION_FLAG_TUNNEL_ENCAP BIT(6)
7379
#define BNXT_TC_ACTION_FLAG_TUNNEL_DECAP BIT(7)
80+
#define BNXT_TC_ACTION_FLAG_L2_REWRITE BIT(8)
7481

7582
u16 dst_fid;
7683
struct net_device *dst_dev;
@@ -79,6 +86,10 @@ struct bnxt_tc_actions {
7986

8087
/* tunnel encap */
8188
struct ip_tunnel_key tun_encap_key;
89+
#define PEDIT_OFFSET_SMAC_LAST_4_BYTES 0x8
90+
__be16 l2_rewrite_dmac[3];
91+
__be16 l2_rewrite_smac[3];
92+
8293
};
8394

8495
struct bnxt_tc_flow {

0 commit comments

Comments
 (0)