This paper analyzes Linux Kernel 1.2.13 based on
Original works, reproduced please mark http://blog.csdn.net/yming0221/article/details/7555870
See column, Address http://blog.csdn.net/column/details/linux-kernel-net.html
Shuming
Note: In the title, "(UP)", "(bottom)" means that the analysis process is based on the delivery direction of the packet: "(top)" means that the analysis is parsed from the bottom up, and "(bottom)" indicates that the analysis is parsed from the top down.
In the blog post Linux kernel--Network stack Implementation Analysis (iii)--The driver layer (link layer) (above) on the network device structure, network device initialization functions such as a preliminary understanding, and lists the device's send and receive functions.
The device interface layer calls the function device driver layer Ei_start_xmit () function to send data, and there is no detailed analysis.
[CPP]View Plaincopy
- static int ei_start_xmit (struct sk_buff *skb, struct device *dev)
- {
- int e8390_base = dev->base_addr;
- struct Ei_device *ei_local = (struct Ei_device *) dev->priv;//Remove the private data of the network card device, and the specific NIC model, in the Ethdev_init () function has allocated space
- int length, send_length;
- unsigned long flags;
- /*
- * We normally shouldn ' t be called if dev->tbusy are set, but the
- * Existing code does anyway. If It has been too long since the
- * Last Tx, we assume the board have died and kick it.
- */
- if (dev->tbusy) {/* timeouts, just like the 8003 driver. */
- ........................................
- ........................................
- }
- /* Sending a NULL SKB means some higher layer thinks we ' ve missed an
- Tx-done interrupt. Caution:dev_tint () handles the CLI ()/sti ()
- itself. */
- if (SKB = = NULL) {//The condition does not seem to occur, which is used to handle bugs in the kernel
- Dev_tint (dev);//Send all cached packets in the device
- return 0;
- }
- Length = skb->len;
- if (skb->len <= 0)
- return 0;
- Save_flags (flags);
- CLI ();
- /* Block a timer-based transmit from overlapping. */
- if ((Set_bit (0, (void*) &dev->tbusy)! = 0) | | ei_local->irqlock) {
- PRINTK ("%S:TX access conflict. irq=%d lock=%d tx1=%d tx2=%d last=%d\n ",
- Dev->name, Dev->interrupt, Ei_local->irqlock, EI_LOCAL->TX1,
- EI_LOCAL->TX2, EI_LOCAL->LASTTX);
- Restore_flags (flags);
- return 1;
- }
- /* Mask interrupts from the Ethercard. */
- Outb (0x00, e8390_base + EN0_IMR);
- Ei_local->irqlock = 1;
- Restore_flags (flags);
- Send_length = Eth_zlen < length? Length:eth_zlen;
- if (Ei_local->pingpong) {
- int output_page;
- if (ei_local->tx1 = = 0) {
- Output_page = ei_local->tx_start_page;
- EI_LOCAL->TX1 = Send_length;
- if (ei_debug && ei_local->tx2 > 0)
- PRINTK ("%s:idle transmitter tx2=%d, lasttx=%d, txing=%d.\n",
- Dev->name, EI_LOCAL->TX2, EI_LOCAL->LASTTX,
- ei_local->txing);
- } else if (ei_local->tx2 = = 0) {
- Output_page = ei_local->tx_start_page + 6;
- EI_LOCAL->TX2 = Send_length;
- if (ei_debug && ei_local->tx1 > 0)
- PRINTK ("%s:idle transmitter, tx1=%d, lasttx=%d, txing=%d.\n",
- Dev->name, EI_LOCAL->TX1, EI_LOCAL->LASTTX,
- ei_local->txing);
- } else {/* We should never get here. */
- if (Ei_debug)
- PRINTK ("%s:no Tx buffers free. irq=%d tx1=%d tx2=%d last=%d\n ",
- Dev->name, Dev->interrupt, EI_LOCAL->TX1,
- EI_LOCAL->TX2, EI_LOCAL->LASTTX);
- Ei_local->irqlock = 0;
- Dev->tbusy = 1;
- Outb_p (Enisr_all, e8390_base + EN0_IMR);
- return 1;
- }
- Ei_block_output (Dev, length, skb->data, output_page);
- if (! ei_local->txing) {
- ei_local->txing = 1;
- Ns8390_trigger_send (Dev, send_length, output_page);
- Dev->trans_start = jiffies;
- if (output_page = = ei_local->tx_start_page)
- EI_LOCAL->TX1 =-1, Ei_local->lasttx =-1;
- Else
- EI_LOCAL->TX2 =-1, Ei_local->lasttx =-2;
- } else
- ei_local->txqueue++;
- Dev->tbusy = (ei_local->tx1 && ei_local->tx2);
- } else {/* No pingpong, just a single Tx buffer. */
- Ei_block_output (Dev, length, skb->data, ei_local->tx_start_page);
- ei_local->txing = 1;
- Ns8390_trigger_send (Dev, send_length, ei_local->tx_start_page);
- Dev->trans_start = jiffies;
- Dev->tbusy = 1;
- }
- /* Turn 8390 interrupts back on. */
- Ei_local->irqlock = 0;
- Outb_p (Enisr_all, e8390_base + EN0_IMR);
- DEV_KFREE_SKB (SKB, free_write);
- return 0;
One of the Dev_tint () functions is to send all of the data from all the cache queues in the device to Dev_queue_xmit ().
[CPP]View Plaincopy
- /*
- * This routine was called when an device driver (i.e. an
- * interface) is transmit a packet.
- */
- Function: Traverse the buffer queue of the device, send data to all packets called dev_queue_xmit () function
- void Dev_tint (struct device *dev)
- {
- int i;
- struct Sk_buff *skb;
- unsigned long flags;
- Save_flags (flags);
- /*
- * Work the queues in priority order
- */
- for (i = 0;i < dev_numbuffs; i++)
- {
- /*
- * Pull packets from the queue
- */
- CLI ();
- while ((Skb=skb_dequeue (&dev->buffs[i))!=null)
- {
- /*
- * Stop anyone freeing the buffer while we retransmit it
- */
- Skb_device_lock (SKB);
- Restore_flags (flags);
- /*
- * Feed them to the output stage and if it fails
- * Indicate they re-queue at the front.
- */
- Dev_queue_xmit (skb,dev,-i-1);//Pay attention to the calculation of the priority, in the function dev_queue_xmit () Priority if <0 is calculated pri=-pri-1=-(-i-1) -1=i,
- The purpose of this is to get the correct where value in the function (Dev_queue_xmit ())
- /*
- * If We can take no further then stop here.
- */
- if (dev->tbusy)
- Return
- CLI ();
- }
- }
- Restore_flags (flags);
- }
The driving layer is strictly not the content of the kernel network stack, and the hardware is closely related, not to mention this network card hardware equipment may have been used, there is no detailed analysis, if you are interested in network card driver can look at the analysis of the Arm-linux under the DM9000 network card driver analysis, links as follows:
- Arm-linux Drive analysis of driver--dm9000 NIC (i)
- Driver analysis of Arm-linux Drive--dm9000 NIC (ii)
- Driver analysis of Arm-linux Drive--dm9000 network card (iii)
- Arm-linux Driving analysis of--dm9000 network card driver (four)
Linux kernel--Network stack Implementation Analysis (11)--Driver layer (bottom)