meta-flow: New functions for reading and writing generalized subfields.
authorBen Pfaff <blp@nicira.com>
Wed, 11 Apr 2012 21:45:34 +0000 (14:45 -0700)
committerBen Pfaff <blp@nicira.com>
Sat, 14 Apr 2012 04:19:09 +0000 (21:19 -0700)
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.

Also update some existing comments.

Signed-off-by: Ben Pfaff <blp@nicira.com>
lib/meta-flow.c
lib/meta-flow.h

index 11d27b1597d3973b04611bdc02600dfc1209bea7..84ba88bf714d6e5d7ab4843d7fa8845c5eb7ab06 100644 (file)
@@ -2241,25 +2241,48 @@ mf_format(const struct mf_field *mf,
     }
 }
 \f
-/* 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);
+}
+
+/* Makes subfield 'sf' within 'rule' exactly match the 'sf->n_bits'
+ * least-significant bits of 'x'.
+ *
+ * Example: suppose that 'sf->field' is originally the following 2-byte field
+ * in 'rule':
  *
  *     value == 0xe00a == 2#1110000000001010
  *      mask == 0xfc3f == 2#1111110000111111
  *
- * The call mf_set_subfield(mf, 0x55, 8, 7, rule) would have the following
- * effect (note that 0x55 is 2#1010101):
+ * The call mf_set_subfield(sf, 0x55, 8, 7, rule), where sf->ofs == 8 and
+ * sf->n_bits == 7 would have the following effect (note that 0x55 is
+ * 2#1010101):
  *
  *     value == 0xd50a == 2#1101010100001010
  *      mask == 0xff3f == 2#1111111100111111
+ *                           ^^^^^^^ affected bits
  *
  * The caller is responsible for ensuring that the result will be a valid
- * wildcard pattern for 'mf'.  The caller is responsible for ensuring that
- * 'rule' meets 'mf''s prerequisites. */
+ * wildcard pattern for 'sf->field'.  The caller is responsible for ensuring
+ * that 'rule' meets 'sf->field''s prerequisites. */
 void
 mf_set_subfield(const struct mf_subfield *sf, uint64_t x,
                 struct cls_rule *rule)
@@ -2314,6 +2337,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. */
index e062312325cf243b69d3f304dcc7f91767dd6498..91d52c7dffc8be9dbfc09d99c979c5ad467b0d5b 100644 (file)
@@ -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 *);