This patch moves the hardware packet miss recovery API from the
netdev-offload to the dpif-offload provider. The API name has been
changed from hw_miss_packet_recover() to hw_miss_packet_postprocess()
to reflect that it may also be used for other tasks in the future,
such as conntrack post-processing.

Signed-off-by: Eelco Chaudron <[email protected]>
---
 lib/dpif-netdev.c             | 18 +++++++++++-------
 lib/dpif-offload-dpdk.c       | 10 ++++++++++
 lib/dpif-offload-provider.h   | 12 ++++++++++++
 lib/dpif-offload.c            | 36 +++++++++++++++++++++++++++++++++++
 lib/dpif-offload.h            |  2 ++
 lib/netdev-offload-dpdk.c     |  3 +--
 lib/netdev-offload-dpdk.h     |  2 ++
 lib/netdev-offload-provider.h |  6 ------
 lib/netdev-offload.c          | 33 +++-----------------------------
 lib/netdev-offload.h          |  4 ++--
 lib/netdev.c                  |  2 +-
 11 files changed, 80 insertions(+), 48 deletions(-)

diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c
index 82df85823..5d32a47b3 100644
--- a/lib/dpif-netdev.c
+++ b/lib/dpif-netdev.c
@@ -122,7 +122,7 @@ COVERAGE_DEFINE(datapath_drop_invalid_bond);
 COVERAGE_DEFINE(datapath_drop_invalid_tnl_port);
 COVERAGE_DEFINE(datapath_drop_rx_invalid_packet);
 #ifdef ALLOW_EXPERIMENTAL_API /* Packet restoration API required. */
-COVERAGE_DEFINE(datapath_drop_hw_miss_recover);
+COVERAGE_DEFINE(datapath_drop_hw_miss_postprocess);
 #endif
 
 /* Protects against changes to 'dp_netdevs'. */
