免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
1234下一页
最近访问板块 发新帖
查看: 24101 | 回复: 30

2.6内核数据包接收流程分析 [复制链接]

论坛徽章:
6
金牛座
日期:2013-10-08 10:19:10技术图书徽章
日期:2013-10-14 16:24:09CU十二周年纪念徽章
日期:2013-10-24 15:41:34狮子座
日期:2013-11-24 19:26:19未羊
日期:2014-01-23 15:50:002015年亚洲杯之阿联酋
日期:2015-05-09 14:36:15
发表于 2009-09-01 13:16 |显示全部楼层
2.6.24.4内核网络接收数据包分析

在2.6.24.4中所有的网卡,不管是否支持napi,都是通过struct napi_struct结构进行。所有我们先说一下这个结果。
struct napi_struct{
   struct list_head poll_list;
   unsigned long state;
   int weight;
   int (*poll)(struct napi_struct *,int);
}
对应支持napi的网卡,自己填充这个结构体;而非napi网卡,则使用per cpu的softnet_data->backlog,这个结构的初始化在net_dev_init()中完成。
我们先说一下非napi机制的网卡:
    网卡接收到数据包后dma到内核空间,然后调用netif_rx()将数据包挂接到softnet_data->input_pkt_queue中,如果backlog这个napi_struct没有被调度,则napi_schedule(&backlog).
napi_schedule()会将backlog的poll_list挂接到softnet_data->poll_list上,同时触发软中断NET_RX_SOFTIRQ。
NET_RX_SOFTIRQ软中断,调用相应的函数net_rx_action()。

对应napi机制的网卡:
     网卡初始化是会自己初始化一个自己的数据包接收队列,当有数据包到达时,将数据包dma到自己的数据包队列中,如果自己的napi没有调度,则napi_schedule(mynapi),这里的mynapi是网卡自己的napi_struct.napi_schedule()会将网卡自己的poll_list挂接到softnet_data->poll_list上,同时出发软中断NET_RX_SOFTIRQ。NET_RX_SOFTIRQ软中断,调用相应的函数net_rx_action()。



net_rx_action():
    首先获取softnet_data->poll_list,通过遍历poll_list,获取每个poll_list对应的napi_struct结构(container_of实现),然后根据napi_struct的weight调用poll函数,如果是非napi网卡,这里的napi_struct是backlog,所以poll函数就是process_backlog;如果是napi的网卡,则会使自己的poll函数。
napi网卡的poll函数就是从自己数据包队列中dequeue出一个skb,然后调用netif_receive_skb().
非napi的process_backlog会获取softnet_data->input_pkt_queue,然后对队列input_pkt_queue进行dequeue操作,获得一个skb,之后调用netif_receive_skb(skb)。

netif_receive_skb():
    对skb做一些准备工作,例如设置mac_len等,调用deliver_skb()给所有的注册ptype_all类型的协议处理handle,然后是网桥和VLAN的处理,之后会给注册的相应协议的ptype_base的handle。这里假设是ip协议,则会调用相应的ip协议handle的处理函数ip_rcv。

ip_rcv():
    对skb做一些检查工作后,会转入netfilter的NF_IP_PRE_ROUTING的hook点,调用所有在该点注册的hook函数。比如说如果开启了conntrack,则会在这里进行数据包重组。之后调用ip_rcv_finish().

ip_rcv_finish():
    首先调用ip_route_input()决定数据包的路由,初始化skb->dst,调用dst_input(skb).

dst_input():
    实际上是调用skb->dst->input(skb),对应input的初始化在route.c中。如果是发往本地的数据包dst->input=ip_local_deliver;如果是转发的数据包dst->input=ip_forward;

本地流程:
ip_local_deliver():
    首先是对分片的数据包重组,会转入netfilter的NF_IP_LOCAL_IN的hook点,调用所有在该点注册的hook函数。之后会调用ip_local_deliver_finish(),之后就到第四层了。

转发流程:
ip_forward():
    做一些源路由等方面的检查后,会转入netfilter的NF_IP_FORWARD的hook点,调用所有在该点注册的hook函数。之后会调用ip_forward_finish().

ip_forward_finish():
    调用dst_output().

dst_output():
    skb->dst->output(skb).一般output=ip_output.

ip_output():
    设置skb的dev为发包的dev,同时设置skb->protocol,会转入netfilter的NF_IP_POST_ROUTING的hook点,调用所有在该点注册的hook函数。之后会调用ip_finish_output().

ip_finish_output():
    检查一下数据包是否需要分片,如果需要分片,则进行ip_fragement(),之后调用ip_finish_output2().

ip_finish_output2():
    根据neighbour,调用dst->neighbour->output.

到这为止,数据包会经过dev_queue_xmit放入dev的qdisc中。之后就是流控出队列。


分析有不对的地方还请各位大虾不吝赐教。

[ 本帖最后由 瀚海书香 于 2009-9-1 13:34 编辑 ]

评分

参与人数 1可用积分 +30 收起 理由
Godbach + 30 原创内容

查看全部评分

