[ovs-dev] [RFCv2 11/12] dpif-linux: Support unique flow identifiers.

Joe Stringer joestringer at nicira.com
Wed Aug 27 08:43:07 UTC 2014


Signed-off-by: Joe Stringer <joestringer at nicira.com>
---
 lib/dpif-linux.c |   91 +++++++++++++++++++++++++-----------------------------
 1 file changed, 42 insertions(+), 49 deletions(-)

diff --git a/lib/dpif-linux.c b/lib/dpif-linux.c
index f4e78a1..a5f4182 100644
--- a/lib/dpif-linux.c
+++ b/lib/dpif-linux.c
@@ -110,6 +110,8 @@ struct dpif_linux_flow {
     size_t mask_len;
     const struct nlattr *actions;       /* OVS_FLOW_ATTR_ACTIONS. */
     size_t actions_len;
+    const struct nlattr *uid;           /* OVS_FLOW_ATTR_UID. */
+    size_t uid_len;
     const struct ovs_flow_stats *stats; /* OVS_FLOW_ATTR_STATS. */
     const uint8_t *tcp_flags;           /* OVS_FLOW_ATTR_TCP_FLAGS. */
     const ovs_32aligned_u64 *used;      /* OVS_FLOW_ATTR_USED. */
@@ -1050,25 +1052,16 @@ dpif_linux_port_poll_wait(const struct dpif *dpif_)
 
 static void
 dpif_linux_init_flow_get(const struct dpif_linux *dpif,
-                         const struct nlattr *key, size_t key_len,
+                         const struct dpif_flow_get *get,
                          struct dpif_linux_flow *request)
 {
     dpif_linux_flow_init(request);
     request->cmd = OVS_FLOW_CMD_GET;
     request->dp_ifindex = dpif->dp_ifindex;
-    request->key = key;
-    request->key_len = key_len;
-}
-
-static int
-dpif_linux_flow_get(const struct dpif_linux *dpif,
-                    const struct nlattr *key, size_t key_len,
-                    struct dpif_linux_flow *reply, struct ofpbuf **bufp)
-{
-    struct dpif_linux_flow request;
-
-    dpif_linux_init_flow_get(dpif, key, key_len, &request);
-    return dpif_linux_flow_transact(&request, reply, bufp);
+    request->key = get->key;
+    request->key_len = get->key_len;
+    request->uid = get->uid;
+    request->uid_len = get->uid_len;
 }
 
 static void
@@ -1085,6 +1078,9 @@ dpif_linux_init_flow_put(struct dpif_linux *dpif, const struct dpif_flow_put *pu
     request->key_len = put->key_len;
     request->mask = put->mask;
     request->mask_len = put->mask_len;
+    request->uid = put->uid;
+    request->uid_len = put->uid_len;
+
     /* Ensure that OVS_FLOW_ATTR_ACTIONS will always be included. */
     request->actions = (put->actions
                         ? put->actions
@@ -1105,6 +1101,8 @@ dpif_linux_init_flow_del(struct dpif_linux *dpif, const struct dpif_flow_del *de
     request->dp_ifindex = dpif->dp_ifindex;
     request->key = del->key;
     request->key_len = del->key_len;
+    request->uid = del->uid;
+    request->uid_len = del->uid_len;
 }
 
 struct dpif_linux_flow_dump {
@@ -1120,13 +1118,13 @@ dpif_linux_flow_dump_cast(struct dpif_flow_dump *dump)
 }
 
 static struct dpif_flow_dump *
-dpif_linux_flow_dump_create(const struct dpif *dpif_,
-                            uint32_t dump_flags OVS_UNUSED)
+dpif_linux_flow_dump_create(const struct dpif *dpif_, uint32_t dump_flags)
 {
     const struct dpif_linux *dpif = dpif_linux_cast(dpif_);
     struct dpif_linux_flow_dump *dump;
     struct dpif_linux_flow request;
-    struct ofpbuf *buf;
+    struct ofpbuf *buf, uid;
+    struct odputil_uidbuf uid_buf;
 
     dump = xmalloc(sizeof *dump);
     dpif_flow_dump_init(&dump->up, dpif_);
@@ -1135,6 +1133,11 @@ dpif_linux_flow_dump_create(const struct dpif *dpif_,
     request.cmd = OVS_FLOW_CMD_GET;
     request.dp_ifindex = dpif->dp_ifindex;
 
+    ofpbuf_use_stack(&uid, &uid_buf, sizeof uid_buf);
+    odp_uid_to_nlattrs(&uid, NULL, dump_flags);
+    request.uid = ofpbuf_data(&uid);
+    request.uid_len = ofpbuf_size(&uid);
+
     buf = ofpbuf_new(1024);
     dpif_linux_flow_to_ofpbuf(&request, buf);
     nl_dump_start(&dump->nl_dump, NETLINK_GENERIC, buf);
@@ -1207,8 +1210,8 @@ dpif_linux_flow_to_dpif_flow(struct dpif_flow *dpif_flow,
     dpif_flow->mask_len = linux_flow->mask_len;
     dpif_flow->actions = linux_flow->actions;
     dpif_flow->actions_len = linux_flow->actions_len;
-    dpif_flow->uid = NULL;
-    dpif_flow->uid_len = 0;
+    dpif_flow->uid = linux_flow->uid;
+    dpif_flow->uid_len = linux_flow->uid_len;
     dpif_linux_flow_get_stats(linux_flow, &dpif_flow->stats);
 }
 
@@ -1219,7 +1222,6 @@ dpif_linux_flow_dump_next(struct dpif_flow_dump_thread *thread_,
     struct dpif_linux_flow_dump_thread *thread
         = dpif_linux_flow_dump_thread_cast(thread_);
     struct dpif_linux_flow_dump *dump = thread->dump;
-    struct dpif_linux *dpif = dpif_linux_cast(thread->up.dpif);
     int n_flows;
 
     ofpbuf_delete(thread->nl_actions);
@@ -1244,30 +1246,7 @@ dpif_linux_flow_dump_next(struct dpif_flow_dump_thread *thread_,
             break;
         }
 
-        if (linux_flow.actions) {
-            /* Common case: the flow includes actions. */
-            dpif_linux_flow_to_dpif_flow(&flows[n_flows++], &linux_flow);
-        } else {
-            /* Rare case: the flow does not include actions.  Retrieve this
-             * individual flow again to get the actions. */
-            error = dpif_linux_flow_get(dpif, linux_flow.key,
-                                        linux_flow.key_len, &linux_flow,
-                                        &thread->nl_actions);
-            if (error == ENOENT) {
-                VLOG_DBG("dumped flow disappeared on get");
-                continue;
-            } else if (error) {
-                VLOG_WARN("error fetching dumped flow: %s",
-                          ovs_strerror(error));
-                atomic_store(&dump->status, error);
-                break;
-            }
-
-            /* Save this flow.  Then exit, because we only have one buffer to
-             * handle this case. */
-            dpif_linux_flow_to_dpif_flow(&flows[n_flows++], &linux_flow);
-            break;
-        }
+        dpif_linux_flow_to_dpif_flow(&flows[n_flows++], &linux_flow);
     }
     return n_flows;
 }
@@ -1367,7 +1346,7 @@ dpif_linux_operate__(struct dpif_linux *dpif,
 
         case DPIF_OP_FLOW_GET:
             get = &op->u.flow_get;
-            dpif_linux_init_flow_get(dpif, get->key, get->key_len, &flow);
+            dpif_linux_init_flow_get(dpif, get, &flow);
             aux->txn.reply = get->buffer;
             dpif_linux_flow_to_ofpbuf(&flow, &aux->request);
             break;
@@ -2268,14 +2247,15 @@ static int
 dpif_linux_flow_from_ofpbuf(struct dpif_linux_flow *flow,
                             const struct ofpbuf *buf)
 {
-    static const struct nl_policy ovs_flow_policy[] = {
-        [OVS_FLOW_ATTR_KEY] = { .type = NL_A_NESTED },
+    static const struct nl_policy ovs_flow_policy[__OVS_FLOW_ATTR_MAX] = {
+        [OVS_FLOW_ATTR_KEY] = { .type = NL_A_NESTED, .optional = true },
         [OVS_FLOW_ATTR_MASK] = { .type = NL_A_NESTED, .optional = true },
         [OVS_FLOW_ATTR_ACTIONS] = { .type = NL_A_NESTED, .optional = true },
         [OVS_FLOW_ATTR_STATS] = { NL_POLICY_FOR(struct ovs_flow_stats),
                                   .optional = true },
         [OVS_FLOW_ATTR_TCP_FLAGS] = { .type = NL_A_U8, .optional = true },
         [OVS_FLOW_ATTR_USED] = { .type = NL_A_U64, .optional = true },
+        [OVS_FLOW_ATTR_UID] = { .type = NL_A_NESTED, .optional = true },
         /* The kernel never uses OVS_FLOW_ATTR_CLEAR. */
     };
 
@@ -2297,12 +2277,21 @@ dpif_linux_flow_from_ofpbuf(struct dpif_linux_flow *flow,
                             ARRAY_SIZE(ovs_flow_policy))) {
         return EINVAL;
     }
+    if (!a[OVS_FLOW_ATTR_KEY] && !a[OVS_FLOW_ATTR_UID]) {
+        return EINVAL;
+    }
 
     flow->nlmsg_flags = nlmsg->nlmsg_flags;
     flow->dp_ifindex = ovs_header->dp_ifindex;
-    flow->key = nl_attr_get(a[OVS_FLOW_ATTR_KEY]);
-    flow->key_len = nl_attr_get_size(a[OVS_FLOW_ATTR_KEY]);
+    if (a[OVS_FLOW_ATTR_KEY]) {
+        flow->key = nl_attr_get(a[OVS_FLOW_ATTR_KEY]);
+        flow->key_len = nl_attr_get_size(a[OVS_FLOW_ATTR_KEY]);
+    }
 
+    if (a[OVS_FLOW_ATTR_UID]) {
+        flow->uid = nl_attr_get(a[OVS_FLOW_ATTR_UID]);
+        flow->uid_len = nl_attr_get_size(a[OVS_FLOW_ATTR_UID]);
+    }
     if (a[OVS_FLOW_ATTR_MASK]) {
         flow->mask = nl_attr_get(a[OVS_FLOW_ATTR_MASK]);
         flow->mask_len = nl_attr_get_size(a[OVS_FLOW_ATTR_MASK]);
@@ -2346,6 +2335,10 @@ dpif_linux_flow_to_ofpbuf(const struct dpif_linux_flow *flow,
         nl_msg_put_unspec(buf, OVS_FLOW_ATTR_MASK, flow->mask, flow->mask_len);
     }
 
+    if (flow->uid_len) {
+        nl_msg_put_unspec(buf, OVS_FLOW_ATTR_UID, flow->uid, flow->uid_len);
+    }
+
     if (flow->actions || flow->actions_len) {
         nl_msg_put_unspec(buf, OVS_FLOW_ATTR_ACTIONS,
                           flow->actions, flow->actions_len);
-- 
1.7.10.4




More information about the dev mailing list