[ovs-dev] [PATCHv10 ovs 11/15] dpif: Generate flow_hash for revalidators in dpif.

Joe Stringer joestringer at nicira.com
Thu Nov 13 19:17:51 UTC 2014


This patch shifts the responsibility for determining the hash for a flow
from the revalidation logic down to the dpif layer. This assists in
handling backward-compatibility for revalidation with the upcoming
unique identifier "UFID" patches.

A 128-bit UFID was selected to minimize the likelihood of hash conflicts.
Handler threads will not install a flow that has an identical UFID as
another flow, to prevent misattribution of stats and to ensure that the
correct flow key cache is used for revalidation.

The UFID for a flow is a 128-bit hash of the flow key. For datapaths that
do not support UFID, which is currently all datapaths, the dpif will
generate the UFID and pass it up during upcall and flow_dump. This is
generated based on the datapath flow key.

Later patches will add support for datapaths to store and interpret this
UFID, in which case the dpif has a responsibility to pass it through
transparently.

Signed-off-by: Joe Stringer <joestringer at nicira.com>
Acked-by: Ben Pfaff <blp at nicira.com>
---
v9-v10: Rebase.
v8: Rebase.
v7: Use ovs_u128_equal() for UID comparison.
v6: Split out from "dpif: Add Unique flow identifiers."
    Store flow hash seed staticly for all dpifs.
    Rebase.
v5: Always pass flow_key down to dpif, to improve error logging.
    Rebase.
v4: Generate UID in dpif layer and pass up to ofproto-dpif-upcall.
    Skip sending flow key in flow_del.
    Combine dpif,upcall,dpif-netdev,dpif-linux changes into one patch.
v3: Rebase.
---
 lib/dpif-netdev.c             |   78 +++++++++++++++++++++--------------------
 lib/dpif-netlink.c            |   22 +++++++-----
 lib/dpif.c                    |   15 ++++++++
 lib/dpif.h                    |   11 ++++--
 ofproto/ofproto-dpif-upcall.c |   71 ++++++++++++++++++++-----------------
 5 files changed, 116 insertions(+), 81 deletions(-)

diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c
index 65df19b..421801e 100644
--- a/lib/dpif-netdev.c
+++ b/lib/dpif-netdev.c
@@ -1547,24 +1547,44 @@ get_dpif_flow_stats(const struct dp_netdev_flow *netdev_flow,
     }
 }
 
+/* Converts to the dpif_flow format, using 'key_buf' and 'mask_buf' for
+ * storing the netlink-formatted key/mask. 'key_buf' may be the same as
+ * '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 dp_netdev_flow *netdev_flow,
-                            struct ofpbuf *buffer, struct dpif_flow *flow)
+dp_netdev_flow_to_dpif_flow(const struct dpif *dpif,
+                            const struct dp_netdev_flow *netdev_flow,
+                            struct ofpbuf *key_buf, struct ofpbuf *mask_buf,
+                            struct dpif_flow *flow)
 {
     struct flow_wildcards wc;
     struct dp_netdev_actions *actions;
+    size_t offset;
 
     miniflow_expand(&netdev_flow->cr.mask->mf, &wc.masks);
-    odp_flow_key_from_mask(buffer, &wc.masks, &netdev_flow->flow,
+
+    /* Key */
+    offset = ofpbuf_size(key_buf);
+    flow->key = ofpbuf_tail(key_buf);
+    odp_flow_key_from_flow(key_buf, &netdev_flow->flow, &wc.masks,
+                           netdev_flow->flow.in_port.odp_port, true);
+    flow->key_len = ofpbuf_size(key_buf) - offset;
+
+    /* Mask */
+    offset = ofpbuf_size(mask_buf);
+    flow->mask = ofpbuf_tail(mask_buf);
+    odp_flow_key_from_mask(mask_buf, &wc.masks, &netdev_flow->flow,
                            odp_to_u32(wc.masks.in_port.odp_port),
                            SIZE_MAX, true);
-    flow->mask = ofpbuf_data(buffer);
-    flow->mask_len = ofpbuf_size(buffer);
+    flow->mask_len = ofpbuf_size(mask_buf) - offset;
 
+    /* Actions */
     actions = dp_netdev_flow_get_actions(netdev_flow);
     flow->actions = actions->actions;
     flow->actions_len = actions->size;
 
+    dpif_flow_hash(dpif, &netdev_flow->flow, sizeof netdev_flow->flow,
+                   &flow->ufid);
     get_dpif_flow_stats(netdev_flow, &flow->stats);
 }
 
@@ -1676,7 +1696,8 @@ dpif_netdev_flow_get(const struct dpif *dpif, const struct dpif_flow_get *get)
     netdev_flow = dp_netdev_find_flow(dp, &key);
 
     if (netdev_flow) {
-        dp_netdev_flow_to_dpif_flow(netdev_flow, get->buffer, get->flow);
+        dp_netdev_flow_to_dpif_flow(dpif, netdev_flow, get->buffer,
+                                    get->buffer, get->flow);
      } else {
         error = ENOENT;
     }
@@ -1953,34 +1974,11 @@ dpif_netdev_flow_dump_next(struct dpif_flow_dump_thread *thread_,
         struct odputil_keybuf *keybuf = &thread->keybuf[i];
         struct dp_netdev_flow *netdev_flow = netdev_flows[i];
         struct dpif_flow *f = &flows[i];
-        struct dp_netdev_actions *dp_actions;
-        struct flow_wildcards wc;
-        struct ofpbuf buf;
-
-        miniflow_expand(&netdev_flow->cr.mask->mf, &wc.masks);
-
-        /* Key. */
-        ofpbuf_use_stack(&buf, keybuf, sizeof *keybuf);
-        odp_flow_key_from_flow(&buf, &netdev_flow->flow, &wc.masks,
-                               netdev_flow->flow.in_port.odp_port, true);
-        f->key = ofpbuf_data(&buf);
-        f->key_len = ofpbuf_size(&buf);
-
-        /* Mask. */
-        ofpbuf_use_stack(&buf, maskbuf, sizeof *maskbuf);
-        odp_flow_key_from_mask(&buf, &wc.masks, &netdev_flow->flow,
-                               odp_to_u32(wc.masks.in_port.odp_port),
-                               SIZE_MAX, true);
-        f->mask = ofpbuf_data(&buf);
-        f->mask_len = ofpbuf_size(&buf);
-
-        /* Actions. */
-        dp_actions = dp_netdev_flow_get_actions(netdev_flow);
-        f->actions = dp_actions->actions;
-        f->actions_len = dp_actions->size;
+        struct ofpbuf key, mask;
 
-        /* Stats. */
-        get_dpif_flow_stats(netdev_flow, &f->stats);
+        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);
     }
 
     return n_flows;
