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: {
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);
enum ofperr err;
err = ofpacts_check(ofpacts.data, ofpacts.size, &fm->match.flow,
- OFPP_MAX, 0, true);
+ 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);
* 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;
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;
}
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);