aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefano Brivio <sbrivio@redhat.com>2018-11-08 06:19:18 -0500
committerDavid S. Miller <davem@davemloft.net>2018-11-08 20:13:08 -0500
commita07966447f39fe43e37d05c9bfc92b1493267a59 (patch)
tree1d0f40f7fdb052d82a7ae556148c7b0e0ea6f30d
parent582888792f7bc2d543d85cb610160e2162d5f132 (diff)
geneve: ICMP error lookup handler
Export an encap_err_lookup() operation to match an ICMP error against a valid VNI. Signed-off-by: Stefano Brivio <sbrivio@redhat.com> Reviewed-by: Sabrina Dubroca <sd@queasysnail.net> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/geneve.c52
1 files changed, 52 insertions, 0 deletions
diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c
index fbfc13d81f66..4dc457489770 100644
--- a/drivers/net/geneve.c
+++ b/drivers/net/geneve.c
@@ -387,6 +387,57 @@ drop:
387 return 0; 387 return 0;
388} 388}
389 389
390/* Callback from net/ipv{4,6}/udp.c to check that we have a tunnel for errors */
391static int geneve_udp_encap_err_lookup(struct sock *sk, struct sk_buff *skb)
392{
393 struct genevehdr *geneveh;
394 struct geneve_sock *gs;
395 u8 zero_vni[3] = { 0 };
396 u8 *vni = zero_vni;
397
398 if (skb->len < GENEVE_BASE_HLEN)
399 return -EINVAL;
400
401 geneveh = geneve_hdr(skb);
402 if (geneveh->ver != GENEVE_VER)
403 return -EINVAL;
404
405 if (geneveh->proto_type != htons(ETH_P_TEB))
406 return -EINVAL;
407
408 gs = rcu_dereference_sk_user_data(sk);
409 if (!gs)
410 return -ENOENT;
411
412 if (geneve_get_sk_family(gs) == AF_INET) {
413 struct iphdr *iph = ip_hdr(skb);
414 __be32 addr4 = 0;
415
416 if (!gs->collect_md) {
417 vni = geneve_hdr(skb)->vni;
418 addr4 = iph->daddr;
419 }
420
421 return geneve_lookup(gs, addr4, vni) ? 0 : -ENOENT;
422 }
423
424#if IS_ENABLED(CONFIG_IPV6)
425 if (geneve_get_sk_family(gs) == AF_INET6) {
426 struct ipv6hdr *ip6h = ipv6_hdr(skb);
427 struct in6_addr addr6 = { 0 };
428
429 if (!gs->collect_md) {
430 vni = geneve_hdr(skb)->vni;
431 addr6 = ip6h->daddr;
432 }
433
434 return geneve6_lookup(gs, addr6, vni) ? 0 : -ENOENT;
435 }
436#endif
437
438 return -EPFNOSUPPORT;
439}
440
390static struct socket *geneve_create_sock(struct net *net, bool ipv6, 441static struct socket *geneve_create_sock(struct net *net, bool ipv6,
391 __be16 port, bool ipv6_rx_csum) 442 __be16 port, bool ipv6_rx_csum)
392{ 443{
@@ -544,6 +595,7 @@ static struct geneve_sock *geneve_socket_create(struct net *net, __be16 port,
544 tunnel_cfg.gro_receive = geneve_gro_receive; 595 tunnel_cfg.gro_receive = geneve_gro_receive;
545 tunnel_cfg.gro_complete = geneve_gro_complete; 596 tunnel_cfg.gro_complete = geneve_gro_complete;
546 tunnel_cfg.encap_rcv = geneve_udp_encap_recv; 597 tunnel_cfg.encap_rcv = geneve_udp_encap_recv;
598 tunnel_cfg.encap_err_lookup = geneve_udp_encap_err_lookup;
547 tunnel_cfg.encap_destroy = NULL; 599 tunnel_cfg.encap_destroy = NULL;
548 setup_udp_tunnel_sock(net, sock, &tunnel_cfg); 600 setup_udp_tunnel_sock(net, sock, &tunnel_cfg);
549 list_add(&gs->list, &gn->sock_list); 601 list_add(&gs->list, &gn->sock_list);