???????????????????????豸??????????????????·?????????dev_queue_xmit()

?????ú???????ù?????£?

/*
 * 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 ");
  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 ");
  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. ");
  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);
}
 


???????????????????dev->hard_start_xmit????????????????з?????

????????????http://blog.csdn.net/yming0221/article/details/7492423