unregister_netdev is used to delete a net device. In fact, it equals:
1 2 3 4
rtnl_lock(); rollback_registered_many( a temp list with a single net device); list_add_tail(&dev->todo_list, &net_todo_list); rtnl_unlock();
a temporary list stores a single net device, which is to be deleted. net_todo_list stores all the net devices are being deleted.
The core function is rollback_registered_many, which efficiently deletes many devices in a list. But here, in this case, one a single netdevice in the list.
firstly check the status and confirm the net device is registered(NETREG_REGISTERED), or it will do nothing for the net device.
for each net device, close it by dev_close_many, and notify(broadcast) ‘NETDEV_DOWN’ message by rtmsg and net device notify.
remove netdevice from kernel net device list (by name, ifindex, ..).
net device bemomes NETREG_UNREGISTERING.
synchronize_net();
dev_shutdown shut down net device tx/rx queue.
call call_netdevice_notifiers with NETDEV_UNREGISTER
Flush the unicast and multicast chains, remove sys, ..
dev_put (here only decrease reference);
in the finally, do rtnl_unlock, which do more than unlock rtnl.
it will check all the devices in the net_todo_list and wait them to be freed. to enhace efficience, net_todo_list will be copied(moved) to a temp list, and empty net_todo_list. thus rtnl lock is freed.
then for each netdevice in the temp list, wait them to be free(un-reference), and then free them(deconstruct). for safe, we Rebroadcast unregister notification every 250ms(try within 10s), during wait dev reference.
5976/** 5977 * unregister_netdev - remove device from the kernel 5978 * @dev: device 5979 * 5980 * This function shuts down a device interface and removes it 5981 * from the kernel tables. 5982 * 5983 * This is just a wrapper for unregister_netdevice that takes 5984 * the rtnl semaphore. In general you want to use this and not 5985 * unregister_netdevice. 5986 */ 5987voidunregister_netdev(struct net_device *dev) 5988 { 5989 rtnl_lock(); 5990 unregister_netdevice(dev); 5991 rtnl_unlock(); 5992 } 5993 EXPORT_SYMBOL(unregister_netdev);
1303staticint __dev_close_many(struct list_head *head) 1304 { 1305structnet_device *dev; 1306 1307 ASSERT_RTNL(); 1308 might_sleep(); 1309 1310 list_for_each_entry(dev, head, unreg_list) { 1311 call_netdevice_notifiers(NETDEV_GOING_DOWN, dev); 1312 1313 clear_bit(__LINK_STATE_START, &dev->state); 1314 1315/* Synchronize to scheduled poll. We cannot touch poll list, it 1316 * can be even on different cpu. So just clear netif_running(). 1317 * 1318 * dev->stop() will invoke napi_disable() on all of it's 1319 * napi_struct instances on this device. 1320 */ 1321 smp_mb__after_clear_bit(); /* Commit netif_running(). */ 1322 } 1323 1324 dev_deactivate_many(head); 1325 1326 list_for_each_entry(dev, head, unreg_list) { 1327conststructnet_device_ops *ops = dev->netdev_ops; 1328 1329/* 1330 * Call the device specific close. This cannot fail. 1331 * Only if device is UP 1332 * 1333 * We allow it to be called even after a DETACH hot-plug 1334 * event. 1335 */ 1336if (ops->ndo_stop) 1337 ops->ndo_stop(dev); 1338 1339 dev->flags &= ~IFF_UP; 1340 net_dmaengine_put(); 1341 } 1342 1343return0; 1344 }