TCP/IP协议栈中IP层架构
来源:互联网 发布:黑暗之魂不死人知乎 编辑:程序博客网 时间:2024/05/22 01:58
/* * Main IP Receive routine. * 对IP头部合法性进行严格检查,然后把具体功能交给ip_rcv_finish */int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev){ const struct iphdr *iph; u32 len; /* * 当网卡处于混杂模式时,丢掉所有接收到的的垃圾数据,不要试图解析它 */ //noted: 其实也就是丢弃掉不是发往本地的数据包。网卡在混杂模式下会接收一切到达网卡的数据,不管目的地mac是否是本网卡 //noted: 在调用ip_rcv之前,内核会将该数据包交给嗅探器,所以该函数仅丢弃该包 if (skb->pkt_type == PACKET_OTHERHOST) goto drop; //noted:该宏用于内核做一些统计,关于网络层snmp统计的信息,也可以通过netstat 指令看到这些统计值 IP_UPD_PO_STATS_BH(dev_net(dev), IPSTATS_MIB_IN, skb->len); //noted: ip_rcv是由netif_receive_skb函数调用,如果嗅探器或者其他的用户对数据包需要进 //进行处理,则在调用ip_rcv之前,netif_receive_skb会增加skb的引用计数,既该引 //用计数会大于1。若如此次,则skb_share_check会创建sk_buff的一份拷贝。 if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) { //noted: SNMP所需要的统计数据,忽略 IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_INDISCARDS); goto out; } //noted:pskb_may_pull确保skb->data指向的内存包含的数据至少为IP头部大小,由于每个 //IP数据包包括IP分片必须包含一个完整的IP头部。如果小于IP头部大小,则缺失 //的部分将从数据分片中拷贝。这些分片保存在skb_shinfo(skb)->frags[]中。 if (!pskb_may_pull(skb, sizeof(struct iphdr))) goto inhdr_error; //noted: pskb_may_pull可能会调整skb中的指针,所以需要重新定义IP头部 iph = ip_hdr(skb); /* * RFC1122: 3.2.1.2 必须默默地放弃任何IP帧校验和失败. * * 数据报可接收? * * 1. 长度至少是一个ip报头的大小 * 2. 版本4 * 3. 校验和正确。(速度优化后,跳过回路校验和) * 4. 没有虚假的长度 */ //noted: 检测ip首部长度及协议版本 if (iph->ihl < 5 || iph->version != 4) goto inhdr_error; //noted: 确保IP完整的头部包括选项在内存中 if (!pskb_may_pull(skb, iph->ihl*4)) goto inhdr_error; iph = ip_hdr(skb); //noted:验证IP头部的校验和 if (unlikely(ip_fast_csum((u8 *)iph, iph->ihl))) goto csum_error; //noted:检测ip报文长度是否小于skb->len 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; /* 我们的传输介质可能填充缓冲区。现在我们知道这是 我们可以从此帧中削减的真实长度的ip帧 * 注意现在意味着skb->len包括ntohs(iph->tot_len) */ if (pskb_trim_rcsum(skb, len)) { IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_INDISCARDS); goto drop; } //noted: 设置tcp报头指针 skb->transport_header = skb->network_header + iph->ihl*4; /* 删除任何套接字控制块碎片 */ memset(IPCB(skb), 0, sizeof(struct inet_skb_parm)); /* 因为tproxy,现在必须丢掉socket */ //noted: tproxy是iptables的一附加控件,在mangle表的PREROUTING链中使用,不修改数据包包头, //直接把数据传递给一个本地socket(即不对数据包进行任何nat操作)。具体百度搜索tproxy skb_orphan(skb); //noted: 在做完基本的头校验等工作后,就交由NF_HOOK管理了 //noted: NF_HOOK在做完PRE_ROUTING的筛选后,PRE_ROUTING点上注册的所有钩子都 //返回NF_ACCEPT才会执行后面的ip_rcv_finish函数 ,然后继续执行路由等处理 //如果是本地的就会交给更高层的协议进行处理,如果不是交由本地的就执行FORWARD return NF_HOOK(NFPROTO_IPV4, NF_INET_PRE_ROUTING, skb, dev, NULL, ip_rcv_finish);csum_error: IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_CSUMERRORS);inhdr_error: IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_INHDRERRORS);drop: kfree_skb(skb);out: return NET_RX_DROP;}
/* * Main IP Receive routine. * 对IP头部合法性进行严格检查,然后把具体功能交给ip_rcv_finish */int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev){ const struct iphdr *iph; u32 len; /* * 当网卡处于混杂模式时,丢掉所有接收到的的垃圾数据,不要试图解析它 */ //noted: 其实也就是丢弃掉不是发往本地的数据包。网卡在混杂模式下会接收一切到达网卡的数据,不管目的地mac是否是本网卡 //noted: 在调用ip_rcv之前,内核会将该数据包交给嗅探器,所以该函数仅丢弃该包 if (skb->pkt_type == PACKET_OTHERHOST) goto drop; //noted:该宏用于内核做一些统计,关于网络层snmp统计的信息,也可以通过netstat 指令看到这些统计值 IP_UPD_PO_STATS_BH(dev_net(dev), IPSTATS_MIB_IN, skb->len); //noted: ip_rcv是由netif_receive_skb函数调用,如果嗅探器或者其他的用户对数据包需要进 //进行处理,则在调用ip_rcv之前,netif_receive_skb会增加skb的引用计数,既该引 //用计数会大于1。若如此次,则skb_share_check会创建sk_buff的一份拷贝。 if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) { //noted: SNMP所需要的统计数据,忽略 IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_INDISCARDS); goto out; } //noted:pskb_may_pull确保skb->data指向的内存包含的数据至少为IP头部大小,由于每个 //IP数据包包括IP分片必须包含一个完整的IP头部。如果小于IP头部大小,则缺失 //的部分将从数据分片中拷贝。这些分片保存在skb_shinfo(skb)->frags[]中。 if (!pskb_may_pull(skb, sizeof(struct iphdr))) goto inhdr_error; //noted: pskb_may_pull可能会调整skb中的指针,所以需要重新定义IP头部 iph = ip_hdr(skb); /* * RFC1122: 3.2.1.2 必须默默地放弃任何IP帧校验和失败. * * 数据报可接收? * * 1. 长度至少是一个ip报头的大小 * 2. 版本4 * 3. 校验和正确。(速度优化后,跳过回路校验和) * 4. 没有虚假的长度 */ //noted: 检测ip首部长度及协议版本 if (iph->ihl < 5 || iph->version != 4) goto inhdr_error; //noted: 确保IP完整的头部包括选项在内存中 if (!pskb_may_pull(skb, iph->ihl*4)) goto inhdr_error; iph = ip_hdr(skb); //noted:验证IP头部的校验和 if (unlikely(ip_fast_csum((u8 *)iph, iph->ihl))) goto csum_error; //noted:检测ip报文长度是否小于skb->len 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; /* 我们的传输介质可能填充缓冲区。现在我们知道这是 我们可以从此帧中削减的真实长度的ip帧 * 注意现在意味着skb->len包括ntohs(iph->tot_len) */ if (pskb_trim_rcsum(skb, len)) { IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_INDISCARDS); goto drop; } //noted: 设置tcp报头指针 skb->transport_header = skb->network_header + iph->ihl*4; /* 删除任何套接字控制块碎片 */ memset(IPCB(skb), 0, sizeof(struct inet_skb_parm)); /* 因为tproxy,现在必须丢掉socket */ //noted: tproxy是iptables的一附加控件,在mangle表的PREROUTING链中使用,不修改数据包包头, //直接把数据传递给一个本地socket(即不对数据包进行任何nat操作)。具体百度搜索tproxy skb_orphan(skb); //noted: 在做完基本的头校验等工作后,就交由NF_HOOK管理了 //noted: NF_HOOK在做完PRE_ROUTING的筛选后,PRE_ROUTING点上注册的所有钩子都 //返回NF_ACCEPT才会执行后面的ip_rcv_finish函数 ,然后继续执行路由等处理 //如果是本地的就会交给更高层的协议进行处理,如果不是交由本地的就执行FORWARD return NF_HOOK(NFPROTO_IPV4, NF_INET_PRE_ROUTING, skb, dev, NULL, ip_rcv_finish);csum_error: IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_CSUMERRORS);inhdr_error: IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_INHDRERRORS);drop: kfree_skb(skb);out: return NET_RX_DROP;}
'''
NIC Memory 台式机一般都采用内置网卡来连接网络。网卡也叫“网络适配器”,英文全称为“Network Interface Card”
interrupt Generator 中断发生器
DMA Engine 直接存储器存取引擎 DMA驱动 它允许客户端对外设指定DMA的方向、DMA地址、总线宽度、DMA突发长度等等
softirq 软中断; 软件中断为此,整个softirq机制的设计与实现中
自始自终都贯彻了一个思想:“谁触发,谁执行”(Who marks,Who runs),也即触发
软中断的那个CPU负责执行它所触发的软中断,而且每个CPU都由它自己的软中断触发与
控制机制。这个设计思想也使得softirq机制充分利用了SMP系统的性能和特点。
interrupt handler 中断处理程序
pointer to device
backlog 定义是已连接但未进行accept处理的SOCKET队列大小,已是(并非syn的SOCKET队列)。
'''s
阅读全文
0 0
- TCP/IP协议栈中IP层架构
- TCP/IP协议架构
- TCP/IP四层协议栈
- TCP/IP 协议栈和主要层
- TCP&IP协议: 4层协议栈架构的初始化过程
- TCP/IP应用层协议
- TCP/IP 七层协议
- TCP/IP四层协议
- TCP/IP 四层协议
- TCP/IP 5层协议
- TCP/IP协议栈传输层协议(TCP/UDP)
- TCP/IP协议栈 --- 网络层(IP 首部 和分片)
- TCP/IP协议--IP层ip_local_deliver实现
- TCP/IP协议栈中,为什么选择IP层负责分片?
- 网络传输层协议中,基于TCP/IP协议…
- OSI7层模型与TCP/IP协议栈4层
- OSI7层模型与TCP/IP协议栈4层
- tcp/ip协议栈-tcp层(1)
- linux 下面查找某个文件是否含有某个字符串
- BMP文件格式
- 不带doc\view结构的单文档窗口多次分割
- Windows单机最大TCP连接数
- mysql取系统当前时间的函数
- TCP/IP协议栈中IP层架构
- 计算机组成原理——linux常用命令
- 自定义View实现解锁
- JNI中java类型与C/C++类型对应关系
- 块级子元素在父元素中实现水平垂直居中
- 移除CSDN各种广告
- linux 安装nginx+php+mysql
- 机器学习实践一
- 方法与数组(2)