dpif: Index flows using unique identifiers.
[cascardo/ovs.git] / lib / dpif-netdev.c
index 5233130..fb3a774 100644 (file)
@@ -304,6 +304,7 @@ struct dp_netdev_flow {
 
     /* Hash table index by unmasked flow. */
     const struct cmap_node node; /* In owning dp_netdev's 'flow_table'. */
+    const ovs_u128 ufid;         /* Unique flow identifier. */
     const struct flow flow;      /* Unmasked flow that created this entry. */
 
     /* Number of references.
@@ -327,6 +328,8 @@ struct dp_netdev_flow {
 
 static void dp_netdev_flow_unref(struct dp_netdev_flow *);
 static bool dp_netdev_flow_ref(struct dp_netdev_flow *);
+static int dpif_netdev_flow_from_nlattrs(const struct nlattr *, uint32_t,
+                                         struct flow *);
 
 /* Contained by struct dp_netdev_flow's 'stats' member.  */
 struct dp_netdev_flow_stats {
@@ -1156,6 +1159,12 @@ static void dp_netdev_flow_unref(struct dp_netdev_flow *flow)
     }
 }
 
+static uint32_t
+dp_netdev_flow_hash(const ovs_u128 *ufid)
+{
+    return ufid->u32[0];
+}
+
 static void
 dp_netdev_remove_flow(struct dp_netdev *dp, struct dp_netdev_flow *flow)
     OVS_REQUIRES(dp->flow_mutex)
@@ -1163,7 +1172,7 @@ dp_netdev_remove_flow(struct dp_netdev *dp, struct dp_netdev_flow *flow)
     struct cmap_node *node = CONST_CAST(struct cmap_node *, &flow->node);
 
     dpcls_remove(&dp->cls, &flow->cr);
-    cmap_remove(&dp->flow_table, node, flow_hash(&flow->flow, 0));
+    cmap_remove(&dp->flow_table, node, dp_netdev_flow_hash(&flow->ufid));
     flow->dead = true;
 
     dp_netdev_flow_unref(flow);
@@ -1531,14 +1540,26 @@ dp_netdev_lookup_flow(const struct dp_netdev *dp,
 }
 
 static struct dp_netdev_flow *
-dp_netdev_find_flow(const struct dp_netdev *dp, const struct flow *flow)
+dp_netdev_find_flow(const struct dp_netdev *dp, const ovs_u128 *ufidp,
+                    const struct nlattr *key, size_t key_len)
 {
     struct dp_netdev_flow *netdev_flow;
+    struct flow flow;
+    ovs_u128 ufid;
+
+    /* If a UFID is not provided, determine one based on the key. */
+    if (!ufidp && key && key_len
+        && !dpif_netdev_flow_from_nlattrs(key, key_len, &flow)) {
+        dpif_flow_hash(dp->dpif, &flow, sizeof flow, &ufid);
+        ufidp = &ufid;
+    }
 
-    CMAP_FOR_EACH_WITH_HASH (netdev_flow, node, flow_hash(flow, 0),
-                             &dp->flow_table) {
-        if (flow_equal(&netdev_flow->flow, flow)) {
-            return netdev_flow;
+    if (ufidp) {
+        CMAP_FOR_EACH_WITH_HASH (netdev_flow, node, dp_netdev_flow_hash(ufidp),
+                                 &dp->flow_table) {
+            if (ovs_u128_equal(&netdev_flow->ufid, ufidp)) {
+                return netdev_flow;
+            }
         }
     }
 
@@ -1568,8 +1589,7 @@ get_dpif_flow_stats(const struct dp_netdev_flow *netdev_flow,
  * 'mask_buf'. Actions will be returned without copying, by relying on RCU to
  * protect them. */
 static void
-dp_netdev_flow_to_dpif_flow(const struct dpif *dpif,
-                            const struct dp_netdev_flow *netdev_flow,
+dp_netdev_flow_to_dpif_flow(const struct dp_netdev_flow *netdev_flow,
                             struct ofpbuf *key_buf, struct ofpbuf *mask_buf,
                             struct dpif_flow *flow)
 {
@@ -1599,8 +1619,8 @@ dp_netdev_flow_to_dpif_flow(const struct dpif *dpif,
     flow->actions = actions->actions;
     flow->actions_len = actions->size;
 
-    dpif_flow_hash(dpif, &netdev_flow->flow, sizeof netdev_flow->flow,
-                   &flow->ufid);
+    flow->ufid = netdev_flow->ufid;
+    flow->ufid_present = true;
     get_dpif_flow_stats(netdev_flow, &flow->stats);
 }
 
@@ -1701,20 +1721,13 @@ dpif_netdev_flow_get(const struct dpif *dpif, const struct dpif_flow_get *get)
 {
     struct dp_netdev *dp = get_dp_netdev(dpif);
     struct dp_netdev_flow *netdev_flow;
-    struct flow key;
-    int error;
-
-    error = dpif_netdev_flow_from_nlattrs(get->key, get->key_len, &key);
-    if (error) {
-        return error;
-    }
-
-    netdev_flow = dp_netdev_find_flow(dp, &key);
+    int error = 0;
 
+    netdev_flow = dp_netdev_find_flow(dp, get->ufid, get->key, get->key_len);
     if (netdev_flow) {
-        dp_netdev_flow_to_dpif_flow(dpif, netdev_flow, get->buffer,
-                                    get->buffer, get->flow);
-     } else {
+        dp_netdev_flow_to_dpif_flow(netdev_flow, get->buffer, get->buffer,
+                                    get->flow);
+    } else {
         error = ENOENT;
     }
 
@@ -1723,6 +1736,7 @@ dpif_netdev_flow_get(const struct dpif *dpif, const struct dpif_flow_get *get)
 
 static struct dp_netdev_flow *
 dp_netdev_flow_add(struct dp_netdev *dp, struct match *match,
+                   const ovs_u128 *ufid,
                    const struct nlattr *actions, size_t actions_len)
     OVS_REQUIRES(dp->flow_mutex)
 {
@@ -1737,13 +1751,14 @@ dp_netdev_flow_add(struct dp_netdev *dp, struct match *match,
     flow = xmalloc(sizeof *flow - sizeof flow->cr.flow.mf + mask.len);
     flow->dead = false;
     *CONST_CAST(struct flow *, &flow->flow) = match->flow;
+    *CONST_CAST(ovs_u128 *, &flow->ufid) = *ufid;
     ovs_refcount_init(&flow->ref_cnt);
     ovsthread_stats_init(&flow->stats);
     ovsrcu_set(&flow->actions, dp_netdev_actions_create(actions, actions_len));
 
     cmap_insert(&dp->flow_table,
                 CONST_CAST(struct cmap_node *, &flow->node),
-                flow_hash(&flow->flow, 0));
+                dp_netdev_flow_hash(&flow->ufid));
     netdev_flow_key_init_masked(&flow->cr.flow, &match->flow, &mask);
     dpcls_insert(&dp->cls, &flow->cr, &mask);
 
@@ -1755,6 +1770,8 @@ dp_netdev_flow_add(struct dp_netdev *dp, struct match *match,
         miniflow_expand(&flow->cr.mask->mf, &match.wc.masks);
 
         ds_put_cstr(&ds, "flow_add: ");
+        odp_format_ufid(ufid, &ds);
+        ds_put_cstr(&ds, " ");
         match_format(&match, &ds, OFP_DEFAULT_PRIORITY);
         ds_put_cstr(&ds, ", actions:");
         format_odp_actions(&ds, actions, actions_len);
@@ -1790,6 +1807,7 @@ dpif_netdev_flow_put(struct dpif *dpif, const struct dpif_flow_put *put)
     struct dp_netdev_flow *netdev_flow;
     struct netdev_flow_key key;
     struct match match;
+    ovs_u128 ufid;
     int error;
 
     error = dpif_netdev_flow_from_nlattrs(put->key, put->key_len, &match.flow);
@@ -1808,6 +1826,12 @@ dpif_netdev_flow_put(struct dpif *dpif, const struct dpif_flow_put *put)
      * for upcall processing any more. */
     netdev_flow_key_from_flow(&key, &match.flow);
 
+    if (put->ufid) {
+        ufid = *put->ufid;
+    } else {
+        dpif_flow_hash(dpif, &match.flow, sizeof match.flow, &ufid);
+    }
+
     ovs_mutex_lock(&dp->flow_mutex);
     netdev_flow = dp_netdev_lookup_flow(dp, &key);
     if (!netdev_flow) {
@@ -1816,7 +1840,8 @@ dpif_netdev_flow_put(struct dpif *dpif, const struct dpif_flow_put *put)
                 if (put->stats) {
                     memset(put->stats, 0, sizeof *put->stats);
                 }
-                dp_netdev_flow_add(dp, &match, put->actions, put->actions_len);
+                dp_netdev_flow_add(dp, &match, &ufid, put->actions,
+                                   put->actions_len);
                 error = 0;
             } else {
                 error = EFBIG;
@@ -1861,16 +1886,10 @@ dpif_netdev_flow_del(struct dpif *dpif, const struct dpif_flow_del *del)
 {
     struct dp_netdev *dp = get_dp_netdev(dpif);
     struct dp_netdev_flow *netdev_flow;
-    struct flow key;
-    int error;
-
-    error = dpif_netdev_flow_from_nlattrs(del->key, del->key_len, &key);
-    if (error) {
-        return error;
-    }
+    int error = 0;
 
     ovs_mutex_lock(&dp->flow_mutex);
-    netdev_flow = dp_netdev_find_flow(dp, &key);
+    netdev_flow = dp_netdev_find_flow(dp, del->ufid, del->key, del->key_len);
     if (netdev_flow) {
         if (del->stats) {
             get_dpif_flow_stats(netdev_flow, del->stats);
@@ -1994,7 +2013,7 @@ dpif_netdev_flow_dump_next(struct dpif_flow_dump_thread *thread_,
 
         ofpbuf_use_stack(&key, keybuf, sizeof *keybuf);
         ofpbuf_use_stack(&mask, maskbuf, sizeof *maskbuf);
-        dp_netdev_flow_to_dpif_flow(&dpif->dpif, netdev_flow, &key, &mask, f);
+        dp_netdev_flow_to_dpif_flow(netdev_flow, &key, &mask, f);
     }
 
     return n_flows;
@@ -2900,7 +2919,7 @@ fast_path_processing(struct dp_netdev_pmd_thread *pmd,
                 ovs_mutex_lock(&dp->flow_mutex);
                 netdev_flow = dp_netdev_lookup_flow(dp, &keys[i]);
                 if (OVS_LIKELY(!netdev_flow)) {
-                    netdev_flow = dp_netdev_flow_add(dp, &match,
+                    netdev_flow = dp_netdev_flow_add(dp, &match, &ufid,
                                                      ofpbuf_data(add_actions),
                                                      ofpbuf_size(add_actions));
                 }