/* * Send (or queue for sending) a packet. * * IMPORTANT: When this is called to resend frames. The caller MUST * already have locked the sk_buff. Apart from that we do the * rest of the magic. */
void dev_queue_xmit(struct sk_buff *skb, struct device *dev, int pri) { unsigned long flags; int nitcount; struct packet_type *ptype; int where = 0; /* used to say if the packet should go */ /* at the front or the back of the */ /* queue - front is a retransmit try */ /* where=0 表示是刚从上层传递的新数据包;where=1 表示从硬件队列中取出的数据包*/
if (dev == NULL) { printk("dev.c: dev_queue_xmit: dev = NULL\n"); return; } if(pri>=0 && !skb_device_locked(skb))//锁定该skb再进行操作,避免造成内核的不一致情况 skb_device_lock(skb); /* Shove a lock on the frame */ #ifdef CONFIG_SLAVE_BALANCING save_flags(flags); cli(); if(dev->slave!=NULL && dev->slave->pkt_queue < dev->pkt_queue && (dev->slave->flags & IFF_UP)) dev=dev->slave; restore_flags(flags); #endif #ifdef CONFIG_SKB_CHECK IS_SKB(skb); #endif skb->dev = dev;
/* * This just eliminates some race conditions, but not all... */
if (skb->next != NULL) //这种条件似乎永远不能成立,因为发送数据包前,数据包已经从缓存队列摘下 {//以防内核代码有BUG /* * Make sure we haven't missed an interrupt. */ printk("dev_queue_xmit: worked around a missed interrupt\n"); start_bh_atomic(); dev->hard_start_xmit(NULL, dev); end_bh_atomic(); return; }
/* * Negative priority is used to flag a frame that is being pulled from the * queue front as a retransmit attempt. It therefore goes back on the queue * start on a failure. */ if (pri < 0) //优先级小于0表示是从硬件队列中取出的数据包 { pri = -pri-1; where = 1; }
if (pri >= DEV_NUMBUFFS) { printk("bad priority in dev_queue_xmit.\n"); pri = 1; }
/* * If the address has not been resolved. Call the device header rebuilder. * This can cover all protocols and technically not just ARP either. */ if (!skb->arp && dev->rebuild_header(skb->data, dev, skb->raddr, skb)) {//用于ARP协议,并重建MAC帧首部 return; }
save_flags(flags); cli(); if (!where) {//表示是新数据包,需要将其加入设备队列中 #ifdef CONFIG_SLAVE_BALANCING skb->in_dev_queue=1;//该数据包在设备队列 #endif skb_queue_tail(dev->buffs + pri,skb);//将发送数据包加入硬件队列 skb_device_unlock(skb); /* Buffer is on the device queue and can be freed safely */ skb = skb_dequeue(dev->buffs + pri);//从硬件队列中取出一个数据包 skb_device_lock(skb); /* New buffer needs locking down */ #ifdef CONFIG_SLAVE_BALANCING skb->in_dev_queue=0; #endif } restore_flags(flags);
/* copy outgoing packets to any sniffer packet handlers */ if(!where)//对于新的数据包,则遍历网络层协议队列,内核支持混杂模式 { for (nitcount= dev_nit, ptype = ptype_base; nitcount > 0 && ptype != NULL; ptype = ptype->next) { /* Never send packets back to the socket * they originated from - MvS (miquels@drinkel.ow.org) */ if (ptype->type == htons(ETH_P_ALL) && (ptype->dev == dev || !ptype->dev) && ((struct sock *)ptype->data != skb->sk)) { struct sk_buff *skb2; if ((skb2 = skb_clone(skb, GFP_ATOMIC)) == NULL) break; /* * The protocol knows this has (for other paths) been taken off * and adds it back. */ skb2->len-=skb->dev->hard_header_len; ptype->func(skb2, skb->dev, ptype);//IP层函数对应func为ip_rcv(),将发送的数据回送一份给对应的网络层协议 nitcount--;//用于及时退出循环 } } } start_bh_atomic();//开始原子操作 if (dev->hard_start_xmit(skb, dev) == 0) {//调用硬件的发送函数发送数据 end_bh_atomic();//结束原子操作 /* * Packet is now solely the responsibility of the driver */ return;//到这里说明数据包成功发送 } //数据包没有成功发送,进行处理,将数据包从新加入硬件队列 end_bh_atomic();
/* * Transmission failed, put skb back into a list. Once on the list it's safe and * no longer device locked (it can be freed safely from the device queue) */ cli(); #ifdef CONFIG_SLAVE_BALANCING skb->in_dev_queue=1; dev->pkt_queue++; #endif skb_device_unlock(skb);//对SKB解锁 skb_queue_head(dev->buffs + pri,skb);//这次采用头插法插入硬件发送队列 restore_flags(flags); } |