summaryrefslogtreecommitdiff
path: root/lib/ofp-actions.c
diff options
context:
space:
mode:
authorYi-Hung Wei <yihung.wei@gmail.com>2017-03-13 11:28:21 -0700
committerJoe Stringer <joe@ovn.org>2017-03-15 14:45:40 -0700
commit5c7c16d896137382783818ebd65af2ff89fc6919 (patch)
tree3c682b45c1dfe76192e2316ea01341d108aa9982 /lib/ofp-actions.c
parent3cddeff01cad5cf61904fed0dcd02e71dacfe3b8 (diff)
downloadopenvswitch-5c7c16d896137382783818ebd65af2ff89fc6919.tar.gz
ofproto: Add ref counting for variable length mf_fields.
Currently, a controller may potentially trigger a segmentation fault if it accidentally removes a TLV mapping that is still used by an active flow. To resolve this issue, in this patch, we maintain reference counting for each dynamically allocated variable length mf_fields, so that vswitchd can use this information to properly remove a TLV mapping, and to return an error if the controller tries to remove a TLV mapping that is still used by any active flow. To keep track of the usage of tun_metadata for each flow, two 'uint64_t' bitmaps are introduce for the flow match and flow action respectively. We use 'uint64_t' as a bitmap since the 64 geneve TLV tunnel metadata are the only available variable length mf_fields for now. We shall adopt general bitmap when more variable length mf_fields are introduced. The bitmaps are configured during the flow decoding process, and vswitchd use these bitmaps to increase or decrease the ref counting when the flow is created or deleted. VMWare-BZ: #1768370 Fixes: 04f48a68c428 ("ofp-actions: Fix variable length meta-flow OXMs.") Suggested-by: Jarno Rajahalme <jarno@ovn.org> Suggested-by: Joe Stringer <joe@ovn.org> Signed-off-by: Yi-Hung Wei <yihung.wei@gmail.com> Signed-off-by: Joe Stringer <joe@ovn.org>
Diffstat (limited to 'lib/ofp-actions.c')
-rw-r--r--lib/ofp-actions.c208
1 files changed, 129 insertions, 79 deletions
diff --git a/lib/ofp-actions.c b/lib/ofp-actions.c
index 2c8ab1788..ef04d7b4b 100644
--- a/lib/ofp-actions.c
+++ b/lib/ofp-actions.c
@@ -407,7 +407,7 @@ 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,
- const struct vl_mff_map *vl_mff_map);
+ const struct vl_mff_map *vl_mff_map, uint64_t *ofpacts_tlv_bitmap);
static char * OVS_WARN_UNUSED_RESULT ofpacts_parse_copy(
const char *s_, struct ofpbuf *ofpacts,
enum ofputil_protocol *usable_protocols,
@@ -1123,9 +1123,10 @@ 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)
+ uint64_t *tlv_bitmap, struct ofpbuf *out)
{
struct ofpact_output_reg *output_reg;
+ enum ofperr error;
if (!is_all_zeros(naor->zero, sizeof naor->zero)) {
return OFPERR_OFPBAC_BAD_ARGUMENT;
@@ -1133,13 +1134,13 @@ 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), 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;
+ error = mf_vl_mff_mf_from_nxm_header(ntohl(naor->src), vl_mff_map,
+ &output_reg->src.field, tlv_bitmap);
+ if (error) {
+ return error;
}
return mf_check_src(&output_reg->src, NULL);
@@ -1149,9 +1150,11 @@ 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)
+ uint64_t *tlv_bitmap, struct ofpbuf *out)
{
struct ofpact_output_reg *output_reg;
+ enum ofperr error;
+
output_reg = ofpact_put_OUTPUT_REG(out);
output_reg->ofpact.raw = NXAST_RAW_OUTPUT_REG2;
output_reg->src.ofs = nxm_decode_ofs(naor->ofs_nbits);
@@ -1161,11 +1164,12 @@ 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, vl_mff_map, &output_reg->src.field,
- NULL);
+ error = mf_vl_mff_nx_pull_header(&b, vl_mff_map, &output_reg->src.field,
+ NULL, tlv_bitmap);
if (error) {
return error;
}
+
if (!is_all_zeros(b.data, b.size)) {
return OFPERR_NXBRC_MUST_BE_ZERO;
}
@@ -1288,7 +1292,8 @@ OFP_ASSERT(sizeof(struct nx_action_bundle) == 32);
static enum ofperr
decode_bundle(bool load, const struct nx_action_bundle *nab,
- const struct vl_mff_map *vl_mff_map, struct ofpbuf *ofpacts)
+ const struct vl_mff_map *vl_mff_map, uint64_t *tlv_bitmap,
+ struct ofpbuf *ofpacts)
{
static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
struct ofpact_bundle *bundle;
@@ -1325,11 +1330,12 @@ decode_bundle(bool load, const struct nx_action_bundle *nab,
}
if (load) {
- 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;
+ error = mf_vl_mff_mf_from_nxm_header(ntohl(nab->dst), vl_mff_map,
+ &bundle->dst.field, tlv_bitmap);
+ if (error) {
+ return error;
}
if (bundle->dst.n_bits < 16) {
@@ -1371,16 +1377,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, NULL, out);
+ return decode_bundle(false, nab, NULL, 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)
+ uint64_t *tlv_bitmap, struct ofpbuf *out)
{
- return decode_bundle(true, nab, vl_mff_map, out);
+ return decode_bundle(true, nab, vl_mff_map, tlv_bitmap, out);
}
static void
@@ -2284,9 +2290,11 @@ 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)
+ uint64_t *tlv_bitmap, struct ofpbuf *ofpacts)
{
struct ofpact_reg_move *move = ofpact_put_REG_MOVE(ofpacts);
+ enum ofperr error;
+
move->ofpact.raw = ONFACT_RAW13_COPY_FIELD;
move->src.ofs = ntohs(src_offset);
move->src.n_bits = ntohs(n_bits);
@@ -2296,11 +2304,13 @@ 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, vl_mff_map, &move->src.field, NULL);
+ error = mf_vl_mff_nx_pull_header(&b, vl_mff_map, &move->src.field, NULL,
+ tlv_bitmap);
if (error) {
return error;
}
- error = nx_pull_header(&b, vl_mff_map, &move->dst.field, NULL);
+ error = mf_vl_mff_nx_pull_header(&b, vl_mff_map, &move->dst.field, NULL,
+ tlv_bitmap);
if (error) {
return error;
}
@@ -2316,33 +2326,35 @@ 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)
+ uint64_t *tlv_bitmap, struct ofpbuf *ofpacts)
{
return decode_copy_field__(oacf->src_offset, oacf->dst_offset,
oacf->n_bits, oacf, oacf->len,
OBJECT_OFFSETOF(oacf, pad2), vl_mff_map,
- ofpacts);
+ tlv_bitmap, 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)
+ uint64_t *tlv_bitmap, struct ofpbuf *ofpacts)
{
return decode_copy_field__(oacf->src_offset, oacf->dst_offset,
oacf->n_bits, oacf, oacf->len,
OBJECT_OFFSETOF(oacf, pad3), vl_mff_map,
- ofpacts);
+ tlv_bitmap, 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)
+ uint64_t *tlv_bitmap, struct ofpbuf *ofpacts)
{
struct ofpact_reg_move *move = ofpact_put_REG_MOVE(ofpacts);
+ enum ofperr error;
+
move->ofpact.raw = NXAST_RAW_REG_MOVE;
move->src.ofs = ntohs(narm->src_ofs);
move->src.n_bits = ntohs(narm->n_bits);
@@ -2352,11 +2364,14 @@ 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, vl_mff_map, &move->src.field, NULL);
+ error = mf_vl_mff_nx_pull_header(&b, vl_mff_map, &move->src.field, NULL,
+ tlv_bitmap);
if (error) {
return error;
}
- error = nx_pull_header(&b, vl_mff_map, &move->dst.field, NULL);
+
+ error = mf_vl_mff_nx_pull_header(&b, vl_mff_map, &move->dst.field, NULL,
+ tlv_bitmap);
if (error) {
return error;
}
@@ -2483,20 +2498,22 @@ 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, const struct vl_mff_map *vl_mff_map,
- struct ofpbuf *ofpacts)
+ uint64_t *tlv_bitmap, 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, vl_mff_map, &field, &value,
- may_mask ? &mask : NULL);
+ enum ofperr error;
+ error = mf_vl_mff_nx_pull_entry(&b, vl_mff_map, &field, &value,
+ may_mask ? &mask : NULL, tlv_bitmap);
if (error) {
return (error == OFPERR_OFPBMC_BAD_MASK
? OFPERR_OFPBAC_BAD_SET_MASK
: error);
}
+
if (!may_mask) {
memset(&mask, 0xff, field->n_bytes);
}
@@ -2542,34 +2559,36 @@ 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)
+ uint64_t *tlv_bitmap, struct ofpbuf *ofpacts)
{
- return decode_ofpat_set_field(oasf, false, vl_mff_map, ofpacts);
+ return decode_ofpat_set_field(oasf, false, vl_mff_map, tlv_bitmap,
+ 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)
+ uint64_t *tlv_bitmap, struct ofpbuf *ofpacts)
{
- return decode_ofpat_set_field(oasf, true, vl_mff_map, ofpacts);
+ return decode_ofpat_set_field(oasf, true, vl_mff_map, tlv_bitmap, 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)
+ uint64_t *tlv_bitmap, struct ofpbuf *out)
{
struct mf_subfield dst;
enum ofperr error;
- 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_vl_mff_mf_from_nxm_header(ntohl(narl->dst), vl_mff_map,
+ &dst.field, tlv_bitmap);
+ if (error) {
+ return error;
}
error = mf_check_dst(&dst, NULL);
@@ -2598,17 +2617,20 @@ 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)
+ uint64_t *tlv_bitmap, struct ofpbuf *out)
{
struct ofpbuf b = ofpbuf_const_initializer(eah, ntohs(eah->len));
ofpbuf_pull(&b, OBJECT_OFFSETOF(eah, pad));
union mf_value value, mask;
const struct mf_field *field;
- enum ofperr error = nx_pull_entry(&b, vl_mff_map, &field, &value, &mask);
+ enum ofperr error;
+ error = mf_vl_mff_nx_pull_entry(&b, vl_mff_map, &field, &value, &mask,
+ tlv_bitmap);
if (error) {
return error;
}
+
if (!is_all_zeros(b.data, b.size)) {
return OFPERR_OFPBAC_BAD_SET_ARGUMENT;
}
@@ -3113,18 +3135,21 @@ 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,
+ const struct vl_mff_map *vl_mff_map, uint64_t *tlv_bitmap,
struct ofpact_stack *stack_action)
{
+ enum ofperr error;
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, vl_mff_map,
- &stack_action->subfield.field, NULL);
+ error = mf_vl_mff_nx_pull_header(&b, vl_mff_map,
+ &stack_action->subfield.field, NULL,
+ tlv_bitmap);
if (error) {
return error;
}
+
stack_action->subfield.n_bits = ntohs(*(const ovs_be16 *) b.data);
ofpbuf_pull(&b, 2);
if (!is_all_zeros(b.data, b.size)) {
@@ -3138,10 +3163,11 @@ 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)
+ uint64_t *tlv_bitmap, struct ofpbuf *ofpacts)
{
struct ofpact_stack *push = ofpact_put_STACK_PUSH(ofpacts);
- enum ofperr error = decode_stack_action(nasp, vl_mff_map, push);
+ enum ofperr error = decode_stack_action(nasp, vl_mff_map, tlv_bitmap,
+ push);
return error ? error : nxm_stack_push_check(push, NULL);
}
@@ -3149,10 +3175,11 @@ 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)
+ uint64_t *tlv_bitmap, struct ofpbuf *ofpacts)
{
struct ofpact_stack *pop = ofpact_put_STACK_POP(ofpacts);
- enum ofperr error = decode_stack_action(nasp, vl_mff_map, pop);
+ enum ofperr error = decode_stack_action(nasp, vl_mff_map, tlv_bitmap,
+ pop);
return error ? error : nxm_stack_pop_check(pop, NULL);
}
@@ -4318,15 +4345,15 @@ get_be32(const void **pp)
static enum ofperr
get_subfield(int n_bits, const void **p, struct mf_subfield *sf,
- const struct vl_mff_map *vl_mff_map)
+ const struct vl_mff_map *vl_mff_map, uint64_t *tlv_bitmap)
{
- sf->field = mf_from_nxm_header(ntohl(get_be32(p)), vl_mff_map);
+ enum ofperr error;
+
+ error = mf_vl_mff_mf_from_nxm_header(ntohl(get_be32(p)), vl_mff_map,
+ &sf->field, tlv_bitmap);
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;
+ return error;
}
static unsigned int
@@ -4358,7 +4385,7 @@ 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)
+ uint64_t *tlv_bitmap, struct ofpbuf *ofpacts)
{
struct ofpact_learn *learn;
const void *p, *end;
@@ -4423,7 +4450,8 @@ decode_NXAST_RAW_LEARN(const struct nx_action_learn *nal,
unsigned int imm_bytes = 0;
enum ofperr error;
if (spec->src_type == NX_LEARN_SRC_FIELD) {
- error = get_subfield(spec->n_bits, &p, &spec->src, vl_mff_map);
+ error = get_subfield(spec->n_bits, &p, &spec->src, vl_mff_map,
+ tlv_bitmap);
if (error) {
return error;
}
@@ -4438,7 +4466,8 @@ 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) {
- error = get_subfield(spec->n_bits, &p, &spec->dst, vl_mff_map);
+ error = get_subfield(spec->n_bits, &p, &spec->dst, vl_mff_map,
+ tlv_bitmap);
if (error) {
return error;
}
@@ -4688,11 +4717,12 @@ 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)
+ uint64_t *tlv_bitmap, struct ofpbuf *out)
{
uint32_t n_links = ntohs(nam->max_link) + 1;
size_t min_n_bits = log_2_ceil(n_links);
struct ofpact_multipath *mp;
+ enum ofperr error;
mp = ofpact_put_MULTIPATH(out);
mp->fields = ntohs(nam->fields);
@@ -4700,12 +4730,12 @@ 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), 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;
+ error = mf_vl_mff_mf_from_nxm_header(ntohl(nam->dst), vl_mff_map,
+ &mp->dst.field, tlv_bitmap);
+ if (error) {
+ return error;
}
if (!flow_hash_fields_valid(mp->fields)) {
@@ -4894,7 +4924,7 @@ static enum ofperr
decode_NXAST_RAW_CLONE(const struct ext_action_header *eah,
enum ofp_version ofp_version,
const struct vl_mff_map *vl_mff_map,
- struct ofpbuf *out)
+ uint64_t *tlv_bitmap, struct ofpbuf *out)
{
int error;
struct ofpbuf openflow;
@@ -4908,7 +4938,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, vl_mff_map);
+ out, 0, vl_mff_map, tlv_bitmap);
clone = ofpbuf_push_uninit(out, sizeof *clone);
out->header = &clone->ofpact;
ofpact_finish_CLONE(out, &clone);
@@ -5364,17 +5394,18 @@ OFP_ASSERT(sizeof(struct nx_action_conntrack) == 24);
static enum ofperr
decode_ct_zone(const struct nx_action_conntrack *nac,
struct ofpact_conntrack *out,
- const struct vl_mff_map *vl_mff_map)
+ const struct vl_mff_map *vl_mff_map, uint64_t *tlv_bitmap)
{
if (nac->zone_src) {
enum ofperr error;
- 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_vl_mff_mf_from_nxm_header(ntohl(nac->zone_src),
+ vl_mff_map, &out->zone_src.field,
+ tlv_bitmap);
+ if (error) {
+ return error;
}
error = mf_check_src(&out->zone_src, NULL);
@@ -5398,7 +5429,8 @@ 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,
- const struct vl_mff_map *vl_mff_map, struct ofpbuf *out)
+ const struct vl_mff_map *vl_mff_map, uint64_t *tlv_bitmap,
+ struct ofpbuf *out)
{
const size_t ct_offset = ofpacts_pull(out);
struct ofpact_conntrack *conntrack = ofpact_put_CT(out);
@@ -5411,7 +5443,7 @@ decode_NXAST_RAW_CT(const struct nx_action_conntrack *nac,
goto out;
}
- error = decode_ct_zone(nac, conntrack, vl_mff_map);
+ error = decode_ct_zone(nac, conntrack, vl_mff_map, tlv_bitmap);
if (error) {
goto out;
}
@@ -5425,7 +5457,8 @@ 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, vl_mff_map);
+ out, OFPACT_CT, vl_mff_map,
+ tlv_bitmap);
if (error) {
goto out;
}
@@ -6318,7 +6351,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,
- const struct vl_mff_map *vl_mff_map, struct ofpbuf *ofpacts)
+ const struct vl_mff_map *vl_mff_map,
+ uint64_t *ofpacts_tlv_bitmap, struct ofpbuf *ofpacts)
{
struct ofpbuf openflow = ofpbuf_const_initializer(actions, actions_len);
while (openflow.size) {
@@ -6330,7 +6364,7 @@ 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, vl_mff_map,
- ofpacts);
+ ofpacts_tlv_bitmap, ofpacts);
}
if (error) {
@@ -6348,7 +6382,8 @@ ofpacts_pull_openflow_actions__(struct ofpbuf *openflow,
uint32_t allowed_ovsinsts,
struct ofpbuf *ofpacts,
enum ofpact_type outer_action,
- const struct vl_mff_map *vl_mff_map)
+ const struct vl_mff_map *vl_mff_map,
+ uint64_t *ofpacts_tlv_bitmap)
{
const struct ofp_action_header *actions;
size_t orig_size = ofpacts->size;
@@ -6368,7 +6403,8 @@ ofpacts_pull_openflow_actions__(struct ofpbuf *openflow,
return OFPERR_OFPBRC_BAD_LEN;
}
- error = ofpacts_decode(actions, actions_len, version, vl_mff_map, ofpacts);
+ error = ofpacts_decode(actions, actions_len, version, vl_mff_map,
+ ofpacts_tlv_bitmap, ofpacts);
if (error) {
ofpacts->size = orig_size;
return error;
@@ -6394,6 +6430,13 @@ ofpacts_pull_openflow_actions__(struct ofpbuf *openflow,
* you should call ofpacts_pull_openflow_instructions() instead of this
* function.
*
+ * 'vl_mff_map' and 'ofpacts_tlv_bitmap' are optional. If 'vl_mff_map' is
+ * provided, it is used to get variable length mf_fields with configured
+ * length in the actions. If an action uses a variable length mf_field,
+ * 'ofpacts_tlv_bitmap' is updated accordingly for ref counting. If
+ * 'vl_mff_map' is not provided, the default mf_fields with maximum length
+ * will be used.
+ *
* The parsed actions are valid generically, but they may not be valid in a
* specific context. For example, port numbers up to OFPP_MAX are valid
* generically, but specific datapaths may only support port numbers in a
@@ -6404,11 +6447,13 @@ ofpacts_pull_openflow_actions(struct ofpbuf *openflow,
unsigned int actions_len,
enum ofp_version version,
const struct vl_mff_map *vl_mff_map,
+ uint64_t *ofpacts_tlv_bitmap,
struct ofpbuf *ofpacts)
{
return ofpacts_pull_openflow_actions__(openflow, actions_len, version,
1u << OVSINST_OFPIT11_APPLY_ACTIONS,
- ofpacts, 0, vl_mff_map);
+ ofpacts, 0, vl_mff_map,
+ ofpacts_tlv_bitmap);
}
/* OpenFlow 1.1 actions. */
@@ -6648,13 +6693,15 @@ 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,
+ uint64_t *ofpacts_tlv_bitmap,
struct ofpbuf *out)
{
enum ofperr error;
struct ofpact *a;
size_t start = out->size;
- error = ofpacts_decode(in, n_in, version, vl_mff_map, out);
+ error = ofpacts_decode(in, n_in, version, vl_mff_map, ofpacts_tlv_bitmap,
+ out);
if (error) {
return error;
@@ -6953,6 +7000,7 @@ ofpacts_pull_openflow_instructions(struct ofpbuf *openflow,
unsigned int instructions_len,
enum ofp_version version,
const struct vl_mff_map *vl_mff_map,
+ uint64_t *ofpacts_tlv_bitmap,
struct ofpbuf *ofpacts)
{
const struct ofp11_instruction *instructions;
@@ -6964,7 +7012,8 @@ ofpacts_pull_openflow_instructions(struct ofpbuf *openflow,
return ofpacts_pull_openflow_actions__(openflow, instructions_len,
version,
(1u << N_OVS_INSTRUCTIONS) - 1,
- ofpacts, 0, vl_mff_map);
+ ofpacts, 0, vl_mff_map,
+ ofpacts_tlv_bitmap);
}
if (instructions_len % OFP11_INSTRUCTION_ALIGN != 0) {
@@ -7009,7 +7058,7 @@ 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, vl_mff_map,
- ofpacts);
+ ofpacts_tlv_bitmap, ofpacts);
if (error) {
goto exit;
}
@@ -7029,7 +7078,8 @@ 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, vl_mff_map, ofpacts);
+ version, vl_mff_map,
+ ofpacts_tlv_bitmap, ofpacts);
if (error) {
goto exit;
}