@@ -2604,7 +2602,7 @@ dp_netdev_count_packet(struct dp_netdev *dp, enum dp_stat_type type, int cnt)
 
 static int
 dp_netdev_upcall(struct dp_netdev *dp, struct dpif_packet *packet_,
-                 struct flow *flow, struct flow_wildcards *wc,
+                 struct flow *flow, struct flow_wildcards *wc, ovs_u128 *ufid,
                  enum dpif_upcall_type type, const struct nlattr *userdata,
                  struct ofpbuf *actions, struct ofpbuf *put_actions)
 {
@@ -2640,7 +2638,7 @@ dp_netdev_upcall(struct dp_netdev *dp, struct dpif_packet *packet_,
         ds_destroy(&ds);
     }
 
-    return dp->upcall_cb(packet, flow, type, userdata, actions, wc,
+    return dp->upcall_cb(packet, flow, ufid, type, userdata, actions, wc,
                          put_actions, dp->upcall_aux);
 }
 
@@ -2825,6 +2823,7 @@ fast_path_processing(struct dp_netdev_pmd_thread *pmd,
     if (OVS_UNLIKELY(any_miss) && !fat_rwlock_tryrdlock(&dp->upcall_rwlock)) {
         uint64_t actions_stub[512 / 8], slow_stub[512 / 8];
         struct ofpbuf actions, put_actions;
+        ovs_u128 ufid;
 
         ofpbuf_use_stub(&actions, actions_stub, sizeof actions_stub);
         ofpbuf_use_stub(&put_actions, slow_stub, sizeof slow_stub);
@@ -2853,8 +2852,9 @@ fast_path_processing(struct dp_netdev_pmd_thread *pmd,
             ofpbuf_clear(&actions);
             ofpbuf_clear(&put_actions);
 
+            dpif_flow_hash(dp->dpif, &match.flow, sizeof match.flow, &ufid);
             error = dp_netdev_upcall(dp, packets[i], &match.flow, &match.wc,
-                                     DPIF_UC_MISS, NULL, &actions,
+                                     &ufid, DPIF_UC_MISS, NULL, &actions,
                                      &put_actions);
             if (OVS_UNLIKELY(error && error != ENOSPC)) {
                 continue;
@@ -3083,6 +3083,7 @@ dp_execute_cb(void *aux_, struct dpif_packet **packets, int cnt,
             const struct nlattr *userdata;
             struct ofpbuf actions;
             struct flow flow;
+            ovs_u128 ufid;
 
             userdata = nl_attr_find_nested(a, OVS_USERSPACE_ATTR_USERDATA);
             ofpbuf_init(&actions, 0);
@@ -3093,8 +3094,9 @@ dp_execute_cb(void *aux_, struct dpif_packet **packets, int cnt,
                 ofpbuf_clear(&actions);
 
                 flow_extract(&packets[i]->ofpbuf, &packets[i]->md, &flow);
-                error = dp_netdev_upcall(dp, packets[i], &flow, NULL,
-                                         DPIF_UC_ACTION, userdata, &actions,
+                dpif_flow_hash(dp->dpif, &flow, sizeof flow, &ufid);
+                error = dp_netdev_upcall(dp, packets[i], &flow, NULL, &ufid,
+                                         DPIF_UC_ACTION, userdata,&actions,
                                          NULL);
                 if (!error || error == ENOSPC) {
                     dp_netdev_execute_actions(pmd, &packets[i], 1, may_steal,
diff --git a/lib/dpif-netlink.c b/lib/dpif-netlink.c
index d90fdd9..6c0cc07 100644
--- a/lib/dpif-netlink.c
+++ b/lib/dpif-netlink.c
@@ -133,7 +133,7 @@ static int dpif_netlink_flow_transact(struct dpif_netlink_flow *request,
                                       struct ofpbuf **bufp);
 static void dpif_netlink_flow_get_stats(const struct dpif_netlink_flow *,
                                         struct dpif_flow_stats *);
-static void dpif_netlink_flow_to_dpif_flow(struct dpif_flow *,
+static void dpif_netlink_flow_to_dpif_flow(struct dpif *, struct dpif_flow *,
                                            const struct dpif_netlink_flow *);
 
 /* One of the dpif channels between the kernel and userspace. */
@@ -1364,7 +1364,7 @@ dpif_netlink_flow_dump_thread_destroy(struct dpif_flow_dump_thread *thread_)
 }
 
 static void
-dpif_netlink_flow_to_dpif_flow(struct dpif_flow *dpif_flow,
+dpif_netlink_flow_to_dpif_flow(struct dpif *dpif, struct dpif_flow *dpif_flow,
                                const struct dpif_netlink_flow *datapath_flow)
 {
     dpif_flow->key = datapath_flow->key;
@@ -1373,6 +1373,8 @@ dpif_netlink_flow_to_dpif_flow(struct dpif_flow *dpif_flow,
     dpif_flow->mask_len = datapath_flow->mask_len;
     dpif_flow->actions = datapath_flow->actions;
     dpif_flow->actions_len = datapath_flow->actions_len;
+    dpif_flow_hash(dpif, datapath_flow->key, datapath_flow->key_len,
+                   &dpif_flow->ufid);
     dpif_netlink_flow_get_stats(datapath_flow, &dpif_flow->stats);
 }
 
@@ -1410,7 +1412,8 @@ dpif_netlink_flow_dump_next(struct dpif_flow_dump_thread *thread_,
 
         if (datapath_flow.actions) {
             /* Common case: the flow includes actions. */
-            dpif_netlink_flow_to_dpif_flow(&flows[n_flows++], &datapath_flow);
+            dpif_netlink_flow_to_dpif_flow(&dpif->dpif, &flows[n_flows++],
+                                           &datapath_flow);
         } else {
             /* Rare case: the flow does not include actions.  Retrieve this
              * individual flow again to get the actions. */
@@ -1429,7 +1432,8 @@ dpif_netlink_flow_dump_next(struct dpif_flow_dump_thread *thread_,
 
             /* Save this flow.  Then exit, because we only have one buffer to
              * handle this case. */
-            dpif_netlink_flow_to_dpif_flow(&flows[n_flows++], &datapath_flow);
+            dpif_netlink_flow_to_dpif_flow(&dpif->dpif, &flows[n_flows++],
+                                           &datapath_flow);
             break;
         }
     }
@@ -1600,7 +1604,8 @@ dpif_netlink_operate__(struct dpif_netlink *dpif,
 
                 op->error = dpif_netlink_flow_from_ofpbuf(&reply, txn->reply);
                 if (!op->error) {
-                    dpif_netlink_flow_to_dpif_flow(get->flow, &reply);
+                    dpif_netlink_flow_to_dpif_flow(&dpif->dpif, get->flow,
+                                                   &reply);
                 }
             }
             break;
@@ -1853,8 +1858,8 @@ dpif_netlink_queue_to_priority(const struct dpif *dpif OVS_UNUSED,
 }
 
 static int
-parse_odp_packet(struct ofpbuf *buf, struct dpif_upcall *upcall,
-                 int *dp_ifindex)
+parse_odp_packet(const struct dpif_netlink *dpif, struct ofpbuf *buf,
+                 struct dpif_upcall *upcall, int *dp_ifindex)
 {
     static const struct nl_policy ovs_packet_policy[] = {
         /* Always present. */
@@ -1898,6 +1903,7 @@ parse_odp_packet(struct ofpbuf *buf, struct dpif_upcall *upcall,
     upcall->key = CONST_CAST(struct nlattr *,
                              nl_attr_get(a[OVS_PACKET_ATTR_KEY]));
     upcall->key_len = nl_attr_get_size(a[OVS_PACKET_ATTR_KEY]);
+    dpif_flow_hash(&dpif->dpif, upcall->key, upcall->key_len, &upcall->ufid);
     upcall->userdata = a[OVS_PACKET_ATTR_USERDATA];
     upcall->out_tun_key = a[OVS_PACKET_ATTR_EGRESS_TUN_KEY];
 
@@ -2046,7 +2052,7 @@ dpif_netlink_recv__(struct dpif_netlink *dpif, uint32_t handler_id,
                 return error;
             }
 
-            error = parse_odp_packet(buf, upcall, &dp_ifindex);
+            error = parse_odp_packet(dpif, buf, upcall, &dp_ifindex);
             if (!error && dp_ifindex == dpif->dp_ifindex) {
                 return 0;
             } else if (error) {
diff --git a/lib/dpif.c b/lib/dpif.c
index d179d8a..6cfe263 100644
--- a/lib/dpif.c
+++ b/lib/dpif.c
@@ -822,6 +822,21 @@ dpif_flow_stats_format(const struct dpif_flow_stats *stats, struct ds *s)
     }
 }
 
+/* Places the hash of the 'key_len' bytes starting at 'key' into '*hash'. */
+void
+dpif_flow_hash(const struct dpif *dpif OVS_UNUSED,
+               const void *key, size_t key_len, ovs_u128 *hash)
+{
+    static struct ovsthread_once once = OVSTHREAD_ONCE_INITIALIZER;
+    static uint32_t secret;
+
+    if (ovsthread_once_start(&once)) {
+        secret = random_uint32();
+        ovsthread_once_done(&once);
+    }
+    hash_bytes128(key, key_len, secret, hash);
+}
+
 /* Deletes all flows from 'dpif'.  Returns 0 if successful, otherwise a
  * positive errno value.  */
 int
diff --git a/lib/dpif.h b/lib/dpif.h
index 598e609..9e49b20 100644
--- a/lib/dpif.h
+++ b/lib/dpif.h
@@ -515,6 +515,8 @@ enum dpif_flow_put_flags {
     DPIF_FP_PROBE = 1 << 3      /* Suppress error messages, if any. */
 };
 
+void dpif_flow_hash(const struct dpif *, const void *key, size_t key_len,
+                    ovs_u128 *hash);
 int dpif_flow_flush(struct dpif *);
 int dpif_flow_put(struct dpif *, enum dpif_flow_put_flags,
                   const struct nlattr *key, size_t key_len,
@@ -571,6 +573,7 @@ struct dpif_flow {
     size_t mask_len;              /* 'mask' length in bytes. */
     const struct nlattr *actions; /* Actions, as OVS_ACTION_ATTR_ */
     size_t actions_len;           /* 'actions' length in bytes. */
+    ovs_u128 ufid;                /* Unique flow identifier. */
     struct dpif_flow_stats stats; /* Flow statistics. */
 };
 int dpif_flow_dump_next(struct dpif_flow_dump_thread *,
@@ -735,6 +738,7 @@ struct dpif_upcall {
     struct ofpbuf packet;       /* Packet data. */
     struct nlattr *key;         /* Flow key. */
     size_t key_len;             /* Length of 'key' in bytes. */
+    ovs_u128 ufid;              /* Unique flow identifier for 'key'. */
 
     /* DPIF_UC_ACTION only. */
     struct nlattr *userdata;    /* Argument to OVS_ACTION_ATTR_USERSPACE. */
@@ -743,9 +747,9 @@ struct dpif_upcall {
 
 /* A callback to process an upcall, currently implemented only by dpif-netdev.
  *
- * The caller provides the 'packet' and 'flow' to process, the 'type' of the
- * upcall, and if 'type' is DPIF_UC_ACTION then the 'userdata' attached to the
- * action.
+ * The caller provides the 'packet' and 'flow' to process, the corresponding
+ * 'ufid' as generated by dpif_flow_hash(), the 'type' of the upcall, and if
+ * 'type' is DPIF_UC_ACTION then the 'userdata' attached to the action.
  *
  * The callback must fill in 'actions' with the datapath actions to apply to
  * 'packet'.  'wc' and 'put_actions' will either be both null or both nonnull.
@@ -760,6 +764,7 @@ struct dpif_upcall {
  * flow should be installed, or some otherwise a positive errno value. */
 typedef int upcall_callback(const struct ofpbuf *packet,
                             const struct flow *flow,
+                            ovs_u128 *ufid,
                             enum dpif_upcall_type type,
                             const struct nlattr *userdata,
                             struct ofpbuf *actions,
diff --git a/ofproto/ofproto-dpif-upcall.c b/ofproto/ofproto-dpif-upcall.c
index 9b8f8a0..0b1b597 100644
--- a/ofproto/ofproto-dpif-upcall.c
+++ b/ofproto/ofproto-dpif-upcall.c
@@ -99,8 +99,6 @@ struct udpif {
     struct dpif *dpif;                 /* Datapath handle. */
     struct dpif_backer *backer;        /* Opaque dpif_backer pointer. */
 
-    uint32_t secret;                   /* Random seed for upcall hash. */
-
     struct handler *handlers;          /* Upcall handlers. */
     size_t n_handlers;
 
@@ -158,6 +156,7 @@ struct upcall {
      * dpif-netdev.  If a modification is absolutely necessary, a const cast
      * may be used with other datapaths. */
     const struct flow *flow;       /* Parsed representation of the packet. */
+    const ovs_u128 *ufid;          /* Unique identifier for 'flow'. */
     const struct ofpbuf *packet;   /* Packet associated with this upcall. */
     ofp_port_t in_port;            /* OpenFlow in port, or OFPP_NONE. */
 
@@ -208,6 +207,7 @@ struct udpif_key {
     const struct nlattr *mask;     /* Datapath flow mask. */
     size_t mask_len;               /* Length of 'mask'. */
     struct ofpbuf *actions;        /* Datapath flow actions as nlattrs. */
+    ovs_u128 ufid;                 /* Unique flow identifier. */
     uint32_t hash;                 /* Pre-computed hash for 'key'. */
 
     struct ovs_mutex mutex;                   /* Guards the following. */
@@ -263,15 +263,14 @@ static void upcall_unixctl_dump_wait(struct unixctl_conn *conn, int argc,
 static void upcall_unixctl_purge(struct unixctl_conn *conn, int argc,
                                  const char *argv[], void *aux);
 
-static struct udpif_key *ukey_create_from_upcall(const struct udpif *,
-                                                 const struct upcall *);
+static struct udpif_key *ukey_create_from_upcall(const struct upcall *);
 static struct udpif_key *ukey_create_from_dpif_flow(const struct udpif *,
                                                     const struct dpif_flow *);
 static bool ukey_install_start(struct udpif *, struct udpif_key *ukey);
 static bool ukey_install_finish(struct udpif_key *ukey, int error);
 static bool ukey_install(struct udpif *udpif, struct udpif_key *ukey);
-static struct udpif_key *ukey_lookup(struct udpif *udpif, uint32_t hash,
-                                     const struct nlattr *key, size_t key_len);
+static struct udpif_key *ukey_lookup(struct udpif *udpif,
+                                     const ovs_u128 *ufid);
 static int ukey_acquire(struct udpif *, const struct dpif_flow *,
                         struct udpif_key **result);
 static void ukey_delete__(struct udpif_key *);
@@ -281,7 +280,8 @@ static enum upcall_type classify_upcall(enum dpif_upcall_type type,
 
 static int upcall_receive(struct upcall *, const struct dpif_backer *,
                           const struct ofpbuf *packet, enum dpif_upcall_type,
-                          const struct nlattr *userdata, const struct flow *);
+                          const struct nlattr *userdata, const struct flow *,
+                          const ovs_u128 *ufid);
 static void upcall_uninit(struct upcall *);
 
 static upcall_callback upcall_cb;
@@ -313,7 +313,6 @@ udpif_create(struct dpif_backer *backer, struct dpif *dpif)
     udpif->dpif = dpif;
     udpif->backer = backer;
     atomic_init(&udpif->flow_limit, MIN(ofproto_flow_limit, 10000));
-    udpif->secret = random_uint32();
     udpif->reval_seq = seq_create();
     udpif->dump_seq = seq_create();
     latch_init(&udpif->exit_latch);
@@ -637,7 +636,8 @@ recv_upcalls(struct handler *handler)
         }
 
         error = upcall_receive(upcall, udpif->backer, &dupcall->packet,
-                               dupcall->type, dupcall->userdata, flow);
+                               dupcall->type, dupcall->userdata, flow,
+                               &dupcall->ufid);
         if (error) {
             if (error == ENODEV) {
                 /* Received packet on datapath port for which we couldn't
@@ -654,6 +654,7 @@ recv_upcalls(struct handler *handler)
 
         upcall->key = dupcall->key;
         upcall->key_len = dupcall->key_len;
+        upcall->ufid = &dupcall->ufid;
 
         upcall->out_tun_key = dupcall->out_tun_key;
 
@@ -861,7 +862,8 @@ compose_slow_path(struct udpif *udpif, struct xlate_out *xout,
 static int
 upcall_receive(struct upcall *upcall, const struct dpif_backer *backer,
                const struct ofpbuf *packet, enum dpif_upcall_type type,
-               const struct nlattr *userdata, const struct flow *flow)
+               const struct nlattr *userdata, const struct flow *flow,
+               const ovs_u128 *ufid)
 {
     int error;
 
@@ -873,6 +875,7 @@ upcall_receive(struct upcall *upcall, const struct dpif_backer *backer,
 
     upcall->flow = flow;
     upcall->packet = packet;
+    upcall->ufid = ufid;
     upcall->type = type;
     upcall->userdata = userdata;
     ofpbuf_init(&upcall->put_actions, 0);
@@ -955,7 +958,7 @@ upcall_xlate(struct udpif *udpif, struct upcall *upcall,
                           &upcall->put_actions);
     }
 
-    upcall->ukey = ukey_create_from_upcall(udpif, upcall);
+    upcall->ukey = ukey_create_from_upcall(upcall);
 }
 
 static void
@@ -973,7 +976,7 @@ upcall_uninit(struct upcall *upcall)
 }
 
 static int
-upcall_cb(const struct ofpbuf *packet, const struct flow *flow,
+upcall_cb(const struct ofpbuf *packet, const struct flow *flow, ovs_u128 *ufid,
           enum dpif_upcall_type type, const struct nlattr *userdata,
           struct ofpbuf *actions, struct flow_wildcards *wc,
           struct ofpbuf *put_actions, void *aux)
@@ -988,7 +991,7 @@ upcall_cb(const struct ofpbuf *packet, const struct flow *flow,
     atomic_read_relaxed(&udpif->flow_limit, &flow_limit);
 
     error = upcall_receive(&upcall, udpif->backer, packet, type, userdata,
-                           flow);
+                           flow, ufid);
     if (error) {
         return error;
     }
@@ -1156,6 +1159,7 @@ handle_upcalls(struct udpif *udpif, struct upcall *upcalls,
 
             upcall->ukey_persists = true;
             op = &ops[n_ops++];
+
             op->ukey = ukey;
             op->dop.type = DPIF_OP_FLOW_PUT;
             op->dop.u.flow_put.flags = DPIF_FP_CREATE;
@@ -1210,15 +1214,21 @@ handle_upcalls(struct udpif *udpif, struct upcall *upcalls,
     }
 }
 
+static uint32_t
+get_ufid_hash(const ovs_u128 *ufid)
+{
+    return ufid->u32[0];
+}
+
 static struct udpif_key *
-ukey_lookup(struct udpif *udpif, uint32_t hash, const struct nlattr *key,
-            size_t key_len)
+ukey_lookup(struct udpif *udpif, const ovs_u128 *ufid)
 {
     struct udpif_key *ukey;
-    struct cmap *cmap = &udpif->ukeys[hash % N_UMAPS].cmap;
+    int idx = get_ufid_hash(ufid) % N_UMAPS;
+    struct cmap *cmap = &udpif->ukeys[idx].cmap;
 
-    CMAP_FOR_EACH_WITH_HASH (ukey, cmap_node, hash, cmap) {
-        if (ukey->key_len == key_len && !memcmp(ukey->key, key, key_len)) {
+    CMAP_FOR_EACH_WITH_HASH (ukey, cmap_node, get_ufid_hash(ufid), cmap) {
+        if (ovs_u128_equal(&ukey->ufid, ufid)) {
             return ukey;
         }
     }
@@ -1226,10 +1236,9 @@ ukey_lookup(struct udpif *udpif, uint32_t hash, const struct nlattr *key,
 }
 
 static struct udpif_key *
-ukey_create__(const struct udpif *udpif,
-              const struct nlattr *key, size_t key_len,
+ukey_create__(const struct nlattr *key, size_t key_len,
               const struct nlattr *mask, size_t mask_len,
-              const struct ofpbuf *actions,
+              const ovs_u128 *ufid, const struct ofpbuf *actions,
               uint64_t dump_seq, uint64_t reval_seq, long long int used)
     OVS_NO_THREAD_SAFETY_ANALYSIS
 {
@@ -1241,7 +1250,8 @@ ukey_create__(const struct udpif *udpif,
     memcpy(&ukey->maskbuf, mask, mask_len);
     ukey->mask = &ukey->maskbuf.nla;
     ukey->mask_len = mask_len;
-    ukey->hash = hash_bytes(ukey->key, ukey->key_len, udpif->secret);
+    ukey->ufid = *ufid;
+    ukey->hash = get_ufid_hash(&ukey->ufid);
     ukey->actions = ofpbuf_clone(actions);
 
     ovs_mutex_init(&ukey->mutex);
@@ -1257,7 +1267,7 @@ ukey_create__(const struct udpif *udpif,
 }
 
 static struct udpif_key *
-ukey_create_from_upcall(const struct udpif *udpif, const struct upcall *upcall)
+ukey_create_from_upcall(const struct upcall *upcall)
 {
     struct odputil_keybuf keystub, maskstub;
     struct ofpbuf keybuf, maskbuf;
@@ -1284,9 +1294,9 @@ ukey_create_from_upcall(const struct udpif *udpif, const struct upcall *upcall)
                                UINT32_MAX, max_mpls, recirc);
     }
 
-    return ukey_create__(udpif, ofpbuf_data(&keybuf), ofpbuf_size(&keybuf),
+    return ukey_create__(ofpbuf_data(&keybuf), ofpbuf_size(&keybuf),
                          ofpbuf_data(&maskbuf), ofpbuf_size(&maskbuf),
-                         &upcall->put_actions, upcall->dump_seq,
+                         upcall->ufid, &upcall->put_actions, upcall->dump_seq,
                          upcall->reval_seq, 0);
 }
 
@@ -1300,8 +1310,8 @@ ukey_create_from_dpif_flow(const struct udpif *udpif,
     dump_seq = seq_read(udpif->dump_seq);
     reval_seq = seq_read(udpif->reval_seq);
     ofpbuf_use_const(&actions, &flow->actions, flow->actions_len);
-    return ukey_create__(udpif, flow->key, flow->key_len,
-                         flow->mask, flow->mask_len, &actions,
+    return ukey_create__(flow->key, flow->key_len,
+                         flow->mask, flow->mask_len, &flow->ufid, &actions,
                          dump_seq, reval_seq, flow->stats.used);
 }
 
@@ -1321,8 +1331,7 @@ ukey_install_start(struct udpif *udpif, struct udpif_key *new_ukey)
     idx = new_ukey->hash % N_UMAPS;
     umap = &udpif->ukeys[idx];
     ovs_mutex_lock(&umap->mutex);
-    old_ukey = ukey_lookup(udpif, new_ukey->hash, new_ukey->key,
-                           new_ukey->key_len);
+    old_ukey = ukey_lookup(udpif, &new_ukey->ufid);
     if (old_ukey) {
         /* Uncommon case: A ukey is already installed with the same UFID. */
         if (old_ukey->key_len == new_ukey->key_len
@@ -1393,11 +1402,9 @@ ukey_acquire(struct udpif *udpif, const struct dpif_flow *flow,
     OVS_TRY_LOCK(true, (*result)->mutex)
 {
     struct udpif_key *ukey;
-    uint32_t hash;
     bool locked = false;
 
-    hash = hash_bytes(flow->key, flow->key_len, udpif->secret);
-    ukey = ukey_lookup(udpif, hash, flow->key, flow->key_len);
+    ukey = ukey_lookup(udpif, &flow->ufid);
     if (ukey) {
         if (!ovs_mutex_trylock(&ukey->mutex)) {
             locked = true;
-- 
1.7.10.4




More information about the dev mailing list