原文出处:

http://blog.chinaunix.net/uid-23629988-id-371188.html

http://blog.chinaunix.net/uid-23629988-id-439718.html

http://blog.chinaunix.net/uid-23629988-id-1619346.html

 

IP报文的发送的入口函数是ip_output,这个函数一般是挂载到dst->output上。 在发送IP报文时,都需要进行路由查找,得到dst,然后通过dst->output来发送数据包。对于IPv4来说,一般情况下,dst->output都是指向ip_output。

  1. intip_output(struct sk_buff*skb)

  2. {

  3. /* 得到出口的dev */

  4. struct net_device*dev=skb_dst(skb)->dev;

/* 增加统计信息 */
  1. IP_UPD_PO_STATS(dev_net(dev),IPSTATS_MIB_OUT,skb->len);

  1. skb->dev=dev;

  2. skb->protocol=htons(ETH_P_IP);

/* 进入netfilter的POSTROUTING链 */
  1. return NF_HOOK_COND(NFPROTO_IPV4,NF_INET_POST_ROUTING,skb,NULL,dev,

  2. ip_finish_output,

  3. !(IPCB(skb)->flags&IPSKB_REROUTED));

  4. }

进入ip_finish_output
  1. staticintip_finish_output(struct sk_buff*skb)

  2. {

  3. #ifdefined(CONFIG_NETFILTER)&&defined(CONFIG_XFRM)

  4. /*Policy lookup after SNAT yielded a new policy*/

  5. if(skb_dst(skb)->xfrm!=NULL){

  6. IPCB(skb)->flags|=IPSKB_REROUTED;

  7. return dst_output(skb);

  8. }

  9. #endif

  10. /* 处理需要IP分片的情况 */

  11. if(skb->len>ip_skb_dst_mtu(skb)&&!skb_is_gso(skb))

  12. return ip_fragment(skb,ip_finish_output2);

  13. /* 不需要IP分片, 我们就看这种一般情况 */

  14. else

  15. return ip_finish_output2(skb);

  16. }

进入ip_finish_output2
  1. static inlineintip_finish_output2(struct sk_buff*skb)

  2. {

  3. struct dst_entry*dst=skb_dst(skb);

  4. struct rtable*rt=(struct rtable*)dst;

  5. struct net_device*dev=dst->dev;

  6. unsignedinthh_len=LL_RESERVED_SPACE(dev);

/* 根据路由的类型,增加统计信息 */
  1. if(rt->rt_type==RTN_MULTICAST){

  2. IP_UPD_PO_STATS(dev_net(dev),IPSTATS_MIB_OUTMCAST,skb->len);

  3. }elseif(rt->rt_type==RTN_BROADCAST)

  4. IP_UPD_PO_STATS(dev_net(dev),IPSTATS_MIB_OUTBCAST,skb->len);


  5. /*Be paranoid,rather than too clever.*/

  6. if(unlikely(skb_headroom(skb)<hh_len&&dev->header_ops)){

  7. /* 

  8. skb的首部空间不足,无法保存l2层的硬件地址。

  9. 这时,需要重新分配一个更大bufer。

  10. */

  11. struct sk_buff*skb2;


  12. skb2=skb_realloc_headroom(skb,LL_RESERVED_SPACE(dev));

  13. if(skb2==NULL){

  14. kfree_skb(skb);

  15. return-ENOMEM;

  16. }

  17. if(skb->sk)

  18. skb_set_owner_w(skb2,skb->sk);

  19. kfree_skb(skb);

  20. skb=skb2;

  21. }

/* dst有L2层硬件地址的cache*/
  1. if(dst->hh)

  2. return neigh_hh_output(dst->hh,skb);

  3. /* 

  4. dst没有L2层地址的cache,需要调用neighbour子系统的output进行发送。

  5. */

  6. elseif(dst->neighbour)

  7. return dst->neighbour->output(skb);


/* 
正常情况下,不会到达此处
*/
  1. if(net_ratelimit())

  2. printk(KERN_DEBUG"ip_finish_output2: No header cache and no neighbour!\n");

  3. kfree_skb(skb);

  4. return-EINVAL;

  5. }

在IPv4中,neighbour subsystem使用的是arp,所以一般情况下,dst->neighbour->outpu指向的是arp_generic_ops->neigh_resolve_output(这是需要解析L2硬件地址的情况,其他情况本文暂不考虑)。

通常,neighbour subsystem使用的operation都是arp_generic_ops(在arp.c中定义,且还有其他的同类型变量,用于不同情况)。

