diff options
author | Mahesh Bandewar <maheshb@google.com> | 2017-01-09 18:05:54 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2017-01-10 20:47:12 -0500 |
commit | da36e13cf653541e385a8d2ec2637fff6ea3461a (patch) | |
tree | 3d86b8c8337e679806f77b875ee6564ebf6712dc /drivers/net/ipvlan/ipvlan_main.c | |
parent | de28c99d71d91251713b67c545fa05b2b5e0d232 (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.c | 13 |
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 |