[ovs-dev] [PATCHv3] dpif: Support fetching flow mask via dpif_flow_get().

Joe Stringer joestringer at nicira.com
Fri Jul 4 00:37:12 UTC 2014


Change the interface to allow implementations to pass back a buffer, and
allow callers to specify which of actions, mask, and stats they wish to
receive. This will be used in the next commit.

Signed-off-by: Joe Stringer <joestringer at nicira.com>
---
v3: Set *bufp to NULL before calling ->flow_get().
    Allocate the correct size for the buffer in dpif_netdev_flow_get().
    Don't overwrite mask with actions in dpif_netdev_flow_get().
    Remove unneeded *bufp = NULL in dpif_netdev_flow_get().
v2: First post.
---
 lib/dpif-linux.c    |   23 +++++++++++++----------
 lib/dpif-netdev.c   |   30 +++++++++++++++++++++++++++---
 lib/dpif-provider.h |   21 ++++++++++++++++-----
 lib/dpif.c          |   44 ++++++++++++++++++++++++++++++++------------
 lib/dpif.h          |    5 ++++-
 5 files changed, 92 insertions(+), 31 deletions(-)

diff --git a/lib/dpif-linux.c b/lib/dpif-linux.c
index 6a8564a..93154a3 100644
--- a/lib/dpif-linux.c
+++ b/lib/dpif-linux.c
@@ -1041,24 +1041,27 @@ dpif_linux_flow_get__(const struct dpif_linux *dpif,
 static int
 dpif_linux_flow_get(const struct dpif *dpif_,
                     const struct nlattr *key, size_t key_len,
-                    struct ofpbuf **actionsp, struct dpif_flow_stats *stats)
+                    struct ofpbuf **bufp,
+                    struct nlattr **maskp, size_t *mask_len,
+                    struct nlattr **actionsp, size_t *actions_len,
+                    struct dpif_flow_stats *stats)
 {
     const struct dpif_linux *dpif = dpif_linux_cast(dpif_);
     struct dpif_linux_flow reply;
-    struct ofpbuf *buf;
     int error;
 
-    error = dpif_linux_flow_get__(dpif, key, key_len, &reply, &buf);
+    error = dpif_linux_flow_get__(dpif, key, key_len, &reply, bufp);
     if (!error) {
-        if (stats) {
-            dpif_linux_flow_get_stats(&reply, stats);
+        if (maskp) {
+            *maskp = CONST_CAST(struct nlattr *, reply.mask);
+            *mask_len = reply.mask_len;
         }
         if (actionsp) {
-            ofpbuf_set_data(buf, CONST_CAST(struct nlattr *, reply.actions));
-            ofpbuf_set_size(buf, reply.actions_len);
-            *actionsp = buf;
-        } else {
-            ofpbuf_delete(buf);
+            *actionsp = CONST_CAST(struct nlattr *, reply.actions);
+            *actions_len = reply.actions_len;
+        }
+        if (stats) {
+            dpif_linux_flow_get_stats(&reply, stats);
         }
     }
     return error;
diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c
index fdf1af4..fb35306 100644
--- a/lib/dpif-netdev.c
+++ b/lib/dpif-netdev.c
@@ -1191,7 +1191,10 @@ dpif_netdev_flow_from_nlattrs(const struct nlattr *key, uint32_t key_len,
 static int
 dpif_netdev_flow_get(const struct dpif *dpif,
                      const struct nlattr *nl_key, size_t nl_key_len,
-                     struct ofpbuf **actionsp, struct dpif_flow_stats *stats)
+                     struct ofpbuf **bufp,
+                     struct nlattr **maskp, size_t *mask_len,
+                     struct nlattr **actionsp, size_t *actions_len,
+                     struct dpif_flow_stats *stats)
 {
     struct dp_netdev *dp = get_dp_netdev(dpif);
     struct dp_netdev_flow *netdev_flow;
@@ -1212,11 +1215,32 @@ dpif_netdev_flow_get(const struct dpif *dpif,
             get_dpif_flow_stats(netdev_flow, stats);
         }
 
-        if (actionsp) {
+        if (maskp || actionsp) {
             struct dp_netdev_actions *actions;
+            size_t len = 0;
 
             actions = dp_netdev_flow_get_actions(netdev_flow);
-            *actionsp = ofpbuf_clone_data(actions->actions, actions->size);
+            len += maskp ? sizeof(struct odputil_keybuf) : 0;
+            len += actionsp ? actions->size : 0;
+
+            *bufp = ofpbuf_new(len);
+            if (maskp) {
+                struct flow_wildcards wc;
+
+                minimask_expand(&netdev_flow->cr.match.mask, &wc);
+                odp_flow_key_from_mask(*bufp, &wc.masks, &netdev_flow->flow,
+                                       odp_to_u32(wc.masks.in_port.odp_port),
+                                       SIZE_MAX);
+                *maskp = ofpbuf_data(*bufp);
+                *mask_len = ofpbuf_size(*bufp);
+            }
+            if (actionsp) {
+                struct dp_netdev_actions *actions;
+
+                actions = dp_netdev_flow_get_actions(netdev_flow);
+                *actionsp = ofpbuf_put(*bufp, actions->actions, actions->size);
+                *actions_len = actions->size;
+            }
         }
      } else {
         error = ENOENT;
diff --git a/lib/dpif-provider.h b/lib/dpif-provider.h
index 615f2c6..389e84e 100644
--- a/lib/dpif-provider.h
+++ b/lib/dpif-provider.h
@@ -224,16 +224,27 @@ struct dpif_class {
      * Returns 0 if successful.  If no flow matches, returns ENOENT.  On other
      * failure, returns a positive errno value.
      *
-     * If 'actionsp' is nonnull, then on success '*actionsp' must be set to an
-     * ofpbuf owned by the caller that contains the Netlink attributes for the
-     * flow's actions.  The caller must free the ofpbuf (with ofpbuf_delete())
-     * when it is no longer needed.
+     * On success, '*bufp' will be set to an ofpbuf owned by the caller that
+     * contains the response for 'maskp' and 'actionsp'. The caller must supply
+     * a valid pointer, and must free the ofpbuf (with ofpbuf_delete()) when it
+     * is no longer needed.
+     *
+     * If 'maskp' is nonnull, then on success '*maskp' will point to the
+     * Netlink attributes for the flow's mask, stored in '*bufp'. '*mask_len'
+     * will be set to the length of the mask attributes.
+     *
+     * If 'actionsp' is nonnull, then on success '*actionsp' will point to the
+     * Netlink attributes for the flow's actions, stored in '*bufp'.
+     * '*actions_len' will be set to the length of the actions attributes.
      *
      * If 'stats' is nonnull, then on success it must be updated with the
      * flow's statistics. */
     int (*flow_get)(const struct dpif *dpif,
                     const struct nlattr *key, size_t key_len,
-                    struct ofpbuf **actionsp, struct dpif_flow_stats *stats);
+                    struct ofpbuf **bufp,
+                    struct nlattr **maskp, size_t *mask_len,
+                    struct nlattr **actionsp, size_t *acts_len,
+                    struct dpif_flow_stats *stats);
 
     /* Adds or modifies a flow in 'dpif'.  The flow is specified by the Netlink
      * attributes with types OVS_KEY_ATTR_* in the 'put->key_len' bytes
diff --git a/lib/dpif.c b/lib/dpif.c
index 8ec8200..450c6c8 100644
--- a/lib/dpif.c
+++ b/lib/dpif.c
@@ -831,44 +831,64 @@ dpif_flow_flush(struct dpif *dpif)
  * Returns 0 if successful.  If no flow matches, returns ENOENT.  On other
  * failure, returns a positive errno value.
  *
- * If 'actionsp' is nonnull, then on success '*actionsp' will be set to an
- * ofpbuf owned by the caller that contains the Netlink attributes for the
- * flow's actions.  The caller must free the ofpbuf (with ofpbuf_delete()) when
- * it is no longer needed.
+ * On success, '*bufp' will be set to an ofpbuf owned by the caller that
+ * contains the response for 'maskp' and 'actionsp'. The caller must supply
+ * a valid pointer, and must free the ofpbuf (with ofpbuf_delete()) when it
+ * is no longer needed.
+ *
+ * If 'maskp' is nonnull, then on success '*maskp' will point to the
+ * Netlink attributes for the flow's mask, stored in '*bufp'. '*mask_len'
+ * will be set to the length of the mask attributes.
+ *
+ * If 'actionsp' is nonnull, then on success '*actionsp' will point to the
+ * Netlink attributes for the flow's actions, stored in '*bufp'.
+ * '*actions_len' will be set to the length of the actions attributes.
  *
  * If 'stats' is nonnull, then on success it will be updated with the flow's
  * statistics. */
 int
 dpif_flow_get(const struct dpif *dpif,
-              const struct nlattr *key, size_t key_len,
-              struct ofpbuf **actionsp, struct dpif_flow_stats *stats)
+              const struct nlattr *key, size_t key_len, struct ofpbuf **bufp,
+              struct nlattr **maskp, size_t *mask_len,
+              struct nlattr **actionsp, size_t *actions_len,
+              struct dpif_flow_stats *stats)
 {
     int error;
 
     COVERAGE_INC(dpif_flow_get);
 
-    error = dpif->dpif_class->flow_get(dpif, key, key_len, actionsp, stats);
+    *bufp = NULL;
+    error = dpif->dpif_class->flow_get(dpif, key, key_len, bufp,
+                                       maskp, mask_len,
+                                       actionsp, actions_len,
+                                       stats);
     if (error) {
         if (actionsp) {
             *actionsp = NULL;
+            *actions_len = 0;
+        }
+        if (maskp) {
+            *maskp = NULL;
+            *mask_len = 0;
         }
         if (stats) {
             memset(stats, 0, sizeof *stats);
         }
+        ofpbuf_delete(*bufp);
     }
     if (should_log_flow_message(error)) {
         const struct nlattr *actions;
-        size_t actions_len;
+        size_t acts_len;
 
         if (!error && actionsp) {
-            actions = ofpbuf_data(*actionsp);
-            actions_len = ofpbuf_size(*actionsp);
+            actions = *actionsp;
+            acts_len = *actions_len;
         } else {
             actions = NULL;
-            actions_len = 0;
+            acts_len = 0;
         }
         log_flow_message(dpif, error, "flow_get", key, key_len,
-                         NULL, 0, stats, actions, actions_len);
+                         NULL, 0, stats, actions, acts_len);
     }
     return error;
 }
diff --git a/lib/dpif.h b/lib/dpif.h
index e7aca8e..f13cc36 100644
--- a/lib/dpif.h
+++ b/lib/dpif.h
@@ -524,7 +524,10 @@ int dpif_flow_del(struct dpif *,
                   struct dpif_flow_stats *);
 int dpif_flow_get(const struct dpif *,
                   const struct nlattr *key, size_t key_len,
-                  struct ofpbuf **actionsp, struct dpif_flow_stats *);
+                  struct ofpbuf **bufp,
+                  struct nlattr **maskp, size_t *mask_len,
+                  struct nlattr **actionsp, size_t *acts_len,
+                  struct dpif_flow_stats *stats);
 
 struct dpif_flow_dump {
     const struct dpif *dpif;
-- 
1.7.10.4




More information about the dev mailing list