下面看neigh_resolve_output
  1. int neigh_resolve_output(struct sk_buff *skb)

  2. {

  3. struct dst_entry *dst = skb_dst(skb);

  4. struct neighbour *neigh;

  5. int rc = 0;


  6. if(!dst ||!(neigh = dst->neighbour))

  7. goto discard;

  1. __skb_pull(skb, skb_network_offset(skb));

/* 判断是否发送neigh请求,对于IPv4来说就是arp request */
  1. if(!neigh_event_send(neigh, skb)){

  2. /* 无需发送neigh请求, 可以直接从dev中获得 */

  3. interr;

  4. struct net_device *dev = neigh->dev;

/* 从dev中获得L2硬件地址*/
  1. if(dev->header_ops->cache &&!dst->hh){

  2. write_lock_bh(&neigh->lock);

  3. if(!dst->hh)

  4. neigh_hh_init(neigh, dst, dst->ops->protocol);

  5. err= dev_hard_header(skb, dev, ntohs(skb->protocol),

  6. neigh->ha,NULL, skb->len);

  7. write_unlock_bh(&neigh->lock);

  8. }else{

  9. read_lock_bh(&neigh->lock);

  10. err= dev_hard_header(skb, dev, ntohs(skb->protocol),

  11. neigh->ha,NULL, skb->len);

  12. read_unlock_bh(&neigh->lock);

  13. }

  14. if(err>= 0)

  15. rc = neigh->ops->queue_xmit(skb); //发送数据包

  16. else

  17. goto out_kfree_skb;

  18. }

  19. out:

  20. return rc;

  21. discard:

  22. NEIGH_PRINTK1("neigh_resolve_output: dst=%p neigh=%p\n",

  23. dst, dst ? dst->neighbour :NULL);

  24. out_kfree_skb:

  25. rc =-EINVAL;

  26. kfree_skb(skb);

  27. goto out;

  28. }

在neigh_event_send中,实际上并不立刻执行发送neigh 请求,而是将这个数据包加到一个队列中__skb_queue_tail(&neigh->arp_queue, skb);,即语句中的arp_queue。
然后通过neighbour subsystem的定时处理函数neigh_timer_handler来处理这个队列。

