The software described in this documentation is either in Extended Support or Sustaining Support. See https://www.oracle.com/us/support/library/enterprise-linux-support-policies-069172.pdf for more information.
Oracle recommends that you upgrade the software described by this documentation as soon as possible.
Network device drivers receive and transmit data packets on hardware interface that connect to external systems, and provide a uniform interface that network protocols can access. In Oracle Linux, these drivers are abstracted from the hardware implementation of the network adapters themselves, whose implementation hides the underlying layer-1 and layer-2 protocols.
Like a block driver's
routine, most callback routines of a network driver must be
registered with the kernel to allow the kernel to execute them
when data arrives on a network port or when the kernel needs to
send data out on a network port. Like a character driver, a
network driver does not access physically addressable storage
media or support file system access. Unlike block and character
device drivers, network drivers do not have device files under
driver_
request()/dev
. Instead, you use a
net_device
structure to define the capabilities
of a network interface and the kernel updates the members of this
structure when you use a command such as ip to
configure the interface.
The implementation of network device drivers is likely to differ in many respects between Linux and UNIX operating systems, with most differences arising from the functions that the driver uses to handle network requests, the structures that are used to represent network driver methods and to define the properties of network interfaces, and the kernel interface routines for handling network queues.
The
and
driver_
int()
routines that UNIX network device drivers use to handle device
interrupts and the transfer incoming data from a network device to
the upstream protocol module are usually named
driver_
svr()
and driver_
interrupt()
on
Linux systems. The
driver_
rx()
method
should call driver_
rx()netif_rx()
to pass the socket
buffer to the upstream module.
The
routine that UNIX network device drivers use to send data out on a
network device corresponds to the
driver_
put()ndo_start_xmit()
method on Linux systems. The
method can use the following utility functions to control upstream
queueing of socket buffers for transmission:
-
netif_queue_stopped()
Asks the kernel whether a queue is currently stopped.
-
netif_start_queue()
Informs the kernel that the driver is ready to start sending packets.
-
netif_stop_queue()
Asks the kernel to stop sending packets when transmission buffers are full or for driver cleanup when closing the device.
-
netif_wake_queue()
Asks the kernel to wake up a queue that is currently stopped and resume sending packets.
After a network packet has been sent out successfully,
calls a driver_
interrupt()
routine that deletes the driver's copy of the socket buffer data.
driver_
tx
The net_device_ops
structure for a network
device, defined in <linux/netdevice.h>
,
contains a set of method pointers that specify how the system
interacts with the device.
struct net_device_ops { int (*ndo_init)(struct net_device *dev); void (*ndo_uninit)(struct net_device *dev); int (*ndo_open)(struct net_device *dev); int (*ndo_stop)(struct net_device *dev); netdev_tx_t (*ndo_start_xmit) (struct sk_buff *skb, struct net_device *dev); u16 (*ndo_select_queue)(struct net_device *dev, struct sk_buff *skb); void (*ndo_change_rx_flags)(struct net_device *dev, int flags); void (*ndo_set_rx_mode)(struct net_device *dev); void (*ndo_set_multicast_list)(struct net_device *dev); int (*ndo_set_mac_address)(struct net_device *dev, void *addr); int (*ndo_validate_addr)(struct net_device *dev); int (*ndo_do_ioctl)(struct net_device *dev, struct ifreq *ifr, int cmd); int (*ndo_set_config)(struct net_device *dev, struct ifmap *map); int (*ndo_change_mtu)(struct net_device *dev, int new_mtu); int (*ndo_neigh_setup)(struct net_device *dev, struct neigh_parms *); void (*ndo_tx_timeout) (struct net_device *dev); struct rtnl_link_stats64* (*ndo_get_stats64)(struct net_device *dev, struct rtnl_link_stats64 *storage); struct net_device_stats* (*ndo_get_stats)(struct net_device *dev); void (*ndo_vlan_rx_register)(struct net_device *dev, struct vlan_group *grp); void (*ndo_vlan_rx_add_vid)(struct net_device *dev, unsigned short vid); void (*ndo_vlan_rx_kill_vid)(struct net_device *dev, unsigned short vid); /* Several lines omitted */ };
A simple network device driver might only need to implement a subset of the functions defined for this structure, for example:
struct net_device_opsdriver_netdevops
= { .ndo_init =driver_init
, .ndo_open =driver_open
, .ndo_stop =foo_close
, .ndo_start_xmit =foo_start_xmit
, .ndo_do_ioctl =foo_ioctl
, .ndo_tx_timeout =foo_tx_timeout
, };
The kernel calls ndo_open()
when you bring up
and assign an address to a network interface,
ndo_stop()
when you shut down the interface,
and ndo_start_xmit()
when it wants to transmit
a packet.
The net_device
structure for a character
device, defined in <linux/netdevice.h>
,
defines the properties of the network interface.
The most important members of the net_device
structure are:
-
dev_addr
The hardware media access control (MAC) address.
-
features
A bit mask that describes the features that the device supports.
-
flags
Describes the current properties of the device, such as the following:
-
IFF_BROADCAST
Broadcast mode is enabled.
-
IFF_LOOPBACK
The interface corresponds to a loopback device.
-
IFF_MULTICAST
Multicast mode is enabled.
-
IFF_NOARP
The interface does not use ARP to perform address resolution. This flag is usually set by point-to-point interfaces.
-
IFF_PROMISC
Promiscuous mode is enabled.
-
IFF_UP
The interface is enabled. The driver does not set this flag. Using an application such as ip to bring an interface up or down causes the kernel to invoke the
ndo_open()
orndo_stop()
method and set or unset the flag to indicate the state of the interface.
-
-
irq
The interrupt request queue (IRQ) number.
-
mtu
The maximum transmission unit (MTU), which is the maximum frame size that the device can transmit.
-
name
The name of the interface, for example,
eth0
orlo0
.-
netdev_ops
A pointer to a
net_device_ops
structure that defines the methods for the interface.-
promiscuity
A counter of how many client applications have placed the interface in promiscuous mode.
-
stats
A
net_device_stats
structure that contains interface usage statistics.
As well as driver methods,
,
and related helper routines, it is usual to define
driver_
interrupt()module_init()
initialization and
module_exit()
cleanup routines for the driver
that are called when the driver is loaded and unloaded. These
routines should call register_netdev()
and
unregister_netdev()
to register and unregister
the device, and alloc_netdev()
and
free_netdev()
to allocate and delete the
kernel's representation of the device. For Ethernet devices, it is
usual to call alloc_etherdev()
instead of
alloc_netdev()
. When initializing the driver,
use request_irq()
to install the interrupt
handler, remembering to specify shared interrupts by setting the
SA_SHIRQ
bit in the
flags
argument as well as a unique
dev_id
argument that the handler can
use to identify interrupts that it should process. The cleanup
routine should call free_irq()
to unregister
the handler.