mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-28 11:49:32 +00:00
nfp: add set ipv4 header action flower offload
Previously we did not have offloading support for set IPv4 actions. This patch enables TC flower offload of set IPv4 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>
This commit is contained in:
parent
da83d8fe58
commit
c0b1bd9a8b
2 changed files with 56 additions and 0 deletions
|
@ -265,15 +265,54 @@ nfp_fl_set_eth(const struct tc_action *action, int idx, u32 off,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
nfp_fl_set_ip4(const struct tc_action *action, int idx, u32 off,
|
||||
struct nfp_fl_set_ip4_addrs *set_ip_addr)
|
||||
{
|
||||
u16 tmp_set_ipv4_op;
|
||||
__be32 exact, mask;
|
||||
|
||||
/* We are expecting tcf_pedit to return a big endian value */
|
||||
mask = (__force __be32)~tcf_pedit_mask(action, idx);
|
||||
exact = (__force __be32)tcf_pedit_val(action, idx);
|
||||
|
||||
if (exact & ~mask)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
switch (off) {
|
||||
case offsetof(struct iphdr, daddr):
|
||||
set_ip_addr->ipv4_dst_mask = mask;
|
||||
set_ip_addr->ipv4_dst = exact;
|
||||
break;
|
||||
case offsetof(struct iphdr, saddr):
|
||||
set_ip_addr->ipv4_src_mask = mask;
|
||||
set_ip_addr->ipv4_src = exact;
|
||||
break;
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
set_ip_addr->reserved = cpu_to_be16(0);
|
||||
tmp_set_ipv4_op = FIELD_PREP(NFP_FL_ACT_LEN_LW,
|
||||
sizeof(*set_ip_addr) >> NFP_FL_LW_SIZ) |
|
||||
FIELD_PREP(NFP_FL_ACT_JMP_ID,
|
||||
NFP_FL_ACTION_OPCODE_SET_IPV4_ADDRS);
|
||||
set_ip_addr->a_op = cpu_to_be16(tmp_set_ipv4_op);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
nfp_fl_pedit(const struct tc_action *action, char *nfp_action, int *a_len)
|
||||
{
|
||||
struct nfp_fl_set_ip4_addrs set_ip_addr;
|
||||
struct nfp_fl_set_eth set_eth;
|
||||
enum pedit_header_type htype;
|
||||
int idx, nkeys, err;
|
||||
size_t act_size;
|
||||
u32 offset, cmd;
|
||||
|
||||
memset(&set_ip_addr, 0, sizeof(set_ip_addr));
|
||||
memset(&set_eth, 0, sizeof(set_eth));
|
||||
nkeys = tcf_pedit_nkeys(action);
|
||||
|
||||
|
@ -289,6 +328,9 @@ nfp_fl_pedit(const struct tc_action *action, char *nfp_action, int *a_len)
|
|||
case TCA_PEDIT_KEY_EX_HDR_TYPE_ETH:
|
||||
err = nfp_fl_set_eth(action, idx, offset, &set_eth);
|
||||
break;
|
||||
case TCA_PEDIT_KEY_EX_HDR_TYPE_IP4:
|
||||
err = nfp_fl_set_ip4(action, idx, offset, &set_ip_addr);
|
||||
break;
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
@ -300,6 +342,10 @@ nfp_fl_pedit(const struct tc_action *action, char *nfp_action, int *a_len)
|
|||
act_size = sizeof(set_eth);
|
||||
memcpy(nfp_action, &set_eth, act_size);
|
||||
*a_len += act_size;
|
||||
} else if (set_ip_addr.a_op) {
|
||||
act_size = sizeof(set_ip_addr);
|
||||
memcpy(nfp_action, &set_ip_addr, act_size);
|
||||
*a_len += act_size;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -78,6 +78,7 @@
|
|||
#define NFP_FL_ACTION_OPCODE_POP_VLAN 2
|
||||
#define NFP_FL_ACTION_OPCODE_SET_IPV4_TUNNEL 6
|
||||
#define NFP_FL_ACTION_OPCODE_SET_ETHERNET 7
|
||||
#define NFP_FL_ACTION_OPCODE_SET_IPV4_ADDRS 9
|
||||
#define NFP_FL_ACTION_OPCODE_PRE_TUNNEL 17
|
||||
#define NFP_FL_ACTION_OPCODE_NUM 32
|
||||
|
||||
|
@ -115,6 +116,15 @@ struct nfp_fl_set_eth {
|
|||
u8 eth_addr_val[ETH_ALEN * 2];
|
||||
};
|
||||
|
||||
struct nfp_fl_set_ip4_addrs {
|
||||
__be16 a_op;
|
||||
__be16 reserved;
|
||||
__be32 ipv4_src_mask;
|
||||
__be32 ipv4_src;
|
||||
__be32 ipv4_dst_mask;
|
||||
__be32 ipv4_dst;
|
||||
};
|
||||
|
||||
struct nfp_fl_output {
|
||||
__be16 a_op;
|
||||
__be16 flags;
|
||||
|
|
Loading…
Reference in a new issue