[ovs-dev] [PATCH 1/2] flow: Factor out flag parsing and formatting routines.

Jesse Gross jesse at nicira.com
Mon Jul 13 21:53:56 UTC 2015


There are several implementations of functions that parse/format
flags and their binary representation. This factors them out into
common routines. In addition to reducing code, it also makes things
more consistent across different parts of OVS.

Signed-off-by: Jesse Gross <jesse at nicira.com>
---
 lib/flow.c            | 157 +++++++++++++++++++++++++++++++++++++++++++++++++-
 lib/flow.h            |   5 +-
 lib/match.c           |  17 +-----
 lib/meta-flow.c       | 154 +++++++++----------------------------------------
 lib/odp-util.c        | 155 ++++++-------------------------------------------
 tests/odp.at          |   8 +--
 tests/ofproto-dpif.at |   2 +-
 tests/ovs-ofctl.at    |  13 -----
 tests/tunnel.at       |  40 ++++++-------
 9 files changed, 233 insertions(+), 318 deletions(-)

diff --git a/lib/flow.c b/lib/flow.c
index 3669228..80dcfcb 100644
--- a/lib/flow.c
+++ b/lib/flow.c
@@ -864,11 +864,22 @@ format_flags(struct ds *ds, const char *(*bit_to_string)(uint32_t),
 void
 format_flags_masked(struct ds *ds, const char *name,
                     const char *(*bit_to_string)(uint32_t), uint32_t flags,
-                    uint32_t mask)
+                    uint32_t mask, uint32_t max_mask)
 {
     if (name) {
         ds_put_format(ds, "%s=", name);
     }
+
+    if (mask == max_mask) {
+        if (flags) {
+            format_flags(ds, bit_to_string, flags, '|');
+        } else {
+            ds_put_char(ds, '0');
+        }
+
+        return;
+    }
+
     while (mask) {
         uint32_t bit = rightmost_1bit(mask);
         const char *s = bit_to_string(bit);
@@ -879,6 +890,150 @@ format_flags_masked(struct ds *ds, const char *name,
     }
 }
 
+int
+parse_flags(const char *s, const char *(*bit_to_string)(uint32_t),
+            char end, const char *field_name, char **res_string,
+            uint32_t *res_flags, uint32_t allowed, uint32_t *res_mask)
+{
+    uint32_t result = 0;
+    int n;
+
+    /* Parse masked flags in numeric format? */
+    if (res_mask && ovs_scan(s, "%"SCNi32"/%"SCNi32"%n",
+                             res_flags, res_mask, &n) && n > 0) {
+        if (*res_flags & ~allowed || *res_mask & ~allowed) {
+            goto unknown;
+        }
+        return n;
+    }
+
+    n = 0;
+
+    if (res_mask && (*s == '+' || *s == '-')) {
+        uint32_t flags = 0, mask = 0;
+
+        /* Parse masked flags. */
+        while (s[0] != end) {
+            bool set;
+            uint32_t bit;
+            size_t len;
+
+            if (s[0] == '+') {
+                set = true;
+            } else if (s[0] == '-') {
+                set = false;
+            } else {
+                if (res_string) {
+                    *res_string = xasprintf("%s: %s must be preceed by '+' "
+                                            "(for SET) or '-' (NOT SET)", s,
+                                            field_name);
+                }
+                return -EINVAL;
+            }
+            s++;
+            n++;
+
+            for (bit = 1; bit; bit <<= 1) {
+                const char *fname = bit_to_string(bit);
+
+                if (!fname) {
+                    continue;
+                }
+
+                len = strlen(fname);
+                if (strncmp(s, fname, len) ||
+                    (s[len] != '+' && s[len] != '-' && s[len] != end)) {
+                    continue;
+                }
+
+                if (mask & bit) {
+                    /* bit already set. */
+                    if (res_string) {
+                        *res_string = xasprintf("%s: Each %s flag can be "
+                                                "specified only once", s,
+                                                field_name);
+                    }
+                    return -EINVAL;
+                }
+                if (!(bit & allowed)) {
+                    goto unknown;
+                }
+                if (set) {
+                   flags |= bit;
+                }
+                mask |= bit;
+                break;
+            }
+
+            if (!bit) {
+                goto unknown;
+            }
+            s += len;
+            n += len;
+        }
+
+        *res_flags = flags;
+        *res_mask = mask;
+        return n;
+    }
+
+    /* Parse unmasked flags.  If a flag is present, it is set, otherwise
+     * it is not set. */
+    while (s[n] != end) {
+        unsigned long long int flags;
+        uint32_t bit;
+        int n0;
+
+        if (ovs_scan(&s[n], "%lli%n", &flags, &n0)) {
+            if (flags & ~allowed) {
+                goto unknown;
+            }
+            n += n0 + (s[n + n0] == '|');
+            result |= flags;
+            continue;
+        }
+
+        for (bit = 1; bit; bit <<= 1) {
+            const char *name = bit_to_string(bit);
+            size_t len;
+
+            if (!name) {
+                continue;
+            }
+
+            len = strlen(name);
+            if (!strncmp(s + n, name, len) &&
+                (s[n + len] == '|' || s[n + len] == end)) {
+                if (!(bit & allowed)) {
+                    goto unknown;
+                }
+                result |= bit;
+                n += len + (s[n + len] == '|');
+                break;
+            }
+        }
+
+        if (!bit) {
+            goto unknown;
+        }
+    }
+
+    *res_flags = result;
+    if (res_mask) {
+        *res_mask = UINT32_MAX;
+    }
+    if (res_string) {
+        *res_string = NULL;
+    }
+    return n;
+
+unknown:
+    if (res_string) {
+        *res_string = xasprintf("%s: unknown %s flag(s)", s, field_name);
+    }
+    return -EINVAL;
+}
+
 void
 flow_format(struct ds *ds, const struct flow *flow)
 {
diff --git a/lib/flow.h b/lib/flow.h
index 9779085..b961746 100644
--- a/lib/flow.h
+++ b/lib/flow.h
@@ -191,7 +191,10 @@ void format_flags(struct ds *ds, const char *(*bit_to_string)(uint32_t),
                   uint32_t flags, char del);
 void format_flags_masked(struct ds *ds, const char *name,
                          const char *(*bit_to_string)(uint32_t),
-                         uint32_t flags, uint32_t mask);
+                         uint32_t flags, uint32_t mask, uint32_t max_mask);
+int parse_flags(const char *s, const char *(*bit_to_string)(uint32_t),
+                char end, const char *field_name, char **res_string,
+                uint32_t *res_flags, uint32_t allowed, uint32_t *res_mask);
 
 void flow_format(struct ds *, const struct flow *);
 void flow_print(FILE *, const struct flow *);
diff --git a/lib/match.c b/lib/match.c
index ca9492f..6fd62e0 100644
--- a/lib/match.c
+++ b/lib/match.c
@@ -1150,20 +1150,9 @@ match_format(const struct match *match, struct ds *s, int priority)
         format_be16_masked(s, "tp_dst", f->tp_dst, wc->masks.tp_dst);
     }
     if (is_ip_any(f) && f->nw_proto == IPPROTO_TCP && wc->masks.tcp_flags) {
-        uint16_t mask = TCP_FLAGS(wc->masks.tcp_flags);
-
-        if (mask == TCP_FLAGS(OVS_BE16_MAX)) {
-            ds_put_cstr(s, "tcp_flags=");
-            if (f->tcp_flags) {
-                format_flags(s, packet_tcp_flag_to_string, ntohs(f->tcp_flags),
-                             '|');
-            } else {
-                ds_put_cstr(s, "0"); /* Zero flags. */
-            }
-        } else if (mask) {
-            format_flags_masked(s, "tcp_flags", packet_tcp_flag_to_string,
-                                ntohs(f->tcp_flags), mask);
-        }
+        format_flags_masked(s, "tcp_flags", packet_tcp_flag_to_string,
+                            ntohs(f->tcp_flags), TCP_FLAGS(wc->masks.tcp_flags),
+                            TCP_FLAGS(OVS_BE16_MAX));
     }
 
     if (s->length > start_len) {
diff --git a/lib/meta-flow.c b/lib/meta-flow.c
index 21a13b4..e2a31e7 100644
--- a/lib/meta-flow.c
+++ b/lib/meta-flow.c
@@ -2014,144 +2014,44 @@ mf_from_frag_string(const char *s, uint8_t *valuep, uint8_t *maskp)
                      "\"yes\", \"first\", \"later\", \"not_first\"", s);
 }
 
