-/* Compares the specified field in 'a' and 'b'. Returns true if the fields are
- * equal, or if the ofp_match wildcard bits in 'wildcards' are set such that
- * non-equal values may be ignored. 'nw_src_mask' and 'nw_dst_mask' must be
- * those that would be set for 'wildcards' by cls_rule_set_masks().
- *
- * The compared field is the one with wildcard bit or bits 'field_wc', offset
- * 'rule_ofs' within cls_rule's "fields" member, and length 'len', in bytes. */
-static inline bool ALWAYS_INLINE
-field_matches(const flow_t *a_, const flow_t *b_,
- uint32_t wildcards, uint32_t nw_src_mask, uint32_t nw_dst_mask,
- uint32_t field_wc, int ofs, int len)
-{
- /* This function is always inlined, and it is always called with 'field_wc'
- * as a compile-time constant, so the "if" conditionals here generate no
- * code. */
- const void *a = (const uint8_t *) a_ + ofs;
- const void *b = (const uint8_t *) b_ + ofs;
- if (!(field_wc & (field_wc - 1))) {
- /* Handle all the single-bit wildcard cases. */
- return wildcards & field_wc || equal_bytes(a, b, len);
- } else if (field_wc == OFPFW_NW_SRC_MASK ||
- field_wc == OFPFW_NW_DST_MASK) {
- uint32_t a_ip = read_uint32(a);
- uint32_t b_ip = read_uint32(b);
- uint32_t mask = (field_wc == OFPFW_NW_SRC_MASK
- ? nw_src_mask : nw_dst_mask);
- return ((a_ip ^ b_ip) & mask) == 0;
- } else {
- abort();
- }
-}
-
-/* Returns true if 'a' and 'b' match, ignoring fields for which the wildcards
- * in 'wildcards' are set. 'nw_src_mask' and 'nw_dst_mask' must be those that
- * would be set for 'wildcards' by cls_rule_set_masks(). 'field_idx' is the
- * index of the first field to be compared; fields before 'field_idx' are
- * assumed to match. (Always returns true if 'field_idx' is CLS_N_FIELDS.) */
-static bool
-rules_match(const struct cls_rule *a, const struct cls_rule *b,
- uint32_t wildcards, uint32_t nw_src_mask, uint32_t nw_dst_mask,
- int field_idx)
-{
- /* This is related to Duff's device (see
- * http://en.wikipedia.org/wiki/Duff's_device). */
- switch (field_idx) {
-#define CLS_FIELD(WILDCARDS, MEMBER, NAME) \
- case CLS_F_IDX_##NAME: \
- if (!field_matches(&a->flow, &b->flow, \
- wildcards, nw_src_mask, nw_dst_mask, \
- WILDCARDS, offsetof(flow_t, MEMBER), \
- sizeof a->flow.MEMBER)) { \
- return false; \
- } \
- /* Fall though */
- CLS_FIELDS
-#undef CLS_FIELD
- }
- return true;
-}
-
-/* Returns true if 'fixed' and 'wild' match. All fields in 'fixed' must have
- * fixed values; 'wild' may contain wildcards.
- *
- * 'field_idx' is the index of the first field to be compared; fields before
- * 'field_idx' are assumed to match. Always returns true if 'field_idx' is
- * CLS_N_FIELDS. */