版本说明

Linux版本: 3.10.103

网卡驱动: ixgbe

网络协议注册

inet_init主要是注册各种协议

注册TCP协议proto_register(&tcp_prot, 1)

继续注册UDP、RAW、PING

arp_init, ip_init, tcp_init, udp_init, ping_init, icmp_init

dev_add_pack(&ip_packet_type)主要是注册ip报文处理函数ip_rcv到pttype_base。

arp_init-->dev_add_pack(&arp_packet_type)主要是注册arp报文处理函数arp_rcv到pttype_base。

报文处理

网卡调用__netif_receivve_skb_core后,会调用deliver_skb(skb, pt_prev, orig_dev)处理对应的3层协议函数。

ip协议

ip_rcv主要获取报文头,报文健康检查,最后进入NF_HOOK(NFPROTO_IPV4, NF_INET_PRE_ROUTING,...,ip_rcv_finish)。

ip_rcv_finish进行路由查找,ip_route_input_noref-->ip_route_input_slow进行慢速路由判定。

ip_route_input_slow判定报文是本地的话,就给input装载ip_local_deliver函数,如果不是本地继续调用ip_mkroute_input-->__mkroute_input查找路由,并且给input装载ip_forward函数,output装载ip_output。

ip_local_deliver函数直接进入NF_HOOK(NFPROTO_IPV4, NF_INET_LOCAL_IN,..., ip_local_deliver_finish)。

ip_local_deliver_finish调用ipprot->handler进入4层的协议处理函数。

ip_forward进入NF_HOOK(NFPROTO_IPV4, NF_INET_FORWARD,..., ip_forward_finish)。

ip_forward_finish调用output装载的ip_output。

ip_output进入NF_HOOK(NFPROTO_IPV4, NF_INET_POST_ROUTING,...,ip_finish_output)

ip_finish_output进行分片的判断和操作,此处涉及到GSO的判定,最后调用ip_finish_output2。

ip_finish_output2调用__ipv4_neigh_lookup_noref进行邻居子系统的表查找,ipv4主要是arp表,查找到arp表,则调用dst_neigh_output-->neigh_hh_output-->dev_queue_xmit进行报文发送。

如果没有查找到,则调用__neigh_create-->arp_constructor进行发送等函数的装载,最后也调用dst_neigh_output,然后也调用装载的发送函数,将报文修改为request,调用dev_queue_xmit进行发送。

arp协议

arp_rcv健康检查后,进入NF_HOOK(NFPROTO_ARP, NF_ARP_IN, ..., arp_process)

arp_process完成了所有的处理操作,包括是reply报文则更新arp表;如果是request本地的话,则更新或者创建arp表,并且调用arp_send回复arp报文;如果不是本地不支持arp proxy的话,丢弃报文;支持的话转发报文。

arp_send调用arp_create创建报文,并且调用arp_xmit发送报文。

arp_xmit进入NF_HOOK(NFPROTO_ARP, NF_ARP_OUT, ..., dev_queue_xmit_sk),最后调用dev_queue_xmit发送报文。

转发流程

邻居子系统

Generic neighbouring interface(VFT),为上层协议提供了一个统一的输出接口neigh->output()。

Generic neighbouring interface,为下层提供的也是一个统一的接口dev_queue_xmit()。

ARP是为IPV4设计的地址解析协议,而ND(neighbour detect)则是为IPv6设计的。这些地址解析协议可以说是“嵌入”在邻居子系统里面,但是又可以自由灵活的拆卸,非常方便。

为了加速数据包的发送速度,会将路由表和邻居缓存进行绑定,这个绑定其实就是把邻居缓存中的每个项的结构体嵌入路由表中的一个路由项中,这样报文在查找到路由以后,其实也相当于已经在邻居子系统中查到了缓存,减少了查找的次数。这样在进入邻居子系统后的处理流程就很短。

struct neigh_table :邻居表,每个地址解析协议就会创建这样的一个表(比如arp)

struct neighbour :邻居项代表一个邻居。邻居项用哈希表+链表链的组织方式

