The existing functions for reading and writing the values of subfields only handle subfields up to 64 bits wide. These new functions handle subfields of any width.
Signed-off-by: Ben Pfaff <b...@nicira.com> --- lib/meta-flow.c | 41 ++++++++++++++++++++++++++++++++++++----- lib/meta-flow.h | 20 ++++++++++++++++++++ 2 files changed, 56 insertions(+), 5 deletions(-) diff --git a/lib/meta-flow.c b/lib/meta-flow.c index 11d27b1..a8cfd74 100644 --- a/lib/meta-flow.c +++ b/lib/meta-flow.c @@ -2241,12 +2241,27 @@ mf_format(const struct mf_field *mf, } } -/* Makes a subfield starting at bit offset 'ofs' and continuing for 'n_bits' in - * 'rule''s field 'mf' exactly match the 'n_bits' least-significant bits of - * 'x'. +/* Makes subfield 'sf' within 'rule' exactly match the 'sf->n_bits' + * least-significant bits in 'x'. * - * Example: suppose that 'mf' is originally the following 2-byte field in - * 'rule': + * See mf_set_subfield() for an example. + * + * The difference between this function and mf_set_subfield() is that the + * latter function can only handle subfields up to 64 bits wide, whereas this + * one handles the general case. On the other hand, mf_set_subfield() is + * arguably easier to use. */ +void +mf_write_subfield(const struct mf_subfield *sf, const union mf_subvalue *x, + struct cls_rule *rule) +{ + const struct mf_field *field = sf->field; + union mf_value value, mask; + + mf_get(field, rule, &value, &mask); + bitwise_copy(x, sizeof *x, 0, &value, field->n_bytes, sf->ofs, sf->n_bits); + bitwise_one ( &mask, field->n_bytes, sf->ofs, sf->n_bits); + mf_set(field, &value, &mask, rule); +} * * value == 0xe00a == 2#1110000000001010 * mask == 0xfc3f == 2#1111110000111111 @@ -2314,6 +2329,22 @@ mf_set_subfield_value(const struct mf_subfield *sf, uint64_t x, } } +/* Initializes 'x' to the value of 'sf' within 'flow'. 'sf' must be valid for + * reading 'flow', e.g. as checked by mf_check_src(). */ +void +mf_read_subfield(const struct mf_subfield *sf, const struct flow *flow, + union mf_subvalue *x) +{ + union mf_value value; + + mf_get_value(sf->field, flow, &value); + + memset(x, 0, sizeof *x); + bitwise_copy(&value, sf->field->n_bytes, sf->ofs, + x, sizeof *x, 0, + sf->n_bits); +} + /* Returns the value of 'sf' within 'flow'. 'sf' must be valid for reading * 'flow', e.g. as checked by mf_check_src() and sf->n_bits must be 64 or * less. */ diff --git a/lib/meta-flow.h b/lib/meta-flow.h index e062312..91d52c7 100644 --- a/lib/meta-flow.h +++ b/lib/meta-flow.h @@ -207,6 +207,7 @@ union mf_value { uint8_t mac[ETH_ADDR_LEN]; struct in6_addr ipv6; }; +BUILD_ASSERT_DECL(sizeof(union mf_value) == 16); /* Part of a field. */ struct mf_subfield { @@ -215,6 +216,19 @@ struct mf_subfield { unsigned int n_bits; /* Number of bits. */ }; +/* Data for some part of an mf_field. + * + * The data is stored "right-justified". For example, if "union mf_subvalue + * value" contains NXM_OF_VLAN_TCI[0..11], then one could access the + * corresponding data in value.be16[7] as the bits in the mask htons(0xfff). */ +union mf_subvalue { + uint8_t u8[16]; + ovs_be16 be16[8]; + ovs_be32 be32[4]; + ovs_be64 be64[2]; +}; +BUILD_ASSERT_DECL(sizeof(union mf_value) == sizeof (union mf_subvalue)); + /* Finding mf_fields. */ const struct mf_field *mf_from_id(enum mf_field_id); const struct mf_field *mf_from_name(const char *name); @@ -253,12 +267,18 @@ void mf_set_wild(const struct mf_field *, struct cls_rule *); void mf_random_value(const struct mf_field *, union mf_value *value); /* Subfields. */ +void mf_write_subfield(const struct mf_subfield *, const union mf_subvalue *, + struct cls_rule *); void mf_set_subfield(const struct mf_subfield *, uint64_t value, struct cls_rule *); void mf_set_subfield_value(const struct mf_subfield *, uint64_t value, struct flow *); + +void mf_read_subfield(const struct mf_subfield *, const struct flow *, + union mf_subvalue *); uint64_t mf_get_subfield(const struct mf_subfield *, const struct flow *); + void mf_format_subfield(const struct mf_subfield *, struct ds *); char *mf_parse_subfield__(struct mf_subfield *sf, const char **s); const char *mf_parse_subfield(struct mf_subfield *, const char *); -- 1.7.2.5 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev