Skip to content

Commit

Permalink
Support looking up named route table in routing rule
Browse files Browse the repository at this point in the history
The user may need to define the named route table in the routing rule
besides the table id, add support for that.

The commit fixes
#506.

Signed-off-by: Wen Liang <liangwen12year@gmail.com>
  • Loading branch information
liangwen12year committed Sep 28, 2022
1 parent f5a01f9 commit 03f88e2
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 2 deletions.
5 changes: 4 additions & 1 deletion README.md
Expand Up @@ -581,7 +581,10 @@ The IP configuration supports the following options:
- `suppress_prefixlength` -
Reject routing decisions that have a prefix length of the specified or less.
- `table` -
The route table to look up for the `to-table` action.
The route table to look up for the `to-table` action. `table` supports both the
numeric table and named table. In order to specify the named table, the users
have to ensure the named table is properly defined in `/etc/iproute2/rt_tables`
or `/etc/iproute2/rt_tables.d/*.conf`.
- `to` -
The destination address of the packet to match (e.g. `192.168.100.58/24`).
- `tos` -
Expand Down
5 changes: 4 additions & 1 deletion module_utils/network_lsr/argument_validator.py
Expand Up @@ -2336,7 +2336,10 @@ def _validate_post(self, value, name, result):
VALIDATE_ONE_MODE_INITSCRIPTS = "initscripts"

def validate_route_tables(self, connection, idx):
for r in connection["ip"]["route"]:
rule_route_combined_list = (
connection["ip"]["route"] + connection["ip"]["routing_rule"]
)
for r in rule_route_combined_list:
if isinstance(r["table"], Util.STRING_TYPE):
mapping = IPRouteUtils.get_route_tables_mapping()
if r["table"] in mapping:
Expand Down
36 changes: 36 additions & 0 deletions tests/playbooks/tests_routing_rules.yml
Expand Up @@ -19,6 +19,14 @@
state: present
- include_tasks: tasks/assert_device_present.yml

- name: Create a dedicated test file in `/etc/iproute2/rt_tables.d/` and
add a new routing table
lineinfile:
path: /etc/iproute2/rt_tables.d/table.conf
line: "200 custom"
mode: "0644"
create: yes

- name: Configure connection profile and specify the numeric table in
static routes
import_role:
Expand Down Expand Up @@ -91,6 +99,9 @@
dport: 128 - 256
invert: True
table: 30600
- priority: 200
from: 198.51.100.56/26
table: custom
# the routing rule selector sport and ipproto are not supported by iproute
# since v4.17.0, and the iproute installed in CentOS-7 and RHEL-7 is
# v4.11.0
Expand All @@ -115,6 +126,13 @@
changed_when: false
when: ansible_distribution_major_version != "7"

- name: Get the routing rule for looking up the table 'custom'
command: ip rule list table custom
register: route_rule_table_custom
ignore_errors: yes
changed_when: false
when: ansible_distribution_major_version != "7"

- name: Get the IPv4 routing rule for the connection "{{ interface }}"
command: nmcli -f ipv4.routing-rules c show "{{ interface }}"
register: connection_route_rule
Expand Down Expand Up @@ -171,6 +189,16 @@
specified rule"
when: ansible_distribution_major_version != "7"

- name: Assert that the routing rule with 'custom' table lookup matches the
specified rule
assert:
that:
- route_rule_table_custom.stdout is search("200:(\s+)from
198.51.100.56/26 lookup custom")
msg: "the routing rule with 'custom' table lookup does not match the
specified rule"
when: ansible_distribution_major_version != "7"

- name: Assert that the IPv4 routing rule in the connection
"{{ interface }}" matches the specified rule
assert:
Expand All @@ -191,6 +219,8 @@
0.0.0.0/0 iif iiftest table 30400")
- connection_route_rule.stdout is search("priority 30402 from
0.0.0.0/0 oif oiftest table 30400")
- connection_route_rule.stdout is search("priority 200 from
198.51.100.56/26 table 200")
msg: "the IPv4 routing rule in the connection '{{ interface }}' does
not match the specified rule"

Expand All @@ -206,6 +236,12 @@
::/0 dport 128-256 table 30600")
msg: "the IPv6 routing rule in the connection '{{ interface }}' does
not match the specified rule"

- name: Remove the dedicated test file in `/etc/iproute2/rt_tables.d/`
file:
state: absent
path: /etc/iproute2/rt_tables.d/table.conf

- import_playbook: down_profile+delete_interface.yml
vars:
profile: "{{ interface }}"
Expand Down
37 changes: 37 additions & 0 deletions tests/unit/test_network_connections.py
Expand Up @@ -4395,6 +4395,7 @@ def setUp(self):
"table": 30400,
},
],
"routing_rule": [],
},
}
]
Expand Down Expand Up @@ -4650,6 +4651,25 @@ def setUp(self):
}
]
self.validator = network_lsr.argument_validator.ArgValidator_ListConnections()
self.old_getter = (
network_lsr.argument_validator.IPRouteUtils.get_route_tables_mapping
)
network_lsr.argument_validator.IPRouteUtils.get_route_tables_mapping = (
classmethod(
lambda cls: {
"custom": 200,
"eth": 30400,
}
)
)
# the connection index is 0 because there is only one connection profile
# defined here
self.connection_index = 0

def tearDown(self):
network_lsr.argument_validator.IPRouteUtils.get_route_tables_mapping = (
self.old_getter
)

def test_routing_rule_missing_address_family(self):
"""
Expand Down Expand Up @@ -4831,6 +4851,23 @@ def test_routing_rule_validate_suppress_prefixlength(self):
self.test_connections,
)

def test_table_found_when_lookup_named_table(self):
"""
Test that the `validate_route_tables()` will find the table id mapping from
`IPRouteUtils.get_route_tables_mapping()`.
"""

self.test_connections[0]["ip"]["routing_rule"][0]["table"] = "custom"

self.validator.validate_route_tables(
self.test_connections[0],
self.connection_index,
)
self.assertEqual(
self.test_connections[0]["ip"]["routing_rule"][0]["table"],
200,
)


class TestValidatorDictBond(Python26CompatTestCase):
def setUp(self):
Expand Down

0 comments on commit 03f88e2

Please sign in to comment.