From: Kumar Amber <kumar.am...@intel.com>

This patch adds support for selecting the recirculation
implementation based on the DPIF implementation.

Signed-off-by: Kumar Amber <kumar.am...@intel.com>
Signed-off-by: Cian Ferriter <cian.ferri...@intel.com>
Co-authored-by: Cian Ferriter <cian.ferri...@intel.com>
Acked-by: Sunil Pai G <sunil.pa...@intel.com>
---
 lib/dpif-netdev-private-dpif.c   | 73 +++++++++++++++++++++++---------
 lib/dpif-netdev-private-dpif.h   | 18 ++++++++
 lib/dpif-netdev-private-thread.h |  3 ++
 lib/dpif-netdev.c                | 14 +++++-
 4 files changed, 88 insertions(+), 20 deletions(-)

diff --git a/lib/dpif-netdev-private-dpif.c b/lib/dpif-netdev-private-dpif.c
index 07039b1c2..3c7218ca0 100644
--- a/lib/dpif-netdev-private-dpif.c
+++ b/lib/dpif-netdev-private-dpif.c
@@ -55,18 +55,39 @@ dp_netdev_input_avx512_probe(void)
 static struct dpif_netdev_impl_info_t dpif_impls[] = {
     /* The default scalar C code implementation. */
     [DPIF_NETDEV_IMPL_SCALAR] = { .input_func = dp_netdev_input,
+      .recirc_func = dp_netdev_recirculate,
       .probe = NULL,
       .name = "dpif_scalar", },
 
 #if DPIF_NETDEV_IMPL_AVX512_CHECK
     /* Only available on x86_64 bit builds with SSE 4.2 used for OVS core. */
     [DPIF_NETDEV_IMPL_AVX512] = { .input_func = dp_netdev_input_avx512,
+      .recirc_func = dp_netdev_input_avx512_recirc,
       .probe = dp_netdev_input_avx512_probe,
       .name = "dpif_avx512", },
 #endif
 };
 
 static dp_netdev_input_func default_dpif_func;
+static dp_netdev_recirc_func default_dpif_recirc_func;
+
+static inline int
+dp_netdev_dpif_probe(int dpif_idx)
+{
+/* Configure-time overriding to run test suite on all implementations. */
+#if DPIF_NETDEV_IMPL_AVX512_CHECK
+#ifdef DPIF_AVX512_DEFAULT
+    dp_netdev_input_func_probe probe;
+
+    /* Check if the compiled default is compatible. */
+    probe = dpif_impls[DPIF_NETDEV_IMPL_AVX512].probe;
+    if (!probe || !probe()) {
+         dpif_idx = DPIF_NETDEV_IMPL_AVX512;
+    }
+#endif
+#endif
+    return dpif_idx;
+}
 
 dp_netdev_input_func
 dp_netdev_impl_get_default(void)
@@ -76,18 +97,7 @@ dp_netdev_impl_get_default(void)
     if (!default_dpif_func) {
         int dpif_idx = DPIF_NETDEV_IMPL_SCALAR;
 
-/* Configure-time overriding to run test suite on all implementations. */
-#if DPIF_NETDEV_IMPL_AVX512_CHECK
-#ifdef DPIF_AVX512_DEFAULT
-        dp_netdev_input_func_probe probe;
-
-        /* Check if the compiled default is compatible. */
-        probe = dpif_impls[DPIF_NETDEV_IMPL_AVX512].probe;
-        if (!probe || !probe()) {
-            dpif_idx = DPIF_NETDEV_IMPL_AVX512;
-        }
-#endif
-#endif
+        dpif_idx = dp_netdev_dpif_probe(dpif_idx);
 
         VLOG_INFO("Default DPIF implementation is %s.\n",
                   dpif_impls[dpif_idx].name);
@@ -97,6 +107,24 @@ dp_netdev_impl_get_default(void)
     return default_dpif_func;
 }
 
+dp_netdev_recirc_func
+dp_netdev_recirc_impl_get_default(void)
+{
+    /* For the first call, this will be NULL. Compute the compile time default.
+     */
+    if (!default_dpif_recirc_func) {
+        int dpif_idx = DPIF_NETDEV_IMPL_SCALAR;
+
+        dpif_idx = dp_netdev_dpif_probe(dpif_idx);
+
+        VLOG_INFO("Default re-circulate DPIF implementation is %s.\n",
+                  dpif_impls[dpif_idx].name);
+        default_dpif_recirc_func = dpif_impls[dpif_idx].recirc_func;
+    }
+
+    return default_dpif_recirc_func;
+}
+
 void
 dp_netdev_impl_get(struct ds *reply, struct dp_netdev_pmd_thread **pmd_list,
                    size_t n)
@@ -132,10 +160,12 @@ dp_netdev_impl_get(struct ds *reply, struct 
dp_netdev_pmd_thread **pmd_list,
  * returns the function pointer to the one requested by "name".
  */
 static int32_t
-dp_netdev_impl_get_by_name(const char *name, dp_netdev_input_func *out_func)
+dp_netdev_impl_get_by_name(const char *name, dp_netdev_input_func *dpif_func,
+                           dp_netdev_recirc_func *dpif_recirc_func)
 {
     ovs_assert(name);
-    ovs_assert(out_func);
+    ovs_assert(dpif_func);
+    ovs_assert(dpif_recirc_func);
 
     uint32_t i;
 
@@ -145,11 +175,13 @@ dp_netdev_impl_get_by_name(const char *name, 
dp_netdev_input_func *out_func)
             if (dpif_impls[i].probe) {
                 int probe_err = dpif_impls[i].probe();
                 if (probe_err) {
-                    *out_func = NULL;
+                    *dpif_func = NULL;
+                    *dpif_recirc_func = NULL;
                     return probe_err;
                 }
             }
-            *out_func = dpif_impls[i].input_func;
+            *dpif_func = dpif_impls[i].input_func;
+            *dpif_recirc_func = dpif_impls[i].recirc_func;
             return 0;
         }
     }