struct hh_cache :这个字段存的就是封装好的二层协议头部,每个报文在进入邻居子系统前都会查找路由,路由项中就会包含这hh_cache这个结构

状态机

邻居项存在一种状态机,邻居项都有一个对于管理和维护邻居表来说非常重要的成员,nud_state,用来表示该邻居项当前所处的状态。下面依依介绍这几个状态:

NUD_NONE:邻居项刚建立时处于的状态,在该状态下,还没有硬件地址可以用,所以还不能发送请求报文。一旦有报文要输出到该邻居,便会出发对该邻居硬件地址的请求,进入NUD_INCOMPLETE状态,并缓存发送的报文。

NUD_INCOMPLETE:该状态是请求报文已发送,但尚未收到应答的状态。该状态下还没解析到硬件地址,因此尚无可用硬件地址,如果有报文要输出到该邻居,会将其缓存起来。这个状态会启动一个定时器,如果在定时器到期时还没有接收到邻居的回应,则会重复发送请求报文,否则发送请求报文的次数打到上限,便会进入NUD_FAILED。

NUD_REACHABLE:该状态以及得到并缓存了邻居的硬件地址。进入该状态首先设置邻居项相关的output函数(该状态使用neighbors_ops结构的connectd_outpt),然后查看是否存在要发送给该邻居的报文。如果在该状态下闲置时间达到上限,便会进入NUD_STATLE。

NUD_STATLE:该状态一旦有报文要输出到该邻居,则会进入NUD_DELAY并将该报文输出。如果在该状态下闲置时间达到上限,且此时的引用计数为1,则通过垃圾回收机制将其删除,在该状态下,报文的输出不收限制,使用慢速发送过程。

NUD_DELAY:该状态下表示NUD_STATE状态下发送的报文已经发出,需得到邻居的可达性确认的状态。在为接收到邻居的应答或确认时也会定时地重发请求,如果发送请求报文的次数到上限,如果收到邻居的应答,进入NUD_REACHABLE,否则进入NUD_FAILED,在该状态下,报文的输出不收限制,使用慢速发送过程。

操作

neigh_create:

创建一个neighbour项结构,当以下情况发生:

传输请求:向一台L2地址未知的主机传输请求,就需要对这个地址进行解析。

收到solicitation请求:收到这个请求的主机会假定两个系统有通信发生,会创建一个缓存项。

手工添加:手工添加一个邻居缓存项。

neigh_release:

这个函数会减少neighbour的引用计数,当引用计数为0时,才真正删除neighbour结构,这个函数真正调用neigh_destroy。以下是函数调用的原因:

内核企图向一个不可到达的主机发送报文。

与这个邻居结构相关的L2地址改变了。

邻居结构存在的时间太长,内核需要它占用的内存。

neigh_update:

更新neighbour状态和链路层地址。流程如下:

更新状态不是NUD_VALID态的邻居发生的变化,主要是状态机和neigh->output。

更新L2地址,给状态不是NUD_VALID态的邻居使用。

设置一个新的链路层地址。

改变NUD状态。

处理arp_queue队列。

arp例子

