[ovs-dev] [PATCHv10 ovs 15/15] dpctl: Add support for using UFID to add/del flows.

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


Signed-off-by: Joe Stringer <joestringer at nicira.com>
---
v10: First post.
---
 lib/dpctl.c    |   41 +++++++++++++++++++++++++++++++++++++----
 lib/odp-util.c |   35 +++++++++++++++++++++++++++++++++++
 lib/odp-util.h |    2 ++
 3 files changed, 74 insertions(+), 4 deletions(-)

diff --git a/lib/dpctl.c b/lib/dpctl.c
index 4e41fe4..7dc4714 100644
--- a/lib/dpctl.c
+++ b/lib/dpctl.c
@@ -819,9 +819,11 @@ dpctl_put_flow(int argc, const char *argv[], enum dpif_flow_put_flags flags,
     struct ofpbuf key;
     struct ofpbuf mask;
     struct dpif *dpif;
+    ovs_u128 ufid;
+    bool ufid_present;
     char *dp_name;
     struct simap port_names;
-    int error;
+    int n, error;
 
     dp_name = argc == 4 ? xstrdup(argv[1]) : get_one_dp(dpctl_p);
     if (!dp_name) {
@@ -834,6 +836,15 @@ dpctl_put_flow(int argc, const char *argv[], enum dpif_flow_put_flags flags,
         return error;
     }
 
+    ufid_present = false;
+    n = odp_ufid_from_string(key_s, &ufid);
+    if (n < 0) {
+        dpctl_error(dpctl_p, error, "parsing flow ufid");
+        return -n;
+    } else if (n) {
+        key_s += n;
+        ufid_present = true;
+    }
 
     simap_init(&port_names);
     DPIF_PORT_FOR_EACH (&dpif_port, &port_dump, dpif) {
@@ -860,7 +871,8 @@ dpctl_put_flow(int argc, const char *argv[], enum dpif_flow_put_flags flags,
                           ofpbuf_size(&mask) == 0 ? NULL : ofpbuf_data(&mask),
                           ofpbuf_size(&mask),
                           ofpbuf_data(&actions), ofpbuf_size(&actions),
-                          NULL, dpctl_p->print_statistics ? &stats : NULL);
+                          ufid_present ? &ufid : NULL,
+                          dpctl_p->print_statistics ? &stats : NULL);
     if (error) {
         dpctl_error(dpctl_p, error, "updating flow table");
         goto out_freeactions;
@@ -916,9 +928,11 @@ dpctl_del_flow(int argc, const char *argv[], struct dpctl_params *dpctl_p)
     struct ofpbuf key;
     struct ofpbuf mask; /* To be ignored. */
     struct dpif *dpif;
+    ovs_u128 ufid;
+    bool ufid_present;
     char *dp_name;
     struct simap port_names;
-    int error;
+    int n, error;
 
     dp_name = argc == 3 ? xstrdup(argv[1]) : get_one_dp(dpctl_p);
     if (!dp_name) {
@@ -931,6 +945,16 @@ dpctl_del_flow(int argc, const char *argv[], struct dpctl_params *dpctl_p)
         return error;
     }
 
+    ufid_present = false;
+    n = odp_ufid_from_string(key_s, &ufid);
+    if (n < 0) {
+        dpctl_error(dpctl_p, error, "parsing flow ufid");
+        return -n;
+    } else if (n) {
+        key_s += n;
+        ufid_present = true;
+    }
+
     simap_init(&port_names);
     DPIF_PORT_FOR_EACH (&dpif_port, &port_dump, dpif) {
         simap_put(&port_names, dpif_port.name, odp_to_u32(dpif_port.port_no));
@@ -946,10 +970,19 @@ dpctl_del_flow(int argc, const char *argv[], struct dpctl_params *dpctl_p)
     }
 
     error = dpif_flow_del(dpif,
-                          ofpbuf_data(&key), ofpbuf_size(&key), NULL,
+                          ofpbuf_data(&key), ofpbuf_size(&key),
+                          ufid_present ? &ufid : NULL,
                           dpctl_p->print_statistics ? &stats : NULL);
     if (error) {
         dpctl_error(dpctl_p, error, "deleting flow");
+        if (error == ENOENT && !ufid_present) {
+            struct ds s;
+
+            ds_init(&s);
+            ds_put_format(&s, "Perhaps you need to specify a UFID?");
+            dpctl_print(dpctl_p, "%s\n", ds_cstr(&s));
+            ds_destroy(&s);
+        }
         goto out;
     }
 
diff --git a/lib/odp-util.c b/lib/odp-util.c
index cc465e9..d093e9d 100644
--- a/lib/odp-util.c
+++ b/lib/odp-util.c
@@ -3162,6 +3162,41 @@ odp_ufid_to_nlattrs(struct ofpbuf *buf, const ovs_u128 *ufid, uint32_t flags)
     nl_msg_end_nested(buf, offset);
 }
 
+int
+odp_ufid_from_string(const char *s_, ovs_u128 *ufid)
+{
+    const char *s = s_;
+
+    if (!strncmp(s, "ufid:", 5)) {
+        const char *upper;
+        size_t n;
+
+        s += 5;
+        n = strspn(s, "0123456789abcdefABCDEF");
+        if (!n || n > 32) {
+            return -EINVAL;
+        }
+
+        upper = s;
+        if (n > 16) {
+            char *lower = strndup(s, n - 16);
+
+            ufid->u64.lo = strtoull(lower, NULL, 16);
+            upper += (n - 16);
+            free(lower);
+        } else {
+            ufid->u64.lo = 0;
+        }
+        ufid->u64.hi = strtoull(upper, NULL, 16);
+        s += n;
+        s += strspn(s, delimiters);
+
+        return s - s_;
+    }
+
+    return 0;
+}
+
 void
 odp_format_ufid(const ovs_u128 *ufid, struct ds *ds)
 {
diff --git a/lib/odp-util.h b/lib/odp-util.h
index 1e12f3d..eba3f3d 100644
--- a/lib/odp-util.h
+++ b/lib/odp-util.h
@@ -162,6 +162,8 @@ void odp_flow_key_from_mask(struct ofpbuf *, const struct flow *mask,
                             size_t max_mpls_depth, bool recirc);
 
 uint32_t odp_flow_key_hash(const struct nlattr *, size_t);
+
+int odp_ufid_from_string(const char *s_, ovs_u128 *ufid);
 void odp_ufid_to_nlattrs(struct ofpbuf *, const ovs_u128 *, uint32_t flags);
 void odp_format_ufid(const ovs_u128 *ufid, struct ds *);
 
-- 
1.7.10.4




More information about the dev mailing list