/*
- * Copyright (c) 2011, 2012, 2013, 2014, 2015 Nicira, Inc.
+ * Copyright (c) 2011, 2012, 2013, 2014, 2015, 2016 Nicira, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include <config.h>
-#include "meta-flow.h"
+#include "openvswitch/meta-flow.h"
#include <errno.h>
#include <limits.h>
#include <netinet/ip6.h>
#include "classifier.h"
-#include "dynamic-string.h"
+#include "openvswitch/dynamic-string.h"
#include "nx-match.h"
-#include "ofp-errors.h"
-#include "ofp-util.h"
+#include "openvswitch/ofp-util.h"
#include "ovs-thread.h"
#include "packets.h"
#include "random.h"
#include "tun-metadata.h"
#include "unaligned.h"
#include "util.h"
+#include "openvswitch/ofp-errors.h"
#include "openvswitch/vlog.h"
VLOG_DEFINE_THIS_MODULE(meta_flow);
}
}
+/* Appends a formatted representation of 'sv' to 's'. */
+void
+mf_subvalue_format(const union mf_subvalue *sv, struct ds *s)
+{
+ ds_put_hex(s, sv, sizeof *sv);
+}
+
/* Returns true if 'wc' wildcards all the bits in field 'mf', false if 'wc'
* specifies at least one bit in the field.
*
return !wc->masks.tunnel.ip_src;
case MFF_TUN_DST:
return !wc->masks.tunnel.ip_dst;
+ case MFF_TUN_IPV6_SRC:
+ return ipv6_mask_is_any(&wc->masks.tunnel.ipv6_src);
+ case MFF_TUN_IPV6_DST:
+ return ipv6_mask_is_any(&wc->masks.tunnel.ipv6_dst);
case MFF_TUN_ID:
return !wc->masks.tunnel.tun_id;
case MFF_TUN_TOS:
case MFF_CT_MARK:
return !wc->masks.ct_mark;
case MFF_CT_LABEL:
- return ovs_u128_is_zero(&wc->masks.ct_label);
+ return ovs_u128_is_zero(wc->masks.ct_label);
CASE_MFF_REGS:
return !wc->masks.regs[mf->id - MFF_REG0];
CASE_MFF_XREGS:
return !(wc->masks.mpls_lse[0] & htonl(MPLS_TC_MASK));
case MFF_MPLS_BOS:
return !(wc->masks.mpls_lse[0] & htonl(MPLS_BOS_MASK));
+ case MFF_MPLS_TTL:
+ return !(wc->masks.mpls_lse[0] & htonl(MPLS_TTL_MASK));
case MFF_IPV4_SRC:
return !wc->masks.nw_src;
return is_ip_any(flow) && flow->nw_proto == IPPROTO_SCTP
&& !(flow->nw_frag & FLOW_NW_FRAG_LATER);
case MFP_ICMPV4:
- return is_icmpv4(flow);
+ return is_icmpv4(flow, NULL);
case MFP_ICMPV6:
- return is_icmpv6(flow);
+ return is_icmpv6(flow, NULL);
case MFP_ND:
- return (is_icmpv6(flow)
+ return (is_icmpv6(flow, NULL)
&& flow->tp_dst == htons(0)
&& (flow->tp_src == htons(ND_NEIGHBOR_SOLICIT) ||
flow->tp_src == htons(ND_NEIGHBOR_ADVERT)));
case MFP_ND_SOLICIT:
- return (is_icmpv6(flow)
+ return (is_icmpv6(flow, NULL)
&& flow->tp_dst == htons(0)
&& (flow->tp_src == htons(ND_NEIGHBOR_SOLICIT)));
case MFP_ND_ADVERT:
- return (is_icmpv6(flow)
+ return (is_icmpv6(flow, NULL)
&& flow->tp_dst == htons(0)
&& (flow->tp_src == htons(ND_NEIGHBOR_ADVERT)));
}
void
mf_mask_field_and_prereqs(const struct mf_field *mf, struct flow_wildcards *wc)
{
- mf_set_flow_value(mf, &exact_match_mask, &wc->masks);
+ mf_mask_field_and_prereqs__(mf, &exact_match_mask, wc);
+}
+
+void
+mf_mask_field_and_prereqs__(const struct mf_field *mf,
+ const union mf_value *mask,
+ struct flow_wildcards *wc)
+{
+ mf_set_flow_value_masked(mf, &exact_match_mask, mask, &wc->masks);
switch (mf->prereqs) {
case MFP_ND:
case MFF_TUN_ID:
case MFF_TUN_SRC:
case MFF_TUN_DST:
+ case MFF_TUN_IPV6_SRC:
+ case MFF_TUN_IPV6_DST:
case MFF_TUN_TOS:
case MFF_TUN_TTL:
case MFF_TUN_GBP_ID:
case MFF_ETH_DST:
case MFF_ETH_TYPE:
case MFF_VLAN_TCI:
+ case MFF_MPLS_TTL:
case MFF_IPV4_SRC:
case MFF_IPV4_DST:
case MFF_IPV6_SRC:
case MFF_TUN_DST:
value->be32 = flow->tunnel.ip_dst;
break;
+ case MFF_TUN_IPV6_SRC:
+ value->ipv6 = flow->tunnel.ipv6_src;
+ break;
+ case MFF_TUN_IPV6_DST:
+ value->ipv6 = flow->tunnel.ipv6_dst;
+ break;
case MFF_TUN_FLAGS:
value->be16 = htons(flow->tunnel.flags & FLOW_TNL_PUB_F_MASK);
break;
value->u8 = mpls_lse_to_bos(flow->mpls_lse[0]);
break;
+ case MFF_MPLS_TTL:
+ value->u8 = mpls_lse_to_ttl(flow->mpls_lse[0]);
+ break;
+
case MFF_IPV4_SRC:
value->be32 = flow->nw_src;
break;
case MFF_TUN_DST:
match_set_tun_dst(match, value->be32);
break;
+ case MFF_TUN_IPV6_SRC:
+ match_set_tun_ipv6_src(match, &value->ipv6);
+ break;
+ case MFF_TUN_IPV6_DST:
+ match_set_tun_ipv6_dst(match, &value->ipv6);
+ break;
case MFF_TUN_FLAGS:
match_set_tun_flags(match, ntohs(value->be16));
break;
match_set_mpls_bos(match, 0, value->u8);
break;
+ case MFF_MPLS_TTL:
+ match_set_mpls_ttl(match, 0, value->u8);
+ break;
+
case MFF_IPV4_SRC:
match_set_nw_src(match, value->be32);
break;
case MFF_TUN_DST:
flow->tunnel.ip_dst = value->be32;
break;
+ case MFF_TUN_IPV6_SRC:
+ flow->tunnel.ipv6_src = value->ipv6;
+ break;
+ case MFF_TUN_IPV6_DST:
+ flow->tunnel.ipv6_dst = value->ipv6;
+ break;
case MFF_TUN_FLAGS:
flow->tunnel.flags = (flow->tunnel.flags & ~FLOW_TNL_PUB_F_MASK) |
ntohs(value->be16);
flow_set_mpls_bos(flow, 0, value->u8);
break;
+ case MFF_MPLS_TTL:
+ flow_set_mpls_ttl(flow, 0, value->u8);
+ break;
+
case MFF_IPV4_SRC:
flow->nw_src = value->be32;
break;
case MFF_TUN_DST:
match_set_tun_dst_masked(match, htonl(0), htonl(0));
break;
+ case MFF_TUN_IPV6_SRC:
+ memset(&match->wc.masks.tunnel.ipv6_src, 0,
+ sizeof match->wc.masks.tunnel.ipv6_src);
+ memset(&match->flow.tunnel.ipv6_src, 0,
+ sizeof match->flow.tunnel.ipv6_src);
+ break;
+ case MFF_TUN_IPV6_DST:
+ memset(&match->wc.masks.tunnel.ipv6_dst, 0,
+ sizeof match->wc.masks.tunnel.ipv6_dst);
+ memset(&match->flow.tunnel.ipv6_dst, 0,
+ sizeof match->flow.tunnel.ipv6_dst);
+ break;
case MFF_TUN_FLAGS:
match_set_tun_flags_masked(match, 0, 0);
break;
match_set_any_mpls_bos(match, 0);
break;
+ case MFF_MPLS_TTL:
+ match_set_any_mpls_ttl(match, 0);
+ break;
+
case MFF_IPV4_SRC:
case MFF_ARP_SPA:
match_set_nw_src_masked(match, htonl(0), htonl(0));
case MFF_MPLS_LABEL:
case MFF_MPLS_TC:
case MFF_MPLS_BOS:
+ case MFF_MPLS_TTL:
case MFF_IP_PROTO:
case MFF_IP_TTL:
case MFF_IP_DSCP:
case MFF_TUN_DST:
match_set_tun_dst_masked(match, value->be32, mask->be32);
break;
+ case MFF_TUN_IPV6_SRC:
+ match_set_tun_ipv6_src_masked(match, &value->ipv6, &mask->ipv6);
+ break;
+ case MFF_TUN_IPV6_DST:
+ match_set_tun_ipv6_dst_masked(match, &value->ipv6, &mask->ipv6);
+ break;
case MFF_TUN_FLAGS:
match_set_tun_flags_masked(match, ntohs(value->be16), ntohs(mask->be16));
break;