概述
规则路由(rule route)
这部分详见ip rule命令帮助手册,
https://man7.org/linux/man-pages/man8/ip-rule.8.html
简要总结:
- 支持多种形式的路由查找,不再仅仅局限于根据目的地址查找一种模式。
- rule route采用了类似match-action模式, 不过rule route称之为
SELECTOR
和ACTION
。 SELECTOR
支持多种形式,比如IP、PORT、进出网口、tos以及非操作(not
)ACTION
中几个重要的类型:- table:到指定的TABLE_ID对应的路由表里查找(所以这里要求必须支持多table)
- nat: 支持IP地址nat
- goto: 跳转到指定的rule route,通过这个可以做成多级级联。
几点说明
优先级
rule route是支持优先级的。 通过 ip rule show
命令我们可以看到每条rule对应的优先级。添加rule时候,默认的是当前除0以外最高优先级的值-1, 即默认新建的rule优先级高。
1 | root@martin-Standard-PC-Q35-ICH9-2009:/home/martin# ip rule show |
没有嵌套
rule route里goto 可以反复多次嵌套多条rule,其他action均不能嵌套执行。
比如lookup,table查找的结果就是最终结果,不会再有其他跳转和嵌套。
内核代码解析
根据内核v6.6代码整理
数据结构
每个netns下有个IPv4相关的路由信息变量struct netns_ipv4 ipv4
,
然后通过rules_ops
指向IPv4对应的struct fib_rules_ops
.
在这个ops下有一个rules_list
链表,串联了所有的rule route。
每个rule对应一个结构体struct fib_rule
- 每次增加rule规则时候,
struct netns_ipv4
里的变量fib_has_custom_rules
被更新为true,以记录规则路由被启用了。 - ops的初始化
系统初始化时候,在fib4_rules_init
里,通过复制模版创建一个ops,并把net信息记录到’ops’里。
这个新创建的’ops’又被挂到’net’下的rule_ops
链表里. 最后这个ops被保存到’IPv4’下的rules_ops
1
2
3
4
5
6fib4_rules_init
--> fib_rules_register(&fib4_rules_ops_template, net)
--> --> ops = kmemdup && ops->fro_net = net ;//复制模版创建一个ops,并把net信息记录到ops里。
--> --> __fib_rules_register
--> net->ipv4.rules_ops = ops;
--> net->ipv4.fib_has_custom_rules = false;
1 | 61 struct net { |
1 | 44 struct netns_ipv4 { |
1 | 60 struct fib_rules_ops { |
1 | 20 struct fib_rule { |
函数调用关系
IPv4路由查找的关键函数
+ ip_route_output_flow
:路由查找的入口函数
+ fib_table_lookup
: 在一个具体table里,查找路由
tcp/udp/icmp/raw等类型的socket发送数据时候, 先调用到函数ip_route_output_flow
,进而调用到fib_lookup
,在这里通过宏CONFIG_IP_MULTIPLE_TABLES
并分两种场景支持多table
和单table
- 单table:只有一个
main
路由table表,不支持多table。` - 多table: 支持多个table。这是支持规则路由的一起必要条件。