本文主要讲解了Linux内核IP层的整体架构和对从网卡接受的报文处理流程,使用的内核的版本是2.6.32.27
为了方便理解,本文采用整体流程图加伪代码的方式对Linxu内核中IP整体实现架构和对网卡报文的处理流程进行了讲解,希望可以对大家有所帮助。阅读本文章假设大家对C语言有了一定的了解
IP层的整体实现架构
IP层接受底层数据报文的处理流程
/*
* 在NET_RX_SOFTIRQ软中后,由ETH_P_IP触发的ipv4协议入口函数
*/
int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev)
{
/*
* 过滤掉送往其他主机的数据包(这时网卡正在处于混杂模式)
*/
if (skb->pkt_type == PACKET_OTHERHOST)
goto drop;
iph = ip_hdr(skb);
/*头的长度是否至少是IP头长度(5); 是否是IPV4报文*/
if (iph->ihl < 5 || iph->version != 4)
goto inhdr_error;
/*IP头长度是否正确,不是伪造的长度*/
if (!pskb_may_pull(skb, iph->ihl*4))
goto inhdr_error;
iph = ip_hdr(skb);
/*检查校验和*/
if (unlikely(ip_fast_csum((u8 *)iph, iph->ihl)))
goto inhdr_error;
len = ntohs(iph->tot_len);
if (skb->len < len) {
IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_INTRUNCATEDPKTS);
goto drop;
} else if (len < (iph->ihl*4))
goto inhdr_error;
/*实际尺寸不匹配套接字缓冲(skb->len)中维护的信息,则调用skb_trim调整数据包的长度*/
if (psk