vyos-1x
vyos-1x copied to clipboard
pbr: T6430: Allow forwarding into VRFs by name as well as route table IDs
Change Summary
My previous PR for simply extending the table ID range was rejected, so I've prepared another PR closer to my own use case for this - "policy based route leaking" between VRFs. It may or may not line up with Bernhard's intention from the original ticket.
This PR extends PBR syntax to allow "set vrf" as well as "set table", resolving table ID from an active VRF and then treating it the same as a "set table".
Types of changes
- [ ] Bug fix (non-breaking change which fixes an issue)
- [x] New feature (non-breaking change which adds functionality)
- [ ] Code style update (formatting, renaming)
- [ ] Refactoring (no functional changes)
- [ ] Migration from an old Vyatta component to vyos-1x, please link to related PR inside obsoleted component
- [ ] Other (please describe):
Related Task(s)
- https://vyos.dev/T6430
Related PR(s)
Component(s) name
- pbr
Proposed changes
- PBR can only target table IDs up to 200 and the previous PR to extend the range was rejected
- PBR with this PR can now also target VRFs directly by name, working around targeting problems for VRF table IDs outside the overlapping 100-200 range
- Validation ensures rules can't target both a table ID and a VRF name (internally they are handled the same)
- Added a simple accessor (get_vrf_table_id) for runtime mapping a VRF name to table ID, based on vyos.ifconfig.interface._set_vrf_ct_zone(). It does not replace that usage, as it deliberately does not handle non-VRF interface lookups (would fail with a KeyError).
The use cases of this feature are limited and you will need to know exactly what you are doing to have it work properly, but for example, when I was experimenting with cross-VRF DNS lookup solutions, this would've been better than manipulating ip rules and nftables manually and externally.
How to test
Rules apply OK:
set name MGT table '666'
set policy route TEST rule 100 destination address '8.8.8.8'
set policy route TEST rule 100 destination port '53'
set policy route TEST rule 100 protocol 'tcp_udp'
set policy route TEST rule 100 set vrf 'MGT'
set policy route TEST2 rule 100 destination address '10.11.12.77'
set policy route TEST2 rule 100 protocol 'tcp_udp'
set policy route TEST2 rule 100 set vrf 'default'
set policy route TEST2 rule 100 source port '53'
Looking at the results:
# sudo ip rule show
220: from all lookup 220
254: from all fwmark 0x7fffff01 lookup main
666: from all fwmark 0x7ffffd65 lookup MGT
1000: from all lookup [l3mdev-table]
2000: from all lookup [l3mdev-table] unreachable
32765: from all lookup local
32766: from all lookup main
32767: from all lookup default
# sudo nft list ruleset
[...]
table ip vyos_mangle {
chain VYOS_PBR_PREROUTING {
type filter hook prerouting priority mangle; policy accept;
}
chain VYOS_PBR_POSTROUTING {
type filter hook postrouting priority mangle; policy accept;
}
chain VYOS_PBR_UD_TEST {
meta l4proto { tcp, udp } ip daddr 8.8.8.8 th dport 53 counter packets 0 bytes 0 meta mark set 0x7ffffd65 return comment "ipv4-route-TEST-100"
}
chain VYOS_PBR_UD_TEST2 {
meta l4proto { tcp, udp } ip daddr 10.11.12.77 th sport 53 counter packets 0 bytes 0 meta mark set 0x7fffff01 return comment "ipv4-route-TEST2-100"
}
}
[...]
Attaching the PBRs to interfaces and watching traffic flow with tcpdump works as expected, the same as set table
.
Smoketest result
$ python3 /usr/libexec/vyos/tests/smoke/cli/test_policy_route.py
test_pbr_group (__main__.TestPolicyRoute.test_pbr_group) ... ok
test_pbr_mark (__main__.TestPolicyRoute.test_pbr_mark) ... ok
test_pbr_mark_connection (__main__.TestPolicyRoute.test_pbr_mark_connection) ... ok
test_pbr_matching_criteria (__main__.TestPolicyRoute.test_pbr_matching_criteria) ... ok
test_pbr_table (__main__.TestPolicyRoute.test_pbr_table) ... ok
----------------------------------------------------------------------
Ran 5 tests in 38.373s
Checklist:
- [x] I have read the CONTRIBUTING document
- [x] I have linked this PR to one or more Phabricator Task(s)
- [x] I have run the components SMOKETESTS if applicable
- [x] My commit headlines contain a valid Task id
- [ ] My change requires a change to the documentation
- [ ] I have updated the documentation accordingly