ipvlan: assign unique dev-id for each slave device.
IPvlan setup uses one mac-address (of master). The IPv6 link-local addresses are derived using the mac-address on the link. Lack of dev-ids makes these link-local addresses same for all slaves including that of master device. dev-ids are necessary to add differentiation when L2 address is shared. Signed-off-by: Mahesh Bandewar <maheshb@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Родитель
a896eee334
Коммит
009146d117
|
@ -97,6 +97,7 @@ struct ipvl_port {
|
|||
struct work_struct wq;
|
||||
struct sk_buff_head backlog;
|
||||
int count;
|
||||
struct ida ida;
|
||||
};
|
||||
|
||||
struct ipvl_skb_cb {
|
||||
|
|
|
@ -119,6 +119,7 @@ static int ipvlan_port_create(struct net_device *dev)
|
|||
|
||||
skb_queue_head_init(&port->backlog);
|
||||
INIT_WORK(&port->wq, ipvlan_process_multicast);
|
||||
ida_init(&port->ida);
|
||||
|
||||
err = netdev_rx_handler_register(dev, ipvlan_handle_frame, port);
|
||||
if (err)
|
||||
|
@ -150,6 +151,7 @@ static void ipvlan_port_destroy(struct net_device *dev)
|
|||
dev_put(skb->dev);
|
||||
kfree_skb(skb);
|
||||
}
|
||||
ida_destroy(&port->ida);
|
||||
kfree(port);
|
||||
}
|
||||
|
||||
|
@ -533,6 +535,16 @@ static int ipvlan_link_new(struct net *src_net, struct net_device *dev,
|
|||
ipvlan_adjust_mtu(ipvlan, phy_dev);
|
||||
INIT_LIST_HEAD(&ipvlan->addrs);
|
||||
|
||||
/* Since L2 address is shared among all IPvlan slaves including
|
||||
* master, use unique 16 bit dev-ids to diffentiate among them.
|
||||
* Assign IDs between 0x1 and 0xFFFE (used by the master) to each
|
||||
* slave link [see addrconf_ifid_eui48()].
|
||||
*/
|
||||
err = ida_simple_get(&port->ida, 1, 0xFFFE, GFP_KERNEL);
|
||||
if (err < 0)
|
||||
goto destroy_ipvlan_port;
|
||||
dev->dev_id = err;
|
||||
|
||||
/* TODO Probably put random address here to be presented to the
|
||||
* world but keep using the physical-dev address for the outgoing
|
||||
* packets.
|
||||
|
@ -543,7 +555,7 @@ static int ipvlan_link_new(struct net *src_net, struct net_device *dev,
|
|||
|
||||
err = register_netdevice(dev);
|
||||
if (err < 0)
|
||||
goto destroy_ipvlan_port;
|
||||
goto remove_ida;
|
||||
|
||||
err = netdev_upper_dev_link(phy_dev, dev);
|
||||
if (err) {
|
||||
|
@ -562,6 +574,8 @@ unlink_netdev:
|
|||
netdev_upper_dev_unlink(phy_dev, dev);
|
||||
unregister_netdev:
|
||||
unregister_netdevice(dev);
|
||||
remove_ida:
|
||||
ida_simple_remove(&port->ida, dev->dev_id);
|
||||
destroy_ipvlan_port:
|
||||
if (create)
|
||||
ipvlan_port_destroy(phy_dev);
|
||||
|
@ -579,6 +593,7 @@ static void ipvlan_link_delete(struct net_device *dev, struct list_head *head)
|
|||
kfree_rcu(addr, rcu);
|
||||
}
|
||||
|
||||
ida_simple_remove(&ipvlan->port->ida, dev->dev_id);
|
||||
list_del_rcu(&ipvlan->pnode);
|
||||
unregister_netdevice_queue(dev, head);
|
||||
netdev_upper_dev_unlink(ipvlan->phy_dev, dev);
|
||||
|
|
Загрузка…
Ссылка в новой задаче