summaryrefslogtreecommitdiffstats
path: root/drivers/net/geneve.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2016-10-30 12:42:58 -0400
committerDavid S. Miller <davem@davemloft.net>2016-10-30 12:42:58 -0400
commit27058af401e49d88a905df000dd26f443fcfa8ce (patch)
tree819f32113d3b8374b9fbf72e2202d4c4d4511a60 /drivers/net/geneve.c
parent357f4aae859b5d74554b0ccbb18556f1df4166c3 (diff)
parent2a26d99b251b8625d27aed14e97fc10707a3a81f (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Mostly simple overlapping changes. For example, David Ahern's adjacency list revamp in 'net-next' conflicted with an adjacency list traversal bug fix in 'net'. Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/geneve.c')
-rw-r--r--drivers/net/geneve.c47
1 files changed, 35 insertions, 12 deletions
diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c
index 752bcaa852e4..85a423a66478 100644
--- a/drivers/net/geneve.c
+++ b/drivers/net/geneve.c
@@ -58,9 +58,9 @@ struct geneve_dev {
58 struct hlist_node hlist; /* vni hash table */ 58 struct hlist_node hlist; /* vni hash table */
59 struct net *net; /* netns for packet i/o */ 59 struct net *net; /* netns for packet i/o */
60 struct net_device *dev; /* netdev for geneve tunnel */ 60 struct net_device *dev; /* netdev for geneve tunnel */
61 struct geneve_sock *sock4; /* IPv4 socket used for geneve tunnel */ 61 struct geneve_sock __rcu *sock4; /* IPv4 socket used for geneve tunnel */
62#if IS_ENABLED(CONFIG_IPV6) 62#if IS_ENABLED(CONFIG_IPV6)
63 struct geneve_sock *sock6; /* IPv6 socket used for geneve tunnel */ 63 struct geneve_sock __rcu *sock6; /* IPv6 socket used for geneve tunnel */
64#endif 64#endif
65 u8 vni[3]; /* virtual network ID for tunnel */ 65 u8 vni[3]; /* virtual network ID for tunnel */
66 u8 ttl; /* TTL override */ 66 u8 ttl; /* TTL override */
@@ -453,7 +453,7 @@ static struct sk_buff **geneve_gro_receive(struct sock *sk,
453 453
454 skb_gro_pull(skb, gh_len); 454 skb_gro_pull(skb, gh_len);
455 skb_gro_postpull_rcsum(skb, gh, gh_len); 455 skb_gro_postpull_rcsum(skb, gh, gh_len);
456 pp = ptype->callbacks.gro_receive(head, skb); 456 pp = call_gro_receive(ptype->callbacks.gro_receive, head, skb);
457 flush = 0; 457 flush = 0;
458 458
459out_unlock: 459out_unlock:
@@ -543,9 +543,19 @@ static void __geneve_sock_release(struct geneve_sock *gs)
543 543
544static void geneve_sock_release(struct geneve_dev *geneve) 544static void geneve_sock_release(struct geneve_dev *geneve)
545{ 545{
546 __geneve_sock_release(geneve->sock4); 546 struct geneve_sock *gs4 = rtnl_dereference(geneve->sock4);
547#if IS_ENABLED(CONFIG_IPV6) 547#if IS_ENABLED(CONFIG_IPV6)
548 __geneve_sock_release(geneve->sock6); 548 struct geneve_sock *gs6 = rtnl_dereference(geneve->sock6);
549
550 rcu_assign_pointer(geneve->sock6, NULL);
551#endif
552
553 rcu_assign_pointer(geneve->sock4, NULL);
554 synchronize_net();
555
556 __geneve_sock_release(gs4);
557#if IS_ENABLED(CONFIG_IPV6)
558 __geneve_sock_release(gs6);
549#endif 559#endif
550} 560}
551 561
@@ -586,10 +596,10 @@ out:
586 gs->flags = geneve->flags; 596 gs->flags = geneve->flags;
587#if IS_ENABLED(CONFIG_IPV6) 597#if IS_ENABLED(CONFIG_IPV6)
588 if (ipv6) 598 if (ipv6)
589 geneve->sock6 = gs; 599 rcu_assign_pointer(geneve->sock6, gs);
590 else 600 else
591#endif 601#endif
592 geneve->sock4 = gs; 602 rcu_assign_pointer(geneve->sock4, gs);
593 603
594 hash = geneve_net_vni_hash(geneve->vni); 604 hash = geneve_net_vni_hash(geneve->vni);
595 hlist_add_head_rcu(&geneve->hlist, &gs->vni_list[hash]); 605 hlist_add_head_rcu(&geneve->hlist, &gs->vni_list[hash]);
@@ -603,9 +613,7 @@ static int geneve_open(struct net_device *dev)
603 bool metadata = geneve->collect_md; 613 bool metadata = geneve->collect_md;
604 int ret = 0; 614 int ret = 0;
605 615
606 geneve->sock4 = NULL;
607#if IS_ENABLED(CONFIG_IPV6) 616#if IS_ENABLED(CONFIG_IPV6)
608 geneve->sock6 = NULL;
609 if (ipv6 || metadata) 617 if (ipv6 || metadata)
610 ret = geneve_sock_add(geneve, true); 618 ret = geneve_sock_add(geneve, true);
611#endif 619#endif
@@ -720,6 +728,9 @@ static struct rtable *geneve_get_v4_rt(struct sk_buff *skb,
720 struct rtable *rt = NULL; 728 struct rtable *rt = NULL;
721 __u8 tos; 729 __u8 tos;
722 730
731 if (!rcu_dereference(geneve->sock4))
732 return ERR_PTR(-EIO);
733
723 memset(fl4, 0, sizeof(*fl4)); 734 memset(fl4, 0, sizeof(*fl4));
724 fl4->flowi4_mark = skb->mark; 735 fl4->flowi4_mark = skb->mark;
725 fl4->flowi4_proto = IPPROTO_UDP; 736 fl4->flowi4_proto = IPPROTO_UDP;
@@ -772,11 +783,15 @@ static struct dst_entry *geneve_get_v6_dst(struct sk_buff *skb,
772{ 783{
773 bool use_cache = ip_tunnel_dst_cache_usable(skb, info); 784 bool use_cache = ip_tunnel_dst_cache_usable(skb, info);
774 struct geneve_dev *geneve = netdev_priv(dev); 785 struct geneve_dev *geneve = netdev_priv(dev);
775 struct geneve_sock *gs6 = geneve->sock6;
776 struct dst_entry *dst = NULL; 786 struct dst_entry *dst = NULL;
777 struct dst_cache *dst_cache; 787 struct dst_cache *dst_cache;
788 struct geneve_sock *gs6;
778 __u8 prio; 789 __u8 prio;
779 790
791 gs6 = rcu_dereference(geneve->sock6);
792 if (!gs6)
793 return ERR_PTR(-EIO);
794
780 memset(fl6, 0, sizeof(*fl6)); 795 memset(fl6, 0, sizeof(*fl6));
781 fl6->flowi6_mark = skb->mark; 796 fl6->flowi6_mark = skb->mark;
782 fl6->flowi6_proto = IPPROTO_UDP; 797 fl6->flowi6_proto = IPPROTO_UDP;
@@ -842,7 +857,7 @@ static netdev_tx_t geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev,
842 struct ip_tunnel_info *info) 857 struct ip_tunnel_info *info)
843{ 858{
844 struct geneve_dev *geneve = netdev_priv(dev); 859 struct geneve_dev *geneve = netdev_priv(dev);
845 struct geneve_sock *gs4 = geneve->sock4; 860 struct geneve_sock *gs4;
846 struct rtable *rt = NULL; 861 struct rtable *rt = NULL;
847 const struct iphdr *iip; /* interior IP header */ 862 const struct iphdr *iip; /* interior IP header */
848 int err = -EINVAL; 863 int err = -EINVAL;
@@ -853,6 +868,10 @@ static netdev_tx_t geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev,
853 bool xnet = !net_eq(geneve->net, dev_net(geneve->dev)); 868 bool xnet = !net_eq(geneve->net, dev_net(geneve->dev));
854 u32 flags = geneve->flags; 869 u32 flags = geneve->flags;
855 870
871 gs4 = rcu_dereference(geneve->sock4);
872 if (!gs4)
873 goto tx_error;
874
856 if (geneve->collect_md) { 875 if (geneve->collect_md) {
857 if (unlikely(!info || !(info->mode & IP_TUNNEL_INFO_TX))) { 876 if (unlikely(!info || !(info->mode & IP_TUNNEL_INFO_TX))) {
858 netdev_dbg(dev, "no tunnel metadata\n"); 877 netdev_dbg(dev, "no tunnel metadata\n");
@@ -932,9 +951,9 @@ static netdev_tx_t geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev,
932 struct ip_tunnel_info *info) 951 struct ip_tunnel_info *info)
933{ 952{
934 struct geneve_dev *geneve = netdev_priv(dev); 953 struct geneve_dev *geneve = netdev_priv(dev);
935 struct geneve_sock *gs6 = geneve->sock6;
936 struct dst_entry *dst = NULL; 954 struct dst_entry *dst = NULL;
937 const struct iphdr *iip; /* interior IP header */ 955 const struct iphdr *iip; /* interior IP header */
956 struct geneve_sock *gs6;
938 int err = -EINVAL; 957 int err = -EINVAL;
939 struct flowi6 fl6; 958 struct flowi6 fl6;
940 __u8 prio, ttl; 959 __u8 prio, ttl;
@@ -943,6 +962,10 @@ static netdev_tx_t geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev,
943 bool xnet = !net_eq(geneve->net, dev_net(geneve->dev)); 962 bool xnet = !net_eq(geneve->net, dev_net(geneve->dev));
944 u32 flags = geneve->flags; 963 u32 flags = geneve->flags;
945 964
965 gs6 = rcu_dereference(geneve->sock6);
966 if (!gs6)
967 goto tx_error;
968
946 if (geneve->collect_md) { 969 if (geneve->collect_md) {
947 if (unlikely(!info || !(info->mode & IP_TUNNEL_INFO_TX))) { 970 if (unlikely(!info || !(info->mode & IP_TUNNEL_INFO_TX))) {
948 netdev_dbg(dev, "no tunnel metadata\n"); 971 netdev_dbg(dev, "no tunnel metadata\n");