概述

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网络技术内幕》阅读笔记 --- 路由查找的更多相关文章

  1. 深入理解linux网络技术内幕读书笔记(三)--用户空间与内核的接口

    Table of Contents 1 概论 1.1 procfs (/proc 文件系统) 1.1.1 编程接口 1.2 sysctl (/proc/sys目录) 1.2.1 编程接口 1.3 sy ...

  2. 深入理解linux网络技术内幕读书笔记(十)--帧的接收

    Table of Contents 1 概述 1.1 帧接收的中断处理 2 设备的开启与关闭 3 队列 4 通知内核帧已接收:NAPI和netif_rx 4.1 NAPI简介 4.1.1 NAPI优点 ...

  3. 深入理解linux网络技术内幕读书笔记(九)--中断与网络驱动程序

    Table of Contents 1 接收到帧时通知驱动程序 1.1 轮询 1.2 中断 2 中断处理程序 3 抢占功能 4 下半部函数 4.1 内核2.4版本以后的下半部函数: 引入软IRQ 5 ...

  4. 深入理解linux网络技术内幕读书笔记(四)--通知链

    Table of Contents 1 概述 2 定义链 3 链注册 4 链上的通知事件 5 网络子系统的通知链 5.1 包裹函数 5.2 范例 6 测试实例 概述 [注意] 通知链只在内核子系统之间 ...

  5. 深入理解linux网络技术内幕读书笔记(二)--关键数据结构

    Table of Contents 1 套接字缓冲区: sk_buff结构 1.1 网络选项及内核结构 1.2 结构说明及操作函数 2 net_device结构 2.1 MTU 2.2 结构说明及操作 ...

  6. 深入理解linux网络技术内幕读书笔记(八)--设备注册与初始化

    Table of Contents 1 设备注册之时 2 设备除名之时 3 分配net_device结构 4 NIC注册和除名架构 4.1 注册 4.2 除名 5 设备初始化 6 设备类型初始化: x ...

  7. 深入理解linux网络技术内幕读书笔记(七)--组件初始化的内核基础架构

    Table of Contents 1 引导期间的内核选项 2 注册关键字 3 模块初始化代码 引导期间的内核选项 linux运行用户把内核配置选项传给引导记录,然后引导记录再把选项传给内核. 在引导 ...

  8. 深入理解linux网络技术内幕读书笔记(五)--网络设备初始化

    Table of Contents 1 简介 2 系统初始化概论 2.1 引导期间选项 2.2 中断和定时器 2.3 初始化函数 3 设备注册和初始化 3.1 硬件初始化 3.2 软件初始化 3.3 ...

  9. 深入理解linux网络技术内幕读书笔记(六)--PCI层与网络接口卡

    Table of Contents 1 本章涉及的数据结构 1.1 pci_device_id结构 1.2 pci_dev结构 1.3 pci_driver结构 2 PCI NIC设备驱动程序的注册 ...

  10. 深入理解linux网络技术内幕读书笔记(一)--简介

    Table of Contents 1 基本术语 1.1 本书常用的缩写 2 引用计数 2.1 引用计数函数 3 垃圾回收 3.1 异步 3.2 同步 4 函数指针 4.1 缺点 5 goto语句 5 ...

随机推荐

  1. C语言中的传值调用

    在c语言中每个变量都有两个属性一个是值,一个是址. 比方: int a = 2; 变量a的值是2,变量a的地址,能够用&取地址操作符获取,即&a. 因此以C语言的函数传递中具备两种方式 ...

  2. Postman 常用操作

    一,入参为json 格式 实例:添加学生信息,这个接口是用来讲入参式json 类型的 二,上传文件 三,添加header 信息 实例:获取所有学生信息 四,添加cookie以及身份验证 实例:学生金币 ...

  3. Windows虚拟环境下安装mysql-python

    因为在虚拟环境下安装mysql-python走了许多弯路,特此记录,也希望以后的朋友避免像我一样,被环境配置问题搞的半死 直接使用pip安装mysql-python会报错 pip install My ...

  4. How to add total page to Odoo Report(7.0 version)

    add this codes to your rml file: <drawRightString x="19.5cm" y="0.3cm">Pag ...

  5. Unix系统编程(四)creat系统调用

    我好疑惑啊,creat系统调用为啥没有以e结尾呢?搞得我每次都怀疑我敲错了. 在早期的UNIX实现中,open只有两个参数,无法创建新文件,而是使用creat系统调用创建并打开一个新文件. int c ...

  6. 微信小程序-page

    一 什么是page() page(),是一个函数,用来注册一个页面, 接受一个object参数, 指定页面的初始数据,生命周期函数,事件处理函数 等等 object参数说明: (1)data (obj ...

  7. Could not load type ‘System.ServiceModel.Activation.HttpModule’ from&

    1. 部署网站到IIS7.5,Window 2008的时候出现这个错误   2. 错误信息 Server Error in ‘/’ Application. Could not load type ‘ ...

  8. 关联数据和formatter问题-easyui+微型持久化工具

    控制器 using System; using System.Collections.Generic; using System.Linq; using System.Web; using Syste ...

  9. Java语言中两种异常的差别

    Java提供了两类主要的异常:runtime exception和checked exception.所有的checked exception是从java.lang.Exception类衍生出来的,而 ...

  10. datagrid使用要点

    table自适应: (fit:true(设置table)) 列自动撑开:fitColumns: true,注意给列的width属性赋值