From: Simon Horman <hidden> Date: 2017-09-25 10:24:00
From: Simon Horman <redacted>
John says:
This patch set allows offloading of TC flower match and set tunnel fields
to the NFP. The initial focus is on VXLAN traffic. Due to the current
state of the NFP firmware, only VXLAN traffic on well known port 4789 is
handled. The match and action fields must explicity set this value to be
supported. Tunnel end point information is also offloaded to the NFP for
both encapsulation and decapsulation. The NFP expects 3 separate data sets
to be supplied.
For decapsulation, 2 separate lists exist; a list of MAC addresses
referenced by an index comprised of the port number, and a list of IP
addresses. These IP addresses are not connected to a MAC or port. The MAC
addresses can be written as a block or one at a time (because they have an
index, previous values can be overwritten) while the IP addresses are
always written as a list of all the available IPs. Because the MAC address
used as a tunnel end point may be associated with a physical port or may
be a virtual netdev like an OVS bridge, we do not know which addresses
should be offloaded. For this reason, all MAC addresses of active netdevs
are offloaded to the NFP. A notifier checks for changes to any currently
offloaded MACs or any new netdevs that may occur. For IP addresses, the
tunnel end point used in the rules is known as the destination IP address
must be specified in the flower classifier rule. When a new IP address
appears in a rule, the IP address is offloaded. The IP is removed from the
offloaded list when all rules matching on that IP are deleted.
For encapsulation, a next hop table is updated on the NFP that contains
the source/dest IPs, MACs and egress port. These are written individually
when requested. If the NFP tries to encapsulate a packet but does not know
the next hop, then is sends a request to the host. The host carries out a
route lookup and populates the given entry on the NFP table. A notifier
also exists to check for any links changing or going down in the kernel
next hop table. If an offloaded next hop entry is removed from the kernel
then it is also removed on the NFP.
The NFP periodically sends a message to the host telling it which tunnel
ports have packets egressing the system. The host uses this information to
update the used value in the neighbour entry. This means that, rather than
expire when it times out, the kernel will send an ARP to check if the link
is still live. From an NFP perspective, this means that valid entries will
not be removed from its next hop table.
John Hurley (7):
nfp: add helper to get flower cmsg length
nfp: compile flower vxlan tunnel metadata match fields
nfp: compile flower vxlan tunnel set actions
nfp: offload flower vxlan endpoint MAC addresses
nfp: offload vxlan IPv4 endpoints of flower rules
nfp: flower vxlan neighbour offload
nfp: flower vxlan neighbour keep-alive
drivers/net/ethernet/netronome/nfp/Makefile | 3 +-
drivers/net/ethernet/netronome/nfp/flower/action.c | 169 ++++-
drivers/net/ethernet/netronome/nfp/flower/cmsg.c | 16 +-
drivers/net/ethernet/netronome/nfp/flower/cmsg.h | 87 ++-
drivers/net/ethernet/netronome/nfp/flower/main.c | 13 +
drivers/net/ethernet/netronome/nfp/flower/main.h | 35 +
drivers/net/ethernet/netronome/nfp/flower/match.c | 75 +-
.../net/ethernet/netronome/nfp/flower/metadata.c | 2 +-
.../net/ethernet/netronome/nfp/flower/offload.c | 74 +-
.../ethernet/netronome/nfp/flower/tunnel_conf.c | 811 +++++++++++++++++++++
10 files changed, 1243 insertions(+), 42 deletions(-)
create mode 100644 drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c
--
2.1.4
From: Simon Horman <hidden> Date: 2017-09-25 10:24:01
From: John Hurley <redacted>
Add a helper function that returns the length of the cmsg data when given
the cmsg skb
Signed-off-by: John Hurley <redacted>
Signed-off-by: Simon Horman <redacted>
---
drivers/net/ethernet/netronome/nfp/flower/cmsg.h | 5 +++++
drivers/net/ethernet/netronome/nfp/flower/metadata.c | 2 +-
2 files changed, 6 insertions(+), 1 deletion(-)
From: Simon Horman <hidden> Date: 2017-09-25 10:24:02
From: John Hurley <redacted>
Compile ovs-tc flower vxlan metadata match fields for offloading. Only
support offload of tunnel data when the VXLAN port specifically matches
well known port 4789.
Signed-off-by: John Hurley <redacted>
Signed-off-by: Simon Horman <redacted>
---
drivers/net/ethernet/netronome/nfp/flower/cmsg.h | 38 ++++++++++++
drivers/net/ethernet/netronome/nfp/flower/main.h | 2 +
drivers/net/ethernet/netronome/nfp/flower/match.c | 60 +++++++++++++++++--
.../net/ethernet/netronome/nfp/flower/offload.c | 70 +++++++++++++++++++---
4 files changed, 158 insertions(+), 12 deletions(-)
@@ -230,6 +238,36 @@ struct nfp_flower_ipv6 {structin6_addripv6_dst;};+/* Flow Frame VXLAN --> Tunnel details (4W/16B)+*-----------------------------------------------------------------+*321+*10987654321098765432109876543210+*+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-++*|ipv4_addr_src|+*+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-++*|ipv4_addr_dst|+*+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-++*|tun_flags|tos|ttl|+*+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-++*|gpe_flags|Reserved|NextProtocol|+*+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-++*|VNI|Reserved|+*+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-++*/+structnfp_flower_vxlan{+__be32ip_src;+__be32ip_dst;+__be16tun_flags;+u8tos;+u8ttl;+u8gpe_flags;+u8reserved[2];+u8nxt_proto;+__be32tun_id;+};++#define NFP_FL_TUN_VNI_OFFSET 8+/* The base header for a control message packet.*Definesan8-bitversion,andan8-bittype,padded*toa32-bitword.Restofthepacketistype-specific.
@@ -125,15 +142,58 @@ nfp_flower_calculate_key_layers(struct nfp_fl_key_ls *ret_key_ls,if(flow->dissector->used_keys&~NFP_FLOWER_WHITELIST_DISSECTOR)return-EOPNOTSUPP;+/* If any tun dissector is used then the required set must be used. */+if(flow->dissector->used_keys&NFP_FLOWER_WHITELIST_TUN_DISSECTOR&&+(flow->dissector->used_keys&NFP_FLOWER_WHITELIST_TUN_DISSECTOR_R)+!=NFP_FLOWER_WHITELIST_TUN_DISSECTOR_R)+return-EOPNOTSUPP;++key_layer_two=0;+key_layer=NFP_FLOWER_LAYER_PORT|NFP_FLOWER_LAYER_MAC;+key_size=sizeof(structnfp_flower_meta_one)++sizeof(structnfp_flower_in_port)++sizeof(structnfp_flower_mac_mpls);+if(dissector_uses_key(flow->dissector,FLOW_DISSECTOR_KEY_ENC_CONTROL)){+structflow_dissector_key_ipv4_addrs*mask_ipv4=NULL;+structflow_dissector_key_ports*mask_enc_ports=NULL;+structflow_dissector_key_ports*enc_ports=NULL;structflow_dissector_key_control*mask_enc_ctl=skb_flow_dissector_target(flow->dissector,FLOW_DISSECTOR_KEY_ENC_CONTROL,flow->mask);-/* We are expecting a tunnel. For now we ignore offloading. */-if(mask_enc_ctl->addr_type)+structflow_dissector_key_control*enc_ctl=+skb_flow_dissector_target(flow->dissector,+FLOW_DISSECTOR_KEY_ENC_CONTROL,+flow->key);+if(mask_enc_ctl->addr_type!=0xffff||+enc_ctl->addr_type!=FLOW_DISSECTOR_KEY_IPV4_ADDRS)return-EOPNOTSUPP;++/* These fields are already verified as used. */+mask_ipv4=+skb_flow_dissector_target(flow->dissector,+FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS,+flow->mask);+if(mask_ipv4->dst!=cpu_to_be32(~0))+return-EOPNOTSUPP;++mask_enc_ports=+skb_flow_dissector_target(flow->dissector,+FLOW_DISSECTOR_KEY_ENC_PORTS,+flow->mask);+enc_ports=+skb_flow_dissector_target(flow->dissector,+FLOW_DISSECTOR_KEY_ENC_PORTS,+flow->key);++if(mask_enc_ports->dst!=cpu_to_be16(~0)||+enc_ports->dst!=htons(NFP_FL_VXLAN_PORT))+return-EOPNOTSUPP;++key_layer|=NFP_FLOWER_LAYER_VXLAN;+key_size+=sizeof(structnfp_flower_vxlan);}if(dissector_uses_key(flow->dissector,FLOW_DISSECTOR_KEY_BASIC)){
@@ -151,12 +211,6 @@ nfp_flower_calculate_key_layers(struct nfp_fl_key_ls *ret_key_ls,FLOW_DISSECTOR_KEY_IP,flow->mask);-key_layer_two=0;-key_layer=NFP_FLOWER_LAYER_PORT|NFP_FLOWER_LAYER_MAC;-key_size=sizeof(structnfp_flower_meta_one)+-sizeof(structnfp_flower_in_port)+-sizeof(structnfp_flower_mac_mpls);-if(mask_basic&&mask_basic->n_proto){/* Ethernet type is present in the key. */switch(key_basic->n_proto){
From: Simon Horman <hidden> Date: 2017-09-25 10:24:04
From: John Hurley <redacted>
Compile set tunnel actions for tc flower. Only support VXLAN and ensure a
tunnel destination port of 4789 is used.
Signed-off-by: John Hurley <redacted>
Signed-off-by: Simon Horman <redacted>
---
drivers/net/ethernet/netronome/nfp/flower/action.c | 169 ++++++++++++++++++---
drivers/net/ethernet/netronome/nfp/flower/cmsg.h | 31 +++-
2 files changed, 179 insertions(+), 21 deletions(-)
@@ -80,14 +81,27 @@ nfp_fl_push_vlan(struct nfp_fl_push_vlan *push_vlan,push_vlan->vlan_tci=cpu_to_be16(tmp_push_vlan_tci);}+staticboolnfp_fl_netdev_is_tunnel_type(structnet_device*out_dev,+enumnfp_flower_tun_typetun_type)+{+if(!out_dev->rtnl_link_ops)+returnfalse;++if(!strcmp(out_dev->rtnl_link_ops->kind,"vxlan"))+returntun_type==NFP_FL_TUNNEL_VXLAN;++returnfalse;+}+staticintnfp_fl_output(structnfp_fl_output*output,conststructtc_action*action,structnfp_fl_payload*nfp_flow,boollast,-structnet_device*in_dev)+structnet_device*in_dev,enumnfp_flower_tun_typetun_type,+int*tun_out_cnt){size_tact_size=sizeof(structnfp_fl_output);+u16tmp_output_op,tmp_flags;structnet_device*out_dev;-u16tmp_output_op;intifindex;/* Set action opcode to output action. */
@@ -97,25 +111,114 @@ nfp_fl_output(struct nfp_fl_output *output, const struct tc_action *action,output->a_op=cpu_to_be16(tmp_output_op);-/* Set action output parameters. */-output->flags=cpu_to_be16(last?NFP_FL_OUT_FLAGS_LAST:0);-ifindex=tcf_mirred_ifindex(action);out_dev=__dev_get_by_index(dev_net(in_dev),ifindex);if(!out_dev)return-EOPNOTSUPP;-/* Only offload egress ports are on the same device as the ingress-*port.+tmp_flags=last?NFP_FL_OUT_FLAGS_LAST:0;++if(tun_type){+/* Verify the egress netdev matches the tunnel type. */+if(!nfp_fl_netdev_is_tunnel_type(out_dev,tun_type))+return-EOPNOTSUPP;++if(*tun_out_cnt)+return-EOPNOTSUPP;+(*tun_out_cnt)++;++output->flags=cpu_to_be16(tmp_flags|+NFP_FL_OUT_FLAGS_USE_TUN);+output->port=cpu_to_be32(NFP_FL_PORT_TYPE_TUN|tun_type);+}else{+/* Set action output parameters. */+output->flags=cpu_to_be16(tmp_flags);++/* Only offload if egress ports are on the same device as the+*ingressport.+*/+if(!switchdev_port_same_parent_id(in_dev,out_dev))+return-EOPNOTSUPP;++output->port=cpu_to_be32(nfp_repr_get_port_id(out_dev));+if(!output->port)+return-EOPNOTSUPP;+}+nfp_flow->meta.shortcut=output->port;++return0;+}++staticboolnfp_fl_supported_tun_port(conststructtc_action*action)+{+structip_tunnel_info*tun=tcf_tunnel_info(action);++returntun->key.tp_dst==htons(NFP_FL_VXLAN_PORT);+}++staticstructnfp_fl_pre_tunnel*nfp_fl_pre_tunnel(char*act_data,intact_len)+{+size_tact_size=sizeof(structnfp_fl_pre_tunnel);+structnfp_fl_pre_tunnel*pre_tun_act;+u16tmp_pre_tun_op;++/* Pre_tunnel action must be first on action list.+*Ifotheractionsalreadyexisttheyneedpushedforward.*/-if(!switchdev_port_same_parent_id(in_dev,out_dev))-return-EOPNOTSUPP;+if(act_len)+memmove(act_data+act_size,act_data,act_len);++pre_tun_act=(structnfp_fl_pre_tunnel*)act_data;++memset(pre_tun_act,0,act_size);++tmp_pre_tun_op=+FIELD_PREP(NFP_FL_ACT_LEN_LW,act_size>>NFP_FL_LW_SIZ)|+FIELD_PREP(NFP_FL_ACT_JMP_ID,NFP_FL_ACTION_OPCODE_PRE_TUNNEL);++pre_tun_act->a_op=cpu_to_be16(tmp_pre_tun_op);-output->port=cpu_to_be32(nfp_repr_get_port_id(out_dev));-if(!output->port)+returnpre_tun_act;+}++staticint+nfp_fl_set_vxlan(structnfp_fl_set_vxlan*set_vxlan,+conststructtc_action*action,+structnfp_fl_pre_tunnel*pre_tun)+{+structip_tunnel_info*vxlan=tcf_tunnel_info(action);+size_tact_size=sizeof(structnfp_fl_set_vxlan);+u32tmp_set_vxlan_type_index=0;+u16tmp_set_vxlan_op;+/* Currently support one pre-tunnel so index is always 0. */+intpretun_idx=0;++if(vxlan->options_len){+/* Do not support options e.g. vxlan gpe. */return-EOPNOTSUPP;+}-nfp_flow->meta.shortcut=output->port;+tmp_set_vxlan_op=+FIELD_PREP(NFP_FL_ACT_LEN_LW,act_size>>NFP_FL_LW_SIZ)|+FIELD_PREP(NFP_FL_ACT_JMP_ID,+NFP_FL_ACTION_OPCODE_SET_IPV4_TUNNEL);++set_vxlan->a_op=cpu_to_be16(tmp_set_vxlan_op);++/* Set tunnel type and pre-tunnel index. */+tmp_set_vxlan_type_index|=+FIELD_PREP(NFP_FL_IPV4_TUNNEL_TYPE,NFP_FL_TUNNEL_VXLAN)|+FIELD_PREP(NFP_FL_IPV4_PRE_TUN_INDEX,pretun_idx);++set_vxlan->tun_type_index=cpu_to_be32(tmp_set_vxlan_type_index);++set_vxlan->tun_id=vxlan->key.tun_id;+set_vxlan->tun_flags=vxlan->key.tun_flags;+set_vxlan->ipv4_ttl=vxlan->key.ttl;+set_vxlan->ipv4_tos=vxlan->key.tos;++/* Complete pre_tunnel action. */+pre_tun->ipv4_dst=vxlan->key.u.ipv4.dst;return0;}
@@ -170,6 +278,29 @@ nfp_flower_loop_action(const struct tc_action *a,nfp_fl_push_vlan(psh_v,a);*a_len+=sizeof(structnfp_fl_push_vlan);+}elseif(is_tcf_tunnel_set(a)&&nfp_fl_supported_tun_port(a)){+/* Pre-tunnel action is required for tunnel encap.+*ThischecksfornexthopentriesonNFP.+*Ifnone,thepacketfallsbackbeforeapplyingotheractions.+*/+if(*a_len+sizeof(structnfp_fl_pre_tunnel)++sizeof(structnfp_fl_set_vxlan)>NFP_FL_MAX_A_SIZ)+return-EOPNOTSUPP;++*tun_type=NFP_FL_TUNNEL_VXLAN;+pre_tun=nfp_fl_pre_tunnel(nfp_fl->action_data,*a_len);+nfp_fl->meta.shortcut=cpu_to_be32(NFP_FL_SC_ACT_NULL);+*a_len+=sizeof(structnfp_fl_pre_tunnel);++s_vxl=(structnfp_fl_set_vxlan*)&nfp_fl->action_data[*a_len];+err=nfp_fl_set_vxlan(s_vxl,a,pre_tun);+if(err)+returnerr;++*a_len+=sizeof(structnfp_fl_set_vxlan);+}elseif(is_tcf_tunnel_release(a)){+/* Tunnel decap is handled by default so accept action. */+return0;}else{/* Currently we do not handle any other actions. */return-EOPNOTSUPP;
@@ -182,18 +313,22 @@ int nfp_flower_compile_action(struct tc_cls_flower_offload *flow,structnet_device*netdev,structnfp_fl_payload*nfp_flow){-intact_len,act_cnt,err;+intact_len,act_cnt,err,tun_out_cnt;+enumnfp_flower_tun_typetun_type;conststructtc_action*a;LIST_HEAD(actions);memset(nfp_flow->action_data,0,NFP_FL_MAX_A_SIZ);nfp_flow->meta.act_len=0;+tun_type=NFP_FL_TUNNEL_NONE;act_len=0;act_cnt=0;+tun_out_cnt=0;tcf_exts_to_list(flow->exts,&actions);list_for_each_entry(a,&actions,list){-err=nfp_flower_loop_action(a,nfp_flow,&act_len,netdev);+err=nfp_flower_loop_action(a,nfp_flow,&act_len,netdev,+&tun_type,&tun_out_cnt);if(err)returnerr;act_cnt++;
@@ -123,6 +127,25 @@ struct nfp_flower_meta_one {u16reserved;};+structnfp_fl_pre_tunnel{+__be16a_op;+__be16reserved;+__be32ipv4_dst;+/* reserved for use with IPv6 addresses */+__be32extra[3];+};++structnfp_fl_set_vxlan{+__be16a_op;+__be16reserved;+__be64tun_id;+__be32tun_type_index;+__be16tun_flags;+u8ipv4_ttl;+u8ipv4_tos;+__be32extra[2];+}__packed;+/* Metadata with L2 (1W/4B)*----------------------------------------------------------------*321
From: Simon Horman <hidden> Date: 2017-09-25 10:24:05
From: John Hurley <redacted>
Generate a list of MAC addresses of netdevs that could be used as VXLAN
tunnel end points. Give offloaded MACs an index for storage on the NFP in
the ranges:
0x100-0x1ff physical port representors
0x200-0x2ff VF port representors
0x300-0x3ff other offloads (e.g. vxlan netdevs, ovs bridges)
Assign phys and vf indexes based on unique 8 bit values in the port num.
Maintain list of other netdevs to ensure same netdev is not offloaded
twice and each gets a unique ID without exhausting the entries. Because
the IDs are unique but constant for a netdev, any changes are implemented
by overwriting the index on NFP.
Signed-off-by: John Hurley <redacted>
Signed-off-by: Simon Horman <redacted>
---
drivers/net/ethernet/netronome/nfp/Makefile | 3 +-
drivers/net/ethernet/netronome/nfp/flower/cmsg.c | 7 -
drivers/net/ethernet/netronome/nfp/flower/cmsg.h | 9 +
drivers/net/ethernet/netronome/nfp/flower/main.c | 13 +
drivers/net/ethernet/netronome/nfp/flower/main.h | 18 +
drivers/net/ethernet/netronome/nfp/flower/match.c | 7 +
.../ethernet/netronome/nfp/flower/tunnel_conf.c | 374 +++++++++++++++++++++
7 files changed, 423 insertions(+), 8 deletions(-)
create mode 100644 drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c
@@ -232,6 +232,7 @@ int nfp_flower_compile_flow_match(struct tc_cls_flower_offload *flow,structnfp_fl_payload*nfp_flow){enumnfp_flower_tun_typetun_type=NFP_FL_TUNNEL_NONE;+structnfp_repr*netdev_repr;interr;u8*ext;u8*msk;
@@ -341,6 +342,12 @@ int nfp_flower_compile_flow_match(struct tc_cls_flower_offload *flow,flow,true);ext+=sizeof(structnfp_flower_vxlan);msk+=sizeof(structnfp_flower_vxlan);++/* Configure tunnel end point MAC. */+if(nfp_netdev_is_nfp_repr(netdev)){+netdev_repr=netdev_priv(netdev);+nfp_tunnel_write_macs(netdev_repr->app);+}}return0;
@@ -0,0 +1,374 @@+/*+*Copyright(C)2017NetronomeSystems,Inc.+*+*ThissoftwareisduallicensedundertheGNUGeneralLicenseVersion2,+*June1991asshowninthefileCOPYINGinthetop-leveldirectoryofthis+*sourcetreeortheBSD2-ClauseLicenseprovidedbelow.Youhavethe+*optiontolicensethissoftwareunderthecompletetermsofeitherlicense.+*+*TheBSD2-ClauseLicense:+*+*Redistributionanduseinsourceandbinaryforms,withor+*withoutmodification,arepermittedprovidedthatthefollowing+*conditionsaremet:+*+*1.Redistributionsofsourcecodemustretaintheabove+*copyrightnotice,thislistofconditionsandthefollowing+*disclaimer.+*+*2.Redistributionsinbinaryformmustreproducetheabove+*copyrightnotice,thislistofconditionsandthefollowing+*disclaimerinthedocumentationand/orothermaterials+*providedwiththedistribution.+*+*THESOFTWAREISPROVIDED"AS IS",WITHOUTWARRANTYOFANYKIND,+*EXPRESSORIMPLIED,INCLUDINGBUTNOTLIMITEDTOTHEWARRANTIESOF+*MERCHANTABILITY,FITNESSFORAPARTICULARPURPOSEAND+*NONINFRINGEMENT.INNOEVENTSHALLTHEAUTHORSORCOPYRIGHTHOLDERS+*BELIABLEFORANYCLAIM,DAMAGESOROTHERLIABILITY,WHETHERINAN+*ACTIONOFCONTRACT,TORTOROTHERWISE,ARISINGFROM,OUTOFORIN+*CONNECTIONWITHTHESOFTWAREORTHEUSEOROTHERDEALINGSINTHE+*SOFTWARE.+*/++#include<linux/etherdevice.h>+#include<linux/idr.h>+#include<net/dst_metadata.h>++#include"cmsg.h"+#include"main.h"+#include"../nfp_net_repr.h"+#include"../nfp_net.h"++/**+*structnfp_tun_mac_addr-configureMACaddressoftunnelEPonNFP+*@reserved:reservedforfutureuse+*@count:numberofMACaddressesinthemessage+*@index:indexofMACaddressinthelookuptable+*@addr:interfaceMACaddress+*@addresses:seriesofMACstooffload+*/+structnfp_tun_mac_addr{+__be16reserved;+__be16count;+structindex_mac_addr{+__be16index;+u8addr[ETH_ALEN];+}addresses[];+};++/**+*structnfp_tun_mac_offload_entry-listofMACstooffload+*@index:indexofMACaddressforoffloading+*@addr:interfaceMACaddress+*@list:listpointer+*/+structnfp_tun_mac_offload_entry{+__be16index;+u8addr[ETH_ALEN];+structlist_headlist;+};++#define NFP_MAX_MAC_INDEX 0xff++/**+*structnfp_tun_mac_non_nfp_idx-convertsnonNFPnetdevifindexto8-bitid+*@ifindex:netdevifindexofthedevice+*@index:indexofnetdevsmaconNFP+*@list:listpointer+*/+structnfp_tun_mac_non_nfp_idx{+intifindex;+u8index;+structlist_headlist;+};++staticboolnfp_tun_is_netdev_to_offload(structnet_device*netdev)+{+if(!netdev->rtnl_link_ops)+returnfalse;+if(!strcmp(netdev->rtnl_link_ops->kind,"openvswitch"))+returntrue;+if(!strcmp(netdev->rtnl_link_ops->kind,"vxlan"))+returntrue;++returnfalse;+}++staticint+nfp_flower_xmit_tun_conf(structnfp_app*app,u8mtype,u16plen,void*pdata)+{+structsk_buff*skb;+unsignedchar*msg;++skb=nfp_flower_cmsg_alloc(app,plen,mtype);+if(!skb)+return-ENOMEM;++msg=nfp_flower_cmsg_get_data(skb);+memcpy(msg,pdata,nfp_flower_cmsg_get_data_len(skb));++nfp_ctrl_tx(app->ctrl,skb);+return0;+}++voidnfp_tunnel_write_macs(structnfp_app*app)+{+structnfp_flower_priv*priv=app->priv;+structnfp_tun_mac_offload_entry*entry;+structnfp_tun_mac_addr*payload;+structlist_head*ptr,*storage;+intmac_count,err,pay_size;++mutex_lock(&priv->nfp_mac_off_lock);+if(!priv->nfp_mac_off_count){+mutex_unlock(&priv->nfp_mac_off_lock);+return;+}++pay_size=sizeof(structnfp_tun_mac_addr)++sizeof(structindex_mac_addr)*priv->nfp_mac_off_count;++payload=kzalloc(pay_size,GFP_KERNEL);+if(!payload){+mutex_unlock(&priv->nfp_mac_off_lock);+return;+}++payload->count=cpu_to_be16(priv->nfp_mac_off_count);++mac_count=0;+list_for_each_safe(ptr,storage,&priv->nfp_mac_off_list){+entry=list_entry(ptr,structnfp_tun_mac_offload_entry,+list);+payload->addresses[mac_count].index=entry->index;+ether_addr_copy(payload->addresses[mac_count].addr,+entry->addr);+mac_count++;+}++err=nfp_flower_xmit_tun_conf(app,NFP_FLOWER_CMSG_TYPE_TUN_MAC,+pay_size,payload);++kfree(payload);++if(err){+mutex_unlock(&priv->nfp_mac_off_lock);+/* Write failed so retain list for future retry. */+return;+}++/* If list was successfully offloaded, flush it. */+list_for_each_safe(ptr,storage,&priv->nfp_mac_off_list){+entry=list_entry(ptr,structnfp_tun_mac_offload_entry,+list);+list_del(&entry->list);+kfree(entry);+}++priv->nfp_mac_off_count=0;+mutex_unlock(&priv->nfp_mac_off_lock);+}++staticintnfp_tun_get_mac_idx(structnfp_app*app,intifindex)+{+structnfp_flower_priv*priv=app->priv;+structnfp_tun_mac_non_nfp_idx*entry;+structlist_head*ptr,*storage;+intidx;++mutex_lock(&priv->nfp_mac_index_lock);+list_for_each_safe(ptr,storage,&priv->nfp_mac_index_list){+entry=list_entry(ptr,structnfp_tun_mac_non_nfp_idx,list);+if(entry->ifindex==ifindex){+idx=entry->index;+mutex_unlock(&priv->nfp_mac_index_lock);+returnidx;+}+}++idx=ida_simple_get(&priv->nfp_mac_off_ids,0,+NFP_MAX_MAC_INDEX,GFP_KERNEL);+if(idx<0){+mutex_unlock(&priv->nfp_mac_index_lock);+returnidx;+}++entry=kmalloc(sizeof(*entry),GFP_KERNEL);+if(!entry){+mutex_unlock(&priv->nfp_mac_index_lock);+return-ENOMEM;+}+entry->ifindex=ifindex;+entry->index=idx;+list_add_tail(&entry->list,&priv->nfp_mac_index_list);+mutex_unlock(&priv->nfp_mac_index_lock);++returnidx;+}++staticvoidnfp_tun_del_mac_idx(structnfp_app*app,intifindex)+{+structnfp_flower_priv*priv=app->priv;+structnfp_tun_mac_non_nfp_idx*entry;+structlist_head*ptr,*storage;++mutex_lock(&priv->nfp_mac_index_lock);+list_for_each_safe(ptr,storage,&priv->nfp_mac_index_list){+entry=list_entry(ptr,structnfp_tun_mac_non_nfp_idx,list);+if(entry->ifindex==ifindex){+ida_simple_remove(&priv->nfp_mac_off_ids,+entry->index);+list_del(&entry->list);+kfree(entry);+break;+}+}+mutex_unlock(&priv->nfp_mac_index_lock);+}++staticvoidnfp_tun_add_to_mac_offload_list(structnet_device*netdev,+structnfp_app*app)+{+structnfp_flower_priv*priv=app->priv;+structnfp_tun_mac_offload_entry*entry;+u16nfp_mac_idx;+intport=0;++/* Check if MAC should be offloaded. */+if(!is_valid_ether_addr(netdev->dev_addr))+return;++if(nfp_netdev_is_nfp_repr(netdev))+port=nfp_repr_get_port_id(netdev);+elseif(!nfp_tun_is_netdev_to_offload(netdev))+return;++entry=kmalloc(sizeof(*entry),GFP_KERNEL);+if(!entry){+nfp_flower_cmsg_warn(app,"Mem fail when offloading MAC.\n");+return;+}++if(FIELD_GET(NFP_FLOWER_CMSG_PORT_TYPE,port)==+NFP_FLOWER_CMSG_PORT_TYPE_PHYS_PORT){+nfp_mac_idx=port<<8|NFP_FLOWER_CMSG_PORT_TYPE_PHYS_PORT;+}elseif(FIELD_GET(NFP_FLOWER_CMSG_PORT_TYPE,port)==+NFP_FLOWER_CMSG_PORT_TYPE_PCIE_PORT){+port=FIELD_GET(NFP_FLOWER_CMSG_PORT_VNIC,port);+nfp_mac_idx=port<<8|NFP_FLOWER_CMSG_PORT_TYPE_PCIE_PORT;+}else{+/* Must assign our own unique 8-bit index. */+intidx=nfp_tun_get_mac_idx(app,netdev->ifindex);++if(idx<0){+nfp_flower_cmsg_warn(app,"Can't assign non-repr MAC index.\n");+kfree(entry);+return;+}+nfp_mac_idx=idx<<8|NFP_FLOWER_CMSG_PORT_TYPE_OTHER_PORT;+}++entry->index=cpu_to_be16(nfp_mac_idx);+ether_addr_copy(entry->addr,netdev->dev_addr);++mutex_lock(&priv->nfp_mac_off_lock);+priv->nfp_mac_off_count++;+list_add_tail(&entry->list,&priv->nfp_mac_off_list);+mutex_unlock(&priv->nfp_mac_off_lock);+}++staticintnfp_tun_mac_event_handler(structnotifier_block*nb,+unsignedlongevent,void*ptr)+{+structnfp_flower_priv*app_priv;+structnet_device*netdev;+structnfp_app*app;++if(event==NETDEV_DOWN||event==NETDEV_UNREGISTER){+app_priv=container_of(nb,structnfp_flower_priv,+nfp_tun_mac_nb);+app=app_priv->app;+netdev=netdev_notifier_info_to_dev(ptr);++/* If non-nfp netdev then free its offload index. */+if(nfp_tun_is_netdev_to_offload(netdev))+nfp_tun_del_mac_idx(app,netdev->ifindex);+}elseif(event==NETDEV_UP||event==NETDEV_CHANGEADDR||+event==NETDEV_REGISTER){+app_priv=container_of(nb,structnfp_flower_priv,+nfp_tun_mac_nb);+app=app_priv->app;+netdev=netdev_notifier_info_to_dev(ptr);++nfp_tun_add_to_mac_offload_list(netdev,app);++/* Force a list write to keep NFP up to date. */+nfp_tunnel_write_macs(app);+}+returnNOTIFY_OK;+}++intnfp_tunnel_config_start(structnfp_app*app)+{+structnfp_flower_priv*priv=app->priv;+structnet_device*netdev;+interr;++/* Initialise priv data for MAC offloading. */+priv->nfp_mac_off_count=0;+mutex_init(&priv->nfp_mac_off_lock);+INIT_LIST_HEAD(&priv->nfp_mac_off_list);+priv->nfp_tun_mac_nb.notifier_call=nfp_tun_mac_event_handler;+mutex_init(&priv->nfp_mac_index_lock);+INIT_LIST_HEAD(&priv->nfp_mac_index_list);+ida_init(&priv->nfp_mac_off_ids);++err=register_netdevice_notifier(&priv->nfp_tun_mac_nb);+if(err)+gotoerr_free_mac_ida;++/* Parse netdevs already registered for MACs that need offloaded. */+rtnl_lock();+for_each_netdev(&init_net,netdev)+nfp_tun_add_to_mac_offload_list(netdev,app);+rtnl_unlock();++return0;++err_free_mac_ida:+ida_destroy(&priv->nfp_mac_off_ids);+returnerr;+}++voidnfp_tunnel_config_stop(structnfp_app*app)+{+structnfp_tun_mac_offload_entry*mac_entry;+structnfp_flower_priv*priv=app->priv;+structnfp_tun_mac_non_nfp_idx*mac_idx;+structlist_head*ptr,*storage;++unregister_netdevice_notifier(&priv->nfp_tun_mac_nb);++/* Free any memory that may be occupied by MAC list. */+mutex_lock(&priv->nfp_mac_off_lock);+list_for_each_safe(ptr,storage,&priv->nfp_mac_off_list){+mac_entry=list_entry(ptr,structnfp_tun_mac_offload_entry,+list);+list_del(&mac_entry->list);+kfree(mac_entry);+}+mutex_unlock(&priv->nfp_mac_off_lock);++/* Free any memory that may be occupied by MAC index list. */+mutex_lock(&priv->nfp_mac_index_lock);+list_for_each_safe(ptr,storage,&priv->nfp_mac_index_list){+mac_idx=list_entry(ptr,structnfp_tun_mac_non_nfp_idx,+list);+list_del(&mac_idx->list);+kfree(mac_idx);+}+mutex_unlock(&priv->nfp_mac_index_lock);++ida_destroy(&priv->nfp_mac_off_ids);+}
From: Simon Horman <hidden> Date: 2017-09-25 10:24:07
From: John Hurley <redacted>
Maintain a list of IPv4 addresses used as the tunnel destination IP match
fields in currently active flower rules. Offload the entire list of
NFP_FL_IPV4_ADDRS_MAX (even if some are unused) when new IPs are added or
removed. The NFP should only be aware of tunnel end points that are
currently used by rules on the device
Signed-off-by: John Hurley <redacted>
Reviewed-by: Simon Horman <redacted>
Signed-off-by: Simon Horman <redacted>
---
drivers/net/ethernet/netronome/nfp/flower/cmsg.h | 1 +
drivers/net/ethernet/netronome/nfp/flower/main.h | 7 ++
drivers/net/ethernet/netronome/nfp/flower/match.c | 14 ++-
.../net/ethernet/netronome/nfp/flower/offload.c | 4 +
.../ethernet/netronome/nfp/flower/tunnel_conf.c | 120 +++++++++++++++++++++
5 files changed, 143 insertions(+), 3 deletions(-)
@@ -347,6 +349,12 @@ int nfp_flower_compile_flow_match(struct tc_cls_flower_offload *flow,if(nfp_netdev_is_nfp_repr(netdev)){netdev_repr=netdev_priv(netdev);nfp_tunnel_write_macs(netdev_repr->app);++/* Store the tunnel destination in the rule data.+*Thismustbepresentandbeanexactmatch.+*/+nfp_flow->nfp_tun_ipv4_addr=tun_dst;+nfp_tunnel_add_ipv4_off(netdev_repr->app,tun_dst);}}
@@ -324,6 +430,10 @@ int nfp_tunnel_config_start(struct nfp_app *app)INIT_LIST_HEAD(&priv->nfp_mac_index_list);ida_init(&priv->nfp_mac_off_ids);+/* Initialise priv data for IPv4 offloading. */+mutex_init(&priv->nfp_ipv4_off_lock);+INIT_LIST_HEAD(&priv->nfp_ipv4_off_list);+err=register_netdevice_notifier(&priv->nfp_tun_mac_nb);if(err)gotoerr_free_mac_ida;
@@ -371,4 +482,13 @@ void nfp_tunnel_config_stop(struct nfp_app *app)mutex_unlock(&priv->nfp_mac_index_lock);ida_destroy(&priv->nfp_mac_off_ids);++/* Free any memory that may be occupied by ipv4 list. */+mutex_lock(&priv->nfp_ipv4_off_lock);+list_for_each_safe(ptr,storage,&priv->nfp_ipv4_off_list){+ip_entry=list_entry(ptr,structnfp_ipv4_addr_entry,list);+list_del(&ip_entry->list);+kfree(ip_entry);+}+mutex_unlock(&priv->nfp_ipv4_off_lock);}
From: Simon Horman <hidden> Date: 2017-09-25 10:24:08
From: John Hurley <redacted>
Receive a request when the NFP does not know the next hop for a packet
that is to be encapsulated in a VXLAN tunnel. Do a route lookup, determine
the next hop entry and update neighbour table on NFP. Monitor the kernel
neighbour table for link changes and update NFP with relevant information.
Overwrite routes with zero values on the NFP when they expire.
Signed-off-by: John Hurley <redacted>
Reviewed-by: Simon Horman <redacted>
Signed-off-by: Simon Horman <redacted>
---
drivers/net/ethernet/netronome/nfp/flower/cmsg.c | 6 +
drivers/net/ethernet/netronome/nfp/flower/cmsg.h | 2 +
drivers/net/ethernet/netronome/nfp/flower/main.h | 7 +
.../ethernet/netronome/nfp/flower/tunnel_conf.c | 253 +++++++++++++++++++++
4 files changed, 268 insertions(+)
@@ -181,6 +181,12 @@ nfp_flower_cmsg_process_one_rx(struct nfp_app *app, struct sk_buff *skb)caseNFP_FLOWER_CMSG_TYPE_FLOW_STATS:nfp_flower_rx_flow_stats(app,skb);break;+caseNFP_FLOWER_CMSG_TYPE_NO_NEIGH:+nfp_tunnel_request_route(app,skb);+break;+caseNFP_FLOWER_CMSG_TYPE_TUN_NEIGH:+/* Acks from the NFP that the route is added - ignore. */+break;default:nfp_flower_cmsg_warn(app,"Cannot handle invalid repr control type %u\n",type);
@@ -137,6 +176,197 @@ nfp_flower_xmit_tun_conf(struct nfp_app *app, u8 mtype, u16 plen, void *pdata)return0;}+staticboolnfp_tun_has_route(structnfp_app*app,__be32ipv4_addr)+{+structnfp_flower_priv*priv=app->priv;+structnfp_ipv4_route_entry*entry;+structlist_head*ptr,*storage;++mutex_lock(&priv->nfp_neigh_off_lock);+list_for_each_safe(ptr,storage,&priv->nfp_neigh_off_list){+entry=list_entry(ptr,structnfp_ipv4_route_entry,list);+if(entry->ipv4_addr==ipv4_addr){+mutex_unlock(&priv->nfp_neigh_off_lock);+returntrue;+}+}+mutex_unlock(&priv->nfp_neigh_off_lock);+returnfalse;+}++staticvoidnfp_tun_add_route_to_cache(structnfp_app*app,__be32ipv4_addr)+{+structnfp_flower_priv*priv=app->priv;+structnfp_ipv4_route_entry*entry;+structlist_head*ptr,*storage;++mutex_lock(&priv->nfp_neigh_off_lock);+list_for_each_safe(ptr,storage,&priv->nfp_neigh_off_list){+entry=list_entry(ptr,structnfp_ipv4_route_entry,list);+if(entry->ipv4_addr==ipv4_addr){+mutex_unlock(&priv->nfp_neigh_off_lock);+return;+}+}+entry=kmalloc(sizeof(*entry),GFP_KERNEL);+if(!entry){+mutex_unlock(&priv->nfp_neigh_off_lock);+nfp_flower_cmsg_warn(app,"Mem error when storing new route.\n");+return;+}++entry->ipv4_addr=ipv4_addr;+list_add_tail(&entry->list,&priv->nfp_neigh_off_list);+mutex_unlock(&priv->nfp_neigh_off_lock);+}++staticvoidnfp_tun_del_route_from_cache(structnfp_app*app,__be32ipv4_addr)+{+structnfp_flower_priv*priv=app->priv;+structnfp_ipv4_route_entry*entry;+structlist_head*ptr,*storage;++mutex_lock(&priv->nfp_neigh_off_lock);+list_for_each_safe(ptr,storage,&priv->nfp_neigh_off_list){+entry=list_entry(ptr,structnfp_ipv4_route_entry,list);+if(entry->ipv4_addr==ipv4_addr){+list_del(&entry->list);+kfree(entry);+break;+}+}+mutex_unlock(&priv->nfp_neigh_off_lock);+}++staticvoid+nfp_tun_write_neigh(structnet_device*netdev,structnfp_app*app,+structflowi4*flow,structneighbour*neigh)+{+structnfp_tun_neighpayload;++/* Only offload representor IPv4s for now. */+if(!nfp_netdev_is_nfp_repr(netdev))+return;++memset(&payload,0,sizeof(structnfp_tun_neigh));+payload.dst_ipv4=flow->daddr;++/* If entry has expired send dst IP with all other fields 0. */+if(!(neigh->nud_state&NUD_VALID)){+nfp_tun_del_route_from_cache(app,payload.dst_ipv4);+/* Trigger ARP to verify invalid neighbour state. */+neigh_event_send(neigh,NULL);+gotosend_msg;+}++/* Have a valid neighbour so populate rest of entry. */+payload.src_ipv4=flow->saddr;+ether_addr_copy(payload.src_addr,netdev->dev_addr);+neigh_ha_snapshot(payload.dst_addr,neigh,netdev);+payload.port_id=cpu_to_be32(nfp_repr_get_port_id(netdev));+/* Add destination of new route to NFP cache. */+nfp_tun_add_route_to_cache(app,payload.dst_ipv4);++send_msg:+nfp_flower_xmit_tun_conf(app,NFP_FLOWER_CMSG_TYPE_TUN_NEIGH,+sizeof(structnfp_tun_neigh),+(unsignedchar*)&payload);+}++staticint+nfp_tun_neigh_event_handler(structnotifier_block*nb,unsignedlongevent,+void*ptr)+{+structnfp_flower_priv*app_priv;+structnetevent_redirect*redir;+structflowi4flow={};+structneighbour*n;+structnfp_app*app;+structrtable*rt;+interr;++switch(event){+caseNETEVENT_REDIRECT:+redir=(structnetevent_redirect*)ptr;+n=redir->neigh;+break;+caseNETEVENT_NEIGH_UPDATE:+n=(structneighbour*)ptr;+break;+default:+returnNOTIFY_DONE;+}++flow.daddr=*(__be32*)n->primary_key;++/* Only concerned with route changes for representors. */+if(!nfp_netdev_is_nfp_repr(n->dev))+returnNOTIFY_DONE;++app_priv=container_of(nb,structnfp_flower_priv,nfp_tun_neigh_nb);+app=app_priv->app;++/* Only concerned with changes to routes already added to NFP. */+if(!nfp_tun_has_route(app,flow.daddr))+returnNOTIFY_DONE;++#if IS_ENABLED(CONFIG_INET)+/* Do a route lookup to populate flow data. */+rt=ip_route_output_key(dev_net(n->dev),&flow);+err=PTR_ERR_OR_ZERO(rt);+if(err)+returnNOTIFY_DONE;+#else+returnNOTIFY_DONE;+#endif++flow.flowi4_proto=IPPROTO_UDP;+nfp_tun_write_neigh(n->dev,app,&flow,n);++returnNOTIFY_OK;+}++voidnfp_tunnel_request_route(structnfp_app*app,structsk_buff*skb)+{+structnfp_tun_req_route_ipv4*payload;+structnet_device*netdev;+structflowi4flow={};+structneighbour*n;+structrtable*rt;+interr;++payload=nfp_flower_cmsg_get_data(skb);++netdev=nfp_app_repr_get(app,be32_to_cpu(payload->ingress_port));+if(!netdev)+gotoroute_fail_warning;++flow.daddr=payload->ipv4_addr;+flow.flowi4_proto=IPPROTO_UDP;++#if IS_ENABLED(CONFIG_INET)+/* Do a route lookup on same namespace as ingress port. */+rt=ip_route_output_key(dev_net(netdev),&flow);+err=PTR_ERR_OR_ZERO(rt);+if(err)+gotoroute_fail_warning;+#else+gotoroute_fail_warning;+#endif++/* Get the neighbour entry for the lookup */+n=dst_neigh_lookup(&rt->dst,&flow.daddr);+ip_rt_put(rt);+if(!n)+gotoroute_fail_warning;+nfp_tun_write_neigh(n->dev,app,&flow,n);+neigh_release(n);+return;++route_fail_warning:+nfp_flower_cmsg_warn(app,"Requested route not found.\n");+}+staticvoidnfp_tun_write_ipv4_list(structnfp_app*app){structnfp_flower_priv*priv=app->priv;
@@ -434,10 +664,19 @@ int nfp_tunnel_config_start(struct nfp_app *app)mutex_init(&priv->nfp_ipv4_off_lock);INIT_LIST_HEAD(&priv->nfp_ipv4_off_list);+/* Initialise priv data for neighbour offloading. */+mutex_init(&priv->nfp_neigh_off_lock);+INIT_LIST_HEAD(&priv->nfp_neigh_off_list);+priv->nfp_tun_neigh_nb.notifier_call=nfp_tun_neigh_event_handler;+err=register_netdevice_notifier(&priv->nfp_tun_mac_nb);if(err)gotoerr_free_mac_ida;+err=register_netevent_notifier(&priv->nfp_tun_neigh_nb);+if(err)+gotoerr_unreg_mac_nb;+/* Parse netdevs already registered for MACs that need offloaded. */rtnl_lock();for_each_netdev(&init_net,netdev)
@@ -446,6 +685,8 @@ int nfp_tunnel_config_start(struct nfp_app *app)return0;+err_unreg_mac_nb:+unregister_netdevice_notifier(&priv->nfp_tun_mac_nb);err_free_mac_ida:ida_destroy(&priv->nfp_mac_off_ids);returnerr;
@@ -455,11 +696,13 @@ void nfp_tunnel_config_stop(struct nfp_app *app){structnfp_tun_mac_offload_entry*mac_entry;structnfp_flower_priv*priv=app->priv;+structnfp_ipv4_route_entry*route_entry;structnfp_tun_mac_non_nfp_idx*mac_idx;structnfp_ipv4_addr_entry*ip_entry;structlist_head*ptr,*storage;unregister_netdevice_notifier(&priv->nfp_tun_mac_nb);+unregister_netevent_notifier(&priv->nfp_tun_neigh_nb);/* Free any memory that may be occupied by MAC list. */mutex_lock(&priv->nfp_mac_off_lock);
@@ -491,4 +734,14 @@ void nfp_tunnel_config_stop(struct nfp_app *app)kfree(ip_entry);}mutex_unlock(&priv->nfp_ipv4_off_lock);++/* Free any memory that may be occupied by the route list. */+mutex_lock(&priv->nfp_neigh_off_lock);+list_for_each_safe(ptr,storage,&priv->nfp_neigh_off_list){+route_entry=list_entry(ptr,structnfp_ipv4_route_entry,+list);+list_del(&route_entry->list);+kfree(route_entry);+}+mutex_unlock(&priv->nfp_neigh_off_lock);}
From: Simon Horman <hidden> Date: 2017-09-25 10:24:09
From: John Hurley <redacted>
Periodically receive messages containing the destination IPs of tunnels
that have recently forwarded traffic. Update the neighbour entries 'used'
value for these IPs next hop.
This prevents the neighbour entry from expiring on timeout but rather
signals an ARP to verify the connection. From an NFP perspective, packets
will not fall back mid-flow unless the link is verified to be down.
Signed-off-by: John Hurley <redacted>
Reviewed-by: Simon Horman <redacted>
Signed-off-by: Simon Horman <redacted>
---
drivers/net/ethernet/netronome/nfp/flower/cmsg.c | 3 +
drivers/net/ethernet/netronome/nfp/flower/cmsg.h | 1 +
drivers/net/ethernet/netronome/nfp/flower/main.h | 1 +
.../ethernet/netronome/nfp/flower/tunnel_conf.c | 64 ++++++++++++++++++++++
4 files changed, 69 insertions(+)
@@ -184,6 +184,9 @@ nfp_flower_cmsg_process_one_rx(struct nfp_app *app, struct sk_buff *skb)caseNFP_FLOWER_CMSG_TYPE_NO_NEIGH:nfp_tunnel_request_route(app,skb);break;+caseNFP_FLOWER_CMSG_TYPE_ACTIVE_TUNS:+nfp_tunnel_keep_alive(app,skb);+break;caseNFP_FLOWER_CMSG_TYPE_TUN_NEIGH:/* Acks from the NFP that the route is added - ignore. */break;
@@ -147,6 +171,46 @@ struct nfp_tun_mac_non_nfp_idx {structlist_headlist;};+voidnfp_tunnel_keep_alive(structnfp_app*app,structsk_buff*skb)+{+structnfp_tun_active_tuns*payload;+structnet_device*netdev;+intcount,i,pay_len;+structneighbour*n;+__be32ipv4_addr;+u32port;++payload=nfp_flower_cmsg_get_data(skb);+count=be32_to_cpu(payload->count);+if(count>NFP_FL_MAX_ROUTES){+nfp_flower_cmsg_warn(app,"Tunnel keep-alive request exceeds max routes.\n");+return;+}++pay_len=nfp_flower_cmsg_get_data_len(skb);+if(pay_len!=sizeof(structnfp_tun_active_tuns)++sizeof(structroute_ip_info)*count){+nfp_flower_cmsg_warn(app,"Corruption in tunnel keep-alive message.\n");+return;+}++for(i=0;i<count;i++){+ipv4_addr=payload->tun_info[i].ipv4;+port=be32_to_cpu(payload->tun_info[i].egress_port);+netdev=nfp_app_repr_get(app,port);+if(!netdev)+continue;++n=neigh_lookup(&arp_tbl,&ipv4_addr,netdev);+if(!n)+continue;++/* Update the used timestamp of neighbour */+neigh_event_send(n,NULL);+neigh_release(n);+}+}+staticboolnfp_tun_is_netdev_to_offload(structnet_device*netdev){if(!netdev->rtnl_link_ops)
From: Jakub Kicinski <hidden> Date: 2017-09-25 11:00:56
On Mon, 25 Sep 2017 12:23:34 +0200, Simon Horman wrote:
From: Simon Horman <redacted>
John says:
This patch set allows offloading of TC flower match and set tunnel fields
to the NFP. The initial focus is on VXLAN traffic. Due to the current
state of the NFP firmware, only VXLAN traffic on well known port 4789 is
handled. The match and action fields must explicity set this value to be
supported. Tunnel end point information is also offloaded to the NFP for
both encapsulation and decapsulation. The NFP expects 3 separate data sets
to be supplied.
From: Or Gerlitz <hidden> Date: 2017-09-25 15:25:04
On Mon, Sep 25, 2017 at 1:23 PM, Simon Horman
[off-list ref] wrote:
From: Simon Horman <redacted>
John says:
This patch set allows offloading of TC flower match and set tunnel fields
to the NFP. The initial focus is on VXLAN traffic. Due to the current
state of the NFP firmware, only VXLAN traffic on well known port 4789 is
handled. The match and action fields must explicity set this value to be
supported. Tunnel end point information is also offloaded to the NFP for
both encapsulation and decapsulation. The NFP expects 3 separate data sets
to be supplied.
For decapsulation, 2 separate lists exist; a list of MAC addresses
referenced by an index comprised of the port number, and a list of IP
addresses. These IP addresses are not connected to a MAC or port.
Do these IP addresses exist on the host kernel SW stack? can the same
set of TC rules be fully functional and generate the same traffic
pattern when set to run in SW (skip_hw)?
The MAC
addresses can be written as a block or one at a time (because they have an
index, previous values can be overwritten) while the IP addresses are
always written as a list of all the available IPs. Because the MAC address
used as a tunnel end point may be associated with a physical port or may
be a virtual netdev like an OVS bridge, we do not know which addresses
should be offloaded. For this reason, all MAC addresses of active netdevs
are offloaded to the NFP. A notifier checks for changes to any currently
offloaded MACs or any new netdevs that may occur. For IP addresses, the
tunnel end point used in the rules is known as the destination IP address
must be specified in the flower classifier rule. When a new IP address
appears in a rule, the IP address is offloaded. The IP is removed from the
offloaded list when all rules matching on that IP are deleted.
For encapsulation, a next hop table is updated on the NFP that contains
the source/dest IPs, MACs and egress port. These are written individually
when requested. If the NFP tries to encapsulate a packet but does not know
the next hop, then is sends a request to the host. The host carries out a
route lookup and populates the given entry on the NFP table. A notifier
also exists to check for any links changing or going down in the kernel
next hop table. If an offloaded next hop entry is removed from the kernel
then it is also removed on the NFP.
The NFP periodically sends a message to the host telling it which tunnel
ports have packets egressing the system. The host uses this information to
update the used value in the neighbour entry. This means that, rather than
expire when it times out, the kernel will send an ARP to check if the link
is still live. From an NFP perspective, this means that valid entries will
not be removed from its next hop table.
John Hurley (7):
nfp: add helper to get flower cmsg length
nfp: compile flower vxlan tunnel metadata match fields
nfp: compile flower vxlan tunnel set actions
nfp: offload flower vxlan endpoint MAC addresses
nfp: offload vxlan IPv4 endpoints of flower rules
nfp: flower vxlan neighbour offload
nfp: flower vxlan neighbour keep-alive
drivers/net/ethernet/netronome/nfp/Makefile | 3 +-
drivers/net/ethernet/netronome/nfp/flower/action.c | 169 ++++-
drivers/net/ethernet/netronome/nfp/flower/cmsg.c | 16 +-
drivers/net/ethernet/netronome/nfp/flower/cmsg.h | 87 ++-
drivers/net/ethernet/netronome/nfp/flower/main.c | 13 +
drivers/net/ethernet/netronome/nfp/flower/main.h | 35 +
drivers/net/ethernet/netronome/nfp/flower/match.c | 75 +-
.../net/ethernet/netronome/nfp/flower/metadata.c | 2 +-
.../net/ethernet/netronome/nfp/flower/offload.c | 74 +-
.../ethernet/netronome/nfp/flower/tunnel_conf.c | 811 +++++++++++++++++++++
10 files changed, 1243 insertions(+), 42 deletions(-)
create mode 100644 drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c
--
2.1.4
From: Simon Horman <hidden> Date: 2017-09-25 17:04:56
On Mon, Sep 25, 2017 at 06:25:03PM +0300, Or Gerlitz wrote:
On Mon, Sep 25, 2017 at 1:23 PM, Simon Horman
[off-list ref] wrote:
quoted
From: Simon Horman <redacted>
John says:
This patch set allows offloading of TC flower match and set tunnel fields
to the NFP. The initial focus is on VXLAN traffic. Due to the current
state of the NFP firmware, only VXLAN traffic on well known port 4789 is
handled. The match and action fields must explicity set this value to be
supported. Tunnel end point information is also offloaded to the NFP for
both encapsulation and decapsulation. The NFP expects 3 separate data sets
to be supplied.
quoted
For decapsulation, 2 separate lists exist; a list of MAC addresses
referenced by an index comprised of the port number, and a list of IP
addresses. These IP addresses are not connected to a MAC or port.
Do these IP addresses exist on the host kernel SW stack? can the same
set of TC rules be fully functional and generate the same traffic
pattern when set to run in SW (skip_hw)?
Hi Or,
I asked John (now CCed) about this and his response was:
The MAC addresses are extracted from the netdevs already loaded in the
kernel and are monitored for any changes. The IP addresses are slightly
different in that they are extracted from the rules themselves. We make the
assumption that, if a packet is decapsulated at the end point and a match
is attempted on the IP address, that this IP address should be recognised
in the kernel. That being the case, the same traffic pattern should be
witnessed if the skip_hw flag is applied.
From: Or Gerlitz <hidden> Date: 2017-09-25 18:32:13
On Mon, Sep 25, 2017 at 1:23 PM, Simon Horman
[off-list ref] wrote:
From: John Hurley <redacted>
Periodically receive messages containing the destination IPs of tunnels
that have recently forwarded traffic. Update the neighbour entries 'used'
value for these IPs next hop.
Are you proactively sending keep alive messages from the driver or the
fw? what's wrong with the probes sent by the kernel NUD subsystem?
In our driver we also update the used value for neighs of offloaded
tunnels, we do it based on flow counters for the offloaded tunnels
which is an evidence for activity. Any reason for you not to apply a
similar practice?
Or.
On Mon, 25 Sep 2017 19:04:53 +0200, Simon Horman wrote:
The MAC addresses are extracted from the netdevs already loaded in the
kernel and are monitored for any changes. The IP addresses are slightly
different in that they are extracted from the rules themselves. We make the
assumption that, if a packet is decapsulated at the end point and a match
is attempted on the IP address,
You lost me here, I'm afraid. What do you mean by "match"?
that this IP address should be recognised
in the kernel. That being the case, the same traffic pattern should be
witnessed if the skip_hw flag is applied.
Just to be really sure that this works correctly, can you confirm that
this will match the packet:
ip link add vxlan0 type vxlan dstport 4789 dev eth0 external
ip link set dev vxlan0 up
tc qdisc add dev vxlan0 ingress
ethtool -K eth0 hw-tc-offload on
tc filter add dev vxlan0 protocol ip parent ffff: flower enc_key_id 102 \
enc_dst_port 4789 src_ip 3.4.5.6 skip_sw action [...]
while this one will NOT match:
ip link add vxlan0 type vxlan dstport 4789 dev eth0 external
ip link set dev vxlan0 up
tc qdisc add dev eth0 ingress
ethtool -K eth0 hw-tc-offload on
tc filter add dev eth0 protocol ip parent ffff: flower enc_key_id 102 \
enc_dst_port 4789 src_ip 3.4.5.6 skip_sw action [...]
We found that with mlx5, the second one actually matches, too. Which is
a very serious bug. (Adding Paolo who found this. And adding a few more
Mellanox guys to be aware of the bug.)
Jiri
From: Or Gerlitz <hidden> Date: 2017-09-26 12:41:39
On Tue, Sep 26, 2017 at 1:15 PM, Jiri Benc [off-list ref] wrote:
On Mon, 25 Sep 2017 19:04:53 +0200, Simon Horman wrote:
quoted
The MAC addresses are extracted from the netdevs already loaded in the
kernel and are monitored for any changes. The IP addresses are slightly
different in that they are extracted from the rules themselves. We make the
assumption that, if a packet is decapsulated at the end point and a match
is attempted on the IP address,
You lost me here, I'm afraid. What do you mean by "match"?
quoted
that this IP address should be recognised
in the kernel. That being the case, the same traffic pattern should be
witnessed if the skip_hw flag is applied.
Just to be really sure that this works correctly, can you confirm that
this will match the packet:
ip link add vxlan0 type vxlan dstport 4789 dev eth0 external
ip link set dev vxlan0 up
tc qdisc add dev vxlan0 ingress
ethtool -K eth0 hw-tc-offload on
tc filter add dev vxlan0 protocol ip parent ffff: flower enc_key_id 102 \
enc_dst_port 4789 src_ip 3.4.5.6 skip_sw action [...]
while this one will NOT match:
what do you exactly mean by "will not match"
ip link add vxlan0 type vxlan dstport 4789 dev eth0 external
ip link set dev vxlan0 up
tc qdisc add dev eth0 ingress
ethtool -K eth0 hw-tc-offload on
tc filter add dev eth0 protocol ip parent ffff: flower enc_key_id 102 \
enc_dst_port 4789 src_ip 3.4.5.6 skip_sw action [...]
Please note that the way the rule is being set to the HW driver is by delegation
done in flower, see these commits (specifically "Add offload support
using egress Hardware device")
a6e1693 net/sched: cls_flower: Set the filter Hardware device for all use-cases
7091d8c net/sched: cls_flower: Add offload support using egress Hardware device
255cb30 net/sched: act_mirred: Add new tc_action_ops get_dev()
Since the egress port is not HW port netdev but rather SW virtual tunnel netdev
we have some logic in the kernel to delegate the rule programming to
HW via the HW netdev
OKay? if not, please elaborate
We found that with mlx5, the second one actually matches, too. Which is
a very serious bug. (Adding Paolo who found this. And adding a few more
Mellanox guys to be aware of the bug.)
On Tue, 26 Sep 2017 15:41:37 +0300, Or Gerlitz wrote:
Please note that the way the rule is being set to the HW driver is by delegation
done in flower, see these commits (specifically "Add offload support
using egress Hardware device")
It's very well possible the bug is somewhere in net/sched.
What is the bug in your view?
If you replace skip_sw with skip_hw, the rules have to work
identically. In software, decapsulated packets appear on the vxlan0
interface, not on the eth0 interface. As the consequence, the second
example must not match on such packets. Those packets do not appear on
eth0 with software only path. eth0 sees encapsulated packets only. It's
vxlan0 that sees decapsulated packets with attached dst_metadata and
that's the only interface where the flower filter in the example can
match.
Hardware offloaded path must behave identically to the software path.
Jiri
IPv6 is not included in this set.
The reason the IPv6 bit is included here is to account for behavior we
have noticed in TC flower.
If, for example, I add a filter with the following match fields:
'protocol ip flower enc_src_ip 10.0.0.1 enc_dst_ip 10.0.0.2
enc_dst_port 4789 enc_key_id 123'
The 'used_keys' value in the dissector marks both IPv4 and IPv6 encap
addresses as 'used'.
I am not sure if this is a bug in TC or that we are expected to check
the enc_control fields to determine if IPv4 or v6 addresses are used.
Including the IPv6 used_keys bit in our whitelist approach allows us
to accept legitimate IPv4 tunnel rules in these situations.
If it is found to be IPv6 when the rule is parsed, it will be rejected here.
IPv6 is not included in this set.
The reason the IPv6 bit is included here is to account for behavior we
have noticed in TC flower.
If, for example, I add a filter with the following match fields:
'protocol ip flower enc_src_ip 10.0.0.1 enc_dst_ip 10.0.0.2
enc_dst_port 4789 enc_key_id 123'
The 'used_keys' value in the dissector marks both IPv4 and IPv6 encap
addresses as 'used'.
I am not sure if this is a bug in TC or that we are expected to check
the enc_control fields to determine if IPv4 or v6 addresses are used.
you should have your code to check enc_control->addr_type to be
FLOW_DISSECTOR_KEY_IPV4_ADDRS or IPV6_ADDRS
Including the IPv6 used_keys bit in our whitelist approach allows us
to accept legitimate IPv4 tunnel rules in these situations.
mmm can please take a look on fl_init_dissector() and tell me if you
see why FLOW_DISSECTOR_KEY_IPV6_ADDRS is set for ipv4 tunnels,
I am not sure.
If it is found to be IPv6 when the rule is parsed, it will be rejected here.
From: Or Gerlitz <hidden> Date: 2017-09-26 14:17:03
On Tue, Sep 26, 2017 at 3:51 PM, Jiri Benc [off-list ref] wrote:
On Tue, 26 Sep 2017 15:41:37 +0300, Or Gerlitz wrote:
quoted
Please note that the way the rule is being set to the HW driver is by delegation
done in flower, see these commits (specifically "Add offload support
using egress Hardware device")
It's very well possible the bug is somewhere in net/sched.
maybe before/instead you call it a bug, take a look on the design
there and maybe
tell us how to possibly do that otherwise?
On Tue, 26 Sep 2017 17:17:02 +0300, Or Gerlitz wrote:
maybe before/instead you call it a bug,
But it is a bug. When offloaded, the rules must not behave differently.
That's the fundamental thing about offloading. Here, the rules behave
differently when offloaded and when not. That's a bug.
take a look on the design there and maybe
tell us how to possibly do that otherwise?
I don't know the design. It's the responsibility of those who implement
the offloading to do it in the way that it's consistent with the
software path. That has always been the case.
This needs to be fixed. If it can't be fixed, the feature needs to be
reverted. It's not that Linux has to make use of every single offload
supported by hardware. If the offloading cannot be fit into how Linux
works, then the offload can't be supported. There are in fact many
precedents.
Jiri
From: Paolo Abeni <pabeni@redhat.com> Date: 2017-09-26 14:50:16
On Tue, 2017-09-26 at 17:17 +0300, Or Gerlitz wrote:
On Tue, Sep 26, 2017 at 3:51 PM, Jiri Benc [off-list ref] wrote:
quoted
On Tue, 26 Sep 2017 15:41:37 +0300, Or Gerlitz wrote:
quoted
Please note that the way the rule is being set to the HW driver is by delegation
done in flower, see these commits (specifically "Add offload support
using egress Hardware device")
It's very well possible the bug is somewhere in net/sched.
maybe before/instead you call it a bug, take a look on the design
there and maybe
tell us how to possibly do that otherwise?
The problem, AFAICT, is in the API between flower and NIC implementing
the offload, because in the above example the kernel will call the
offload hook with exactly the same arguments with the 'bad' rule and
the 'good' one - but the 'bad' rule should never match any packets.
I think that can be fixed changing the flower code to invoke the
offload hook for filters with tunnel-based match only if the device
specified in such match has the appropriate type, e.g. given that
currently only vxlan is supported with something like the code below
(very rough and untested, just to give the idea):
Cheers,
Paolo
---
@@ -243,10 +243,11 @@ static int fl_hw_replace_filter(struct tcf_proto *tp,structfl_flow_key*mask,structcls_fl_filter*f){-structnet_device*dev=tp->q->dev_queue->dev;+structnet_device*ingress_dev,*dev=tp->q->dev_queue->dev;structtc_cls_flower_offloadcls_flower={};interr;+ingress_dev=dev;if(!tc_can_offload(dev)){if(tcf_exts_get_dev(dev,&f->exts,&f->hw_dev)||(f->hw_dev&&!tc_can_offload(f->hw_dev))){
@@ -259,6 +260,12 @@ static int fl_hw_replace_filter(struct tcf_proto *tp,f->hw_dev=dev;}+if((dissector_uses_key(f->dissector,FLOW_DISSECTOR_KEY_ENC_KEYID)||+dissector_uses_key(f->dissector,FLOW_DISSECTOR_KEY_ENC_PORTS)||+// ... list all the others tunnel based keys ...+)&&strcmp(ingress_dev->rtnl_link_ops->kind,"vxlan"))+returntc_skip_sw(f->flags)?-EINVAL:0;+
IPv6 is not included in this set.
The reason the IPv6 bit is included here is to account for behavior we
have noticed in TC flower.
If, for example, I add a filter with the following match fields:
'protocol ip flower enc_src_ip 10.0.0.1 enc_dst_ip 10.0.0.2
enc_dst_port 4789 enc_key_id 123'
The 'used_keys' value in the dissector marks both IPv4 and IPv6 encap
addresses as 'used'.
I am not sure if this is a bug in TC or that we are expected to check
the enc_control fields to determine if IPv4 or v6 addresses are used.
you should have your code to check enc_control->addr_type to be
FLOW_DISSECTOR_KEY_IPV4_ADDRS or IPV6_ADDRS
quoted
Including the IPv6 used_keys bit in our whitelist approach allows us
to accept legitimate IPv4 tunnel rules in these situations.
mmm can please take a look on fl_init_dissector() and tell me if you
see why FLOW_DISSECTOR_KEY_IPV6_ADDRS is set for ipv4 tunnels,
I am not sure.
The fl_init_dissector uses the FL_KEY_SET_IF_MASKED macro to set an
array of keys which are then translated to the used_keys values.
The FL_KEY_SET_IF_MASKED takes a 'struct fl_flow_key' as input and
checks if any mask bits are set in a particular field - if so it
eventually marks it as used.
In struct fl_flow_key, the encap ipv4 and ipv6 addresses are
represented as a union of the 2.
Therefore, if we have masked bits set for IPv4, they are also being
set for the IPv6 field.
quoted
If it is found to be IPv6 when the rule is parsed, it will be rejected here.
IPv6 is not included in this set.
The reason the IPv6 bit is included here is to account for behavior we
have noticed in TC flower.
If, for example, I add a filter with the following match fields:
'protocol ip flower enc_src_ip 10.0.0.1 enc_dst_ip 10.0.0.2
enc_dst_port 4789 enc_key_id 123'
The 'used_keys' value in the dissector marks both IPv4 and IPv6 encap
addresses as 'used'.
I am not sure if this is a bug in TC or that we are expected to check
the enc_control fields to determine if IPv4 or v6 addresses are used.
you should have your code to check enc_control->addr_type to be
FLOW_DISSECTOR_KEY_IPV4_ADDRS or IPV6_ADDRS
quoted
Including the IPv6 used_keys bit in our whitelist approach allows us
to accept legitimate IPv4 tunnel rules in these situations.
mmm can please take a look on fl_init_dissector() and tell me if you
see why FLOW_DISSECTOR_KEY_IPV6_ADDRS is set for ipv4 tunnels,
I am not sure.
The fl_init_dissector uses the FL_KEY_SET_IF_MASKED macro to set an
array of keys which are then translated to the used_keys values.
The FL_KEY_SET_IF_MASKED takes a 'struct fl_flow_key' as input and
checks if any mask bits are set in a particular field - if so it
eventually marks it as used.
In struct fl_flow_key, the encap ipv4 and ipv6 addresses are
represented as a union of the 2.
Therefore, if we have masked bits set for IPv4, they are also being
set for the IPv6 field.
IPv6 is not included in this set.
The reason the IPv6 bit is included here is to account for behavior we
have noticed in TC flower.
If, for example, I add a filter with the following match fields:
'protocol ip flower enc_src_ip 10.0.0.1 enc_dst_ip 10.0.0.2
enc_dst_port 4789 enc_key_id 123'
The 'used_keys' value in the dissector marks both IPv4 and IPv6 encap
addresses as 'used'.
I am not sure if this is a bug in TC or that we are expected to check
the enc_control fields to determine if IPv4 or v6 addresses are used.
you should have your code to check enc_control->addr_type to be
FLOW_DISSECTOR_KEY_IPV4_ADDRS or IPV6_ADDRS
quoted
Including the IPv6 used_keys bit in our whitelist approach allows us
to accept legitimate IPv4 tunnel rules in these situations.
mmm can please take a look on fl_init_dissector() and tell me if you
see why FLOW_DISSECTOR_KEY_IPV6_ADDRS is set for ipv4 tunnels,
I am not sure.
The fl_init_dissector uses the FL_KEY_SET_IF_MASKED macro to set an
array of keys which are then translated to the used_keys values.
The FL_KEY_SET_IF_MASKED takes a 'struct fl_flow_key' as input and
checks if any mask bits are set in a particular field - if so it
eventually marks it as used.
In struct fl_flow_key, the encap ipv4 and ipv6 addresses are
represented as a union of the 2.
Therefore, if we have masked bits set for IPv4, they are also being
set for the IPv6 field.
I see, do you consider it a bug?
The code seems to insist that, if either IPv4 or IPv6 is in use then a
control encap key is also used:
if (FL_KEY_IS_MASKED(&mask->key, enc_ipv4) ||
FL_KEY_IS_MASKED(&mask->key, enc_ipv6))
FL_KEY_SET(keys, cnt, FLOW_DISSECTOR_KEY_ENC_CONTROL,
enc_control);
Therefore, I think it should be ok to use this to determine the IP
type in use by the tunnel.
From: Simon Horman <redacted>
John says:
This patch set allows offloading of TC flower match and set tunnel fields
to the NFP. The initial focus is on VXLAN traffic. Due to the current
state of the NFP firmware, only VXLAN traffic on well known port 4789 is
handled. The match and action fields must explicity set this value to be
supported. Tunnel end point information is also offloaded to the NFP for
both encapsulation and decapsulation. The NFP expects 3 separate data sets
to be supplied.
...
Series applied, thanks.
I see there is some discussion about ipv6 flow dissector key handling
and ND keepalives, but those should be addressable in follow-on changes.
Thanks.
From: Simon Horman <redacted>
John says:
This patch set allows offloading of TC flower match and set tunnel fields
to the NFP. The initial focus is on VXLAN traffic. Due to the current
state of the NFP firmware, only VXLAN traffic on well known port 4789 is
handled. The match and action fields must explicity set this value to be
supported. Tunnel end point information is also offloaded to the NFP for
both encapsulation and decapsulation. The NFP expects 3 separate data sets
to be supplied.
...
Series applied, thanks.
I see there is some discussion about ipv6 flow dissector key handling
and ND keepalives, but those should be addressable in follow-on changes.
Thanks Dave,
I'll make sure that discussion is brought to a satisfactory conclusion.
Tue, Sep 26, 2017 at 04:50:10PM CEST, pabeni@redhat.com wrote:
quoted hunk
On Tue, 2017-09-26 at 17:17 +0300, Or Gerlitz wrote:
quoted
On Tue, Sep 26, 2017 at 3:51 PM, Jiri Benc [off-list ref] wrote:
quoted
On Tue, 26 Sep 2017 15:41:37 +0300, Or Gerlitz wrote:
quoted
Please note that the way the rule is being set to the HW driver is by delegation
done in flower, see these commits (specifically "Add offload support
using egress Hardware device")
It's very well possible the bug is somewhere in net/sched.
maybe before/instead you call it a bug, take a look on the design
there and maybe
tell us how to possibly do that otherwise?
The problem, AFAICT, is in the API between flower and NIC implementing
the offload, because in the above example the kernel will call the
offload hook with exactly the same arguments with the 'bad' rule and
the 'good' one - but the 'bad' rule should never match any packets.
I think that can be fixed changing the flower code to invoke the
offload hook for filters with tunnel-based match only if the device
specified in such match has the appropriate type, e.g. given that
currently only vxlan is supported with something like the code below
(very rough and untested, just to give the idea):
Cheers,
Paolo
---