X-Git-Url: http://git.cascardo.eti.br/?a=blobdiff_plain;f=lib%2Fmatch.c;h=9e465d89277ad160d3e74a3fc106aa4646fa636e;hb=74ff3298c8806bb09d0c7e40a25b889ab7564769;hp=85e3683544fb6c4751925514886872c8c1242705;hpb=ac6073e3cda5764664f1a32b827c9721c8e10bbd;p=cascardo%2Fovs.git diff --git a/lib/match.c b/lib/match.c index 85e368354..9e465d892 100644 --- a/lib/match.c +++ b/lib/match.c @@ -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 @@ -44,6 +46,8 @@ match_wc_init(struct match *match, const struct flow *flow) flow_wildcards_init_for_packet(&match->wc, flow); WC_MASK_FIELD(&match->wc, regs); WC_MASK_FIELD(&match->wc, metadata); + + memset(&match->tun_md, 0, sizeof match->tun_md); } /* Initializes 'match' as a "catch-all" match that matches every packet. */ @@ -52,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 @@ -220,6 +225,8 @@ match_set_tun_flags(struct match *match, uint16_t flags) void match_set_tun_flags_masked(struct match *match, uint16_t flags, uint16_t mask) { + mask &= FLOW_TNL_PUB_F_MASK; + match->wc.masks.tunnel.flags = mask; match->flow.tunnel.flags = flags & mask; } @@ -287,55 +294,54 @@ match_set_dl_type(struct match *match, ovs_be16 dl_type) /* Modifies 'value_src' so that the Ethernet address must match 'value_dst' * exactly. 'mask_dst' is set to all 1s. */ static void -set_eth(const uint8_t value_src[ETH_ADDR_LEN], - uint8_t value_dst[ETH_ADDR_LEN], - uint8_t mask_dst[ETH_ADDR_LEN]) +set_eth(const struct eth_addr value_src, + struct eth_addr *value_dst, + struct eth_addr *mask_dst) { - memcpy(value_dst, value_src, ETH_ADDR_LEN); - memset(mask_dst, 0xff, ETH_ADDR_LEN); + *value_dst = value_src; + *mask_dst = eth_addr_exact; } /* Modifies 'value_src' so that the Ethernet address must match 'value_src' * after each byte is ANDed with the appropriate byte in 'mask_src'. * 'mask_dst' is set to 'mask_src' */ static void -set_eth_masked(const uint8_t value_src[ETH_ADDR_LEN], - const uint8_t mask_src[ETH_ADDR_LEN], - uint8_t value_dst[ETH_ADDR_LEN], - uint8_t mask_dst[ETH_ADDR_LEN]) +set_eth_masked(const struct eth_addr value_src, + const struct eth_addr mask_src, + struct eth_addr *value_dst, struct eth_addr *mask_dst) { size_t i; - for (i = 0; i < ETH_ADDR_LEN; i++) { - value_dst[i] = value_src[i] & mask_src[i]; - mask_dst[i] = mask_src[i]; + for (i = 0; i < ARRAY_SIZE(value_dst->be16); i++) { + value_dst->be16[i] = value_src.be16[i] & mask_src.be16[i]; } + *mask_dst = mask_src; } /* Modifies 'rule' so that the source Ethernet address must match 'dl_src' * exactly. */ void -match_set_dl_src(struct match *match, const uint8_t dl_src[ETH_ADDR_LEN]) +match_set_dl_src(struct match *match, const struct eth_addr dl_src) { - set_eth(dl_src, match->flow.dl_src, match->wc.masks.dl_src); + set_eth(dl_src, &match->flow.dl_src, &match->wc.masks.dl_src); } /* Modifies 'rule' so that the source Ethernet address must match 'dl_src' * after each byte is ANDed with the appropriate byte in 'mask'. */ void match_set_dl_src_masked(struct match *match, - const uint8_t dl_src[ETH_ADDR_LEN], - const uint8_t mask[ETH_ADDR_LEN]) + const struct eth_addr dl_src, + const struct eth_addr mask) { - set_eth_masked(dl_src, mask, match->flow.dl_src, match->wc.masks.dl_src); + set_eth_masked(dl_src, mask, &match->flow.dl_src, &match->wc.masks.dl_src); } /* Modifies 'match' so that the Ethernet address must match 'dl_dst' * exactly. */ void -match_set_dl_dst(struct match *match, const uint8_t dl_dst[ETH_ADDR_LEN]) +match_set_dl_dst(struct match *match, const struct eth_addr dl_dst) { - set_eth(dl_dst, match->flow.dl_dst, match->wc.masks.dl_dst); + set_eth(dl_dst, &match->flow.dl_dst, &match->wc.masks.dl_dst); } /* Modifies 'match' so that the Ethernet address must match 'dl_dst' after each @@ -345,10 +351,10 @@ match_set_dl_dst(struct match *match, const uint8_t dl_dst[ETH_ADDR_LEN]) * accepted by flow_wildcards_is_dl_dst_mask_valid() are allowed. */ void match_set_dl_dst_masked(struct match *match, - const uint8_t dl_dst[ETH_ADDR_LEN], - const uint8_t mask[ETH_ADDR_LEN]) + const struct eth_addr dl_dst, + const struct eth_addr mask) { - set_eth_masked(dl_dst, mask, match->flow.dl_dst, match->wc.masks.dl_dst); + set_eth_masked(dl_dst, mask, &match->flow.dl_dst, &match->wc.masks.dl_dst); } void @@ -637,35 +643,35 @@ match_set_icmp_code(struct match *match, uint8_t icmp_code) } void -match_set_arp_sha(struct match *match, const uint8_t sha[ETH_ADDR_LEN]) +match_set_arp_sha(struct match *match, const struct eth_addr sha) { - memcpy(match->flow.arp_sha, sha, ETH_ADDR_LEN); - memset(match->wc.masks.arp_sha, UINT8_MAX, ETH_ADDR_LEN); + match->flow.arp_sha = sha; + match->wc.masks.arp_sha = eth_addr_exact; } void match_set_arp_sha_masked(struct match *match, - const uint8_t arp_sha[ETH_ADDR_LEN], - const uint8_t mask[ETH_ADDR_LEN]) + const struct eth_addr arp_sha, + const struct eth_addr mask) { set_eth_masked(arp_sha, mask, - match->flow.arp_sha, match->wc.masks.arp_sha); + &match->flow.arp_sha, &match->wc.masks.arp_sha); } void -match_set_arp_tha(struct match *match, const uint8_t tha[ETH_ADDR_LEN]) +match_set_arp_tha(struct match *match, const struct eth_addr tha) { - memcpy(match->flow.arp_tha, tha, ETH_ADDR_LEN); - memset(match->wc.masks.arp_tha, UINT8_MAX, ETH_ADDR_LEN); + match->flow.arp_tha = tha; + match->wc.masks.arp_tha = eth_addr_exact; } void match_set_arp_tha_masked(struct match *match, - const uint8_t arp_tha[ETH_ADDR_LEN], - const uint8_t mask[ETH_ADDR_LEN]) + const struct eth_addr arp_tha, + const struct eth_addr mask) { set_eth_masked(arp_tha, mask, - match->flow.arp_tha, match->wc.masks.arp_tha); + &match->flow.arp_tha, &match->wc.masks.arp_tha); } void @@ -777,12 +783,11 @@ match_init_hidden_fields(struct match *m) static void format_eth_masked(struct ds *s, const char *name, - const uint8_t eth[ETH_ADDR_LEN], - const uint8_t mask[ETH_ADDR_LEN]) + const struct eth_addr eth, const struct eth_addr mask) { if (!eth_addr_is_zero(mask)) { ds_put_format(s, "%s=", name); - eth_format_masked(eth, mask, s); + eth_format_masked(eth, &mask, s); ds_put_char(s, ','); } } @@ -894,9 +899,13 @@ format_flow_tunnel(struct ds *s, const struct match *match) ds_put_format(s, "tun_ttl=%"PRIu8",", tnl->ip_ttl); } if (wc->masks.tunnel.flags) { - format_flags(s, flow_tun_flag_to_string, tnl->flags, '|'); + format_flags_masked(s, "tun_flags", flow_tun_flag_to_string, + tnl->flags, + wc->masks.tunnel.flags & FLOW_TNL_F_MASK, + FLOW_TNL_F_MASK); ds_put_char(s, ','); } + tun_metadata_match_format(s, match); } /* Appends a string representation of 'match' to 's'. If 'priority' is @@ -912,7 +921,7 @@ match_format(const struct match *match, struct ds *s, int priority) int i; - BUILD_ASSERT_DECL(FLOW_WC_SEQ == 31); + BUILD_ASSERT_DECL(FLOW_WC_SEQ == 33); if (priority != OFP_DEFAULT_PRIORITY) { ds_put_format(s, "priority=%d,", priority); @@ -925,7 +934,7 @@ match_format(const struct match *match, struct ds *s, 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); } @@ -1144,20 +1153,9 @@ match_format(const struct match *match, struct ds *s, int priority) 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) { - uint16_t mask = TCP_FLAGS(wc->masks.tcp_flags); - - if (mask == TCP_FLAGS(OVS_BE16_MAX)) { - 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); - } + format_flags_masked(s, "tcp_flags", packet_tcp_flag_to_string, + ntohs(f->tcp_flags), TCP_FLAGS(wc->masks.tcp_flags), + TCP_FLAGS(OVS_BE16_MAX)); } if (s->length > start_len) { @@ -1189,8 +1187,13 @@ match_print(const struct match *match) void minimatch_init(struct minimatch *dst, const struct match *src) { - minimask_init(&dst->mask, &src->wc); - miniflow_init_with_minimask(&dst->flow, &src->flow, &dst->mask); + struct miniflow tmp; + + miniflow_map_init(&tmp, &src->wc.masks); + /* Allocate two consecutive miniflows. */ + miniflow_alloc(dst->flows, 2, &tmp); + miniflow_init(dst->flow, &src->flow); + minimask_init(dst->mask, &src->wc); } /* Initializes 'dst' as a copy of 'src'. The caller must eventually free 'dst' @@ -1198,8 +1201,13 @@ minimatch_init(struct minimatch *dst, const struct match *src) void minimatch_clone(struct minimatch *dst, const struct minimatch *src) { - miniflow_clone(&dst->flow, &src->flow); - minimask_clone(&dst->mask, &src->mask); + /* Allocate two consecutive miniflows. */ + size_t data_size = miniflow_alloc(dst->flows, 2, &src->mask->masks); + + memcpy(miniflow_values(dst->flow), + miniflow_get_values(src->flow), data_size); + memcpy(miniflow_values(&dst->mask->masks), + miniflow_get_values(&src->mask->masks), data_size); } /* Initializes 'dst' with the data in 'src', destroying 'src'. The caller must @@ -1207,8 +1215,8 @@ minimatch_clone(struct minimatch *dst, const struct minimatch *src) void minimatch_move(struct minimatch *dst, struct minimatch *src) { - miniflow_move(&dst->flow, &src->flow); - minimask_move(&dst->mask, &src->mask); + dst->flow = src->flow; + dst->mask = src->mask; } /* Frees any memory owned by 'match'. Does not free the storage in which @@ -1216,24 +1224,24 @@ minimatch_move(struct minimatch *dst, struct minimatch *src) void minimatch_destroy(struct minimatch *match) { - miniflow_destroy(&match->flow); - minimask_destroy(&match->mask); + free(match->flow); } /* Initializes 'dst' as a copy of 'src'. */ void minimatch_expand(const struct minimatch *src, struct match *dst) { - miniflow_expand(&src->flow, &dst->flow); - minimask_expand(&src->mask, &dst->wc); + 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. */ bool minimatch_equal(const struct minimatch *a, const struct minimatch *b) { - return (miniflow_equal(&a->flow, &b->flow) - && minimask_equal(&a->mask, &b->mask)); + return minimask_equal(a->mask, b->mask) + && miniflow_equal(a->flow, b->flow); } /* Returns true if 'target' satisifies 'match', that is, if each bit for which @@ -1246,13 +1254,12 @@ bool minimatch_matches_flow(const struct minimatch *match, const struct flow *target) { - 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; + const uint64_t *flowp = miniflow_get_values(match->flow); + const uint64_t *maskp = miniflow_get_values(&match->mask->masks); + size_t idx; - MAP_FOR_EACH_INDEX(idx, match->flow.map) { - if ((*flowp++ ^ target_u64[idx]) & *maskp++) { + FLOWMAP_FOR_EACH_INDEX(idx, match->flow->map) { + if ((*flowp++ ^ flow_u64_value(target, idx)) & *maskp++) { return false; } }