[ovs-dev] [PATCH 10/13] Upstream VXLAN: Use IP Tunnels rtnl-netlink functions.
Pravin B Shelar
pshelar at nicira.com
Thu Nov 22 15:57:19 UTC 2012
From: Pravin Shelar <pshelar at nicira.com>
IP Tunnel modules defines generic rtnl-netlink ops for tunneling
devices VXLAN can directly use them.
Signed-off-by: Pravin B Shelar <pshelar at nicira.com>
---
drivers/net/vxlan.c | 105 ++++++++++++++++++---------------------------------
1 files changed, 37 insertions(+), 68 deletions(-)
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index 8b0164a..1977da5 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -45,8 +45,6 @@
#define VXLAN_VERSION "0.1"
-#define VNI_HASH_BITS 10
-#define VNI_HASH_SIZE (1<<VNI_HASH_BITS)
#define FDB_HASH_BITS 8
#define FDB_HASH_SIZE (1<<FDB_HASH_BITS)
#define FDB_AGE_DEFAULT 300 /* 5 min */
@@ -64,8 +62,8 @@ MODULE_PARM_DESC(log_ecn_error, "Log packets received with corrupted ECN");
/* per-net private data for this module */
static int vxlan_net_id;
struct vxlan_net {
+ struct ip_tunnel_net itn;
struct socket *sock; /* UDP encap socket */
- struct hlist_head vni_list[VNI_HASH_SIZE];
};
/* Forwarding table entry */
@@ -82,7 +80,6 @@ struct vxlan_fdb {
/* Pseudo network device */
struct vxlan_dev {
struct ip_tunnel tunnel;
- struct hlist_node hlist;
unsigned int link; /* link to multicast over */
__u16 port_min; /* source port range */
__u16 port_max;
@@ -103,30 +100,6 @@ struct vxlan_dev {
#define VXLAN_F_L2MISS 0x08
#define VXLAN_F_L3MISS 0x10
-/* salt for hash table */
-static u32 vxlan_salt __read_mostly;
-
-static inline struct hlist_head *vni_head(struct net *net, __be32 id)
-{
- struct vxlan_net *vn = net_generic(net, vxlan_net_id);
-
- return &vn->vni_list[hash_32((__force u32)id, VNI_HASH_BITS)];
-}
-
-/* Look up VNI in a per net namespace table */
-static struct vxlan_dev *vxlan_find_vni(struct net *net, __be32 vni)
-{
- struct vxlan_dev *vxlan;
- struct hlist_node *node;
-
- hlist_for_each_entry_rcu(vxlan, node, vni_head(net, vni), hlist) {
- if (vxlan->tunnel.parms.i_key == vni)
- return vxlan;
- }
-
- return NULL;
-}
-
/* Fill in neighbour message in skbuff. */
static int vxlan_fdb_info(struct sk_buff *skb, struct vxlan_dev *vxlan,
const struct vxlan_fdb *fdb,
@@ -453,19 +426,18 @@ static void vxlan_snoop(struct net_device *dev,
static bool vxlan_group_used(struct vxlan_net *vn,
const struct vxlan_dev *this)
{
- const struct vxlan_dev *vxlan;
- struct hlist_node *node;
+ const struct ip_tunnel *t;
unsigned h;
- for (h = 0; h < VNI_HASH_SIZE; ++h)
- hlist_for_each_entry(vxlan, node, &vn->vni_list[h], hlist) {
- if (vxlan == this)
+ for (h = 0; h < IPT_HASH_SIZE; ++h)
+ for_each_ip_tunnel_rcu(t, vn->itn.tunnels[h]) {
+ if (t == (const struct ip_tunnel *) this)
continue;
- if (!netif_running(vxlan->tunnel.dev))
+ if (!netif_running(t->dev))
continue;
- if (vxlan->tunnel.parms.iph.daddr == this->tunnel.parms.iph.daddr)
+ if (t->parms.iph.daddr == this->tunnel.parms.iph.daddr)
return true;
}
@@ -575,12 +547,13 @@ static int vxlan_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi)
{
struct vxlan_dev *vxlan;
struct net *net = dev_net(skb->dev);
+ struct vxlan_net *vn = net_generic(net, vxlan_net_id);
struct iphdr *oip;
struct pcpu_tstats *stats;
int err;
/* Is this VNI defined? */
- vxlan = vxlan_find_vni(net, tpi->key);
+ vxlan = (struct vxlan_dev *) ip_tunnel_lookup_key(&vn->itn, tpi->key);
if (!vxlan)
return 1;
@@ -1108,6 +1081,8 @@ static void vxlan_setup(struct net_device *dev)
for (h = 0; h < FDB_HASH_SIZE; ++h)
INIT_HLIST_HEAD(&vxlan->fdb_head[h]);
+
+ ip_tunnel_setup(dev, vxlan_net_id);
}
static const struct nla_policy vxlan_policy[IFLA_VXLAN_MAX + 1] = {
@@ -1172,22 +1147,19 @@ static int vxlan_validate(struct nlattr *tb[], struct nlattr *data[])
return 0;
}
-static int vxlan_newlink(struct net *net, struct net_device *dev,
- struct nlattr *tb[], struct nlattr *data[])
+static int vxlan_netlink_parms(struct ip_tunnel *t, struct nlattr *data[],
+ struct nlattr *tb[], struct ip_tunnel_parm *parms)
{
- struct vxlan_dev *vxlan = netdev_priv(dev);
+ struct vxlan_dev *vxlan = (struct vxlan_dev *)t;
+ struct net_device *dev = vxlan->tunnel.dev;
+ struct net *net = dev_net(dev);
__u32 vni;
- int err;
if (!data[IFLA_VXLAN_ID])
return -EINVAL;
vni = nla_get_u32(data[IFLA_VXLAN_ID]);
vxlan->tunnel.parms.i_key = htonl(vni << 8);
- if (vxlan_find_vni(net, vxlan->tunnel.parms.i_key)) {
- pr_info("duplicate VNI %u\n", vni);
- return -EEXIST;
- }
if (data[IFLA_VXLAN_GROUP])
vxlan->tunnel.parms.iph.daddr = nla_get_be32(data[IFLA_VXLAN_GROUP]);
@@ -1249,20 +1221,7 @@ static int vxlan_newlink(struct net *net, struct net_device *dev,
vxlan->port_max = ntohs(p->high);
}
- err = register_netdevice(dev);
- if (!err)
- hlist_add_head_rcu(&vxlan->hlist, vni_head(net, vxlan->tunnel.parms.i_key));
-
- return err;
-}
-
-static void vxlan_dellink(struct net_device *dev, struct list_head *head)
-{
- struct vxlan_dev *vxlan = netdev_priv(dev);
-
- hlist_del_rcu(&vxlan->hlist);
-
- unregister_netdevice_queue(dev, head);
+ return 0;
}
static size_t vxlan_get_size(const struct net_device *dev)
@@ -1339,8 +1298,8 @@ static struct rtnl_link_ops vxlan_link_ops __read_mostly = {
.priv_size = sizeof(struct vxlan_dev),
.setup = vxlan_setup,
.validate = vxlan_validate,
- .newlink = vxlan_newlink,
- .dellink = vxlan_dellink,
+ .newlink = ip_tunnel_newlink,
+ .dellink = ip_tunnel_dellink,
.get_size = vxlan_get_size,
.fill_info = vxlan_fill_info,
};
@@ -1388,18 +1347,28 @@ struct socket *vxlan_create_socket(struct net *net, int portno)
}
EXPORT_SYMBOL(vxlan_create_socket);
+static const struct ip_tunnel_ops vxlan_tunnel_ops = {
+ .flags = HASH_ON_KEY,
+ .parse_netlink_parms = vxlan_netlink_parms,
+};
+
static __net_init int vxlan_init_net(struct net *net)
{
struct vxlan_net *vn = net_generic(net, vxlan_net_id);
- unsigned h;
+ struct ip_tunnel_net *itn = &vn->itn;
+ int rc;
+
+ itn->ops = &vxlan_tunnel_ops;
+ rc = ip_tunnel_init_net(net, vxlan_net_id, NULL);
+ if (rc)
+ return rc;
vn->sock = vxlan_create_socket(net, vxlan_port);
if (IS_ERR(vn->sock)) {
+ ip_tunnel_delete_net(itn);
vn->sock = NULL;
return PTR_ERR(vn->sock);
}
- for (h = 0; h < VNI_HASH_SIZE; ++h)
- INIT_HLIST_HEAD(&vn->vni_list[h]);
return 0;
}
@@ -1407,11 +1376,13 @@ static __net_init int vxlan_init_net(struct net *net)
static __net_exit void vxlan_exit_net(struct net *net)
{
struct vxlan_net *vn = net_generic(net, vxlan_net_id);
+ struct ip_tunnel_net *itn = &vn->itn;
if (vn->sock) {
sk_release_kernel(vn->sock->sk);
vn->sock = NULL;
}
+ ip_tunnel_delete_net(itn);
}
static struct pernet_operations vxlan_net_ops = {
@@ -1422,17 +1393,15 @@ static struct pernet_operations vxlan_net_ops = {
};
static struct ipt_protocol vxlan_protocol = {
- .handler = vxlan_rcv,
- .priority = 0,
- .type = IPT_VXLAN,
+ .handler = vxlan_rcv,
+ .priority = 0,
+ .type = IPT_VXLAN,
};
static int __init vxlan_init_module(void)
{
int rc;
- get_random_bytes(&vxlan_salt, sizeof(vxlan_salt));
-
rc = register_pernet_device(&vxlan_net_ops);
if (rc)
goto out1;
--
1.7.1
More information about the dev
mailing list