数据包在Linux中的流程

博客介绍了网卡数据包的处理流程。网卡收到帧引发中断,CPU调用中断处理函数将数据包读入RAM,标记软中断。软中断被调用时,通过net_rx_action函数根据协议类型找到处理函数,将数据包交给上层处理,如IP协议的数据包会经过一系列处理,包括路由操作等。

1.中断处理函数中:

网卡收到一帧------------------------〉

引发中断-------------------〉

cpu调用相应的中断处理函数(指向此网卡驱动中的相应的处理函数)(把此packet读到ram中)--------------------〉

呼叫netif_rx函数来打上timestamp,并把此skb放入到cpu设置的队列中-----------------〉

标记软中断(__cpu_raise_softirq)---------------------〉中断完成。

2.当软中断被调用时(一共在三个地方调用),呼叫NET_RX_SOFTIRQ(其实就是net_rx_action()函数)来处理网络方面的软中断。-----------------〉

net_rx_action()根据数据包的协议类型在数组ptype_base[16]里找到相应的协议,并从中知道了接收的处理函数,然后把数据包交给处理函数,这样就交给了上层处理,实际调用处理函数是通过net_rx_action()里的pt_prev->func()这一句。例如如果数据包是IP协议的话,ptype_base[ETH_P_IP]->func()(ip_rcv()),这样就把数据包交给了IP协议。根据包的类型,查找系统中注册了的相应的包处理函数,对于ipv4的ip包,呼叫ip_rcv-------------〉
NF_IP_PRE_ROUTING--------------〉

ip_rcv_finish(进行对此包的路由操作)---------------------〉

根据路由的结果,呼叫ip_local_deliver(给本机的包)/ip_forwardd(要转发的包)/ip_error()(出现错误的包)/ip_mr_input()(多播包的处理)ip_forward:要进行转发的包,check ttl, mtu, call NF_IP_FORWARDS,--------------〉

ip_forwmard_finish(check other ip options for forwardd!)-------------------〉

ip_send(如果需要分片,则调用ip_fragment,否则调用ip_finish_output()(call NF_IP_POST_ROUTING,然后时ip_finish_output2(填充链路层头部到skb结构中)--------------〉

hh->hh_output/dsr->neighbour->output

<think>嗯,用户想了解Linux协议栈中数据包处理的函数调用流程。我需要先回忆一下相关的知识,并结合提供的引用内容来构建答案。首先,数据包处理分为接收和发送两个方向,可能需要分开说明。 根据引用3,内核协议栈的收包和发包流程有详细的结构。收包流程驱动程序开始,涉及到中断和NAPI机制,然后经过数据链路层、网络层、传输层,最后到应用层。发包流程则相反,从应用层经过各层处理,最后通过驱动程序发送出去。 引用4提到设备接口层处理完数据包后调用ip_rcv(),然后行路由决策,决定是转发还是递交给本机。如果是本机,会经过LOCAL_IN点,并根据协议类型调用高层处理函数,比如TCP或UDP。 引用1中提到了传输层的tcp函数,网络层的ip函数和neigh相关的ARP处理,以及数据链路层的e1000函数。需要将这些函数对应到各层的处理流程中。 引用2说明ARP的初始化过程,arp_rcv()作为接收处理函数被注册到ptype_base哈希表中,当收到ARP包时会被调用。这可能属于网络层的ARP子流程。 现在需要将各层的函数调用流程整理出来。接收流程从数据链路层的驱动程序开始,比如e1000,然后到网络层处理IP或ARP。如果是IP包,入ip_rcv(),然后路由查询,决定转发或本地处理。本地的话,传输层的tcp_v4_rcv()或udp_rcv()会被调用,之后交给socket层。 发送流程从socket层开始,调用tcp_sendmsg(),入传输层,经过网络层处理路由、ARP,然后通过数据链路层的驱动程序发送。 还需要注意netfilter的钩子点,如PREROUTING、FORWARD、POSTROUTING等,这些在接收和发送流程中会被触发。 用户可能希望具体的函数调用顺序,所以需要分步骤列出每个层次的关键函数,并引用对应的参考文献。同时,生成的相关问题需要围绕流程的细节、性能优化、工具等展开。</think>### Linux协议栈数据包处理函数调用流程 #### 一、接收流程(自底向上) 1. **数据链路层** - 网卡驱动(如`e1000_xmit`)通过DMA将数据包存入内存,触发中断或使用NAPI轮询[^3] - 调用`netif_receive_skb()`解析以太网帧类型 - 若为ARP包,通过`ptype_base`哈希表调用`arp_rcv()`[^2] 2. **网络层** - IP包调用`ip_rcv()`行校验和检查 - 经过Netfilter的`NF_INET_PRE_ROUTING`钩子[^4] - 路由决策:`ip_route_input()`判断转发/本地处理 - **递交给本机**: - 触发`NF_INET_LOCAL_IN`钩子 - 根据IP协议字段调用传输层处理函数(如TCP调用`tcp_v4_rcv()`)[^1] - **转发**: - 触发`NF_INET_FORWARD`钩子 - 调用`ip_forward()`修改TTL,入发送流程 3. **传输层** - TCP包调用`tcp_v4_rcv()`处理序列号、窗口等 - UDP包调用`udp_rcv()`直接递送数据 4. **Socket层** - 通过`sock_def_readable()`唤醒等待队列 - 用户态通过`recv()`系统调用从socket缓冲区读取数据 #### 二、发送流程(自顶向下) 1. **Socket层** - 用户态调用`send()`写入数据到`sock.send_queue` - 触发传输层处理(如TCP调用`tcp_sendmsg()`) 2. **传输层** - TCP协议构建报文头(序列号、ACK等) - 调用`ip_queue_xmit()`入网络层 3. **网络层** - `ip_output()`处理路由选择 - 若需ARP查询,调用`neigh_resolve_output()`[^1] - 经过Netfilter的`NF_INET_POST_ROUTING`钩子[^4] 4. **数据链路层** - 调用网卡驱动(如`e1000_xmit`)通过DMA发送数据 - 若使用TSO/GSO,由网卡硬件分片[^3] #### 核心数据结构 - `struct sk_buff`:贯穿全协议栈的数据包容器[^3] - `struct net_device`:网卡设备描述符 - `struct sock`:传输层连接控制块[^1] ```c // 典型IP层接收代码片段(简化的内核源码) int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev){ struct iphdr *iph = ip_hdr(skb); if (ip_rcv_finish(skb) != NET_RX_SUCCESS) goto drop; return NET_RX_SUCCESS; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值