linux内核的邻居表,Linux内核报文收发-L3 - Section 3. IP协议、邻居子系统主要是接收、转发和发送三部分...相关推荐

  1. linux终端分辨率对应表,Linux下设置终端分辨率,最全的VGA代码和分辨率对照表...

    一般安装完linux后默认的kernel给的tty分辨率是非常有限的,解决的方法就是给kernel传递VGA参数.对应的要修改的配置文件为 /etc/grub.conf,(或者 /boot/grub/ ...

  2. linux无法同步数据库表,Linux数据库:MySQL主从同步设置和同步错误处理

    注意: 1.两台服务器数据库版本应一致,如果不一致,从服务器的版本要高于主服务器的版本. 2.MySQL进行实时数据同步,本质上是将mysql动作同步到Slave服务器,而不是对实质的数据进行同 步. ...

  3. linux系统mysql创建表,Linux系统下手动新建数据库

    1.设置环境变量和SID [oracle@server01 dbs]$ORACLE_BASE=/opt/oracle [oracle@server01 dbs]$ export ORACLE_BASE ...

  4. linux 查看ko符号表,linux modprobe命令参数及用法详解--linux加载模块命令

    modprobe(module probe) 功能说明:自动处理可载入模块. 语 法:modprobe [-acdlrtvV][--help][模块文件][符号名称 = 符号值] 补充说明:modpr ...

  5. 【转】Linux内核报文收发

    赵占旭的博客 Linux内核报文收发-网卡部分 https://zhaozhanxu.com/2016/07/12/Linux/2016-07-12-Linux-Kernel-Pkts_Process ...

  6. 邻居表项的delay_probe_time时长

    delay_probe_time控制首次发送邻居请求报文的等待时长,对于arp协议,内核默认的delay_probe_time时长为5秒钟. struct neigh_table arp_tbl = ...

  7. 邻居表项的retrans_time时长

    retrans_time控制在发送过邻居地址探测报文之后,经过多长时间检测邻居表项的变化,如果检测不成功,进行重新探测,对于arp协议,内核默认的retrans_time为1秒钟. 通过PROC文件r ...

  8. 邻居表项的STALE状态超时时间

    对于arp协议,内核默认的STALE状态超时时长为60秒钟. struct neigh_table arp_tbl = {.family = AF_INET,.key_len = 4,.protoco ...

  9. IP协议详解【IP报文头部结构、IP分片、IP路由、IP转发】

    目录 IP协议:全称:Internet Protocol(网际互连协议) IP协议的特点: IP头部结构: IP分片: IP路由: IP转发: IP协议:全称:Internet Protocol(网际 ...

最新文章

  1. gps两点距离 php,PHP应用:PHP计算百度地图两个GPS坐标之间距离的方法
  2. DAY4-打卡第四天-2018-1-12
  3. oracle中dlink使用,Oracle,MetaLink,中文使用指南
  4. 云原生系列「二」Kubernetes网络详解
  5. 硬盘的原理以及SQL Server如何利用硬盘原理减少IO
  6. Ananagrams Uva 156
  7. MYSQL 数学运算符问题
  8. 推荐系统遇上深度学习(七)--NFM模型理论和实践
  9. c++中的智能指针怎样释放连续的资源?
  10. 只用一行代码,就导入Python所有库
  11. var radioname = new array();_体坛观察丨争议判罚不止中超 为何VAR屡成足坛焦点?_足球...
  12. Seldom2.0: 如何更简单的实现HTTP接口测试
  13. 2、数字,字符串,列表,字典,集合
  14. 计算机四级网络考试容易蒙吗,计算机四级网络工程师通过率有多少
  15. 如何实现施耐德Twido系列PLC远程上下载
  16. 装系统缺少硬盘驱动_缺少操作系统-向我学习,请在今年备份您的硬盘!
  17. GitLab 注册 Runner Registering Runners
  18. 关于学习管理系统 LMS
  19. 怎么给PDF添加页面?推荐三个PDF如何插入页面小妙招
  20. neuq计算机与通信工程学院,王新宇

热门文章

  1. 安装zabbix及LNMP的平台的搭建
  2. 比较TFS与SVN,你必须知道的10点区别
  3. visual studio 2015 搭建python开发环境,python入门到精通[三]
  4. EAT/IAT Hook
  5. Windows 8 JavaScript Metro应用程序--入门(上)
  6. [密码学基础][每个信息安全博士生应该知道的52件事][Bristol Cryptography][第39篇]侧信道攻击和故障攻击有什么区别
  7. HDU 5787 wolf Number 数位dp
  8. 提高电脑反应速度_设计师笔记本电脑推荐——视觉系ThinkBook 15p创造本
  9. 安川最小巧机器人_2020工博会,安川展品前瞻(机器人篇)
  10. 车载电脑中控软件_数字图书馆智能化系统集成-ipad中控软件