Skip to content

Commit da36e13

Browse files
Mahesh Bandewardavem330
authored andcommitted
ipvlan: improvise dev_id generation logic in IPvlan
The patch 009146d ("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: 009146d ("ipvlan: assign unique dev-id for each slave device.") Signed-off-by: Mahesh Bandewar <[email protected]> CC: Eric Dumazet <[email protected]> CC: David Miller <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent de28c99 commit da36e13

File tree

2 files changed

+13
-1
lines changed

2 files changed

+13
-1
lines changed

drivers/net/ipvlan/ipvlan.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ struct ipvl_port {
9494
struct hlist_head hlhead[IPVLAN_HASH_SIZE];
9595
struct list_head ipvlans;
9696
u16 mode;
97+
u16 dev_id_start;
9798
struct work_struct wq;
9899
struct sk_buff_head backlog;
99100
int count;

drivers/net/ipvlan/ipvlan_main.c

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ static int ipvlan_port_create(struct net_device *dev)
120120
skb_queue_head_init(&port->backlog);
121121
INIT_WORK(&port->wq, ipvlan_process_multicast);
122122
ida_init(&port->ida);
123+
port->dev_id_start = 1;
123124

124125
err = netdev_rx_handler_register(dev, ipvlan_handle_frame, port);
125126
if (err)
@@ -534,15 +535,25 @@ static int ipvlan_link_new(struct net *src_net, struct net_device *dev,
534535
ipvlan_adjust_mtu(ipvlan, phy_dev);
535536
INIT_LIST_HEAD(&ipvlan->addrs);
536537

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+
537545
/* Since L2 address is shared among all IPvlan slaves including
538546
* master, use unique 16 bit dev-ids to diffentiate among them.
539547
* Assign IDs between 0x1 and 0xFFFE (used by the master) to each
540548
* slave link [see addrconf_ifid_eui48()].
541549
*/
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);
543552
if (err < 0)
544553
goto destroy_ipvlan_port;
545554
dev->dev_id = err;
555+
/* Increment id-base to the next slot for the future assignment */
556+
port->dev_id_start = err + 1;
546557

547558
/* TODO Probably put random address here to be presented to the
548559
* world but keep using the physical-dev address for the outgoing

0 commit comments

Comments
 (0)