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;
}
}
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;
{
size_t orig_size = ofpacts->size;
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:
if (vid & ~VLAN_VID_MASK) {
return xasprintf("%s: not a valid VLAN VID", arg);
}
- ofpact_put_SET_VLAN_VID(ofpacts)->vlan_vid = vid;
+ vlan_vid = ofpact_put_SET_VLAN_VID(ofpacts);
+ vlan_vid->vlan_vid = vid;
+ vlan_vid->ofpact.compat = code;
+ vlan_vid->push_vlan_if_needed = code == OFPUTIL_OFPAT10_SET_VLAN_VID;
break;
case OFPUTIL_OFPAT10_SET_VLAN_PCP:
if (pcp & ~7) {
return xasprintf("%s: not a valid VLAN PCP", arg);
}
- ofpact_put_SET_VLAN_PCP(ofpacts)->vlan_pcp = pcp;
+ vlan_pcp = ofpact_put_SET_VLAN_PCP(ofpacts);
+ vlan_pcp->vlan_pcp = pcp;
+ vlan_pcp->ofpact.compat = code;
+ vlan_pcp->push_vlan_if_needed = code == OFPUTIL_OFPAT10_SET_VLAN_PCP;
break;
case OFPUTIL_OFPAT12_SET_FIELD:
case OFPUTIL_OFPAT10_STRIP_VLAN:
case OFPUTIL_OFPAT11_POP_VLAN:
- ofpact_put_STRIP_VLAN(ofpacts);
+ ofpact_put_STRIP_VLAN(ofpacts)->ofpact.compat = code;
break;
case OFPUTIL_OFPAT11_PUSH_VLAN:
break;
case OFPUTIL_OFPAT11_DEC_NW_TTL:
- NOT_REACHED();
+ 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:
error = parse_set_mpls_ttl(ofpacts, arg);
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: {
break;
default:
- NOT_REACHED();
+ OVS_NOT_REACHED();
}
match_init_catchall(&fm->match);
enum ofperr err;
err = ofpacts_check(ofpacts.data, ofpacts.size, &fm->match.flow,
- OFPP_MAX, 0);
+ OFPP_MAX, fm->table_id, 255, usable_protocols);
+ if (!err && !usable_protocols) {
+ err = OFPERR_OFPBAC_MATCH_INCONSISTENT;
+ }
if (err) {
error = xasprintf("actions are invalid with specified match "
"(%s)", ofperr_to_string(err));
}
+
}
if (error) {
ofpbuf_uninit(&ofpacts);
break;
default:
- NOT_REACHED();
+ OVS_NOT_REACHED();
}
mm->command = command;
*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) {
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);