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 enum ofperr nx_pull_raw(const uint8_t *p, unsigned int match_len, bool strict, struct match *match, ovs_be64 *cookie, ovs_be64 *cookie_mask) { uint32_t header; ovs_assert((cookie != NULL) == (cookie_mask != NULL)); match_init_catchall(match); if (cookie) { *cookie = *cookie_mask = htonll(0); } if (!match_len) { return 0; } for (; (header = nx_entry_ok(p, match_len)) != 0; p += 4 + NXM_LENGTH(header), match_len -= 4 + NXM_LENGTH(header)) { const struct mf_field *mf; enum ofperr error; mf = mf_from_nxm_header(header); if (!mf) { if (strict) { error = OFPERR_OFPBMC_BAD_FIELD; } else { continue; } } else if (!mf_are_prereqs_ok(mf, &match->flow)) { error = OFPERR_OFPBMC_BAD_PREREQ; } else if (!mf_is_all_wild(mf, &match->wc)) { error = OFPERR_OFPBMC_DUP_FIELD; } else { unsigned int width = mf->n_bytes; union mf_value value; memcpy(&value, p + 4, width); if (!mf_is_value_valid(mf, &value)) { error = OFPERR_OFPBMC_BAD_VALUE; } else if (!NXM_HASMASK(header)) { error = 0; mf_set_value(mf, &value, match); } else { union mf_value mask; memcpy(&mask, p + 4 + width, width); if (!mf_is_mask_valid(mf, &mask)) { error = OFPERR_OFPBMC_BAD_MASK; } else { error = check_mask_consistency(p, mf); if (!error) { mf_set(mf, &value, &mask, match); } } } } /* Check if the match is for a cookie rather than a classifier rule. */ if ((header == NXM_NX_COOKIE || header == NXM_NX_COOKIE_W) && cookie) { if (*cookie_mask) { error = OFPERR_OFPBMC_DUP_FIELD; } else { unsigned int width = sizeof *cookie; memcpy(cookie, p + 4, width); if (NXM_HASMASK(header)) { memcpy(cookie_mask, p + 4 + width, width); } else { *cookie_mask = OVS_BE64_MAX; } error = 0; } } if (error) { VLOG_DBG_RL(&rl, "bad nxm_entry %#08"PRIx32" (vendor=%"PRIu32", " "field=%"PRIu32", hasmask=%"PRIu32", len=%"PRIu32"), " "(%s)", header, NXM_VENDOR(header), NXM_FIELD(header), NXM_HASMASK(header), NXM_LENGTH(header), ofperr_to_string(error)); return error; } } return match_len ? OFPERR_OFPBMC_BAD_LEN : 0; }