The Mfex study function is split into outer and inner to allow
for independent selection and studying of packets in outer and inner
flows to different ISA optimized Mfexs.

Signed-off-by: Kumar Amber <kumar.am...@intel.com>
---
 lib/dpif-netdev-extract-study.c | 126 +++++++++++++++++++++-----------
 1 file changed, 83 insertions(+), 43 deletions(-)

diff --git a/lib/dpif-netdev-extract-study.c b/lib/dpif-netdev-extract-study.c
index 71354cc4c..03d97c64e 100644
--- a/lib/dpif-netdev-extract-study.c
+++ b/lib/dpif-netdev-extract-study.c
@@ -30,7 +30,9 @@ static atomic_uint32_t mfex_study_pkts_count = 
MFEX_MAX_PKT_COUNT;
 /* Struct to hold miniflow study stats. */
 struct study_stats {
     uint32_t pkt_count;
+    uint32_t pkt_inner_count;
     uint32_t impl_hitcount[MFEX_IMPL_MAX];
+    uint32_t impl_inner_hitcount[MFEX_IMPL_MAX];
 };
 
 /* Define per thread data to hold the study stats. */
@@ -67,6 +69,58 @@ mfex_set_study_pkt_cnt(uint32_t pkt_cmp_count, const char 
*name)
     return -EINVAL;
 }
 
