@@ -85,7 +85,7 @@ struct vxlan_sock {
85
85
struct hlist_node hlist ;
86
86
struct rcu_head rcu ;
87
87
struct work_struct del_work ;
88
- unsigned int refcnt ;
88
+ atomic_t refcnt ;
89
89
struct socket * sock ;
90
90
struct hlist_head vni_list [VNI_HASH_SIZE ];
91
91
};
@@ -131,6 +131,7 @@ struct vxlan_dev {
131
131
__u8 ttl ;
132
132
u32 flags ; /* VXLAN_F_* below */
133
133
134
+ struct work_struct igmp_work ;
134
135
unsigned long age_interval ;
135
136
struct timer_list age_timer ;
136
137
spinlock_t hash_lock ;
@@ -648,76 +649,58 @@ static bool vxlan_snoop(struct net_device *dev,
648
649
649
650
650
651
/* See if multicast group is already in use by other ID */
651
- static bool vxlan_group_used (struct vxlan_net * vn ,
652
- const struct vxlan_dev * this )
652
+ static bool vxlan_group_used (struct vxlan_net * vn , __be32 remote_ip )
653
653
{
654
654
struct vxlan_dev * vxlan ;
655
655
656
656
list_for_each_entry (vxlan , & vn -> vxlan_list , next ) {
657
- if (vxlan == this )
658
- continue ;
659
-
660
657
if (!netif_running (vxlan -> dev ))
661
658
continue ;
662
659
663
- if (vxlan -> default_dst .remote_ip == this -> default_dst . remote_ip )
660
+ if (vxlan -> default_dst .remote_ip == remote_ip )
664
661
return true;
665
662
}
666
663
667
664
return false;
668
665
}
669
666
670
- /* kernel equivalent to IP_ADD_MEMBERSHIP */
671
- static int vxlan_join_group (struct net_device * dev )
667
+ static void vxlan_sock_hold (struct vxlan_sock * vs )
672
668
{
673
- struct vxlan_dev * vxlan = netdev_priv (dev );
674
- struct vxlan_net * vn = net_generic (dev_net (dev ), vxlan_net_id );
675
- struct sock * sk = vxlan -> vn_sock -> sock -> sk ;
676
- struct ip_mreqn mreq = {
677
- .imr_multiaddr .s_addr = vxlan -> default_dst .remote_ip ,
678
- .imr_ifindex = vxlan -> default_dst .remote_ifindex ,
679
- };
680
- int err ;
681
-
682
- /* Already a member of group */
683
- if (vxlan_group_used (vn , vxlan ))
684
- return 0 ;
669
+ atomic_inc (& vs -> refcnt );
670
+ }
685
671
686
- /* Need to drop RTNL to call multicast join */
687
- rtnl_unlock ();
688
- lock_sock (sk );
689
- err = ip_mc_join_group (sk , & mreq );
690
- release_sock (sk );
691
- rtnl_lock ();
672
+ static void vxlan_sock_release (struct vxlan_sock * vs )
673
+ {
674
+ if (!atomic_dec_and_test (& vs -> refcnt ))
675
+ return ;
692
676
693
- return err ;
677
+ hlist_del_rcu (& vs -> hlist );
678
+ queue_work (vxlan_wq , & vs -> del_work );
694
679
}
695
680
696
-
697
- /* kernel equivalent to IP_DROP_MEMBERSHIP */
698
- static int vxlan_leave_group (struct net_device * dev )
681
+ /* Callback to update multicast group membership.
682
+ * Scheduled when vxlan goes up/down.
683
+ */
684
+ static void vxlan_igmp_work (struct work_struct * work )
699
685
{
700
- struct vxlan_dev * vxlan = netdev_priv ( dev );
701
- struct vxlan_net * vn = net_generic (dev_net (dev ), vxlan_net_id );
702
- int err = 0 ;
703
- struct sock * sk = vxlan -> vn_sock -> sock -> sk ;
686
+ struct vxlan_dev * vxlan = container_of ( work , struct vxlan_dev , igmp_work );
687
+ struct vxlan_net * vn = net_generic (dev_net (vxlan -> dev ), vxlan_net_id );
688
+ struct vxlan_sock * vs = vxlan -> vn_sock ;
689
+ struct sock * sk = vs -> sock -> sk ;
704
690
struct ip_mreqn mreq = {
705
691
.imr_multiaddr .s_addr = vxlan -> default_dst .remote_ip ,
706
692
.imr_ifindex = vxlan -> default_dst .remote_ifindex ,
707
693
};
708
694
709
- /* Only leave group when last vxlan is done. */
710
- if (vxlan_group_used (vn , vxlan ))
711
- return 0 ;
712
-
713
- /* Need to drop RTNL to call multicast leave */
714
- rtnl_unlock ();
715
695
lock_sock (sk );
716
- err = ip_mc_leave_group (sk , & mreq );
696
+ if (vxlan_group_used (vn , vxlan -> default_dst .remote_ip ))
697
+ ip_mc_join_group (sk , & mreq );
698
+ else
699
+ ip_mc_leave_group (sk , & mreq );
717
700
release_sock (sk );
718
- rtnl_lock ();
719
701
720
- return err ;
702
+ vxlan_sock_release (vs );
703
+ dev_put (vxlan -> dev );
721
704
}
722
705
723
706
/* Callback from net/ipv4/udp.c to receive packets */
@@ -1249,12 +1232,11 @@ static int vxlan_init(struct net_device *dev)
1249
1232
static int vxlan_open (struct net_device * dev )
1250
1233
{
1251
1234
struct vxlan_dev * vxlan = netdev_priv (dev );
1252
- int err ;
1253
1235
1254
1236
if (IN_MULTICAST (ntohl (vxlan -> default_dst .remote_ip ))) {
1255
- err = vxlan_join_group ( dev );
1256
- if ( err )
1257
- return err ;
1237
+ vxlan_sock_hold ( vxlan -> vn_sock );
1238
+ dev_hold ( dev );
1239
+ queue_work ( vxlan_wq , & vxlan -> igmp_work ) ;
1258
1240
}
1259
1241
1260
1242
if (vxlan -> age_interval )
@@ -1285,8 +1267,11 @@ static int vxlan_stop(struct net_device *dev)
1285
1267
{
1286
1268
struct vxlan_dev * vxlan = netdev_priv (dev );
1287
1269
1288
- if (IN_MULTICAST (ntohl (vxlan -> default_dst .remote_ip )))
1289
- vxlan_leave_group (dev );
1270
+ if (IN_MULTICAST (ntohl (vxlan -> default_dst .remote_ip ))) {
1271
+ vxlan_sock_hold (vxlan -> vn_sock );
1272
+ dev_hold (dev );
1273
+ queue_work (vxlan_wq , & vxlan -> igmp_work );
1274
+ }
1290
1275
1291
1276
del_timer_sync (& vxlan -> age_timer );
1292
1277
@@ -1355,6 +1340,7 @@ static void vxlan_setup(struct net_device *dev)
1355
1340
1356
1341
INIT_LIST_HEAD (& vxlan -> next );
1357
1342
spin_lock_init (& vxlan -> hash_lock );
1343
+ INIT_WORK (& vxlan -> igmp_work , vxlan_igmp_work );
1358
1344
1359
1345
init_timer_deferrable (& vxlan -> age_timer );
1360
1346
vxlan -> age_timer .function = vxlan_cleanup ;
@@ -1498,8 +1484,8 @@ static struct vxlan_sock *vxlan_socket_create(struct net *net, __be16 port)
1498
1484
udp_sk (sk )-> encap_type = 1 ;
1499
1485
udp_sk (sk )-> encap_rcv = vxlan_udp_encap_recv ;
1500
1486
udp_encap_enable ();
1487
+ atomic_set (& vs -> refcnt , 1 );
1501
1488
1502
- vs -> refcnt = 1 ;
1503
1489
return vs ;
1504
1490
}
1505
1491
@@ -1589,7 +1575,7 @@ static int vxlan_newlink(struct net *net, struct net_device *dev,
1589
1575
1590
1576
vs = vxlan_find_port (net , vxlan -> dst_port );
1591
1577
if (vs )
1592
- ++ vs -> refcnt ;
1578
+ atomic_inc ( & vs -> refcnt ) ;
1593
1579
else {
1594
1580
/* Drop lock because socket create acquires RTNL lock */
1595
1581
rtnl_unlock ();
@@ -1606,12 +1592,7 @@ static int vxlan_newlink(struct net *net, struct net_device *dev,
1606
1592
1607
1593
err = register_netdevice (dev );
1608
1594
if (err ) {
1609
- if (-- vs -> refcnt == 0 ) {
1610
- rtnl_unlock ();
1611
- sk_release_kernel (vs -> sock -> sk );
1612
- kfree (vs );
1613
- rtnl_lock ();
1614
- }
1595
+ vxlan_sock_release (vs );
1615
1596
return err ;
1616
1597
}
1617
1598
@@ -1629,11 +1610,7 @@ static void vxlan_dellink(struct net_device *dev, struct list_head *head)
1629
1610
hlist_del_rcu (& vxlan -> hlist );
1630
1611
list_del (& vxlan -> next );
1631
1612
unregister_netdevice_queue (dev , head );
1632
-
1633
- if (-- vs -> refcnt == 0 ) {
1634
- hlist_del_rcu (& vs -> hlist );
1635
- queue_work (vxlan_wq , & vs -> del_work );
1636
- }
1613
+ vxlan_sock_release (vs );
1637
1614
}
1638
1615
1639
1616
static size_t vxlan_get_size (const struct net_device * dev )
0 commit comments