-static int
-parse_flow_tun_flags(const char *s_, const char *(*bit_to_string)(uint32_t),
-                     ovs_be16 *res)
+static char *
+parse_mf_flags(const char *s, const char *(*bit_to_string)(uint32_t),
+               const char *field_name, ovs_be16 *flagsp, ovs_be16 allowed,
+               ovs_be16 *maskp)
 {
-    uint32_t result = 0;
-    char *save_ptr = NULL;
-    char *name;
-    int rc = 0;
-    char *s = xstrdup(s_);
-
-    for (name = strtok_r((char *)s, " |", &save_ptr); name;
-         name = strtok_r(NULL, " |", &save_ptr)) {
-        int name_len;
-        unsigned long long int flags;
-        uint32_t bit;
-
-        if (ovs_scan(name, "%lli", &flags)) {
-            result |= flags;
-            continue;
-        }
-        name_len = strlen(name);
-        for (bit = 1; bit; bit <<= 1) {
-            const char *fname = bit_to_string(bit);
-            size_t len;
-
-            if (!fname) {
-                continue;
-            }
+    int err;
+    char *err_str;
+    uint32_t flags, mask;
 
-            len = strlen(fname);
-            if (len != name_len) {
-                continue;
-            }
-            if (!strncmp(name, fname, len)) {
-                result |= bit;
-                break;
-            }
-        }
+    err = parse_flags(s, bit_to_string, '\0', field_name, &err_str,
+                      &flags, ntohs(allowed), maskp ? &mask : NULL);
+    if (err < 0) {
+        return err_str;
+    }
 
-        if (!bit) {
-            rc = -ENOENT;
-            goto out;
-        }
+    *flagsp = htons(flags);
+    if (maskp) {
+        *maskp = htons(mask);
     }
 
-    *res = htons(result);
-out:
-    free(s);
-    return rc;
+    return NULL;
 }
 
 static char *
-mf_from_tun_flags_string(const char *s, ovs_be16 *valuep, ovs_be16 *maskp)
+mf_from_tcp_flags_string(const char *s, ovs_be16 *flagsp, ovs_be16 *maskp)
 {
-    if (!parse_flow_tun_flags(s, flow_tun_flag_to_string, valuep)) {
-        *maskp = OVS_BE16_MAX;
-        return NULL;
-    }
-
-    return xasprintf("%s: unknown tunnel flags (valid flags are \"df\", "
-                     "\"csum\", \"key\")", s);
+    return parse_mf_flags(s, packet_tcp_flag_to_string, "TCP", flagsp,
+                          TCP_FLAGS_BE16(OVS_BE16_MAX), maskp);
 }
 
 static char *
-mf_from_tcp_flags_string(const char *s, ovs_be16 *flagsp, ovs_be16 *maskp)
+mf_from_tun_flags_string(const char *s, ovs_be16 *flagsp, ovs_be16 *maskp)
 {
-    uint16_t flags = 0;
-    uint16_t mask = 0;
-    uint16_t bit;
-    int n;
-
-    if (ovs_scan(s, "%"SCNi16"/%"SCNi16"%n", &flags, &mask, &n) && !s[n]) {
-        *flagsp = htons(flags);
-        *maskp = htons(mask);
-        return NULL;
-    }
-    if (ovs_scan(s, "%"SCNi16"%n", &flags, &n) && !s[n]) {
-        *flagsp = htons(flags);
-        *maskp = OVS_BE16_MAX;
-        return NULL;
-    }
-
-    while (*s != '\0') {
-        bool set;
-        int name_len;
-
-        switch (*s) {
-        case '+':
-            set = true;
-            break;
-        case '-':
-            set = false;
-            break;
-        default:
-            return xasprintf("%s: TCP flag must be preceded by '+' (for SET) "
-                             "or '-' (NOT SET)", s);
-        }
-        s++;
-
-        name_len = strcspn(s,"+-");
-
-        for (bit = 1; bit; bit <<= 1) {
-            const char *fname = packet_tcp_flag_to_string(bit);
-            size_t len;
-
-            if (!fname) {
-                continue;
-            }
-
-            len = strlen(fname);
-            if (len != name_len) {
-                continue;
-            }
-            if (!strncmp(s, fname, len)) {
-                if (mask & bit) {
-                    return xasprintf("%s: Each TCP flag can be specified only "
-                                     "once", s);
-                }
-                if (set) {
-                    flags |= bit;
-                }
-                mask |= bit;
-                break;
-            }
-        }
-
-        if (!bit) {
-            return xasprintf("%s: unknown TCP flag(s)", s);
-        }
-        s += name_len;
-    }
-
-    *flagsp = htons(flags);
-    *maskp = htons(mask);
-    return NULL;
+    *maskp = OVS_BE16_MAX;
+    return parse_mf_flags(s, flow_tun_flag_to_string, "tunnel", flagsp,
+                          htons(FLOW_TNL_F_MASK), NULL);
 }
 
-
 /* Parses 's', a string value for field 'mf', into 'value' and 'mask'.  Returns
  * NULL if successful, otherwise a malloc()'d string describing the error. */
 char *
@@ -2280,16 +2180,16 @@ mf_format_frag_string(uint8_t value, uint8_t mask, struct ds *s)
 }
 
 static void
