summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorPravin B Shelar <pshelar@ovn.org>2016-03-24 09:30:57 -0700
committerPravin B Shelar <pshelar@ovn.org>2016-03-24 09:30:57 -0700
commitb23ddcc57d419849219c3a5aedc25f39d3818ad7 (patch)
tree5b338af3da5e9ad30a80137d08a700db0e1ef8c0 /lib
parenta8704b502785a9661721f041b2ee168d7a4eb460 (diff)
downloadopenvswitch-b23ddcc57d419849219c3a5aedc25f39d3818ad7.tar.gz
tnl-neigh-cache: tighten arp and nd snooping.
Currently arp and nd snooping is pretty loose. That causes unnecessary entries in neighbour cache. Following patch adds required checks. Thanks Cascardo for detailed comment msg. CC: Thadeu Lima de Souza Cascardo <cascardo@redhat.com> Signed-off-by: Pravin B Shelar <pshelar@ovn.org> Acked-by: Thadeu Lima de Souza Cascardo <cascardo@redhat.com>
Diffstat (limited to 'lib')
-rw-r--r--lib/tnl-neigh-cache.c13
1 files changed, 12 insertions, 1 deletions
diff --git a/lib/tnl-neigh-cache.c b/lib/tnl-neigh-cache.c
index a62402c57..8650e73e7 100644
--- a/lib/tnl-neigh-cache.c
+++ b/lib/tnl-neigh-cache.c
@@ -147,7 +147,9 @@ 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)) {
+ if (flow->dl_type != htons(ETH_TYPE_ARP) ||
+ flow->nw_proto != ARP_OP_REPLY ||
+ eth_addr_is_zero(flow->arp_sha)) {
return EINVAL;
}
@@ -170,6 +172,15 @@ tnl_nd_snoop(const struct flow *flow, struct flow_wildcards *wc,
flow->tp_src != htons(ND_NEIGHBOR_ADVERT)) {
return EINVAL;
}
+ /* - RFC4861 says Neighbor Advertisements sent in response to unicast Neighbor
+ * Solicitations SHOULD include the Target link-layer address. However, Linux
+ * doesn't. So, the response to Solicitations sent by OVS will include the
+ * 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)) {
+ return EINVAL;
+ }
memset(&wc->masks.ipv6_src, 0xff, sizeof wc->masks.ipv6_src);
memset(&wc->masks.ipv6_dst, 0xff, sizeof wc->masks.ipv6_dst);