neigh_timer_handler主要是neighbour状态的处理和变迁,本文并将其列为重点,留作以后分析学习。对于IPv4来说,当没有对应的neighbour信息时,会先调用arp_solicit发送ARP请求,当收到ARP包时,由arp_process进行处理(可参见我前面的博文 TCP/IP学习(33)——ARP数据包的处理流程分析,  http://blog.chinaunix.net/space.php?uid=23629988&do=blog&id=335262 )。当收到ARP reply时,会调用neigh_update,当neighbour的状态为valid且neighbour的arp_queue不为空时,会调用n1->output将之前的skb数据包发送。

  1. while(neigh->nud_state & NUD_VALID &&

  2. (skb = __skb_dequeue(&neigh->arp_queue))!=NULL){

  3. struct neighbour *n1 = neigh;

  4. write_unlock_bh(&neigh->lock);

  5. /*On shaper/eql skb->dst->neighbour != neigh :(*/

  6. if(skb_dst(skb)&& skb_dst(skb)->neighbour)

  7. n1 = skb_dst(skb)->neighbour;

  8. n1->output(skb);

  9. write_lock_bh(&neigh->lock);

  10. }

当解析neighbour信息成功时,这个n1->output是指向neigh_connected_output,并最终调用dev_queue_xmit->__dev_xmit_skb将数据包添加到dev的queue中,并发送数据包。

当发送完毕时,引发NET_TX_SOFTIRQ软中断,进行下半部处理,如释放已发送的数据包skb的内存等。

本文还遗留了不少细节有待完善,如neighbour subsystem和发送软中断等。

 

上次学习IP包的发送流程时,学习到了dev_queue_xmit这个函数。
  1. intdev_queue_xmit(struct sk_buff*skb)

  2. {

  3. struct net_device*dev=skb->dev;

  4. struct netdev_queue*txq;

  5. struct Qdisc*q;

  6. intrc=-ENOMEM;


  7. /*Disable soft irqsforvarious locks below.Also

  8. *stops preemptionforRCU.

  9. */

  10. rcu_read_lock_bh();

/* 得到发送队列 */
  1. txq=dev_pick_tx(dev,skb);

  2. q=rcu_dereference_bh(txq->qdisc);


  3. #ifdef CONFIG_NET_CLS_ACT

  4. skb->tc_verd=SET_TC_AT(skb->tc_verd,AT_EGRESS);

  5. #endif

  6. if(q->enqueue){

  7. /* 一般的dev都应该进入这里 */

  8. rc=__dev_xmit_skb(skb,q,dev,txq);

  9. goto out;

  10. }

...... ......
  1. }

进入函数__dev_xmit_skb
  1. static inline int __dev_xmit_skb(struct sk_buff *skb, struct Qdisc *q,

  2. struct net_device *dev,

  3. struct netdev_queue *txq)

  4. {

  5. spinlock_t *root_lock = qdisc_lock(q);

  6. bool contended = qdisc_is_running(q);

  7. int rc;


  8. /*

  9. * Heuristic to force contended enqueues to serialize on a

  10. * separate lock before trying toget qdisc main lock.

  11. * This permits __QDISC_STATE_RUNNING owner toget the lock more often

  12. *and dequeue packets faster.

  13. */

  14. if(unlikely(contended))

  15. spin_lock(&q->busylock);


  16. spin_lock(root_lock);

  17. if(unlikely(test_bit(__QDISC_STATE_DEACTIVATED,&q->state))){

  18. /* 该quque的状态为非活动的,drop该数据包 */

  19. kfree_skb(skb);

  20. rc = NET_XMIT_DROP;

  21. }elseif((q->flags & TCQ_F_CAN_BYPASS)&&!qdisc_qlen(q)&&

  22. qdisc_run_begin(q)){

/* 
这部分代码,从注释上看,似乎选中的queue是一个保留的工作queue。
想来也是非正常路径,暂时保留不看。
*/
  1. /*

  2. * This is a work-conserving queue; there are no old skbs

  3. * waiting to be sent out;and the qdisc isnot running -

  4. * xmit the skb directly.

  5. */

  6. if(!(dev->priv_flags & IFF_XMIT_DST_RELEASE))

  7. skb_dst_force(skb);

  8. __qdisc_update_bstats(q, skb->len);

  9. if(sch_direct_xmit(skb, q, dev, txq, root_lock)){

  10. if(unlikely(contended)){

  11. spin_unlock(&q->busylock);

  12. contended =false;

  13. }

  14. __qdisc_run(q);

  15. }else

  16. qdisc_run_end(q);


  17. rc = NET_XMIT_SUCCESS;

  18. }else{

/* 正常路径 */

/* 确保dst被引用,防止被其他模块释放 */
  1. skb_dst_force(skb);

  2. /* 将数据包加入到queue中 */

  3. rc = qdisc_enqueue_root(skb, q);

/* 如果queue不是运行状态,将其置为运行状态 */
  1. if(qdisc_run_begin(q)){

  2. if(unlikely(contended)){

  3. spin_unlock(&q->busylock);

  4. contended =false;

  5. }

  6. __qdisc_run(q);

  7. }

  8. }

  9. spin_unlock(root_lock);

  10. if(unlikely(contended))

  11. spin_unlock(&q->busylock);

  12. return rc;

  13. }

将数据包加入队列的函数是通过q->enque的回调实现的,那么这个enque的回调钩子函数是何时注册上的呢?
请看dev_activate,用于激活网卡。
  1. void dev_activate(struct net_device *dev)

  2. {

  3. int need_watchdog;


  4. /* No queueing discipline is attached to device;

  5. create default one i.e. pfifo_fast for devices,

  6. which need queueing and noqueue_qdisc for

  7. virtual interfaces

  8. */

/*
当没有指定queueing discipline时,就使用默认的discipline
*/

  1. if(dev->qdisc ==&noop_qdisc)

  2. attach_default_qdiscs(dev);


  3. ...... ...... 

  4. }

这里不列出attach_default_qdiscs的代码了,一般情况下,网卡只有一个queue时,这个默认的discipline为
  1. struct Qdisc_ops pfifo_fast_ops __read_mostly ={

  2. .id ="pfifo_fast",

  3. .priv_size = sizeof(struct pfifo_fast_priv),

  4. .enqueue = pfifo_fast_enqueue,

  5. .dequeue = pfifo_fast_dequeue,

  6. .peek = pfifo_fast_peek,

  7. .init = pfifo_fast_init,

  8. .reset = pfifo_fast_reset,

  9. .dump = pfifo_fast_dump,

  10. .owner = THIS_MODULE,

  11. };

那么对于我们来说,就确定了默认的要是一般情况下的enque函数为pfifo_fast_enqueue。
  1. static int pfifo_fast_enqueue(struct sk_buff *skb, struct Qdisc* qdisc)

  2. {

  3. if(skb_queue_len(&qdisc->q)< qdisc_dev(qdisc)->tx_queue_len){

  4. int band = prio2band[skb->priority & TC_PRIO_MAX];

  5. struct pfifo_fast_priv *priv = qdisc_priv(qdisc);

  6. struct sk_buff_head *list = band2list(priv, band);


  7. priv->bitmap |=(<< band);

  8. qdisc->q.qlen++;

  9. return __qdisc_enqueue_tail(skb, qdisc, list);

  10. }


  11. return qdisc_drop(skb, qdisc);

  12. }

上面就是 __dev_xmit_skb中调用的q->enque的代码,将数据包加入到了dev->_tx所对应的队列中。
然后我还需要回到__dev_xmit_skb中,在加数据包加入到队列中后。要保证qdisc为运行态。
  1. rc = qdisc_enqueue_root(skb, q);

  2. if(qdisc_run_begin(q)){

  3. if(unlikely(contended)){

  4. spin_unlock(&q->busylock);

  5. contended =false;

  6. }

  7. __qdisc_run(q);

  8. }

查看__qdisc_run的代码。
  1. void __qdisc_run(struct Qdisc *q)

  2. {

  3. unsigned long start_time = jiffies;


/*
qdisc_restart中发送了数据包。
这里是循环发送,直至qdisc_restart返回0
或者其它进程请求CPU或发送已运行比较长的时间(1jiffie)则也跳出循环体。
*/

  1. while(qdisc_restart(q)){

  2. /*

  3. * Postpone processing if

  4. * 1. another process needs the CPU;

  5. * 2. we've been doing it for too long.

  6. */

  7. if(need_resched()|| jiffies != start_time){

  8. /*

  9. 需要以后再执行发送动作(利用softirq)

  10. */

  11. __netif_schedule(q);

  12. break;

  13. }

  14. }


  15. qdisc_run_end(q);

  16. }

进入qdisc_restart->sch_direct_xmit,该函数用于发送一个数据包
  1. int sch_direct_xmit(struct sk_buff *skb, struct Qdisc *q,

  2. struct net_device *dev, struct netdev_queue *txq,

  3. spinlock_t *root_lock)

  4. {

  5. int ret = NETDEV_TX_BUSY;


  6. /*And release qdisc */

  7. spin_unlock(root_lock);


  8. HARD_TX_LOCK(dev, txq, smp_processor_id());

  9. //设备没有被停止,且发送队列没有被冻结

  10. if(!netif_tx_queue_stopped(txq)&&!netif_tx_queue_frozen(txq))

  11. ret = dev_hard_start_xmit(skb, dev, txq)//发送数据包


  12. HARD_TX_UNLOCK(dev, txq);


  13. spin_lock(root_lock);


  14. if(dev_xmit_complete(ret)){

  15. /* Driver sent out skb successfully or skb was consumed */

  16. //发送成功,返回qdisc新的队列产的

  17. ret = qdisc_qlen(q);

  18. }elseif(ret == NETDEV_TX_LOCKED){

  19. /* Driver try lock failed */

  20. //锁冲突

  21. ret = handle_dev_cpu_collision(skb, txq, q);

  22. }else{

  23. /* Driver returned NETDEV_TX_BUSY - requeue skb */

  24. if(unlikely (ret != NETDEV_TX_BUSY && net_ratelimit()))

  25. printk(KERN_WARNING "BUG %s code %d qlen %d\n",

  26. dev->name, ret, q->q.qlen);

//设备繁忙,重新调度发送(利用softirq)
  1. ret = dev_requeue_skb(skb, q);

  2. }


  3. if(ret &&(netif_tx_queue_stopped(txq)||

  4. netif_tx_queue_frozen(txq)))

  5. ret = 0;


  6. return ret;

  7. }

到此,本文长度已经不短了,先就此结尾。IP包的发送流程比接收流程要复杂得多,估计还需一篇博文才能基本走完。

 

前文已经学习到了sch_direct_xmit函数,下面进入下一级函数。
  1. int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,

  2. struct netdev_queue *txq)

  3. {

  4. const struct net_device_ops *ops = dev->netdev_ops;

  5. int rc = NETDEV_TX_OK;


  6. if(likely(!skb->next)){

/* skb->next为null,即只发送一个skb */

  1. if(!list_empty(&ptype_all))

  2. dev_queue_xmit_nit(skb, dev)//ptype_all上的协议处理,如tcpdump


  3. /*

  4. *If device doesnt need skb->dst, release it rightnowwhile

  5. * its hot in this cpu cache

  6. */

  7. /* device 不需要dst */

  8. if(dev->priv_flags & IFF_XMIT_DST_RELEASE)

  9. skb_dst_drop(skb);


/* 使该skb不属于任何一个socket */
  1. skb_orphan_try(skb);


  2. if(netif_needs_gso(dev, skb)){

  3. /* 需要scatter gather功能 */

/*
从注释上看,是进行perform protocol segmentation on skb。
但是实际工作,目前我不清楚
*/
  1. if(unlikely(dev_gso_segment(skb)))

  2. goto out_kfree_skb;

  3. if(skb->next)

  4. goto gso;

  5. }else{

  6. //不需要scatter gather

/*
如需要连续内存,则将skb内存线性化,即连续内存 
*/
  1. if(skb_needs_linearize(skb, dev)&&

  2. __skb_linearize(skb))

  3. goto out_kfree_skb;


  4. /*If packet isnot checksummed and device does not

  5. * support checksumming for this protocol, complete

  6. * checksumming here.

  7. */

  8. if(skb->ip_summed == CHECKSUM_PARTIAL){

  9. /* 计算checksum */

  10. skb_set_transport_header(skb, skb->csum_start -

  11. skb_headroom(skb));

  12. if(!dev_can_checksum(dev, skb)&&

  13. skb_checksum_help(skb))

  14. goto out_kfree_skb;

  15. }

  16. }


/* 发送skb数据 */
  1. rc = ops->ndo_start_xmit(skb, dev);

  2. if(rc == NETDEV_TX_OK)

  3. txq_trans_update(txq);

  4. return rc;

  5. }


  6. gso:

  7. /* 循环发送数据包 */

  8. do{

  9. struct sk_buff *nskb = skb->next;


  10. skb->next= nskb->next;

  11. nskb->next=NULL;


  12. /*

  13. *If device doesnt need nskb->dst, release it rightnowwhile

  14. * its hot in this cpu cache

  15. */

  16. if(dev->priv_flags & IFF_XMIT_DST_RELEASE)

  17. skb_dst_drop(nskb);


  18. rc = ops->ndo_start_xmit(nskb, dev);

  19. if(unlikely(rc != NETDEV_TX_OK)){

  20. if(rc &~NETDEV_TX_MASK)

  21. goto out_kfree_gso_skb;

  22. nskb->next= skb->next;

  23. skb->next= nskb;

  24. return rc;

  25. }

  26. txq_trans_update(txq);

  27. if(unlikely(netif_tx_queue_stopped(txq)&& skb->next))

  28. return NETDEV_TX_BUSY;

  29. }while(skb->next);


  30. out_kfree_gso_skb:

  31. if(likely(skb->next==NULL))

  32. skb->destructor = DEV_GSO_CB(skb)->destructor;

  33. out_kfree_skb:

  34. kfree_skb(skb);

  35. return rc;

  36. }

