驱动的发送接收流程分析

来源:互联网 发布:大数据导论 教学大纲 编辑:程序博客网 时间:2024/04/29 09:56

查询方式(发送)

netpoll_poll_dev实际上调用netpoll_send_skb_on_dev,后者依次完成以下工作:

1、如果该接口上没有待输出的数据包,则直接调用底层驱动的ndo_start_xmit方法发出数据包,此过程重复1个时钟节拍,操作间隔为50us;

2、如果在第一步中每一次尝试发出数据包没有获得成功的话,则调用netpoll_poll_dev去处理该接口上的其他查询任务;

3、如果该接口上已经有待处理的数据包或者当前的数据包没有成功的发出去,则把当前的数据包加入到npinfo的txp队列尾部,然后调度queue_process去处理那些没有发出去的数据包;

注意:netpoll_send_skb_on_dev直接发送数据包和queue_process发送数据包不能同时运行。

queue_process函数实际上就是持续发出npinfo的txp队列上的数据包直到以下条件满足:

1、如果SKB所在的传输队列被停掉或者底层网卡已经无法再继续处理数据包时,则延时调度queue_process函数在至少HZ/10时间以后再来处理剩余的数据包;

2、如果所有的数据包都顺利的处理完成的话,则停止该工作的运行;


netpoll_poll_dev完成的工作包括:

1、调用底层驱动函数的ndo_poll_controller方法查看网卡的收发情况以及是否出错,然后进行相应的处理;

2、执行所有在该接口上注册的NAPI任务;

3、处理arp发送任务,如果是从设备,则把该接口上的arp包转移到主设备上;如果是主设备,则调用arp_reply把数据包发出去;

4、释放当前CPU上已经发出去的数据包所占用的内存空间;


查询方式(接收)

netpoll_receive_skb经过层层解封装最终调用__netpoll_rx函数完成实际的处理工作;

1、如果收到的是ARP包,则放到npinfo->arp_tx队列尾部,然后完成处理返回,刚收到的ARP包会在上诉发送过程中进行arp_reply;

2、如果不是UDP包、不是本机的包或者已经有其他部分在处理该包,则不处理直接返回;

3、调用注册到该接口上的所有netpoll的rx_hook方法处理接收到的数据包;

4、释放掉已处理过的数据包所占用的内存;


要使用查询方式则必须调用__netpoll_setup或netpoll_setup注册查询模块;


中断方式(发送)

1、首先应该调用netif_start_queue函数使能传输队列的发送;

2、中断产生以后,检查是否传输通道缓冲环有空闲,则调用netif_wake_queue函数把传输通道Qdisc加入到当前CPU的Qdisc待处理队列中,然后唤醒相关的软中断;

3、一旦轮到软中断执行时,则net_tx_action会被执行,该函数主要完成2个功能,一是释放已经发送出去的数据包所占用的内存资源;二是运行等待的Qdisc队列,每个Qdsic依次从相应的发送队列中取出数据包发给底层的网卡驱动直到配额用完或者网卡已经无法继续发送数据帧为止;

4、在中断中还应该检查已完成发送的数据包,并调用dev_kfree_skb_irq函数让net_tx_action去释放内存;


中断方式(接收)

1、通过netif_napi_add添加网卡状态处理监控函数;

2、一旦发生中断,调用napi_schedule函数添加NAPI到CPU的待处理NAPI队列中;

3、当软中断运行时,调用net_rx_action函数执行注册的网卡状态监控处理函数;

4、对接收到的数据包进行二层处理后调用netif_receive_skb交给上层处理;实际上netif_receive_skb会调用enqueue_to_backlog把数据包添加到sd->input_pkt_queue队列中,然后把sd->backlog这个NAPI添加到CPU的待处理NAPI队列中,在下次软中断运行时执行process_backlog这个函数,才真正的把等候在上面的数据包交给__netif_receive_skb这个真正的上层协议处理函数进行处理;

 

 

OPEN函数:

1、分配并初始化传输和接收描述符环(需要DMA地址);

2、注册中断相关函数;

3、初始化网络硬件模块;

2、调用netif_start_queue或者netif_tx_start_all_queues使能传输队列调度;

3、调用netif_wake_queue或者netif_tx_wake_all_queues开启传输队列的调度(因为此时所有的传输环为空,可以立刻开始传输);

5、使能传输/接收通道,打开中断;

 

ndo_start_xmit函数

1、检查skb_shinfo(skb)->tx_flags标志位,SKBTX_HW_TSTAMP指示硬件向上层软件提供硬件时间戳(调用skb_tstamp_tx),SKBTX_IN_PROGRESS由硬件置位,表示硬件正在处理上层的时间戳提取要求;

2、根据ip_summed查看是否需要协助计算校验和,需要csum_start和csum_offset;

3、是否需要VLAN标签插入,需要vlan_proto和vlan_tci;

4、queue_mapping指示该SKB需要插入到哪个传输队列上;

5、根据nr_frags检查是否需要发送碎片包,此时需要初始化nr_frags数量的传输描述符;

6、检查skb->encapsulation,确定是否需要使用内层协议头;

7、检查skb_shinfo(skb)->gso_size是否需要硬件进行分片操作;

7、映射DMA操作需要的地址,填入传输描述符中;

8、更新传输描述环相关状态;

 

中断函数

1、检查是否有已经发出的数据包,有则复位相应传输描述符以供下次使用,同时UNMAP内存到DMA的映射,释放SKB的引用;更新传输描述符环相关信息;如果传输队列的空闲空间高于阙值,则重新启动传输调度机制运行;

2、检查是否有接收到新的数据包,有则调用NAPI去处理接收的数据包,同时禁止接收中断;

3、如果有错误信息,则通过delaywork机制调用错误恢复程序;

4、更新网络收发数据统计计数;

 

接收函数

1、遍历接受描述符环,分别处理接收到的数据包,并复位处理过的接收描述符;

2、依次分配SKB;

3、指定接收队列(skb->queue_mapping);

4、检查网络层数据的校验和(skb->csum和skb->ip_summed);

5、提取Vlan信息(硬件支持的话、skb->vlan_proto和skb->vlan_tci);

6、提取硬件时间戳(skb_shinfo(skb)->hwtstamps);

7、提取接收HASH过滤结果(skb->rxhash和l4_rxhash);

8、检查是否封包(skb->encapsulation);

9、以太网包可以调用eth_type_trans提取(skb->pkt_type、skb->protocal),指定MAC头指针;

9、指定skb的数据指针()

6,调用napi_gro_receive提交给网络核心层处理;

3、更新网络包处理的统计计数;

0 0
原创粉丝点击