diff options
author | Jesse Gross <jesse@nicira.com> | 2015-05-06 18:05:18 -0700 |
---|---|---|
committer | Jesse Gross <jesse@nicira.com> | 2015-06-25 11:08:57 -0700 |
commit | 4ede8c79eb9bc8fda4ef230615b6677cba8e6906 (patch) | |
tree | e69293eed8fb376e81e04494de261a5a328e867b /lib/nx-match.c | |
parent | dc3eb9539f17f3b9a2ea9221a86221196b5c002e (diff) | |
download | openvswitch-4ede8c79eb9bc8fda4ef230615b6677cba8e6906.tar.gz |
nx-match: Trim variable length fields when encoding as actions.
It is technically correct to send the entire maximum length of
a field when it is variable length. However, it is awkward to
do so and not what one would naively expect. Since receivers will
internally zero-extend fields, we can do the opposite and trim
off leading zeros. This results in encodings that are generally
sensible without specific knowledge of what is being transmitted.
(Of course, other implementations, such as controllers, may know
exactly the expected length of the field and are free to encode
it that way even if it has leading zeros.)
Signed-off-by: Jesse Gross <jesse@nicira.com>
Acked-by: Ben Pfaff <blp@nicira.com>
Diffstat (limited to 'lib/nx-match.c')
-rw-r--r-- | lib/nx-match.c | 20 |
1 files changed, 13 insertions, 7 deletions
diff --git a/lib/nx-match.c b/lib/nx-match.c index 1a6b89a85..2d06fe338 100644 --- a/lib/nx-match.c +++ b/lib/nx-match.c @@ -1168,8 +1168,10 @@ oxm_put_field_array(struct ofpbuf *b, const struct field_array *fa, for (i = 0; i < MFF_N_IDS; i++) { if (bitmap_is_set(fa->used.bm, i)) { - nxm_put_unmasked(b, i, version, &fa->value[i], - mf_from_id(i)->n_bytes); + int len = mf_field_len(mf_from_id(i), &fa->value[i], NULL); + nxm_put_unmasked(b, i, version, + &fa->value[i].u8 + mf_from_id(i)->n_bytes - len, + len); } } @@ -1210,13 +1212,17 @@ nx_put_entry(struct ofpbuf *b, enum mf_field_id field, enum ofp_version version, const union mf_value *value, const union mf_value *mask) { - int n_bytes = mf_from_id(field)->n_bytes; - bool masked = mask && !is_all_ones(mask, n_bytes); + const struct mf_field *mf = mf_from_id(field); + bool masked = mask && !is_all_ones(mask, mf->n_bytes); + int len, offset; - nx_put_header(b, field, version, masked); - ofpbuf_put(b, value, n_bytes); + len = mf_field_len(mf, value, mask); + offset = mf->n_bytes - len; + + nx_put_header_len(b, field, version, masked, len); + ofpbuf_put(b, &value->u8 + offset, len); if (masked) { - ofpbuf_put(b, mask, n_bytes); + ofpbuf_put(b, &mask->u8 + offset, len); } } |