diff options
author | Jesse Gross <jesse@nicira.com> | 2015-07-11 20:48:29 -0700 |
---|---|---|
committer | Jesse Gross <jesse@nicira.com> | 2015-07-15 20:24:04 -0700 |
commit | 8e4c1621e939cd29df79b526920e5c243a48bdaa (patch) | |
tree | 5aa1b4ed59018da58f89dcc8f85fb584bac5209c /lib/meta-flow.c | |
parent | cadf7ec937db1e743571cba8773d3724064c9500 (diff) | |
download | openvswitch-8e4c1621e939cd29df79b526920e5c243a48bdaa.tar.gz |
flow: Factor out flag parsing and formatting routines.
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@nicira.com>
Diffstat (limited to 'lib/meta-flow.c')
-rw-r--r-- | lib/meta-flow.c | 154 |
1 files changed, 27 insertions, 127 deletions
diff --git a/lib/meta-flow.c b/lib/meta-flow.c index 541143c6b..a2abc4dbc 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: |