dpif-netlink: Fix compiler warning.
[cascardo/ovs.git] / lib / match.c
index 8364906..ca9492f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014 Nicira, Inc.
+ * Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014, 2015 Nicira, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -21,6 +21,7 @@
 #include "dynamic-string.h"
 #include "ofp-util.h"
 #include "packets.h"
+#include "tun-metadata.h"
 
 /* Converts the flow in 'flow' into a match in 'match', with the given
  * 'wildcards'. */
@@ -31,6 +32,7 @@ match_init(struct match *match,
     match->flow = *flow;
     match->wc = *wc;
     match_zero_wildcarded_fields(match);
+    memset(&match->tun_md, 0, sizeof match->tun_md);
 }
 
 /* Converts a flow into a match.  It sets the wildcard masks based on
@@ -39,108 +41,13 @@ match_init(struct match *match,
 void
 match_wc_init(struct match *match, const struct flow *flow)
 {
-    struct flow_wildcards *wc;
-    int i;
-
     match->flow = *flow;
-    wc = &match->wc;
-    memset(&wc->masks, 0x0, sizeof wc->masks);
-
-    memset(&wc->masks.dl_type, 0xff, sizeof wc->masks.dl_type);
-
-    if (flow->nw_proto) {
-        memset(&wc->masks.nw_proto, 0xff, sizeof wc->masks.nw_proto);
-    }
-
-    if (flow->skb_priority) {
-        memset(&wc->masks.skb_priority, 0xff, sizeof wc->masks.skb_priority);
-    }
-
-    if (flow->pkt_mark) {
-        memset(&wc->masks.pkt_mark, 0xff, sizeof wc->masks.pkt_mark);
-    }
-
-    for (i = 0; i < FLOW_N_REGS; i++) {
-        if (flow->regs[i]) {
-            memset(&wc->masks.regs[i], 0xff, sizeof wc->masks.regs[i]);
-        }
-    }
-
-    if (flow->tunnel.ip_dst) {
-        if (flow->tunnel.flags & FLOW_TNL_F_KEY) {
-            memset(&wc->masks.tunnel.tun_id, 0xff, sizeof wc->masks.tunnel.tun_id);
-        }
-        memset(&wc->masks.tunnel.ip_src, 0xff, sizeof wc->masks.tunnel.ip_src);
-        memset(&wc->masks.tunnel.ip_dst, 0xff, sizeof wc->masks.tunnel.ip_dst);
-        memset(&wc->masks.tunnel.flags, 0xff, sizeof wc->masks.tunnel.flags);
-        memset(&wc->masks.tunnel.ip_tos, 0xff, sizeof wc->masks.tunnel.ip_tos);
-        memset(&wc->masks.tunnel.ip_ttl, 0xff, sizeof wc->masks.tunnel.ip_ttl);
-    } else if (flow->tunnel.tun_id) {
-        memset(&wc->masks.tunnel.tun_id, 0xff, sizeof wc->masks.tunnel.tun_id);
-    }
-
-    memset(&wc->masks.metadata, 0xff, sizeof wc->masks.metadata);
-    memset(&wc->masks.in_port, 0xff, sizeof wc->masks.in_port);
-    memset(&wc->masks.vlan_tci, 0xff, sizeof wc->masks.vlan_tci);
-    memset(&wc->masks.dl_src, 0xff, sizeof wc->masks.dl_src);
-    memset(&wc->masks.dl_dst, 0xff, sizeof wc->masks.dl_dst);
-
-    if (flow->dl_type == htons(ETH_TYPE_IPV6)) {
-        memset(&wc->masks.ipv6_src, 0xff, sizeof wc->masks.ipv6_src);
-        memset(&wc->masks.ipv6_dst, 0xff, sizeof wc->masks.ipv6_dst);
-        memset(&wc->masks.ipv6_label, 0xff, sizeof wc->masks.ipv6_label);
-    } else if (flow->dl_type == htons(ETH_TYPE_IP) ||
-               (flow->dl_type == htons(ETH_TYPE_ARP)) ||
-               (flow->dl_type == htons(ETH_TYPE_RARP))) {
-        memset(&wc->masks.nw_src, 0xff, sizeof wc->masks.nw_src);
-        memset(&wc->masks.nw_dst, 0xff, sizeof wc->masks.nw_dst);
-    } else if (eth_type_mpls(flow->dl_type)) {
-        int i;
-
-        for (i = 0; i < FLOW_MAX_MPLS_LABELS; i++) {
-            wc->masks.mpls_lse[i] = OVS_BE32_MAX;
-            if (flow->mpls_lse[i] & htonl(MPLS_BOS_MASK)) {
-                break;
-            }
-        }
-    }
-
-    if (flow->dl_type == htons(ETH_TYPE_ARP) ||
-        flow->dl_type == htons(ETH_TYPE_RARP)) {
-        memset(&wc->masks.arp_sha, 0xff, sizeof wc->masks.arp_sha);
-        memset(&wc->masks.arp_tha, 0xff, sizeof wc->masks.arp_tha);
-    }
 
-    if (is_ip_any(flow)) {
-        memset(&wc->masks.nw_tos, 0xff, sizeof wc->masks.nw_tos);
-        memset(&wc->masks.nw_ttl, 0xff, sizeof wc->masks.nw_ttl);
+    flow_wildcards_init_for_packet(&match->wc, flow);
+    WC_MASK_FIELD(&match->wc, regs);
+    WC_MASK_FIELD(&match->wc, metadata);
 
-        if (flow->nw_frag) {
-            memset(&wc->masks.nw_frag, 0xff, sizeof wc->masks.nw_frag);
-            if (flow->nw_frag & FLOW_NW_FRAG_LATER) {
-                /* No transport layer header in later fragments. */
-                return;
-            }
-        }
-
-        if (flow->nw_proto == IPPROTO_ICMP ||
-            flow->nw_proto == IPPROTO_ICMPV6 ||
-            (flow->tp_src || flow->tp_dst)) {
-            memset(&wc->masks.tp_src, 0xff, sizeof wc->masks.tp_src);
-            memset(&wc->masks.tp_dst, 0xff, sizeof wc->masks.tp_dst);
-        }
-        if (flow->nw_proto == IPPROTO_TCP) {
-            memset(&wc->masks.tcp_flags, 0xff, sizeof wc->masks.tcp_flags);
-        }
-
-        if (flow->nw_proto == IPPROTO_ICMPV6) {
-            memset(&wc->masks.arp_sha, 0xff, sizeof wc->masks.arp_sha);
-            memset(&wc->masks.arp_tha, 0xff, sizeof wc->masks.arp_tha);
-            memset(&wc->masks.nd_target, 0xff, sizeof wc->masks.nd_target);
-        }
-    }
-
-    return;
+    memset(&match->tun_md, 0, sizeof match->tun_md);
 }
 
 /* Initializes 'match' as a "catch-all" match that matches every packet. */
