X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;ds=sidebyside;f=lib%2Fmatch.c;h=6a4fec72f87da44cc8d317b75e1820627ad29bc1;hb=7c690f462fec1af60d76c67fac226fc648ea9149;hp=69129d4f2abc1cf145d57cc803371693e3650ec4;hpb=e8d780af73b8571f5998cae8d3fa97069e49c9fe;p=sliver-openvswitch.git diff --git a/lib/match.c b/lib/match.c index 69129d4f2..6a4fec72f 100644 --- a/lib/match.c +++ b/lib/match.c @@ -21,6 +21,10 @@ #include "byte-order.h" #include "dynamic-string.h" #include "packets.h" +#include "vlog.h" + +VLOG_DEFINE_THIS_MODULE(match); + /* Converts the flow in 'flow' into a match in 'match', with the given * 'wildcards'. */ @@ -33,12 +37,94 @@ match_init(struct match *match, match_zero_wildcarded_fields(match); } +/* Converts a flow into a match. It sets the wildcard masks based on + * the packet contents. It will not set the mask for fields that do not + * make sense for the packet type. */ +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); + } + + 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 || flow->tunnel.tun_id) { + 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); + } + 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))) { + memset(&wc->masks.nw_src, 0xff, sizeof wc->masks.nw_src); + memset(&wc->masks.nw_dst, 0xff, sizeof wc->masks.nw_dst); + } + + if (flow->dl_type == htons(ETH_TYPE_ARP)) { + memset(&wc->masks.arp_sha, 0xff, sizeof wc->masks.arp_sha); + memset(&wc->masks.arp_tha, 0xff, sizeof wc->masks.arp_tha); + } + + if (flow->dl_type == htons(ETH_TYPE_IPV6) || + flow->dl_type == htons(ETH_TYPE_IP)) { + memset(&wc->masks.nw_tos, 0xff, sizeof wc->masks.nw_tos); + memset(&wc->masks.nw_ttl, 0xff, sizeof wc->masks.nw_ttl); + } + + if (flow->nw_frag) { + memset(&wc->masks.nw_frag, 0xff, sizeof wc->masks.nw_frag); + } + + 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_ICMPV6) { + memset(&wc->masks.arp_sha, 0xff, sizeof wc->masks.arp_sha); + memset(&wc->masks.arp_tha, 0xff, sizeof wc->masks.arp_tha); + } + + return; +} + /* Converts the flow in 'flow' into an exact-match match in 'match'. */ void match_init_exact(struct match *match, const struct flow *flow) { + ovs_be64 tun_id = flow->tunnel.tun_id; + match->flow = *flow; match->flow.skb_priority = 0; + memset(&match->flow.tunnel, 0, sizeof match->flow.tunnel); + match->flow.tunnel.tun_id = tun_id; flow_wildcards_init_exact(&match->wc); } @@ -102,8 +188,8 @@ match_set_tun_id(struct match *match, ovs_be64 tun_id) void match_set_tun_id_masked(struct match *match, ovs_be64 tun_id, ovs_be64 mask) { - match->wc.masks.tun_id = mask; - match->flow.tun_id = tun_id & mask; + match->wc.masks.tunnel.tun_id = mask; + match->flow.tunnel.tun_id = tun_id & mask; } void @@ -626,15 +712,16 @@ match_format(const struct match *match, struct ds *s, unsigned int priority) break; } } - switch (wc->masks.tun_id) { + switch (wc->masks.tunnel.tun_id) { case 0: break; case CONSTANT_HTONLL(UINT64_MAX): - ds_put_format(s, "tun_id=%#"PRIx64",", ntohll(f->tun_id)); + ds_put_format(s, "tun_id=%#"PRIx64",", ntohll(f->tunnel.tun_id)); break; default: ds_put_format(s, "tun_id=%#"PRIx64"/%#"PRIx64",", - ntohll(f->tun_id), ntohll(wc->masks.tun_id)); + ntohll(f->tunnel.tun_id), + ntohll(wc->masks.tunnel.tun_id)); break; } switch (wc->masks.metadata) { @@ -693,6 +780,9 @@ match_format(const struct match *match, struct ds *s, unsigned int priority) ntohl(wc->masks.ipv6_label)); } } + } else if (f->dl_type == htons(ETH_TYPE_ARP)) { + format_ip_netmask(s, "arp_spa", f->nw_src, wc->masks.nw_src); + format_ip_netmask(s, "arp_tpa", f->nw_dst, wc->masks.nw_dst); } else { format_ip_netmask(s, "nw_src", f->nw_src, wc->masks.nw_src); format_ip_netmask(s, "nw_dst", f->nw_dst, wc->masks.nw_dst); @@ -735,10 +825,12 @@ match_format(const struct match *match, struct ds *s, unsigned int priority) f->nw_frag & FLOW_NW_FRAG_LATER ? "later" : "not_later"); break; } - if (f->nw_proto == IPPROTO_ICMP) { + if (f->dl_type == htons(ETH_TYPE_IP) && + f->nw_proto == IPPROTO_ICMP) { format_be16_masked(s, "icmp_type", f->tp_src, wc->masks.tp_src); format_be16_masked(s, "icmp_code", f->tp_dst, wc->masks.tp_dst); - } else if (f->nw_proto == IPPROTO_ICMPV6) { + } else if (f->dl_type == htons(ETH_TYPE_IPV6) && + f->nw_proto == IPPROTO_ICMPV6) { format_be16_masked(s, "icmp_type", f->tp_src, wc->masks.tp_src); format_be16_masked(s, "icmp_code", f->tp_dst, wc->masks.tp_dst); format_ipv6_netmask(s, "nd_target", &f->nd_target,