static char * WARN_UNUSED_RESULT
str_to_mac(const char *str, uint8_t mac[6])
{
- if (sscanf(str, ETH_ADDR_SCAN_FMT, ETH_ADDR_SCAN_ARGS(mac))
- != ETH_ADDR_SCAN_COUNT) {
+ if (!ovs_scan(str, ETH_ADDR_SCAN_FMT, ETH_ADDR_SCAN_ARGS(mac))) {
return xasprintf("invalid mac address %s", str);
}
return NULL;
parse_enqueue(char *arg, struct ofpbuf *ofpacts)
{
char *sp = NULL;
- char *port = strtok_r(arg, ":q", &sp);
+ char *port = strtok_r(arg, ":q,", &sp);
char *queue = strtok_r(NULL, "", &sp);
struct ofpact_enqueue *enqueue;
if (port == NULL || queue == NULL) {
- return xstrdup("\"enqueue\" syntax is \"enqueue:PORT:QUEUE\"");
+ return xstrdup("\"enqueue\" syntax is \"enqueue:PORT:QUEUE\" or "
+ "\"enqueue(PORT,QUEUE)\"");
}
enqueue = ofpact_put_ENQUEUE(ofpacts);
struct ofpact_output *output;
output = ofpact_put_OUTPUT(ofpacts);
- output->max_len = output->port == OFPP_CONTROLLER ? UINT16_MAX : 0;
if (!ofputil_port_from_string(arg, &output->port)) {
return xasprintf("%s: output to unknown port", arg);
}
+ output->max_len = output->port == OFPP_CONTROLLER ? UINT16_MAX : 0;
return NULL;
}
}
}
ofpbuf_put(ofpacts, &byte, 1);
- note = ofpacts->l2;
+ note = ofpacts->frame;
note->length++;
arg += 2;
ids = ofpact_put_DEC_TTL(b);
ofpbuf_put(b, &id, sizeof id);
- ids = b->l2;
+ ids = b->frame;
ids->n_controllers++;
ofpact_update_len(b, &ids->ofpact);
}
uint16_t id = atoi(cntr);
ofpbuf_put(b, &id, sizeof id);
- ids = b->l2;
+ ids = b->frame;
ids->n_controllers++;
}
if (!ids->n_controllers) {
return NULL;
}
+/* Parses 'arg' as the argument to a "set_mpls_label" action, and appends such
+ * an action to 'b'.
+ *
+ * Returns NULL if successful, otherwise a malloc()'d string describing the
+ * error. The caller is responsible for freeing the returned string. */
+static char * WARN_UNUSED_RESULT
+parse_set_mpls_label(struct ofpbuf *b, const char *arg)
+{
+ struct ofpact_mpls_label *mpls_label = ofpact_put_SET_MPLS_LABEL(b);
+
+ if (*arg == '\0') {
+ return xstrdup("parse_set_mpls_label: expected label.");
+ }
+
+ mpls_label->label = htonl(atoi(arg));
+ return NULL;
+}
+
+/* Parses 'arg' as the argument to a "set_mpls_tc" action, and appends such an
+ * action to 'b'.
+ *
+ * Returns NULL if successful, otherwise a malloc()'d string describing the
+ * error. The caller is responsible for freeing the returned string. */
+static char * WARN_UNUSED_RESULT
+parse_set_mpls_tc(struct ofpbuf *b, const char *arg)
+{
+ struct ofpact_mpls_tc *mpls_tc = ofpact_put_SET_MPLS_TC(b);
+
+ if (*arg == '\0') {
+ return xstrdup("parse_set_mpls_tc: expected tc.");
+ }
+
+ mpls_tc->tc = atoi(arg);
+ return NULL;
+}
+
/* Parses 'arg' as the argument to a "set_mpls_ttl" action, and appends such an
* action to 'ofpacts'.
*
set_field_parse__(char *arg, struct ofpbuf *ofpacts,
enum ofputil_protocol *usable_protocols)
{
- struct ofpact_reg_load *load = ofpact_put_REG_LOAD(ofpacts);
+ struct ofpact_set_field *sf = ofpact_put_SET_FIELD(ofpacts);
char *value;
char *delim;
char *key;
const struct mf_field *mf;
char *error;
- union mf_value mf_value;
value = arg;
delim = strstr(arg, "->");
if (!mf->writable) {
return xasprintf("%s is read-only", key);
}
-
+ sf->field = mf;
delim[0] = '\0';
- error = mf_parse_value(mf, value, &mf_value);
+ error = mf_parse_value(mf, value, &sf->value);
if (error) {
return error;
}
- if (!mf_is_value_valid(mf, &mf_value)) {
+
+ if (!mf_is_value_valid(mf, &sf->value)) {
return xasprintf("%s is not a valid value for field %s", value, key);
}
- ofpact_set_field_init(load, mf, &mf_value);
*usable_protocols &= mf->usable_protocols;
return NULL;
char *arg, struct ofpbuf *ofpacts,
enum ofputil_protocol *usable_protocols)
{
- size_t orig_size = ofpacts->size;
+ size_t orig_size = ofpbuf_size(ofpacts);
struct ofpact_tunnel *tunnel;
struct ofpact_vlan_vid *vlan_vid;
struct ofpact_vlan_pcp *vlan_pcp;
char *error = NULL;
uint16_t ethertype = 0;
uint16_t vid = 0;
- uint8_t tos = 0, ecn, ttl;
+ uint8_t tos = 0;
+ uint8_t ecn = 0;
+ uint8_t ttl = 0;
uint8_t pcp = 0;
switch (code) {
case OFPUTIL_ACTION_INVALID:
- NOT_REACHED();
+ OVS_NOT_REACHED();
case OFPUTIL_OFPAT10_OUTPUT:
case OFPUTIL_OFPAT11_OUTPUT:
+ case OFPUTIL_OFPAT13_OUTPUT:
error = parse_output(arg, ofpacts);
break;
break;
case OFPUTIL_OFPAT12_SET_FIELD:
+ case OFPUTIL_OFPAT13_SET_FIELD:
return set_field_parse(arg, ofpacts, usable_protocols);
case OFPUTIL_OFPAT10_STRIP_VLAN:
case OFPUTIL_OFPAT11_POP_VLAN:
+ case OFPUTIL_OFPAT13_POP_VLAN:
ofpact_put_STRIP_VLAN(ofpacts)->ofpact.compat = code;
break;
case OFPUTIL_OFPAT11_PUSH_VLAN:
+ case OFPUTIL_OFPAT13_PUSH_VLAN:
*usable_protocols &= OFPUTIL_P_OF11_UP;
error = str_to_u16(arg, "ethertype", ðertype);
if (error) {
break;
case OFPUTIL_OFPAT11_SET_QUEUE:
+ case OFPUTIL_OFPAT13_SET_QUEUE:
error = str_to_u32(arg, &ofpact_put_SET_QUEUE(ofpacts)->queue_id);
break;
break;
case OFPUTIL_OFPAT11_SET_NW_TTL:
+ case OFPUTIL_OFPAT13_SET_NW_TTL:
error = str_to_u8(arg, "TTL", &ttl);
if (error) {
return error;
break;
case OFPUTIL_OFPAT11_DEC_NW_TTL:
- NOT_REACHED();
+ case OFPUTIL_OFPAT13_DEC_NW_TTL:
+ OVS_NOT_REACHED();
case OFPUTIL_OFPAT10_SET_TP_SRC:
case OFPUTIL_OFPAT11_SET_TP_SRC:
case OFPUTIL_NXAST_RESUBMIT_TABLE:
case OFPUTIL_NXAST_OUTPUT_REG:
case OFPUTIL_NXAST_DEC_TTL_CNT_IDS:
- NOT_REACHED();
+ OVS_NOT_REACHED();
case OFPUTIL_NXAST_LEARN:
error = learn_parse(arg, ofpacts);
error = parse_dec_ttl(ofpacts, arg);
break;
+ case OFPUTIL_NXAST_SET_MPLS_LABEL:
+ case OFPUTIL_OFPAT11_SET_MPLS_LABEL:
+ error = parse_set_mpls_label(ofpacts, arg);
+ break;
+
+ case OFPUTIL_NXAST_SET_MPLS_TC:
+ case OFPUTIL_OFPAT11_SET_MPLS_TC:
+ error = parse_set_mpls_tc(ofpacts, arg);
+ break;
+
case OFPUTIL_NXAST_SET_MPLS_TTL:
case OFPUTIL_OFPAT11_SET_MPLS_TTL:
+ case OFPUTIL_OFPAT13_SET_MPLS_TTL:
error = parse_set_mpls_ttl(ofpacts, arg);
break;
case OFPUTIL_OFPAT11_DEC_MPLS_TTL:
+ case OFPUTIL_OFPAT13_DEC_MPLS_TTL:
case OFPUTIL_NXAST_DEC_MPLS_TTL:
ofpact_put_DEC_MPLS_TTL(ofpacts);
break;
break;
case OFPUTIL_OFPAT11_PUSH_MPLS:
+ case OFPUTIL_OFPAT13_PUSH_MPLS:
case OFPUTIL_NXAST_PUSH_MPLS:
error = str_to_u16(arg, "push_mpls", ðertype);
if (!error) {
break;
case OFPUTIL_OFPAT11_POP_MPLS:
+ case OFPUTIL_OFPAT13_POP_MPLS:
case OFPUTIL_NXAST_POP_MPLS:
error = str_to_u16(arg, "pop_mpls", ðertype);
if (!error) {
break;
case OFPUTIL_OFPAT11_GROUP:
+ case OFPUTIL_OFPAT13_GROUP:
error = str_to_u32(arg, &ofpact_put_GROUP(ofpacts)->group_id);
break;
+ /* FIXME when implement OFPAT13_* */
+ case OFPUTIL_OFPAT13_COPY_TTL_OUT:
+ case OFPUTIL_OFPAT13_COPY_TTL_IN:
+ case OFPUTIL_OFPAT13_PUSH_PBB:
+ case OFPUTIL_OFPAT13_POP_PBB:
+ OVS_NOT_REACHED();
+
case OFPUTIL_NXAST_STACK_PUSH:
error = nxm_parse_stack_action(ofpact_put_STACK_PUSH(ofpacts), arg);
break;
}
if (error) {
- ofpacts->size = orig_size;
+ ofpbuf_set_size(ofpacts, orig_size);
}
return error;
}
str_to_ofpacts__(char *str, struct ofpbuf *ofpacts,
enum ofputil_protocol *usable_protocols)
{
- size_t orig_size = ofpacts->size;
+ size_t orig_size = ofpbuf_size(ofpacts);
char *pos, *act, *arg;
int n_actions;
char *error = str_to_ofpact__(pos, act, arg, ofpacts, n_actions,
usable_protocols);
if (error) {
- ofpacts->size = orig_size;
+ ofpbuf_set_size(ofpacts, orig_size);
return error;
}
n_actions++;
str_to_ofpacts(char *str, struct ofpbuf *ofpacts,
enum ofputil_protocol *usable_protocols)
{
- size_t orig_size = ofpacts->size;
+ size_t orig_size = ofpbuf_size(ofpacts);
char *error_s;
enum ofperr error;
return error_s;
}
- error = ofpacts_verify(ofpacts->data, ofpacts->size);
+ error = ofpacts_verify(ofpbuf_data(ofpacts), ofpbuf_size(ofpacts));
if (error) {
- ofpacts->size = orig_size;
+ ofpbuf_set_size(ofpacts, orig_size);
return xstrdup("Incorrect action ordering");
}
switch (type) {
case OVSINST_OFPIT11_APPLY_ACTIONS:
- NOT_REACHED(); /* This case is handled by str_to_inst_ofpacts() */
+ OVS_NOT_REACHED(); /* This case is handled by str_to_inst_ofpacts() */
break;
case OVSINST_OFPIT11_WRITE_ACTIONS: {
size_t ofs;
ofpact_pad(ofpacts);
- ofs = ofpacts->size;
+ ofs = ofpbuf_size(ofpacts);
on = ofpact_put(ofpacts, OFPACT_WRITE_ACTIONS,
offsetof(struct ofpact_nest, actions));
error_s = str_to_ofpacts__(arg, ofpacts, usable_protocols);
on = ofpbuf_at_assert(ofpacts, ofs, sizeof *on);
- on->ofpact.len = ofpacts->size - ofs;
+ on->ofpact.len = ofpbuf_size(ofpacts) - ofs;
if (error_s) {
- ofpacts->size = ofs;
+ ofpbuf_set_size(ofpacts, ofs);
}
break;
}
/* If write_metadata is specified as an action AND an instruction, ofpacts
could be invalid. */
- error = ofpacts_verify(ofpacts->data, ofpacts->size);
+ error = ofpacts_verify(ofpbuf_data(ofpacts), ofpbuf_size(ofpacts));
if (error) {
return xstrdup("Incorrect instruction ordering");
}
str_to_inst_ofpacts(char *str, struct ofpbuf *ofpacts,
enum ofputil_protocol *usable_protocols)
{
- size_t orig_size = ofpacts->size;
+ size_t orig_size = ofpbuf_size(ofpacts);
char *pos, *inst, *arg;
int type;
const char *prev_inst = NULL;
char *error = str_to_ofpact__(pos, inst, arg, ofpacts, n_actions,
usable_protocols);
if (error) {
- ofpacts->size = orig_size;
+ ofpbuf_set_size(ofpacts, orig_size);
return error;
}
continue;
}
} else if (type == OVSINST_OFPIT11_APPLY_ACTIONS) {
- ofpacts->size = orig_size;
+ ofpbuf_set_size(ofpacts, orig_size);
return xasprintf("%s isn't supported. Just write actions then "
"it is interpreted as apply_actions", inst);
} else {
char *error = parse_named_instruction(type, arg, ofpacts,
usable_protocols);
if (error) {
- ofpacts->size = orig_size;
+ ofpbuf_set_size(ofpacts, orig_size);
return error;
}
}
if (type <= prev_type) {
- ofpacts->size = orig_size;
+ ofpbuf_set_size(ofpacts, orig_size);
if (type == prev_type) {
return xasprintf("instruction %s may be specified only once",
inst);
static char * WARN_UNUSED_RESULT
parse_ofp_str__(struct ofputil_flow_mod *fm, int command, char *string,
- enum ofputil_protocol *usable_protocols,
- bool enforce_consistency)
+ enum ofputil_protocol *usable_protocols)
{
enum {
F_OUT_PORT = 1 << 0,
break;
default:
- NOT_REACHED();
+ OVS_NOT_REACHED();
}
match_init_catchall(&fm->match);
} else if (fields & F_FLAGS && !strcmp(name, "no_byte_counts")) {
fm->flags |= OFPUTIL_FF_NO_BYT_COUNTS;
*usable_protocols &= OFPUTIL_P_OF13_UP;
+ } else if (!strcmp(name, "no_readonly_table")
+ || !strcmp(name, "allow_hidden_fields")) {
+ /* ignore these fields. */
} else {
char *value;
if (!error) {
enum ofperr err;
- err = ofpacts_check(ofpacts.data, ofpacts.size, &fm->match.flow,
- OFPP_MAX, 0, true);
+ err = ofpacts_check(ofpbuf_data(&ofpacts), ofpbuf_size(&ofpacts), &fm->match.flow,
+ OFPP_MAX, fm->table_id, 255, usable_protocols);
+ if (!err && !usable_protocols) {
+ err = OFPERR_OFPBAC_MATCH_INCONSISTENT;
+ }
if (err) {
- if (!enforce_consistency &&
- err == OFPERR_OFPBAC_MATCH_INCONSISTENT) {
- /* Allow inconsistent actions to be used with OF 1.0. */
- *usable_protocols &= OFPUTIL_P_OF10_ANY;
- /* Try again, allowing for inconsistency.
- * XXX: As a side effect, logging may be duplicated. */
- err = ofpacts_check(ofpacts.data, ofpacts.size,
- &fm->match.flow, OFPP_MAX, 0, false);
- }
- if (err) {
- error = xasprintf("actions are invalid with specified match "
- "(%s)", ofperr_to_string(err));
- }
+ error = xasprintf("actions are invalid with specified match "
+ "(%s)", ofperr_to_string(err));
}
+
}
if (error) {
ofpbuf_uninit(&ofpacts);
return error;
}
- fm->ofpacts_len = ofpacts.size;
+ fm->ofpacts_len = ofpbuf_size(&ofpacts);
fm->ofpacts = ofpbuf_steal_data(&ofpacts);
} else {
fm->ofpacts_len = 0;
* error. The caller is responsible for freeing the returned string. */
char * WARN_UNUSED_RESULT
parse_ofp_str(struct ofputil_flow_mod *fm, int command, const char *str_,
- enum ofputil_protocol *usable_protocols,
- bool enforce_consistency)
+ enum ofputil_protocol *usable_protocols)
{
char *string = xstrdup(str_);
char *error;
- error = parse_ofp_str__(fm, command, string, usable_protocols,
- enforce_consistency);
+ error = parse_ofp_str__(fm, command, string, usable_protocols);
if (error) {
fm->ofpacts = NULL;
fm->ofpacts_len = 0;
break;
default:
- NOT_REACHED();
+ OVS_NOT_REACHED();
}
mm->command = command;
char * WARN_UNUSED_RESULT
parse_ofp_flow_mod_str(struct ofputil_flow_mod *fm, const char *string,
uint16_t command,
- enum ofputil_protocol *usable_protocols,
- bool enforce_consistency)
+ enum ofputil_protocol *usable_protocols)
{
- char *error = parse_ofp_str(fm, command, string, usable_protocols,
- enforce_consistency);
+ char *error = parse_ofp_str(fm, command, string, usable_protocols);
if (!error) {
/* Normalize a copy of the match. This ensures that non-normalized
* flows get logged but doesn't affect what gets sent to the switch, so
*usable_protocols = OFPUTIL_P_OF11_UP;
if (!strcasecmp(table_id, "all")) {
- tm->table_id = 255;
+ tm->table_id = OFPTT_ALL;
} else {
char *error = str_to_u8(table_id, "table_id", &tm->table_id);
if (error) {
char * WARN_UNUSED_RESULT
parse_ofp_flow_mod_file(const char *file_name, uint16_t command,
struct ofputil_flow_mod **fms, size_t *n_fms,
- enum ofputil_protocol *usable_protocols,
- bool enforce_consistency)
+ enum ofputil_protocol *usable_protocols)
{
size_t allocated_fms;
int line_number;
*fms = x2nrealloc(*fms, &allocated_fms, sizeof **fms);
}
error = parse_ofp_flow_mod_str(&(*fms)[*n_fms], ds_cstr(&s), command,
- &usable, enforce_consistency);
+ &usable);
if (error) {
size_t i;
for (i = 0; i < *n_fms; i++) {
- free((*fms)[i].ofpacts);
+ free(CONST_CAST(struct ofpact *, (*fms)[i].ofpacts));
}
free(*fms);
*fms = NULL;
char * WARN_UNUSED_RESULT
parse_ofp_flow_stats_request_str(struct ofputil_flow_stats_request *fsr,
bool aggregate, const char *string,
- enum ofputil_protocol *usable_protocols,
- bool enforce_consistency)
+ enum ofputil_protocol *usable_protocols)
{
struct ofputil_flow_mod fm;
char *error;
- error = parse_ofp_str(&fm, -1, string, usable_protocols,
- enforce_consistency);
+ error = parse_ofp_str(&fm, -1, string, usable_protocols);
if (error) {
return error;
}
}
ofpact_pad(&ofpacts);
- bucket->ofpacts = ofpacts.data;
- bucket->ofpacts_len = ofpacts.size;
+ bucket->ofpacts = ofpbuf_data(&ofpacts);
+ bucket->ofpacts_len = ofpbuf_size(&ofpacts);
return NULL;
}
break;
default:
- NOT_REACHED();
+ OVS_NOT_REACHED();
}
memset(gm, 0, sizeof *gm);
char *error;
if (*n_gms >= allocated_gms) {
+ size_t i;
+
*gms = x2nrealloc(*gms, &allocated_gms, sizeof **gms);
+ for (i = 0; i < *n_gms; i++) {
+ list_moved(&(*gms)[i].buckets);
+ }
}
error = parse_ofp_group_mod_str(&(*gms)[*n_gms], command, ds_cstr(&s),
&usable);