@@ -8423,14 +8423,18 @@ dp_netdev_hw_flow(const struct dp_netdev_pmd_thread 
*pmd,
 #ifdef ALLOW_EXPERIMENTAL_API /* Packet restoration API required. */
     /* Restore the packet if HW processing was terminated before completion. */
     struct dp_netdev_rxq *rxq = pmd->ctx.last_rxq;
-    bool miss_api_supported;
+    bool postprocess_api_supported;
+
+    atomic_read_relaxed(&rxq->port->netdev->hw_info.postprocess_api_supported,
+                        &postprocess_api_supported);
+    if (postprocess_api_supported) {
+        int err = dpif_offload_netdev_hw_miss_packet_postprocess(
+            rxq->port->netdev, packet);
 
-    atomic_read_relaxed(&rxq->port->netdev->hw_info.miss_api_supported,
-                        &miss_api_supported);
-    if (miss_api_supported) {
-        int err = netdev_hw_miss_packet_recover(rxq->port->netdev, packet);
         if (err && err != EOPNOTSUPP) {
-            COVERAGE_INC(datapath_drop_hw_miss_recover);
+            if (err != ECANCELED) {
+                COVERAGE_INC(datapath_drop_hw_miss_postprocess);
+            }
             return -1;
         }
     }
diff --git a/lib/dpif-offload-dpdk.c b/lib/dpif-offload-dpdk.c
index 76a8946c9..c8ae1adb2 100644
--- a/lib/dpif-offload-dpdk.c
+++ b/lib/dpif-offload-dpdk.c
@@ -286,6 +286,14 @@ dpif_offload_dpdk_netdev_flow_flush(const struct 
dpif_offload *offload
     return netdev_offload_dpdk_flow_flush(netdev);
 }
 
+static int
+dpif_offload_dpdk_netdev_hw_miss_packet_postprocess(
+    const struct dpif_offload *offload_ OVS_UNUSED, struct netdev *netdev,
+    struct dp_packet *packet)
+{
+    return netdev_offload_dpdk_hw_miss_packet_recover(netdev, packet);
+}
+
 struct dpif_offload_class dpif_offload_dpdk_class = {
     .type = "dpdk",
     .supported_dpif_types = (const char *const[]) {
@@ -300,6 +308,8 @@ struct dpif_offload_class dpif_offload_dpdk_class = {
     .port_del = dpif_offload_dpdk_port_del,
     .flow_get_n_offloaded = dpif_offload_dpdk_get_n_offloaded,
     .netdev_flow_flush = dpif_offload_dpdk_netdev_flow_flush,
+    .netdev_hw_miss_packet_postprocess = \
+        dpif_offload_dpdk_netdev_hw_miss_packet_postprocess,
 };
 
 /* XXX: Temporary functions below, which will be removed once fully
diff --git a/lib/dpif-offload-provider.h b/lib/dpif-offload-provider.h
index 60d6c5321..78cf5d7fa 100644
--- a/lib/dpif-offload-provider.h
+++ b/lib/dpif-offload-provider.h
@@ -168,6 +168,18 @@ struct dpif_offload_class {
     /* Deletes all offloaded flows on this netdev.  Return 0 if successful,
      * otherwise returns a positive errno value. */
     int (*netdev_flow_flush)(const struct dpif_offload *, struct netdev *);
+
+    /* Recover and/or set the packet state (contents and metadata) for
+     * continued processing in software, and perform any additional
+     * post-processing required by the offload provider.
+     *
+     * Return 0 if successful and the packet requires further processing;
+     * otherwise, return a positive errno value and take ownership of the
+     * packet if errno != EOPNOTSUPP.  Return ECANCELED if the packet was
+     * fully consumed by the provider for non-error conditions. */
+    int (*netdev_hw_miss_packet_postprocess)(const struct dpif_offload *,
+                                             struct netdev *,
+                                             struct dp_packet *);
 };
 
 
diff --git a/lib/dpif-offload.c b/lib/dpif-offload.c
index 99cfe2aac..8ac0f8f96 100644
--- a/lib/dpif-offload.c
+++ b/lib/dpif-offload.c
@@ -846,6 +846,42 @@ dpif_offload_netdev_flush_flows(struct netdev *netdev)
     return EOPNOTSUPP;
 }
 
+int
+dpif_offload_netdev_hw_miss_packet_postprocess(struct netdev *netdev,
+                                               struct dp_packet *packet)
+{
+    const struct dpif_offload *offload;
+    bool postprocess_api_supported;
+    int rc;
+
+    atomic_read_relaxed(&netdev->hw_info.postprocess_api_supported,
+                        &postprocess_api_supported);
+    if (!postprocess_api_supported) {
+        return EOPNOTSUPP;
+    }
+
+    offload = ovsrcu_get(const struct dpif_offload *, &netdev->dpif_offload);
+
+    if (!offload || !offload->class->netdev_hw_miss_packet_postprocess) {
+        if (offload) {
+            /* Offload is configured and API unsupported by the port;
+             * avoid subsequent calls. */
+            atomic_store_relaxed(&netdev->hw_info.postprocess_api_supported,
+                                 false);
+        }
+        return EOPNOTSUPP;
+    }
+
+    rc = offload->class->netdev_hw_miss_packet_postprocess(offload, netdev,
+                                                           packet);
+    if (rc == EOPNOTSUPP) {
+        /* API unsupported by the port; avoid subsequent calls. */
+        atomic_store_relaxed(&netdev->hw_info.postprocess_api_supported,
+                             false);
+    }
+    return rc;
+}
+
 
 struct dpif_offload_port_mgr *
 dpif_offload_port_mgr_init(void)
diff --git a/lib/dpif-offload.h b/lib/dpif-offload.h
index fb7edf269..fe73b278d 100644
--- a/lib/dpif-offload.h
+++ b/lib/dpif-offload.h
@@ -75,5 +75,7 @@ void dpif_offload_meter_del(const struct dpif *dpif, 
ofproto_meter_id meter_id,
 
 /* Netdev specific function, which can be used in the fast path. */
 int dpif_offload_netdev_flush_flows(struct netdev *);
+int dpif_offload_netdev_hw_miss_packet_postprocess(struct netdev *,
+                                                   struct dp_packet *);
 
 #endif /* DPIF_OFFLOAD_H */
diff --git a/lib/netdev-offload-dpdk.c b/lib/netdev-offload-dpdk.c
index d1781d8e4..c3d5e83f5 100644
--- a/lib/netdev-offload-dpdk.c
+++ b/lib/netdev-offload-dpdk.c
@@ -2685,7 +2685,7 @@ get_vport_netdev(const char *dpif_type,
     return aux.vport;
 }
 
-static int
+int
 netdev_offload_dpdk_hw_miss_packet_recover(struct netdev *netdev,
                                            struct dp_packet *packet)
 {
@@ -2803,5 +2803,4 @@ const struct netdev_flow_api netdev_offload_dpdk = {
     .init_flow_api = netdev_offload_dpdk_init_flow_api,
     .uninit_flow_api = netdev_offload_dpdk_uninit_flow_api,
     .flow_get = netdev_offload_dpdk_flow_get,
-    .hw_miss_packet_recover = netdev_offload_dpdk_hw_miss_packet_recover,
 };
diff --git a/lib/netdev-offload-dpdk.h b/lib/netdev-offload-dpdk.h
index d5061b40c..475822e1b 100644
--- a/lib/netdev-offload-dpdk.h
+++ b/lib/netdev-offload-dpdk.h
@@ -24,5 +24,7 @@ struct netdev;
  * associated dpif offload provider. */
 int netdev_offload_dpdk_flow_flush(struct netdev *);
 uint64_t netdev_offload_dpdk_flow_get_n_offloaded(struct netdev *);
+int netdev_offload_dpdk_hw_miss_packet_recover(struct netdev *,
+                                               struct dp_packet *);
 
 #endif /* NETDEV_OFFLOAD_DPDK_H */
diff --git a/lib/netdev-offload-provider.h b/lib/netdev-offload-provider.h
index 898df8333..f762af19a 100644
--- a/lib/netdev-offload-provider.h
+++ b/lib/netdev-offload-provider.h
@@ -80,12 +80,6 @@ struct netdev_flow_api {
     int (*flow_del)(struct netdev *, const ovs_u128 *ufid,
                     struct dpif_flow_stats *);
 
-    /* Recover the packet state (contents and data) for continued processing
-     * in software.
-     * Return 0 if successful, otherwise returns a positive errno value and
-     * takes ownership of a packet if errno != EOPNOTSUPP. */
-    int (*hw_miss_packet_recover)(struct netdev *, struct dp_packet *);
-
     /* Initializies the netdev flow api.
      * Return 0 if successful, otherwise returns a positive errno value. */
     int (*init_flow_api)(struct netdev *);
diff --git a/lib/netdev-offload.c b/lib/netdev-offload.c
index 0c4209290..be5787f4d 100644
--- a/lib/netdev-offload.c
+++ b/lib/netdev-offload.c
@@ -186,7 +186,8 @@ netdev_assign_flow_api(struct netdev *netdev)
     CMAP_FOR_EACH (rfa, cmap_node, &netdev_flow_apis) {
         if (!rfa->flow_api->init_flow_api(netdev)) {
             ovs_refcount_ref(&rfa->refcnt);
-            atomic_store_relaxed(&netdev->hw_info.miss_api_supported, true);
+            atomic_store_relaxed(&netdev->hw_info.postprocess_api_supported,
+                                 true);
             ovsrcu_set(&netdev->flow_api, rfa->flow_api);
             VLOG_INFO("%s: Assigned flow API '%s'.",
                       netdev_get_name(netdev), rfa->flow_api->type);
@@ -195,7 +196,7 @@ netdev_assign_flow_api(struct netdev *netdev)
         VLOG_DBG("%s: flow API '%s' is not suitable.",
                  netdev_get_name(netdev), rfa->flow_api->type);
     }
-    atomic_store_relaxed(&netdev->hw_info.miss_api_supported, false);
+    atomic_store_relaxed(&netdev->hw_info.postprocess_api_supported, false);
     VLOG_INFO("%s: No suitable flow API found.", netdev_get_name(netdev));
 
     return -1;
@@ -254,34 +255,6 @@ netdev_flow_put(struct netdev *netdev, struct match *match,
            : EOPNOTSUPP;
 }
 
-int
-netdev_hw_miss_packet_recover(struct netdev *netdev,
-                              struct dp_packet *packet)
-{
-    const struct netdev_flow_api *flow_api;
-    bool miss_api_supported;
-    int rv;
-
-    atomic_read_relaxed(&netdev->hw_info.miss_api_supported,
-                        &miss_api_supported);
-    if (!miss_api_supported) {
-        return EOPNOTSUPP;
-    }
-
-    flow_api = ovsrcu_get(const struct netdev_flow_api *, &netdev->flow_api);
-    if (!flow_api || !flow_api->hw_miss_packet_recover) {
-        return EOPNOTSUPP;
-    }
-
-    rv = flow_api->hw_miss_packet_recover(netdev, packet);
-    if (rv == EOPNOTSUPP) {
-        /* API unsupported by the port; avoid subsequent calls. */
-        atomic_store_relaxed(&netdev->hw_info.miss_api_supported, false);
-    }
-
-    return rv;
-}
-
 int
 netdev_flow_get(struct netdev *netdev, struct match *match,
                 struct nlattr **actions, const ovs_u128 *ufid,
diff --git a/lib/netdev-offload.h b/lib/netdev-offload.h
index 2b32179ec..6006396b9 100644
--- a/lib/netdev-offload.h
+++ b/lib/netdev-offload.h
@@ -47,7 +47,8 @@ struct ovs_action_push_tnl;
 /* Offload-capable (HW) netdev information */
 struct netdev_hw_info {
     bool oor;                         /* Out of Offload Resources ? */
-    atomic_bool miss_api_supported;   /* hw_miss_packet_recover() supported.*/
+    /* Is hw_miss_packet_postprocess() supported.*/
+    atomic_bool postprocess_api_supported;
     int offload_count;                /* Offloaded flow count */
     int pending_count;                /* Pending (non-offloaded) flow count */
     OVSRCU_TYPE(void *) offload_data; /* Offload metadata. */
@@ -110,7 +111,6 @@ bool netdev_flow_dump_next(struct netdev_flow_dump *, 
struct match *,
 int netdev_flow_put(struct netdev *, struct match *, struct nlattr *actions,
                     size_t actions_len, const ovs_u128 *,
                     struct offload_info *, struct dpif_flow_stats *);
-int netdev_hw_miss_packet_recover(struct netdev *, struct dp_packet *);
 int netdev_flow_get(struct netdev *, struct match *, struct nlattr **actions,
                     const ovs_u128 *, struct dpif_flow_stats *,
                     struct dpif_flow_attrs *, struct ofpbuf *wbuffer);
diff --git a/lib/netdev.c b/lib/netdev.c
index 6a05e9a7e..13f3d707e 100644
--- a/lib/netdev.c
+++ b/lib/netdev.c
@@ -435,7 +435,7 @@ netdev_open(const char *name, const char *type, struct 
netdev **netdevp)
                     seq_read(netdev->reconfigure_seq);
                 ovsrcu_set(&netdev->flow_api, NULL);
                 netdev->hw_info.oor = false;
-                atomic_init(&netdev->hw_info.miss_api_supported, false);
+                atomic_init(&netdev->hw_info.postprocess_api_supported, false);
                 netdev->node = shash_add(&netdev_shash, name, netdev);
 
                 /* By default enable one tx and rx queue per netdev. */
-- 
2.50.1

_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to