@@ -149,6 +56,7 @@ match_init_catchall(struct match *match)
 {
     memset(&match->flow, 0, sizeof match->flow);
     flow_wildcards_init_catchall(&match->wc);
+    memset(&match->tun_md, 0, sizeof match->tun_md);
 }
 
 /* For each bit or field wildcarded in 'match', sets the corresponding bit or
@@ -185,6 +93,13 @@ match_set_recirc_id(struct match *match, uint32_t value)
     match->wc.masks.recirc_id = UINT32_MAX;
 }
 
+void
+match_set_conj_id(struct match *match, uint32_t value)
+{
+    match->flow.conj_id = value;
+    match->wc.masks.conj_id = UINT32_MAX;
+}
+
 void
 match_set_reg(struct match *match, unsigned int reg_idx, uint32_t value)
 {
@@ -215,6 +130,13 @@ match_set_xreg_masked(struct match *match, unsigned int xreg_idx,
     flow_set_xreg(&match->flow, xreg_idx, value & mask);
 }
 
+void
+match_set_actset_output(struct match *match, ofp_port_t actset_output)
+{
+    match->wc.masks.actset_output = u16_to_ofp(UINT16_MAX);
+    match->flow.actset_output = actset_output;
+}
+
 void
 match_set_metadata(struct match *match, ovs_be64 metadata)
 {
@@ -307,6 +229,32 @@ match_set_tun_flags_masked(struct match *match, uint16_t flags, uint16_t mask)
     match->flow.tunnel.flags = flags & mask;
 }
 
+void
+match_set_tun_gbp_id_masked(struct match *match, ovs_be16 gbp_id, ovs_be16 mask)
+{
+    match->wc.masks.tunnel.gbp_id = mask;
+    match->flow.tunnel.gbp_id = gbp_id & mask;
+}
+
+void
+match_set_tun_gbp_id(struct match *match, ovs_be16 gbp_id)
+{
+    match_set_tun_gbp_id_masked(match, gbp_id, OVS_BE16_MAX);
+}
+
+void
+match_set_tun_gbp_flags_masked(struct match *match, uint8_t flags, uint8_t mask)
+{
+    match->wc.masks.tunnel.gbp_flags = mask;
+    match->flow.tunnel.gbp_flags = flags & mask;
+}
+
+void
+match_set_tun_gbp_flags(struct match *match, uint8_t flags)
+{
+    match_set_tun_gbp_flags_masked(match, flags, UINT8_MAX);
+}
+
 void
 match_set_in_port(struct match *match, ofp_port_t ofp_port)
 {
@@ -833,8 +781,9 @@ match_init_hidden_fields(struct match *m)
 }
 
 static void
-format_eth_masked(struct ds *s, const char *name, const uint8_t eth[6],
-                  const uint8_t mask[6])
+format_eth_masked(struct ds *s, const char *name,
+                  const uint8_t eth[ETH_ADDR_LEN],
+                  const uint8_t mask[ETH_ADDR_LEN])
 {
     if (!eth_addr_is_zero(mask)) {
         ds_put_format(s, "%s=", name);
@@ -934,6 +883,15 @@ format_flow_tunnel(struct ds *s, const struct match *match)
     format_ip_netmask(s, "tun_src", tnl->ip_src, wc->masks.tunnel.ip_src);
     format_ip_netmask(s, "tun_dst", tnl->ip_dst, wc->masks.tunnel.ip_dst);
 
+    if (wc->masks.tunnel.gbp_id) {
+        format_be16_masked(s, "tun_gbp_id", tnl->gbp_id,
+                           wc->masks.tunnel.gbp_id);
+    }
+
+    if (wc->masks.tunnel.gbp_flags) {
+        ds_put_format(s, "tun_gbp_flags=%#"PRIx8",", tnl->gbp_flags);
+    }
+
     if (wc->masks.tunnel.ip_tos) {
         ds_put_format(s, "tun_tos=%"PRIx8",", tnl->ip_tos);
     }
@@ -944,12 +902,13 @@ format_flow_tunnel(struct ds *s, const struct match *match)
         format_flags(s, flow_tun_flag_to_string, tnl->flags, '|');
         ds_put_char(s, ',');
     }
+    tun_metadata_match_format(s, match);
 }
 
 /* Appends a string representation of 'match' to 's'.  If 'priority' is
  * different from OFP_DEFAULT_PRIORITY, includes it in 's'. */
 void
