@@ -988,28 +988,33 @@ static bool vxlan_snoop(struct net_device *dev,
988
988
static bool vxlan_group_used (struct vxlan_net * vn , struct vxlan_dev * dev )
989
989
{
990
990
struct vxlan_dev * vxlan ;
991
+ struct vxlan_sock * sock4 ;
992
+ struct vxlan_sock * sock6 = NULL ;
991
993
unsigned short family = dev -> default_dst .remote_ip .sa .sa_family ;
992
994
995
+ sock4 = rtnl_dereference (dev -> vn4_sock );
996
+
993
997
/* The vxlan_sock is only used by dev, leaving group has
994
998
* no effect on other vxlan devices.
995
999
*/
996
- if (family == AF_INET && dev -> vn4_sock &&
997
- atomic_read (& dev -> vn4_sock -> refcnt ) == 1 )
1000
+ if (family == AF_INET && sock4 && atomic_read (& sock4 -> refcnt ) == 1 )
998
1001
return false;
999
1002
#if IS_ENABLED (CONFIG_IPV6 )
1000
- if ( family == AF_INET6 && dev -> vn6_sock &&
1001
- atomic_read (& dev -> vn6_sock -> refcnt ) == 1 )
1003
+ sock6 = rtnl_dereference ( dev -> vn6_sock );
1004
+ if ( family == AF_INET6 && sock6 && atomic_read (& sock6 -> refcnt ) == 1 )
1002
1005
return false;
1003
1006
#endif
1004
1007
1005
1008
list_for_each_entry (vxlan , & vn -> vxlan_list , next ) {
1006
1009
if (!netif_running (vxlan -> dev ) || vxlan == dev )
1007
1010
continue ;
1008
1011
1009
- if (family == AF_INET && vxlan -> vn4_sock != dev -> vn4_sock )
1012
+ if (family == AF_INET &&
1013
+ rtnl_dereference (vxlan -> vn4_sock ) != sock4 )
1010
1014
continue ;
1011
1015
#if IS_ENABLED (CONFIG_IPV6 )
1012
- if (family == AF_INET6 && vxlan -> vn6_sock != dev -> vn6_sock )
1016
+ if (family == AF_INET6 &&
1017
+ rtnl_dereference (vxlan -> vn6_sock ) != sock6 )
1013
1018
continue ;
1014
1019
#endif
1015
1020
@@ -1047,24 +1052,27 @@ static bool __vxlan_sock_release_prep(struct vxlan_sock *vs)
1047
1052
1048
1053
static void vxlan_sock_release (struct vxlan_dev * vxlan )
1049
1054
{
1050
- bool ipv4 = __vxlan_sock_release_prep (vxlan -> vn4_sock );
1055
+ struct vxlan_sock * sock4 = rtnl_dereference (vxlan -> vn4_sock );
1051
1056
#if IS_ENABLED (CONFIG_IPV6 )
1052
- bool ipv6 = __vxlan_sock_release_prep (vxlan -> vn6_sock );
1057
+ struct vxlan_sock * sock6 = rtnl_dereference (vxlan -> vn6_sock );
1058
+
1059
+ rcu_assign_pointer (vxlan -> vn6_sock , NULL );
1053
1060
#endif
1054
1061
1062
+ rcu_assign_pointer (vxlan -> vn4_sock , NULL );
1055
1063
synchronize_net ();
1056
1064
1057
1065
vxlan_vs_del_dev (vxlan );
1058
1066
1059
- if (ipv4 ) {
1060
- udp_tunnel_sock_release (vxlan -> vn4_sock -> sock );
1061
- kfree (vxlan -> vn4_sock );
1067
+ if (__vxlan_sock_release_prep ( sock4 ) ) {
1068
+ udp_tunnel_sock_release (sock4 -> sock );
1069
+ kfree (sock4 );
1062
1070
}
1063
1071
1064
1072
#if IS_ENABLED (CONFIG_IPV6 )
1065
- if (ipv6 ) {
1066
- udp_tunnel_sock_release (vxlan -> vn6_sock -> sock );
1067
- kfree (vxlan -> vn6_sock );
1073
+ if (__vxlan_sock_release_prep ( sock6 ) ) {
1074
+ udp_tunnel_sock_release (sock6 -> sock );
1075
+ kfree (sock6 );
1068
1076
}
1069
1077
#endif
1070
1078
}
@@ -1080,18 +1088,21 @@ static int vxlan_igmp_join(struct vxlan_dev *vxlan)
1080
1088
int ret = - EINVAL ;
1081
1089
1082
1090
if (ip -> sa .sa_family == AF_INET ) {
1091
+ struct vxlan_sock * sock4 = rtnl_dereference (vxlan -> vn4_sock );
1083
1092
struct ip_mreqn mreq = {
1084
1093
.imr_multiaddr .s_addr = ip -> sin .sin_addr .s_addr ,
1085
1094
.imr_ifindex = ifindex ,
1086
1095
};
1087
1096
1088
- sk = vxlan -> vn4_sock -> sock -> sk ;
1097
+ sk = sock4 -> sock -> sk ;
1089
1098
lock_sock (sk );
1090
1099
ret = ip_mc_join_group (sk , & mreq );
1091
1100
release_sock (sk );
1092
1101
#if IS_ENABLED (CONFIG_IPV6 )
1093
1102
} else {
1094
- sk = vxlan -> vn6_sock -> sock -> sk ;
1103
+ struct vxlan_sock * sock6 = rtnl_dereference (vxlan -> vn6_sock );
1104
+
1105
+ sk = sock6 -> sock -> sk ;
1095
1106
lock_sock (sk );
1096
1107
ret = ipv6_stub -> ipv6_sock_mc_join (sk , ifindex ,
1097
1108
& ip -> sin6 .sin6_addr );
@@ -1111,18 +1122,21 @@ static int vxlan_igmp_leave(struct vxlan_dev *vxlan)
1111
1122
int ret = - EINVAL ;
1112
1123
1113
1124
if (ip -> sa .sa_family == AF_INET ) {
1125
+ struct vxlan_sock * sock4 = rtnl_dereference (vxlan -> vn4_sock );
1114
1126
struct ip_mreqn mreq = {
1115
1127
.imr_multiaddr .s_addr = ip -> sin .sin_addr .s_addr ,
1116
1128
.imr_ifindex = ifindex ,
1117
1129
};
1118
1130
1119
- sk = vxlan -> vn4_sock -> sock -> sk ;
1131
+ sk = sock4 -> sock -> sk ;
1120
1132
lock_sock (sk );
1121
1133
ret = ip_mc_leave_group (sk , & mreq );
1122
1134
release_sock (sk );
1123
1135
#if IS_ENABLED (CONFIG_IPV6 )
1124
1136
} else {
1125
- sk = vxlan -> vn6_sock -> sock -> sk ;
1137
+ struct vxlan_sock * sock6 = rtnl_dereference (vxlan -> vn6_sock );
1138
+
1139
+ sk = sock6 -> sock -> sk ;
1126
1140
lock_sock (sk );
1127
1141
ret = ipv6_stub -> ipv6_sock_mc_drop (sk , ifindex ,
1128
1142
& ip -> sin6 .sin6_addr );
@@ -1934,9 +1948,11 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
1934
1948
vxlan -> cfg .port_max , true);
1935
1949
1936
1950
if (dst -> sa .sa_family == AF_INET ) {
1937
- if (!vxlan -> vn4_sock )
1951
+ struct vxlan_sock * sock4 = rcu_dereference (vxlan -> vn4_sock );
1952
+
1953
+ if (!sock4 )
1938
1954
goto drop ;
1939
- sk = vxlan -> vn4_sock -> sock -> sk ;
1955
+ sk = sock4 -> sock -> sk ;
1940
1956
memset (& fl4 , 0 , sizeof (fl4 ));
1941
1957
fl4 .flowi4_oif = rdst -> remote_ifindex ;
1942
1958
fl4 .flowi4_tos = RT_TOS (tos );
@@ -1990,13 +2006,14 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
1990
2006
iptunnel_xmit_stats (err , & dev -> stats , dev -> tstats );
1991
2007
#if IS_ENABLED (CONFIG_IPV6 )
1992
2008
} else {
2009
+ struct vxlan_sock * sock6 = rcu_dereference (vxlan -> vn6_sock );
1993
2010
struct dst_entry * ndst ;
1994
2011
struct flowi6 fl6 ;
1995
2012
u32 flags ;
1996
2013
1997
- if (!vxlan -> vn6_sock )
2014
+ if (!sock6 )
1998
2015
goto drop ;
1999
- sk = vxlan -> vn6_sock -> sock -> sk ;
2016
+ sk = sock6 -> sock -> sk ;
2000
2017
2001
2018
memset (& fl6 , 0 , sizeof (fl6 ));
2002
2019
fl6 .flowi6_oif = rdst -> remote_ifindex ;
@@ -2587,10 +2604,10 @@ static int __vxlan_sock_add(struct vxlan_dev *vxlan, bool ipv6)
2587
2604
return PTR_ERR (vs );
2588
2605
#if IS_ENABLED (CONFIG_IPV6 )
2589
2606
if (ipv6 )
2590
- vxlan -> vn6_sock = vs ;
2607
+ rcu_assign_pointer ( vxlan -> vn6_sock , vs ) ;
2591
2608
else
2592
2609
#endif
2593
- vxlan -> vn4_sock = vs ;
2610
+ rcu_assign_pointer ( vxlan -> vn4_sock , vs ) ;
2594
2611
vxlan_vs_add_dev (vs , vxlan );
2595
2612
return 0 ;
2596
2613
}
@@ -2601,9 +2618,9 @@ static int vxlan_sock_add(struct vxlan_dev *vxlan)
2601
2618
bool metadata = vxlan -> flags & VXLAN_F_COLLECT_METADATA ;
2602
2619
int ret = 0 ;
2603
2620
2604
- vxlan -> vn4_sock = NULL ;
2621
+ RCU_INIT_POINTER ( vxlan -> vn4_sock , NULL ) ;
2605
2622
#if IS_ENABLED (CONFIG_IPV6 )
2606
- vxlan -> vn6_sock = NULL ;
2623
+ RCU_INIT_POINTER ( vxlan -> vn6_sock , NULL ) ;
2607
2624
if (ipv6 || metadata )
2608
2625
ret = __vxlan_sock_add (vxlan , true);
2609
2626
#endif
0 commit comments