@@ -58,9 +58,9 @@ struct geneve_dev {
58
58
struct hlist_node hlist ; /* vni hash table */
59
59
struct net * net ; /* netns for packet i/o */
60
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
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
64
#endif
65
65
u8 vni [3 ]; /* virtual network ID for tunnel */
66
66
u8 ttl ; /* TTL override */
@@ -543,9 +543,19 @@ static void __geneve_sock_release(struct geneve_sock *gs)
543
543
544
544
static 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
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
559
#endif
550
560
}
551
561
@@ -586,10 +596,10 @@ static int geneve_sock_add(struct geneve_dev *geneve, bool ipv6)
586
596
gs -> flags = geneve -> flags ;
587
597
#if IS_ENABLED (CONFIG_IPV6 )
588
598
if (ipv6 )
589
- geneve -> sock6 = gs ;
599
+ rcu_assign_pointer ( geneve -> sock6 , gs ) ;
590
600
else
591
601
#endif
592
- geneve -> sock4 = gs ;
602
+ rcu_assign_pointer ( geneve -> sock4 , gs ) ;
593
603
594
604
hash = geneve_net_vni_hash (geneve -> vni );
595
605
hlist_add_head_rcu (& geneve -> hlist , & gs -> vni_list [hash ]);
@@ -603,9 +613,7 @@ static int geneve_open(struct net_device *dev)
603
613
bool metadata = geneve -> collect_md ;
604
614
int ret = 0 ;
605
615
606
- geneve -> sock4 = NULL ;
607
616
#if IS_ENABLED (CONFIG_IPV6 )
608
- geneve -> sock6 = NULL ;
609
617
if (ipv6 || metadata )
610
618
ret = geneve_sock_add (geneve , true);
611
619
#endif
@@ -720,6 +728,9 @@ static struct rtable *geneve_get_v4_rt(struct sk_buff *skb,
720
728
struct rtable * rt = NULL ;
721
729
__u8 tos ;
722
730
731
+ if (!rcu_dereference (geneve -> sock4 ))
732
+ return ERR_PTR (- EIO );
733
+
723
734
memset (fl4 , 0 , sizeof (* fl4 ));
724
735
fl4 -> flowi4_mark = skb -> mark ;
725
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
784
bool use_cache = ip_tunnel_dst_cache_usable (skb , info );
774
785
struct geneve_dev * geneve = netdev_priv (dev );
775
- struct geneve_sock * gs6 = geneve -> sock6 ;
776
786
struct dst_entry * dst = NULL ;
777
787
struct dst_cache * dst_cache ;
788
+ struct geneve_sock * gs6 ;
778
789
__u8 prio ;
779
790
791
+ gs6 = rcu_dereference (geneve -> sock6 );
792
+ if (!gs6 )
793
+ return ERR_PTR (- EIO );
794
+
780
795
memset (fl6 , 0 , sizeof (* fl6 ));
781
796
fl6 -> flowi6_mark = skb -> mark ;
782
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
857
struct ip_tunnel_info * info )
843
858
{
844
859
struct geneve_dev * geneve = netdev_priv (dev );
845
- struct geneve_sock * gs4 = geneve -> sock4 ;
860
+ struct geneve_sock * gs4 ;
846
861
struct rtable * rt = NULL ;
847
862
const struct iphdr * iip ; /* interior IP header */
848
863
int err = - EINVAL ;
@@ -853,6 +868,10 @@ static netdev_tx_t geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev,
853
868
bool xnet = !net_eq (geneve -> net , dev_net (geneve -> dev ));
854
869
u32 flags = geneve -> flags ;
855
870
871
+ gs4 = rcu_dereference (geneve -> sock4 );
872
+ if (!gs4 )
873
+ goto tx_error ;
874
+
856
875
if (geneve -> collect_md ) {
857
876
if (unlikely (!info || !(info -> mode & IP_TUNNEL_INFO_TX ))) {
858
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
951
struct ip_tunnel_info * info )
933
952
{
934
953
struct geneve_dev * geneve = netdev_priv (dev );
935
- struct geneve_sock * gs6 = geneve -> sock6 ;
936
954
struct dst_entry * dst = NULL ;
937
955
const struct iphdr * iip ; /* interior IP header */
956
+ struct geneve_sock * gs6 ;
938
957
int err = - EINVAL ;
939
958
struct flowi6 fl6 ;
940
959
__u8 prio , ttl ;
@@ -943,6 +962,10 @@ static netdev_tx_t geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev,
943
962
bool xnet = !net_eq (geneve -> net , dev_net (geneve -> dev ));
944
963
u32 flags = geneve -> flags ;
945
964
965
+ gs6 = rcu_dereference (geneve -> sock6 );
966
+ if (!gs6 )
967
+ goto tx_error ;
968
+
946
969
if (geneve -> collect_md ) {
947
970
if (unlikely (!info || !(info -> mode & IP_TUNNEL_INFO_TX ))) {
948
971
netdev_dbg (dev , "no tunnel metadata\n" );
0 commit comments