26.3. Linux Implementation
Early Linux kernels had L3 protocols call functions provided by neighboring protocols directly. The IPv4 subsystem, therefore, interacted directly with the ARP code. In recent versions of the kernel, developers have identified common requirements for different protocols and have abstracted them into a new layer called the neighboring infrastructure.
Because the kernel still includes old pieces of code that have not been updated to the new, protocol-independent layer, you can still find direct calls to a few deprecated functions of the ARP code (e.g., arp_find), but they are exceptions. The section "Common Interface Between L3 Protocols and Neighboring Protocols" in Chapter 27 discusses in detail the interface to the neighboring infrastructure.
Figure 26-5 shows the key parts of Linux's neighboring subsystems and the other parts of the kernel with which they interact. The L3 protocols interact with the neighboring layer via a common interface, which uses the right neighboring protocol (ARP, ND, etc.) depending on the L3 protocol that is asking for the service.[*]
When transmitting a packet, the following steps take place:
Note that dev_queue_xmit is called when the packet to transmit is ready to go, so if an L2 header is needed, the neighboring layer must add it before calling the function. Certain types of transmissionspoint-to-point connections, broadcasts, and multicastsdo not require any L2 layer header and therefore do not need an L3-to-L2 mapping; these transmissions are covered in the section "Special Cases." Other transmissions use a shared medium and therefore need an L2 header, either from the neighboring subsystem's cache or through a request issued by the neighboring subsystem to the network.
26.3.1. Neighboring Protocols
Two protocols are in use in IP networks today. The vast majority of systems use ARP with IPv4. A more general-purpose protocol called Neighbor Discovery (ND) was developed for IPv6. Other neighboring protocols are also implemented in the Linux kernel for use with proprietary networks, such as the one used by DECnet, but we will not cover them in this book due to their limited use.
Although ARP is considered an L3 protocol, the task has been moved into L4 by the designers of IPv6. As shown in Figure 26-6, the ND protocol is considered a part of the IPv6 implementation of the Internet Control Message Protocol (ICMP). This choice was based on years of experience with IPv4. It provides ND with several advantages, among them the opportunity to take advantage of L3 features such as IPsec encryption. The section "Improvements in ND (IPv6) over ARP (IPv4)" in Chapter 28 gives an overview of the key differences between ND and ARP.
Figure 26-6. Positions of the ARP/ND protocols in the network stack
As mentioned, Linux also provides a common infrastructure to reduce overhead and code replication for services that are very similar across all neighboring protocols. The generic neighboring infrastructure provides services that can be tailored by different protocols to suit their needs. Here are some of the services provided by the infrastructure to the protocols:
To let each protocol tailor the behavior of the neighboring subsystem, it defines a set of placeholder or virtual functions for which each protocol plugs in the functions it wants to use. This is similar to the way much of the Linux kernel allows customization. The neighboring layer also provides a bunch of tuning parameters that can be configured via user-space commands, /proc, or the protocol itself. Finally, the functions to access the cache are common to all of the protocols, but different protocols may use keys (addresses) of different sizes. Therefore, the infrastructure provides a generic way to define which type of key to use. Later chapters will cover all of these points in detail.
Each protocol can run and be configured independently from the others. The section "Protocol Initialization and Cleanup" in Chapter 27 shows how a neighboring protocol registers and unregisters itself with the kernel.