This adds support for receiving variable length fields encoded in
NXM/OXM and mapping them into OVS internal structures. In order
for this to make sense, we need to define some semantics:

There are three lengths that matter in this process: the maximum
size of the field (represented as the existing mf->n_bytes), the
size of the field in the incoming NXM (given by the length in the
NXM header), and the currently configured length of the field
(defined by the consumer of the field and outside the scope of
this patch).

Fields are modeled as being their maximum length and have the
characteristics expected by exsiting code (i.e. exact match fields
have masks that are all 1's for the whole field, etc.). Incoming
NXMs are stored in the field in the least significant bits. If
the NXM length is larger than the field, is is truncated, if it
is smaller it is zero-extended. When the field is consumed, the
component that needs data picks the configured length out of the
generated field.

In most cases, the configured and NXM lengths will be equal and
these edge cases do not matter. However, since we cannot easily
enforce that the lengths match (and might not even know what the
right length is, such as in the case of a string parsed by
ovs-ofctl), these semantics should provide deterministic results
that are easy to understand and not require most existing code
to be aware of variable length fields.

Signed-off-by: Jesse Gross <je...@nicira.com>
---
 lib/nx-match.c | 33 +++++++++++++++++++++++++++------
 1 file changed, 27 insertions(+), 6 deletions(-)

diff --git a/lib/nx-match.c b/lib/nx-match.c
index f51af08..e539a9f 100644
--- a/lib/nx-match.c
+++ b/lib/nx-match.c
@@ -328,15 +328,17 @@ error:
 
 static enum ofperr
 nx_pull_entry__(struct ofpbuf *b, bool allow_cookie, uint64_t *header,
-                const struct mf_field **field,
+                const struct mf_field **field_,
                 union mf_value *value, union mf_value *mask)
 {
+    const struct mf_field *field;
     enum ofperr header_error;
     unsigned int payload_len;
     const uint8_t *payload;
-    int width;
+    int width, copy_len;
+    void *copy_dst;
 
-    header_error = nx_pull_header__(b, allow_cookie, header, field);
+    header_error = nx_pull_header__(b, allow_cookie, header, &field);
     if (header_error && header_error != OFPERR_OFPBMC_BAD_FIELD) {
         return header_error;
     }
@@ -356,12 +358,28 @@ nx_pull_entry__(struct ofpbuf *b, bool allow_cookie, 
uint64_t *header,
         return OFPERR_OFPBMC_BAD_WILDCARDS;
     }
 
-    memcpy(value, payload, MIN(width, sizeof *value));
+    copy_dst = value;
+    copy_len = MIN(width, field ? field->n_bytes : sizeof *value);
+
+    if (field && field->variable_len) {
+        memset(value, 0, field->n_bytes);
+        copy_dst = &value->u8 + field->n_bytes - copy_len;
+    }
+
+    memcpy(copy_dst, payload, copy_len);
     if (mask) {
         if (nxm_hasmask(*header)) {
-            memcpy(mask, payload + width, MIN(width, sizeof *mask));
+            copy_dst = mask;
+            copy_len = MIN(width, field ? field->n_bytes : sizeof *mask);
+
+            if (field && field->variable_len) {
+                memset(mask, 0, field->n_bytes);
+                copy_dst = &mask->u8 + field->n_bytes - copy_len;
+            }
+
+            memcpy(copy_dst, payload + width, copy_len);
         } else {
-            memset(mask, 0xff, MIN(width, sizeof *mask));
+            memset(mask, 0xff, sizeof *mask);
         }
     } else if (nxm_hasmask(*header)) {
         VLOG_DBG_RL(&rl, "OXM header "NXM_HEADER_FMT" includes mask but "
@@ -370,6 +388,9 @@ nx_pull_entry__(struct ofpbuf *b, bool allow_cookie, 
uint64_t *header,
         return OFPERR_OFPBMC_BAD_MASK;
     }
 
+    if (field_) {
+        *field_ = field;
+    }
     return header_error;
 }
 
-- 
2.1.0

_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to