linux内核协议栈之路由选择

linux内核协议栈之路由选择

Posted by lwk on February 3, 2020

之前在分析TCP内核协议栈的3次握手过程中涉及到了路由选择,也就是TCP在连接建立过程中会选择下一跳地址,今天就详细阐述下内核是怎么进行路由选择的。

首先,进入到内核代码的tcp_v4_connect函数,这里是client在调用connect时触发的内核部分代码

image

其中,ip_route_connect是路由选择核心部分。 image 对于熟悉linux下socket编程的同学都清楚,client端主要执行逻辑是socket->connect->send->recv,在执行connect的时候和server端建立连接,从内核代码可以看出,建立连接过程涉及到的client源端口和源地址都是在tcp_v4_connect中处理的,其中路由策略则是在ip_route_connect中处理。

由于刚开始源地址为0,因此执行__ip_route_output_key image

image

image

image

image 如果系统配置了路由规则,则进入__fib_lookup,通过fib_rules_lookup查询对应的路由表

image 进入fib_rules_lookup函数,该函数主要逻辑是对路由策略链表进行遍历,查找匹配的规则项。

image

image

image

其中ops->match和ops->action调用的是net/ipv4/fib_rules.c对应的fib4_rule_action和fib4_rule_match,匹配规则也不难,就是用源地址、目的地址以及掩码进行对比。并返回是否命中。

如果没有配置路由规则,则查询main表和默认路由表。并返回是否命中。

这里说下linux的路由表:

Linux内核最多支持255个路由表,每张路由表有一个table id和table name。其中有4张表是linux系统内置的

(1)table id = 0

系统保留。

(2)table id = 255

称为本地路由表,表名为local。像本地接口地址,广播地址,以及NAT地址都放在这个表。该路由表由系统自动维护,管理员不能直接修改。

(3)table id = 254

称为主路由表,表名为main。如果没有指明路由所属的表,所有的路由都默认都放在这个表里。一般来说,旧的路由工具(如route)所添加的路由都会加到这个表。main表中路由记录都是普通的路由记录。而且,使用ip route配置路由时,如果不明确制定要操作的路由表,默认情况下也是主路由表(表254)进行操作。

备注:我们使用ip route list 或 route -n 或 netstat -rn查看的路由记录,也都是main表中记录。

(4)table id = 253

称为默认路由表,表名为default。一般来说默认的路由都放在这张表。

并且路由表的数据结构是trie,中文名叫字典树,本文就不介绍该数据结构了。

image 当fib_lookup失败时,如果type是本地路由,则进行make_route操作,更新路由表并返回。