aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ipvlan/ipvlan_main.c
diff options
context:
space:
mode:
authorMahesh Bandewar <maheshb@google.com>2017-01-09 18:05:54 -0500
committerDavid S. Miller <davem@davemloft.net>2017-01-10 20:47:12 -0500
commitda36e13cf653541e385a8d2ec2637fff6ea3461a (patch)
tree3d86b8c8337e679806f77b875ee6564ebf6712dc /drivers/net/ipvlan/ipvlan_main.c
parentde28c99d71d91251713b67c545fa05b2b5e0d232 (diff)
ipvlan: improvise dev_id generation logic in IPvlan
The patch 009146d117b ("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: 009146d117b ("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>
Diffstat (limited to 'drivers/net/ipvlan/ipvlan_main.c')
-rw-r--r--drivers/net/ipvlan/ipvlan_main.c13
1 files changed, 12 insertions, 1 deletions
diff --git a/drivers/net/ipvlan/ipvlan_main.c b/drivers/net/ipvlan/ipvlan_main.c
index 1cdb8c5ec403..92b221a03350 100644
--- a/drivers/net/ipvlan/ipvlan_main.c
+++ b/drivers/net/ipvlan/ipvlan_main.c
@@ -120,6 +120,7 @@ static int ipvlan_port_create(struct net_device *dev)
120 skb_queue_head_init(&port->backlog); 120 skb_queue_head_init(&port->backlog);
121 INIT_WORK(&port->wq, ipvlan_process_multicast); 121 INIT_WORK(&port->wq, ipvlan_process_multicast);
122 ida_init(&port->ida); 122 ida_init(&port->ida);
123 port->dev_id_start = 1;
123 124
124 err = netdev_rx_handler_register(dev, ipvlan_handle_frame, port); 125 err = netdev_rx_handler_register(dev, ipvlan_handle_frame, port);
125 if (err) 126 if (err)
@@ -534,15 +535,25 @@ static int ipvlan_link_new(struct net *src_net, struct net_device *dev,
534 ipvlan_adjust_mtu(ipvlan, phy_dev); 535 ipvlan_adjust_mtu(ipvlan, phy_dev);
535 INIT_LIST_HEAD(&ipvlan->addrs); 536 INIT_LIST_HEAD(&ipvlan->addrs);
536 537
538 /* If the port-id base is at the MAX value, then wrap it around and
539 * begin from 0x1 again. This may be due to a busy system where lots
540 * of slaves are getting created and deleted.
541 */
542 if (port->dev_id_start == 0xFFFE)
543 port->dev_id_start = 0x1;
544
537 /* Since L2 address is shared among all IPvlan slaves including 545 /* Since L2 address is shared among all IPvlan slaves including
538 * master, use unique 16 bit dev-ids to diffentiate among them. 546 * master, use unique 16 bit dev-ids to diffentiate among them.
539 * Assign IDs between 0x1 and 0xFFFE (used by the master) to each 547 * Assign IDs between 0x1 and 0xFFFE (used by the master) to each
540 * slave link [see addrconf_ifid_eui48()]. 548 * slave link [see addrconf_ifid_eui48()].
541 */ 549 */
542 err = ida_simple_get(&port->ida, 1, 0xFFFE, GFP_KERNEL); 550 err = ida_simple_get(&port->ida, port->dev_id_start, 0xFFFE,
551 GFP_KERNEL);
543 if (err < 0) 552 if (err < 0)
544 goto destroy_ipvlan_port; 553 goto destroy_ipvlan_port;
545 dev->dev_id = err; 554 dev->dev_id = err;
555 /* Increment id-base to the next slot for the future assignment */
556 port->dev_id_start = err + 1;
546 557
547 /* TODO Probably put random address here to be presented to the 558 /* TODO Probably put random address here to be presented to the
548 * world but keep using the physical-dev address for the outgoing 559 * world but keep using the physical-dev address for the outgoing