-match_format(const struct match *match, struct ds *s, unsigned int priority)
+match_format(const struct match *match, struct ds *s, int priority)
 {
     const struct flow_wildcards *wc = &match->wc;
     size_t start_len = s->length;
@@ -959,10 +918,10 @@ match_format(const struct match *match, struct ds *s, unsigned int priority)
 
     int i;
 
-    BUILD_ASSERT_DECL(FLOW_WC_SEQ == 27);
+    BUILD_ASSERT_DECL(FLOW_WC_SEQ == 32);
 
     if (priority != OFP_DEFAULT_PRIORITY) {
-        ds_put_format(s, "priority=%u,", priority);
+        ds_put_format(s, "priority=%d,", priority);
     }
 
     format_uint32_masked(s, "pkt_mark", f->pkt_mark, wc->masks.pkt_mark);
@@ -972,15 +931,25 @@ match_format(const struct match *match, struct ds *s, unsigned int priority)
                              wc->masks.recirc_id);
     }
 
-    if (f->dp_hash && wc->masks.dp_hash) {
+    if (wc->masks.dp_hash) {
         format_uint32_masked(s, "dp_hash", f->dp_hash,
                              wc->masks.dp_hash);
     }
 
+    if (wc->masks.conj_id) {
+        ds_put_format(s, "conj_id=%"PRIu32",", f->conj_id);
+    }
+
     if (wc->masks.skb_priority) {
         ds_put_format(s, "skb_priority=%#"PRIx32",", f->skb_priority);
     }
 
+    if (wc->masks.actset_output) {
+        ds_put_cstr(s, "actset_output=");
+        ofputil_format_port(f->actset_output, s);
+        ds_put_char(s, ',');
+    }
+
     if (wc->masks.dl_type) {
         skip_type = true;
         if (f->dl_type == htons(ETH_TYPE_IP)) {
@@ -1125,19 +1094,19 @@ match_format(const struct match *match, struct ds *s, unsigned int priority)
     }
     if (wc->masks.mpls_lse[0] & htonl(MPLS_LABEL_MASK)) {
         ds_put_format(s, "mpls_label=%"PRIu32",",
-                 mpls_lse_to_label(f->mpls_lse[0]));
+                      mpls_lse_to_label(f->mpls_lse[0]));
     }
     if (wc->masks.mpls_lse[0] & htonl(MPLS_TC_MASK)) {
         ds_put_format(s, "mpls_tc=%"PRIu8",",
-                 mpls_lse_to_tc(f->mpls_lse[0]));
+                      mpls_lse_to_tc(f->mpls_lse[0]));
     }
     if (wc->masks.mpls_lse[0] & htonl(MPLS_TTL_MASK)) {
         ds_put_format(s, "mpls_ttl=%"PRIu8",",
-                 mpls_lse_to_ttl(f->mpls_lse[0]));
+                      mpls_lse_to_ttl(f->mpls_lse[0]));
     }
     if (wc->masks.mpls_lse[0] & htonl(MPLS_BOS_MASK)) {
         ds_put_format(s, "mpls_bos=%"PRIu8",",
-                 mpls_lse_to_bos(f->mpls_lse[0]));
+                      mpls_lse_to_bos(f->mpls_lse[0]));
     }
     format_be32_masked(s, "mpls_lse1", f->mpls_lse[1], wc->masks.mpls_lse[1]);
     format_be32_masked(s, "mpls_lse2", f->mpls_lse[2], wc->masks.mpls_lse[2]);
