linux网络协议栈ip_rcv
int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev)
{const struct iphdr *iph;struct net *net;u32 len;//丢弃PACKET_OTHERHOST类型的包/* When the interface is in promisc. mode, drop all the crap* that it receives, do not try to analyse it.*/if (skb->pkt_type == PACKET_OTHERHOST)goto drop;net = dev_net(dev);IP_UPD_PO_STATS_BH(net, IPSTATS_MIB_IN, skb->len);skb = skb_share_check(skb, GFP_ATOMIC);if (!skb) {IP_INC_STATS_BH(net, IPSTATS_MIB_INDISCARDS);goto out;}//尝试以最小长度获取ip头,获取不到则返回errorif (!pskb_may_pull(skb, sizeof(struct iphdr)))goto inhdr_error;//获取ip头iph = ip_hdr(skb);/** RFC1122: 3.2.1.2 MUST silently discard any IP frame that fails the checksum.** Is the datagram acceptable?** 1. Length at least the size of an ip header* 2. Version of 4* 3. Checksums correctly. [Speed optimisation for later, skip loopback checksums]* 4. Doesn't have a bogus length*///校验ip头的长度和版本if (iph->ihl < 5 || iph->version != 4)goto inhdr_error;BUILD_BUG_ON(IPSTATS_MIB_ECT1PKTS != IPSTATS_MIB_NOECTPKTS + INET_ECN_ECT_1);BUILD_BUG_ON(IPSTATS_MIB_ECT0PKTS != IPSTATS_MIB_NOECTPKTS + INET_ECN_ECT_0);BUILD_BUG_ON(IPSTATS_MIB_CEPKTS != IPSTATS_MIB_NOECTPKTS + INET_ECN_CE);IP_ADD_STATS_BH(net,IPSTATS_MIB_NOECTPKTS + (iph->tos & INET_ECN_MASK),max_t(unsigned short, 1, skb_shinfo(skb)->gso_segs));//尝试以ip头携带的ip头部长度获取ip头,获取失败返回errorif (!pskb_may_pull(skb, iph->ihl*4))goto inhdr_error;iph = ip_hdr(skb);if (unlikely(ip_fast_csum((u8 *)iph, iph->ihl)))goto csum_error;//skb的长度,比ip头携带的ip包总长度小,丢弃报文//ip包总长度,比ip头长度小,返回errorlen = ntohs(iph->tot_len);if (skb->len < len) {IP_INC_STATS_BH(net, IPSTATS_MIB_INTRUNCATEDPKTS);goto drop;} else if (len < (iph->ihl*4))goto inhdr_error;/* Our transport medium may have padded the buffer out. Now we know it* is IP we can trim to the true length of the frame.* Note this now means skb->len holds ntohs(iph->tot_len).*/if (pskb_trim_rcsum(skb, len)) {IP_INC_STATS_BH(net, IPSTATS_MIB_INDISCARDS);goto drop;}//获取传输层数据指针skb->transport_header = skb->network_header + iph->ihl*4;/* Remove any debris in the socket control block */memset(IPCB(skb), 0, sizeof(struct inet_skb_parm));/* Must drop socket now because of tproxy. */skb_orphan(skb);#ifdef CONFIG_RTK_HOST_SPEEDUPif (isHostCheck(skb, NF_INET_PRE_ROUTING, 2) == 1) return ip_rcv_finish(net, NULL, skb);
#ifdef CONFIG_RTK_SMB_SPEEDUP else if ( checkSMBIPPort(skb, NF_INET_PRE_ROUTING) == 1)return ip_rcv_finish(net, NULL, skb);
#endif else
#endif//通过iptables的PRE_ROUTING链,如果继续则进入ip_rcv_finishreturn NF_HOOK(NFPROTO_IPV4, NF_INET_PRE_ROUTING,net, NULL, skb, dev, NULL,ip_rcv_finish);csum_error:IP_INC_STATS_BH(net, IPSTATS_MIB_CSUMERRORS);
inhdr_error:IP_INC_STATS_BH(net, IPSTATS_MIB_INHDRERRORS);
drop:kfree_skb(skb);
out:return NET_RX_DROP;
}
大体流程:
- 丢弃PACKET_OTHERHOST类型的包
- dmac不是本主机且没有被bridge消耗
- 携带vlan且没有对应的vlan子接口,没有被bridge消耗
- 其他
- 以最小长度获取ip头,校验版本和头部长度
- 以ip头携带的头部长度获取ip头,校验skb长度、ip头长度以及ip包总长度
- 通过iptables的PRE_ROUTING链,继续则进入ip_rcv_finish
linux网络协议栈ip_rcv相关推荐
- linux 虚拟机大量udp请求失败_理解 Linux 网络栈:Linux 网络协议栈简单总结分析...
1. Linux 网络路径 1.1 发送端 1.1.1 应用层 (1) Socket 应用层的各种网络应用程序基本上都是通过 Linux Socket 编程接口来和内核空间的网络协议栈通信的.Linu ...
- Linux网络协议栈:中断下半部处理
<Linux中断处理:上半部和下半部> <Linux网络协议栈:中断下半部处理> 目录 数据包上送 网络中断下半部处理 总结 推荐阅读 在<Linux网络协议栈:网络包接 ...
- Linux网络协议栈:网络包接收过程
目录 一 Linux网络收包总览 二 Linux启动 2.1 创建ksoftirqd内核线程 2.2 网络子系统初始化 2.3 协议栈注册 2.4 网卡驱动初始化 2.5 启动网卡 三 迎接数据的到来 ...
- 监控和调整Linux网络协议栈的图解指南:接收数据
Table of Contents 入门 最初设定 数据到达 网络数据处理开始 网络数据处理继续 协议栈和用户态套接字 结论 监视和调整Linux网络协议栈:接收数据(图解):https://rtoa ...
- 监视和调整Linux网络协议栈:接收数据
Table of Contents 有关监视和调整Linux网络协议栈的建议 总览 详细外观 网络设备驱动程序 初始化 网络设备初始化 启动网络设备 监控网络设备 调整网络设备 SoftIRQ 什么是 ...
- 理解 Linux 网络栈:Linux 网络协议栈简单总结
1. Linux 网络路径 1.1 发送端 1.1.1 应用层 (1) Socket 应用层的各种网络应用程序基本上都是通过 Linux Socket 编程接口来和内核空间的网络协议栈通信的.Linu ...
- Linux网络协议栈:用eBPF写TCP拥塞控制算法
其实不想用这个题目的,只因为TCP相关的东西比较吸引人的眼球,这篇文章的主题还是eBPF,而不是TCP. 用eBPF写TCP拥塞控制算法只是本文所讲内容的一个再平凡不过的例子. 先看两个问题,或者说是 ...
- Linux网络协议栈:关闭一个还有没发送数据完的TCP连接
<监视和调整Linux网络协议栈:接收数据> <监控和调整Linux网络协议栈的图解指南:接收数据> <Linux网络 - 数据包的接收过程> <Linux网 ...
- Linux网络协议栈:一个TCP链接的耗时
<一次系统调用开销到底有多大?strace.time.perf命令> 目录 一 正常TCP连接建立过程 二 TCP连接建立时的异常情况 1)客户端connect系统调用耗时失控 2)半/全 ...
- Linux网络协议栈:网卡收包分析
Table of Contents 网卡收包 一,框架 二,初始化 三,驱动收包 四,内核处理 参考文章 推荐阅读 网卡收包 内核网络模块如何初始化? 内核如何通过网卡驱动收发数据包? 驱动收到的数据 ...
最新文章
- 阿里云发布第四代神龙架构云计算首次进入5微秒时延时代
- Openssl生成证书流程
- Zynq常见内核崩溃
- C#装箱,拆箱和强制转换(转)
- python hex 补0_Python保留前导零的二进制到十六进制转换
- 内控与IT安全的关系,IT内控与安全审计的关系
- 如何不编程,采集网站评论信息?(视频教程)
- JMeter入门教程(自己做测试了)
- java 多重注解_Java注解-元数据、注解分类、内置注解和自定义注解
- php 图片不让下载,php简单实现文件或图片强制下载的方法
- android基本控件学习-----ProgressBar
- 使用第三方库iOS-ECharts做柱状图的心得
- 若依可以商用吗_商用自动炒菜机Qamp;A,你想知道的都在这里!
- 计算机房里的UPS的作用,机房监控Ups的作用?
- Tomcat7与Tomcat8的差异详细对比
- 3dmax 计算机中丢失,3dmax材质丢失怎么快速找回-解决3dmax材质不见了的方法 - 河东软件园...
- 音视频开发系列(49)视频编码标准发展史
- 解决:蓝奏云下载链接没法打开问题
- 详解会议中控系统及其优点特点有哪些?
- 陈满雪冤背后英雄:上百名同学捐款数十万元