IP Tunnel modules defines generic rtnl-netlink ops for tunneling devices VXLAN can directly use them.
Signed-off-by: Pravin B Shelar <[email protected]> --- drivers/net/vxlan.c | 105 ++++++++++++++++++--------------------------------- 1 file changed, 37 insertions(+), 68 deletions(-) diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index a56e00d..8faaeb8 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -43,8 +43,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 */ @@ -62,8 +60,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 */ @@ -80,7 +78,6 @@ struct vxlan_fdb { /* Pseudo network device */ struct vxlan_dev { struct ip_tunnel tunnel; - struct hlist_node hlist; __u16 port_min; /* source port range */ __u16 port_max; bool learn; @@ -94,30 +91,6 @@ struct vxlan_dev { struct hlist_head fdb_head[FDB_HASH_SIZE]; }; -/* 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, @@ -412,19 +385,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(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; } @@ -534,12 +506,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; @@ -930,6 +903,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] = { @@ -990,22 +965,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]); @@ -1051,20 +1023,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) @@ -1126,8 +1085,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, }; @@ -1175,18 +1134,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; } @@ -1194,11 +1163,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 = { @@ -1209,17 +1180,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.10 _______________________________________________ dev mailing list [email protected] http://openvswitch.org/mailman/listinfo/dev
