On 20 January 2017 at 15:12, Yi-Hung Wei <yihung....@gmail.com> wrote: > 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. > > VMWare-BZ: #1768370 > Reported-by: Harold Lim <haro...@vmware.com> > Suggested-by: Joe Stringer <j...@ovn.org> > Suggested-by: Jarno Rajahalme <ja...@ovn.org> > Signed-off-by: Yi-Hung Wei <yihung....@gmail.com>
Thanks for the patch! I wonder about renaming OFPERR_NXFMFC_INVALID_VL_MFF to something like OFPERR_NXFMFC_INVALID_TLV_FIELD, this is slightly less cryptic than VL_MFF to the unknowing eye. Thoughts? <snip> > +/* Updates the tun_metadata mf_field in 'vl_mff_map' according to 'ttm'. > + * This function is supposed to be invoked after tun_metadata_table_mod(). */ > +enum ofperr > +mf_vl_mff_map_mod_from_tun_metadata(struct vl_mff_map *vl_mff_map, > + const struct ofputil_tlv_table_mod *ttm) > + OVS_REQUIRES(vl_mff_map->mutex) > +{ > + struct ofputil_tlv_map *tlv_map; > + struct mf_field *mf; > + unsigned int idx; > + > + switch (ttm->command) { > + case NXTTMC_ADD: > + LIST_FOR_EACH (tlv_map, list_node, &ttm->mappings) { > + idx = MFF_TUN_METADATA0 + tlv_map->index; > + if (idx >= MFF_TUN_METADATA0 + TUN_METADATA_NUM_OPTS) { > + return OFPERR_NXTTMFC_BAD_FIELD_IDX; > + } > + > + mf = xmalloc(sizeof *mf); > + *mf = mf_fields[idx]; > + mf->n_bytes = tlv_map->option_len; > + mf->n_bits = tlv_map->option_len * 8; > + mf->mapped = true; > + > + cmap_insert(&vl_mff_map->cmap, &mf->cmap_node, > mf_field_hash(idx)); > + } > + break; > + > + case NXTTMC_DELETE: > + LIST_FOR_EACH (tlv_map, list_node, &ttm->mappings) { > + idx = MFF_TUN_METADATA0 + tlv_map->index; > + if (idx >= MFF_TUN_METADATA0 + TUN_METADATA_NUM_OPTS) { > + return OFPERR_NXTTMFC_BAD_FIELD_IDX; > + } > + > + CMAP_FOR_EACH_WITH_HASH (mf, cmap_node, mf_field_hash(idx), > + &vl_mff_map->cmap) { > + if (mf->id == idx) { > + cmap_remove(&vl_mff_map->cmap, &mf->cmap_node, > + mf_field_hash(idx)); > + ovsrcu_postpone(free, mf); > + break; > + } > + } > + } > + break; > + > + case NXTTMC_CLEAR: > + mf_vl_mff_map_clear(vl_mff_map); > + break; > + > + default: > + OVS_NOT_REACHED(); > + } I think that this could be a bit restructured to share the list iteration/error checking between ADD and DELETE. > + > + return 0; > +} > + > +/* If 'mff' is a variable length field, looks up 'vl_mff_map', returns a > + * pointer to the variable length meta-flow field corresponding to 'mff'. > + * Returns NULL if no mapping is existed for 'mff'. */ > +const struct mf_field * > +mf_get_vl_mff(const struct mf_field *mff, > + const struct vl_mff_map *vl_mff_map) > +{ > + const struct mf_field *field; > + > + if (mff && mff->variable_len && vl_mff_map) { > + const uint32_t id = mff->id; > + > + CMAP_FOR_EACH_WITH_HASH (field, cmap_node, mf_field_hash(id), > + &vl_mff_map->cmap) { > + if (field->id == id) { > + return field; > + } > + } > + } > + > + return NULL; > +} > + > +/* Returns true if a variable length meta-flow field 'mff' is not mapped in > + * the 'vl_mff_map'. */ > +bool > +mf_vl_mff_not_mapped(const struct mf_field *mff, > + const struct vl_mff_map *vl_mff_map) Typically we would reverse this function so you can have calls to "mf_vl_mff_mapped(...)", then if you want to invert the logic, you can use "!mf_vl_mff_mapped(...)". If the name has "not" in it, then it makes things harder to read when negation is involved. <snip> > diff --git a/lib/tun-metadata.c b/lib/tun-metadata.c > index 92643b3..eb27e25 100644 > --- a/lib/tun-metadata.c > +++ b/lib/tun-metadata.c > @@ -32,7 +32,7 @@ > > struct tun_meta_entry { > struct hmap_node node; /* In struct tun_table's key_hmap. */ > - uint32_t key; /* (class << 16) | type. */ > + uint32_t key; /* (class << 8) | type. */ > struct tun_metadata_loc loc; > bool valid; /* True if allocated to a class and type. */ > }; Was this always wrong? (Maybe it can be updated in a separate patch since it seems to be a documentation bugfix and not directly related to outputting variable length mapped MFFs correctly) <snip> I also saw a couple of spelling mistakes. I've included an incremental diff below, if you're happy with these changes then I'll apply them with your patch to master. diff --git a/include/openvswitch/meta-flow.h b/include/openvswitch/meta-flow.h index 0dc2ce6ad968..8457c86c094e 100644 --- a/include/openvswitch/meta-flow.h +++ b/include/openvswitch/meta-flow.h @@ -1996,5 +1996,5 @@ enum ofperr mf_vl_mff_map_mod_from_tun_metadata( OVS_REQUIRES(vl_mff_map->mutex); const struct mf_field * mf_get_vl_mff(const struct mf_field *, const struct vl_mff_map *); -bool mf_vl_mff_not_mapped(const struct mf_field *, const struct vl_mff_map *); +bool mf_vl_mff_mapped(const struct mf_field *, const struct vl_mff_map *); #endif /* meta-flow.h */ diff --git a/include/openvswitch/ofp-errors.h b/include/openvswitch/ofp-errors.h index ffe6c000cb78..7ff06a122c50 100644 --- a/include/openvswitch/ofp-errors.h +++ b/include/openvswitch/ofp-errors.h @@ -397,7 +397,7 @@ enum ofperr { /* NX1.0-1.1(1,536), NX1.2+(37). Attempted to add a flow with an invalid * variable length meta-flow field. */ - OFPERR_NXFMFC_INVALID_VL_MFF, + OFPERR_NXFMFC_INVALID_TLV_FIELD, /* ## ---------------------- ## */ /* ## OFPET_GROUP_MOD_FAILED ## */ diff --git a/lib/meta-flow.c b/lib/meta-flow.c index a20fab3bced3..11753cf89e30 100644 --- a/lib/meta-flow.c +++ b/lib/meta-flow.c @@ -2659,6 +2659,35 @@ mf_vl_mff_map_clear(struct vl_mff_map *vl_mff_map) } } +static struct mf_field * +mf_get_vl_mff__(uint32_t id, const struct vl_mff_map *vl_mff_map) +{ + struct mf_field *field; + + CMAP_FOR_EACH_WITH_HASH (field, cmap_node, mf_field_hash(id), + &vl_mff_map->cmap) { + if (field->id == id) { + return field; + } + } + + return NULL; +} + +/* If 'mff' is a variable length field, looks up 'vl_mff_map', returns a + * pointer to the variable length meta-flow field corresponding to 'mff'. + * Returns NULL if no mapping is existed for 'mff'. */ +const struct mf_field * +mf_get_vl_mff(const struct mf_field *mff, + const struct vl_mff_map *vl_mff_map) +{ + if (mff && mff->variable_len && vl_mff_map) { + return mf_get_vl_mff__(mff->id, vl_mff_map); + } + + return NULL; +} + /* Updates the tun_metadata mf_field in 'vl_mff_map' according to 'ttm'. * This function is supposed to be invoked after tun_metadata_table_mod(). */ enum ofperr @@ -2667,17 +2696,22 @@ mf_vl_mff_map_mod_from_tun_metadata(struct vl_mff_map *vl_mff_map, OVS_REQUIRES(vl_mff_map->mutex) { struct ofputil_tlv_map *tlv_map; - struct mf_field *mf; - unsigned int idx; - - switch (ttm->command) { - case NXTTMC_ADD: - LIST_FOR_EACH (tlv_map, list_node, &ttm->mappings) { - idx = MFF_TUN_METADATA0 + tlv_map->index; - if (idx >= MFF_TUN_METADATA0 + TUN_METADATA_NUM_OPTS) { - return OFPERR_NXTTMFC_BAD_FIELD_IDX; - } + if (ttm->command == NXTTMC_CLEAR) { + mf_vl_mff_map_clear(vl_mff_map); + return 0; + } + + LIST_FOR_EACH (tlv_map, list_node, &ttm->mappings) { + unsigned int idx = MFF_TUN_METADATA0 + tlv_map->index; + struct mf_field *mf; + + if (idx >= MFF_TUN_METADATA0 + TUN_METADATA_NUM_OPTS) { + return OFPERR_NXTTMFC_BAD_FIELD_IDX; + } + + switch (ttm->command) { + case NXTTMC_ADD: mf = xmalloc(sizeof *mf); *mf = mf_fields[idx]; mf->n_bytes = tlv_map->option_len; @@ -2685,73 +2719,30 @@ mf_vl_mff_map_mod_from_tun_metadata(struct vl_mff_map *vl_mff_map, mf->mapped = true; cmap_insert(&vl_mff_map->cmap, &mf->cmap_node, mf_field_hash(idx)); - } - break; + break; - case NXTTMC_DELETE: - LIST_FOR_EACH (tlv_map, list_node, &ttm->mappings) { - idx = MFF_TUN_METADATA0 + tlv_map->index; - if (idx >= MFF_TUN_METADATA0 + TUN_METADATA_NUM_OPTS) { - return OFPERR_NXTTMFC_BAD_FIELD_IDX; + case NXTTMC_DELETE: + mf = mf_get_vl_mff__(idx, vl_mff_map); + if (mf) { + cmap_remove(&vl_mff_map->cmap, &mf->cmap_node, + mf_field_hash(idx)); + ovsrcu_postpone(free, mf); } + break; - CMAP_FOR_EACH_WITH_HASH (mf, cmap_node, mf_field_hash(idx), - &vl_mff_map->cmap) { - if (mf->id == idx) { - cmap_remove(&vl_mff_map->cmap, &mf->cmap_node, - mf_field_hash(idx)); - ovsrcu_postpone(free, mf); - break; - } - } + case NXTTMC_CLEAR: + default: + OVS_NOT_REACHED(); } - break; - - case NXTTMC_CLEAR: - mf_vl_mff_map_clear(vl_mff_map); - break; - - default: - OVS_NOT_REACHED(); } return 0; } -/* If 'mff' is a variable length field, looks up 'vl_mff_map', returns a - * pointer to the variable length meta-flow field corresponding to 'mff'. - * Returns NULL if no mapping is existed for 'mff'. */ -const struct mf_field * -mf_get_vl_mff(const struct mf_field *mff, - const struct vl_mff_map *vl_mff_map) -{ - const struct mf_field *field; - - if (mff && mff->variable_len && vl_mff_map) { - const uint32_t id = mff->id; - - CMAP_FOR_EACH_WITH_HASH (field, cmap_node, mf_field_hash(id), - &vl_mff_map->cmap) { - if (field->id == id) { - return field; - } - } - } - - return NULL; -} - /* Returns true if a variable length meta-flow field 'mff' is not mapped in * the 'vl_mff_map'. */ bool -mf_vl_mff_not_mapped(const struct mf_field *mff, - const struct vl_mff_map *vl_mff_map) +mf_vl_mff_mapped(const struct mf_field *mff, const struct vl_mff_map *map) { - if (mff && vl_mff_map) { - if (mff->variable_len && !mff->mapped) { - return true; - } - } - - return false; + return !(map && mff && mff->variable_len && !mff->mapped); } diff --git a/lib/nx-match.c b/lib/nx-match.c index 8824f22c4b5c..7cfd3614219a 100644 --- a/lib/nx-match.c +++ b/lib/nx-match.c @@ -232,8 +232,8 @@ mf_nxm_header(enum mf_field_id id) } /* Returns the 32-bit OXM or NXM header to use for field 'mff'. If 'mff' is - * a mapped variable length mf_field, update header with the configured - * lenght of 'mff'. Returns 0 if 'mff' cannot be expressed with a 32-bit NXM + * a mapped variable length mf_field, update the header with the configured + * length of 'mff'. Returns 0 if 'mff' cannot be expressed with a 32-bit NXM * or OXM header.*/ uint32_t nxm_header_from_mff(const struct mf_field *mff) @@ -339,8 +339,8 @@ nx_pull_header__(struct ofpbuf *b, bool allow_cookie, VLOG_DBG_RL(&rl, "OXM header "NXM_HEADER_FMT" is unknown", NXM_HEADER_ARGS(*header)); return OFPERR_OFPBMC_BAD_FIELD; - } else if (mf_vl_mff_not_mapped(*field, vl_mff_map)) { - return OFPERR_NXFMFC_INVALID_VL_MFF; + } else if (!mf_vl_mff_mapped(*field, vl_mff_map)) { + return OFPERR_NXFMFC_INVALID_TLV_FIELD; } } diff --git a/lib/ofp-actions.c b/lib/ofp-actions.c index 180344a17d0a..276e008f9b08 100644 --- a/lib/ofp-actions.c +++ b/lib/ofp-actions.c @@ -1135,8 +1135,8 @@ decode_NXAST_RAW_OUTPUT_REG(const struct nx_action_output_reg *naor, output_reg->src.n_bits = nxm_decode_n_bits(naor->ofs_nbits); output_reg->max_len = ntohs(naor->max_len); - if (mf_vl_mff_not_mapped(output_reg->src.field, vl_mff_map)) { - return OFPERR_NXFMFC_INVALID_VL_MFF; + if (!mf_vl_mff_mapped(output_reg->src.field, vl_mff_map)) { + return OFPERR_NXFMFC_INVALID_TLV_FIELD; } return mf_check_src(&output_reg->src, NULL); @@ -1325,8 +1325,8 @@ decode_bundle(bool load, const struct nx_action_bundle *nab, 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_not_mapped(bundle->dst.field, vl_mff_map)) { - return OFPERR_NXFMFC_INVALID_VL_MFF; + if (!mf_vl_mff_mapped(bundle->dst.field, vl_mff_map)) { + return OFPERR_NXFMFC_INVALID_TLV_FIELD; } if (bundle->dst.n_bits < 16) { @@ -2565,8 +2565,8 @@ decode_NXAST_RAW_REG_LOAD(const struct nx_action_reg_load *narl, 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_not_mapped(dst.field, vl_mff_map)) { - return OFPERR_NXFMFC_INVALID_VL_MFF; + if (!mf_vl_mff_mapped(dst.field, vl_mff_map)) { + return OFPERR_NXFMFC_INVALID_TLV_FIELD; } error = mf_check_dst(&dst, NULL); @@ -4283,8 +4283,8 @@ get_subfield(int n_bits, const void **p, struct mf_subfield *sf, 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_not_mapped(sf->field, vl_mff_map)) { - return OFPERR_NXFMFC_INVALID_VL_MFF; + if (!mf_vl_mff_mapped(sf->field, vl_mff_map)) { + return OFPERR_NXFMFC_INVALID_TLV_FIELD; } return 0; } @@ -4664,8 +4664,8 @@ decode_NXAST_RAW_MULTIPATH(const struct nx_action_multipath *nam, mp->dst.ofs = nxm_decode_ofs(nam->ofs_nbits); mp->dst.n_bits = nxm_decode_n_bits(nam->ofs_nbits); - if (mf_vl_mff_not_mapped(mp->dst.field, vl_mff_map)) { - return OFPERR_NXFMFC_INVALID_VL_MFF; + if (!mf_vl_mff_mapped(mp->dst.field, vl_mff_map)) { + return OFPERR_NXFMFC_INVALID_TLV_FIELD; } if (!flow_hash_fields_valid(mp->fields)) { @@ -5324,8 +5324,8 @@ decode_ct_zone(const struct nx_action_conntrack *nac, 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_not_mapped(out->zone_src.field, vl_mff_map)) { - return OFPERR_NXFMFC_INVALID_VL_MFF; + if (!mf_vl_mff_mapped(out->zone_src.field, vl_mff_map)) { + return OFPERR_NXFMFC_INVALID_TLV_FIELD; } error = mf_check_src(&out->zone_src, NULL); diff --git a/ofproto/ofproto-provider.h b/ofproto/ofproto-provider.h index b08a3fd174c4..c08a146154b1 100644 --- a/ofproto/ofproto-provider.h +++ b/ofproto/ofproto-provider.h @@ -128,7 +128,7 @@ struct ofproto { /* Tunnel TLV mapping table. */ OVSRCU_TYPE(struct tun_table *) metadata_tab; - /* Variable length mf_field mapping map. Stores all variable length + /* Variable length mf_field mapping. Stores all configured variable length * meta-flow fields (struct mf_field) in a switch. */ struct vl_mff_map vl_mff_map; }; diff --git a/tests/ofproto.at b/tests/ofproto.at index 48f30cff4958..c899ec80c6cf 100644 --- a/tests/ofproto.at +++ b/tests/ofproto.at @@ -5707,7 +5707,7 @@ NXST_FLOW reply (xid=0x4): dnl Check actions that may use tun_metadata AT_CHECK([ovs-ofctl add-flow br0 "in_port=2 actions=move:tun_metadata1[[0..31]]->NXM_NX_REG0[[]]"], [1], [], [stderr]) AT_CHECK([strip_xids < stderr | sed '/FLOW_MOD/,$d'], [0], [dnl -OFPT_ERROR: NXFMFC_INVALID_VL_MFF +OFPT_ERROR: NXFMFC_INVALID_TLV_FIELD ]) AT_CHECK([ovs-ofctl add-flow br0 "in_port=2 actions=move:tun_metadata0[[32..63]]->NXM_NX_REG0[[]]"], [1], [], [stderr]) @@ -5717,7 +5717,7 @@ OFPT_ERROR: OFPBAC_BAD_SET_LEN AT_CHECK([ovs-ofctl add-flow br0 "in_port=2 actions=push:tun_metadata1[[0..31]]"], [1], [], [stderr]) AT_CHECK([strip_xids < stderr | sed '/FLOW_MOD/,$d'], [0], [dnl -OFPT_ERROR: NXFMFC_INVALID_VL_MFF +OFPT_ERROR: NXFMFC_INVALID_TLV_FIELD ]) AT_CHECK([ovs-ofctl add-flow br0 "in_port=2 actions=pop:tun_metadata0[[32..63]]"], [1], [], [stderr]) @@ -5727,12 +5727,12 @@ OFPT_ERROR: OFPBAC_BAD_SET_LEN AT_CHECK([ovs-ofctl add-flow br0 "in_port=3, actions=load:0x11223344->tun_metadata1"], [1], [], [stderr]) AT_CHECK([strip_xids < stderr | sed '/FLOW_MOD/,$d'], [0], [dnl -OFPT_ERROR: NXFMFC_INVALID_VL_MFF +OFPT_ERROR: NXFMFC_INVALID_TLV_FIELD ]) AT_CHECK([ovs-ofctl add-flow br0 "in_port=2 actions=output:tun_metadata1[[0..31]]"], [1], [], [stderr]) AT_CHECK([strip_xids < stderr | sed '/FLOW_MOD/,$d'], [0], [dnl -OFPT_ERROR: NXFMFC_INVALID_VL_MFF +OFPT_ERROR: NXFMFC_INVALID_TLV_FIELD ]) AT_CHECK([ovs-ofctl add-flow br0 "in_port=2 actions=output:tun_metadata0[[32..63]]"], [1], [], [stderr]) @@ -5742,7 +5742,7 @@ OFPT_ERROR: OFPBAC_BAD_SET_LEN AT_CHECK([ovs-ofctl add-flow br0 "in_port=2 actions=multipath(eth_src,50,modulo_n,1,0,tun_metadata1[[0..31]])"], [1], [], [stderr]) AT_CHECK([strip_xids < stderr | sed '/FLOW_MOD/,$d'], [0], [dnl -OFPT_ERROR: NXFMFC_INVALID_VL_MFF +OFPT_ERROR: NXFMFC_INVALID_TLV_FIELD ]) AT_CHECK([ovs-ofctl add-flow br0 "in_port=2 actions=multipath(eth_src,50,modulo_n,1,0,tun_metadata0[[32..63]])"], [1], [], [stderr]) @@ -5752,7 +5752,7 @@ OFPT_ERROR: OFPBAC_BAD_SET_LEN AT_CHECK([ovs-ofctl add-flow br0 "in_port=2 actions=bundle_load(eth_src,50,hrw,ofport,tun_metadata1[[0..31]], slaves:4,8)"], [1], [], [stderr]) AT_CHECK([strip_xids < stderr | sed '/FLOW_MOD/,$d'], [0], [dnl -OFPT_ERROR: NXFMFC_INVALID_VL_MFF +OFPT_ERROR: NXFMFC_INVALID_TLV_FIELD ]) AT_CHECK([ovs-ofctl add-flow br0 "in_port=2 actions=bundle_load(eth_src,50,hrw,ofport,tun_metadata0[[32..63]], slaves:4,8)"], [1], [], [stderr]) @@ -5762,7 +5762,7 @@ OFPT_ERROR: OFPBAC_BAD_SET_LEN AT_CHECK([ovs-ofctl add-flow br0 "in_port=2 actions=learn(tun_metadata1[[0..31]]=reg0[[0..31]])"], [1], [], [stderr]) AT_CHECK([strip_xids < stderr | sed '/FLOW_MOD/,$d'], [0], [dnl -OFPT_ERROR: NXFMFC_INVALID_VL_MFF +OFPT_ERROR: NXFMFC_INVALID_TLV_FIELD ]) AT_CHECK([ovs-ofctl add-flow br0 "in_port=2 actions=learn(tun_metadata0[[32..63]]=reg0[[0..31]])"], [1], [], [stderr]) @@ -5772,7 +5772,7 @@ OFPT_ERROR: OFPBAC_BAD_SET_LEN AT_CHECK([ovs-ofctl add-flow br0 "in_port=2 actions=clone(move:tun_metadata1[[0..31]]->reg0[[0..31]])"], [1], [], [stderr]) AT_CHECK([strip_xids < stderr | sed '/FLOW_MOD/,$d'], [0], [dnl -OFPT_ERROR: NXFMFC_INVALID_VL_MFF +OFPT_ERROR: NXFMFC_INVALID_TLV_FIELD ]) AT_CHECK([ovs-ofctl add-flow br0 "in_port=2 actions=clone(move:tun_metadata0[[32..63]]->reg0[[0..31]])"], [1], [], [stderr]) @@ -5782,7 +5782,7 @@ OFPT_ERROR: OFPBAC_BAD_SET_LEN AT_CHECK([ovs-ofctl add-flow br0 "ip actions=ct(commit,zone=tun_metadata1[[0..15]],exec(set_field:0x01->ct_mark))"], [1], [], [stderr]) AT_CHECK([strip_xids < stderr | sed '/FLOW_MOD/,$d'], [0], [dnl -OFPT_ERROR: NXFMFC_INVALID_VL_MFF +OFPT_ERROR: NXFMFC_INVALID_TLV_FIELD ]) AT_CHECK([ovs-ofctl add-flow br0 "ip actions=ct(commit,zone=tun_metadata0[[32..47]],exec(set_field:0x01->ct_mark))"], [1], [], [stderr]) @@ -5792,7 +5792,7 @@ OFPT_ERROR: OFPBAC_BAD_SET_LEN AT_CHECK([ovs-ofctl add-flow br0 "ip actions=ct(commit,zone=1,exec(move:tun_metadata1[[0..31]]->ct_mark))"], [1], [], [stderr]) AT_CHECK([strip_xids < stderr | sed '/FLOW_MOD/,$d'], [0], [dnl -OFPT_ERROR: NXFMFC_INVALID_VL_MFF +OFPT_ERROR: NXFMFC_INVALID_TLV_FIELD ]) AT_CHECK([ovs-ofctl add-flow br0 "ip actions=ct(commit,zone=1,exec(move:tun_metadata0[[32..63]]->ct_mark))"], [1], [], [stderr]) @@ -5806,7 +5806,7 @@ NXST_FLOW reply (xid=0x4): cookie=0x0, duration=?s, table=0, n_packets=0, n_bytes=0, idle_age=?, in_port=1 actions=move:NXM_NX_TUN_METADATA0[[0..31]]->NXM_NX_REG0[[]] ]) -OVS_VSWITCHD_STOP(["/NXFMFC_INVALID_VL_MFF/d +OVS_VSWITCHD_STOP(["/NXFMFC_INVALID_TLV_FIELD/d /tun_metadata0/d /OFPBAC_BAD_SET_LEN/d"]) AT_CLEANUP _______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev