aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/vxlan.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/vxlan.c')
-rw-r--r--drivers/net/vxlan.c59
1 files changed, 41 insertions, 18 deletions
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index a5ba8dd7e6be..767f7af3bd40 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -136,7 +136,8 @@ struct vxlan_dev {
136 u32 flags; /* VXLAN_F_* below */ 136 u32 flags; /* VXLAN_F_* below */
137 137
138 struct work_struct sock_work; 138 struct work_struct sock_work;
139 struct work_struct igmp_work; 139 struct work_struct igmp_join;
140 struct work_struct igmp_leave;
140 141
141 unsigned long age_interval; 142 unsigned long age_interval;
142 struct timer_list age_timer; 143 struct timer_list age_timer;
@@ -736,7 +737,6 @@ static bool vxlan_snoop(struct net_device *dev,
736 return false; 737 return false;
737} 738}
738 739
739
740/* See if multicast group is already in use by other ID */ 740/* See if multicast group is already in use by other ID */
741static bool vxlan_group_used(struct vxlan_net *vn, __be32 remote_ip) 741static bool vxlan_group_used(struct vxlan_net *vn, __be32 remote_ip)
742{ 742{
@@ -770,12 +770,13 @@ static void vxlan_sock_release(struct vxlan_net *vn, struct vxlan_sock *vs)
770 queue_work(vxlan_wq, &vs->del_work); 770 queue_work(vxlan_wq, &vs->del_work);
771} 771}
772 772
773/* Callback to update multicast group membership. 773/* Callback to update multicast group membership when first VNI on
774 * Scheduled when vxlan goes up/down. 774 * multicast asddress is brought up
775 * Done as workqueue because ip_mc_join_group acquires RTNL.
775 */ 776 */
776static void vxlan_igmp_work(struct work_struct *work) 777static void vxlan_igmp_join(struct work_struct *work)
777{ 778{
778 struct vxlan_dev *vxlan = container_of(work, struct vxlan_dev, igmp_work); 779 struct vxlan_dev *vxlan = container_of(work, struct vxlan_dev, igmp_join);
779 struct vxlan_net *vn = net_generic(dev_net(vxlan->dev), vxlan_net_id); 780 struct vxlan_net *vn = net_generic(dev_net(vxlan->dev), vxlan_net_id);
780 struct vxlan_sock *vs = vxlan->vn_sock; 781 struct vxlan_sock *vs = vxlan->vn_sock;
781 struct sock *sk = vs->sock->sk; 782 struct sock *sk = vs->sock->sk;
@@ -785,10 +786,27 @@ static void vxlan_igmp_work(struct work_struct *work)
785 }; 786 };
786 787
787 lock_sock(sk); 788 lock_sock(sk);
788 if (vxlan_group_used(vn, vxlan->default_dst.remote_ip)) 789 ip_mc_join_group(sk, &mreq);
789 ip_mc_join_group(sk, &mreq); 790 release_sock(sk);
790 else 791
791 ip_mc_leave_group(sk, &mreq); 792 vxlan_sock_release(vn, vs);
793 dev_put(vxlan->dev);
794}
795
796/* Inverse of vxlan_igmp_join when last VNI is brought down */
797static void vxlan_igmp_leave(struct work_struct *work)
798{
799 struct vxlan_dev *vxlan = container_of(work, struct vxlan_dev, igmp_leave);
800 struct vxlan_net *vn = net_generic(dev_net(vxlan->dev), vxlan_net_id);
801 struct vxlan_sock *vs = vxlan->vn_sock;
802 struct sock *sk = vs->sock->sk;
803 struct ip_mreqn mreq = {
804 .imr_multiaddr.s_addr = vxlan->default_dst.remote_ip,
805 .imr_ifindex = vxlan->default_dst.remote_ifindex,
806 };
807
808 lock_sock(sk);
809 ip_mc_leave_group(sk, &mreq);
792 release_sock(sk); 810 release_sock(sk);
793 811
794 vxlan_sock_release(vn, vs); 812 vxlan_sock_release(vn, vs);
@@ -1359,6 +1377,7 @@ static void vxlan_uninit(struct net_device *dev)
1359/* Start ageing timer and join group when device is brought up */ 1377/* Start ageing timer and join group when device is brought up */
1360static int vxlan_open(struct net_device *dev) 1378static int vxlan_open(struct net_device *dev)
1361{ 1379{
1380 struct vxlan_net *vn = net_generic(dev_net(dev), vxlan_net_id);
1362 struct vxlan_dev *vxlan = netdev_priv(dev); 1381 struct vxlan_dev *vxlan = netdev_priv(dev);
1363 struct vxlan_sock *vs = vxlan->vn_sock; 1382 struct vxlan_sock *vs = vxlan->vn_sock;
1364 1383
@@ -1366,10 +1385,11 @@ static int vxlan_open(struct net_device *dev)
1366 if (!vs) 1385 if (!vs)
1367 return -ENOTCONN; 1386 return -ENOTCONN;
1368 1387
1369 if (IN_MULTICAST(ntohl(vxlan->default_dst.remote_ip))) { 1388 if (IN_MULTICAST(ntohl(vxlan->default_dst.remote_ip)) &&
1389 vxlan_group_used(vn, vxlan->default_dst.remote_ip)) {
1370 vxlan_sock_hold(vs); 1390 vxlan_sock_hold(vs);
1371 dev_hold(dev); 1391 dev_hold(dev);
1372 queue_work(vxlan_wq, &vxlan->igmp_work); 1392 queue_work(vxlan_wq, &vxlan->igmp_join);
1373 } 1393 }
1374 1394
1375 if (vxlan->age_interval) 1395 if (vxlan->age_interval)
@@ -1400,13 +1420,15 @@ static void vxlan_flush(struct vxlan_dev *vxlan)
1400/* Cleanup timer and forwarding table on shutdown */ 1420/* Cleanup timer and forwarding table on shutdown */
1401static int vxlan_stop(struct net_device *dev) 1421static int vxlan_stop(struct net_device *dev)
1402{ 1422{
1423 struct vxlan_net *vn = net_generic(dev_net(dev), vxlan_net_id);
1403 struct vxlan_dev *vxlan = netdev_priv(dev); 1424 struct vxlan_dev *vxlan = netdev_priv(dev);
1404 struct vxlan_sock *vs = vxlan->vn_sock; 1425 struct vxlan_sock *vs = vxlan->vn_sock;
1405 1426
1406 if (vs && IN_MULTICAST(ntohl(vxlan->default_dst.remote_ip))) { 1427 if (vs && IN_MULTICAST(ntohl(vxlan->default_dst.remote_ip)) &&
1428 ! vxlan_group_used(vn, vxlan->default_dst.remote_ip)) {
1407 vxlan_sock_hold(vs); 1429 vxlan_sock_hold(vs);
1408 dev_hold(dev); 1430 dev_hold(dev);
1409 queue_work(vxlan_wq, &vxlan->igmp_work); 1431 queue_work(vxlan_wq, &vxlan->igmp_leave);
1410 } 1432 }
1411 1433
1412 del_timer_sync(&vxlan->age_timer); 1434 del_timer_sync(&vxlan->age_timer);
@@ -1471,7 +1493,8 @@ static void vxlan_setup(struct net_device *dev)
1471 1493
1472 INIT_LIST_HEAD(&vxlan->next); 1494 INIT_LIST_HEAD(&vxlan->next);
1473 spin_lock_init(&vxlan->hash_lock); 1495 spin_lock_init(&vxlan->hash_lock);
1474 INIT_WORK(&vxlan->igmp_work, vxlan_igmp_work); 1496 INIT_WORK(&vxlan->igmp_join, vxlan_igmp_join);
1497 INIT_WORK(&vxlan->igmp_leave, vxlan_igmp_leave);
1475 INIT_WORK(&vxlan->sock_work, vxlan_sock_work); 1498 INIT_WORK(&vxlan->sock_work, vxlan_sock_work);
1476 1499
1477 init_timer_deferrable(&vxlan->age_timer); 1500 init_timer_deferrable(&vxlan->age_timer);
@@ -1770,8 +1793,6 @@ static void vxlan_dellink(struct net_device *dev, struct list_head *head)
1770 struct vxlan_net *vn = net_generic(dev_net(dev), vxlan_net_id); 1793 struct vxlan_net *vn = net_generic(dev_net(dev), vxlan_net_id);
1771 struct vxlan_dev *vxlan = netdev_priv(dev); 1794 struct vxlan_dev *vxlan = netdev_priv(dev);
1772 1795
1773 flush_workqueue(vxlan_wq);
1774
1775 spin_lock(&vn->sock_lock); 1796 spin_lock(&vn->sock_lock);
1776 hlist_del_rcu(&vxlan->hlist); 1797 hlist_del_rcu(&vxlan->hlist);
1777 spin_unlock(&vn->sock_lock); 1798 spin_unlock(&vn->sock_lock);
@@ -1878,10 +1899,12 @@ static __net_exit void vxlan_exit_net(struct net *net)
1878{ 1899{
1879 struct vxlan_net *vn = net_generic(net, vxlan_net_id); 1900 struct vxlan_net *vn = net_generic(net, vxlan_net_id);
1880 struct vxlan_dev *vxlan; 1901 struct vxlan_dev *vxlan;
1902 LIST_HEAD(list);
1881 1903
1882 rtnl_lock(); 1904 rtnl_lock();
1883 list_for_each_entry(vxlan, &vn->vxlan_list, next) 1905 list_for_each_entry(vxlan, &vn->vxlan_list, next)
1884 dev_close(vxlan->dev); 1906 unregister_netdevice_queue(vxlan->dev, &list);
1907 unregister_netdevice_many(&list);
1885 rtnl_unlock(); 1908 rtnl_unlock();
1886} 1909}
1887 1910