@@ -58,9 +58,9 @@ struct geneve_dev {
5858 struct hlist_node hlist ; /* vni hash table */
5959 struct net * net ; /* netns for packet i/o */
6060 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 */
6262#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 */
6464#endif
6565 u8 vni [3 ]; /* virtual network ID for tunnel */
6666 u8 ttl ; /* TTL override */
@@ -543,9 +543,19 @@ static void __geneve_sock_release(struct geneve_sock *gs)
543543
544544static void geneve_sock_release (struct geneve_dev * geneve )
545545{
546- __geneve_sock_release (geneve -> sock4 );
546+ struct geneve_sock * gs4 = rtnl_dereference (geneve -> sock4 );
547547#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 );
549559#endif
550560}
551561
@@ -586,10 +596,10 @@ static int geneve_sock_add(struct geneve_dev *geneve, bool ipv6)
586596 gs -> flags = geneve -> flags ;
587597#if IS_ENABLED (CONFIG_IPV6 )
588598 if (ipv6 )
589- geneve -> sock6 = gs ;
599+ rcu_assign_pointer ( geneve -> sock6 , gs ) ;
590600 else
591601#endif
592- geneve -> sock4 = gs ;
602+ rcu_assign_pointer ( geneve -> sock4 , gs ) ;
593603
594604 hash = geneve_net_vni_hash (geneve -> vni );
595605 hlist_add_head_rcu (& geneve -> hlist , & gs -> vni_list [hash ]);
@@ -603,9 +613,7 @@ static int geneve_open(struct net_device *dev)
603613 bool metadata = geneve -> collect_md ;
604614 int ret = 0 ;
605615
606- geneve -> sock4 = NULL ;
607616#if IS_ENABLED (CONFIG_IPV6 )
608- geneve -> sock6 = NULL ;
609617 if (ipv6 || metadata )
610618 ret = geneve_sock_add (geneve , true);
611619#endif
@@ -720,6 +728,9 @@ static struct rtable *geneve_get_v4_rt(struct sk_buff *skb,
720728 struct rtable * rt = NULL ;
721729 __u8 tos ;
722730
731+ if (!rcu_dereference (geneve -> sock4 ))
732+ return ERR_PTR (- EIO );
733+
723734 memset (fl4 , 0 , sizeof (* fl4 ));
724735 fl4 -> flowi4_mark = skb -> mark ;
725736 fl4 -> flowi4_proto = IPPROTO_UDP ;
@@ -772,11 +783,15 @@ static struct dst_entry *geneve_get_v6_dst(struct sk_buff *skb,
772783{
773784 bool use_cache = ip_tunnel_dst_cache_usable (skb , info );
774785 struct geneve_dev * geneve = netdev_priv (dev );
775- struct geneve_sock * gs6 = geneve -> sock6 ;
776786 struct dst_entry * dst = NULL ;
777787 struct dst_cache * dst_cache ;
788+ struct geneve_sock * gs6 ;
778789 __u8 prio ;
779790
791+ gs6 = rcu_dereference (geneve -> sock6 );
792+ if (!gs6 )
793+ return ERR_PTR (- EIO );
794+
780795 memset (fl6 , 0 , sizeof (* fl6 ));
781796 fl6 -> flowi6_mark = skb -> mark ;
782797 fl6 -> flowi6_proto = IPPROTO_UDP ;
@@ -842,7 +857,7 @@ static netdev_tx_t geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev,
842857 struct ip_tunnel_info * info )
843858{
844859 struct geneve_dev * geneve = netdev_priv (dev );
845- struct geneve_sock * gs4 = geneve -> sock4 ;
860+ struct geneve_sock * gs4 ;
846861 struct rtable * rt = NULL ;
847862 const struct iphdr * iip ; /* interior IP header */
848863 int err = - EINVAL ;
@@ -853,6 +868,10 @@ static netdev_tx_t geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev,
853868 bool xnet = !net_eq (geneve -> net , dev_net (geneve -> dev ));
854869 u32 flags = geneve -> flags ;
855870
871+ gs4 = rcu_dereference (geneve -> sock4 );
872+ if (!gs4 )
873+ goto tx_error ;
874+
856875 if (geneve -> collect_md ) {
857876 if (unlikely (!info || !(info -> mode & IP_TUNNEL_INFO_TX ))) {
858877 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,
932951 struct ip_tunnel_info * info )
933952{
934953 struct geneve_dev * geneve = netdev_priv (dev );
935- struct geneve_sock * gs6 = geneve -> sock6 ;
936954 struct dst_entry * dst = NULL ;
937955 const struct iphdr * iip ; /* interior IP header */
956+ struct geneve_sock * gs6 ;
938957 int err = - EINVAL ;
939958 struct flowi6 fl6 ;
940959 __u8 prio , ttl ;
@@ -943,6 +962,10 @@ static netdev_tx_t geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev,
943962 bool xnet = !net_eq (geneve -> net , dev_net (geneve -> dev ));
944963 u32 flags = geneve -> flags ;
945964
965+ gs6 = rcu_dereference (geneve -> sock6 );
966+ if (!gs6 )
967+ goto tx_error ;
968+
946969 if (geneve -> collect_md ) {
947970 if (unlikely (!info || !(info -> mode & IP_TUNNEL_INFO_TX ))) {
948971 netdev_dbg (dev , "no tunnel metadata\n" );
0 commit comments