Skip to content

Commit

Permalink
nfp: flower: add ipv4 set ttl and tos offload
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Pieter Jansen van Vuuren authored and David S. Miller committed Nov 7, 2018
1 parent 6a02d1f commit a3c6b06
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 6 deletions.
69 changes: 63 additions & 6 deletions drivers/net/ethernet/netronome/nfp/flower/action.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand All @@ -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;
}

Expand Down Expand Up @@ -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;
Expand All @@ -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));
Expand All @@ -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,
Expand Down Expand Up @@ -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);
Expand Down
10 changes: 10 additions & 0 deletions drivers/net/ethernet/netronome/nfp/flower/cmsg.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit a3c6b06

Please sign in to comment.