summaryrefslogtreecommitdiff
path: root/lib/meta-flow.c
diff options
context:
space:
mode:
authorJesse Gross <jesse@nicira.com>2015-07-11 20:48:29 -0700
committerJesse Gross <jesse@nicira.com>2015-07-15 20:24:04 -0700
commit8e4c1621e939cd29df79b526920e5c243a48bdaa (patch)
tree5aa1b4ed59018da58f89dcc8f85fb584bac5209c /lib/meta-flow.c
parentcadf7ec937db1e743571cba8773d3724064c9500 (diff)
downloadopenvswitch-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.c154
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: