aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/vxlan.c
diff options
context:
space:
mode:
authorPravin B Shelar <pshelar@nicira.com>2013-08-19 14:22:48 -0400
committerDavid S. Miller <davem@davemloft.net>2013-08-20 03:15:43 -0400
commit9c2e24e16fbccf6cc1102442acc4a629f79615a7 (patch)
tree7965520c9933a05a47901d31ddc99db42a7bbd65 /drivers/net/vxlan.c
parent7559fb2fc547b3507ba462c6558e291fb21b9cee (diff)
vxlan: Restructure vxlan socket apis.
Restructure vxlan-socket management APIs so that it can be shared between vxlan and ovs modules. This patch does not change any functionality. Signed-off-by: Pravin B Shelar <pshelar@nicira.com> v6-v7: - get rid of zero refcnt vs from hashtable. Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/vxlan.c')
-rw-r--r--drivers/net/vxlan.c92
1 files changed, 51 insertions, 41 deletions
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index 570ad7aa7204..b784ee668a4e 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -188,7 +188,7 @@ static inline struct vxlan_rdst *first_remote_rtnl(struct vxlan_fdb *fdb)
188} 188}
189 189
190/* Find VXLAN socket based on network namespace and UDP port */ 190/* Find VXLAN socket based on network namespace and UDP port */
191static struct vxlan_sock *vxlan_find_port(struct net *net, __be16 port) 191static struct vxlan_sock *vxlan_find_sock(struct net *net, __be16 port)
192{ 192{
193 struct vxlan_sock *vs; 193 struct vxlan_sock *vs;
194 194
@@ -205,7 +205,7 @@ static struct vxlan_dev *vxlan_find_vni(struct net *net, u32 id, __be16 port)
205 struct vxlan_sock *vs; 205 struct vxlan_sock *vs;
206 struct vxlan_dev *vxlan; 206 struct vxlan_dev *vxlan;
207 207
208 vs = vxlan_find_port(net, port); 208 vs = vxlan_find_sock(net, port);
209 if (!vs) 209 if (!vs)
210 return NULL; 210 return NULL;
211 211
@@ -1365,25 +1365,31 @@ static void vxlan_cleanup(unsigned long arg)
1365 mod_timer(&vxlan->age_timer, next_timer); 1365 mod_timer(&vxlan->age_timer, next_timer);
1366} 1366}
1367 1367
1368static void vxlan_vs_add_dev(struct vxlan_sock *vs, struct vxlan_dev *vxlan)
1369{
1370 __u32 vni = vxlan->default_dst.remote_vni;
1371
1372 vxlan->vn_sock = vs;
1373 hlist_add_head_rcu(&vxlan->hlist, vni_head(vs, vni));
1374}
1375
1368/* Setup stats when device is created */ 1376/* Setup stats when device is created */
1369static int vxlan_init(struct net_device *dev) 1377static int vxlan_init(struct net_device *dev)
1370{ 1378{
1371 struct vxlan_dev *vxlan = netdev_priv(dev); 1379 struct vxlan_dev *vxlan = netdev_priv(dev);
1372 struct vxlan_net *vn = net_generic(dev_net(dev), vxlan_net_id); 1380 struct vxlan_net *vn = net_generic(dev_net(dev), vxlan_net_id);
1373 struct vxlan_sock *vs; 1381 struct vxlan_sock *vs;
1374 __u32 vni = vxlan->default_dst.remote_vni;
1375 1382
1376 dev->tstats = alloc_percpu(struct pcpu_tstats); 1383 dev->tstats = alloc_percpu(struct pcpu_tstats);
1377 if (!dev->tstats) 1384 if (!dev->tstats)
1378 return -ENOMEM; 1385 return -ENOMEM;
1379 1386
1380 spin_lock(&vn->sock_lock); 1387 spin_lock(&vn->sock_lock);
1381 vs = vxlan_find_port(dev_net(dev), vxlan->dst_port); 1388 vs = vxlan_find_sock(dev_net(dev), vxlan->dst_port);
1382 if (vs) { 1389 if (vs) {
1383 /* If we have a socket with same port already, reuse it */ 1390 /* If we have a socket with same port already, reuse it */
1384 atomic_inc(&vs->refcnt); 1391 atomic_inc(&vs->refcnt);
1385 vxlan->vn_sock = vs; 1392 vxlan_vs_add_dev(vs, vxlan);
1386 hlist_add_head_rcu(&vxlan->hlist, vni_head(vs, vni));
1387 } else { 1393 } else {
1388 /* otherwise make new socket outside of RTNL */ 1394 /* otherwise make new socket outside of RTNL */
1389 dev_hold(dev); 1395 dev_hold(dev);
@@ -1633,6 +1639,7 @@ static void vxlan_del_work(struct work_struct *work)
1633 1639
1634static struct vxlan_sock *vxlan_socket_create(struct net *net, __be16 port) 1640static struct vxlan_sock *vxlan_socket_create(struct net *net, __be16 port)
1635{ 1641{
1642 struct vxlan_net *vn = net_generic(net, vxlan_net_id);
1636 struct vxlan_sock *vs; 1643 struct vxlan_sock *vs;
1637 struct sock *sk; 1644 struct sock *sk;
1638 struct sockaddr_in vxlan_addr = { 1645 struct sockaddr_in vxlan_addr = {
@@ -1644,8 +1651,10 @@ static struct vxlan_sock *vxlan_socket_create(struct net *net, __be16 port)
1644 unsigned int h; 1651 unsigned int h;
1645 1652
1646 vs = kmalloc(sizeof(*vs), GFP_KERNEL); 1653 vs = kmalloc(sizeof(*vs), GFP_KERNEL);
1647 if (!vs) 1654 if (!vs) {
1655 pr_debug("memory alocation failure\n");
1648 return ERR_PTR(-ENOMEM); 1656 return ERR_PTR(-ENOMEM);
1657 }
1649 1658
1650 for (h = 0; h < VNI_HASH_SIZE; ++h) 1659 for (h = 0; h < VNI_HASH_SIZE; ++h)
1651 INIT_HLIST_HEAD(&vs->vni_list[h]); 1660 INIT_HLIST_HEAD(&vs->vni_list[h]);
@@ -1673,57 +1682,57 @@ static struct vxlan_sock *vxlan_socket_create(struct net *net, __be16 port)
1673 kfree(vs); 1682 kfree(vs);
1674 return ERR_PTR(rc); 1683 return ERR_PTR(rc);
1675 } 1684 }
1685 atomic_set(&vs->refcnt, 1);
1676 1686
1677 /* Disable multicast loopback */ 1687 /* Disable multicast loopback */
1678 inet_sk(sk)->mc_loop = 0; 1688 inet_sk(sk)->mc_loop = 0;
1689 spin_lock(&vn->sock_lock);
1690 hlist_add_head_rcu(&vs->hlist, vs_head(net, port));
1691 spin_unlock(&vn->sock_lock);
1679 1692
1680 /* Mark socket as an encapsulation socket. */ 1693 /* Mark socket as an encapsulation socket. */
1681 udp_sk(sk)->encap_type = 1; 1694 udp_sk(sk)->encap_type = 1;
1682 udp_sk(sk)->encap_rcv = vxlan_udp_encap_recv; 1695 udp_sk(sk)->encap_rcv = vxlan_udp_encap_recv;
1683 udp_encap_enable(); 1696 udp_encap_enable();
1684 atomic_set(&vs->refcnt, 1); 1697 return vs;
1698}
1699
1700static struct vxlan_sock *vxlan_sock_add(struct net *net, __be16 port)
1701{
1702 struct vxlan_net *vn = net_generic(net, vxlan_net_id);
1703 struct vxlan_sock *vs;
1704
1705 vs = vxlan_socket_create(net, port);
1706 if (!IS_ERR(vs))
1707 return vs;
1685 1708
1709 spin_lock(&vn->sock_lock);
1710 vs = vxlan_find_sock(net, port);
1711 if (vs)
1712 atomic_inc(&vs->refcnt);
1713 else
1714 vs = ERR_PTR(-EINVAL);
1715
1716 spin_unlock(&vn->sock_lock);
1686 return vs; 1717 return vs;
1687} 1718}
1688 1719
1689/* Scheduled at device creation to bind to a socket */ 1720/* Scheduled at device creation to bind to a socket */
1690static void vxlan_sock_work(struct work_struct *work) 1721static void vxlan_sock_work(struct work_struct *work)
1691{ 1722{
1692 struct vxlan_dev *vxlan 1723 struct vxlan_dev *vxlan = container_of(work, struct vxlan_dev, sock_work);
1693 = container_of(work, struct vxlan_dev, sock_work); 1724 struct net *net = dev_net(vxlan->dev);
1694 struct net_device *dev = vxlan->dev;
1695 struct net *net = dev_net(dev);
1696 __u32 vni = vxlan->default_dst.remote_vni;
1697 __be16 port = vxlan->dst_port;
1698 struct vxlan_net *vn = net_generic(net, vxlan_net_id); 1725 struct vxlan_net *vn = net_generic(net, vxlan_net_id);
1699 struct vxlan_sock *nvs, *ovs; 1726 __be16 port = vxlan->dst_port;
1700 1727 struct vxlan_sock *nvs;
1701 nvs = vxlan_socket_create(net, port);
1702 if (IS_ERR(nvs)) {
1703 netdev_err(vxlan->dev, "Can not create UDP socket, %ld\n",
1704 PTR_ERR(nvs));
1705 goto out;
1706 }
1707 1728
1729 nvs = vxlan_sock_add(net, port);
1708 spin_lock(&vn->sock_lock); 1730 spin_lock(&vn->sock_lock);
1709 /* Look again to see if can reuse socket */ 1731 if (!IS_ERR(nvs))
1710 ovs = vxlan_find_port(net, port); 1732 vxlan_vs_add_dev(nvs, vxlan);
1711 if (ovs) { 1733 spin_unlock(&vn->sock_lock);
1712 atomic_inc(&ovs->refcnt); 1734
1713 vxlan->vn_sock = ovs; 1735 dev_put(vxlan->dev);
1714 hlist_add_head_rcu(&vxlan->hlist, vni_head(ovs, vni));
1715 spin_unlock(&vn->sock_lock);
1716
1717 sk_release_kernel(nvs->sock->sk);
1718 kfree(nvs);
1719 } else {
1720 vxlan->vn_sock = nvs;
1721 hlist_add_head_rcu(&nvs->hlist, vs_head(net, port));
1722 hlist_add_head_rcu(&vxlan->hlist, vni_head(nvs, vni));
1723 spin_unlock(&vn->sock_lock);
1724 }
1725out:
1726 dev_put(dev);
1727} 1736}
1728 1737
1729static int vxlan_newlink(struct net *net, struct net_device *dev, 1738static int vxlan_newlink(struct net *net, struct net_device *dev,
@@ -1838,7 +1847,8 @@ static void vxlan_dellink(struct net_device *dev, struct list_head *head)
1838 struct vxlan_dev *vxlan = netdev_priv(dev); 1847 struct vxlan_dev *vxlan = netdev_priv(dev);
1839 1848
1840 spin_lock(&vn->sock_lock); 1849 spin_lock(&vn->sock_lock);
1841 hlist_del_rcu(&vxlan->hlist); 1850 if (!hlist_unhashed(&vxlan->hlist))
1851 hlist_del_rcu(&vxlan->hlist);
1842 spin_unlock(&vn->sock_lock); 1852 spin_unlock(&vn->sock_lock);
1843 1853
1844 list_del(&vxlan->next); 1854 list_del(&vxlan->next);