diff mbox

[ovs-dev,08/11] ovs/dp-cls: tag lookup and processing

Message ID 9c7fbb81d6e493dcfed5a81991f0a32c14a042c3.1499257385.git.shacharbe@mellanox.com
State Deferred
Headers show

Commit Message

Shachar Beiser July 5, 2017, 12:27 p.m. UTC
PMD fetch the flow according to the flow tag .

Signed-off-by: Shachar Beiser <shacharbe@mellanox.com>

Conflicts:
	lib/dpif-netdev.c
	lib/hw-pipeline.c
---
 lib/dpif-netdev.c |  58 +++++++++++++++++++++------
 lib/hw-pipeline.c | 115 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 160 insertions(+), 13 deletions(-)
diff mbox

Patch

diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c
index 1776339..2bd3b89 100644
--- a/lib/dpif-netdev.c
+++ b/lib/dpif-netdev.c
@@ -1580,8 +1580,8 @@  dp_netdev_pmd_remove_flow(struct dp_netdev_pmd_thread *pmd,
 {
     struct cmap_node *node = CONST_CAST(struct cmap_node *, &flow->node);
     struct dpcls *cls;
-    odp_port_t in_port = flow->flow.in_port.odp_port;
 
+    odp_port_t in_port = flow->flow.in_port.odp_port;
     cls = dp_netdev_pmd_lookup_dpcls(pmd, in_port);
     ovs_assert(cls != NULL);
     if (pmd->dp->ppl_md.id == HW_OFFLOAD_PIPELINE &&
@@ -1589,8 +1589,7 @@  dp_netdev_pmd_remove_flow(struct dp_netdev_pmd_thread *pmd,
         VLOG_INFO("hw_pipeline_dpcls_remove");
         hw_pipeline_dpcls_remove(pmd->dp,&flow->cr);
     }
-    else
-    {
+    else {
         VLOG_INFO("skip hw_pipeline_dpcls_remove");
     }
     dpcls_remove(cls, &flow->cr);
@@ -4397,8 +4396,11 @@  static inline size_t
 emc_processing(struct dp_netdev_pmd_thread *pmd,
                struct dp_packet_batch *packets_,
                struct netdev_flow_key *keys,
-               struct packet_batch_per_flow batches[], size_t *n_batches,
-               bool md_is_valid, odp_port_t port_no)
+               struct packet_batch_per_flow batches[],
+               size_t *n_batches,
+               bool md_is_valid,
+               odp_port_t port_no,
+               struct pipeline_md *md_tags)
 {
     struct emc_cache *flow_cache = &pmd->flow_cache;
     struct netdev_flow_key *key = &keys[0];
@@ -4413,6 +4415,13 @@  emc_processing(struct dp_netdev_pmd_thread *pmd,
     DP_PACKET_BATCH_REFILL_FOR_EACH (i, size, packet, packets_) {
         struct dp_netdev_flow *flow;
 
+    if (md_tags[i].id == HW_OFFLOAD_PIPELINE &&
+           md_tags[i].flow_tag != HW_NO_FREE_FLOW_TAG) {
+            VLOG_INFO("skip emc_processing  flow_tag %x\n ",
+                    md_tags[i].flow_tag);
+            continue;
+        }
+
         if (OVS_UNLIKELY(dp_packet_size(packet) < ETH_HEADER_LEN)) {
             dp_packet_delete(packet);
             n_dropped++;
@@ -4530,7 +4539,7 @@  fast_path_processing(struct dp_netdev_pmd_thread *pmd,
                      struct netdev_flow_key *keys,
                      struct packet_batch_per_flow batches[], size_t *n_batches,
                      odp_port_t in_port,
-                     long long now)
+                     long long now,struct pipeline_md *md_tags)
 {
     int cnt = packets_->count;
 #if !defined(__CHECKER__) && !defined(_WIN32)
@@ -4555,7 +4564,14 @@  fast_path_processing(struct dp_netdev_pmd_thread *pmd,
     /* Get the classifier for the in_port */
     cls = dp_netdev_pmd_lookup_dpcls(pmd, in_port);
     if (OVS_LIKELY(cls)) {
-        any_miss = !dpcls_lookup(cls, keys, rules, cnt, &lookup_cnt);
+        if (pmd->dp->ppl_md.id == DEFAULT_SW_PIPELINE) {
+            any_miss = !dpcls_lookup(cls, keys, rules, cnt, &lookup_cnt);
+        }
+        else {
+             memset(rules, 0, sizeof(rules));
+             any_miss = !hw_pipeline_dpcls_lookup(pmd->dp,md_tags,cnt,
+                    &lookup_cnt);
+        }
     } else {
         any_miss = true;
         memset(rules, 0, sizeof(rules));
@@ -4577,8 +4593,18 @@  fast_path_processing(struct dp_netdev_pmd_thread *pmd,
             /* It's possible that an earlier slow path execution installed
              * a rule covering this flow.  In this case, it's a lot cheaper
              * to catch it here than execute a miss. */
-            netdev_flow = dp_netdev_pmd_lookup_flow(pmd, &keys[i],
-                                                    &add_lookup_cnt);
+
+            if (pmd->dp->ppl_md.id == DEFAULT_SW_PIPELINE) {
+                VLOG_INFO("dp_netdev_pmd_lookup_flow \n");
+                netdev_flow = dp_netdev_pmd_lookup_flow(pmd,&keys[i],
+                        &add_lookup_cnt);
+            }
+            else {
+                VLOG_INFO("hw_pipeline_lookup_flow \n");
+                netdev_flow = hw_pipeline_lookup_flow(pmd->dp,
+                                md_tags[i].flow_tag,&add_lookup_cnt);
+            }
+
             if (netdev_flow) {
                 lookup_cnt += add_lookup_cnt;
                 rules[i] = &netdev_flow->cr;
@@ -4645,18 +4671,26 @@  dp_netdev_input__(struct dp_netdev_pmd_thread *pmd,
     OVS_ALIGNED_VAR(CACHE_LINE_SIZE)
         struct netdev_flow_key keys[PKT_ARRAY_SIZE];
     struct packet_batch_per_flow batches[PKT_ARRAY_SIZE];
+    struct pipeline_md md_tags[PKT_ARRAY_SIZE];
     long long now = time_msec();
     size_t n_batches;
     odp_port_t in_port;
+    int index=0;
 
     n_batches = 0;
+
+    for (index=0;index<cnt;index++) {
+        md_tags[index].id = DEFAULT_SW_PIPELINE;
+        md_tags[index].flow_tag = HW_NO_FREE_FLOW_TAG;
+    }
+
     emc_processing(pmd, packets, keys, batches, &n_batches,
-                            md_is_valid, port_no);
+                            md_is_valid, port_no,md_tags);
     if (!dp_packet_batch_is_empty(packets)) {
         /* Get ingress port from first packet's metadata. */
         in_port = packets->packets[0]->md.in_port.odp_port;
-        fast_path_processing(pmd, packets, keys, batches, &n_batches,
-                             in_port, now);
+        fast_path_processing(pmd, packets, keys, batches, &n_batches, in_port,
+                now,md_tags);
     }
 
     /* All the flow batches need to be reset before any call to
diff --git a/lib/hw-pipeline.c b/lib/hw-pipeline.c
index 0acaa9c..9d608c3 100644
--- a/lib/hw-pipeline.c
+++ b/lib/hw-pipeline.c
@@ -36,6 +36,8 @@ 
 
 VLOG_DEFINE_THIS_MODULE(hw_pipeline);
 
+static struct dp_netdev_flow *hw_pipeline_read_flow(flow_tag_pool *p,
+                                                    uint32_t flow_tag);
 static int hw_pipeline_send_insert_flow(struct dp_netdev *dp,
                                         odp_port_t in_port,
                                         struct dp_netdev_flow *flow,
@@ -53,6 +55,10 @@  bool hw_pipeline_ft_pool_is_valid(flow_tag_pool *p);
 
 uint32_t hw_pipeline_ft_pool_init(flow_tag_pool *p,uint32_t pool_size);
 uint32_t hw_pipeline_ft_pool_uninit(flow_tag_pool *p);
+
+struct dp_netdev_flow *hw_pipeline_ft_pool_read_flow(flow_tag_pool *p,
+                                                     uint32_t handle);
+
 // Internal functions Message Queue
 
 static int hw_pipeline_msg_queue_init(msg_queue *message_queue,
@@ -87,6 +93,50 @@  bool hw_pipeline_ft_pool_is_valid(flow_tag_pool *p)
     return false;
 }
 
+flow_elem *hw_pipeline_ft_pool_read_elem(struct dp_netdev *dp,
+                                         uint32_t handle)
+{
+    uint32_t index;
+    flow_elem *elem;
+
+    if (OVS_UNLIKELY(dp == NULL)) {
+        VLOG_ERR("no dp pointer \n");
+        return NULL;
+    }
+
+    index = OVS_FLOW_TAG_INDEX_GET(handle);
+    if (OVS_UNLIKELY(index >= HW_MAX_FLOW_TAG)) {
+        VLOG_ERR("index out of range\n");
+        return NULL;
+    }
+
+    rte_spinlock_lock(&dp->ft_pool.lock);
+    elem = &dp->ft_pool.ft_data[index];
+    rte_spinlock_unlock(&dp->ft_pool.lock);
+
+    return elem;
+}
+
+
+inline struct dp_netdev_flow *hw_pipeline_ft_pool_read_flow(flow_tag_pool *p,
+                                                            uint32_t handle)
+{
+    uint32_t index;
+    struct dp_netdev_flow *flow=NULL;
+    index = OVS_FLOW_TAG_INDEX_GET(handle);
+    if (OVS_UNLIKELY(index >= HW_MAX_FLOW_TAG)) {
+        VLOG_ERR("index out of range\n");
+        return NULL;
+    }
+
+    rte_spinlock_lock(&p->lock);
+    p->ft_data[index].valid =true;
+    flow = p->ft_data[index].sw_flow;
+    rte_spinlock_unlock(&p->lock);
+
+    return flow;
+}
+
 uint32_t hw_pipeline_ft_pool_init(flow_tag_pool *p,
                                   uint32_t pool_size)
 {
@@ -343,10 +393,23 @@  static bool hw_pipeline_msg_queue_enqueue(msg_queue *message_queue,
         }
         return false;
     }
-
     return true;
 }
 
+static struct dp_netdev_flow *hw_pipeline_read_flow(flow_tag_pool *p,
+        uint32_t handle)
+{
+    struct dp_netdev_flow *netdev_flow=NULL;
+    netdev_flow = hw_pipeline_ft_pool_read_flow(p,handle);
+    if (OVS_UNLIKELY(netdev_flow == NULL)) {
+        VLOG_INFO("No flow found");
+        return NULL;
+    }
+    VLOG_INFO("flow found with tag %x\n",netdev_flow->cr.flow_tag);
+    VLOG_INFO("flow found with handle %x\n",handle);
+    return netdev_flow;
+}
+
 static int hw_pipeline_send_insert_flow(struct dp_netdev *dp,
         odp_port_t in_port, struct dp_netdev_flow *flow, struct flow *masks,
         int rxqid)
@@ -438,6 +501,34 @@  static int hw_pipeline_send_remove_flow(struct dp_netdev *dp,uint32_t flow_tag,
     return 0;
 }
 
+bool hw_pipeline_dpcls_lookup(struct dp_netdev *dp,
+                              struct pipeline_md *md_tags,
+                              const size_t cnt,
+                              int *lookup_cnt)
+{
+    int index =0 ;
+    struct dp_netdev_flow *netdev_flow = NULL;
+    bool all_found = true;
+    bool never_lookup = true;
+
+    for (index=0;index<cnt;index++) {
+        if (md_tags[index].flow_tag == HW_NO_FREE_FLOW_TAG) {
+            continue;
+        }
+        never_lookup = false;
+        netdev_flow = hw_pipeline_lookup_flow(dp,
+            md_tags[index].flow_tag,lookup_cnt);
+        if (netdev_flow == NULL) {
+            VLOG_INFO("flow== NULL && miss_any=true");
+            all_found=false;
+        }
+    }
+    if (never_lookup) {
+        return false;
+    }
+    return all_found;
+}
+
 /* Insert 'rule' into 'cls'.
  * Get a unique tag from pool
  * The function sends a message to the message queue
@@ -491,3 +582,25 @@  hw_pipeline_dpcls_remove(struct dp_netdev *dp,
       }
     }
 }
+
+struct dp_netdev_flow *
+hw_pipeline_lookup_flow(struct dp_netdev *dp,
+                        uint32_t flow_tag,
+                        int *lookup_cnt)
+{
+    struct dp_netdev_flow *netdev_flow=NULL;
+    if (OVS_UNLIKELY(flow_tag == HW_NO_FREE_FLOW_TAG)) {
+        return NULL;
+    }
+    netdev_flow = hw_pipeline_read_flow(&dp->ft_pool,flow_tag);
+    if (netdev_flow != NULL) {
+        if (lookup_cnt != NULL) {
+            *lookup_cnt=+1;
+        }
+    }
+    else {
+        VLOG_ERR("No flow found : netdev_flow %p for flow_tag %x",
+                 netdev_flow,flow_tag);
+    }
+    return netdev_flow;
+}