Network Interface Registration - Linux

After all the initialization of the net device structure and the associated private data structure is complete, the driver can be registered as a networking device. Network device registration consists of putting the driver’s net device structure on a linked list. The files linux/net/core/dev.c and linux/net/net_init.c provide utility functions to do the registration and perform other tasks. Most of the functions involved in network device registration use the name field in the net_device structure. This is why driver writers should use the dev_alloc_name function to ensure that the name field is formatted properly. The list of net devices is protected by the netlink mutex locking and unlocking functions, rtnl_lock and rtnl_unlock. The list of devices should not be manipulated without locking because if the locks are not used, it is possible for the device list to become corrupted or two devices that try to register in parallel to be assigned the same name. The device interface utility functions for manipulating the list of network devices are shown later in this section. Each function described here takes a mutex lock so it is safe to call. There are also unsafe versions of each of these functions defined in linux/core/dev.c (in most cases) that can be used if the caller takes the netlink semaphore. The unsafe versions generally have the same name but proceeded by a double underscore with the exception of the register function, which has an unsafe version is called register_netdevice. The network interface driver registration sequence was shown earlier in Figure.

To perform the last step of network interface registration, the driver’s initialization function calls register_netdev, in the file net_init.c.

We lock by taking the netlink semaphore.

rtnl_lock();

Dev_alloc_name is called to substitute the formatting string, %d, in the device name with a number. The number selected is the total number of devices registered so far for the particular type supported by this driver minus one. For example, the first Ethernet device will be called eth0, the second one will be eth1, and so on.

This is a backward compatibility hook for implicit allocation of old Ethernet devices and may be deprecated. By the time this function is called, the name field in the net_device structure should be initialized to the base name plus the formatting character.

We call register_netdevice to do the heavy lifting associated with network interface registration. If the caller knows that the device name is already set up properly, register_netdevice can be called directly, but only if the netlink semaphore is taken first.

err = register_netdevice(dev); out:

We must unlock before returning.

Linux provides the capability of using one of a number of multiple queuing disciplines and classbased scheduling methods for drivers that can benefit from a performance increase. Next, the default packet scheduler and queue disciplines are set for this device by calling dev_init_scheduler in the file sch_generic.c. (Theoretically, although this isn’t done very often, the packet scheduler and queue disciplines could be changed at any time as long as the driver is off line and the appropriate lock mutexes are taken.) The function dev_init_scheduler sets the qdisc field of the net device structure to point to the noop queue discipline. A driver can change the queue discipline later when the driver’s open function is called, but in the meantime, the qdisc and qdisc_sleeping fields should point to a default queuing discipline as the net device structure is initialized.

Network Device Registration Utility Functions

All of the functions in this section are declared in the file linux / include / linux / netdevice.h. The first function dev_ get_ by_ name finds a device by name. It can be called from any context because it does its own locking. It returns a pointer to a net_device based on the string name. The reference count field in net_device is incremented before the function returns.

struct net_device *dev_get_by_name(const char *name);

The first function, register_netdev, registers a network interface device driver. This version of the function acquires the lock. The function register_netdevice can also be used but it requires the caller to hold the rtnl lock.

int register_netdev(struct net_device *dev);

An important responsibility of register_netdevice is to place the net device structure on the list of network device drivers maintained in the Linux kernel. Before doing this, it initializes the device’s queue_lock and xmit_lock fields. It then checks a global variable called dev_boot_phase, set at compile time to indicate that no devices are initialized. If dev_boot_phase is set, the net_dev_init function is called, which initializes the queuing layer—this will only happen once as the first network device is initialized because dev_boot_phase is reset to zero when net_dev_init exits. A unique ifindex is assigned to the device, and this number is set in the ifindex field of the netdevice. Next, the state field is set to __LINK_STATE_PRESENT, which indicates that the device is present and ready to be scheduled.

int register_netdevice(struct net_device *dev);

The next two functions, unregister_netdev and unregister_netdevice, remove the device dev from the list of devices. The first of these functions, unregister_netdev, is the "safe" version. In this routine, we take the rt_netlink semaphore and then call the internal routine unregister_netdevice.

void unregister_netdev(struct net_device *dev);

The next function also unregisters a net_device. In this function, we require the caller to take the rtnl semaphore before invocation.

We also protect against being called with a device that has never been registered.

Next, we check for IFF_UP in the flags of the network device structure to see if the device is running. If the device is running, we call the network interface generic dev_close function to stop the device.

Next, we remove the pointer to the net_device structure from the linked list of devices, and shut down the device’s queues for the particular queuing discipline in effect by calling dev_shutdown.

We send a notification message to any interested protocols that this device is about to be destroyed by calling the notifier_call_chain, covered in Section

notifier_call_chain(&netdev_chain, NETDEV_UNREGISTER, dev);

We flush the list of multicast addresses from the device.

his is a check of the notifier chain. It should have detached us from the master device in the notifier group.

In Linux 2.6, device registration is asynchronous. Work on device registration and unregistration can be deferred if a device is busy. net_set_todo(dev);

Finally, we check the reference count in the refcnt field of the net_device structure by calling dev_put. If it is one or higher, a reference to the device must be active, and we can decrement the reference count.

dev_put(dev); return 0; }

To complete this section on network device registration, we will list a few functions that Linux provides to retrieve a device. Each of these functions returns a net_device structure based on various criteria such as type and hardware address, flags, or ifindex.

There are several functions provided to allocate a device structure or merely a device name string. The first function, dev_alloc_name, checks for a valid format in name. It appends a digit 1 to 99 to the name and returns the number appended to the name.

int dev_alloc_name(struct net_device *dev, const char *name);

The next function, alloc_etherdev, allocates a complete net_device structure specifically for an Ethernet device.

struct net_device *alloc_etherdev(int sizeof_priv);

The last function in this group, alloc_netdev, is generally not called directly. Instead, it is called by one of the functions that are specific to the device type, such as alloc_etherdev in the preceding code. Alloc_netdev allocates the private data area and the net device structure. It also initializes the name field in the net_device structure to the base string for the name such as "eth".

Finally, a function, netdev_boot_setup, is provided to all driver writers to set fields in thenet_device structure from boot time parameters.

int __init netdev_boot_setup(char *str);

All rights reserved © 2018 Wisdom IT Services India Pvt. Ltd DMCA.com Protection Status

Linux Topics