summaryrefslogtreecommitdiff
path: root/lib/nx-match.c
diff options
context:
space:
mode:
authorJesse Gross <jesse@nicira.com>2015-05-06 18:05:18 -0700
committerJesse Gross <jesse@nicira.com>2015-06-25 11:08:57 -0700
commit4ede8c79eb9bc8fda4ef230615b6677cba8e6906 (patch)
treee69293eed8fb376e81e04494de261a5a328e867b /lib/nx-match.c
parentdc3eb9539f17f3b9a2ea9221a86221196b5c002e (diff)
downloadopenvswitch-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.c20
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);
}
}