Global replace of Nicira Networks.
[sliver-openvswitch.git] / lib / nx-match.c
index 9d3b2be..34c8354 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2011, 2012 Nicira Networks.
+ * Copyright (c) 2010, 2011, 2012 Nicira, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -103,7 +103,7 @@ nx_pull_match__(struct ofpbuf *b, unsigned int match_len, bool strict,
         VLOG_DBG_RL(&rl, "nx_match length %u, rounded up to a "
                     "multiple of 8, is longer than space in message (max "
                     "length %zu)", match_len, b->size);
-        return OFPERR_OFPBRC_BAD_LEN;
+        return OFPERR_OFPBMC_BAD_LEN;
     }
 
     cls_rule_init_catchall(rule, priority);
@@ -119,21 +119,21 @@ nx_pull_match__(struct ofpbuf *b, unsigned int match_len, bool strict,
         mf = mf_from_nxm_header(header);
         if (!mf) {
             if (strict) {
-                error = OFPERR_NXBRC_NXM_BAD_TYPE;
+                error = OFPERR_OFPBMC_BAD_FIELD;
             } else {
                 continue;
             }
         } else if (!mf_are_prereqs_ok(mf, &rule->flow)) {
-            error = OFPERR_NXBRC_NXM_BAD_PREREQ;
+            error = OFPERR_OFPBMC_BAD_PREREQ;
         } else if (!mf_is_all_wild(mf, &rule->wc)) {
-            error = OFPERR_NXBRC_NXM_DUP_TYPE;
+            error = OFPERR_OFPBMC_DUP_FIELD;
         } else {
             unsigned int width = mf->n_bytes;
             union mf_value value;
 
             memcpy(&value, p + 4, width);
             if (!mf_is_value_valid(mf, &value)) {
-                error = OFPERR_NXBRC_NXM_BAD_VALUE;
+                error = OFPERR_OFPBMC_BAD_VALUE;
             } else if (!NXM_HASMASK(header)) {
                 error = 0;
                 mf_set_value(mf, &value, rule);
@@ -142,7 +142,7 @@ nx_pull_match__(struct ofpbuf *b, unsigned int match_len, bool strict,
 
                 memcpy(&mask, p + 4 + width, width);
                 if (!mf_is_mask_valid(mf, &mask)) {
-                    error = OFPERR_NXBRC_NXM_BAD_MASK;
+                    error = OFPERR_OFPBMC_BAD_MASK;
                 } else {
                     error = 0;
                     mf_set(mf, &value, &mask, rule);
@@ -153,7 +153,7 @@ nx_pull_match__(struct ofpbuf *b, unsigned int match_len, bool strict,
         /* Check if the match is for a cookie rather than a classifier rule. */
         if ((header == NXM_NX_COOKIE || header == NXM_NX_COOKIE_W) && cookie) {
             if (*cookie_mask) {
-                error = OFPERR_NXBRC_NXM_DUP_TYPE;
+                error = OFPERR_OFPBMC_DUP_FIELD;
             } else {
                 unsigned int width = sizeof *cookie;
 
@@ -178,7 +178,7 @@ nx_pull_match__(struct ofpbuf *b, unsigned int match_len, bool strict,
         }
     }
 
-    return match_len ? OFPERR_NXBRC_NXM_INVALID : 0;
+    return match_len ? OFPERR_OFPBMC_BAD_LEN : 0;
 }
 
 /* Parses the nx_match formatted match description in 'b' with length
@@ -408,6 +408,47 @@ nxm_put_frag(struct ofpbuf *b, const struct cls_rule *cr)
     }
 }
 
+static void
+nxm_put_ip(struct ofpbuf *b, const struct cls_rule *cr,
+           uint8_t icmp_proto, uint32_t icmp_type, uint32_t icmp_code)
+{
+    const flow_wildcards_t wc = cr->wc.wildcards;
+    const struct flow *flow = &cr->flow;
+
+    nxm_put_frag(b, cr);
+
+    if (!(wc & FWW_NW_DSCP)) {
+        nxm_put_8(b, NXM_OF_IP_TOS, flow->nw_tos & IP_DSCP_MASK);
+    }
+
+    if (!(wc & FWW_NW_ECN)) {
+        nxm_put_8(b, NXM_NX_IP_ECN, flow->nw_tos & IP_ECN_MASK);
+    }
+
+    if (!(wc & FWW_NW_TTL)) {
+        nxm_put_8(b, NXM_NX_IP_TTL, flow->nw_ttl);
+    }
+
+    if (!(wc & FWW_NW_PROTO)) {
+        nxm_put_8(b, NXM_OF_IP_PROTO, flow->nw_proto);
+
+        if (flow->nw_proto == IPPROTO_TCP) {
+            nxm_put_16m(b, NXM_OF_TCP_SRC, flow->tp_src, cr->wc.tp_src_mask);
+            nxm_put_16m(b, NXM_OF_TCP_DST, flow->tp_dst, cr->wc.tp_dst_mask);
+        } else if (flow->nw_proto == IPPROTO_UDP) {
+            nxm_put_16m(b, NXM_OF_UDP_SRC, flow->tp_src, cr->wc.tp_src_mask);
+            nxm_put_16m(b, NXM_OF_UDP_DST, flow->tp_dst, cr->wc.tp_dst_mask);
+        } else if (flow->nw_proto == icmp_proto) {
+            if (cr->wc.tp_src_mask) {
+                nxm_put_8(b, icmp_type, ntohs(flow->tp_src));
+            }
+            if (cr->wc.tp_dst_mask) {
+                nxm_put_8(b, icmp_code, ntohs(flow->tp_dst));
+            }
+        }
+    }
+}
+
 /* Appends to 'b' the nx_match format that expresses 'cr' (except for
  * 'cr->priority', because priority is not part of nx_match), plus enough
  * zero bytes to pad the nx_match out to a multiple of 8.  For Flow Mod
@@ -430,7 +471,7 @@ nx_put_match(struct ofpbuf *b, const struct cls_rule *cr,
     int match_len;
     int i;
 
-    BUILD_ASSERT_DECL(FLOW_WC_SEQ == 7);
+    BUILD_ASSERT_DECL(FLOW_WC_SEQ == 10);
 
     /* Metadata. */
     if (!(wc & FWW_IN_PORT)) {
@@ -456,126 +497,32 @@ nx_put_match(struct ofpbuf *b, const struct cls_rule *cr,
         /* IP. */
         nxm_put_32m(b, NXM_OF_IP_SRC, flow->nw_src, cr->wc.nw_src_mask);
         nxm_put_32m(b, NXM_OF_IP_DST, flow->nw_dst, cr->wc.nw_dst_mask);
-        nxm_put_frag(b, cr);
-
-        if (!(wc & FWW_NW_DSCP)) {
-            nxm_put_8(b, NXM_OF_IP_TOS, flow->nw_tos & IP_DSCP_MASK);
-        }
-
-        if (!(wc & FWW_NW_ECN)) {
-            nxm_put_8(b, NXM_NX_IP_ECN, flow->nw_tos & IP_ECN_MASK);
-        }
-
-        if (!(wc & FWW_NW_TTL)) {
-            nxm_put_8(b, NXM_NX_IP_TTL, flow->nw_ttl);
-        }
-
-        if (!(wc & FWW_NW_PROTO)) {
-            nxm_put_8(b, NXM_OF_IP_PROTO, flow->nw_proto);
-            switch (flow->nw_proto) {
-                /* TCP. */
-            case IPPROTO_TCP:
-                if (!(wc & FWW_TP_SRC)) {
-                    nxm_put_16(b, NXM_OF_TCP_SRC, flow->tp_src);
-                }
-                if (!(wc & FWW_TP_DST)) {
-                    nxm_put_16(b, NXM_OF_TCP_DST, flow->tp_dst);
-                }
-                break;
-
-                /* UDP. */
-            case IPPROTO_UDP:
-                if (!(wc & FWW_TP_SRC)) {
-                    nxm_put_16(b, NXM_OF_UDP_SRC, flow->tp_src);
-                }
-                if (!(wc & FWW_TP_DST)) {
-                    nxm_put_16(b, NXM_OF_UDP_DST, flow->tp_dst);
-                }
-                break;
-
-                /* ICMP. */
-            case IPPROTO_ICMP:
-                if (!(wc & FWW_TP_SRC)) {
-                    nxm_put_8(b, NXM_OF_ICMP_TYPE, ntohs(flow->tp_src));
-                }
-                if (!(wc & FWW_TP_DST)) {
-                    nxm_put_8(b, NXM_OF_ICMP_CODE, ntohs(flow->tp_dst));
-                }
-                break;
-            }
-        }
+        nxm_put_ip(b, cr, IPPROTO_ICMP, NXM_OF_ICMP_TYPE, NXM_OF_ICMP_CODE);
     } else if (!(wc & FWW_DL_TYPE) && flow->dl_type == htons(ETH_TYPE_IPV6)) {
         /* IPv6. */
         nxm_put_ipv6(b, NXM_NX_IPV6_SRC, &flow->ipv6_src,
                 &cr->wc.ipv6_src_mask);
         nxm_put_ipv6(b, NXM_NX_IPV6_DST, &flow->ipv6_dst,
                 &cr->wc.ipv6_dst_mask);
-        nxm_put_frag(b, cr);
+        nxm_put_ip(b, cr,
+                   IPPROTO_ICMPV6, NXM_NX_ICMPV6_TYPE, NXM_NX_ICMPV6_CODE);
 
         if (!(wc & FWW_IPV6_LABEL)) {
             nxm_put_32(b, NXM_NX_IPV6_LABEL, flow->ipv6_label);
         }
 
-        if (!(wc & FWW_NW_DSCP)) {
-            nxm_put_8(b, NXM_OF_IP_TOS, flow->nw_tos & IP_DSCP_MASK);
-        }
-
-        if (!(wc & FWW_NW_ECN)) {
-            nxm_put_8(b, NXM_NX_IP_ECN, flow->nw_tos & IP_ECN_MASK);
-        }
-
-        if (!(wc & FWW_NW_TTL)) {
-            nxm_put_8(b, NXM_NX_IP_TTL, flow->nw_ttl);
-        }
-
-        if (!(wc & FWW_NW_PROTO)) {
-            nxm_put_8(b, NXM_OF_IP_PROTO, flow->nw_proto);
-            switch (flow->nw_proto) {
-                /* TCP. */
-            case IPPROTO_TCP:
-                if (!(wc & FWW_TP_SRC)) {
-                    nxm_put_16(b, NXM_OF_TCP_SRC, flow->tp_src);
-                }
-                if (!(wc & FWW_TP_DST)) {
-                    nxm_put_16(b, NXM_OF_TCP_DST, flow->tp_dst);
-                }
-                break;
-
-                /* UDP. */
-            case IPPROTO_UDP:
-                if (!(wc & FWW_TP_SRC)) {
-                    nxm_put_16(b, NXM_OF_UDP_SRC, flow->tp_src);
-                }
-                if (!(wc & FWW_TP_DST)) {
-                    nxm_put_16(b, NXM_OF_UDP_DST, flow->tp_dst);
-                }
-                break;
-
-                /* ICMPv6. */
-            case IPPROTO_ICMPV6:
-                if (!(wc & FWW_TP_SRC)) {
-                    nxm_put_8(b, NXM_NX_ICMPV6_TYPE, ntohs(flow->tp_src));
-
-                    if (flow->tp_src == htons(ND_NEIGHBOR_SOLICIT) ||
-                        flow->tp_src == htons(ND_NEIGHBOR_ADVERT)) {
-                        if (!(wc & FWW_ND_TARGET)) {
-                            nxm_put_ipv6(b, NXM_NX_ND_TARGET, &flow->nd_target,
-                                         &in6addr_exact);
-                        }
-                        if (!(wc & FWW_ARP_SHA)
-                            && flow->tp_src == htons(ND_NEIGHBOR_SOLICIT)) {
-                            nxm_put_eth(b, NXM_NX_ND_SLL, flow->arp_sha);
-                        }
-                        if (!(wc & FWW_ARP_THA)
-                            && flow->tp_src == htons(ND_NEIGHBOR_ADVERT)) {
-                            nxm_put_eth(b, NXM_NX_ND_TLL, flow->arp_tha);
-                        }
-                    }
-                }
-                if (!(wc & FWW_TP_DST)) {
-                    nxm_put_8(b, NXM_NX_ICMPV6_CODE, ntohs(flow->tp_dst));
-                }
-                break;
+        if (flow->nw_proto == IPPROTO_ICMPV6
+            && (flow->tp_src == htons(ND_NEIGHBOR_SOLICIT) ||
+                flow->tp_src == htons(ND_NEIGHBOR_ADVERT))) {
+            nxm_put_ipv6(b, NXM_NX_ND_TARGET, &flow->nd_target,
+                         &cr->wc.nd_target_mask);
+            if (!(wc & FWW_ARP_SHA)
+                && flow->tp_src == htons(ND_NEIGHBOR_SOLICIT)) {
+                nxm_put_eth(b, NXM_NX_ND_SLL, flow->arp_sha);
+            }
+            if (!(wc & FWW_ARP_THA)
+                && flow->tp_src == htons(ND_NEIGHBOR_ADVERT)) {
+                nxm_put_eth(b, NXM_NX_ND_TLL, flow->arp_tha);
             }
         }
     } else if (!(wc & FWW_DL_TYPE) && flow->dl_type == htons(ETH_TYPE_ARP)) {