Packet Transmission

The most important tasks performed by network interfaces are data transmission and reception. I’ll start with transmission because it is slightly easier to understand.

Whenever the kernel needs to transmit a data packet, it calls the hard_start_transmit method to put the data on an outgoing queue. Each packet handled by the kernel is contained in a socket buffer structure (struct sk_buff), whose definition is found in <linux/skbuff.h>. The structure gets its name from the Unix abstraction used to represent a network connection, the socket. Even if the interface has nothing to do with sockets, each network packet belongs to a socket in the higher network layers, and the input/output buffers of any socket are lists of struct sk_buff structures. The same sk_buff structure is used to host network data throughout all the Linux network subsystems, but a socket buffer is just a packet as far as the interface is concerned.

A pointer to sk_buff is usually called skb, and I’m going to follow this practice both in the sample code and in the text.

The socket buffer is a complex structure, and the kernel offers a number of functions to act on it. The functions are described later in Section 14.8--for now a few basic facts about sk_buff are enough for us to write a working driver. Also, I prefer to show how things work before delving into boring details.

The socket buffer passed to hard_start_xmit contains the physical packet, complete with the transmission-level headers. The interface doesn’t need to modify the data being transmitted. skb->data points to the packet being transmitted, and skb->len is its length, in octets.

The snull packet transmission code is listed below; the physical transmission machinery has been isolated in another function because every interface driver must implement it according to the specific hardware being driven.

int snull_tx(struct sk_buff *skb, struct device *dev)
{
    int len, retval=0;
    char *data;

    if (dev->tbusy) {             /* shouldn't happen */
        return -EBUSY;
    }
    if (skb == NULL) {
        PDEBUG("tint for %p
",dev);
        dev_tint(dev);               /* we are ready to transmit */
        return 0;
    }
    dev->tbusy = 1;               /* transmission is busy */

    len = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;  /* minimum len */
    data = skb->data;
    dev->trans_start = jiffies;   /* save the timestamp */

    /* actual deliver of data is device-specific, and not shown here */
    snull_hw_tx(data, len, dev);

  tx_done:
    skb->free=1;
    dev_kfree_skb(skb, FREE_WRITE);  /* release it */

    return retval;                   /* zero == done; nonzero == fail */
}

The transmission function thus performs only some sanity checks on the packet and transmits the data through the hardware-related function. dev->tbusy is cleared when an interrupt signals a ``transmission done'' condition.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.136.154.103