If ports are bonded, the same rule with the same cookie may be offloaded
to multiple ports. Modify the rule lookup function to optionally include
an ingress netdev and a host context along with the cookie value when
searching for a rule. When a new rule is passed to the driver, the netdev
the rule is to be attached to is considered when searching for dublicates.
Conversely, when a stats update is received from the NFP card, the host
context is used alongside the cookie to map to the correct host rule.

Signed-off-by: John Hurley <john.hur...@netronome.com>
---
 drivers/net/ethernet/netronome/nfp/flower/main.h   |  8 ++++--
 .../net/ethernet/netronome/nfp/flower/metadata.c   | 20 +++++++++------
 .../net/ethernet/netronome/nfp/flower/offload.c    | 29 ++++++++++++++++------
 3 files changed, 40 insertions(+), 17 deletions(-)

diff --git a/drivers/net/ethernet/netronome/nfp/flower/main.h 
b/drivers/net/ethernet/netronome/nfp/flower/main.h
index 5fd7c1f..2c48e10 100644
--- a/drivers/net/ethernet/netronome/nfp/flower/main.h
+++ b/drivers/net/ethernet/netronome/nfp/flower/main.h
@@ -47,6 +47,7 @@
 struct net_device;
 struct nfp_app;
 
+#define NFP_FL_STATS_CTX_DONT_CARE     cpu_to_be32(0xffffffff)
 #define NFP_FL_STATS_ENTRY_RS          BIT(20)
 #define NFP_FL_STATS_ELEM_RS           4
 #define NFP_FL_REPEATED_HASH_MAX       BIT(17)
@@ -166,6 +167,7 @@ struct nfp_fl_payload {
        spinlock_t lock; /* lock stats */
        struct nfp_fl_stats stats;
        __be32 nfp_tun_ipv4_addr;
+       struct net_device *ingress_dev;
        char *unmasked_data;
        char *mask_data;
        char *action_data;
@@ -193,12 +195,14 @@ int nfp_flower_compile_action(struct 
tc_cls_flower_offload *flow,
                              struct nfp_fl_payload *nfp_flow);
 int nfp_compile_flow_metadata(struct nfp_app *app,
                              struct tc_cls_flower_offload *flow,
-                             struct nfp_fl_payload *nfp_flow);
+                             struct nfp_fl_payload *nfp_flow,
+                             struct net_device *netdev);
 int nfp_modify_flow_metadata(struct nfp_app *app,
                             struct nfp_fl_payload *nfp_flow);
 
 struct nfp_fl_payload *
-nfp_flower_search_fl_table(struct nfp_app *app, unsigned long 
tc_flower_cookie);
+nfp_flower_search_fl_table(struct nfp_app *app, unsigned long tc_flower_cookie,
+                          struct net_device *netdev, __be32 host_ctx);
 struct nfp_fl_payload *
 nfp_flower_remove_fl_table(struct nfp_app *app, unsigned long 
tc_flower_cookie);
 
diff --git a/drivers/net/ethernet/netronome/nfp/flower/metadata.c 
b/drivers/net/ethernet/netronome/nfp/flower/metadata.c
index db977cf..21668aa 100644
--- a/drivers/net/ethernet/netronome/nfp/flower/metadata.c
+++ b/drivers/net/ethernet/netronome/nfp/flower/metadata.c
@@ -99,14 +99,18 @@ static int nfp_get_stats_entry(struct nfp_app *app, u32 
*stats_context_id)
 
 /* Must be called with either RTNL or rcu_read_lock */
 struct nfp_fl_payload *
