《深入理解Linux网络技术内幕》阅读笔记 --- 路由查找
概述
1、不论是入口还是出口流量,都是利用fib_lookup来查找路由表,fib_lookup是对每一个路由表所提供的查找函数的包裹函数,当不支持策略路由时,查找函数版本针对的是local表和main表

2、辅助函数:
- fib_validate_source:对从一个给定设备接收到的封包的源IP地址检查,检测企图的IP欺骗,而且要在开启非对称路由情况下,确保封包的源IP地址通过该封包接收接口是可达的。另外,该函数也返回用于反方向的首选源地址spec_dst,并初始化路由标签(routing tag)
- inet_select_addr:给定一个设备dev,一个IP地址dst和一个scope,返回为scope的第一个主地址,用于从设备dev向dst发送封包。如果dev上配置的地址都不满足由scope和dst限定的条件,则该函数尝试其他设备,检验是否存在一个IP地址,配置所要求的scope
- rt_set_nexthop:给定一个路由缓存项rtable和一个路由查找结果res,完成rtable的各字段的初始化,如rt_gateway,嵌入dst_entry的metrics向量等
3、fn_hash_lookup搜索一个能够将封包路由到特定目的地的fib_node实例。
4、初始化入口流量的函数指针:入口IP流量是由ip_rcv_finish处理,该函数参照路由表来决定将封包送往本地还是丢弃。在路由缓存不命中的情况下,ip_route_input_slow可以创建以下三种dst->input和dst->output的组合:
- 当封包被转发时,函数将dst->input初始化为ip_forward,将dst->output初始化为ip_output。所以dst_output将调用ip_forward,而在ip_forward的结尾处间接调用dst_output,即ip_output
- 如果封包被送往本地,函数将dst->input初始化为ip_local_deliver,此时不需要初始化dst->output,但它还是被初始化为ip_rt_error,用于检测在处理送往本地封包的dst->ouput是否被错误调用
- 如果根据路由表得出目的地址不可达,dst->input被初始化为ip_error,这将产生一个ICMP消息,消息类型依赖于路由查找返回的准确结果,因为ip_error将skb缓冲区释放,所以不需要初始化dst->output,因为即使在犯错情况下它也不会被调用
5、初始化出口流量的函数指针:同理ip_route_output_slow可以创建以下四种dst->input和dst->output的组合:
- 如果目的地是远程主机,dst->output初始化为ip_output,同理我们可以将dst->input初始化为ip_rt_error
- 如果目的地是本地系统,函数将dst->output初始化为ip_output,将dst->input初始化为ip_local_deliver。这样可以形成一个循环,当dst_ouput调用ip_output时,后者将封包通过loopback设备送出,导致ip_rcv和ip_rcv_finish的执行。ip_rcv_finish检查入口缓冲区,看到skb->dst中已经存在路由信息,因此调用dst_input,启用ip_local_deliver
- 如果目的地是本地配置的多播IP地址,函数将dst->output初始化为ip_mc_output,接下来由多播代码来处理该封包,此时不初始化dst->output
- 当内核编译为支持多播路由时,仍然将dst->output初始化为ip_mc_output,但同时将dst->input初始化为ip_mr_input函数
6、不论是否支持多路径缓存,路由缓存表项的分配和初始化都是通过__mkroute_input和__mkroute_output来完成的,无论ip_route_input_slow或ip_route_output_slow触发将新的路由表项插入到缓存内的操作时,都是调用rt_intern_hash函数来执行
7、首选源地址:添加到路由缓存的路由项是单向的,意味着将用于被路由封包源IP地址的反方向上的流量,不能使用该路由项来进行路由,然而在某些情况下,接收到封包可能触发一个动作,要求本地主机选择一个源IP地址,以便在向发送方回送封包时使用,这个地址即首选源地址。首选源地址的选择如下:

