X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=lib%2Fmatch.c;h=71d86beaefdcde3e3f51eec11523add0038a5ff8;hb=ac60863f78e412004c5b69f5a64a49bc6f0bc46d;hp=02583fd69ba13a6ee12879dabc82a853ed0e830d;hpb=b0a17866c3145fd35e844e1b66c499c55ecf6f1d;p=sliver-openvswitch.git diff --git a/lib/match.c b/lib/match.c index 02583fd69..71d86beae 100644 --- a/lib/match.c +++ b/lib/match.c @@ -21,10 +21,6 @@ #include "dynamic-string.h" #include "ofp-util.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'. */ @@ -114,6 +110,10 @@ match_wc_init(struct match *match, const struct flow *flow) 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 || @@ -122,6 +122,9 @@ match_wc_init(struct match *match, const struct flow *flow) 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); @@ -132,15 +135,6 @@ match_wc_init(struct match *match, const struct flow *flow) return; } -/* Converts the flow in 'flow' into an exact-match match in 'match'. */ -void -match_init_exact(struct match *match, const struct flow *flow) -{ - match->flow = *flow; - match->flow.skb_priority = 0; - flow_wildcards_init_exact(&match->wc); -} - /* Initializes 'match' as a "catch-all" match that matches every packet. */ void match_init_catchall(struct match *match) @@ -541,6 +535,19 @@ match_set_tp_dst_masked(struct match *match, ovs_be16 port, ovs_be16 mask) match->wc.masks.tp_dst = mask; } +void +match_set_tcp_flags(struct match *match, ovs_be16 flags) +{ + match_set_tcp_flags_masked(match, flags, OVS_BE16_MAX); +} + +void +match_set_tcp_flags_masked(struct match *match, ovs_be16 flags, ovs_be16 mask) +{ + match->flow.tcp_flags = flags & mask; + match->wc.masks.tcp_flags = mask; +} + void match_set_nw_proto(struct match *match, uint8_t nw_proto) { @@ -835,7 +842,7 @@ match_format(const struct match *match, struct ds *s, unsigned int priority) int i; - BUILD_ASSERT_DECL(FLOW_WC_SEQ == 21); + BUILD_ASSERT_DECL(FLOW_WC_SEQ == 23); if (priority != OFP_DEFAULT_PRIORITY) { ds_put_format(s, "priority=%u,", priority); @@ -1061,6 +1068,14 @@ match_format(const struct match *match, struct ds *s, unsigned int priority) format_be16_masked(s, "tp_src", f->tp_src, wc->masks.tp_src); format_be16_masked(s, "tp_dst", f->tp_dst, wc->masks.tp_dst); } + if (is_ip_any(f) && f->nw_proto == IPPROTO_TCP && wc->masks.tcp_flags) { + if (wc->masks.tcp_flags == htons(UINT16_MAX)) { + ds_put_format(s, "tcp_flags=0x%03"PRIx16",", ntohs(f->tcp_flags)); + } else { + ds_put_format(s, "tcp_flags=0x%03"PRIx16"/0x%03"PRIx16",", + ntohs(f->tcp_flags), ntohs(wc->masks.tcp_flags)); + } + } if (s->length > start_len && ds_last(s) == ',') { s->length--; @@ -1158,22 +1173,42 @@ minimatch_matches_flow(const struct minimatch *match, const uint32_t *target_u32 = (const uint32_t *) target; const uint32_t *flowp = match->flow.values; const uint32_t *maskp = match->mask.masks.values; - int i; - - for (i = 0; i < MINI_N_MAPS; i++) { - uint32_t map; + uint64_t map; - for (map = match->flow.map[i]; map; map = zero_rightmost_1bit(map)) { - if ((*flowp++ ^ target_u32[raw_ctz(map)]) & *maskp++) { - return false; - } + for (map = match->flow.map; map; map = zero_rightmost_1bit(map)) { + if ((*flowp++ ^ target_u32[raw_ctz(map)]) & *maskp++) { + return false; } - target_u32 += 32; } return true; } +/* Returns a hash value for the bits of range [start, end) in 'minimatch', + * given 'basis'. + * + * The hash values returned by this function are the same as those returned by + * flow_hash_in_minimask_range(), only the form of the arguments differ. */ +uint32_t +minimatch_hash_range(const struct minimatch *match, uint8_t start, uint8_t end, + uint32_t *basis) +{ + const uint32_t *p; + uint64_t map = miniflow_get_map_in_range(&match->mask.masks, start, end, + &p); + const ptrdiff_t df = match->mask.masks.values - match->flow.values; + uint32_t hash = *basis; + + for (; map; map = zero_rightmost_1bit(map)) { + if (*p) { + hash = mhash_add(hash, *(p - df) & *p); + } + p++; + } + *basis = hash; /* Allow continuation from the unfinished value. */ + return mhash_finish(hash, (p - match->mask.masks.values) * 4); +} + /* Appends a string representation of 'match' to 's'. If 'priority' is * different from OFP_DEFAULT_PRIORITY, includes it in 's'. */ void