Previously, TC block tunnel decap rules were only offloaded when a
callback was triggered through registration of the rules egress device.
This meant that the driver had no access to the ingress netdev and so
could not verify it was the same tunnel type that the rule implied.

Register tunnel devices for indirect TC block offloads in NFP, giving
access to new rules based on the ingress device rather than egress. Use
this to verify the netdev type of VXLAN and Geneve based rules and offload
the rules to HW if applicable.

Tunnel registration is done via a netdev notifier. On notifier
registration, this is triggered for already existing netdevs. This means
that NFP can register for offloads from devices that exist before it is
loaded (filter rules will be replayed from the TC core).

Signed-off-by: John Hurley <john.hur...@netronome.com>
Reviewed-by: Jakub Kicinski <jakub.kicin...@netronome.com>
---
 drivers/net/ethernet/netronome/nfp/flower/action.c      | 15 ---------------
 drivers/net/ethernet/netronome/nfp/flower/cmsg.h        | 13 +++++++++++++
 drivers/net/ethernet/netronome/nfp/flower/offload.c     | 11 +++++++----
 drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c |  9 ++++++++-
 4 files changed, 28 insertions(+), 20 deletions(-)

diff --git a/drivers/net/ethernet/netronome/nfp/flower/action.c 
b/drivers/net/ethernet/netronome/nfp/flower/action.c
index 04349c7..1260825 100644
--- a/drivers/net/ethernet/netronome/nfp/flower/action.c
+++ b/drivers/net/ethernet/netronome/nfp/flower/action.c
@@ -91,21 +91,6 @@ nfp_fl_pre_lag(struct nfp_app *app, const struct tc_action 
*action,
        return act_size;
 }
 
-static bool nfp_fl_netdev_is_tunnel_type(struct net_device *out_dev,
-                                        enum nfp_flower_tun_type tun_type)
-{
-       if (!out_dev->rtnl_link_ops)
-               return false;
-
-       if (!strcmp(out_dev->rtnl_link_ops->kind, "vxlan"))
-               return tun_type == NFP_FL_TUNNEL_VXLAN;
-
-       if (!strcmp(out_dev->rtnl_link_ops->kind, "geneve"))
-               return tun_type == NFP_FL_TUNNEL_GENEVE;
-
-       return false;
-}
-
 static int
 nfp_fl_output(struct nfp_app *app, struct nfp_fl_output *output,
              const struct tc_action *action, struct nfp_fl_payload *nfp_flow,
diff --git a/drivers/net/ethernet/netronome/nfp/flower/cmsg.h 
b/drivers/net/ethernet/netronome/nfp/flower/cmsg.h
index 29d673a..06e2888 100644
--- a/drivers/net/ethernet/netronome/nfp/flower/cmsg.h
+++ b/drivers/net/ethernet/netronome/nfp/flower/cmsg.h
@@ -8,6 +8,7 @@
 #include <linux/skbuff.h>
 #include <linux/types.h>
 #include <net/geneve.h>
+#include <net/vxlan.h>
 
 #include "../nfp_app.h"
 #include "../nfpcore/nfp_cpp.h"
@@ -475,6 +476,18 @@ static inline int nfp_flower_cmsg_get_data_len(struct 
sk_buff *skb)
        return skb->len - NFP_FLOWER_CMSG_HLEN;
 }
 
+static inline bool
+nfp_fl_netdev_is_tunnel_type(struct net_device *dev,
+                            enum nfp_flower_tun_type tun_type)
+{
+       if (netif_is_vxlan(dev))
+               return tun_type == NFP_FL_TUNNEL_VXLAN;
+       if (netif_is_geneve(dev))
+               return tun_type == NFP_FL_TUNNEL_GENEVE;
+
+       return false;
+}
+
 struct sk_buff *
 nfp_flower_cmsg_mac_repr_start(struct nfp_app *app, unsigned int num_ports);
 void
diff --git a/drivers/net/ethernet/netronome/nfp/flower/offload.c 
b/drivers/net/ethernet/netronome/nfp/flower/offload.c
index f701b2e..1dc6044 100644
--- a/drivers/net/ethernet/netronome/nfp/flower/offload.c
+++ b/drivers/net/ethernet/netronome/nfp/flower/offload.c
@@ -128,6 +128,7 @@ nfp_flower_calc_opt_layer(struct 
flow_dissector_key_enc_opts *enc_opts,
 
 static int
 nfp_flower_calculate_key_layers(struct nfp_app *app,
+                               struct net_device *netdev,
                                struct nfp_fl_key_ls *ret_key_ls,
                                struct tc_cls_flower_offload *flow,
                                bool egress,
@@ -186,8 +187,6 @@ nfp_flower_calculate_key_layers(struct nfp_app *app,
                        skb_flow_dissector_target(flow->dissector,
                                                  
FLOW_DISSECTOR_KEY_ENC_CONTROL,
                                                  flow->key);
-               if (!egress)
-                       return -EOPNOTSUPP;
 
                if (mask_enc_ctl->addr_type != 0xffff ||
                    enc_ctl->addr_type != FLOW_DISSECTOR_KEY_IPV4_ADDRS)
@@ -250,6 +249,10 @@ nfp_flower_calculate_key_layers(struct nfp_app *app,
                default:
                        return -EOPNOTSUPP;
                }
+
+               /* Ensure the ingress netdev matches the expected tun type. */
+               if (!nfp_fl_netdev_is_tunnel_type(netdev, *tun_type))
+                       return -EOPNOTSUPP;
        } else if (egress) {
                /* Reject non tunnel matches offloaded to egress repr. */
                return -EOPNOTSUPP;
@@ -451,8 +454,8 @@ nfp_flower_add_offload(struct nfp_app *app, struct 
net_device *netdev,
        if (!key_layer)
                return -ENOMEM;
 
-       err = nfp_flower_calculate_key_layers(app, key_layer, flow, egress,
-                                             &tun_type);
+       err = nfp_flower_calculate_key_layers(app, netdev, key_layer, flow,
+                                             egress, &tun_type);
        if (err)
                goto err_free_key_ls;
 
diff --git a/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c 
b/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c
index 170f314..f138f00 100644
--- a/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c
+++ b/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c
@@ -4,7 +4,6 @@
 #include <linux/etherdevice.h>
 #include <linux/inetdevice.h>
 #include <net/netevent.h>
-#include <net/vxlan.h>
 #include <linux/idr.h>
 #include <net/dst_metadata.h>
 #include <net/arp.h>
@@ -670,6 +669,10 @@ static int nfp_tun_mac_event_handler(struct notifier_block 
*nb,
                /* 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);
+
+               if (event == NETDEV_UNREGISTER &&
+                   nfp_tun_is_netdev_to_offload(netdev))
+                       nfp_flower_unregister_indr_block(netdev);
        } else if (event == NETDEV_UP || event == NETDEV_CHANGEADDR ||
                   event == NETDEV_REGISTER) {
                app_priv = container_of(nb, struct nfp_flower_priv,
@@ -681,6 +684,10 @@ static int nfp_tun_mac_event_handler(struct notifier_block 
*nb,
 
                /* Force a list write to keep NFP up to date. */
                nfp_tunnel_write_macs(app);
+
+               if (event == NETDEV_REGISTER &&
+                   nfp_tun_is_netdev_to_offload(netdev))
+                       nfp_flower_register_indr_block(app, netdev);
        }
        return NOTIFY_OK;
 }
-- 
2.7.4

Reply via email to