@@ -1182,16 +1151,23 @@ match_format(const struct match *match, struct ds *s, unsigned int priority)
     }
     if (is_ip_any(f) && f->nw_proto == IPPROTO_TCP && wc->masks.tcp_flags) {
         uint16_t mask = TCP_FLAGS(wc->masks.tcp_flags);
+
         if (mask == TCP_FLAGS(OVS_BE16_MAX)) {
-            ds_put_format(s, "tcp_flags=0x%03"PRIx16",", ntohs(f->tcp_flags));
-        } else {
+            ds_put_cstr(s, "tcp_flags=");
+            if (f->tcp_flags) {
+                format_flags(s, packet_tcp_flag_to_string, ntohs(f->tcp_flags),
+                             '|');
+            } else {
+                ds_put_cstr(s, "0"); /* Zero flags. */
+            }
+        } else if (mask) {
             format_flags_masked(s, "tcp_flags", packet_tcp_flag_to_string,
                                 ntohs(f->tcp_flags), mask);
         }
     }
 
-    if (s->length > start_len && ds_last(s) == ',') {
-        s->length--;
+    if (s->length > start_len) {
+        ds_chomp(s, ',');
     }
 }
 
@@ -1199,7 +1175,7 @@ match_format(const struct match *match, struct ds *s, unsigned int priority)
  * different from OFP_DEFAULT_PRIORITY, includes it in the string.  The caller
  * must free the string (with free()). */
 char *
-match_to_string(const struct match *match, unsigned int priority)
+match_to_string(const struct match *match, int priority)
 {
     struct ds s = DS_EMPTY_INITIALIZER;
     match_format(match, &s, priority);
@@ -1256,6 +1232,7 @@ minimatch_expand(const struct minimatch *src, struct match *dst)
 {
     miniflow_expand(&src->flow, &dst->flow);
     minimask_expand(&src->mask, &dst->wc);
+    memset(&dst->tun_md, 0, sizeof dst->tun_md);
 }
 
 /* Returns true if 'a' and 'b' match the same packets, false otherwise.  */
@@ -1276,13 +1253,13 @@ bool
 minimatch_matches_flow(const struct minimatch *match,
                        const struct flow *target)
 {
-    const uint32_t *target_u32 = (const uint32_t *) target;
-    const uint32_t *flowp = miniflow_get_u32_values(&match->flow);
-    const uint32_t *maskp = miniflow_get_u32_values(&match->mask.masks);
-    uint64_t map;
+    const uint64_t *target_u64 = (const uint64_t *) target;
+    const uint64_t *flowp = miniflow_get_values(&match->flow);
+    const uint64_t *maskp = miniflow_get_values(&match->mask.masks);
+    int idx;
 
-    for (map = match->flow.map; map; map = zero_rightmost_1bit(map)) {
-        if ((*flowp++ ^ target_u32[raw_ctz(map)]) & *maskp++) {
+    MAP_FOR_EACH_INDEX(idx, match->flow.map) {
+        if ((*flowp++ ^ target_u64[idx]) & *maskp++) {
             return false;
         }
     }
@@ -1293,8 +1270,7 @@ minimatch_matches_flow(const struct minimatch *match,
 /* Appends a string representation of 'match' to 's'.  If 'priority' is
  * different from OFP_DEFAULT_PRIORITY, includes it in 's'. */
 void
-minimatch_format(const struct minimatch *match, struct ds *s,
-                 unsigned int priority)
+minimatch_format(const struct minimatch *match, struct ds *s, int priority)
 {
     struct match megamatch;
 
@@ -1306,7 +1282,7 @@ minimatch_format(const struct minimatch *match, struct ds *s,
  * different from OFP_DEFAULT_PRIORITY, includes it in the string.  The caller
  * must free the string (with free()). */
 char *
-minimatch_to_string(const struct minimatch *match, unsigned int priority)
+minimatch_to_string(const struct minimatch *match, int priority)
 {
     struct match megamatch;