简介
所谓策略路由,顾名思义,即是根据一定的策略进行报文转发,因此策略路由是一种比目的路由更灵活的路由机制。在路由器转发一个数据报文时,首先根据配置的规则对报文进行过滤,匹配成功则按照一定的转发策略进行报文转发。这种规则可以是基于标准和扩展访问控制列表(acl),也可以基于报文的长度;而转发策略则是控制报文按照指定的策略路由表进行转发,也可以修改报文的IP优先字段。因此,策略路由是对传统IP路由机制的有效增强。
具体实现
传统设备中策略路由分为强策略和弱策略。参照华为的ME60实现: 如果指定了出接口,表示强策略,不会查fib表,直接根据吓一跳和出接口进行转发。 如果未指定出接口,表示弱策略,会根据指定的吓一跳查fib表,如果查表成功根据查询结果进行转发,查找失败的话就根据报文目的ip进行转发;否则丢弃。
还支持2中配置方式:set ip next-hop和set ip default next-hop命令十分类似,但是操作的顺序完全不同。 1、set ip next-hop命令使得路由器首先检查策略路由,不符合策略后使用路由表进行数据包转发处理; 2、set ip default next-hop命令使得路由器首先检查路由表,若发现没有明确路由则使用策略路由进行数据包转发处理。 处理逻辑如下图所示:
VPP中策略路由叫法ABF(ACL Based Forwarding 基于acl的转发)。abf的实现应该没有区分强策略和弱策略吧,都按照弱策略来实现的。
配置使能:
1、配置acl 目前acl只支持通过vat或api方式进行配置,不支持通过命令行方式来下发配置。
代码语言:javascript复制#acl下发时,必须先申请一个acl索引,再下发acl规则
vat# acl_add_replace permit, ipv4 permit
#下发多条规则时,中间需要用逗号隔开。
vat# acl_add_replace 0 ipv4 permit dst 192.168.100.3/32 , deny dst 192.168.101.3/32
vl_api_acl_add_replace_reply_t_handler:108: ACL index: 0
下面是查询acl配置内容
代码语言:javascript复制vpp# show acl-plugin acl index 0
acl-index 0 count 2 tag {}
0: ipv4 permit src 0.0.0.0/0 dst 192.168.100.3/32 proto 0 sport 0-65535 dport 0-65535
1: ipv4 deny src 0.0.0.0/0 dst 192.168.101.3/32 proto 0 sport 0-65535 dport 0-65535
used in lookup context index: 0
2、配置abf policy 下发policy id为0,acl索引为0,下一跳为192.168.200.1的规则.
代码语言:javascript复制 vpp# abf policy add id 2 acl 0 via 192.168.200.1
查询abf policy表项:
代码语言:javascript复制vpp# show abf policy 2
abf:[0]: policy:2 acl:0
path-list:[18] locks:1 flags:shared,no-uRPF, uPRF-list:18 len:1 itfs:[2, ]
path:[18] pl-index:18 ip4 weight=1 pref=0 recursive: oper-flags:resolved,
via 192.168.200.1 in fib:0 via-fib:15 via-dpo:[dpo-load-balance:17]
3、绑定接口
代码语言:javascript复制vpp# abf attach ip4 policy 2 eth2
查询接口Abf绑定情况
代码语言:javascript复制b# show abf attach eth2
ipv4:
abf-interface-attach: policy:2 priority:0
[@1]: dpo-load-balance: [proto:ip4 index:17 buckets:1 uRPF:20 to:[0:0]]
[0] [@5]: ipv4 via 192.168.200.1 eth3: mtu:1500 005056c00003000c29c0ae840800
测试
大致组网如下:
代码语言:javascript复制pc(192.168.100.1)<--->(192.168.100.3)eth2 (vpp) eth3 (192.168.200.3)<--->pc2(192.168.200.1)
在控制台ping 192.168.100.3,发现报文从eth3接口发送,测试abf功能生效。
代码语言:javascript复制00:03:51:315188: ethernet-input
frame: flags 0x3, hw-if-index 1, sw-if-index 1
IP4: 00:50:56:c0:00:02 -> 00:0c:29:c0:ae:7a
00:03:51:315192: ip4-input-no-checksum
ICMP: 192.168.100.1 -> 192.168.100.3
tos 0x00, ttl 128, length 60, checksum 0xe083
fragment id 0x10e8
ICMP echo_request checksum 0x4ce7
00:03:51:315199: abf-input-ip4 # abf已经生效,报文按照配置进行转发
next 1 index 17
00:03:51:315211: ip4-load-balance
fib 0 dpo-idx 2 flow hash: 0x00000000
ICMP: 192.168.100.1 -> 192.168.100.3
tos 0x00, ttl 128, length 60, checksum 0xe083
fragment id 0x10e8
ICMP echo_request checksum 0x4ce7
00:03:51:315228: ip4-rewrite
tx_sw_if_index 2 dpo-idx 2 : ipv4 via 192.168.200.1 eth3: mtu:1500 005056c00003000c29c0ae840800 flow hash: 0
x00000000
00000000: 005056c00003000c29c0ae8408004500003c10e800007f01e183c0a86401c0a8
00000020: 640308004ce7000100746162636465666768696a6b6c6d6e6f707172
00:03:51:315234: eth3-output
eth3
去掉abf功能后,可以正常ping通,下图流程中命中本地路由,回复relay报文。
代码语言:javascript复制00:34:58:715270: ip4-input-no-checksum
ICMP: 192.168.100.1 -> 192.168.100.3
tos 0x00, ttl 128, length 60, checksum 0xe07b
fragment id 0x10f0
ICMP echo_request checksum 0x4cdf
00:34:58:715272: ip4-lookup
fib 0 dpo-idx 5 flow hash: 0x00000000
ICMP: 192.168.100.1 -> 192.168.100.3
tos 0x00, ttl 128, length 60, checksum 0xe07b
fragment id 0x10f0
ICMP echo_request checksum 0x4cdf
00:34:58:715274: ip4-local
ICMP: 192.168.100.1 -> 192.168.100.3
tos 0x00, ttl 128, length 60, checksum 0xe07b
fragment id 0x10f0
ICMP echo_request checksum 0x4cdf
测试配置下一跳无32位路由只存在网段路由情况。 配置下一跳是同网段不存在ip地址。默认会按照指定的下一跳转发,发送arp请求报文:192.168.200.5.
代码语言:javascript复制vpp# show abf policy
abf:[0]: policy:2 acl:0
path-list:[18] locks:1 flags:shared,no-uRPF, uPRF-list:23 len:1 itfs:[2, ]
path:[25] pl-index:18 ip4 weight=1 pref=0 recursive: oper-flags:resolved,
via 192.168.200.5 in fib:0 via-fib:17 via-dpo:[dpo-load-balance:19]
#trace路径:
00:41:56:093552: ip4-input-no-checksum
ICMP: 192.168.100.1 -> 192.168.100.3
tos 0x00, ttl 128, length 60, checksum 0xe06f
fragment id 0x10fc
ICMP echo_request checksum 0x4cd3
00:41:56:093555: abf-input-ip4
next 1 index 19
00:41:56:093561: ip4-load-balance
fib 0 dpo-idx 4 flow hash: 0x00000000
ICMP: 192.168.100.1 -> 192.168.100.3
tos 0x00, ttl 128, length 60, checksum 0xe06f
fragment id 0x10fc
ICMP echo_request checksum 0x4cd3
00:41:56:093564: ip4-arp
ICMP: 192.168.100.1 -> 192.168.100.3
tos 0x00, ttl 128, length 60, checksum 0xe06f
fragment id 0x10fc
ICMP echo_request checksum 0x4cd3
00:41:56:093577: eth3-output
eth3
ARP: 00:0c:29:c0:ae:84 -> ff:ff:ff:ff:ff:ff
request, type ethernet/IP4, address size 6/4
00:0c:29:c0:ae:84/192.168.200.3 -> 00:00:00:00:00:00/192.168.200.5
测试下一跳查询不到fib情况下,会创建一个32位的路由,动作是drop。
代码语言:javascript复制ucpe-cli-vb# show ip fib 192.168.201.2
ipv4-VRF:0, fib_index:0, flow hash:[src dst sport dport proto ] locks:[src:plugin-hi:2, src:adjacency:2, src:recursive-resolution:1, src:default-route:1, ]
192.168.201.2/32 fib:0 index:18 locks:3
src:recursive-resolution refs:1 src-flags:added,contributing,active, cover:0
path-list:[0] locks:4 flags:drop, uPRF-list:0 len:0 itfs:[]
path:[0] pl-index:0 ip4 weight=1 pref=0 special: cfg-flags:drop,
[@0]: dpo-drop ip4
forwarding: unicast-ip4-chain
[@0]: dpo-load-balance: [proto:ip4 index:21 buckets:1 uRPF:0 to:[0:0]]
[0] [@0]: dpo-drop ip4
ucpe-cli-vb# show abf policy
abf:[0]: policy:2 acl:0
path-list:[18] locks:1 flags:shared,no-uRPF, uPRF-list:23 len:0 itfs:[]
path:[18] pl-index:18 ip4 weight=1 pref=0 recursive:
via 192.168.201.2 in fib:0 via-fib:18 via-dpo:[dpo-load-balance:21]
这个就有点意思,应该不符合策略路由的规则,配置中需要小心了。个人觉得是个bug。
总结
本文参考了csdn博客:
(https://blog.csdn.net/weixin_40815457/article/details/86523457)
简单介绍了vpp abf的功能的基本配置及相关命令行,trace跟踪了基本的流程。也手动尝试几种异常的场景配置下的处理逻辑。希望对初学者有所帮助。
☞还有一个比较有用的信息值得我们去借鉴,就是acl和abf是两个so,理论山不能abf不能访问acl库中的函数。具体如何实现的需要好好研究一下。