in_port_s = strsep(&arg, ",");
if (in_port_s && in_port_s[0]) {
- if (!ofputil_port_from_string(in_port_s, &resubmit->in_port)) {
- resubmit->in_port = str_to_u32(in_port_s);
+ resubmit->in_port = ofputil_port_from_string(in_port_s);
+ if (!resubmit->in_port) {
+ ovs_fatal(0, "%s: resubmit to unknown port", in_port_s);
}
} else {
resubmit->in_port = OFPP_IN_PORT;
}
}
+static void
+parse_dec_ttl(struct ofpbuf *b, char *arg)
+{
+ struct ofpact_cnt_ids *ids;
+
+ ids = ofpact_put_DEC_TTL(b);
+
+ if (*arg == '\0') {
+ uint16_t id = 0;
+
+ ids->ofpact.compat = OFPUTIL_NXAST_DEC_TTL;
+ ofpbuf_put(b, &id, sizeof id);
+ ids = b->l2;
+ ids->n_controllers++;
+ } else {
+ char *cntr;
+
+ ids->ofpact.compat = OFPUTIL_NXAST_DEC_TTL_CNT_IDS;
+ for (cntr = strtok_r(arg, ", ", &arg); cntr != NULL;
+ cntr = strtok_r(NULL, ", ", &arg)) {
+ uint16_t id = atoi(cntr);
+
+ ofpbuf_put(b, &id, sizeof id);
+ ids = b->l2;
+ ids->n_controllers++;
+ }
+ if (!ids->n_controllers) {
+ ovs_fatal(0, "dec_ttl_cnt_ids: expected at least one controller "
+ "id.");
+ }
+
+ }
+ ofpact_update_len(b, &ids->ofpact);
+}
+
+static void
+set_field_parse(const char *arg, struct ofpbuf *ofpacts)
+{
+ char *orig = xstrdup(arg);
+ struct ofpact_reg_load *load = ofpact_put_REG_LOAD(ofpacts);
+ char *value;
+ char *delim;
+ char *key;
+ const struct mf_field *mf;
+ const char *error;
+ union mf_value mf_value;
+
+ value = orig;
+ delim = strstr(orig, "->");
+ if (!delim) {
+ ovs_fatal(0, "%s: missing `->'", orig);
+ }
+ if (strlen(delim) <= strlen("->")) {
+ ovs_fatal(0, "%s: missing field name following `->'", orig);
+ }
+
+ key = delim + strlen("->");
+ mf = mf_from_name(key);
+ if (!mf) {
+ ovs_fatal(0, "%s is not valid oxm field name", key);
+ }
+ if (!mf->writable) {
+ ovs_fatal(0, "%s is not allowed to set", key);
+ }
+
+ delim[0] = '\0';
+ error = mf_parse_value(mf, value, &mf_value);
+ if (error) {
+ ovs_fatal(0, "%s", error);
+ }
+ if (!mf_is_value_valid(mf, &mf_value)) {
+ ovs_fatal(0, "%s is not valid valid for field %s", value, key);
+ }
+ ofpact_set_field_init(load, mf, &mf_value);
+ free(orig);
+}
+
static void
parse_named_action(enum ofputil_action_code code, const struct flow *flow,
char *arg, struct ofpbuf *ofpacts)
ofpact_put_SET_VLAN_PCP(ofpacts)->vlan_pcp = pcp;
break;
+ case OFPUTIL_OFPAT12_SET_FIELD:
+ set_field_parse(arg, ofpacts);
+ break;
+
case OFPUTIL_OFPAT10_STRIP_VLAN:
ofpact_put_STRIP_VLAN(ofpacts);
break;
multipath_parse(ofpact_put_MULTIPATH(ofpacts), arg);
break;
- case OFPUTIL_NXAST_AUTOPATH:
+ case OFPUTIL_NXAST_AUTOPATH__DEPRECATED:
autopath_parse(ofpact_put_AUTOPATH(ofpacts), arg);
break;
case OFPUTIL_NXAST_RESUBMIT_TABLE:
case OFPUTIL_NXAST_OUTPUT_REG:
+ case OFPUTIL_NXAST_DEC_TTL_CNT_IDS:
NOT_REACHED();
case OFPUTIL_NXAST_LEARN:
break;
case OFPUTIL_NXAST_DEC_TTL:
- ofpact_put_DEC_TTL(ofpacts);
+ parse_dec_ttl(ofpacts, arg);
break;
case OFPUTIL_NXAST_FIN_TIMEOUT:
pos = str;
n_actions = 0;
while (ofputil_parse_key_value(&pos, &act, &arg)) {
- uint16_t port;
- int code;
-
- code = ofputil_action_code_from_name(act);
+ int code = ofputil_action_code_from_name(act);
if (code >= 0) {
parse_named_action(code, flow, arg, ofpacts);
} else if (!strcasecmp(act, "drop")) {
"actions");
}
break;
- } else if (ofputil_port_from_string(act, &port)) {
- ofpact_put_OUTPUT(ofpacts)->port = port;
} else {
- ovs_fatal(0, "Unknown action: %s", act);
+ uint16_t port = ofputil_port_from_string(act);
+ if (port) {
+ ofpact_put_OUTPUT(ofpacts)->port = port;
+ } else {
+ ovs_fatal(0, "Unknown action: %s", act);
+ }
}
n_actions++;
}
}
static void
-parse_field(const struct mf_field *mf, const char *s, struct cls_rule *rule)
+parse_field(const struct mf_field *mf, const char *s, struct match *match)
{
union mf_value value, mask;
char *error;
ovs_fatal(0, "%s", error);
}
- mf_set(mf, &value, &mask, rule);
+ mf_set(mf, &value, &mask, match);
}
/* Convert 'str_' (as described in the Flow Syntax section of the ovs-ofctl man
NOT_REACHED();
}
- cls_rule_init_catchall(&fm->cr, OFP_DEFAULT_PRIORITY);
+ match_init_catchall(&fm->match);
+ fm->priority = OFP_DEFAULT_PRIORITY;
fm->cookie = htonll(0);
fm->cookie_mask = htonll(0);
if (command == OFPFC_MODIFY || command == OFPFC_MODIFY_STRICT) {
const struct protocol *p;
if (parse_protocol(name, &p)) {
- cls_rule_set_dl_type(&fm->cr, htons(p->dl_type));
+ match_set_dl_type(&fm->match, htons(p->dl_type));
if (p->nw_proto) {
- cls_rule_set_nw_proto(&fm->cr, p->nw_proto);
+ match_set_nw_proto(&fm->match, p->nw_proto);
}
} else if (fields & F_FLAGS && !strcmp(name, "send_flow_rem")) {
fm->flags |= OFPFF_SEND_FLOW_REM;
if (!strcmp(name, "table")) {
fm->table_id = str_to_table_id(value);
} else if (!strcmp(name, "out_port")) {
- fm->out_port = atoi(value);
+ fm->out_port = ofputil_port_from_string(name);
+ if (!fm->out_port) {
+ ofp_fatal(str_, verbose, "%s is not a valid OpenFlow port",
+ name);
+ }
} else if (fields & F_PRIORITY && !strcmp(name, "priority")) {
- fm->cr.priority = str_to_u16(value, name);
+ fm->priority = str_to_u16(value, name);
} else if (fields & F_TIMEOUT && !strcmp(name, "idle_timeout")) {
fm->idle_timeout = str_to_u16(value, name);
} else if (fields & F_TIMEOUT && !strcmp(name, "hard_timeout")) {
fm->new_cookie = htonll(str_to_u64(value));
}
} else if (mf_from_name(name)) {
- parse_field(mf_from_name(name), value, &fm->cr);
+ parse_field(mf_from_name(name), value, &fm->match);
} else if (!strcmp(name, "duration")
|| !strcmp(name, "n_packets")
|| !strcmp(name, "n_bytes")) {
struct ofpbuf ofpacts;
ofpbuf_init(&ofpacts, 32);
- str_to_ofpacts(&fm->cr.flow, act_str, &ofpacts);
+ str_to_ofpacts(&fm->match.flow, act_str, &ofpacts);
fm->ofpacts_len = ofpacts.size;
fm->ofpacts = ofpbuf_steal_data(&ofpacts);
} else {
| NXFMF_OWN | NXFMF_ACTIONS);
fmr->out_port = OFPP_NONE;
fmr->table_id = 0xff;
- cls_rule_init_catchall(&fmr->match, 0);
+ 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)) {
} else if (!strcmp(name, "!own")) {
fmr->flags &= ~NXFMF_OWN;
} else if (parse_protocol(name, &p)) {
- cls_rule_set_dl_type(&fmr->match, htons(p->dl_type));
+ match_set_dl_type(&fmr->match, htons(p->dl_type));
if (p->nw_proto) {
- cls_rule_set_nw_proto(&fmr->match, p->nw_proto);
+ match_set_nw_proto(&fmr->match, p->nw_proto);
}
} else {
char *value;
parse_ofp_flow_mod_str(struct ofputil_flow_mod *fm, const char *string,
uint16_t command, bool verbose)
{
- struct cls_rule rule_copy;
+ struct match match_copy;
parse_ofp_str(fm, command, string, verbose);
- /* Normalize a copy of the rule. This ensures that non-normalized flows
+ /* 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 that the
* switch can do whatever it likes with the flow. */
- rule_copy = fm->cr;
- ofputil_normalize_rule(&rule_copy);
+ match_copy = fm->match;
+ ofputil_normalize_match(&match_copy);
}
void
fsr->aggregate = aggregate;
fsr->cookie = fm.cookie;
fsr->cookie_mask = fm.cookie_mask;
- fsr->match = fm.cr;
+ fsr->match = fm.match;
fsr->out_port = fm.out_port;
fsr->table_id = fm.table_id;
}