diff options
author | Stefano Brivio <sbrivio@redhat.com> | 2018-11-08 06:19:18 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2018-11-08 20:13:08 -0500 |
commit | a07966447f39fe43e37d05c9bfc92b1493267a59 (patch) | |
tree | 1d0f40f7fdb052d82a7ae556148c7b0e0ea6f30d | |
parent | 582888792f7bc2d543d85cb610160e2162d5f132 (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.c | 52 |
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 */ | ||
391 | static 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 | |||
390 | static struct socket *geneve_create_sock(struct net *net, bool ipv6, | 441 | static 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); |