+ if (*arg == '\0') {
+ parse_noargs_dec_ttl(b);
+ } else {
+ struct ofpact_cnt_ids *ids;
+ char *cntr;
+
+ ids = ofpact_put_DEC_TTL(b);
+ 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
+parse_set_mpls_ttl(struct ofpbuf *b, const char *arg)
+{
+ struct ofpact_mpls_ttl *mpls_ttl = ofpact_put_SET_MPLS_TTL(b);
+
+ if (*arg == '\0') {
+ ovs_fatal(0, "parse_set_mpls_ttl: expected ttl.");
+ }
+
+ mpls_ttl->ttl = atoi(arg);
+}
+
+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_metadata(struct ofpbuf *b, char *arg)
+{
+ struct ofpact_metadata *om;
+ char *mask = strchr(arg, '/');
+
+ om = ofpact_put_WRITE_METADATA(b);
+
+ if (mask) {
+ *mask = '\0';
+ om->mask = htonll(str_to_u64(mask + 1));
+ } else {
+ om->mask = htonll(UINT64_MAX);
+ }
+
+ om->metadata = htonll(str_to_u64(arg));
+}
+
+static void
+parse_sample(struct ofpbuf *b, char *arg)
+{
+ struct ofpact_sample *os = ofpact_put_SAMPLE(b);
+ char *key, *value;
+
+ while (ofputil_parse_key_value(&arg, &key, &value)) {
+ if (!strcmp(key, "probability")) {
+ os->probability = str_to_u16(value, "probability");
+ if (os->probability == 0) {
+ ovs_fatal(0, "invalid probability value \"%s\"", value);
+ }
+ } else if (!strcmp(key, "collector_set_id")) {
+ os->collector_set_id = str_to_u32(value);
+ } else if (!strcmp(key, "obs_domain_id")) {
+ os->obs_domain_id = str_to_u32(value);
+ } else if (!strcmp(key, "obs_point_id")) {
+ os->obs_point_id = str_to_u32(value);
+ } else {
+ ovs_fatal(0, "invalid key \"%s\" in \"sample\" argument",
+ key);
+ }
+ }
+ if (os->probability == 0) {
+ ovs_fatal(0, "non-zero \"probability\" must be specified on sample");
+ }
+}
+
+static void
+parse_named_action(enum ofputil_action_code code,
+ char *arg, struct ofpbuf *ofpacts)
+{
+ struct ofpact_tunnel *tunnel;
+ uint16_t vid;
+ uint16_t ethertype;
+ ovs_be32 ip;
+ uint8_t pcp;
+ uint8_t tos;