-nfp_flower_search_fl_table(struct nfp_app *app, unsigned long tc_flower_cookie)
+nfp_flower_search_fl_table(struct nfp_app *app, unsigned long tc_flower_cookie,
+                          struct net_device *netdev, __be32 host_ctx)
 {
        struct nfp_flower_priv *priv = app->priv;
        struct nfp_fl_payload *flower_entry;
 
        hash_for_each_possible_rcu(priv->flow_table, flower_entry, link,
                                   tc_flower_cookie)
-               if (flower_entry->tc_flower_cookie == tc_flower_cookie)
+               if (flower_entry->tc_flower_cookie == tc_flower_cookie &&
+                   (!netdev || flower_entry->ingress_dev == netdev) &&
+                   (host_ctx == NFP_FL_STATS_CTX_DONT_CARE ||
+                    flower_entry->meta.host_ctx_id == host_ctx))
                        return flower_entry;
 
        return NULL;
@@ -121,13 +125,11 @@ nfp_flower_update_stats(struct nfp_app *app, struct 
nfp_fl_stats_frame *stats)
        flower_cookie = be64_to_cpu(stats->stats_cookie);
 
        rcu_read_lock();
-       nfp_flow = nfp_flower_search_fl_table(app, flower_cookie);
+       nfp_flow = nfp_flower_search_fl_table(app, flower_cookie, NULL,
+                                             stats->stats_con_id);
        if (!nfp_flow)
                goto exit_rcu_unlock;
 
-       if (nfp_flow->meta.host_ctx_id != stats->stats_con_id)
-               goto exit_rcu_unlock;
-
        spin_lock(&nfp_flow->lock);
        nfp_flow->stats.pkts += be32_to_cpu(stats->pkt_count);
        nfp_flow->stats.bytes += be64_to_cpu(stats->byte_count);
@@ -317,7 +319,8 @@ nfp_check_mask_remove(struct nfp_app *app, char *mask_data, 
u32 mask_len,
 
 int nfp_compile_flow_metadata(struct nfp_app *app,
                              struct tc_cls_flower_offload *flow,
-                             struct nfp_fl_payload *nfp_flow)
+                             struct nfp_fl_payload *nfp_flow,
+                             struct net_device *netdev)
 {
        struct nfp_flower_priv *priv = app->priv;
        struct nfp_fl_payload *check_entry;
@@ -348,7 +351,8 @@ int nfp_compile_flow_metadata(struct nfp_app *app,
        nfp_flow->stats.bytes = 0;
        nfp_flow->stats.used = jiffies;
 
-       check_entry = nfp_flower_search_fl_table(app, flow->cookie);
+       check_entry = nfp_flower_search_fl_table(app, flow->cookie, netdev,
+                                                NFP_FL_STATS_CTX_DONT_CARE);
        if (check_entry) {
                if (nfp_release_stats_entry(app, stats_cxt))
                        return -EINVAL;
diff --git a/drivers/net/ethernet/netronome/nfp/flower/offload.c 
b/drivers/net/ethernet/netronome/nfp/flower/offload.c
index eb8abeb..3b554ff 100644
--- a/drivers/net/ethernet/netronome/nfp/flower/offload.c
+++ b/drivers/net/ethernet/netronome/nfp/flower/offload.c
@@ -404,6 +404,9 @@ nfp_flower_add_offload(struct nfp_app *app, struct 
net_device *netdev,
                goto err_free_key_ls;
        }
 
+       if (!egress)
+               flow_pay->ingress_dev = netdev;
+
        err = nfp_flower_compile_flow_match(flow, key_layer, netdev, flow_pay,
                                            tun_type);
        if (err)
@@ -413,7 +416,8 @@ nfp_flower_add_offload(struct nfp_app *app, struct 
net_device *netdev,
        if (err)
                goto err_destroy_flow;
 
-       err = nfp_compile_flow_metadata(app, flow, flow_pay);
+       err = nfp_compile_flow_metadata(app, flow, flow_pay,
+                                       flow_pay->ingress_dev);
        if (err)
                goto err_destroy_flow;
 
@@ -455,13 +459,18 @@ nfp_flower_add_offload(struct nfp_app *app, struct 
net_device *netdev,
  */
 static int
 nfp_flower_del_offload(struct nfp_app *app, struct net_device *netdev,
-                      struct tc_cls_flower_offload *flow)
+                      struct tc_cls_flower_offload *flow, bool egress)
 {
        struct nfp_port *port = nfp_port_from_netdev(netdev);
+       struct net_device *ingr_dev = NULL;
        struct nfp_fl_payload *nfp_flow;
        int err;
 
-       nfp_flow = nfp_flower_search_fl_table(app, flow->cookie);
+       if (!egress)
+               ingr_dev = netdev;
+
+       nfp_flow = nfp_flower_search_fl_table(app, flow->cookie, ingr_dev,
+                                             NFP_FL_STATS_CTX_DONT_CARE);
        if (!nfp_flow)
                return -ENOENT;
 
@@ -498,11 +507,17 @@ nfp_flower_del_offload(struct nfp_app *app, struct 
net_device *netdev,
  * Return: negative value on error, 0 if stats populated successfully.
  */
 static int
-nfp_flower_get_stats(struct nfp_app *app, struct tc_cls_flower_offload *flow)
+nfp_flower_get_stats(struct nfp_app *app, struct net_device *netdev,
+                    struct tc_cls_flower_offload *flow, bool egress)
 {
+       struct net_device *ingr_dev = NULL;
        struct nfp_fl_payload *nfp_flow;
 
-       nfp_flow = nfp_flower_search_fl_table(app, flow->cookie);
+       if (!egress)
+               ingr_dev = netdev;
+
+       nfp_flow = nfp_flower_search_fl_table(app, flow->cookie, ingr_dev,
+                                             NFP_FL_STATS_CTX_DONT_CARE);
        if (!nfp_flow)
                return -EINVAL;
 
@@ -528,9 +543,9 @@ nfp_flower_repr_offload(struct nfp_app *app, struct 
net_device *netdev,
        case TC_CLSFLOWER_REPLACE:
                return nfp_flower_add_offload(app, netdev, flower, egress);
        case TC_CLSFLOWER_DESTROY:
-               return nfp_flower_del_offload(app, netdev, flower);
+               return nfp_flower_del_offload(app, netdev, flower, egress);
        case TC_CLSFLOWER_STATS:
-               return nfp_flower_get_stats(app, flower);
+               return nfp_flower_get_stats(app, netdev, flower, egress);
        }
 
        return -EOPNOTSUPP;
-- 
2.7.4

Reply via email to