diff --git a/drivers/net/ipvlan/ipvlan.h b/drivers/net/ipvlan/ipvlan.h index 0a9068fdee0f15a8c402685734b0aee4970e05ac..406ae4ff0ae891aa6bd1522bbb367699f16109b1 100644 --- a/drivers/net/ipvlan/ipvlan.h +++ b/drivers/net/ipvlan/ipvlan.h @@ -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; diff --git a/drivers/net/ipvlan/ipvlan_main.c b/drivers/net/ipvlan/ipvlan_main.c index 1cdb8c5ec40354492dab50037b8ccf14a491ae6e..92b221a033503d982a48a4112c01b0dbbfcb3287 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) 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