-normalize_match(struct ofp_match *m)
-{
- enum { OFPFW_NW = (OFPFW_NW_SRC_MASK | OFPFW_NW_DST_MASK | OFPFW_NW_PROTO
- | OFPFW_NW_TOS) };
- enum { OFPFW_TP = OFPFW_TP_SRC | OFPFW_TP_DST };
- uint32_t wc;
-
- wc = ntohl(m->wildcards) & OFPFW_ALL;
- if (wc & OFPFW_DL_TYPE) {
- m->dl_type = 0;
-
- /* Can't sensibly match on network or transport headers if the
- * data link type is unknown. */
- wc |= OFPFW_NW | OFPFW_TP;
- m->nw_src = m->nw_dst = m->nw_proto = m->nw_tos = 0;
- m->tp_src = m->tp_dst = 0;
- } else if (m->dl_type == htons(ETH_TYPE_IP)) {
- if (wc & OFPFW_NW_PROTO) {
- m->nw_proto = 0;
-
- /* Can't sensibly match on transport headers if the network
- * protocol is unknown. */
- wc |= OFPFW_TP;
- m->tp_src = m->tp_dst = 0;
- } else if (m->nw_proto == IPPROTO_TCP ||
- m->nw_proto == IPPROTO_UDP ||
- m->nw_proto == IPPROTO_ICMP) {
- if (wc & OFPFW_TP_SRC) {
- m->tp_src = 0;
- }
- if (wc & OFPFW_TP_DST) {
- m->tp_dst = 0;
- }
- } else {
- /* Transport layer fields will always be extracted as zeros, so we
- * can do an exact-match on those values. */
- wc &= ~OFPFW_TP;
- m->tp_src = m->tp_dst = 0;
- }
- if (wc & OFPFW_NW_SRC_MASK) {
- m->nw_src &= ofputil_wcbits_to_netmask(wc >> OFPFW_NW_SRC_SHIFT);
+ofputil_normalize_rule(struct cls_rule *rule, enum nx_flow_format flow_format)
+{
+ enum {
+ MAY_NW_ADDR = 1 << 0, /* nw_src, nw_dst */
+ MAY_TP_ADDR = 1 << 1, /* tp_src, tp_dst */
+ MAY_NW_PROTO = 1 << 2, /* nw_proto */
+ MAY_NW_TOS = 1 << 3, /* nw_tos */
+ MAY_ARP_SHA = 1 << 4, /* arp_sha */
+ MAY_ARP_THA = 1 << 5, /* arp_tha */
+ MAY_IPV6_ADDR = 1 << 6, /* ipv6_src, ipv6_dst */
+ MAY_ND_TARGET = 1 << 7 /* nd_target */
+ } may_match;
+
+ struct flow_wildcards wc;
+
+ /* Figure out what fields may be matched. */
+ if (rule->flow.dl_type == htons(ETH_TYPE_IP)) {
+ may_match = MAY_NW_PROTO | MAY_NW_TOS | MAY_NW_ADDR;
+ if (rule->flow.nw_proto == IPPROTO_TCP ||
+ rule->flow.nw_proto == IPPROTO_UDP ||
+ rule->flow.nw_proto == IPPROTO_ICMP) {
+ may_match |= MAY_TP_ADDR;