@@ -160,12 +192,15 @@ dp_netdev_impl_get_by_name(const char *name, 
dp_netdev_input_func *out_func)
 int32_t
 dp_netdev_impl_set_default_by_name(const char *name)
 {
-    dp_netdev_input_func new_default;
+    dp_netdev_input_func new_dpif_default;
+    dp_netdev_recirc_func new_dpif_recirc_default;
 
-    int32_t err = dp_netdev_impl_get_by_name(name, &new_default);
+    int32_t err = dp_netdev_impl_get_by_name(name, &new_dpif_default,
+                                             &new_dpif_recirc_default);
 
     if (!err) {
-        default_dpif_func = new_default;
+        default_dpif_func = new_dpif_default;
+        default_dpif_recirc_func = new_dpif_recirc_default;
     }
 
     return err;
diff --git a/lib/dpif-netdev-private-dpif.h b/lib/dpif-netdev-private-dpif.h
index 4465d034f..dd4fedec3 100644
--- a/lib/dpif-netdev-private-dpif.h
+++ b/lib/dpif-netdev-private-dpif.h
@@ -36,6 +36,16 @@ typedef int32_t (*dp_netdev_input_func)(struct 
dp_netdev_pmd_thread *pmd,
                                         struct dp_packet_batch *packets,
                                         odp_port_t port_no);
 
+/* Typedef for DPIF re-circulate functions.
+ * The implementation on success must handle the whole batch of packets.
+ * The implementation on failure must return the error code and also
+ * the batch of packets must be unchnaged. After failure, scalar dpif
+ * is called and is expected to handle packet processing thereafter.
+ * Returns 0 on sucess else returns error code on failure.
+ */
+typedef int32_t (*dp_netdev_recirc_func)(struct dp_netdev_pmd_thread *pmd,
+                                         struct dp_packet_batch *packets);
+
 /* Probe a DPIF implementation. This allows the implementation to validate CPU
  * ISA availability. Returns -ENOTSUP if not available, returns 0 if valid to
  * use.
@@ -46,6 +56,10 @@ typedef int32_t (*dp_netdev_input_func_probe)(void);
 struct dpif_netdev_impl_info_t {
     /* Function pointer to execute to have this DPIF implementation run. */
     dp_netdev_input_func input_func;
+
+    /* Function pointer to execute recirc DPIF implementation. */
+    dp_netdev_recirc_func recirc_func;
+
     /* Function pointer to execute to check the CPU ISA is available to run. If
      * not necessary, it must be set to NULL which implies that it is always
      * valid to use. */
@@ -63,6 +77,10 @@ dp_netdev_impl_get(struct ds *reply, struct 
dp_netdev_pmd_thread **pmd_list,
  * overridden at runtime. */
 dp_netdev_input_func dp_netdev_impl_get_default(void);
 
+/* Returns the default recirculate DPIF which is first ./configure selected,
+ * but can be overridden at runtime. */
+dp_netdev_recirc_func dp_netdev_recirc_impl_get_default(void);
+
 /* Overrides the default DPIF with the user set DPIF. */
 int32_t dp_netdev_impl_set_default_by_name(const char *name);
 
diff --git a/lib/dpif-netdev-private-thread.h b/lib/dpif-netdev-private-thread.h
index 4472b199d..bce91358b 100644
--- a/lib/dpif-netdev-private-thread.h
+++ b/lib/dpif-netdev-private-thread.h
@@ -124,6 +124,9 @@ struct dp_netdev_pmd_thread {
     /* Function pointer to call for dp_netdev_input() functionality. */
     ATOMIC(dp_netdev_input_func) netdev_input_func;
 
+    /* Function pointer to call for dp_netdev_recirculate() functionality. */
+    ATOMIC(dp_netdev_recirc_func) netdev_input_recirc_func;
+
     /* Pointer for per-DPIF implementation scratch space. */
     void *netdev_input_func_userdata;
 
diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c
index a50571dc8..99102c5a0 100644
--- a/lib/dpif-netdev.c
+++ b/lib/dpif-netdev.c
@@ -1148,6 +1148,10 @@ dpif_netdev_impl_set(struct unixctl_conn *conn, int argc 
OVS_UNUSED,
              * default. */
             atomic_store_relaxed(&pmd->netdev_input_func,
                                  dp_netdev_impl_get_default());
+            /* Initialize recirc DPIF function pointer to the newly configured
+             * default. */
+            atomic_store_relaxed(&pmd->netdev_input_recirc_func,
+                                 dp_netdev_recirc_impl_get_default());
         };
 
         free(pmd_list);
@@ -7473,6 +7477,11 @@ dp_netdev_configure_pmd(struct dp_netdev_pmd_thread 
*pmd, struct dp_netdev *dp,
     /* Initialize DPIF function pointer to the default configured version. */
     atomic_init(&pmd->netdev_input_func, dp_netdev_impl_get_default());
 
+    /* Initialize recirculate DPIF function pointer to the default configured
+     * version. */
+    atomic_init(&pmd->netdev_input_recirc_func,
+                                        dp_netdev_recirc_impl_get_default());
+
     /* Init default miniflow_extract function */
     atomic_init(&pmd->miniflow_extract_opt, dp_mfex_impl_get_default());
 
@@ -8818,7 +8827,10 @@ dp_execute_cb(void *aux_, struct dp_packet_batch 
*packets_,
                 }
 
                 (*depth)++;
-                dp_netdev_recirculate(pmd, packets_);
+                int ret = pmd->netdev_input_recirc_func(pmd, packets_);
+                if (ret != 0) {
+                    dp_netdev_recirculate(pmd, packets_);
+                }
                 (*depth)--;
                 return;
             }
-- 
2.25.1

_______________________________________________
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to