Chapter 17. Network Drivers
Having discussed char and block drivers, we are now ready to move on
to the world of networking. Network interfaces are the third standard
class of Linux devices, and this chapter describes how they interact
with the rest of the kernel.
The role of a network interface within the system
is
similar to that of a mounted block device. A block device registers
its disks and methods with the kernel, and then
"transmits" and
"receives" blocks on request, by
means of its request function. Similarly, a
network interface must register itself within specific kernel data
structures in order to be invoked when packets are exchanged with the
outside world.
There are a few important differences between mounted disks and
packet-delivery interfaces. To begin with, a disk exists as a special
file in the /dev directory, whereas a network
interface has no such entry point. The normal file operations (read,
write, and so on) do not make sense when applied to network
interfaces, so it is not possible to apply the Unix
"everything is a file" approach to
them. Thus, network interfaces exist in their own namespace and
export a different set of operations.
Although you may object that applications use the
read and write system calls
when using sockets, those calls act on a software object that is
distinct from the interface. Several hundred sockets can be
multiplexed on the same physical interface.
But the most important difference between the two is that block
drivers operate only in response to requests from the kernel, whereas
network drivers receive packets asynchronously from the outside.
Thus, while a block driver is asked to send a
buffer toward the kernel, the network device
asks to push incoming packets toward the kernel.
The kernel interface for network drivers is designed for this
different mode of operation.
Network drivers also have to be prepared to support a number of
administrative tasks, such as setting addresses, modifying
transmission parameters, and maintaining traffic and error
statistics. The API for network drivers reflects this need and,
therefore, looks somewhat different from the interfaces we have seen
so far.
The network subsystem of the Linux kernel is designed to be
completely protocol-independent. This applies to both networking
protocols ( Internet protocol [IP] versus IPX or other
protocols) and hardware protocols (Ethernet versus token ring, etc.).
Interaction between a network driver and the kernel properly deals
with one network packet at a time; this allows protocol issues to be
hidden neatly from the driver and the physical transmission to be
hidden from the protocol.
This chapter describes how the network interfaces fit in with the
rest of the Linux kernel and provides examples in the form of a
memory-based modularized network interface, which is called (you
guessed it) snull. To simplify the discussion,
the interface uses the Ethernet hardware protocol and transmits IP
packets. The knowledge you acquire from examining
snull can be readily applied to protocols other
than IP, and writing a non-Ethernet driver is different only in tiny
details related to the actual network protocol.
This chapter doesn't talk about IP numbering
schemes, network protocols, or other general networking concepts.
Such topics are not (usually) of concern to the driver writer, and
it's impossible to offer a satisfactory overview of
networking technology in less than a few hundred pages. The
interested reader is urged to refer to other books describing
networking issues.
One note on
terminology is called for before getting into network devices. The
networking world uses the term octet to refer to
a group of eight bits, which is generally the smallest unit
understood by networking devices and protocols. The term byte is
almost never encountered in this context. In keeping with standard
usage, we will use octet when talking about networking devices.
The term "header" also merits a
quick mention. A header is a set of bytes (err, octets) prepended to
a packet as it is passed through the various layers of the networking
subsystem. When an application sends a block of data through a TCP
socket, the networking subsystem breaks that data up into packets and
puts a TCP header, describing where each packet fits within the
stream, at the beginning. The lower levels then put an IP header,
used to route the packet to its destination, in front of the TCP
header. If the packet moves over an Ethernet-like medium, an Ethernet
header, interpreted by the hardware, goes in front of the rest.
Network drivers need not concern themselves with higher-level headers
(usually), but they often must be involved in the creation of the
hardware-level header.
|