+
+static inline void
+mfex_reset_stats(uint32_t *impls_hitcount, uint32_t *pkt_cnt) {
+    /* Reset stats so that study function can be called again
+     * for next traffic type and optimal function ptr can be
+     * chosen.
+     */
+    memset(impls_hitcount, 0, sizeof(uint32_t) * MFEX_IMPL_MAX);
+    *pkt_cnt = 0;
+}
+
+static inline void
+mfex_study_select_best_impls(struct dpif_miniflow_extract_impl *mfex_funcs,
+                             uint32_t pkt_cnt, uint32_t *impls_arr,
+                             atomic_uintptr_t *pmd_func, char *name)
+{
+
+    uint32_t best_func_index = MFEX_IMPL_START_IDX;
+    uint32_t max_hits = 0;
+
+    for (int i = MFEX_IMPL_START_IDX; i < MFEX_IMPL_MAX; i++) {
+        if (impls_arr[i] > max_hits) {
+            max_hits = impls_arr[i];
+            best_func_index = i;
+            }
+        }
+
+    /* If 50% of the packets hit, enable the function. */
+    if (max_hits >= (mfex_study_pkts_count / 2)) {
+        atomic_store_relaxed(pmd_func,
+                    (uintptr_t) mfex_funcs[best_func_index].extract_func);
+        VLOG_INFO("MFEX %s study chose impl %s: (hits %u/%u pkts)",
+                  name, mfex_funcs[best_func_index].name, max_hits,
+                  pkt_cnt);
+    } else {
+        /* Set the implementation to null for default miniflow. */
+        atomic_store_relaxed(pmd_func,
+                    (uintptr_t) mfex_funcs[MFEX_IMPL_SCALAR].extract_func);
+        VLOG_INFO("Not enough packets matched (%u/%u), disabling"
+                  " optimized MFEX.", max_hits, pkt_cnt);
+    }
+
+    /* In debug mode show stats for all the counters. */
+    if (VLOG_IS_DBG_ENABLED()) {
+        for (int i = MFEX_IMPL_START_IDX; i < MFEX_IMPL_MAX; i++) {
+                VLOG_DBG("MFEX study results for implementation %s:"
+                         " (hits %u/%u pkts)", mfex_funcs[i].name,
+                         impls_arr[i], pkt_cnt);
+        }
+    }
+}
+
 uint32_t
 mfex_study_traffic(struct dp_packet_batch *packets,
                    struct netdev_flow_key *keys,
@@ -76,10 +130,12 @@ mfex_study_traffic(struct dp_packet_batch *packets,
 {
     uint32_t hitmask = 0;
     uint32_t mask = 0;
+    uint32_t study_cnt_pkts;
     struct dp_netdev_pmd_thread *pmd = pmd_handle;
     struct dpif_miniflow_extract_impl *miniflow_funcs;
     struct study_stats *stats = mfex_study_get_study_stats_ptr();
     miniflow_funcs = dpif_mfex_impl_info_get();
+    atomic_read_relaxed(&mfex_study_pkts_count, &study_cnt_pkts);
 
     /* Run traffic optimized miniflow_extract to collect the hitmask
      * to be compared after certain packets have been hit to choose
@@ -93,7 +149,11 @@ mfex_study_traffic(struct dp_packet_batch *packets,
         hitmask = miniflow_funcs[i].extract_func(packets, keys, keys_size,
                                                  in_port, pmd_handle,
                                                  md_is_valid);
-        stats->impl_hitcount[i] += count_1bits(hitmask);
+        if (!md_is_valid) {
+            stats->impl_hitcount[i] += count_1bits(hitmask);
+        } else {
+            stats->impl_inner_hitcount[i] += count_1bits(hitmask);
+        }
 
         /* If traffic is not classified then we dont overwrite the keys
          * array in minfiflow implementations so its safe to create a
@@ -102,54 +162,34 @@ mfex_study_traffic(struct dp_packet_batch *packets,
         mask |= hitmask;
     }
 
-    stats->pkt_count += dp_packet_batch_size(packets);
-
     /* Choose the best implementation after a minimum packets have been
      * processed.
      */
-    uint32_t study_cnt_pkts;
-    atomic_read_relaxed(&mfex_study_pkts_count, &study_cnt_pkts);
-
-    if (stats->pkt_count >= study_cnt_pkts) {
-        uint32_t best_func_index = MFEX_IMPL_START_IDX;
-        uint32_t max_hits = 0;
-        for (int i = MFEX_IMPL_START_IDX; i < MFEX_IMPL_MAX; i++) {
-            if (stats->impl_hitcount[i] > max_hits) {
-                max_hits = stats->impl_hitcount[i];
-                best_func_index = i;
-            }
+    if (!md_is_valid) {
+        stats->pkt_count += dp_packet_batch_size(packets);
+
+        if (stats->pkt_count >= study_cnt_pkts) {
+            char name[] = "outer";
+            mfex_study_select_best_impls(miniflow_funcs, stats->pkt_count,
+                             stats->impl_hitcount,
+                             (void *)&pmd->miniflow_extract_opt,
+                             name);
+            mfex_reset_stats(stats->impl_hitcount, &stats->pkt_count);
         }
 
-        /* If 50% of the packets hit, enable the function. */
-        if (max_hits >= (mfex_study_pkts_count / 2)) {
-            atomic_store_relaxed(&pmd->miniflow_extract_opt,
-                                 miniflow_funcs[best_func_index].extract_func);
-            VLOG_INFO("MFEX study chose impl %s: (hits %u/%u pkts)",
-                      miniflow_funcs[best_func_index].name, max_hits,
-                      stats->pkt_count);
-        } else {
-            /* Set the implementation to null for default miniflow. */
-            atomic_store_relaxed(&pmd->miniflow_extract_opt,
-                    miniflow_funcs[MFEX_IMPL_SCALAR].extract_func);
-            VLOG_INFO("Not enough packets matched (%u/%u), disabling"
-                      " optimized MFEX.", max_hits, stats->pkt_count);
+    } else {
+        stats->pkt_inner_count += dp_packet_batch_size(packets);
+
+        if (stats->pkt_inner_count >= study_cnt_pkts) {
+            char name[] = "inner";
+            mfex_study_select_best_impls(miniflow_funcs,
+                             stats->pkt_inner_count,
+                             stats->impl_inner_hitcount,
+                             (void *)&pmd->miniflow_extract_inner_opt,
+                             name);
+            mfex_reset_stats(stats->impl_inner_hitcount,
+                             &stats->pkt_inner_count);
         }
-
-        /* In debug mode show stats for all the counters. */
-        if (VLOG_IS_DBG_ENABLED()) {
-
-            for (int i = MFEX_IMPL_START_IDX; i < MFEX_IMPL_MAX; i++) {
-                VLOG_DBG("MFEX study results for implementation %s:"
-                         " (hits %u/%u pkts)", miniflow_funcs[i].name,
-                         stats->impl_hitcount[i], stats->pkt_count);
-            }
-        }
-
-        /* Reset stats so that study function can be called again
-         * for next traffic type and optimal function ptr can be
-         * chosen.
-         */
-        memset(stats, 0, sizeof(struct study_stats));
     }
     return mask;
 }
-- 
2.25.1

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

Reply via email to