Skip to content

Commit 354b82b

Browse files
pjvuurendavem330
authored andcommitted
nfp: add set ipv6 source and destination address
Previously we did not have offloading support for set IPv6 actions. This patch enables TC flower offload of set IPv6 src and dst address actions. Signed-off-by: Pieter Jansen van Vuuren <pieter.jansenvanvuuren@netronome.com> Reviewed-by: Jakub Kicinski <jakub.kicinski@netronome.com> Signed-off-by: Simon Horman <simon.horman@netronome.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent c0b1bd9 commit 354b82b

File tree

2 files changed

+83
-0
lines changed

2 files changed

+83
-0
lines changed

drivers/net/ethernet/netronome/nfp/flower/action.c

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,16 +302,64 @@ nfp_fl_set_ip4(const struct tc_action *action, int idx, u32 off,
302302
return 0;
303303
}
304304

305+
static void
306+
nfp_fl_set_ip6_helper(int opcode_tag, int idx, __be32 exact, __be32 mask,
307+
struct nfp_fl_set_ipv6_addr *ip6)
308+
{
309+
u16 tmp_set_op;
310+
311+
ip6->ipv6[idx % 4].mask = mask;
312+
ip6->ipv6[idx % 4].exact = exact;
313+
314+
ip6->reserved = cpu_to_be16(0);
315+
tmp_set_op = FIELD_PREP(NFP_FL_ACT_LEN_LW, sizeof(*ip6) >>
316+
NFP_FL_LW_SIZ) |
317+
FIELD_PREP(NFP_FL_ACT_JMP_ID, opcode_tag);
318+
ip6->a_op = cpu_to_be16(tmp_set_op);
319+
}
320+
321+
static int
322+
nfp_fl_set_ip6(const struct tc_action *action, int idx, u32 off,
323+
struct nfp_fl_set_ipv6_addr *ip_dst,
324+
struct nfp_fl_set_ipv6_addr *ip_src)
325+
{
326+
__be32 exact, mask;
327+
328+
/* We are expecting tcf_pedit to return a big endian value */
329+
mask = (__force __be32)~tcf_pedit_mask(action, idx);
330+
exact = (__force __be32)tcf_pedit_val(action, idx);
331+
332+
if (exact & ~mask)
333+
return -EOPNOTSUPP;
334+
335+
if (off < offsetof(struct ipv6hdr, saddr))
336+
return -EOPNOTSUPP;
337+
else if (off < offsetof(struct ipv6hdr, daddr))
338+
nfp_fl_set_ip6_helper(NFP_FL_ACTION_OPCODE_SET_IPV6_SRC, idx,
339+
exact, mask, ip_src);
340+
else if (off < offsetof(struct ipv6hdr, daddr) +
341+
sizeof(struct in6_addr))
342+
nfp_fl_set_ip6_helper(NFP_FL_ACTION_OPCODE_SET_IPV6_DST, idx,
343+
exact, mask, ip_dst);
344+
else
345+
return -EOPNOTSUPP;
346+
347+
return 0;
348+
}
349+
305350
static int
306351
nfp_fl_pedit(const struct tc_action *action, char *nfp_action, int *a_len)
307352
{
353+
struct nfp_fl_set_ipv6_addr set_ip6_dst, set_ip6_src;
308354
struct nfp_fl_set_ip4_addrs set_ip_addr;
309355
struct nfp_fl_set_eth set_eth;
310356
enum pedit_header_type htype;
311357
int idx, nkeys, err;
312358
size_t act_size;
313359
u32 offset, cmd;
314360

361+
memset(&set_ip6_dst, 0, sizeof(set_ip6_dst));
362+
memset(&set_ip6_src, 0, sizeof(set_ip6_src));
315363
memset(&set_ip_addr, 0, sizeof(set_ip_addr));
316364
memset(&set_eth, 0, sizeof(set_eth));
317365
nkeys = tcf_pedit_nkeys(action);
@@ -331,6 +379,10 @@ nfp_fl_pedit(const struct tc_action *action, char *nfp_action, int *a_len)
331379
case TCA_PEDIT_KEY_EX_HDR_TYPE_IP4:
332380
err = nfp_fl_set_ip4(action, idx, offset, &set_ip_addr);
333381
break;
382+
case TCA_PEDIT_KEY_EX_HDR_TYPE_IP6:
383+
err = nfp_fl_set_ip6(action, idx, offset, &set_ip6_dst,
384+
&set_ip6_src);
385+
break;
334386
default:
335387
return -EOPNOTSUPP;
336388
}
@@ -346,6 +398,26 @@ nfp_fl_pedit(const struct tc_action *action, char *nfp_action, int *a_len)
346398
act_size = sizeof(set_ip_addr);
347399
memcpy(nfp_action, &set_ip_addr, act_size);
348400
*a_len += act_size;
401+
} else if (set_ip6_dst.a_op && set_ip6_src.a_op) {
402+
/* TC compiles set src and dst IPv6 address as a single action,
403+
* the hardware requires this to be 2 separate actions.
404+
*/
405+
act_size = sizeof(set_ip6_src);
406+
memcpy(nfp_action, &set_ip6_src, act_size);
407+
*a_len += act_size;
408+
409+
act_size = sizeof(set_ip6_dst);
410+
memcpy(&nfp_action[sizeof(set_ip6_src)], &set_ip6_dst,
411+
act_size);
412+
*a_len += act_size;
413+
} else if (set_ip6_dst.a_op) {
414+
act_size = sizeof(set_ip6_dst);
415+
memcpy(nfp_action, &set_ip6_dst, act_size);
416+
*a_len += act_size;
417+
} else if (set_ip6_src.a_op) {
418+
act_size = sizeof(set_ip6_src);
419+
memcpy(nfp_action, &set_ip6_src, act_size);
420+
*a_len += act_size;
349421
}
350422

351423
return 0;

drivers/net/ethernet/netronome/nfp/flower/cmsg.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@
7979
#define NFP_FL_ACTION_OPCODE_SET_IPV4_TUNNEL 6
8080
#define NFP_FL_ACTION_OPCODE_SET_ETHERNET 7
8181
#define NFP_FL_ACTION_OPCODE_SET_IPV4_ADDRS 9
82+
#define NFP_FL_ACTION_OPCODE_SET_IPV6_SRC 11
83+
#define NFP_FL_ACTION_OPCODE_SET_IPV6_DST 12
8284
#define NFP_FL_ACTION_OPCODE_PRE_TUNNEL 17
8385
#define NFP_FL_ACTION_OPCODE_NUM 32
8486

@@ -125,6 +127,15 @@ struct nfp_fl_set_ip4_addrs {
125127
__be32 ipv4_dst;
126128
};
127129

130+
struct nfp_fl_set_ipv6_addr {
131+
__be16 a_op;
132+
__be16 reserved;
133+
struct {
134+
__be32 mask;
135+
__be32 exact;
136+
} ipv6[4];
137+
};
138+
128139
struct nfp_fl_output {
129140
__be16 a_op;
130141
__be16 flags;

0 commit comments

Comments
 (0)