nfp: flower: add ipv4 set ttl and tos offload
Add ipv4 set ttl and tos action offload. Since pedit sets headers per 4 byte word, we need to ensure that setting either version, ihl, protocol, total length or checksum does not get offloaded. Signed-off-by: Pieter Jansen van Vuuren <pieter.jansenvanvuuren@netronome.com> Reviewed-by: John Hurley <john.hurley@netronome.com> Reviewed-by: Jakub Kicinski <jakub.kicinski@netronome.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
6a02d1fa03
commit
a3c6b063fe
|
@ -384,10 +384,21 @@ nfp_fl_set_eth(const struct tc_action *action, int idx, u32 off,
|
|||
return 0;
|
||||
}
|
||||
|
||||
struct ipv4_ttl_word {
|
||||
__u8 ttl;
|
||||
__u8 protocol;
|
||||
__sum16 check;
|
||||
};
|
||||
|
||||
static int
|
||||
nfp_fl_set_ip4(const struct tc_action *action, int idx, u32 off,
|
||||
struct nfp_fl_set_ip4_addrs *set_ip_addr)
|
||||
struct nfp_fl_set_ip4_addrs *set_ip_addr,
|
||||
struct nfp_fl_set_ip4_ttl_tos *set_ip_ttl_tos)
|
||||
{
|
||||
struct ipv4_ttl_word *ttl_word_mask;
|
||||
struct ipv4_ttl_word *ttl_word;
|
||||
struct iphdr *tos_word_mask;
|
||||
struct iphdr *tos_word;
|
||||
__be32 exact, mask;
|
||||
|
||||
/* We are expecting tcf_pedit to return a big endian value */
|
||||
|
@ -402,20 +413,53 @@ nfp_fl_set_ip4(const struct tc_action *action, int idx, u32 off,
|
|||
set_ip_addr->ipv4_dst_mask |= mask;
|
||||
set_ip_addr->ipv4_dst &= ~mask;
|
||||
set_ip_addr->ipv4_dst |= exact & mask;
|
||||
set_ip_addr->head.jump_id = NFP_FL_ACTION_OPCODE_SET_IPV4_ADDRS;
|
||||
set_ip_addr->head.len_lw = sizeof(*set_ip_addr) >>
|
||||
NFP_FL_LW_SIZ;
|
||||
break;
|
||||
case offsetof(struct iphdr, saddr):
|
||||
set_ip_addr->ipv4_src_mask |= mask;
|
||||
set_ip_addr->ipv4_src &= ~mask;
|
||||
set_ip_addr->ipv4_src |= exact & mask;
|
||||
set_ip_addr->head.jump_id = NFP_FL_ACTION_OPCODE_SET_IPV4_ADDRS;
|
||||
set_ip_addr->head.len_lw = sizeof(*set_ip_addr) >>
|
||||
NFP_FL_LW_SIZ;
|
||||
break;
|
||||
case offsetof(struct iphdr, ttl):
|
||||
ttl_word_mask = (struct ipv4_ttl_word *)&mask;
|
||||
ttl_word = (struct ipv4_ttl_word *)&exact;
|
||||
|
||||
if (ttl_word_mask->protocol || ttl_word_mask->check)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
set_ip_ttl_tos->ipv4_ttl_mask |= ttl_word_mask->ttl;
|
||||
set_ip_ttl_tos->ipv4_ttl &= ~ttl_word_mask->ttl;
|
||||
set_ip_ttl_tos->ipv4_ttl |= ttl_word->ttl & ttl_word_mask->ttl;
|
||||
set_ip_ttl_tos->head.jump_id =
|
||||
NFP_FL_ACTION_OPCODE_SET_IPV4_TTL_TOS;
|
||||
set_ip_ttl_tos->head.len_lw = sizeof(*set_ip_ttl_tos) >>
|
||||
NFP_FL_LW_SIZ;
|
||||
break;
|
||||
case round_down(offsetof(struct iphdr, tos), 4):
|
||||
tos_word_mask = (struct iphdr *)&mask;
|
||||
tos_word = (struct iphdr *)&exact;
|
||||
|
||||
if (tos_word_mask->version || tos_word_mask->ihl ||
|
||||
tos_word_mask->tot_len)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
set_ip_ttl_tos->ipv4_tos_mask |= tos_word_mask->tos;
|
||||
set_ip_ttl_tos->ipv4_tos &= ~tos_word_mask->tos;
|
||||
set_ip_ttl_tos->ipv4_tos |= tos_word->tos & tos_word_mask->tos;
|
||||
set_ip_ttl_tos->head.jump_id =
|
||||
NFP_FL_ACTION_OPCODE_SET_IPV4_TTL_TOS;
|
||||
set_ip_ttl_tos->head.len_lw = sizeof(*set_ip_ttl_tos) >>
|
||||
NFP_FL_LW_SIZ;
|
||||
break;
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
set_ip_addr->reserved = cpu_to_be16(0);
|
||||
set_ip_addr->head.jump_id = NFP_FL_ACTION_OPCODE_SET_IPV4_ADDRS;
|
||||
set_ip_addr->head.len_lw = sizeof(*set_ip_addr) >> NFP_FL_LW_SIZ;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -513,6 +557,7 @@ nfp_fl_pedit(const struct tc_action *action, struct tc_cls_flower_offload *flow,
|
|||
char *nfp_action, int *a_len, u32 *csum_updated)
|
||||
{
|
||||
struct nfp_fl_set_ipv6_addr set_ip6_dst, set_ip6_src;
|
||||
struct nfp_fl_set_ip4_ttl_tos set_ip_ttl_tos;
|
||||
struct nfp_fl_set_ip4_addrs set_ip_addr;
|
||||
struct nfp_fl_set_tport set_tport;
|
||||
struct nfp_fl_set_eth set_eth;
|
||||
|
@ -522,6 +567,7 @@ nfp_fl_pedit(const struct tc_action *action, struct tc_cls_flower_offload *flow,
|
|||
u32 offset, cmd;
|
||||
u8 ip_proto = 0;
|
||||
|
||||
memset(&set_ip_ttl_tos, 0, sizeof(set_ip_ttl_tos));
|
||||
memset(&set_ip6_dst, 0, sizeof(set_ip6_dst));
|
||||
memset(&set_ip6_src, 0, sizeof(set_ip6_src));
|
||||
memset(&set_ip_addr, 0, sizeof(set_ip_addr));
|
||||
|
@ -542,7 +588,8 @@ nfp_fl_pedit(const struct tc_action *action, struct tc_cls_flower_offload *flow,
|
|||
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);
|
||||
err = nfp_fl_set_ip4(action, idx, offset, &set_ip_addr,
|
||||
&set_ip_ttl_tos);
|
||||
break;
|
||||
case TCA_PEDIT_KEY_EX_HDR_TYPE_IP6:
|
||||
err = nfp_fl_set_ip6(action, idx, offset, &set_ip6_dst,
|
||||
|
@ -577,6 +624,16 @@ nfp_fl_pedit(const struct tc_action *action, struct tc_cls_flower_offload *flow,
|
|||
memcpy(nfp_action, &set_eth, act_size);
|
||||
*a_len += act_size;
|
||||
}
|
||||
if (set_ip_ttl_tos.head.len_lw) {
|
||||
nfp_action += act_size;
|
||||
act_size = sizeof(set_ip_ttl_tos);
|
||||
memcpy(nfp_action, &set_ip_ttl_tos, act_size);
|
||||
*a_len += act_size;
|
||||
|
||||
/* Hardware will automatically fix IPv4 and TCP/UDP checksum. */
|
||||
*csum_updated |= TCA_CSUM_UPDATE_FLAG_IPV4HDR |
|
||||
nfp_fl_csum_l4_to_flag(ip_proto);
|
||||
}
|
||||
if (set_ip_addr.head.len_lw) {
|
||||
nfp_action += act_size;
|
||||
act_size = sizeof(set_ip_addr);
|
||||
|
|
|
@ -65,6 +65,7 @@
|
|||
#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_SET_IPV4_TTL_TOS 10
|
||||
#define NFP_FL_ACTION_OPCODE_SET_IPV6_SRC 11
|
||||
#define NFP_FL_ACTION_OPCODE_SET_IPV6_DST 12
|
||||
#define NFP_FL_ACTION_OPCODE_SET_UDP 14
|
||||
|
@ -125,6 +126,15 @@ struct nfp_fl_set_ip4_addrs {
|
|||
__be32 ipv4_dst;
|
||||
};
|
||||
|
||||
struct nfp_fl_set_ip4_ttl_tos {
|
||||
struct nfp_fl_act_head head;
|
||||
u8 ipv4_ttl_mask;
|
||||
u8 ipv4_tos_mask;
|
||||
u8 ipv4_ttl;
|
||||
u8 ipv4_tos;
|
||||
__be16 reserved;
|
||||
};
|
||||
|
||||
struct nfp_fl_set_ipv6_addr {
|
||||
struct nfp_fl_act_head head;
|
||||
__be16 reserved;
|
||||
|
|
Loading…
Reference in New Issue