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;
}

大体流程:

  1. 丢弃PACKET_OTHERHOST类型的包

    1. dmac不是本主机且没有被bridge消耗
    2. 携带vlan且没有对应的vlan子接口,没有被bridge消耗
    3. 其他
  2. 以最小长度获取ip头,校验版本和头部长度
  3. 以ip头携带的头部长度获取ip头,校验skb长度、ip头长度以及ip包总长度
  4. 通过iptables的PRE_ROUTING链,继续则进入ip_rcv_finish

linux网络协议栈ip_rcv相关推荐

  1. linux 虚拟机大量udp请求失败_理解 Linux 网络栈:Linux 网络协议栈简单总结分析...

    1. Linux 网络路径 1.1 发送端 1.1.1 应用层 (1) Socket 应用层的各种网络应用程序基本上都是通过 Linux Socket 编程接口来和内核空间的网络协议栈通信的.Linu ...

  2. Linux网络协议栈:中断下半部处理

    <Linux中断处理:上半部和下半部> <Linux网络协议栈:中断下半部处理> 目录 数据包上送 网络中断下半部处理 总结 推荐阅读 在<Linux网络协议栈:网络包接 ...

  3. Linux网络协议栈:网络包接收过程

    目录 一 Linux网络收包总览 二 Linux启动 2.1 创建ksoftirqd内核线程 2.2 网络子系统初始化 2.3 协议栈注册 2.4 网卡驱动初始化 2.5 启动网卡 三 迎接数据的到来 ...

  4. 监控和调整Linux网络协议栈的图解指南:接收数据

    Table of Contents 入门 最初设定 数据到达 网络数据处理开始 网络数据处理继续 协议栈和用户态套接字 结论 监视和调整Linux网络协议栈:接收数据(图解):https://rtoa ...

  5. 监视和调整Linux网络协议栈:接收数据

    Table of Contents 有关监视和调整Linux网络协议栈的建议 总览 详细外观 网络设备驱动程序 初始化 网络设备初始化 启动网络设备 监控网络设备 调整网络设备 SoftIRQ 什么是 ...

  6. 理解 Linux 网络栈:Linux 网络协议栈简单总结

    1. Linux 网络路径 1.1 发送端 1.1.1 应用层 (1) Socket 应用层的各种网络应用程序基本上都是通过 Linux Socket 编程接口来和内核空间的网络协议栈通信的.Linu ...

  7. Linux网络协议栈:用eBPF写TCP拥塞控制算法

    其实不想用这个题目的,只因为TCP相关的东西比较吸引人的眼球,这篇文章的主题还是eBPF,而不是TCP. 用eBPF写TCP拥塞控制算法只是本文所讲内容的一个再平凡不过的例子. 先看两个问题,或者说是 ...

  8. Linux网络协议栈:关闭一个还有没发送数据完的TCP连接

    <监视和调整Linux网络协议栈:接收数据> <监控和调整Linux网络协议栈的图解指南:接收数据> <Linux网络 - 数据包的接收过程> <Linux网 ...

  9. Linux网络协议栈:一个TCP链接的耗时

    <一次系统调用开销到底有多大?strace.time.perf命令> 目录 一 正常TCP连接建立过程 二 TCP连接建立时的异常情况 1)客户端connect系统调用耗时失控 2)半/全 ...

  10. Linux网络协议栈:网卡收包分析

    Table of Contents 网卡收包 一,框架 二,初始化 三,驱动收包 四,内核处理 参考文章 推荐阅读 网卡收包 内核网络模块如何初始化? 内核如何通过网卡驱动收发数据包? 驱动收到的数据 ...

最新文章

  1. 阿里云发布第四代神龙架构云计算首次进入5微秒时延时代
  2. Openssl生成证书流程
  3. Zynq常见内核崩溃
  4. C#装箱,拆箱和强制转换(转)
  5. python hex 补0_Python保留前导零的二进制到十六进制转换
  6. 内控与IT安全的关系,IT内控与安全审计的关系
  7. 如何不编程,采集网站评论信息?(视频教程)
  8. JMeter入门教程(自己做测试了)
  9. java 多重注解_Java注解-元数据、注解分类、内置注解和自定义注解
  10. php 图片不让下载,php简单实现文件或图片强制下载的方法
  11. android基本控件学习-----ProgressBar
  12. 使用第三方库iOS-ECharts做柱状图的心得
  13. 若依可以商用吗_商用自动炒菜机Qamp;A,你想知道的都在这里!
  14. 计算机房里的UPS的作用,机房监控Ups的作用?
  15. Tomcat7与Tomcat8的差异详细对比
  16. 3dmax 计算机中丢失,3dmax材质丢失怎么快速找回-解决3dmax材质不见了的方法 - 河东软件园...
  17. 音视频开发系列(49)视频编码标准发展史
  18. 解决:蓝奏云下载链接没法打开问题
  19. 详解会议中控系统及其优点特点有哪些?
  20. 陈满雪冤背后英雄:上百名同学捐款数十万元

热门文章

  1. 激光雷达运动畸变去除方法
  2. css的语义---Cascading Style Sheet
  3. 牛客多校第九场K-The Flee Plan of Groundhog(树形DP)
  4. sklearn:make_blobs聚类数据生成器
  5. 云硬盘备份 | 概览
  6. [HAL]STM32F1光照度测量BH1750 串口输出
  7. 仿拼多多砍价功能玩法解说
  8. android 功能页面设计,50个优秀用户体验的手机界面设计(APP UI DESIGN)
  9. bagku秋名山老司机
  10. 云原生背景看这一篇就够了