《深入理解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地址,可能的情况下用的是该出口设备上的一个地址

原文地址:https://www.cnblogs.com/YaoDD/p/7132249.html