Skip to content

Commit

Permalink
tnl-neigh-cache: Unwildcard flow members before inspecting them.
Browse files Browse the repository at this point in the history
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 <diproiettod@vmware.com>
Acked-by: Jarno Rajahalme <jarno@ovn.org>
  • Loading branch information
ddiproietto committed Sep 22, 2016
1 parent ee86750 commit 76a88e7
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 14 deletions.
7 changes: 7 additions & 0 deletions lib/flow.h
Expand Up @@ -854,6 +854,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_vlan(const struct flow *flow,
struct flow_wildcards *wc)
{
Expand Down
22 changes: 8 additions & 14 deletions lib/tnl-neigh-cache.c
Expand Up @@ -115,7 +115,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);
Expand Down Expand Up @@ -151,26 +151,21 @@ static int
tnl_arp_snoop(const struct flow *flow, struct flow_wildcards *wc,
const char name[IFNAMSIZ])
{
if (flow->dl_type != htons(ETH_TYPE_ARP) ||
flow->nw_proto != ARP_OP_REPLY ||
eth_addr_is_zero(flow->arp_sha)) {
if (flow->dl_type != htons(ETH_TYPE_ARP)
|| FLOW_WC_GET_AND_MASK_WC(flow, wc, nw_proto) != ARP_OP_REPLY
|| eth_addr_is_zero(FLOW_WC_GET_AND_MASK_WC(flow, wc, arp_sha))) {
return EINVAL;
}

/* Exact Match on all ARP flows. */
memset(&wc->masks.nw_proto, 0xff, sizeof wc->masks.nw_proto);
memset(&wc->masks.nw_src, 0xff, sizeof wc->masks.nw_src);
memset(&wc->masks.arp_sha, 0xff, sizeof wc->masks.arp_sha);

tnl_arp_set(name, flow->nw_src, flow->arp_sha);
tnl_arp_set(name, FLOW_WC_GET_AND_MASK_WC(flow, wc, nw_src), flow->arp_sha);
return 0;
}

static int
tnl_nd_snoop(const struct flow *flow, struct flow_wildcards *wc,
const char name[IFNAMSIZ])
const char name[IFNAMSIZ])
{
if (!is_nd(flow, NULL) || flow->tp_src != htons(ND_NEIGHBOR_ADVERT)) {
if (!is_nd(flow, wc) || flow->tp_src != htons(ND_NEIGHBOR_ADVERT)) {
return EINVAL;
}
/* - RFC4861 says Neighbor Advertisements sent in response to unicast Neighbor
Expand All @@ -179,14 +174,13 @@ tnl_nd_snoop(const struct flow *flow, struct flow_wildcards *wc,
* TLL address and other Advertisements not including it can be ignored.
* - OVS flow extract can set this field to zero in case of packet parsing errors.
* For details refer miniflow_extract()*/
if (eth_addr_is_zero(flow->arp_tha)) {
if (eth_addr_is_zero(FLOW_WC_GET_AND_MASK_WC(flow, wc, arp_tha))) {
return EINVAL;
}

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.nd_target, 0xff, sizeof wc->masks.nd_target);
memset(&wc->masks.arp_tha, 0xff, sizeof wc->masks.arp_tha);

tnl_neigh_set__(name, &flow->nd_target, flow->arp_tha);
return 0;
Expand Down

0 comments on commit 76a88e7

Please sign in to comment.