Linux协议栈代码阅读笔记(三)报文接收

原创 2013年12月02日 13:58:23
(基于linux-2.6.21.7)


(一)网卡接收报文


以Intel PRO/1000网卡为例。

网卡收到报文后,产生中断。
驱动程序的中断处理函数e1000_intr(源码文件:\drivers\net\e1000\e1000_main.c)对报文进行接收。
中断处理程序先做一些基本的接收工作,然后开始如下的执行路径(从e1000_intr内部开始):

(注意,内核与网卡驱动之间,有两套数据交互接口:一套老的,一套新的。新的接口(称为NAPI)有更好的效率。
因此,我们这里只看基于NAPI接口的执行路径。)


__netif_rx_schedule (源码文件:net\core\dev.c)
    __raise_softirq_irqoff(NET_RX_SOFTIRQ); /* 启动报文接收软中断 */
net_rx_action(由上一步触发,(源码文件:net\core\dev.c)
    dev->poll(即e1000_clean,源码文件:\drivers\net\e1000\e1000_main.c)
        adapter->clean_rx(即e1000_clean_rx_irq,源码文件:\drivers\net\e1000\e1000_main.c)
            netif_receive_skb(源码文件:net\core\dev.c)


netif_receive_skb根据以太头中的type值(当然,还有别的信息,在下还没弄明白)查找一个匹配的packet_type条目,
然后调用pt_prev->func对报文进行处理。pt_prev为指向查找到的packet_type条目的指针。
大部分packet_type条目都位于ptype_base中(源码文件:net\core\dev.c)。
各协议模块通过dev_add_pack接口向ptype_base中添加条目。
packet_type条目的一个关键成员是type,它是ethernet头中的type字段的某个值。
另一个关键成员是func,他是该协议模块对报文进行接收处理的函数。


例如,ip模块向ptype_base添加的packet_type为ip_packet_type,其定义如下:


(源码文件:net\ipv4\af_inet.c)


static struct packet_type ip_packet_type = {
.type = __constant_htons(ETH_P_IP),
.func = ip_rcv,
.gso_send_check = inet_gso_send_check,
.gso_segment = inet_gso_segment,
};


再如,arp模块向ptype_base添加的packet_type为arp_packet_type,其定义如下:
(源码文件:net\ipv4\Arp.c)


static struct packet_type arp_packet_type = {
.type = __constant_htons(ETH_P_ARP),
.func = arp_rcv,
};


接下来,我们看看IP协议模块对报文的接收处理。


(二)IP协议模块对报文的接收处理
根据ip_packet_type的定义,ip报文的接收处理由ip_rcv完成。
我们这里仅关注目的ip为本机的报文。
几个关键的执行路径如下:


ip_rcv (源码文件:net\ipv4\ip_input.c)
    ip_rcv_finish
        ip_route_input /* 查找路由,确定报文是上送给host还是转发出去 */
        dst_input
            skb->dst->input(具体函数ip_route_input决定。由于ip为本机,因此对应ip_local_deliver)
                ip_local_deliver_finish


ip_local_deliver_finish中,调用ipprot->handler对报文进行处理。
ipprot是net_protocol指针,他是根据IP报文的protocol(例如udp、tcp啦),引用inet_protos[protocol]得到的。


inet_protos定义如下(源码文件:net\ipv4\protocol.c)。
struct net_protocol *inet_protos[MAX_INET_PROTOS];
inet_protos数组元素指向一个inet_protos结构。
此结构的关键信息是handler函数。他是本协议模块对报文进行接收处理的函数。
例如,tcp、udp、icmp协议的net_protocol结构定义如下。


(源码文件:net\ipv4\af_inet.c)
static struct net_protocol tcp_protocol = {
.handler = tcp_v4_rcv,
.err_handler = tcp_v4_err,
.gso_send_check = tcp_v4_gso_send_check,
.gso_segment = tcp_tso_segment,
.no_policy = 1,
};


static struct net_protocol udp_protocol = {
.handler = udp_rcv,
.err_handler = udp_err,
.no_policy = 1,
};


static struct net_protocol icmp_protocol = {
.handler = icmp_rcv,
};


各协议模块的handler函数对收到到报文进行处理,并将相应的数据提交到各个socket中。
用户则通过一组socket接口将数据读走。
socket则相当于一个媒介,他处于用户和协议模块之间。
也就是说,socket层对于用户与协议模块都是可见的。
二者最终都是与socket进行交互。


最后,ip_local_deliver_finish中,实际上还做了raw socket方面的处理。
在将报文传递给inet_protos[protocol]之前,还要先看看有没有相应的raw_socket。
如果有的话,需要将报文复制给raw_socket一份。



版权声明:本文没有任何版权限制,任何人可以以任何方式使用本文。

static、extern分析总结

引用请注明出处:http://blog.csdn.net/int64ago/article/details/7396325        对于写了很多小程序的人,可能static和extern都...

数据库——SQLite3编译及测试

下载:下载SQLite3的源代码: https://www.sqlite.org/2017/sqlite-amalgamation-3170000.zip 下载SQLite3的动态链接库需要用到里...

【Linux4.1.12源码分析】协议栈报文接收之传输层处理分析(UDP)

UDP报文的处理入口是udp_rcv函数,该函数是在ip_local_deliver_finish函数中被调用的。 1、udp_rcv函数 int udp_rcv(struct sk_buff *...

【Linux4.1.12源码分析】协议栈报文接收之IP层处理分析(ip_local_deliver)

报文提交给内核协议栈处理后,最终会调用到__netif_receive_skb_core函数,如果报文没有被rx_handler消费掉,最终会交给ptype_base中注册的协议处理,包括内核注册的协...

linux网络协议栈(六)传输层 (3)UDP协议 4)报文接收 recv/recvfrom/recvmsg

6.2.2.2.5、报文接收: recv/recvfrom/recvmsg和send族系统调用的道理是一样的,如下图: sock_recvmsg函数最终调用套接字类型ops的recvm...

Linux协议栈报文收发流程记录

RX流程 1. 非NAPI的RX driver的isr调用eth_type_trans                            //确定skb->pkt_type和skb->pro...

Linux内核协议栈IP报文的上送转发及下发

这里主要分析在网络功能简单配置,且报文正常的情况下,报文的处理过程。 网卡接收到IP报文,经过一些执行路径后,最终进入ip_rcv做处理。  ip_rcv在网络功能简单配置,且报文正常的情况下,就是简...

Linux协议栈报文收发流程记录

RX流程 1. 非NAPI的RX driver的isr调用eth_type_trans //确定skb->pkt_type和skb->protocol driver的isr调用netif_rx ...

Linux协议栈报文收发流程记录

来自:http://blog.chinaunix.net/uid-22397896-id-3348984.html RX流程 1. 非NAPI的RX driver的isr调用eth_type_...

【Linux4.1.12源码分析】VXLAN报文内核协议栈处理

4.1.12内核已经支持vxlan报文的gro功能,意味着vxlan报文交给协议栈之前,已经被聚合过了,而在早期的内核中聚合逻辑是在encap_rcv函数之后实现的。 之前分析的UDP报文处理中,可...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Linux协议栈代码阅读笔记(三)报文接收
举报原因:
原因补充:

(最多只允许输入30个字)