mirror of
https://github.com/openvswitch/ovs
synced 2025-09-05 08:45:23 +00:00
ofp-actions: Fix variable length meta-flow OXMs.
Previously, if a flow action that involves a tunnel metadata meta-flow field is dumped from vswitchd, the replied field length in the OXM header is filled with the maximum possible field length, instead of the length configured in the tunnel TLV mapping table. To solve this issue, this patch introduces the following changes. In order to maintain the correct length of variable length mf_fields (i.e. tun_metadata), this patch creates a per-switch based map (struct vl_mff_map) that hosts the variable length mf_fields. This map is updated when a controller adds/deletes tlv-mapping entries to/from a switch. Although the per-swtch based vl_mff_map only hosts tun_metadata for now, it is able to support new variable length mf_fields in the future. With this commit, when a switch decodes a flow action with mf_field, the switch firstly looks up the global mf_fields map to identify the mf_field type. For the variable length mf_fields, the switch uses the vl_mff_map to get the configured mf_field entries. By lookig up vl_mff_map, the switch can check if the added flow action access beyond the configured size of a variable length mf_field, and the switch reports an ofperr if the controller adds a flow with unmapped variable length mf_field. Later on, when a controller request flows from the switch, with the per-switch based mf_fields, the switch will encode the OXM header with correct length for variable length mf_fields. To use the vl_mff_map for decoding flow actions, extract-ofp-actions is updated to pass the vl_mff_map to the required action decoding functions. Also, a new error code is introduced to identify a flow with an invalid variable length mf_field. Moreover, a testcase is added to prevent future regressions. Committer notes: - Factor out common code - Style fixups - Rename OFPERR_NXFMFC_INVALID_VL_MFF -> OFPERR_NXFMFC_INVALID_TLV_FIELD VMWare-BZ: #1768370 Reported-by: Harold Lim <haroldl@vmware.com> Suggested-by: Joe Stringer <joe@ovn.org> Suggested-by: Jarno Rajahalme <jarno@ovn.org> Signed-off-by: Yi-Hung Wei <yihung.wei@gmail.com> Signed-off-by: Joe Stringer <joe@ovn.org>
This commit is contained in:
committed by
Joe Stringer
parent
dc2dab6e6d
commit
04f48a68c4
@@ -114,6 +114,12 @@ OFP_ASSERT(sizeof(struct ext_action_header) == 16);
|
||||
* # "void": The action is just a (standard or vendor extension)
|
||||
* header.
|
||||
*
|
||||
* # Optionally, one may add "VLMFF" in the end of the second part if
|
||||
* the Openflow action may use a variable length meta-flow field
|
||||
* (i.e. tun_metadata). Adding "VLMFF" will pass the per-switch based
|
||||
* variable length meta-flow field mapping map (struct vl_mff_map) to
|
||||
* the corresponding action decoding function.
|
||||
*
|
||||
* - Optional additional text enclosed in square brackets is commentary for
|
||||
* the human reader.
|
||||
*/
|
||||
@@ -226,26 +232,26 @@ enum ofp_raw_action_type {
|
||||
/* NX1.0+(21): struct nx_action_cnt_ids, ... */
|
||||
NXAST_RAW_DEC_TTL_CNT_IDS,
|
||||
|
||||
/* OF1.2-1.4(25): struct ofp12_action_set_field, ... */
|
||||
/* OF1.2-1.4(25): struct ofp12_action_set_field, ... VLMFF */
|
||||
OFPAT_RAW12_SET_FIELD,
|
||||
/* OF1.5+(25): struct ofp12_action_set_field, ... */
|
||||
/* OF1.5+(25): struct ofp12_action_set_field, ... VLMFF */
|
||||
OFPAT_RAW15_SET_FIELD,
|
||||
/* NX1.0-1.4(7): struct nx_action_reg_load.
|
||||
/* NX1.0-1.4(7): struct nx_action_reg_load. VLMFF
|
||||
*
|
||||
* [In OpenFlow 1.5, set_field is a superset of reg_load functionality, so
|
||||
* we drop reg_load.] */
|
||||
NXAST_RAW_REG_LOAD,
|
||||
/* NX1.0-1.4(33): struct ext_action_header, ...
|
||||
/* NX1.0-1.4(33): struct ext_action_header, ... VLMFF
|
||||
*
|
||||
* [In OpenFlow 1.5, set_field is a superset of reg_load2 functionality, so
|
||||
* we drop reg_load2.] */
|
||||
NXAST_RAW_REG_LOAD2,
|
||||
|
||||
/* OF1.5+(28): struct ofp15_action_copy_field, ... */
|
||||
/* OF1.5+(28): struct ofp15_action_copy_field, ... VLMFF */
|
||||
OFPAT_RAW15_COPY_FIELD,
|
||||
/* ONF1.3-1.4(3200): struct onf_action_copy_field, ... */
|
||||
/* ONF1.3-1.4(3200): struct onf_action_copy_field, ... VLMFF */
|
||||
ONFACT_RAW13_COPY_FIELD,
|
||||
/* NX1.0-1.4(6): struct nx_action_reg_move, ... */
|
||||
/* NX1.0-1.4(6): struct nx_action_reg_move, ... VLMFF */
|
||||
NXAST_RAW_REG_MOVE,
|
||||
|
||||
/* ## ------------------------- ## */
|
||||
@@ -270,20 +276,20 @@ enum ofp_raw_action_type {
|
||||
/* NX1.0+(8): struct nx_action_note, ... */
|
||||
NXAST_RAW_NOTE,
|
||||
|
||||
/* NX1.0+(10): struct nx_action_multipath. */
|
||||
/* NX1.0+(10): struct nx_action_multipath. VLMFF */
|
||||
NXAST_RAW_MULTIPATH,
|
||||
|
||||
/* NX1.0+(12): struct nx_action_bundle, ... */
|
||||
NXAST_RAW_BUNDLE,
|
||||
/* NX1.0+(13): struct nx_action_bundle, ... */
|
||||
/* NX1.0+(13): struct nx_action_bundle, ... VLMFF */
|
||||
NXAST_RAW_BUNDLE_LOAD,
|
||||
|
||||
/* NX1.0+(15): struct nx_action_output_reg. */
|
||||
/* NX1.0+(15): struct nx_action_output_reg. VLMFF */
|
||||
NXAST_RAW_OUTPUT_REG,
|
||||
/* NX1.0+(32): struct nx_action_output_reg2. */
|
||||
/* NX1.0+(32): struct nx_action_output_reg2. VLMFF */
|
||||
NXAST_RAW_OUTPUT_REG2,
|
||||
|
||||
/* NX1.0+(16): struct nx_action_learn, ... */
|
||||
/* NX1.0+(16): struct nx_action_learn, ... VLMFF */
|
||||
NXAST_RAW_LEARN,
|
||||
|
||||
/* NX1.0+(17): void. */
|
||||
@@ -300,10 +306,10 @@ enum ofp_raw_action_type {
|
||||
/* NX1.0+(22): struct nx_action_write_metadata. */
|
||||
NXAST_RAW_WRITE_METADATA,
|
||||
|
||||
/* NX1.0+(27): struct nx_action_stack. */
|
||||
/* NX1.0+(27): struct nx_action_stack. VLMFF */
|
||||
NXAST_RAW_STACK_PUSH,
|
||||
|
||||
/* NX1.0+(28): struct nx_action_stack. */
|
||||
/* NX1.0+(28): struct nx_action_stack. VLMFF */
|
||||
NXAST_RAW_STACK_POP,
|
||||
|
||||
/* NX1.0+(29): struct nx_action_sample. */
|
||||
@@ -316,7 +322,7 @@ enum ofp_raw_action_type {
|
||||
/* NX1.0+(34): struct nx_action_conjunction. */
|
||||
NXAST_RAW_CONJUNCTION,
|
||||
|
||||
/* NX1.0+(35): struct nx_action_conntrack, ... */
|
||||
/* NX1.0+(35): struct nx_action_conntrack, ... VLMFF */
|
||||
NXAST_RAW_CT,
|
||||
|
||||
/* NX1.0+(36): struct nx_action_nat, ... */
|
||||
@@ -325,7 +331,7 @@ enum ofp_raw_action_type {
|
||||
/* NX1.0+(39): struct nx_action_output_trunc. */
|
||||
NXAST_RAW_OUTPUT_TRUNC,
|
||||
|
||||
/* NX1.0+(42): struct ext_action_header, ... */
|
||||
/* NX1.0+(42): struct ext_action_header, ... VLMFF */
|
||||
NXAST_RAW_CLONE,
|
||||
|
||||
/* NX1.0+(43): void. */
|
||||
@@ -397,7 +403,8 @@ static char *OVS_WARN_UNUSED_RESULT ofpacts_parse(
|
||||
static enum ofperr ofpacts_pull_openflow_actions__(
|
||||
struct ofpbuf *openflow, unsigned int actions_len,
|
||||
enum ofp_version version, uint32_t allowed_ovsinsts,
|
||||
struct ofpbuf *ofpacts, enum ofpact_type outer_action);
|
||||
struct ofpbuf *ofpacts, enum ofpact_type outer_action,
|
||||
const struct vl_mff_map *vl_mff_map);
|
||||
static char * OVS_WARN_UNUSED_RESULT ofpacts_parse_copy(
|
||||
const char *s_, struct ofpbuf *ofpacts,
|
||||
enum ofputil_protocol *usable_protocols,
|
||||
@@ -1112,6 +1119,7 @@ OFP_ASSERT(sizeof(struct nx_action_output_reg2) == 24);
|
||||
static enum ofperr
|
||||
decode_NXAST_RAW_OUTPUT_REG(const struct nx_action_output_reg *naor,
|
||||
enum ofp_version ofp_version OVS_UNUSED,
|
||||
const struct vl_mff_map *vl_mff_map,
|
||||
struct ofpbuf *out)
|
||||
{
|
||||
struct ofpact_output_reg *output_reg;
|
||||
@@ -1122,17 +1130,22 @@ decode_NXAST_RAW_OUTPUT_REG(const struct nx_action_output_reg *naor,
|
||||
|
||||
output_reg = ofpact_put_OUTPUT_REG(out);
|
||||
output_reg->ofpact.raw = NXAST_RAW_OUTPUT_REG;
|
||||
output_reg->src.field = mf_from_nxm_header(ntohl(naor->src));
|
||||
output_reg->src.field = mf_from_nxm_header(ntohl(naor->src), vl_mff_map);
|
||||
output_reg->src.ofs = nxm_decode_ofs(naor->ofs_nbits);
|
||||
output_reg->src.n_bits = nxm_decode_n_bits(naor->ofs_nbits);
|
||||
output_reg->max_len = ntohs(naor->max_len);
|
||||
|
||||
if (mf_vl_mff_invalid(output_reg->src.field, vl_mff_map)) {
|
||||
return OFPERR_NXFMFC_INVALID_TLV_FIELD;
|
||||
}
|
||||
|
||||
return mf_check_src(&output_reg->src, NULL);
|
||||
}
|
||||
|
||||
static enum ofperr
|
||||
decode_NXAST_RAW_OUTPUT_REG2(const struct nx_action_output_reg2 *naor,
|
||||
enum ofp_version ofp_version OVS_UNUSED,
|
||||
const struct vl_mff_map *vl_mff_map,
|
||||
struct ofpbuf *out)
|
||||
{
|
||||
struct ofpact_output_reg *output_reg;
|
||||
@@ -1145,7 +1158,8 @@ decode_NXAST_RAW_OUTPUT_REG2(const struct nx_action_output_reg2 *naor,
|
||||
struct ofpbuf b = ofpbuf_const_initializer(naor, ntohs(naor->len));
|
||||
ofpbuf_pull(&b, OBJECT_OFFSETOF(naor, pad));
|
||||
|
||||
enum ofperr error = nx_pull_header(&b, &output_reg->src.field, NULL);
|
||||
enum ofperr error = nx_pull_header(&b, vl_mff_map, &output_reg->src.field,
|
||||
NULL);
|
||||
if (error) {
|
||||
return error;
|
||||
}
|
||||
@@ -1174,14 +1188,14 @@ encode_OUTPUT_REG(const struct ofpact_output_reg *output_reg,
|
||||
naor->max_len = htons(output_reg->max_len);
|
||||
|
||||
out->size = size - sizeof naor->pad;
|
||||
nx_put_header(out, output_reg->src.field->id, 0, false);
|
||||
nx_put_mff_header(out, output_reg->src.field, 0, false);
|
||||
out->size = size;
|
||||
} else {
|
||||
struct nx_action_output_reg *naor = put_NXAST_OUTPUT_REG(out);
|
||||
|
||||
naor->ofs_nbits = nxm_encode_ofs_nbits(output_reg->src.ofs,
|
||||
output_reg->src.n_bits);
|
||||
naor->src = htonl(mf_nxm_header(output_reg->src.field->id));
|
||||
naor->src = htonl(nxm_header_from_mff(output_reg->src.field));
|
||||
naor->max_len = htons(output_reg->max_len);
|
||||
}
|
||||
}
|
||||
@@ -1271,7 +1285,7 @@ OFP_ASSERT(sizeof(struct nx_action_bundle) == 32);
|
||||
|
||||
static enum ofperr
|
||||
decode_bundle(bool load, const struct nx_action_bundle *nab,
|
||||
struct ofpbuf *ofpacts)
|
||||
const struct vl_mff_map *vl_mff_map, struct ofpbuf *ofpacts)
|
||||
{
|
||||
static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
|
||||
struct ofpact_bundle *bundle;
|
||||
@@ -1308,9 +1322,12 @@ decode_bundle(bool load, const struct nx_action_bundle *nab,
|
||||
}
|
||||
|
||||
if (load) {
|
||||
bundle->dst.field = mf_from_nxm_header(ntohl(nab->dst));
|
||||
bundle->dst.field = mf_from_nxm_header(ntohl(nab->dst), vl_mff_map);
|
||||
bundle->dst.ofs = nxm_decode_ofs(nab->ofs_nbits);
|
||||
bundle->dst.n_bits = nxm_decode_n_bits(nab->ofs_nbits);
|
||||
if (mf_vl_mff_invalid(bundle->dst.field, vl_mff_map)) {
|
||||
return OFPERR_NXFMFC_INVALID_TLV_FIELD;
|
||||
}
|
||||
|
||||
if (bundle->dst.n_bits < 16) {
|
||||
VLOG_WARN_RL(&rl, "bundle_load action requires at least 16 bit "
|
||||
@@ -1351,15 +1368,16 @@ decode_NXAST_RAW_BUNDLE(const struct nx_action_bundle *nab,
|
||||
enum ofp_version ofp_version OVS_UNUSED,
|
||||
struct ofpbuf *out)
|
||||
{
|
||||
return decode_bundle(false, nab, out);
|
||||
return decode_bundle(false, nab, NULL, out);
|
||||
}
|
||||
|
||||
static enum ofperr
|
||||
decode_NXAST_RAW_BUNDLE_LOAD(const struct nx_action_bundle *nab,
|
||||
enum ofp_version ofp_version OVS_UNUSED,
|
||||
const struct vl_mff_map *vl_mff_map,
|
||||
struct ofpbuf *out)
|
||||
{
|
||||
return decode_bundle(true, nab, out);
|
||||
return decode_bundle(true, nab, vl_mff_map, out);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1384,7 +1402,7 @@ encode_BUNDLE(const struct ofpact_bundle *bundle,
|
||||
if (bundle->dst.field) {
|
||||
nab->ofs_nbits = nxm_encode_ofs_nbits(bundle->dst.ofs,
|
||||
bundle->dst.n_bits);
|
||||
nab->dst = htonl(mf_nxm_header(bundle->dst.field->id));
|
||||
nab->dst = htonl(nxm_header_from_mff(bundle->dst.field));
|
||||
}
|
||||
|
||||
slaves = ofpbuf_put_zeros(out, slaves_len);
|
||||
@@ -2262,6 +2280,7 @@ OFP_ASSERT(sizeof(struct nx_action_reg_move) == 16);
|
||||
static enum ofperr
|
||||
decode_copy_field__(ovs_be16 src_offset, ovs_be16 dst_offset, ovs_be16 n_bits,
|
||||
const void *action, ovs_be16 action_len, size_t oxm_offset,
|
||||
const struct vl_mff_map *vl_mff_map,
|
||||
struct ofpbuf *ofpacts)
|
||||
{
|
||||
struct ofpact_reg_move *move = ofpact_put_REG_MOVE(ofpacts);
|
||||
@@ -2274,11 +2293,11 @@ decode_copy_field__(ovs_be16 src_offset, ovs_be16 dst_offset, ovs_be16 n_bits,
|
||||
struct ofpbuf b = ofpbuf_const_initializer(action, ntohs(action_len));
|
||||
ofpbuf_pull(&b, oxm_offset);
|
||||
|
||||
enum ofperr error = nx_pull_header(&b, &move->src.field, NULL);
|
||||
enum ofperr error = nx_pull_header(&b, vl_mff_map, &move->src.field, NULL);
|
||||
if (error) {
|
||||
return error;
|
||||
}
|
||||
error = nx_pull_header(&b, &move->dst.field, NULL);
|
||||
error = nx_pull_header(&b, vl_mff_map, &move->dst.field, NULL);
|
||||
if (error) {
|
||||
return error;
|
||||
}
|
||||
@@ -2293,26 +2312,31 @@ decode_copy_field__(ovs_be16 src_offset, ovs_be16 dst_offset, ovs_be16 n_bits,
|
||||
static enum ofperr
|
||||
decode_OFPAT_RAW15_COPY_FIELD(const struct ofp15_action_copy_field *oacf,
|
||||
enum ofp_version ofp_version OVS_UNUSED,
|
||||
const struct vl_mff_map *vl_mff_map,
|
||||
struct ofpbuf *ofpacts)
|
||||
{
|
||||
return decode_copy_field__(oacf->src_offset, oacf->dst_offset,
|
||||
oacf->n_bits, oacf, oacf->len,
|
||||
OBJECT_OFFSETOF(oacf, pad2), ofpacts);
|
||||
OBJECT_OFFSETOF(oacf, pad2), vl_mff_map,
|
||||
ofpacts);
|
||||
}
|
||||
|
||||
static enum ofperr
|
||||
decode_ONFACT_RAW13_COPY_FIELD(const struct onf_action_copy_field *oacf,
|
||||
enum ofp_version ofp_version OVS_UNUSED,
|
||||
const struct vl_mff_map *vl_mff_map,
|
||||
struct ofpbuf *ofpacts)
|
||||
{
|
||||
return decode_copy_field__(oacf->src_offset, oacf->dst_offset,
|
||||
oacf->n_bits, oacf, oacf->len,
|
||||
OBJECT_OFFSETOF(oacf, pad3), ofpacts);
|
||||
OBJECT_OFFSETOF(oacf, pad3), vl_mff_map,
|
||||
ofpacts);
|
||||
}
|
||||
|
||||
static enum ofperr
|
||||
decode_NXAST_RAW_REG_MOVE(const struct nx_action_reg_move *narm,
|
||||
enum ofp_version ofp_version OVS_UNUSED,
|
||||
const struct vl_mff_map *vl_mff_map,
|
||||
struct ofpbuf *ofpacts)
|
||||
{
|
||||
struct ofpact_reg_move *move = ofpact_put_REG_MOVE(ofpacts);
|
||||
@@ -2325,14 +2349,15 @@ decode_NXAST_RAW_REG_MOVE(const struct nx_action_reg_move *narm,
|
||||
struct ofpbuf b = ofpbuf_const_initializer(narm, ntohs(narm->len));
|
||||
ofpbuf_pull(&b, sizeof *narm);
|
||||
|
||||
enum ofperr error = nx_pull_header(&b, &move->src.field, NULL);
|
||||
enum ofperr error = nx_pull_header(&b, vl_mff_map, &move->src.field, NULL);
|
||||
if (error) {
|
||||
return error;
|
||||
}
|
||||
error = nx_pull_header(&b, &move->dst.field, NULL);
|
||||
error = nx_pull_header(&b, vl_mff_map, &move->dst.field, NULL);
|
||||
if (error) {
|
||||
return error;
|
||||
}
|
||||
|
||||
if (!is_all_zeros(b.data, b.size)) {
|
||||
return OFPERR_NXBRC_MUST_BE_ZERO;
|
||||
}
|
||||
@@ -2357,8 +2382,8 @@ encode_REG_MOVE(const struct ofpact_reg_move *move,
|
||||
copy->src_offset = htons(move->src.ofs);
|
||||
copy->dst_offset = htons(move->dst.ofs);
|
||||
out->size = out->size - sizeof copy->pad2;
|
||||
nx_put_header(out, move->src.field->id, ofp_version, false);
|
||||
nx_put_header(out, move->dst.field->id, ofp_version, false);
|
||||
nx_put_mff_header(out, move->src.field, ofp_version, false);
|
||||
nx_put_mff_header(out, move->dst.field, ofp_version, false);
|
||||
} else if (ofp_version == OFP13_VERSION
|
||||
&& move->ofpact.raw == ONFACT_RAW13_COPY_FIELD) {
|
||||
struct onf_action_copy_field *copy = put_ONFACT13_COPY_FIELD(out);
|
||||
@@ -2366,15 +2391,15 @@ encode_REG_MOVE(const struct ofpact_reg_move *move,
|
||||
copy->src_offset = htons(move->src.ofs);
|
||||
copy->dst_offset = htons(move->dst.ofs);
|
||||
out->size = out->size - sizeof copy->pad3;
|
||||
nx_put_header(out, move->src.field->id, ofp_version, false);
|
||||
nx_put_header(out, move->dst.field->id, ofp_version, false);
|
||||
nx_put_mff_header(out, move->src.field, ofp_version, false);
|
||||
nx_put_mff_header(out, move->dst.field, ofp_version, false);
|
||||
} else {
|
||||
struct nx_action_reg_move *narm = put_NXAST_REG_MOVE(out);
|
||||
narm->n_bits = htons(move->dst.n_bits);
|
||||
narm->src_ofs = htons(move->src.ofs);
|
||||
narm->dst_ofs = htons(move->dst.ofs);
|
||||
nx_put_header(out, move->src.field->id, 0, false);
|
||||
nx_put_header(out, move->dst.field->id, 0, false);
|
||||
nx_put_mff_header(out, move->src.field, 0, false);
|
||||
nx_put_mff_header(out, move->dst.field, 0, false);
|
||||
}
|
||||
pad_ofpat(out, start_ofs);
|
||||
}
|
||||
@@ -2454,14 +2479,15 @@ OFP_ASSERT(sizeof(struct nx_action_reg_load) == 24);
|
||||
|
||||
static enum ofperr
|
||||
decode_ofpat_set_field(const struct ofp12_action_set_field *oasf,
|
||||
bool may_mask, struct ofpbuf *ofpacts)
|
||||
bool may_mask, const struct vl_mff_map *vl_mff_map,
|
||||
struct ofpbuf *ofpacts)
|
||||
{
|
||||
struct ofpbuf b = ofpbuf_const_initializer(oasf, ntohs(oasf->len));
|
||||
ofpbuf_pull(&b, OBJECT_OFFSETOF(oasf, pad));
|
||||
|
||||
union mf_value value, mask;
|
||||
const struct mf_field *field;
|
||||
enum ofperr error = nx_pull_entry(&b, &field, &value,
|
||||
enum ofperr error = nx_pull_entry(&b, vl_mff_map, &field, &value,
|
||||
may_mask ? &mask : NULL);
|
||||
if (error) {
|
||||
return (error == OFPERR_OFPBMC_BAD_MASK
|
||||
@@ -2512,30 +2538,37 @@ decode_ofpat_set_field(const struct ofp12_action_set_field *oasf,
|
||||
static enum ofperr
|
||||
decode_OFPAT_RAW12_SET_FIELD(const struct ofp12_action_set_field *oasf,
|
||||
enum ofp_version ofp_version OVS_UNUSED,
|
||||
const struct vl_mff_map *vl_mff_map,
|
||||
struct ofpbuf *ofpacts)
|
||||
{
|
||||
return decode_ofpat_set_field(oasf, false, ofpacts);
|
||||
return decode_ofpat_set_field(oasf, false, vl_mff_map, ofpacts);
|
||||
}
|
||||
|
||||
static enum ofperr
|
||||
decode_OFPAT_RAW15_SET_FIELD(const struct ofp12_action_set_field *oasf,
|
||||
enum ofp_version ofp_version OVS_UNUSED,
|
||||
const struct vl_mff_map *vl_mff_map,
|
||||
struct ofpbuf *ofpacts)
|
||||
{
|
||||
return decode_ofpat_set_field(oasf, true, ofpacts);
|
||||
return decode_ofpat_set_field(oasf, true, vl_mff_map, ofpacts);
|
||||
}
|
||||
|
||||
static enum ofperr
|
||||
decode_NXAST_RAW_REG_LOAD(const struct nx_action_reg_load *narl,
|
||||
enum ofp_version ofp_version OVS_UNUSED,
|
||||
const struct vl_mff_map *vl_mff_map,
|
||||
struct ofpbuf *out)
|
||||
{
|
||||
struct mf_subfield dst;
|
||||
enum ofperr error;
|
||||
|
||||
dst.field = mf_from_nxm_header(ntohl(narl->dst));
|
||||
dst.field = mf_from_nxm_header(ntohl(narl->dst), vl_mff_map);
|
||||
dst.ofs = nxm_decode_ofs(narl->ofs_nbits);
|
||||
dst.n_bits = nxm_decode_n_bits(narl->ofs_nbits);
|
||||
if (mf_vl_mff_invalid(dst.field, vl_mff_map)) {
|
||||
return OFPERR_NXFMFC_INVALID_TLV_FIELD;
|
||||
}
|
||||
|
||||
error = mf_check_dst(&dst, NULL);
|
||||
if (error) {
|
||||
return error;
|
||||
@@ -2561,6 +2594,7 @@ decode_NXAST_RAW_REG_LOAD(const struct nx_action_reg_load *narl,
|
||||
static enum ofperr
|
||||
decode_NXAST_RAW_REG_LOAD2(const struct ext_action_header *eah,
|
||||
enum ofp_version ofp_version OVS_UNUSED,
|
||||
const struct vl_mff_map *vl_mff_map,
|
||||
struct ofpbuf *out)
|
||||
{
|
||||
struct ofpbuf b = ofpbuf_const_initializer(eah, ntohs(eah->len));
|
||||
@@ -2568,7 +2602,7 @@ decode_NXAST_RAW_REG_LOAD2(const struct ext_action_header *eah,
|
||||
|
||||
union mf_value value, mask;
|
||||
const struct mf_field *field;
|
||||
enum ofperr error = nx_pull_entry(&b, &field, &value, &mask);
|
||||
enum ofperr error = nx_pull_entry(&b, vl_mff_map, &field, &value, &mask);
|
||||
if (error) {
|
||||
return error;
|
||||
}
|
||||
@@ -2599,7 +2633,7 @@ put_set_field(struct ofpbuf *openflow, enum ofp_version ofp_version,
|
||||
|
||||
oasf = put_OFPAT12_SET_FIELD(openflow);
|
||||
openflow->size = openflow->size - sizeof oasf->pad;
|
||||
nx_put_entry(openflow, field, ofp_version, &value, NULL);
|
||||
nx_put_entry(openflow, mf_from_id(field), ofp_version, &value, NULL);
|
||||
pad_ofpat(openflow, start_ofs);
|
||||
}
|
||||
|
||||
@@ -2611,7 +2645,7 @@ put_reg_load(struct ofpbuf *openflow,
|
||||
|
||||
struct nx_action_reg_load *narl = put_NXAST_REG_LOAD(openflow);
|
||||
narl->ofs_nbits = nxm_encode_ofs_nbits(dst->ofs, dst->n_bits);
|
||||
narl->dst = htonl(mf_nxm_header(dst->field->id));
|
||||
narl->dst = htonl(nxm_header_from_mff(dst->field));
|
||||
narl->value = htonll(value);
|
||||
}
|
||||
|
||||
@@ -2653,7 +2687,7 @@ set_field_to_nxast(const struct ofpact_set_field *sf, struct ofpbuf *openflow)
|
||||
|
||||
eah = put_NXAST_REG_LOAD2(openflow);
|
||||
openflow->size = openflow->size - sizeof eah->pad;
|
||||
nx_put_entry(openflow, sf->field->id, 0, sf->value,
|
||||
nx_put_entry(openflow, sf->field, 0, sf->value,
|
||||
ofpact_set_field_mask(sf));
|
||||
pad_ofpat(openflow, start_ofs);
|
||||
} else {
|
||||
@@ -2799,7 +2833,7 @@ set_field_to_set_field(const struct ofpact_set_field *sf,
|
||||
|
||||
oasf = put_OFPAT12_SET_FIELD(out);
|
||||
out->size = out->size - sizeof oasf->pad;
|
||||
nx_put_entry(out, sf->field->id, ofp_version, sf->value,
|
||||
nx_put_entry(out, sf->field, ofp_version, sf->value,
|
||||
ofpact_set_field_mask(sf));
|
||||
pad_ofpat(out, start_ofs);
|
||||
}
|
||||
@@ -3074,14 +3108,15 @@ OFP_ASSERT(sizeof(struct nx_action_stack) == 24);
|
||||
|
||||
static enum ofperr
|
||||
decode_stack_action(const struct nx_action_stack *nasp,
|
||||
const struct vl_mff_map *vl_mff_map,
|
||||
struct ofpact_stack *stack_action)
|
||||
{
|
||||
stack_action->subfield.ofs = ntohs(nasp->offset);
|
||||
|
||||
struct ofpbuf b = ofpbuf_const_initializer(nasp, sizeof *nasp);
|
||||
ofpbuf_pull(&b, OBJECT_OFFSETOF(nasp, pad));
|
||||
enum ofperr error = nx_pull_header(&b, &stack_action->subfield.field,
|
||||
NULL);
|
||||
enum ofperr error = nx_pull_header(&b, vl_mff_map,
|
||||
&stack_action->subfield.field, NULL);
|
||||
if (error) {
|
||||
return error;
|
||||
}
|
||||
@@ -3097,20 +3132,22 @@ decode_stack_action(const struct nx_action_stack *nasp,
|
||||
static enum ofperr
|
||||
decode_NXAST_RAW_STACK_PUSH(const struct nx_action_stack *nasp,
|
||||
enum ofp_version ofp_version OVS_UNUSED,
|
||||
const struct vl_mff_map *vl_mff_map,
|
||||
struct ofpbuf *ofpacts)
|
||||
{
|
||||
struct ofpact_stack *push = ofpact_put_STACK_PUSH(ofpacts);
|
||||
enum ofperr error = decode_stack_action(nasp, push);
|
||||
enum ofperr error = decode_stack_action(nasp, vl_mff_map, push);
|
||||
return error ? error : nxm_stack_push_check(push, NULL);
|
||||
}
|
||||
|
||||
static enum ofperr
|
||||
decode_NXAST_RAW_STACK_POP(const struct nx_action_stack *nasp,
|
||||
enum ofp_version ofp_version OVS_UNUSED,
|
||||
const struct vl_mff_map *vl_mff_map,
|
||||
struct ofpbuf *ofpacts)
|
||||
{
|
||||
struct ofpact_stack *pop = ofpact_put_STACK_POP(ofpacts);
|
||||
enum ofperr error = decode_stack_action(nasp, pop);
|
||||
enum ofperr error = decode_stack_action(nasp, vl_mff_map, pop);
|
||||
return error ? error : nxm_stack_pop_check(pop, NULL);
|
||||
}
|
||||
|
||||
@@ -3125,7 +3162,7 @@ encode_STACK_op(const struct ofpact_stack *stack_action,
|
||||
|
||||
ofpbuf_use_stack(&b, nasp, ntohs(nasp->len));
|
||||
ofpbuf_put_uninit(&b, OBJECT_OFFSETOF(nasp, pad));
|
||||
nx_put_header(&b, stack_action->subfield.field->id, 0, false);
|
||||
nx_put_mff_header(&b, stack_action->subfield.field, 0, false);
|
||||
n_bits = htons(stack_action->subfield.n_bits);
|
||||
ofpbuf_put(&b, &n_bits, sizeof n_bits);
|
||||
}
|
||||
@@ -4239,12 +4276,17 @@ get_be32(const void **pp)
|
||||
return value;
|
||||
}
|
||||
|
||||
static void
|
||||
get_subfield(int n_bits, const void **p, struct mf_subfield *sf)
|
||||
static enum ofperr
|
||||
get_subfield(int n_bits, const void **p, struct mf_subfield *sf,
|
||||
const struct vl_mff_map *vl_mff_map)
|
||||
{
|
||||
sf->field = mf_from_nxm_header(ntohl(get_be32(p)));
|
||||
sf->field = mf_from_nxm_header(ntohl(get_be32(p)), vl_mff_map);
|
||||
sf->ofs = ntohs(get_be16(p));
|
||||
sf->n_bits = n_bits;
|
||||
if (mf_vl_mff_invalid(sf->field, vl_mff_map)) {
|
||||
return OFPERR_NXFMFC_INVALID_TLV_FIELD;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
@@ -4275,6 +4317,7 @@ learn_min_len(uint16_t header)
|
||||
static enum ofperr
|
||||
decode_NXAST_RAW_LEARN(const struct nx_action_learn *nal,
|
||||
enum ofp_version ofp_version OVS_UNUSED,
|
||||
const struct vl_mff_map *vl_mff_map,
|
||||
struct ofpbuf *ofpacts)
|
||||
{
|
||||
struct ofpact_learn *learn;
|
||||
@@ -4338,8 +4381,12 @@ decode_NXAST_RAW_LEARN(const struct nx_action_learn *nal,
|
||||
/* Get the source. */
|
||||
const uint8_t *imm = NULL;
|
||||
unsigned int imm_bytes = 0;
|
||||
enum ofperr error;
|
||||
if (spec->src_type == NX_LEARN_SRC_FIELD) {
|
||||
get_subfield(spec->n_bits, &p, &spec->src);
|
||||
error = get_subfield(spec->n_bits, &p, &spec->src, vl_mff_map);
|
||||
if (error) {
|
||||
return error;
|
||||
}
|
||||
} else {
|
||||
int p_bytes = 2 * DIV_ROUND_UP(spec->n_bits, 16);
|
||||
p = (const uint8_t *) p + p_bytes;
|
||||
@@ -4351,7 +4398,10 @@ decode_NXAST_RAW_LEARN(const struct nx_action_learn *nal,
|
||||
/* Get the destination. */
|
||||
if (spec->dst_type == NX_LEARN_DST_MATCH ||
|
||||
spec->dst_type == NX_LEARN_DST_LOAD) {
|
||||
get_subfield(spec->n_bits, &p, &spec->dst);
|
||||
error = get_subfield(spec->n_bits, &p, &spec->dst, vl_mff_map);
|
||||
if (error) {
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
if (imm) {
|
||||
@@ -4418,7 +4468,7 @@ encode_LEARN(const struct ofpact_learn *learn,
|
||||
put_u16(out, spec->n_bits | spec->dst_type | spec->src_type);
|
||||
|
||||
if (spec->src_type == NX_LEARN_SRC_FIELD) {
|
||||
put_u32(out, mf_nxm_header(spec->src.field->id));
|
||||
put_u32(out, nxm_header_from_mff(spec->src.field));
|
||||
put_u16(out, spec->src.ofs);
|
||||
} else {
|
||||
size_t n_dst_bytes = 2 * DIV_ROUND_UP(spec->n_bits, 16);
|
||||
@@ -4431,7 +4481,7 @@ encode_LEARN(const struct ofpact_learn *learn,
|
||||
|
||||
if (spec->dst_type == NX_LEARN_DST_MATCH ||
|
||||
spec->dst_type == NX_LEARN_DST_LOAD) {
|
||||
put_u32(out, mf_nxm_header(spec->dst.field->id));
|
||||
put_u32(out, nxm_header_from_mff(spec->dst.field));
|
||||
put_u16(out, spec->dst.ofs);
|
||||
}
|
||||
}
|
||||
@@ -4597,6 +4647,7 @@ OFP_ASSERT(sizeof(struct nx_action_multipath) == 32);
|
||||
static enum ofperr
|
||||
decode_NXAST_RAW_MULTIPATH(const struct nx_action_multipath *nam,
|
||||
enum ofp_version ofp_version OVS_UNUSED,
|
||||
const struct vl_mff_map *vl_mff_map,
|
||||
struct ofpbuf *out)
|
||||
{
|
||||
uint32_t n_links = ntohs(nam->max_link) + 1;
|
||||
@@ -4609,10 +4660,14 @@ decode_NXAST_RAW_MULTIPATH(const struct nx_action_multipath *nam,
|
||||
mp->algorithm = ntohs(nam->algorithm);
|
||||
mp->max_link = ntohs(nam->max_link);
|
||||
mp->arg = ntohl(nam->arg);
|
||||
mp->dst.field = mf_from_nxm_header(ntohl(nam->dst));
|
||||
mp->dst.field = mf_from_nxm_header(ntohl(nam->dst), vl_mff_map);
|
||||
mp->dst.ofs = nxm_decode_ofs(nam->ofs_nbits);
|
||||
mp->dst.n_bits = nxm_decode_n_bits(nam->ofs_nbits);
|
||||
|
||||
if (mf_vl_mff_invalid(mp->dst.field, vl_mff_map)) {
|
||||
return OFPERR_NXFMFC_INVALID_TLV_FIELD;
|
||||
}
|
||||
|
||||
if (!flow_hash_fields_valid(mp->fields)) {
|
||||
VLOG_WARN_RL(&rl, "unsupported fields %d", (int) mp->fields);
|
||||
return OFPERR_OFPBAC_BAD_ARGUMENT;
|
||||
@@ -4643,7 +4698,7 @@ encode_MULTIPATH(const struct ofpact_multipath *mp,
|
||||
nam->max_link = htons(mp->max_link);
|
||||
nam->arg = htonl(mp->arg);
|
||||
nam->ofs_nbits = nxm_encode_ofs_nbits(mp->dst.ofs, mp->dst.n_bits);
|
||||
nam->dst = htonl(mf_nxm_header(mp->dst.field->id));
|
||||
nam->dst = htonl(nxm_header_from_mff(mp->dst.field));
|
||||
}
|
||||
|
||||
static char * OVS_WARN_UNUSED_RESULT
|
||||
@@ -4797,8 +4852,9 @@ format_UNROLL_XLATE(const struct ofpact_unroll_xlate *a, struct ds *s)
|
||||
|
||||
static enum ofperr
|
||||
decode_NXAST_RAW_CLONE(const struct ext_action_header *eah,
|
||||
enum ofp_version ofp_version,
|
||||
struct ofpbuf *out)
|
||||
enum ofp_version ofp_version,
|
||||
const struct vl_mff_map *vl_mff_map,
|
||||
struct ofpbuf *out)
|
||||
{
|
||||
int error;
|
||||
struct ofpbuf openflow;
|
||||
@@ -4812,7 +4868,7 @@ decode_NXAST_RAW_CLONE(const struct ext_action_header *eah,
|
||||
error = ofpacts_pull_openflow_actions__(&openflow, openflow.size,
|
||||
ofp_version,
|
||||
1u << OVSINST_OFPIT11_APPLY_ACTIONS,
|
||||
out, 0);
|
||||
out, 0, vl_mff_map);
|
||||
clone = ofpbuf_push_uninit(out, sizeof *clone);
|
||||
out->header = &clone->ofpact;
|
||||
ofpact_finish_CLONE(out, &clone);
|
||||
@@ -5258,14 +5314,20 @@ OFP_ASSERT(sizeof(struct nx_action_conntrack) == 24);
|
||||
|
||||
static enum ofperr
|
||||
decode_ct_zone(const struct nx_action_conntrack *nac,
|
||||
struct ofpact_conntrack *out)
|
||||
struct ofpact_conntrack *out,
|
||||
const struct vl_mff_map *vl_mff_map)
|
||||
{
|
||||
if (nac->zone_src) {
|
||||
enum ofperr error;
|
||||
|
||||
out->zone_src.field = mf_from_nxm_header(ntohl(nac->zone_src));
|
||||
out->zone_src.field = mf_from_nxm_header(ntohl(nac->zone_src),
|
||||
vl_mff_map);
|
||||
out->zone_src.ofs = nxm_decode_ofs(nac->zone_ofs_nbits);
|
||||
out->zone_src.n_bits = nxm_decode_n_bits(nac->zone_ofs_nbits);
|
||||
if (mf_vl_mff_invalid(out->zone_src.field, vl_mff_map)) {
|
||||
return OFPERR_NXFMFC_INVALID_TLV_FIELD;
|
||||
}
|
||||
|
||||
error = mf_check_src(&out->zone_src, NULL);
|
||||
if (error) {
|
||||
return error;
|
||||
@@ -5286,13 +5348,14 @@ decode_ct_zone(const struct nx_action_conntrack *nac,
|
||||
|
||||
static enum ofperr
|
||||
decode_NXAST_RAW_CT(const struct nx_action_conntrack *nac,
|
||||
enum ofp_version ofp_version, struct ofpbuf *out)
|
||||
enum ofp_version ofp_version,
|
||||
const struct vl_mff_map *vl_mff_map, struct ofpbuf *out)
|
||||
{
|
||||
const size_t ct_offset = ofpacts_pull(out);
|
||||
struct ofpact_conntrack *conntrack = ofpact_put_CT(out);
|
||||
conntrack->flags = ntohs(nac->flags);
|
||||
|
||||
int error = decode_ct_zone(nac, conntrack);
|
||||
int error = decode_ct_zone(nac, conntrack, vl_mff_map);
|
||||
if (error) {
|
||||
goto out;
|
||||
}
|
||||
@@ -5306,7 +5369,7 @@ decode_NXAST_RAW_CT(const struct nx_action_conntrack *nac,
|
||||
error = ofpacts_pull_openflow_actions__(&openflow, openflow.size,
|
||||
ofp_version,
|
||||
1u << OVSINST_OFPIT11_APPLY_ACTIONS,
|
||||
out, OFPACT_CT);
|
||||
out, OFPACT_CT, vl_mff_map);
|
||||
if (error) {
|
||||
goto out;
|
||||
}
|
||||
@@ -5347,7 +5410,7 @@ encode_CT(const struct ofpact_conntrack *conntrack,
|
||||
nac = put_NXAST_CT(out);
|
||||
nac->flags = htons(conntrack->flags);
|
||||
if (conntrack->zone_src.field) {
|
||||
nac->zone_src = htonl(mf_nxm_header(conntrack->zone_src.field->id));
|
||||
nac->zone_src = htonl(nxm_header_from_mff(conntrack->zone_src.field));
|
||||
nac->zone_ofs_nbits = nxm_encode_ofs_nbits(conntrack->zone_src.ofs,
|
||||
conntrack->zone_src.n_bits);
|
||||
} else {
|
||||
@@ -6191,7 +6254,8 @@ log_bad_action(const struct ofp_action_header *actions, size_t actions_len,
|
||||
|
||||
static enum ofperr
|
||||
ofpacts_decode(const void *actions, size_t actions_len,
|
||||
enum ofp_version ofp_version, struct ofpbuf *ofpacts)
|
||||
enum ofp_version ofp_version,
|
||||
const struct vl_mff_map *vl_mff_map, struct ofpbuf *ofpacts)
|
||||
{
|
||||
struct ofpbuf openflow = ofpbuf_const_initializer(actions, actions_len);
|
||||
while (openflow.size) {
|
||||
@@ -6202,7 +6266,8 @@ ofpacts_decode(const void *actions, size_t actions_len,
|
||||
|
||||
error = ofpact_pull_raw(&openflow, ofp_version, &raw, &arg);
|
||||
if (!error) {
|
||||
error = ofpact_decode(action, raw, ofp_version, arg, ofpacts);
|
||||
error = ofpact_decode(action, raw, ofp_version, arg, vl_mff_map,
|
||||
ofpacts);
|
||||
}
|
||||
|
||||
if (error) {
|
||||
@@ -6219,7 +6284,8 @@ ofpacts_pull_openflow_actions__(struct ofpbuf *openflow,
|
||||
enum ofp_version version,
|
||||
uint32_t allowed_ovsinsts,
|
||||
struct ofpbuf *ofpacts,
|
||||
enum ofpact_type outer_action)
|
||||
enum ofpact_type outer_action,
|
||||
const struct vl_mff_map *vl_mff_map)
|
||||
{
|
||||
const struct ofp_action_header *actions;
|
||||
size_t orig_size = ofpacts->size;
|
||||
@@ -6239,7 +6305,7 @@ ofpacts_pull_openflow_actions__(struct ofpbuf *openflow,
|
||||
return OFPERR_OFPBRC_BAD_LEN;
|
||||
}
|
||||
|
||||
error = ofpacts_decode(actions, actions_len, version, ofpacts);
|
||||
error = ofpacts_decode(actions, actions_len, version, vl_mff_map, ofpacts);
|
||||
if (error) {
|
||||
ofpacts->size = orig_size;
|
||||
return error;
|
||||
@@ -6274,11 +6340,12 @@ enum ofperr
|
||||
ofpacts_pull_openflow_actions(struct ofpbuf *openflow,
|
||||
unsigned int actions_len,
|
||||
enum ofp_version version,
|
||||
const struct vl_mff_map *vl_mff_map,
|
||||
struct ofpbuf *ofpacts)
|
||||
{
|
||||
return ofpacts_pull_openflow_actions__(openflow, actions_len, version,
|
||||
1u << OVSINST_OFPIT11_APPLY_ACTIONS,
|
||||
ofpacts, 0);
|
||||
ofpacts, 0, vl_mff_map);
|
||||
}
|
||||
|
||||
/* OpenFlow 1.1 actions. */
|
||||
@@ -6517,13 +6584,14 @@ ofpacts_execute_action_set(struct ofpbuf *action_list,
|
||||
static enum ofperr
|
||||
ofpacts_decode_for_action_set(const struct ofp_action_header *in,
|
||||
size_t n_in, enum ofp_version version,
|
||||
const struct vl_mff_map *vl_mff_map,
|
||||
struct ofpbuf *out)
|
||||
{
|
||||
enum ofperr error;
|
||||
struct ofpact *a;
|
||||
size_t start = out->size;
|
||||
|
||||
error = ofpacts_decode(in, n_in, version, out);
|
||||
error = ofpacts_decode(in, n_in, version, vl_mff_map, out);
|
||||
|
||||
if (error) {
|
||||
return error;
|
||||
@@ -6821,6 +6889,7 @@ enum ofperr
|
||||
ofpacts_pull_openflow_instructions(struct ofpbuf *openflow,
|
||||
unsigned int instructions_len,
|
||||
enum ofp_version version,
|
||||
const struct vl_mff_map *vl_mff_map,
|
||||
struct ofpbuf *ofpacts)
|
||||
{
|
||||
const struct ofp11_instruction *instructions;
|
||||
@@ -6832,7 +6901,7 @@ ofpacts_pull_openflow_instructions(struct ofpbuf *openflow,
|
||||
return ofpacts_pull_openflow_actions__(openflow, instructions_len,
|
||||
version,
|
||||
(1u << N_OVS_INSTRUCTIONS) - 1,
|
||||
ofpacts, 0);
|
||||
ofpacts, 0, vl_mff_map);
|
||||
}
|
||||
|
||||
if (instructions_len % OFP11_INSTRUCTION_ALIGN != 0) {
|
||||
@@ -6875,7 +6944,8 @@ ofpacts_pull_openflow_instructions(struct ofpbuf *openflow,
|
||||
|
||||
get_actions_from_instruction(insts[OVSINST_OFPIT11_APPLY_ACTIONS],
|
||||
&actions, &actions_len);
|
||||
error = ofpacts_decode(actions, actions_len, version, ofpacts);
|
||||
error = ofpacts_decode(actions, actions_len, version, vl_mff_map,
|
||||
ofpacts);
|
||||
if (error) {
|
||||
goto exit;
|
||||
}
|
||||
@@ -6895,7 +6965,7 @@ ofpacts_pull_openflow_instructions(struct ofpbuf *openflow,
|
||||
get_actions_from_instruction(insts[OVSINST_OFPIT11_WRITE_ACTIONS],
|
||||
&actions, &actions_len);
|
||||
error = ofpacts_decode_for_action_set(actions, actions_len,
|
||||
version, ofpacts);
|
||||
version, vl_mff_map, ofpacts);
|
||||
if (error) {
|
||||
goto exit;
|
||||
}
|
||||
|
Reference in New Issue
Block a user