-mf_format_tnl_flags_string(const ovs_be16 *valuep, struct ds *s)
+mf_format_tnl_flags_string(ovs_be16 value, struct ds *s)
 {
-    format_flags(s, flow_tun_flag_to_string, ntohs(*valuep), '|');
+    format_flags(s, flow_tun_flag_to_string, ntohs(value), '|');
 }
 
 static void
 mf_format_tcp_flags_string(ovs_be16 value, ovs_be16 mask, struct ds *s)
 {
     format_flags_masked(s, NULL, packet_tcp_flag_to_string, ntohs(value),
-                        TCP_FLAGS(mask));
+                        TCP_FLAGS(mask), TCP_FLAGS(OVS_BE16_MAX));
 }
 
 /* Appends to 's' a string representation of field 'mf' whose value is in
@@ -2345,7 +2245,7 @@ mf_format(const struct mf_field *mf,
         break;
 
     case MFS_TNL_FLAGS:
-        mf_format_tnl_flags_string(&value->be16, s);
+        mf_format_tnl_flags_string(value->be16, s);
         break;
 
     case MFS_TCP_FLAGS:
diff --git a/lib/odp-util.c b/lib/odp-util.c
index 2eddb34..0e82b12 100644
--- a/lib/odp-util.c
+++ b/lib/odp-util.c
@@ -235,130 +235,11 @@ slow_path_reason_to_explanation(enum slow_path_reason reason)
 }
 
 static int
-parse_flags(const char *s, const char *(*bit_to_string)(uint32_t),
-            uint32_t *res_flags, uint32_t allowed, uint32_t *res_mask)
+parse_odp_flags(const char *s, const char *(*bit_to_string)(uint32_t),
+                uint32_t *res_flags, uint32_t allowed, uint32_t *res_mask)
 {
-    uint32_t result = 0;
-    int n;
-
-    /* Parse masked flags in numeric format? */
-    if (res_mask && ovs_scan(s, "%"SCNi32"/%"SCNi32"%n",
-                             res_flags, res_mask, &n) && n > 0) {
-        if (*res_flags & ~allowed || *res_mask & ~allowed) {
-            return -EINVAL;
-        }
-        return n;
-    }
-
-    n = 0;
-
-    if (res_mask && (*s == '+' || *s == '-')) {
-        uint32_t flags = 0, mask = 0;
-
-        /* Parse masked flags. */
-        while (s[0] != ')') {
-            bool set;
-            uint32_t bit;
-            int name_len;
-
-            if (s[0] == '+') {
-                set = true;
-            } else if (s[0] == '-') {
-                set = false;
-            } else {
-                return -EINVAL;
-            }
-            s++;
-            n++;
-
-            name_len = strcspn(s, "+-)");
-
-            for (bit = 1; bit; bit <<= 1) {
-                const char *fname = bit_to_string(bit);
-                size_t len;
-
-                if (!fname) {
-                    continue;
-                }
-
-                len = strlen(fname);
-                if (len != name_len) {
-                    continue;
-                }
-                if (!strncmp(s, fname, len)) {
-                    if (mask & bit) {
-                        /* bit already set. */
-                        return -EINVAL;
-                    }
-                    if (!(bit & allowed)) {
-                        return -EINVAL;
-                    }
-                    if (set) {
-                        flags |= bit;
-                    }
-                    mask |= bit;
-                    break;
-                }
-            }
-
-            if (!bit) {
-                return -EINVAL; /* Unknown flag name */
-            }
-            s += name_len;
-            n += name_len;
-        }
-
-        *res_flags = flags;
-        *res_mask = mask;
-        return n;
-    }
-
-    /* Parse unmasked flags.  If a flag is present, it is set, otherwise
-     * it is not set. */
-    while (s[n] != ')') {
-        unsigned long long int flags;
-        uint32_t bit;
-        int n0;
-
-        if (ovs_scan(&s[n], "%lli%n", &flags, &n0)) {
-            if (flags & ~allowed) {
-                return -EINVAL;
-            }
-            n += n0 + (s[n + n0] == ',');
-            result |= flags;
-            continue;
-        }
-
-        for (bit = 1; bit; bit <<= 1) {
-            const char *name = bit_to_string(bit);
-            size_t len;
-
-            if (!name) {
-                continue;
-            }
-
-            len = strlen(name);
-            if (!strncmp(s + n, name, len) &&
-                (s[n + len] == ',' || s[n + len] == ')')) {
-                if (!(bit & allowed)) {
-                    return -EINVAL;
-                }
-                result |= bit;
-                n += len + (s[n + len] == ',');
-                break;
-            }
-        }
-
-        if (!bit) {
-            return -EINVAL;
-        }
-    }
-
-    *res_flags = result;
-    if (res_mask) {
-        *res_mask = UINT32_MAX;
-    }
-    return n;
+    return parse_flags(s, bit_to_string, ')', NULL, NULL,
+                       res_flags, allowed, res_mask);
 }
 
 static void
