Skip to content

Commit

Permalink
pbr: T6430: Allow forwarding into VRFs by name as well as route table…
Browse files Browse the repository at this point in the history
… IDs

* 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).
  • Loading branch information
talmakion committed Jun 29, 2024
1 parent 206c07a commit af86aa5
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 6 deletions.
17 changes: 17 additions & 0 deletions interface-definitions/include/policy/route-common.xml.i
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,23 @@
</completionHelp>
</properties>
</leafNode>
<leafNode name="vrf">
<properties>
<help>VRF to forward packet with</help>
<valueHelp>
<format>default</format>
<description>Forward into default global VRF</description>
</valueHelp>
<valueHelp>
<format>txt</format>
<description>VRF instance name</description>
</valueHelp>
<completionHelp>
<path>vrf name</path>
</completionHelp>
#include <include/constraint/vrf.xml.i>
</properties>
</leafNode>
<leafNode name="tcp-mss">
<properties>
<help>TCP Maximum Segment Size</help>
Expand Down
10 changes: 10 additions & 0 deletions python/vyos/firewall.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
from vyos.utils.dict import dict_search_recursive
from vyos.utils.process import cmd
from vyos.utils.process import run
from vyos.utils.network import get_vrf_table_id

# Conntrack
def conntrack_required(conf):
Expand Down Expand Up @@ -469,11 +470,20 @@ def parse_rule(rule_conf, hook, fw_name, rule_id, ip_name):
if 'mark' in rule_conf['set']:
mark = rule_conf['set']['mark']
output.append(f'meta mark set {mark}')
if 'vrf' in rule_conf['set']:
set_table = True
vrf_name = rule_conf['set']['vrf']
# NOTE: VRF->table ID lookup depends on the VRF iface already existing.
if vrf_name == 'default':
table = '254'
else:
table = get_vrf_table_id(vrf_name)
if 'table' in rule_conf['set']:
set_table = True
table = rule_conf['set']['table']
if table == 'main':
table = '254'
if set_table:
mark = 0x7FFFFFFF - int(table)
output.append(f'meta mark set {mark}')
if 'tcp_mss' in rule_conf['set']:
Expand Down
3 changes: 3 additions & 0 deletions python/vyos/utils/network.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,9 @@ def get_vrf_members(vrf: str) -> list:
pass
return interfaces

def get_vrf_table_id(vrf: str):
return get_interface_config(vrf)['linkinfo']['info_data']['table']

def get_interface_vrf(interface):
""" Returns VRF of given interface """
from vyos.utils.dict import dict_search
Expand Down
27 changes: 21 additions & 6 deletions src/conf_mode/policy_route.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
from vyos.utils.dict import dict_search_args
from vyos.utils.process import cmd
from vyos.utils.process import run
from vyos.utils.network import get_vrf_table_id
from vyos import ConfigError
from vyos import airbag
airbag.enable()
Expand Down Expand Up @@ -83,6 +84,9 @@ def verify_rule(policy, name, rule_conf, ipv6, rule_id):
if not tcp_flags or 'syn' not in tcp_flags:
raise ConfigError(f'{name} rule {rule_id}: TCP SYN flag must be set to modify TCP-MSS')

if 'vrf' in rule_conf['set'] and 'table' in rule_conf['set']:
raise ConfigError(f'{name} rule {rule_id}: Cannot set both forwarding route table and VRF')

tcp_flags = dict_search_args(rule_conf, 'tcp', 'flags')
if tcp_flags:
if dict_search_args(rule_conf, 'protocol') != 'tcp':
Expand Down Expand Up @@ -152,15 +156,26 @@ def apply_table_marks(policy):
for name, pol_conf in policy[route].items():
if 'rule' in pol_conf:
for rule_id, rule_conf in pol_conf['rule'].items():
vrf_table_id = None
set_table = dict_search_args(rule_conf, 'set', 'table')
if set_table:
set_vrf = dict_search_args(rule_conf, 'set', 'vrf')
if set_vrf:
if set_vrf == 'default':
vrf_table_id = '254'
else:
# str-cast so that tables uniqueness check works below.
vrf_table_id = str(get_vrf_table_id(set_vrf))
elif set_table:
if set_table == 'main':
set_table = '254'
if set_table in tables:
vrf_table_id = '254'
else:
vrf_table_id = set_table
if vrf_table_id is not None:
if vrf_table_id in tables:
continue
tables.append(set_table)
table_mark = mark_offset - int(set_table)
cmd(f'{cmd_str} rule add pref {set_table} fwmark {table_mark} table {set_table}')
tables.append(vrf_table_id)
table_mark = mark_offset - int(vrf_table_id)
cmd(f'{cmd_str} rule add pref {vrf_table_id} fwmark {table_mark} table {vrf_table_id}')

def cleanup_table_marks():
for cmd_str in ['ip', 'ip -6']:
Expand Down

0 comments on commit af86aa5

Please sign in to comment.