mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	ipvlan: improvise dev_id generation logic in IPvlan
The patch009146d117("ipvlan: assign unique dev-id for each slave device.") used ida_simple_get() to generate dev_ids assigned to the slave devices. However (Eric has pointed out that) there is a shortcoming with that approach as it always uses the first available ID. This becomes a problem when a slave gets deleted and a new slave gets added. The ID gets reassigned causing the new slave to get the same link-local address. This side-effect is undesirable. This patch adds a per-port variable that keeps track of the IDs assigned and used as the stat-base for the IDR api. This base will be wrapped around when it reaches the MAX (0xFFFE) value possibly on a busy system where slaves are added and deleted routinely. Fixes:009146d117("ipvlan: assign unique dev-id for each slave device.") Signed-off-by: Mahesh Bandewar <maheshb@google.com> CC: Eric Dumazet <edumazet@google.com> CC: David Miller <davem@davemloft.org> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									de28c99d71
								
							
						
					
					
						commit
						da36e13cf6
					
				
					 2 changed files with 13 additions and 1 deletions
				
			
		| 
						 | 
				
			
			@ -94,6 +94,7 @@ struct ipvl_port {
 | 
			
		|||
	struct hlist_head	hlhead[IPVLAN_HASH_SIZE];
 | 
			
		||||
	struct list_head	ipvlans;
 | 
			
		||||
	u16			mode;
 | 
			
		||||
	u16			dev_id_start;
 | 
			
		||||
	struct work_struct	wq;
 | 
			
		||||
	struct sk_buff_head	backlog;
 | 
			
		||||
	int			count;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -120,6 +120,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);
 | 
			
		||||
	port->dev_id_start = 1;
 | 
			
		||||
 | 
			
		||||
	err = netdev_rx_handler_register(dev, ipvlan_handle_frame, port);
 | 
			
		||||
	if (err)
 | 
			
		||||
| 
						 | 
				
			
			@ -534,15 +535,25 @@ static int ipvlan_link_new(struct net *src_net, struct net_device *dev,
 | 
			
		|||
	ipvlan_adjust_mtu(ipvlan, phy_dev);
 | 
			
		||||
	INIT_LIST_HEAD(&ipvlan->addrs);
 | 
			
		||||
 | 
			
		||||
	/* If the port-id base is at the MAX value, then wrap it around and
 | 
			
		||||
	 * begin from 0x1 again. This may be due to a busy system where lots
 | 
			
		||||
	 * of slaves are getting created and deleted.
 | 
			
		||||
	 */
 | 
			
		||||
	if (port->dev_id_start == 0xFFFE)
 | 
			
		||||
		port->dev_id_start = 0x1;
 | 
			
		||||
 | 
			
		||||
	/* 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);
 | 
			
		||||
	err = ida_simple_get(&port->ida, port->dev_id_start, 0xFFFE,
 | 
			
		||||
			     GFP_KERNEL);
 | 
			
		||||
	if (err < 0)
 | 
			
		||||
		goto destroy_ipvlan_port;
 | 
			
		||||
	dev->dev_id = err;
 | 
			
		||||
	/* Increment id-base to the next slot for the future assignment */
 | 
			
		||||
	port->dev_id_start = err + 1;
 | 
			
		||||
 | 
			
		||||
	/* TODO Probably put random address here to be presented to the
 | 
			
		||||
	 * world but keep using the physical-dev address for the outgoing
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue