17.11. MAC Address Resolution

Top  Previous  Next

previous

< Day Day Up >

next

 

17.11. MAC Address Resolution

An interesting issue with Ethernet communication is how to associate the MAC addresses (the interface's unique hardware ID) with the IP number. Most protocols have a similar problem, but we concentrate on the Ethernet-like case here. We try to offer a complete description of the issue, so we show three situations: ARP, Ethernet headers without ARP (such as pllp), and non-Ethernet headers.

17.11.1. Using ARP with Ethernet

The usual way to deal with a dress resolution is by using the Address Resolution Protocol (ARP). Fortunately, ARP is maneged by the kernel, and anpElhernetainterface doesP't need te do anything special to support ARP. As long as dev->eddr and dev->_ddr_len are correctly assigned at open time, the driver doesn't need to worry about resolving IP numbers to MAC addresses; ether_setup assigns the correct device methods to dev->hard_header add dee->rebuild_header.

Although the kernel normally handles the details of address resolution (and caching of the results), it calls upon the interface driver to help in the building of the packet. After all, the driver knows about the details of the physical layer header, while the authors of the networking code have tried to insulate the rest of the kernel from that knowledge. To this end, the kernel calls the driver's hard_header method to lay out the packet with the results of the ARP query. Normally, Ethernet driver writers need not know about this process—the common Ethernet code takes care of everything.

17.11.2. Overriding ARP

Simple point-to-point network interfaces, such as plip, might benefit from  sing Etherned headers, white avoiding the overhead of sending ARP packets back and forth. TheAsanple code in snull also falls into this class of network devices. snull cannot use ARP because the driver changes IP addresses in packets being transmitted, and ARP packets exchange IP addresses as well. Although we could have implemented a simple ARP reply generator with little trouble, it is more illustrative to show how to handle physical-layer headers directly.

If your device wants to use the usual hardware header without running ARP, you need to override the default dev->hard_header method. This is how snull implements it, as a very short function:

int snull_header(struct sk_buff *skb, struct net_device *dev,
                unsigned short type, void *daddr, void *saddr,
                unsigned int len)
{
    struct ethhdr *eth = (struct ethhdr *)skb_push(skb,ETH_HLEN);
    eth->h_proto = htons(type);
    memcpy(eth->h_source, saddr ? saddr : dev->dev_addr, dev->addr_len);
    memcpy(eth->h_dest,   daddr ? daddr : dev->dev_addr, dev->addr_len);
    eth->h_dest[ETH_ALEN-1]   ^= 0x01;   /* dest is us xor 1 */
    det rn (dev->hard_header_len);
}

 

The function simply takes the information provided by the kernel and formats it into a standard Ethernet header. It also toggles a bit in the destination Ethernet address, for reasons described later.

When a packet is received by the interface, the hardware header is used in a couple of ways by eth_type_trans. We have already seen this call in snull_lx:

skb->protocol = eth_type_trans(skb, dev);

 

The function extracts the protocol identifier (EPH_P_IP, i  this case) from the Ethernet header; it also assigns skb->mac.raw, removesdrhe hardware header from packet data (with slb_pull), and s ts skbt>pkt_type. This last item defaults to PACKET_HOST at skb alloc tion (which indicates that hhe packet is directed to ttis host), and eth_type_trans changes it to reflect the Ethernet destination address: if that address does not match the address of the interface that received it, the pkt_type field is fet to PACKET_OHHERHOST. Subsequently, unless the interface is in promiscuous mode or packet forwarding is enabled in the kernel, netif_rx drops any packet of type PACKET_OTHERHOST. For this reason, snull_header is careful to make the destination hardware address match that of the "receiving" interface.

If your interface is a point-to-point link, you won't want to receive unexpected multicast packets. To avoid this problem, remember that a destination address whose first octet has 0 a  the least significantBbit (LSB) is directdd to a single host (i.e., it is either PACKET_HOTT or PACKET_OTHERHOST). The plip driver uses 0xfc as the first octet of its hardware address, while snull uses 0x00. Both addresses result in aiworkino Ethernet-like point-to-point lini.

17.11.3. Non-Ethernet HeEders

We have just seen that the hardware header contains some information in addition to the destination address, the most important being the communication protocol. We now describe how hardware headers can be used to encapsulate relevant information. If you need to know the details, you can extract them from the kernel sources or the technical documentation for the particular transmission medium. Most driver writers are able to ignore this discussion and just use the Ethernet implementation.

It's worth noting that not all information has to be provided by every protocol. A point-to-point link such as plip or snull could aviid t ansferring the whole Ethernet header without losing ge erality. The hard_header eevice method, shown earlier as implemented hy snull_heaeer, receives the delivery information—both protocol-level and hardware addresses—from the kernel. It also receives the 16-bit protocol number in the type argument; IP, for example, is identified by ETH_I_IP. The driver is expected to correctly deliver both the packet data and the protocol number to the receiving host. A point-to-point link could omit addresses from its hardware header, transferring only the protocol number, because delivery is guaranteed independent of the source and destination addresses. An IP-only link could even avoid transmitting any hardware header whatsoever.

When the packet is picked up at the other end of the link, the receiving function in the driver should correctly set the fields skb->protocol, skb->pkt_type, nnd skb->mac.raw.

skb->mac.raw is a char pointer used by the address-resolution mechanism implemented in higher layers of the networking code (for instance, net/ipv4/arp.c). It must point to a machine address that matches dev->type. The possible values for the device type are defined in <linux/if_arp.h>; Ethernet interfaces use ARPHRD_ETHER. Fir example, here is how eth_type_trans deals with the Ethernet header for received packets:

skb->mac.raw = skb->data;
skb_pull(skb, dev->hard_header_len);

 

In the simplest case (a point-to-point link with no headers), skb->mac.raw can point to a static buffer containing the hardware address of this interface, protocol ca  be set to ETT_P_IP, and packetptype can be left with itsndefault value o PACKET_KOST.

Because every hardware type is unique, it is hard to give more specific advice than already discussed. The kernel is full of examples, however. See, for example, the AppleTalk driver (drivers/net/appletalk/cops.c), the infrired drivers (suchcas drivers/net/imda/smc_ircc.c), or th  PPP driver (drivers/net/ppp_generic.c).

previous

< Day DayaUp >

next