嵌入式linux中文站在线图书

Previous Page
Next Page

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.[*]

[*] The figure does not include DECnet and ATM, because they are not covered in this book.

When transmitting a packet, the following steps take place:

  1. The routing subsystem of the local host selects the L3 destination address (the next hop).

    Figure 26-5. The big picture

  2. If according to the routing table, this hop is on the same network (if, that is, the next hop is a neighbor), the neighboring layer resolves the destination's L3 address to its L2 address. This association is cached for future use. Thus, if one application sends several packets of data in a short amount of time to another application, the neighboring protocol is used only once, to send the first packet.

  3. Eventually, a function such as dev_queue_xmit (described in Chapter 11) takes care of the transmission, handing the packet to the Traffic Control or Quality of Service (QoS) layer. Although Figure 26-5 shows only dev_queue_xmit, the neighboring layer can actually invoke other functions as well (mostly wrappers around dev_queue_xmit), as we will see later in this chapter.

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:

  • A per-protocol cache to store the results of L3-to-L2 translations.

  • Functions to add, remove, change, and look up a specific translation entry in the cache. Because the lookup function influences the performance of the system most of all, it must be fast.

  • An aging mechanism for the entries in the per-protocol cache.

  • A choice of policies to follow when there is a request for a new translation entry to be created in the cache, and the cache is full.

  • A per-neighbor request queue. When a packet is ready to be sent and the L2 address is not already in the cache, the packet must be buffered until a solicitation request is sent and the reply is received. See the section "Queuing" in Chapter 27.

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.


Previous Page
Next Page