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