继续下一个函数,ops->ndo_start_xmit。又是一个回调函数,这个回调函数由驱动所决定。以e1000_main.c为例,
  1. static const struct net_device_ops e1000_netdev_ops ={

  2. .ndo_open = e1000_open,

  3. .ndo_stop = e1000_close,

  4. .ndo_start_xmit = e1000_xmit_frame,

  5. .ndo_get_stats = e1000_get_stats,

  6. .ndo_set_rx_mode = e1000_set_rx_mode,

  7. .ndo_set_mac_address = e1000_set_mac,

  8. .ndo_tx_timeout = e1000_tx_timeout,

  9. .ndo_change_mtu = e1000_change_mtu,

  10. .ndo_do_ioctl = e1000_ioctl,

  11. .ndo_validate_addr = eth_validate_addr,


  12. .ndo_vlan_rx_register = e1000_vlan_rx_register,

  13. .ndo_vlan_rx_add_vid = e1000_vlan_rx_add_vid,

  14. .ndo_vlan_rx_kill_vid = e1000_vlan_rx_kill_vid,

  15. #ifdef CONFIG_NET_POLL_CONTROLLER

  16. .ndo_poll_controller = e1000_netpoll,

  17. #endif

  18. };

从这里可以看出,对于e1000_main来说,该回调函数为e1000_xmit_frame。这个涉及到驱动层,一般都与硬件相关,在此就不继续探讨了。

那么现在,一个基本的IP包发送流程,基本上浏览完毕。小小的总结一下,当linux发送IP数据包时,数据包有可能是立刻发送出去,也有可能由下一次的软中断发送。