vconn: New function normalize_match().
authorBen Pfaff <blp@nicira.com>
Mon, 2 Mar 2009 19:12:33 +0000 (11:12 -0800)
committerBen Pfaff <blp@nicira.com>
Mon, 2 Mar 2009 21:42:06 +0000 (13:42 -0800)
lib/vconn.c
lib/vconn.h

index cf527ddf9e1377f8d3ce2481aa5e2917fafb9f66..f43b35f18987367fe2e0a9af022f226e92656072 100644 (file)
@@ -1346,6 +1346,67 @@ actions_next(struct actions_iterator *iter)
     }
 }
 
+void
+normalize_match(struct ofp_match *m)
+{
+    enum { OFPFW_NW = OFPFW_NW_SRC_MASK | OFPFW_NW_DST_MASK | OFPFW_NW_PROTO };
+    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 m 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 = 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 m 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-m on those values.  */
+            wc &= ~OFPFW_TP;
+            m->tp_src = m->tp_dst = 0;
+        }
+        if (wc & OFPFW_NW_SRC_MASK) {
+            m->nw_src &= flow_nw_bits_to_mask(wc, OFPFW_NW_SRC_SHIFT);
+        }
+        if (wc & OFPFW_NW_DST_MASK) {
+            m->nw_dst &= flow_nw_bits_to_mask(wc, OFPFW_NW_DST_SHIFT);
+        }
+    } else {
+        /* Network and transport layer fields will always be extracted as
+         * zeros, so we can do an exact-m on those values. */
+        wc &= ~(OFPFW_NW | OFPFW_TP);
+        m->nw_proto = m->nw_src = m->nw_dst = 0;
+        m->tp_src = m->tp_dst = 0;
+    }
+    if (wc & OFPFW_DL_SRC) {
+        memset(m->dl_src, 0, sizeof m->dl_src);
+    }
+    if (wc & OFPFW_DL_DST) {
+        memset(m->dl_dst, 0, sizeof m->dl_dst);
+    }
+    m->wildcards = htonl(wc);
+}
+
 void
 vconn_init(struct vconn *vconn, struct vconn_class *class, int connect_status,
            uint32_t ip, const char *name, bool reconnectable)
index 3c7a9a4ac968a5bc1eed48ebf10c5c9795007ad4..41d60c698810281b828f08beb32ab50530110620 100644 (file)
@@ -43,6 +43,7 @@ struct ofpbuf;
 struct flow;
 struct ofp_action_header;
 struct ofp_header;
+struct ofp_match;
 struct ofp_stats_reply;
 struct pvconn;
 struct vconn;
@@ -130,6 +131,8 @@ const union ofp_action *actions_first(struct actions_iterator *,
 const union ofp_action *actions_next(struct actions_iterator *);
 int validate_actions(const union ofp_action *, size_t n_actions);
 
+void normalize_match(struct ofp_match *);
+
 static inline int
 ofp_mkerr(uint16_t type, uint16_t code)
 {