From db79d7ad2c219813461b474ac453917832151274 Mon Sep 17 00:00:00 2001 From: Daniele Di Proietto Date: Tue, 24 May 2016 17:13:29 -0700 Subject: [PATCH] tnl-neigh-cache: Unwildcard flow members before inspecting them. tnl_neigh_snoop() is part of the translation. During translation we have to unwildcard all the fields we examine to make a decision. tnl_arp_snoop() and tnl_nd_snoop() failed to unwildcard fileds in case of failure. The solution is to do unwildcarding before the field is inspected. Signed-off-by: Daniele Di Proietto Acked-by: Jarno Rajahalme --- lib/flow.h | 7 +++++++ lib/tnl-neigh-cache.c | 13 +++++++------ 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/lib/flow.h b/lib/flow.h index df17c92f793..cef00c81a15 100644 --- a/lib/flow.h +++ b/lib/flow.h @@ -998,6 +998,13 @@ pkt_metadata_from_flow(struct pkt_metadata *md, const struct flow *flow) md->ct_label = flow->ct_label; } +/* Often, during translation we need to read a value from a flow('FLOW') and + * unwildcard the corresponding bits in the wildcards('WC'). This macro makes + * it easier to do that. */ + +#define FLOW_WC_GET_AND_MASK_WC(FLOW, WC, FIELD) \ + (((WC) ? WC_MASK_FIELD(WC, FIELD) : NULL), ((FLOW)->FIELD)) + static inline bool is_ip_any(const struct flow *flow) { return dl_type_is_ip_any(flow->dl_type); diff --git a/lib/tnl-neigh-cache.c b/lib/tnl-neigh-cache.c index 0339b5233bb..b923b257cc9 100644 --- a/lib/tnl-neigh-cache.c +++ b/lib/tnl-neigh-cache.c @@ -111,7 +111,7 @@ tnl_neigh_delete(struct tnl_neigh_entry *neigh) static void tnl_neigh_set__(const char name[IFNAMSIZ], const struct in6_addr *dst, - const struct eth_addr mac) + const struct eth_addr mac) { ovs_mutex_lock(&mutex); struct tnl_neigh_entry *neigh = tnl_neigh_lookup__(name, dst); @@ -162,12 +162,13 @@ tnl_arp_snoop(const struct flow *flow, struct flow_wildcards *wc, static int tnl_nd_snoop(const struct flow *flow, struct flow_wildcards *wc, - const char name[IFNAMSIZ]) + const char name[IFNAMSIZ]) { - if (flow->dl_type != htons(ETH_TYPE_IPV6) || - flow->nw_proto != IPPROTO_ICMPV6 || - flow->tp_dst != htons(0) || - flow->tp_src != htons(ND_NEIGHBOR_ADVERT)) { + if (flow->dl_type != htons(ETH_TYPE_IPV6) + || FLOW_WC_GET_AND_MASK_WC(flow, wc, nw_proto) != IPPROTO_ICMPV6 + || FLOW_WC_GET_AND_MASK_WC(flow, wc, tp_dst) != htons(0) + || FLOW_WC_GET_AND_MASK_WC(flow, wc, tp_src) + != htons(ND_NEIGHBOR_ADVERT)) { return EINVAL; }