#include <ctype.h>
#include <errno.h>
#include <stdlib.h>
+#include <netinet/in.h>
#include "byte-order.h"
#include "dynamic-string.h"
return NULL;
}
+/* Parses 'str' as a conntrack helper into 'alg'.
+ *
+ * Returns NULL if successful, otherwise a malloc()'d string describing the
+ * error. The caller is responsible for freeing the returned string. */
+char * OVS_WARN_UNUSED_RESULT
+str_to_connhelper(const char *str, uint16_t *alg)
+{
+ if (!strcmp(str, "ftp")) {
+ *alg = IPPORT_FTP;
+ return NULL;
+ }
+ return xasprintf("invalid conntrack helper \"%s\"", str);
+}
+
struct protocol {
const char *name;
uint16_t dl_type;
union mf_value value, mask;
char *error;
+ if (!*s) {
+ /* If there's no string, we're just trying to match on the
+ * existence of the field, so use a no-op value. */
+ s = "0/0";
+ }
+
error = mf_parse(mf, s, &value, &mask);
if (!error) {
- *usable_protocols &= mf_set(mf, &value, &mask, match);
+ *usable_protocols &= mf_set(mf, &value, &mask, match, &error);
}
return error;
}
F_PRIORITY = 1 << 4,
F_FLAGS = 1 << 5,
} fields;
- char *save_ptr = NULL;
char *act_str = NULL;
- char *name;
+ char *name, *value;
*usable_protocols = OFPUTIL_P_ANY;
fm->out_port = OFPP_ANY;
fm->flags = 0;
fm->importance = 0;
- fm->out_group = OFPG11_ANY;
+ fm->out_group = OFPG_ANY;
fm->delete_reason = OFPRR_DELETE;
if (fields & F_ACTIONS) {
act_str = extract_actions(string);
return xstrdup("must specify an action");
}
}
- for (name = strtok_r(string, "=, \t\r\n", &save_ptr); name;
- name = strtok_r(NULL, "=, \t\r\n", &save_ptr)) {
+
+ while (ofputil_parse_key_value(&string, &name, &value)) {
const struct protocol *p;
char *error = NULL;
} else if (!strcmp(name, "no_readonly_table")
|| !strcmp(name, "allow_hidden_fields")) {
/* ignore these fields. */
+ } else if (mf_from_name(name)) {
+ error = parse_field(mf_from_name(name), value, &fm->match,
+ usable_protocols);
} else {
- char *value;
-
- value = strtok_r(NULL, ", \t\r\n", &save_ptr);
- if (!value) {
+ if (!*value) {
return xasprintf("field %s missing value", name);
}
error = xasprintf("%s is not a valid OpenFlow port",
value);
}
+ } else if (fields & F_OUT_PORT && !strcmp(name, "out_group")) {
+ *usable_protocols &= OFPUTIL_P_OF11_UP;
+ if (!ofputil_group_from_string(value, &fm->out_group)) {
+ error = xasprintf("%s is not a valid OpenFlow group",
+ value);
+ }
} else if (fields & F_PRIORITY && !strcmp(name, "priority")) {
uint16_t priority = 0;
error = str_to_be64(value, &fm->new_cookie);
fm->modify_cookie = true;
}
- } else if (mf_from_name(name)) {
- error = parse_field(mf_from_name(name), value, &fm->match,
- usable_protocols);
} else if (!strcmp(name, "duration")
|| !strcmp(name, "n_packets")
|| !strcmp(name, "n_bytes")
} else {
error = xasprintf("unknown keyword %s", name);
}
+ }
- if (error) {
- return error;
- }
+ if (error) {
+ return error;
}
}
/* Check for usable protocol interdependencies between match fields. */
enum ofputil_protocol *usable_protocols)
{
static atomic_count id = ATOMIC_COUNT_INIT(0);
- char *save_ptr = NULL;
- char *name;
+ char *name, *value;
fmr->id = atomic_count_inc(&id);
fmr->table_id = 0xff;
match_init_catchall(&fmr->match);
- for (name = strtok_r(string, "=, \t\r\n", &save_ptr); name;
- name = strtok_r(NULL, "=, \t\r\n", &save_ptr)) {
+ while (ofputil_parse_key_value(&string, &name, &value)) {
const struct protocol *p;
+ char *error = NULL;
if (!strcmp(name, "!initial")) {
fmr->flags &= ~NXFMF_INITIAL;
if (p->nw_proto) {
match_set_nw_proto(&fmr->match, p->nw_proto);
}
+ } else if (mf_from_name(name)) {
+ error = parse_field(mf_from_name(name), value, &fmr->match,
+ usable_protocols);
} else {
- char *value;
-
- value = strtok_r(NULL, ", \t\r\n", &save_ptr);
- if (!value) {
+ if (!*value) {
return xasprintf("%s: field %s missing value", str_, name);
}
if (!strcmp(name, "table")) {
- char *error = str_to_u8(value, "table", &fmr->table_id);
- if (error) {
- return error;
- }
+ error = str_to_u8(value, "table", &fmr->table_id);
} else if (!strcmp(name, "out_port")) {
fmr->out_port = u16_to_ofp(atoi(value));
- } else if (mf_from_name(name)) {
- char *error;
-
- error = parse_field(mf_from_name(name), value, &fmr->match,
- usable_protocols);
- if (error) {
- return error;
- }
} else {
return xasprintf("%s: unknown keyword %s", str_, name);
}
}
+
+ if (error) {
+ return error;
+ }
}
return NULL;
}
goto exit;
}
- if (!mf_is_zero(mf, flow)) {
+ if (mf_is_set(mf, flow)) {
error = xasprintf("%s: field %s set multiple times", s, key);
goto exit;
}
bucket->weight = group_type == OFPGT11_SELECT ? 1 : 0;
bucket->bucket_id = OFPG15_BUCKET_ALL;
bucket->watch_port = OFPP_ANY;
- bucket->watch_group = OFPG11_ANY;
+ bucket->watch_group = OFPG_ANY;
ds_init(&actions);
parse_select_group_field(char *s, struct field_array *fa,
enum ofputil_protocol *usable_protocols)
{
- char *save_ptr = NULL;
- char *name;
+ char *name, *value_str;
- for (name = strtok_r(s, "=, \t\r\n", &save_ptr); name;
- name = strtok_r(NULL, "=, \t\r\n", &save_ptr)) {
+ while (ofputil_parse_key_value(&s, &name, &value_str)) {
const struct mf_field *mf = mf_from_name(name);
if (mf) {
char *error;
- const char *value_str;
union mf_value value;
if (bitmap_is_set(fa->used.bm, mf->id)) {
return xasprintf("%s: duplicate field", name);
}
- value_str = strtok_r(NULL, ", \t\r\n", &save_ptr);
- if (value_str) {
+ if (*value_str) {
error = mf_parse_value(mf, value_str, &value);
if (error) {
return error;
}
/* The mask cannot be all-zeros */
- if (is_all_zeros(&value, mf->n_bytes)) {
+ if (!mf_is_tun_metadata(mf) &&
+ is_all_zeros(&value, mf->n_bytes)) {
return xasprintf("%s: values are wildcards here "
"and must not be all-zeros", s);
}
F_COMMAND_BUCKET_ID = 1 << 2,
F_COMMAND_BUCKET_ID_ALL = 1 << 3,
} fields;
- char *save_ptr = NULL;
bool had_type = false;
bool had_command_bucket_id = false;
- char *name;
struct ofputil_bucket *bucket;
char *error = NULL;
}
/* Parse everything before the buckets. */
- for (name = strtok_r(string, "=, \t\r\n", &save_ptr); name;
- name = strtok_r(NULL, "=, \t\r\n", &save_ptr)) {
- char *value;
-
- value = strtok_r(NULL, ", \t\r\n", &save_ptr);
- if (!value) {
- error = xasprintf("field %s missing value", name);
- goto out;
- }
-
+ char *pos = string;
+ char *name, *value;
+ while (ofputil_parse_key_value(&pos, &name, &value)) {
if (!strcmp(name, "command_bucket_id")) {
if (!(fields & F_COMMAND_BUCKET_ID)) {
error = xstrdup("command bucket id is not needed");