8、路由失败:当一个封包由于主机配置或者由于没有路由匹配而不能被路由时,一个新的路由项就被添加到缓存中,该路由的dst->input被初始化为ip_error。这意味着所有匹配该路由的入口封包将由ip_error来处理。将错误路由添加到缓存中是有意义的,因为这样可以加速对后续发送给同样不正确地址的封包错误进行处理
9、输出路由:不论将封包送往本地或者转发出去,两者都需要执行以下任务:(1)、从匹配的路由项中选择处使用的出口设备,(2)根据被搜索路由项的scope选择出要使用的源IP地址,(3)、创建及初始化一个新缓存表项,并将它插入到缓存中
10、因为调用ip_route_output_slow只是为了路由本地产生的流量,所以搜索关键字fl中的源设备被初始化为回环设备,同时,如果目的地址也是本地地址,那么出口地址也被初始化为回环设备
11、路由时,源IP地址的选择如下:

12、当fib_lookup看到封包的目的地址是本地配置地址,或者当封包中没有提供目的地址时(即搜索包含了未知地址0.0.0.0),该封包被送往本地。在这种情况下,出口设备被设置为回环地址,这意味着封包不会离开本地主机,该封包被发送后重新输入到IP输入栈。dst->input被初始化为ip_local_deliver,当封包重新注入IP输入栈时,ip_rcv_finish将启用dst_input,即启用ip_local_deliver函数来处理该封包。注意:当搜索关键字中,源IP地址和目的IP地址都没有被设置时,封包被送往本地,源地址和目的地址被设置为默认回环地址127.0.0.1(INADDR_LOOPBACK),该地址的scope为RT_SCOPE_HOST

13、当查找返回的路由是默认路由时,需要选择使用默认网关。这是由fib_select_default来完成的。(当res.prefixlen字段为0时表示是默认路由,这表示“前缀长度”,即与该地址相关的网络掩码长度为0)
14、即使fib_lookup路由查找失败,但还是可能成功地将封包发送出去,当搜索关键字提供了出口设备,ip_route_output_slow假定通过该出口设备可以直接到达目的地。在这种情况下,如果还没有源IP地址,则还需要设置一个scope为RT_SCOPE_LINK的源IP地址,可能的情况下用的是该出口设备上的一个地址
《深入理解Linux网络技术内幕》阅读笔记 --- 路由查找的更多相关文章
- 深入理解linux网络技术内幕读书笔记(三)--用户空间与内核的接口
Table of Contents 1 概论 1.1 procfs (/proc 文件系统) 1.1.1 编程接口 1.2 sysctl (/proc/sys目录) 1.2.1 编程接口 1.3 sy ...
- 深入理解linux网络技术内幕读书笔记(十)--帧的接收
Table of Contents 1 概述 1.1 帧接收的中断处理 2 设备的开启与关闭 3 队列 4 通知内核帧已接收:NAPI和netif_rx 4.1 NAPI简介 4.1.1 NAPI优点 ...
- 深入理解linux网络技术内幕读书笔记(九)--中断与网络驱动程序
Table of Contents 1 接收到帧时通知驱动程序 1.1 轮询 1.2 中断 2 中断处理程序 3 抢占功能 4 下半部函数 4.1 内核2.4版本以后的下半部函数: 引入软IRQ 5 ...
- 深入理解linux网络技术内幕读书笔记(四)--通知链
Table of Contents 1 概述 2 定义链 3 链注册 4 链上的通知事件 5 网络子系统的通知链 5.1 包裹函数 5.2 范例 6 测试实例 概述 [注意] 通知链只在内核子系统之间 ...
- 深入理解linux网络技术内幕读书笔记(二)--关键数据结构
Table of Contents 1 套接字缓冲区: sk_buff结构 1.1 网络选项及内核结构 1.2 结构说明及操作函数 2 net_device结构 2.1 MTU 2.2 结构说明及操作 ...
- 深入理解linux网络技术内幕读书笔记(八)--设备注册与初始化
Table of Contents 1 设备注册之时 2 设备除名之时 3 分配net_device结构 4 NIC注册和除名架构 4.1 注册 4.2 除名 5 设备初始化 6 设备类型初始化: x ...
- 深入理解linux网络技术内幕读书笔记(七)--组件初始化的内核基础架构
Table of Contents 1 引导期间的内核选项 2 注册关键字 3 模块初始化代码 引导期间的内核选项 linux运行用户把内核配置选项传给引导记录,然后引导记录再把选项传给内核. 在引导 ...
- 深入理解linux网络技术内幕读书笔记(五)--网络设备初始化
Table of Contents 1 简介 2 系统初始化概论 2.1 引导期间选项 2.2 中断和定时器 2.3 初始化函数 3 设备注册和初始化 3.1 硬件初始化 3.2 软件初始化 3.3 ...
- 深入理解linux网络技术内幕读书笔记(六)--PCI层与网络接口卡
Table of Contents 1 本章涉及的数据结构 1.1 pci_device_id结构 1.2 pci_dev结构 1.3 pci_driver结构 2 PCI NIC设备驱动程序的注册 ...
- 深入理解linux网络技术内幕读书笔记(一)--简介
Table of Contents 1 基本术语 1.1 本书常用的缩写 2 引用计数 2.1 引用计数函数 3 垃圾回收 3.1 异步 3.2 同步 4 函数指针 4.1 缺点 5 goto语句 5 ...
随机推荐
- Postman 常用操作
一,入参为json 格式 实例:添加学生信息,这个接口是用来讲入参式json 类型的 二,上传文件 三,添加header 信息 实例:获取所有学生信息 四,添加cookie以及身份验证 实例:学生金币 ...
- 关于MBR、GPT以及BIOS引导模式区分
关于MBR.GPT.ESP.MSR.EFI.UEFI和WIN8中SECURE BOOT的基础知识: 1.MBR分区表:Master Boot Record,即硬盘主引导记录分区表,只支持容量在 2.1 ...
- c++的set_unexpected不起作用
代码是从:http://www.cplusplus.com/referen ... /?kw=set_unexpected找的 // set_unexpected example #include & ...
- Javaweb开发中关于不同地方出现的绝对路径和相对路径
1.转发和包含路径 a)以“/”开头:相对当前项目路径,即默认为http://localhost:8080/项目名/ b)不以“/”开头:相对当前Servlet路径. eg:在Aservlet中写“B ...
- ecmall的物流配送体系改造
接触多了ecshop.ecmall原始逻辑的,一般都习惯以整单的方式统一计算运费,这是一种很简单的思路. 但淘宝多了,就发现,物流运费没有那么简单. 首先,每种商品单独设置运费的体系,或者叫运费模板: ...
- glibc中malloc的详细解释_转
glibc中的malloc实现: The main properties of the algorithms are:* For large (>= 512 bytes) requests, i ...
- cocos2dx3.1 win7安装步骤及编译到安桌
1. 下载及安装好工具 python2.7 ndk sdk ant cocos2dx3.1 eclipse 这些工具和曾经一样下载好放到同一文件夹下 加入环境变量 将python2.7的安装路径加入 ...
- Python 使用标准库根据进程名获取进程PID
应用场景 在进行 Linux 运维的环境中,我们经常会遇到维护同一台服务器上的多个程序,涉及到程序的启动.关闭和重启操作. 通常这些程序之间存在着相互依存的关系需要进行依次的启动关闭操作. 下面介绍几 ...
- find命令结合cp bash mv 命令使用的4种方式
工作经常需要用find结合其它命令一起使用,下面介绍4种结合方式. 例: 用find查找/data目录下,以.txt文件结尾的文件并复制到/tmp下 方法一 find与|xargs是黄金搭档,-t 参 ...
- linux下的线程池
什么时候需要创建线程池呢?简单的说,如果一个应用需要频繁的创建和销毁线程,而任务执行的时间又非常短,这样线程创建和销毁的带来的开销就不容忽视,这时也是线程池该出场的机会了.如果线程创建和销毁时间相比任 ...