@@ -823,9 +704,9 @@ parse_odp_userspace_action(const char *s, struct ofpbuf *actions)
             cookie.slow_path.unused = 0;
             cookie.slow_path.reason = 0;
 
-            res = parse_flags(&s[n], slow_path_reason_to_string,
-                              &cookie.slow_path.reason,
-                              SLOW_PATH_REASON_MASK, NULL);
+            res = parse_odp_flags(&s[n], slow_path_reason_to_string,
+                                  &cookie.slow_path.reason,
+                                  SLOW_PATH_REASON_MASK, NULL);
             if (res < 0 || s[n + res] != ')') {
                 return res;
             }
@@ -1791,14 +1672,13 @@ format_tun_flags(struct ds *ds, const char *name, uint16_t key,
     bool mask_empty = mask && !*mask;
 
     if (verbose || !mask_empty) {
-        bool mask_full = !mask || (*mask & FLOW_TNL_F_MASK) == FLOW_TNL_F_MASK;
-
         ds_put_cstr(ds, name);
         ds_put_char(ds, '(');
-        if (!mask_full) { /* Partially masked. */
-            format_flags_masked(ds, NULL, flow_tun_flag_to_string, key, *mask);
+        if (mask) {
+            format_flags_masked(ds, NULL, flow_tun_flag_to_string, key,
+                                *mask & FLOW_TNL_F_MASK, FLOW_TNL_F_MASK);
         } else { /* Fully masked. */
-            format_flags(ds, flow_tun_flag_to_string, key, ',');
+            format_flags(ds, flow_tun_flag_to_string, key, '|');
         }
         ds_put_cstr(ds, "),");
     }
@@ -2277,10 +2157,11 @@ format_odp_key_attr(const struct nlattr *a, const struct nlattr *ma,
         if (!is_exact) {
             format_flags_masked(ds, NULL, packet_tcp_flag_to_string,
                                 ntohs(nl_attr_get_be16(a)),
-                                ntohs(nl_attr_get_be16(ma)));
+                                TCP_FLAGS(nl_attr_get_be16(ma)),
+                                TCP_FLAGS(OVS_BE16_MAX));
         } else {
             format_flags(ds, packet_tcp_flag_to_string,
-                         ntohs(nl_attr_get_be16(a)), ',');
+                         ntohs(nl_attr_get_be16(a)), '|');
         }
         break;
 
@@ -2680,8 +2561,8 @@ scan_tun_flags(const char *s, uint16_t *key, uint16_t *mask)
     uint32_t flags, fmask;
     int n;
 
-    n = parse_flags(s, flow_tun_flag_to_string, &flags,
-                    FLOW_TNL_F_MASK, mask ? &fmask : NULL);
+    n = parse_odp_flags(s, flow_tun_flag_to_string, &flags,
+                        FLOW_TNL_F_MASK, mask ? &fmask : NULL);
     if (n >= 0 && s[n] == ')') {
         *key = flags;
         if (mask) {
@@ -2698,8 +2579,8 @@ scan_tcp_flags(const char *s, ovs_be16 *key, ovs_be16 *mask)
     uint32_t flags, fmask;
     int n;
 
-    n = parse_flags(s, packet_tcp_flag_to_string, &flags,
-                    TCP_FLAGS(OVS_BE16_MAX), mask ? &fmask : NULL);
+    n = parse_odp_flags(s, packet_tcp_flag_to_string, &flags,
+                        TCP_FLAGS(OVS_BE16_MAX), mask ? &fmask : NULL);
     if (n >= 0) {
         *key = htons(flags);
         if (mask) {
diff --git a/tests/odp.at b/tests/odp.at
index 090b976..1d8b915 100644
--- a/tests/odp.at
+++ b/tests/odp.at
@@ -39,7 +39,7 @@ s/^/skb_priority(0),skb_mark(0),recirc_id(0),dp_hash(0),/
 
  echo
  echo '# Valid forms with tunnel header.'
- sed 's/^/skb_priority(0),tunnel(tun_id=0x7f10354,src=10.10.10.10,dst=20.20.20.20,ttl=64,flags(csum,key)),skb_mark(0x1234),recirc_id(0),dp_hash(0),/' odp-base.txt
+ sed 's/^/skb_priority(0),tunnel(tun_id=0x7f10354,src=10.10.10.10,dst=20.20.20.20,ttl=64,flags(csum|key)),skb_mark(0x1234),recirc_id(0),dp_hash(0),/' odp-base.txt
 
  echo
  echo '# Valid forms with VLAN header.'
@@ -117,7 +117,7 @@ skb_mark(0x1234/0xfff0),in_port(1),eth(src=00:01:02:03:04:05,dst=10:11:12:13:14:
 
  echo
  echo '# Valid forms with tunnel header.'
- sed 's/^/tunnel(tun_id=0x7f10354\/0xff,src=10.10.10.10\/255.255.255.0,dst=20.20.20.20\/255.255.255.0,ttl=64,vxlan(gbp(id=10\/0xff,flags=0xb)),flags(csum,key)),/' odp-base.txt
+ sed 's/^/tunnel(tun_id=0x7f10354\/0xff,src=10.10.10.10\/255.255.255.0,dst=20.20.20.20\/255.255.255.0,ttl=64,vxlan(gbp(id=10\/0xff,flags=0xb)),flags(csum|key)),/' odp-base.txt
 
  echo
  echo '# Valid forms with tunnel header (wildcard flag).'
@@ -125,7 +125,7 @@ skb_mark(0x1234/0xfff0),in_port(1),eth(src=00:01:02:03:04:05,dst=10:11:12:13:14:
 
  echo
  echo '# Valid forms with Geneve header.'
- sed 's/^/tunnel(tun_id=0x7f10354\/0xff,src=10.10.10.10\/255.255.255.0,dst=20.20.20.20\/255.255.255.0,ttl=64,geneve({class=0,type=0,len=4,0xa\/0xff}{class=0xffff,type=0x1,len=4,0xffffffff}),flags(csum,key)),/' odp-base.txt
+ sed 's/^/tunnel(tun_id=0x7f10354\/0xff,src=10.10.10.10\/255.255.255.0,dst=20.20.20.20\/255.255.255.0,ttl=64,geneve({class=0,type=0,len=4,0xa\/0xff}{class=0xffff,type=0x1,len=4,0xffffffff}),flags(csum|key)),/' odp-base.txt
 
  echo
  echo '# Valid forms with VLAN header.'
@@ -284,7 +284,7 @@ push_vlan(tpid=0x9100,vid=13,pcp=5)
 push_vlan(tpid=0x9100,vid=13,pcp=5,cfi=0)
 pop_vlan
 sample(sample=9.7%,actions(1,2,3,push_vlan(vid=1,pcp=2)))
-set(tunnel(tun_id=0xabcdef1234567890,src=1.1.1.1,dst=2.2.2.2,ttl=64,flags(df,csum,key)))
+set(tunnel(tun_id=0xabcdef1234567890,src=1.1.1.1,dst=2.2.2.2,ttl=64,flags(df|csum|key)))
 set(tunnel(tun_id=0xabcdef1234567890,src=1.1.1.1,dst=2.2.2.2,ttl=64,flags(key)))
 tnl_pop(4)
 tnl_push(tnl_port(4),header(size=42,type=3,eth(dst=f8:bc:12:44:34:b6,src=f8:bc:12:46:58:e0,dl_type=0x0800),ipv4(src=1.1.2.88,dst=1.1.2.92,proto=47,tos=0,ttl=64,frag=0x40),gre((flags=0x2000,proto=0x6558),key=0x1e241)),out_port(1))
diff --git a/tests/ofproto-dpif.at b/tests/ofproto-dpif.at
index cbf5737..f9d92e0 100644
--- a/tests/ofproto-dpif.at
+++ b/tests/ofproto-dpif.at
@@ -960,7 +960,7 @@ AT_CHECK([ovs-ofctl -OOpenFlow12 add-flow br0 'table=0 actions=goto_table(1)'])
 AT_CHECK([ovs-ofctl monitor -P openflow10 br0 65534 --detach --no-chdir --pidfile 2> ofctl_monitor.log])
 
 for i in 1 2 3 ; do
-    ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=9),tcp_flags(urg,rst)'
+    ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=9),tcp_flags(urg|rst)'
 done
 OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 6])
 OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit])
diff --git a/tests/ovs-ofctl.at b/tests/ovs-ofctl.at
index 28bca14..b4e638b 100644
--- a/tests/ovs-ofctl.at
+++ b/tests/ovs-ofctl.at
@@ -10,7 +10,6 @@ for test_case in \
     'tun_dst=1.2.3.4                             NXM,OXM' \
     'tun_dst=1.2.3.4/0.0.0.1                     NXM,OXM' \
     'tun_flags=0                                 none' \
-    'tun_flags=1/1                               none' \
     'tun_tos=0                                   none' \
     'tun_ttl=0                                   none' \
     'tun_gbp_id=0                                NXM,OXM' \
@@ -303,18 +302,6 @@ AT_CHECK([ovs-ofctl --protocols OpenFlow11 add-flow br0 'ip actions=mod_tp_dst:1
 ])
 AT_CLEANUP
 
-AT_SETUP([ovs-ofctl parse-flows (With Tunnel-Parameters)])
-AT_DATA([flows.txt], [[
-tun_id=0x1234000056780000/0xffff0000ffff0000,tun_src=1.1.1.1,tun_dst=2.2.2.2,tun_tos=0x3,tun_ttl=20,tun_flags=key|csum actions=drop
-]])
-
-AT_CHECK([ovs-ofctl parse-flows flows.txt
-], [1], [usable protocols: none
-], [stderr])
-
-AT_CLEANUP
-
-
 AT_SETUP([ovs-ofctl parse-flows (skb_priority)])
 AT_DATA([flows.txt], [[
 skb_priority=0x12341234,tcp,tp_src=123,actions=flood
diff --git a/tests/tunnel.at b/tests/tunnel.at
index ce4cb1e..b22a621 100644
--- a/tests/tunnel.at
+++ b/tests/tunnel.at
@@ -131,13 +131,13 @@ AT_CHECK([ovs-appctl dpif/show | tail -n +3], [0], [dnl
 dnl Basic
 AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(2),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=4,ttl=128,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
 AT_CHECK([tail -1 stdout], [0],
-  [Datapath actions: set(tunnel(tun_id=0x5,src=2.2.2.2,dst=1.1.1.1,ttl=64,flags(df,key))),1
+  [Datapath actions: set(tunnel(tun_id=0x5,src=2.2.2.2,dst=1.1.1.1,ttl=64,flags(df|key))),1
 ])
 
 dnl ECN
 AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(2),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=1,ttl=64,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
 AT_CHECK([tail -1 stdout], [0],
-  [Datapath actions: set(tunnel(tun_id=0x5,src=2.2.2.2,dst=1.1.1.1,tos=0x1,ttl=64,flags(df,key))),1
+  [Datapath actions: set(tunnel(tun_id=0x5,src=2.2.2.2,dst=1.1.1.1,tos=0x1,ttl=64,flags(df|key))),1
 ])
 OVS_VSWITCHD_STOP
 AT_CLEANUP
@@ -208,10 +208,10 @@ AT_CHECK([ovs-appctl dpif/show | tail -n +3], [0], [dnl
 
 AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(100),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)'], [0], [stdout])
 AT_CHECK([tail -1 stdout], [0], [Datapath actions: dnl
-set(tunnel(tun_id=0x1,dst=1.1.1.1,ttl=64,flags(df,key))),1,dnl
-set(tunnel(tun_id=0x2,dst=2.2.2.2,ttl=64,flags(df,key))),1,dnl
-set(tunnel(tun_id=0x3,dst=3.3.3.3,ttl=64,flags(df,key))),1,dnl
-set(tunnel(tun_id=0x5,dst=4.4.4.4,ttl=64,flags(df,key))),1
+set(tunnel(tun_id=0x1,dst=1.1.1.1,ttl=64,flags(df|key))),1,dnl
+set(tunnel(tun_id=0x2,dst=2.2.2.2,ttl=64,flags(df|key))),1,dnl
+set(tunnel(tun_id=0x3,dst=3.3.3.3,ttl=64,flags(df|key))),1,dnl
+set(tunnel(tun_id=0x5,dst=4.4.4.4,ttl=64,flags(df|key))),1
 ])
 OVS_VSWITCHD_STOP
 AT_CLEANUP
@@ -240,23 +240,23 @@ AT_CHECK([ovs-appctl dpif/show | tail -n +3], [0], [dnl
 
 AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'tunnel(tun_id=0x1,src=1.1.1.1,dst=2.2.2.2,ttl=64,flags(key)),in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
 AT_CHECK([tail -1 stdout], [0], [Datapath actions: dnl
-set(tunnel(tun_id=0x1,dst=1.1.1.1,ttl=64,flags(df,key))),1,dnl
-set(tunnel(tun_id=0x3,dst=1.1.1.1,ttl=64,flags(df,key))),1,dnl
-set(tunnel(tun_id=0x5,dst=1.1.1.1,ttl=64,flags(df,key))),1
+set(tunnel(tun_id=0x1,dst=1.1.1.1,ttl=64,flags(df|key))),1,dnl
+set(tunnel(tun_id=0x3,dst=1.1.1.1,ttl=64,flags(df|key))),1,dnl
+set(tunnel(tun_id=0x5,dst=1.1.1.1,ttl=64,flags(df|key))),1
 ])
 
 AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'tunnel(tun_id=0x2,src=1.1.1.1,dst=2.2.2.2,ttl=64,flags(key)),in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
 AT_CHECK([tail -1 stdout], [0], [Datapath actions: dnl
-set(tunnel(tun_id=0x3,dst=1.1.1.1,ttl=64,flags(df,key))),1,dnl
-set(tunnel(tun_id=0x1,dst=1.1.1.1,ttl=64,flags(df,key))),1,dnl
-set(tunnel(tun_id=0x5,dst=1.1.1.1,ttl=64,flags(df,key))),1
+set(tunnel(tun_id=0x3,dst=1.1.1.1,ttl=64,flags(df|key))),1,dnl
+set(tunnel(tun_id=0x1,dst=1.1.1.1,ttl=64,flags(df|key))),1,dnl
+set(tunnel(tun_id=0x5,dst=1.1.1.1,ttl=64,flags(df|key))),1
 ])
 
 AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'tunnel(src=1.1.1.1,dst=2.2.2.2,ttl=64,flags()),in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
 AT_CHECK([tail -1 stdout], [0], [Datapath actions: dnl
-set(tunnel(tun_id=0x5,dst=1.1.1.1,ttl=64,flags(df,key))),1,dnl
-set(tunnel(tun_id=0x1,dst=1.1.1.1,ttl=64,flags(df,key))),1,dnl
-set(tunnel(tun_id=0x3,dst=1.1.1.1,ttl=64,flags(df,key))),1
+set(tunnel(tun_id=0x5,dst=1.1.1.1,ttl=64,flags(df|key))),1,dnl
+set(tunnel(tun_id=0x1,dst=1.1.1.1,ttl=64,flags(df|key))),1,dnl
+set(tunnel(tun_id=0x3,dst=1.1.1.1,ttl=64,flags(df|key))),1
 ])
 
 AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'tunnel(tun_id=0xf,src=1.1.1.1,dst=2.2.2.2,ttl=64,flags(key)),in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=9)'], [2], [ignore], [dnl
@@ -300,7 +300,7 @@ Datapath actions: 3
 
 AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'tunnel(tun_id=0x3,src=1.1.1.1,dst=2.2.2.2,ttl=64,flags(key)),in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
 AT_CHECK([tail -1 stdout], [0], [dnl
-Datapath actions: 4,3,set(tunnel(tun_id=0x3,dst=3.3.3.3,ttl=64,flags(df,key))),1,5
+Datapath actions: 4,3,set(tunnel(tun_id=0x3,dst=3.3.3.3,ttl=64,flags(df|key))),1,5
 ])
 
 AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'tunnel(tun_id=0x3,src=3.3.3.3,dst=2.2.2.2,ttl=64,flags(key)),in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
@@ -407,7 +407,7 @@ in_port=5 actions=set_field:5->tun_id
 AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
 AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(90),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)'], [0], [stdout])
 AT_CHECK([tail -1 stdout], [0],
-  [Datapath actions: set(tunnel(tun_id=0x2a,dst=1.1.1.1,ttl=64,flags(df,key))),1,set(tunnel(tun_id=0x2a,dst=3.3.3.3,ttl=64,flags(df,key))),1,set(tunnel(tun_id=0x2a,src=1.1.1.1,dst=4.4.4.4,ttl=64,flags(df,key))),1,set(tunnel(tun_id=0x3,dst=2.2.2.2,ttl=64,flags(df,key))),1
+  [Datapath actions: set(tunnel(tun_id=0x2a,dst=1.1.1.1,ttl=64,flags(df|key))),1,set(tunnel(tun_id=0x2a,dst=3.3.3.3,ttl=64,flags(df|key))),1,set(tunnel(tun_id=0x2a,src=1.1.1.1,dst=4.4.4.4,ttl=64,flags(df|key))),1,set(tunnel(tun_id=0x3,dst=2.2.2.2,ttl=64,flags(df|key))),1
 ])
 OVS_VSWITCHD_STOP
 AT_CLEANUP
@@ -434,14 +434,14 @@ AT_CHECK([tail -1 stdout], [0],
 ])
 
 dnl Option match
-AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'recirc_id(0),tunnel(tun_id=0x0,src=1.1.1.1,dst=1.1.1.2,ttl=64,geneve({class=0xffff,type=0,len=4,0xb}),flags(df,key)),in_port(6081),skb_mark(0),eth_type(0x0800),ipv4(frag=no)'], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'recirc_id(0),tunnel(tun_id=0x0,src=1.1.1.1,dst=1.1.1.2,ttl=64,geneve({class=0xffff,type=0,len=4,0xb}),flags(df|key)),in_port(6081),skb_mark(0),eth_type(0x0800),ipv4(frag=no)'], [0], [stdout])
 AT_CHECK([tail -2 stdout], [0],
   [Megaflow: pkt_mark=0,recirc_id=0,ip,tun_id=0,tun_src=1.1.1.1,tun_dst=1.1.1.2,tun_tos=0,tun_ttl=64,df|key,tun_metadata0=0xb/0xf,in_port=1,nw_frag=no
 Datapath actions: 2
 ])
 
 dnl Skip unknown option
-AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'recirc_id(0),tunnel(tun_id=0x0,src=1.1.1.1,dst=1.1.1.2,ttl=64,geneve({class=0xffff,type=0,len=4,0xb}{class=0xffff,type=2,len=4,0xc}),flags(df,key)),in_port(6081),skb_mark(0),eth_type(0x0800),ipv4(frag=no)'], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'recirc_id(0),tunnel(tun_id=0x0,src=1.1.1.1,dst=1.1.1.2,ttl=64,geneve({class=0xffff,type=0,len=4,0xb}{class=0xffff,type=2,len=4,0xc}),flags(df|key)),in_port(6081),skb_mark(0),eth_type(0x0800),ipv4(frag=no)'], [0], [stdout])
 AT_CHECK([tail -2 stdout], [0],
   [Megaflow: pkt_mark=0,recirc_id=0,ip,tun_id=0,tun_src=1.1.1.1,tun_dst=1.1.1.2,tun_tos=0,tun_ttl=64,df|key,tun_metadata0=0xb/0xf,in_port=1,nw_frag=no
 Datapath actions: 2
@@ -466,7 +466,7 @@ AT_CHECK([ovs-ofctl del-geneve-map br0 "{class=0xffff,type=3,len=4}->tun_metadat
 AT_CHECK([ovs-ofctl add-geneve-map br0 "{class=0xffff,type=3,len=8}->tun_metadata3"])
 
 AT_CHECK([ovs-ofctl add-flow br0 tun_metadata3=0x1234567890abcdef,actions=2])
-AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'recirc_id(0),tunnel(tun_id=0x0,src=1.1.1.1,dst=1.1.1.2,ttl=64,geneve({class=0xffff,type=3,len=8,0x1234567890abcdef}),flags(df,key)),in_port(6081),skb_mark(0),eth_type(0x0800),ipv4(frag=no)'], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'recirc_id(0),tunnel(tun_id=0x0,src=1.1.1.1,dst=1.1.1.2,ttl=64,geneve({class=0xffff,type=3,len=8,0x1234567890abcdef}),flags(df|key)),in_port(6081),skb_mark(0),eth_type(0x0800),ipv4(frag=no)'], [0], [stdout])
 AT_CHECK([tail -2 stdout], [0],
   [Megaflow: pkt_mark=0,recirc_id=0,ip,tun_id=0,tun_src=1.1.1.1,tun_dst=1.1.1.2,tun_tos=0,tun_ttl=64,df|key,tun_metadata0=0/0xf,tun_metadata3=0x1234567890abcdef,in_port=1,nw_frag=no
 Datapath actions: 2
-- 
2.1.4




More information about the dev mailing list