forked from mirrors/linux
		
	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:
		
							parent
							
								
									a896eee334
								
							
						
					
					
						commit
						009146d117
					
				
					 2 changed files with 17 additions and 1 deletions
				
			
		|  | @ -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 @@ static int ipvlan_link_new(struct net *src_net, struct net_device *dev, | |||
| 	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); | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 Mahesh Bandewar
						Mahesh Bandewar