论坛徽章:
36
IT运维版块每日发帖之星
日期:2016-04-10 06:20:00IT运维版块每日发帖之星
日期:2016-04-16 06:20:0015-16赛季CBA联赛之广东
日期:2016-04-16 19:59:32IT运维版块每日发帖之星
日期:2016-04-18 06:20:00IT运维版块每日发帖之星
日期:2016-04-19 06:20:00每日论坛发贴之星
日期:2016-04-19 06:20:00IT运维版块每日发帖之星
日期:2016-04-25 06:20:00IT运维版块每日发帖之星
日期:2016-05-06 06:20:00IT运维版块每日发帖之星
日期:2016-05-08 06:20:00IT运维版块每日发帖之星
日期:2016-05-13 06:20:00IT运维版块每日发帖之星
日期:2016-05-28 06:20:00每日论坛发贴之星
日期:2016-05-28 06:20:00
发表于 2009-09-01 13:21 |显示全部楼层
很不错的文章。多谢LZ分享。
BTW,能否把有些显示不太好的分行统一整理一下。:wink:

论坛徽章:
6
金牛座
日期:2013-10-08 10:19:10技术图书徽章
日期:2013-10-14 16:24:09CU十二周年纪念徽章
日期:2013-10-24 15:41:34狮子座
日期:2013-11-24 19:26:19未羊
日期:2014-01-23 15:50:002015年亚洲杯之阿联酋
日期:2015-05-09 14:36:15
发表于 2009-09-01 13:23 |显示全部楼层

回复 #2 Godbach 的帖子

已整理

论坛徽章:
36
IT运维版块每日发帖之星
日期:2016-04-10 06:20:00IT运维版块每日发帖之星
日期:2016-04-16 06:20:0015-16赛季CBA联赛之广东
日期:2016-04-16 19:59:32IT运维版块每日发帖之星
日期:2016-04-18 06:20:00IT运维版块每日发帖之星
日期:2016-04-19 06:20:00每日论坛发贴之星
日期:2016-04-19 06:20:00IT运维版块每日发帖之星
日期:2016-04-25 06:20:00IT运维版块每日发帖之星
日期:2016-05-06 06:20:00IT运维版块每日发帖之星
日期:2016-05-08 06:20:00IT运维版块每日发帖之星
日期:2016-05-13 06:20:00IT运维版块每日发帖之星
日期:2016-05-28 06:20:00每日论坛发贴之星
日期:2016-05-28 06:20:00
发表于 2009-09-01 13:28 |显示全部楼层
netif_receive_skb():
    对skb做一些准备工作,例如设置mac_len等,调用deliver_skb()给所有的注册ptype_all类型的协议处理handle发送一个 clone skb,然后是网桥和VLAN的处理,之后会给注册的相应协议的ptype_base的handle发生一个clone skb。这里假设是ip协议,则会调用相应的ip协议handle的处理函数ip_rcv。


在这个函数中,做了clone的动作吗?

论坛徽章:
6
金牛座
日期:2013-10-08 10:19:10技术图书徽章
日期:2013-10-14 16:24:09CU十二周年纪念徽章
日期:2013-10-24 15:41:34狮子座
日期:2013-11-24 19:26:19未羊
日期:2014-01-23 15:50:002015年亚洲杯之阿联酋
日期:2015-05-09 14:36:15
发表于 2009-09-01 13:32 |显示全部楼层

回复 #4 Godbach 的帖子

多谢提醒,是在deliver_skb中增加skb->users.
已改正

论坛徽章:
0
发表于 2009-09-01 14:03 |显示全部楼层
刚写好一个类似的笔记,准备再整理一下发出来,没想到LZ发了一份
呵呵
不过我的跟lz的还有点不同,没有管ip_forward这条线,
而是从驱动一直走到用户空间,晚上弄好了发来一起学习吧

论坛徽章:
36
IT运维版块每日发帖之星
日期:2016-04-10 06:20:00IT运维版块每日发帖之星
日期:2016-04-16 06:20:0015-16赛季CBA联赛之广东
日期:2016-04-16 19:59:32IT运维版块每日发帖之星
日期:2016-04-18 06:20:00IT运维版块每日发帖之星
日期:2016-04-19 06:20:00每日论坛发贴之星
日期:2016-04-19 06:20:00IT运维版块每日发帖之星
日期:2016-04-25 06:20:00IT运维版块每日发帖之星
日期:2016-05-06 06:20:00IT运维版块每日发帖之星
日期:2016-05-08 06:20:00IT运维版块每日发帖之星
日期:2016-05-13 06:20:00IT运维版块每日发帖之星
日期:2016-05-28 06:20:00每日论坛发贴之星
日期:2016-05-28 06:20:00
发表于 2009-09-01 14:15 |显示全部楼层

回复 #6 peimichael 的帖子

欢迎分享啊。。。

论坛徽章:
6
金牛座
日期:2013-10-08 10:19:10技术图书徽章
日期:2013-10-14 16:24:09CU十二周年纪念徽章
日期:2013-10-24 15:41:34狮子座
日期:2013-11-24 19:26:19未羊
日期:2014-01-23 15:50:002015年亚洲杯之阿联酋
日期:2015-05-09 14:36:15
发表于 2009-09-01 14:25 |显示全部楼层

回复 #6 peimichael 的帖子

期待ing

论坛徽章:
0
发表于 2009-09-01 14:33 |显示全部楼层
桥部分没有分析
如果有网桥,那么数据流程就截然不同了

论坛徽章:
0
发表于 2009-09-01 14:34 |显示全部楼层
原帖由 peimichael 于 2009-9-1 14:03 发表
刚写好一个类似的笔记,准备再整理一下发出来,没想到LZ发了一份
呵呵
不过我的跟lz的还有点不同,没有管ip_forward这条线,
而是从驱动一直走到用户空间,晚上弄好了发来一起学习吧

期待啊!
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP