summaryrefslogtreecommitdiff
path: root/smoketest/scripts
diff options
context:
space:
mode:
Diffstat (limited to 'smoketest/scripts')
-rw-r--r--smoketest/scripts/cli/base_interfaces_test.py7
-rwxr-xr-xsmoketest/scripts/cli/test_firewall.py189
-rwxr-xr-xsmoketest/scripts/cli/test_interfaces_bonding.py67
-rwxr-xr-xsmoketest/scripts/cli/test_interfaces_bridge.py105
-rwxr-xr-xsmoketest/scripts/cli/test_interfaces_vti.py34
-rwxr-xr-xsmoketest/scripts/cli/test_load_balancning_wan.py257
-rwxr-xr-xsmoketest/scripts/cli/test_pki.py57
-rwxr-xr-xsmoketest/scripts/cli/test_policy.py129
-rwxr-xr-xsmoketest/scripts/cli/test_policy_route.py106
-rwxr-xr-xsmoketest/scripts/cli/test_protocols_bgp.py15
-rwxr-xr-xsmoketest/scripts/cli/test_protocols_rip.py66
-rwxr-xr-xsmoketest/scripts/cli/test_service_dns_forwarding.py48
-rwxr-xr-xsmoketest/scripts/cli/test_service_monitoring_telegraf.py8
-rwxr-xr-xsmoketest/scripts/cli/test_service_router-advert.py14
-rwxr-xr-xsmoketest/scripts/cli/test_service_ssh.py49
-rwxr-xr-xsmoketest/scripts/cli/test_system_flow-accounting.py94
-rwxr-xr-xsmoketest/scripts/cli/test_system_frr.py146
-rwxr-xr-xsmoketest/scripts/cli/test_system_ip.py13
-rwxr-xr-xsmoketest/scripts/cli/test_system_ntp.py17
-rwxr-xr-xsmoketest/scripts/cli/test_vpn_sstp.py16
-rwxr-xr-xsmoketest/scripts/cli/test_vrf.py24
21 files changed, 1318 insertions, 143 deletions
diff --git a/smoketest/scripts/cli/base_interfaces_test.py b/smoketest/scripts/cli/base_interfaces_test.py
index 816ba6dcd..55343b893 100644
--- a/smoketest/scripts/cli/base_interfaces_test.py
+++ b/smoketest/scripts/cli/base_interfaces_test.py
@@ -232,6 +232,9 @@ class BasicInterfaceTest:
for interface in self._interfaces:
base = self._base_path + [interface]
+ # just set the interface base without any option - some interfaces
+ # (VTI) do not require any option to be brought up
+ self.cli_set(base)
for option in self._options.get(interface, []):
self.cli_set(base + option.split())
@@ -635,6 +638,7 @@ class BasicInterfaceTest:
self.cli_set(path + ['ip', 'arp-cache-timeout', arp_tmo])
self.cli_set(path + ['ip', 'disable-arp-filter'])
self.cli_set(path + ['ip', 'disable-forwarding'])
+ self.cli_set(path + ['ip', 'enable-directed-broadcast'])
self.cli_set(path + ['ip', 'enable-arp-accept'])
self.cli_set(path + ['ip', 'enable-arp-announce'])
self.cli_set(path + ['ip', 'enable-arp-ignore'])
@@ -671,6 +675,9 @@ class BasicInterfaceTest:
tmp = read_file(f'{proc_base}/forwarding')
self.assertEqual('0', tmp)
+ tmp = read_file(f'{proc_base}/bc_forwarding')
+ self.assertEqual('1', tmp)
+
tmp = read_file(f'{proc_base}/proxy_arp')
self.assertEqual('1', tmp)
diff --git a/smoketest/scripts/cli/test_firewall.py b/smoketest/scripts/cli/test_firewall.py
index 37e6b9e7a..4de90e1ec 100755
--- a/smoketest/scripts/cli/test_firewall.py
+++ b/smoketest/scripts/cli/test_firewall.py
@@ -20,6 +20,7 @@ from glob import glob
from base_vyostest_shim import VyOSUnitTestSHIM
+from vyos.configsession import ConfigSessionError
from vyos.util import cmd
sysfs_config = {
@@ -56,11 +57,63 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase):
self.cli_delete(['firewall'])
self.cli_commit()
+ # Verify chains/sets are cleaned up from nftables
+ nftables_search = [
+ ['set M_smoketest_mac'],
+ ['set N_smoketest_network'],
+ ['set P_smoketest_port'],
+ ['set D_smoketest_domain'],
+ ['set RECENT_smoketest_4'],
+ ['chain NAME_smoketest']
+ ]
+
+ self.verify_nftables(nftables_search, 'ip filter', inverse=True)
+
+ def verify_nftables(self, nftables_search, table, inverse=False, args=''):
+ nftables_output = cmd(f'sudo nft {args} list table {table}')
+
+ for search in nftables_search:
+ matched = False
+ for line in nftables_output.split("\n"):
+ if all(item in line for item in search):
+ matched = True
+ break
+ self.assertTrue(not matched if inverse else matched, msg=search)
+
+ def test_geoip(self):
+ self.cli_set(['firewall', 'name', 'smoketest', 'rule', '1', 'action', 'drop'])
+ self.cli_set(['firewall', 'name', 'smoketest', 'rule', '1', 'source', 'geoip', 'country-code', 'se'])
+ self.cli_set(['firewall', 'name', 'smoketest', 'rule', '1', 'source', 'geoip', 'country-code', 'gb'])
+ self.cli_set(['firewall', 'name', 'smoketest', 'rule', '2', 'action', 'accept'])
+ self.cli_set(['firewall', 'name', 'smoketest', 'rule', '2', 'source', 'geoip', 'country-code', 'de'])
+ self.cli_set(['firewall', 'name', 'smoketest', 'rule', '2', 'source', 'geoip', 'country-code', 'fr'])
+ self.cli_set(['firewall', 'name', 'smoketest', 'rule', '2', 'source', 'geoip', 'inverse-match'])
+
+ self.cli_commit()
+
+ nftables_search = [
+ ['ip saddr @GEOIP_CC_smoketest_1', 'drop'],
+ ['ip saddr != @GEOIP_CC_smoketest_2', 'return']
+ ]
+ # -t prevents 1000+ GeoIP elements being returned
+ self.verify_nftables(nftables_search, 'ip filter', args='-t')
+
def test_groups(self):
+ hostmap_path = ['system', 'static-host-mapping', 'host-name']
+ example_org = ['192.0.2.8', '192.0.2.10', '192.0.2.11']
+
+ self.cli_set(hostmap_path + ['example.com', 'inet', '192.0.2.5'])
+ for ips in example_org:
+ self.cli_set(hostmap_path + ['example.org', 'inet', ips])
+
+ self.cli_commit()
+
self.cli_set(['firewall', 'group', 'mac-group', 'smoketest_mac', 'mac-address', '00:01:02:03:04:05'])
self.cli_set(['firewall', 'group', 'network-group', 'smoketest_network', 'network', '172.16.99.0/24'])
self.cli_set(['firewall', 'group', 'port-group', 'smoketest_port', 'port', '53'])
self.cli_set(['firewall', 'group', 'port-group', 'smoketest_port', 'port', '123'])
+ self.cli_set(['firewall', 'group', 'domain-group', 'smoketest_domain', 'address', 'example.com'])
+ self.cli_set(['firewall', 'group', 'domain-group', 'smoketest_domain', 'address', 'example.org'])
self.cli_set(['firewall', 'name', 'smoketest', 'rule', '1', 'action', 'accept'])
self.cli_set(['firewall', 'name', 'smoketest', 'rule', '1', 'source', 'group', 'network-group', 'smoketest_network'])
self.cli_set(['firewall', 'name', 'smoketest', 'rule', '1', 'destination', 'address', '172.16.10.10'])
@@ -68,41 +121,88 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase):
self.cli_set(['firewall', 'name', 'smoketest', 'rule', '1', 'protocol', 'tcp_udp'])
self.cli_set(['firewall', 'name', 'smoketest', 'rule', '2', 'action', 'accept'])
self.cli_set(['firewall', 'name', 'smoketest', 'rule', '2', 'source', 'group', 'mac-group', 'smoketest_mac'])
+ self.cli_set(['firewall', 'name', 'smoketest', 'rule', '3', 'action', 'accept'])
+ self.cli_set(['firewall', 'name', 'smoketest', 'rule', '3', 'source', 'group', 'domain-group', 'smoketest_domain'])
self.cli_set(['interfaces', 'ethernet', 'eth0', 'firewall', 'in', 'name', 'smoketest'])
self.cli_commit()
-
nftables_search = [
['iifname "eth0"', 'jump NAME_smoketest'],
- ['ip saddr { 172.16.99.0/24 }', 'ip daddr 172.16.10.10', 'th dport { 53, 123 }', 'return'],
- ['ether saddr { 00:01:02:03:04:05 }', 'return']
+ ['ip saddr @N_smoketest_network', 'ip daddr 172.16.10.10', 'th dport @P_smoketest_port', 'return'],
+ ['elements = { 172.16.99.0/24 }'],
+ ['elements = { 53, 123 }'],
+ ['ether saddr @M_smoketest_mac', 'return'],
+ ['elements = { 00:01:02:03:04:05 }'],
+ ['set D_smoketest_domain'],
+ ['elements = { 192.0.2.5, 192.0.2.8,'],
+ ['192.0.2.10, 192.0.2.11 }'],
+ ['ip saddr @D_smoketest_domain', 'return']
]
+ self.verify_nftables(nftables_search, 'ip filter')
- nftables_output = cmd('sudo nft list table ip filter')
+ self.cli_delete(['system', 'static-host-mapping'])
+ self.cli_commit()
- for search in nftables_search:
- matched = False
- for line in nftables_output.split("\n"):
- if all(item in line for item in search):
- matched = True
- break
- self.assertTrue(matched, msg=search)
+ def test_nested_groups(self):
+ self.cli_set(['firewall', 'group', 'network-group', 'smoketest_network', 'network', '172.16.99.0/24'])
+ self.cli_set(['firewall', 'group', 'network-group', 'smoketest_network1', 'network', '172.16.101.0/24'])
+ self.cli_set(['firewall', 'group', 'network-group', 'smoketest_network1', 'include', 'smoketest_network'])
+ self.cli_set(['firewall', 'group', 'port-group', 'smoketest_port', 'port', '53'])
+ self.cli_set(['firewall', 'group', 'port-group', 'smoketest_port1', 'port', '123'])
+ self.cli_set(['firewall', 'group', 'port-group', 'smoketest_port1', 'include', 'smoketest_port'])
+ self.cli_set(['firewall', 'name', 'smoketest', 'rule', '1', 'action', 'accept'])
+ self.cli_set(['firewall', 'name', 'smoketest', 'rule', '1', 'source', 'group', 'network-group', 'smoketest_network1'])
+ self.cli_set(['firewall', 'name', 'smoketest', 'rule', '1', 'destination', 'group', 'port-group', 'smoketest_port1'])
+ self.cli_set(['firewall', 'name', 'smoketest', 'rule', '1', 'protocol', 'tcp_udp'])
+
+ self.cli_set(['interfaces', 'ethernet', 'eth0', 'firewall', 'in', 'name', 'smoketest'])
+
+ self.cli_commit()
+
+ # Test circular includes
+ self.cli_set(['firewall', 'group', 'network-group', 'smoketest_network', 'include', 'smoketest_network1'])
+ with self.assertRaises(ConfigSessionError):
+ self.cli_commit()
+
+ self.cli_delete(['firewall', 'group', 'network-group', 'smoketest_network', 'include', 'smoketest_network1'])
+
+ nftables_search = [
+ ['iifname "eth0"', 'jump NAME_smoketest'],
+ ['ip saddr @N_smoketest_network1', 'th dport @P_smoketest_port1', 'return'],
+ ['elements = { 172.16.99.0/24, 172.16.101.0/24 }'],
+ ['elements = { 53, 123 }']
+ ]
+
+ self.verify_nftables(nftables_search, 'ip filter')
def test_basic_rules(self):
self.cli_set(['firewall', 'name', 'smoketest', 'default-action', 'drop'])
+ self.cli_set(['firewall', 'name', 'smoketest', 'enable-default-log'])
self.cli_set(['firewall', 'name', 'smoketest', 'rule', '1', 'action', 'accept'])
self.cli_set(['firewall', 'name', 'smoketest', 'rule', '1', 'source', 'address', '172.16.20.10'])
self.cli_set(['firewall', 'name', 'smoketest', 'rule', '1', 'destination', 'address', '172.16.10.10'])
+ self.cli_set(['firewall', 'name', 'smoketest', 'rule', '1', 'log', 'enable'])
+ self.cli_set(['firewall', 'name', 'smoketest', 'rule', '1', 'log-level', 'debug'])
+ self.cli_set(['firewall', 'name', 'smoketest', 'rule', '1', 'ttl', 'eq', '15'])
self.cli_set(['firewall', 'name', 'smoketest', 'rule', '2', 'action', 'reject'])
self.cli_set(['firewall', 'name', 'smoketest', 'rule', '2', 'protocol', 'tcp'])
self.cli_set(['firewall', 'name', 'smoketest', 'rule', '2', 'destination', 'port', '8888'])
+ self.cli_set(['firewall', 'name', 'smoketest', 'rule', '2', 'log', 'enable'])
+ self.cli_set(['firewall', 'name', 'smoketest', 'rule', '2', 'log-level', 'err'])
self.cli_set(['firewall', 'name', 'smoketest', 'rule', '2', 'tcp', 'flags', 'syn'])
self.cli_set(['firewall', 'name', 'smoketest', 'rule', '2', 'tcp', 'flags', 'not', 'ack'])
+ self.cli_set(['firewall', 'name', 'smoketest', 'rule', '2', 'ttl', 'gt', '102'])
self.cli_set(['firewall', 'name', 'smoketest', 'rule', '3', 'action', 'accept'])
self.cli_set(['firewall', 'name', 'smoketest', 'rule', '3', 'protocol', 'tcp'])
self.cli_set(['firewall', 'name', 'smoketest', 'rule', '3', 'destination', 'port', '22'])
self.cli_set(['firewall', 'name', 'smoketest', 'rule', '3', 'limit', 'rate', '5/minute'])
+ self.cli_set(['firewall', 'name', 'smoketest', 'rule', '3', 'log', 'disable'])
+ self.cli_set(['firewall', 'name', 'smoketest', 'rule', '4', 'action', 'drop'])
+ self.cli_set(['firewall', 'name', 'smoketest', 'rule', '4', 'protocol', 'tcp'])
+ self.cli_set(['firewall', 'name', 'smoketest', 'rule', '4', 'destination', 'port', '22'])
+ self.cli_set(['firewall', 'name', 'smoketest', 'rule', '4', 'recent', 'count', '10'])
+ self.cli_set(['firewall', 'name', 'smoketest', 'rule', '4', 'recent', 'time', 'minute'])
self.cli_set(['interfaces', 'ethernet', 'eth0', 'firewall', 'in', 'name', 'smoketest'])
@@ -110,27 +210,25 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase):
nftables_search = [
['iifname "eth0"', 'jump NAME_smoketest'],
- ['saddr 172.16.20.10', 'daddr 172.16.10.10', 'return'],
- ['tcp flags & (syn | ack) == syn', 'tcp dport { 8888 }', 'reject'],
+ ['saddr 172.16.20.10', 'daddr 172.16.10.10', 'log prefix "[smoketest-1-A]" level debug', 'ip ttl 15','return'],
+ ['tcp flags & (syn | ack) == syn', 'tcp dport { 8888 }', 'log prefix "[smoketest-2-R]" level err', 'ip ttl > 102', 'reject'],
['tcp dport { 22 }', 'limit rate 5/minute', 'return'],
- ['smoketest default-action', 'drop']
+ ['log prefix "[smoketest-default-D]"','smoketest default-action', 'drop'],
+ ['tcp dport { 22 }', 'add @RECENT_smoketest_4 { ip saddr limit rate over 10/minute burst 10 packets }', 'drop']
]
- nftables_output = cmd('sudo nft list table ip filter')
-
- for search in nftables_search:
- matched = False
- for line in nftables_output.split("\n"):
- if all(item in line for item in search):
- matched = True
- break
- self.assertTrue(matched, msg=search)
+ self.verify_nftables(nftables_search, 'ip filter')
def test_basic_rules_ipv6(self):
self.cli_set(['firewall', 'ipv6-name', 'v6-smoketest', 'default-action', 'drop'])
+ self.cli_set(['firewall', 'ipv6-name', 'v6-smoketest', 'enable-default-log'])
+
self.cli_set(['firewall', 'ipv6-name', 'v6-smoketest', 'rule', '1', 'action', 'accept'])
self.cli_set(['firewall', 'ipv6-name', 'v6-smoketest', 'rule', '1', 'source', 'address', '2002::1'])
self.cli_set(['firewall', 'ipv6-name', 'v6-smoketest', 'rule', '1', 'destination', 'address', '2002::1:1'])
+ self.cli_set(['firewall', 'ipv6-name', 'v6-smoketest', 'rule', '1', 'log', 'enable'])
+ self.cli_set(['firewall', 'ipv6-name', 'v6-smoketest', 'rule', '1', 'log-level', 'crit'])
+
self.cli_set(['firewall', 'ipv6-name', 'v6-smoketest', 'rule', '2', 'action', 'reject'])
self.cli_set(['firewall', 'ipv6-name', 'v6-smoketest', 'rule', '2', 'protocol', 'tcp_udp'])
self.cli_set(['firewall', 'ipv6-name', 'v6-smoketest', 'rule', '2', 'destination', 'port', '8888'])
@@ -141,20 +239,12 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase):
nftables_search = [
['iifname "eth0"', 'jump NAME6_v6-smoketest'],
- ['saddr 2002::1', 'daddr 2002::1:1', 'return'],
+ ['saddr 2002::1', 'daddr 2002::1:1', 'log prefix "[v6-smoketest-1-A]" level crit', 'return'],
['meta l4proto { tcp, udp }', 'th dport { 8888 }', 'reject'],
- ['smoketest default-action', 'drop']
+ ['smoketest default-action', 'log prefix "[v6-smoketest-default-D]"', 'drop']
]
- nftables_output = cmd('sudo nft list table ip6 filter')
-
- for search in nftables_search:
- matched = False
- for line in nftables_output.split("\n"):
- if all(item in line for item in search):
- matched = True
- break
- self.assertTrue(matched, msg=search)
+ self.verify_nftables(nftables_search, 'ip6 filter')
def test_state_policy(self):
self.cli_set(['firewall', 'state-policy', 'established', 'action', 'accept'])
@@ -173,6 +263,37 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase):
nftables_output = cmd(f'sudo nft list chain {table} {chain}')
self.assertTrue('jump VYOS_STATE_POLICY' in nftables_output)
+ def test_state_and_status_rules(self):
+ self.cli_set(['firewall', 'name', 'smoketest', 'default-action', 'drop'])
+ self.cli_set(['firewall', 'name', 'smoketest', 'rule', '1', 'action', 'accept'])
+ self.cli_set(['firewall', 'name', 'smoketest', 'rule', '1', 'state', 'established', 'enable'])
+ self.cli_set(['firewall', 'name', 'smoketest', 'rule', '1', 'state', 'related', 'enable'])
+ self.cli_set(['firewall', 'name', 'smoketest', 'rule', '2', 'action', 'reject'])
+ self.cli_set(['firewall', 'name', 'smoketest', 'rule', '2', 'state', 'invalid', 'enable'])
+ self.cli_set(['firewall', 'name', 'smoketest', 'rule', '3', 'action', 'accept'])
+ self.cli_set(['firewall', 'name', 'smoketest', 'rule', '3', 'state', 'new', 'enable'])
+
+ self.cli_set(['firewall', 'name', 'smoketest', 'rule', '3', 'connection-status', 'nat', 'destination'])
+ self.cli_set(['firewall', 'name', 'smoketest', 'rule', '4', 'action', 'accept'])
+ self.cli_set(['firewall', 'name', 'smoketest', 'rule', '4', 'state', 'new', 'enable'])
+ self.cli_set(['firewall', 'name', 'smoketest', 'rule', '4', 'state', 'established', 'enable'])
+ self.cli_set(['firewall', 'name', 'smoketest', 'rule', '4', 'connection-status', 'nat', 'source'])
+
+ self.cli_set(['interfaces', 'ethernet', 'eth0', 'firewall', 'in', 'name', 'smoketest'])
+
+ self.cli_commit()
+
+ nftables_search = [
+ ['iifname "eth0"', 'jump NAME_smoketest'],
+ ['ct state { established, related }', 'return'],
+ ['ct state { invalid }', 'reject'],
+ ['ct state { new }', 'ct status { dnat }', 'return'],
+ ['ct state { established, new }', 'ct status { snat }', 'return'],
+ ['smoketest default-action', 'drop']
+ ]
+
+ self.verify_nftables(nftables_search, 'ip filter')
+
def test_sysfs(self):
for name, conf in sysfs_config.items():
paths = glob(conf['sysfs'])
diff --git a/smoketest/scripts/cli/test_interfaces_bonding.py b/smoketest/scripts/cli/test_interfaces_bonding.py
index 237abb487..cd3995ed9 100755
--- a/smoketest/scripts/cli/test_interfaces_bonding.py
+++ b/smoketest/scripts/cli/test_interfaces_bonding.py
@@ -49,7 +49,7 @@ class BondingInterfaceTest(BasicInterfaceTest.TestCase):
if not '.' in tmp:
cls._members.append(tmp)
- cls._options['bond0'] = []
+ cls._options = {'bond0' : []}
for member in cls._members:
cls._options['bond0'].append(f'member interface {member}')
cls._interfaces = list(cls._options)
@@ -136,7 +136,7 @@ class BondingInterfaceTest(BasicInterfaceTest.TestCase):
def test_bonding_hash_policy(self):
# Define available bonding hash policies
- hash_policies = ['layer2', 'layer2+3', 'layer2+3', 'encap2+3', 'encap3+4']
+ hash_policies = ['layer2', 'layer2+3', 'encap2+3', 'encap3+4']
for hash_policy in hash_policies:
for interface in self._interfaces:
for option in self._options.get(interface, []):
@@ -151,6 +151,29 @@ class BondingInterfaceTest(BasicInterfaceTest.TestCase):
defined_policy = read_file(f'/sys/class/net/{interface}/bonding/xmit_hash_policy').split()
self.assertEqual(defined_policy[0], hash_policy)
+ def test_bonding_mii_monitoring_interval(self):
+ for interface in self._interfaces:
+ for option in self._options.get(interface, []):
+ self.cli_set(self._base_path + [interface] + option.split())
+
+ self.cli_commit()
+
+ # verify default
+ for interface in self._interfaces:
+ tmp = read_file(f'/sys/class/net/{interface}/bonding/miimon').split()
+ self.assertIn('100', tmp)
+
+ mii_mon = '250'
+ for interface in self._interfaces:
+ self.cli_set(self._base_path + [interface, 'mii-mon-interval', mii_mon])
+
+ self.cli_commit()
+
+ # verify new CLI value
+ for interface in self._interfaces:
+ tmp = read_file(f'/sys/class/net/{interface}/bonding/miimon').split()
+ self.assertIn(mii_mon, tmp)
+
def test_bonding_multi_use_member(self):
# Define available bonding hash policies
for interface in ['bond10', 'bond20']:
@@ -165,6 +188,46 @@ class BondingInterfaceTest(BasicInterfaceTest.TestCase):
self.cli_commit()
+ def test_bonding_source_interface(self):
+ # Re-use member interface that is already a source-interface
+ bond = 'bond99'
+ pppoe = 'pppoe98756'
+ member = next(iter(self._members))
+
+ self.cli_set(self._base_path + [bond, 'member', 'interface', member])
+ self.cli_set(['interfaces', 'pppoe', pppoe, 'source-interface', member])
+
+ # check validate() - can not add interface to bond, it is the source-interface of ...
+ with self.assertRaises(ConfigSessionError):
+ self.cli_commit()
+
+ self.cli_delete(['interfaces', 'pppoe', pppoe])
+ self.cli_commit()
+
+ # verify config
+ slaves = read_file(f'/sys/class/net/{bond}/bonding/slaves').split()
+ self.assertIn(member, slaves)
+
+ def test_bonding_source_bridge_interface(self):
+ # Re-use member interface that is already a source-interface
+ bond = 'bond1097'
+ bridge = 'br6327'
+ member = next(iter(self._members))
+
+ self.cli_set(self._base_path + [bond, 'member', 'interface', member])
+ self.cli_set(['interfaces', 'bridge', bridge, 'member', 'interface', member])
+
+ # check validate() - can not add interface to bond, it is a member of bridge ...
+ with self.assertRaises(ConfigSessionError):
+ self.cli_commit()
+
+ self.cli_delete(['interfaces', 'bridge', bridge])
+ self.cli_commit()
+
+ # verify config
+ slaves = read_file(f'/sys/class/net/{bond}/bonding/slaves').split()
+ self.assertIn(member, slaves)
+
def test_bonding_uniq_member_description(self):
ethernet_path = ['interfaces', 'ethernet']
for interface in self._interfaces:
diff --git a/smoketest/scripts/cli/test_interfaces_bridge.py b/smoketest/scripts/cli/test_interfaces_bridge.py
index ca0ead9e8..664dc48bc 100755
--- a/smoketest/scripts/cli/test_interfaces_bridge.py
+++ b/smoketest/scripts/cli/test_interfaces_bridge.py
@@ -86,9 +86,83 @@ class BridgeInterfaceTest(BasicInterfaceTest.TestCase):
# validate member interface configuration
for member in self._members:
tmp = get_interface_config(member)
+ # verify member is assigned to the bridge
+ self.assertEqual(interface, tmp['master'])
# Isolated must be enabled as configured above
self.assertTrue(tmp['linkinfo']['info_slave_data']['isolated'])
+ def test_igmp_querier_snooping(self):
+ # Add member interfaces to bridge
+ for interface in self._interfaces:
+ base = self._base_path + [interface]
+
+ # assign members to bridge interface
+ for member in self._members:
+ base_member = base + ['member', 'interface', member]
+ self.cli_set(base_member)
+
+ # commit config
+ self.cli_commit()
+
+ for interface in self._interfaces:
+ # Verify IGMP default configuration
+ tmp = read_file(f'/sys/class/net/{interface}/bridge/multicast_snooping')
+ self.assertEqual(tmp, '0')
+ tmp = read_file(f'/sys/class/net/{interface}/bridge/multicast_querier')
+ self.assertEqual(tmp, '0')
+
+ # Enable IGMP snooping
+ for interface in self._interfaces:
+ base = self._base_path + [interface]
+ self.cli_set(base + ['igmp', 'snooping'])
+
+ # commit config
+ self.cli_commit()
+
+ for interface in self._interfaces:
+ # Verify IGMP snooping configuration
+ # Verify IGMP default configuration
+ tmp = read_file(f'/sys/class/net/{interface}/bridge/multicast_snooping')
+ self.assertEqual(tmp, '1')
+ tmp = read_file(f'/sys/class/net/{interface}/bridge/multicast_querier')
+ self.assertEqual(tmp, '0')
+
+ # Enable IGMP querieer
+ for interface in self._interfaces:
+ base = self._base_path + [interface]
+ self.cli_set(base + ['igmp', 'querier'])
+
+ # commit config
+ self.cli_commit()
+
+ for interface in self._interfaces:
+ # Verify IGMP snooping & querier configuration
+ tmp = read_file(f'/sys/class/net/{interface}/bridge/multicast_snooping')
+ self.assertEqual(tmp, '1')
+ tmp = read_file(f'/sys/class/net/{interface}/bridge/multicast_querier')
+ self.assertEqual(tmp, '1')
+
+ # Disable IGMP
+ for interface in self._interfaces:
+ base = self._base_path + [interface]
+ self.cli_delete(base + ['igmp'])
+
+ # commit config
+ self.cli_commit()
+
+ for interface in self._interfaces:
+ # Verify IGMP snooping & querier configuration
+ tmp = read_file(f'/sys/class/net/{interface}/bridge/multicast_snooping')
+ self.assertEqual(tmp, '0')
+ tmp = read_file(f'/sys/class/net/{interface}/bridge/multicast_querier')
+ self.assertEqual(tmp, '0')
+
+ # validate member interface configuration
+ for member in self._members:
+ tmp = get_interface_config(member)
+ # verify member is assigned to the bridge
+ self.assertEqual(interface, tmp['master'])
+
def test_add_remove_bridge_member(self):
# Add member interfaces to bridge and set STP cost/priority
@@ -230,7 +304,7 @@ class BridgeInterfaceTest(BasicInterfaceTest.TestCase):
self.cli_delete(self._base_path + [interface, 'member'])
- def test_bridge_vlan_members(self):
+ def test_bridge_vif_members(self):
# T2945: ensure that VIFs are not dropped from bridge
vifs = ['300', '400']
for interface in self._interfaces:
@@ -255,5 +329,34 @@ class BridgeInterfaceTest(BasicInterfaceTest.TestCase):
self.cli_delete(['interfaces', 'ethernet', member, 'vif', vif])
self.cli_delete(['interfaces', 'bridge', interface, 'member', 'interface', f'{member}.{vif}'])
+ def test_bridge_vif_s_vif_c_members(self):
+ # T2945: ensure that VIFs are not dropped from bridge
+ vifs = ['300', '400']
+ vifc = ['301', '401']
+ for interface in self._interfaces:
+ for member in self._members:
+ for vif_s in vifs:
+ for vif_c in vifc:
+ self.cli_set(['interfaces', 'ethernet', member, 'vif-s', vif_s, 'vif-c', vif_c])
+ self.cli_set(['interfaces', 'bridge', interface, 'member', 'interface', f'{member}.{vif_s}.{vif_c}'])
+
+ self.cli_commit()
+
+ # Verify config
+ for interface in self._interfaces:
+ for member in self._members:
+ for vif_s in vifs:
+ for vif_c in vifc:
+ # member interface must be assigned to the bridge
+ self.assertTrue(os.path.exists(f'/sys/class/net/{interface}/lower_{member}.{vif_s}.{vif_c}'))
+
+ # delete all members
+ for interface in self._interfaces:
+ for member in self._members:
+ for vif_s in vifs:
+ self.cli_delete(['interfaces', 'ethernet', member, 'vif-s', vif_s])
+ for vif_c in vifc:
+ self.cli_delete(['interfaces', 'bridge', interface, 'member', 'interface', f'{member}.{vif_s}.{vif_c}'])
+
if __name__ == '__main__':
unittest.main(verbosity=2)
diff --git a/smoketest/scripts/cli/test_interfaces_vti.py b/smoketest/scripts/cli/test_interfaces_vti.py
new file mode 100755
index 000000000..9cbf104f0
--- /dev/null
+++ b/smoketest/scripts/cli/test_interfaces_vti.py
@@ -0,0 +1,34 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2022 VyOS maintainers and contributors
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 or later as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+import unittest
+
+from base_interfaces_test import BasicInterfaceTest
+
+class VTIInterfaceTest(BasicInterfaceTest.TestCase):
+ @classmethod
+ def setUpClass(cls):
+ cls._test_ip = True
+ cls._test_ipv6 = True
+ cls._test_mtu = True
+ cls._base_path = ['interfaces', 'vti']
+ cls._interfaces = ['vti10', 'vti20', 'vti30']
+
+ # call base-classes classmethod
+ super(VTIInterfaceTest, cls).setUpClass()
+
+if __name__ == '__main__':
+ unittest.main(verbosity=2)
diff --git a/smoketest/scripts/cli/test_load_balancning_wan.py b/smoketest/scripts/cli/test_load_balancning_wan.py
new file mode 100755
index 000000000..303dece86
--- /dev/null
+++ b/smoketest/scripts/cli/test_load_balancning_wan.py
@@ -0,0 +1,257 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2022 VyOS maintainers and contributors
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 or later as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+import os
+import unittest
+import time
+
+from base_vyostest_shim import VyOSUnitTestSHIM
+from vyos.configsession import ConfigSessionError
+from vyos.ifconfig import Section
+from vyos.util import call
+from vyos.util import cmd
+
+
+base_path = ['load-balancing']
+
+
+def create_netns(name):
+ return call(f'sudo ip netns add {name}')
+
+def create_veth_pair(local='veth0', peer='ceth0'):
+ return call(f'sudo ip link add {local} type veth peer name {peer}')
+
+def move_interface_to_netns(iface, netns_name):
+ return call(f'sudo ip link set {iface} netns {netns_name}')
+
+def rename_interface(iface, new_name):
+ return call(f'sudo ip link set {iface} name {new_name}')
+
+def cmd_in_netns(netns, cmd):
+ return call(f'sudo ip netns exec {netns} {cmd}')
+
+def delete_netns(name):
+ return call(f'sudo ip netns del {name}')
+
+
+class TestLoadBalancingWan(VyOSUnitTestSHIM.TestCase):
+ @classmethod
+ def setUpClass(cls):
+ super(TestLoadBalancingWan, cls).setUpClass()
+
+ # ensure we can also run this test on a live system - so lets clean
+ # out the current configuration :)
+ cls.cli_delete(cls, base_path)
+
+ def tearDown(self):
+ self.cli_delete(base_path)
+ self.cli_commit()
+
+ def test_table_routes(self):
+
+ ns1 = 'ns201'
+ ns2 = 'ns202'
+ ns3 = 'ns203'
+ iface1 = 'eth201'
+ iface2 = 'eth202'
+ iface3 = 'eth203'
+ container_iface1 = 'ceth0'
+ container_iface2 = 'ceth1'
+ container_iface3 = 'ceth2'
+
+ # Create network namespeces
+ create_netns(ns1)
+ create_netns(ns2)
+ create_netns(ns3)
+ create_veth_pair(iface1, container_iface1)
+ create_veth_pair(iface2, container_iface2)
+ create_veth_pair(iface3, container_iface3)
+ move_interface_to_netns(container_iface1, ns1)
+ move_interface_to_netns(container_iface2, ns2)
+ move_interface_to_netns(container_iface3, ns3)
+ call(f'sudo ip address add 203.0.113.10/24 dev {iface1}')
+ call(f'sudo ip address add 192.0.2.10/24 dev {iface2}')
+ call(f'sudo ip address add 198.51.100.10/24 dev {iface3}')
+ call(f'sudo ip link set dev {iface1} up')
+ call(f'sudo ip link set dev {iface2} up')
+ call(f'sudo ip link set dev {iface3} up')
+ cmd_in_netns(ns1, f'ip link set {container_iface1} name eth0')
+ cmd_in_netns(ns2, f'ip link set {container_iface2} name eth0')
+ cmd_in_netns(ns3, f'ip link set {container_iface3} name eth0')
+ cmd_in_netns(ns1, 'ip address add 203.0.113.1/24 dev eth0')
+ cmd_in_netns(ns2, 'ip address add 192.0.2.1/24 dev eth0')
+ cmd_in_netns(ns3, 'ip address add 198.51.100.1/24 dev eth0')
+ cmd_in_netns(ns1, 'ip link set dev eth0 up')
+ cmd_in_netns(ns2, 'ip link set dev eth0 up')
+ cmd_in_netns(ns3, 'ip link set dev eth0 up')
+
+ # Set load-balancing configuration
+ self.cli_set(base_path + ['wan', 'interface-health', iface1, 'failure-count', '2'])
+ self.cli_set(base_path + ['wan', 'interface-health', iface1, 'nexthop', '203.0.113.1'])
+ self.cli_set(base_path + ['wan', 'interface-health', iface1, 'success-count', '1'])
+ self.cli_set(base_path + ['wan', 'interface-health', iface2, 'failure-count', '2'])
+ self.cli_set(base_path + ['wan', 'interface-health', iface2, 'nexthop', '192.0.2.1'])
+ self.cli_set(base_path + ['wan', 'interface-health', iface2, 'success-count', '1'])
+
+ self.cli_set(base_path + ['wan', 'rule', '10', 'inbound-interface', iface3])
+ self.cli_set(base_path + ['wan', 'rule', '10', 'source', 'address', '198.51.100.0/24'])
+
+
+ # commit changes
+ self.cli_commit()
+
+ time.sleep(5)
+ # Check default routes in tables 201, 202
+ # Expected values
+ original = 'default via 203.0.113.1 dev eth201'
+ tmp = cmd('sudo ip route show table 201')
+ self.assertEqual(tmp, original)
+
+ original = 'default via 192.0.2.1 dev eth202'
+ tmp = cmd('sudo ip route show table 202')
+ self.assertEqual(tmp, original)
+
+ # Delete veth interfaces and netns
+ for iface in [iface1, iface2]:
+ call(f'sudo ip link del dev {iface}')
+
+ delete_netns(ns1)
+ delete_netns(ns2)
+
+ def test_check_chains(self):
+
+ ns1 = 'nsA'
+ ns2 = 'nsB'
+ ns3 = 'nsC'
+ iface1 = 'veth1'
+ iface2 = 'veth2'
+ iface3 = 'veth3'
+ container_iface1 = 'ceth0'
+ container_iface2 = 'ceth1'
+ container_iface3 = 'ceth2'
+ mangle_isp1 = """table ip mangle {
+ chain ISP_veth1 {
+ counter ct mark set 0xc9
+ counter meta mark set 0xc9
+ counter accept
+ }
+}"""
+ mangle_isp2 = """table ip mangle {
+ chain ISP_veth2 {
+ counter ct mark set 0xca
+ counter meta mark set 0xca
+ counter accept
+ }
+}"""
+ mangle_prerouting = """table ip mangle {
+ chain PREROUTING {
+ type filter hook prerouting priority mangle; policy accept;
+ counter jump WANLOADBALANCE_PRE
+ }
+}"""
+ mangle_wanloadbalance_pre = """table ip mangle {
+ chain WANLOADBALANCE_PRE {
+ iifname "veth3" ip saddr 198.51.100.0/24 ct state new counter jump ISP_veth1
+ iifname "veth3" ip saddr 198.51.100.0/24 ct state new counter jump ISP_veth2
+ iifname "veth3" ip saddr 198.51.100.0/24 counter meta mark set ct mark
+ }
+}"""
+ nat_wanloadbalance = """table ip nat {
+ chain WANLOADBALANCE {
+ ct mark 0xc9 counter snat to 203.0.113.10
+ ct mark 0xca counter snat to 192.0.2.10
+ }
+}"""
+ nat_vyos_pre_snat_hook = """table ip nat {
+ chain VYOS_PRE_SNAT_HOOK {
+ counter jump WANLOADBALANCE
+ return
+ }
+}"""
+
+ # Create network namespeces
+ create_netns(ns1)
+ create_netns(ns2)
+ create_netns(ns3)
+ create_veth_pair(iface1, container_iface1)
+ create_veth_pair(iface2, container_iface2)
+ create_veth_pair(iface3, container_iface3)
+ move_interface_to_netns(container_iface1, ns1)
+ move_interface_to_netns(container_iface2, ns2)
+ move_interface_to_netns(container_iface3, ns3)
+ call(f'sudo ip address add 203.0.113.10/24 dev {iface1}')
+ call(f'sudo ip address add 192.0.2.10/24 dev {iface2}')
+ call(f'sudo ip address add 198.51.100.10/24 dev {iface3}')
+ call(f'sudo ip link set dev {iface1} up')
+ call(f'sudo ip link set dev {iface2} up')
+ call(f'sudo ip link set dev {iface3} up')
+ cmd_in_netns(ns1, f'ip link set {container_iface1} name eth0')
+ cmd_in_netns(ns2, f'ip link set {container_iface2} name eth0')
+ cmd_in_netns(ns3, f'ip link set {container_iface3} name eth0')
+ cmd_in_netns(ns1, 'ip address add 203.0.113.1/24 dev eth0')
+ cmd_in_netns(ns2, 'ip address add 192.0.2.1/24 dev eth0')
+ cmd_in_netns(ns3, 'ip address add 198.51.100.1/24 dev eth0')
+ cmd_in_netns(ns1, 'ip link set dev eth0 up')
+ cmd_in_netns(ns2, 'ip link set dev eth0 up')
+ cmd_in_netns(ns3, 'ip link set dev eth0 up')
+
+ # Set load-balancing configuration
+ self.cli_set(base_path + ['wan', 'interface-health', iface1, 'failure-count', '2'])
+ self.cli_set(base_path + ['wan', 'interface-health', iface1, 'nexthop', '203.0.113.1'])
+ self.cli_set(base_path + ['wan', 'interface-health', iface1, 'success-count', '1'])
+ self.cli_set(base_path + ['wan', 'interface-health', iface2, 'failure-count', '2'])
+ self.cli_set(base_path + ['wan', 'interface-health', iface2, 'nexthop', '192.0.2.1'])
+ self.cli_set(base_path + ['wan', 'interface-health', iface2, 'success-count', '1'])
+ self.cli_set(base_path + ['wan', 'rule', '10', 'inbound-interface', iface3])
+ self.cli_set(base_path + ['wan', 'rule', '10', 'source', 'address', '198.51.100.0/24'])
+ self.cli_set(base_path + ['wan', 'rule', '10', 'interface', iface1])
+ self.cli_set(base_path + ['wan', 'rule', '10', 'interface', iface2])
+
+ # commit changes
+ self.cli_commit()
+
+ time.sleep(5)
+
+ # Check mangle chains
+ tmp = cmd(f'sudo nft -s list chain mangle ISP_{iface1}')
+ self.assertEqual(tmp, mangle_isp1)
+
+ tmp = cmd(f'sudo nft -s list chain mangle ISP_{iface2}')
+ self.assertEqual(tmp, mangle_isp2)
+
+ tmp = cmd(f'sudo nft -s list chain mangle PREROUTING')
+ self.assertEqual(tmp, mangle_prerouting)
+
+ tmp = cmd(f'sudo nft -s list chain mangle WANLOADBALANCE_PRE')
+ self.assertEqual(tmp, mangle_wanloadbalance_pre)
+
+ # Check nat chains
+ tmp = cmd(f'sudo nft -s list chain nat WANLOADBALANCE')
+ self.assertEqual(tmp, nat_wanloadbalance)
+
+ tmp = cmd(f'sudo nft -s list chain nat VYOS_PRE_SNAT_HOOK')
+ self.assertEqual(tmp, nat_vyos_pre_snat_hook)
+
+ # Delete veth interfaces and netns
+ for iface in [iface1, iface2]:
+ call(f'sudo ip link del dev {iface}')
+
+ delete_netns(ns1)
+ delete_netns(ns2)
+
+
+if __name__ == '__main__':
+ unittest.main(verbosity=2)
diff --git a/smoketest/scripts/cli/test_pki.py b/smoketest/scripts/cli/test_pki.py
index e92123dbc..cba5ffdde 100755
--- a/smoketest/scripts/cli/test_pki.py
+++ b/smoketest/scripts/cli/test_pki.py
@@ -128,6 +128,27 @@ g6a75NnEXo0J6YLAOOxd8fD2/HidhbceCmTF+3msidIzCsBidBkgn6V5TXx2IyMS
xGsJxVHfSKeooUQn6q76sg==
"""
+valid_update_cert = """
+MIICJTCCAcugAwIBAgIUZJqjNmPfVQwePjNFBtB6WI31ThMwCgYIKoZIzj0EAwIw
+VzELMAkGA1UEBhMCR0IxEzARBgNVBAgMClNvbWUtU3RhdGUxEjAQBgNVBAcMCVNv
+bWUtQ2l0eTENMAsGA1UECgwEVnlPUzEQMA4GA1UEAwwHdnlvcy5pbzAeFw0yMjA1
+MzExNTE3NDlaFw0yMzA1MzExNTE3NDlaMFcxCzAJBgNVBAYTAkdCMRMwEQYDVQQI
+DApTb21lLVN0YXRlMRIwEAYDVQQHDAlTb21lLUNpdHkxDTALBgNVBAoMBFZ5T1Mx
+EDAOBgNVBAMMB3Z5b3MuaW8wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQMe0h/
+3CdD8mEgy+klk55QfJ8R3ZycefxCn4abWjzTXz/TuCIxqb4wpRT8DZtIn4NRimFT
+mODYdEDOYxFtZm37o3UwczAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIHgDAT
+BgNVHSUEDDAKBggrBgEFBQcDAjAdBgNVHQ4EFgQUqH7KSZpzArpMFuxLXqI8e1QD
+fBkwHwYDVR0jBBgwFoAUqH7KSZpzArpMFuxLXqI8e1QDfBkwCgYIKoZIzj0EAwID
+SAAwRQIhAKofUgRtcUljmbubPF6sqHtn/3TRvuafl8VfPbk3s2bJAiBp3Q1AnU/O
+i7t5FGhCgnv5m8DW2F3LZPCJdW4ELQ3d9A==
+"""
+
+valid_update_private_key = """
+MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgvyODf22w/p7Zgfz9
+dyLIT09LqLOrUN6zbAecfukiiiyhRANCAAQMe0h/3CdD8mEgy+klk55QfJ8R3Zyc
+efxCn4abWjzTXz/TuCIxqb4wpRT8DZtIn4NRimFTmODYdEDOYxFtZm37
+"""
+
class TestPKI(VyOSUnitTestSHIM.TestCase):
@classmethod
def setUpClass(cls):
@@ -189,5 +210,41 @@ class TestPKI(VyOSUnitTestSHIM.TestCase):
with self.assertRaises(ConfigSessionError):
self.cli_commit()
+ def test_certificate_in_use(self):
+ self.cli_set(base_path + ['certificate', 'smoketest', 'certificate', valid_ca_cert.replace('\n','')])
+ self.cli_set(base_path + ['certificate', 'smoketest', 'private', 'key', valid_ca_private_key.replace('\n','')])
+ self.cli_commit()
+
+ self.cli_set(['service', 'https', 'certificates', 'certificate', 'smoketest'])
+ self.cli_commit()
+
+ self.cli_delete(base_path + ['certificate', 'smoketest'])
+ with self.assertRaises(ConfigSessionError):
+ self.cli_commit()
+
+ self.cli_delete(['service', 'https', 'certificates', 'certificate'])
+
+ def test_certificate_https_update(self):
+ self.cli_set(base_path + ['certificate', 'smoketest', 'certificate', valid_ca_cert.replace('\n','')])
+ self.cli_set(base_path + ['certificate', 'smoketest', 'private', 'key', valid_ca_private_key.replace('\n','')])
+ self.cli_commit()
+
+ self.cli_set(['service', 'https', 'certificates', 'certificate', 'smoketest'])
+ self.cli_commit()
+
+ cert_data = None
+
+ with open('/etc/ssl/certs/smoketest.pem') as f:
+ cert_data = f.read()
+
+ self.cli_set(base_path + ['certificate', 'smoketest', 'certificate', valid_update_cert.replace('\n','')])
+ self.cli_set(base_path + ['certificate', 'smoketest', 'private', 'key', valid_update_private_key.replace('\n','')])
+ self.cli_commit()
+
+ with open('/etc/ssl/certs/smoketest.pem') as f:
+ self.assertNotEqual(cert_data, f.read())
+
+ self.cli_delete(['service', 'https', 'certificates', 'certificate'])
+
if __name__ == '__main__':
unittest.main(verbosity=2)
diff --git a/smoketest/scripts/cli/test_policy.py b/smoketest/scripts/cli/test_policy.py
index 3e8dd35ae..3d37d22ae 100755
--- a/smoketest/scripts/cli/test_policy.py
+++ b/smoketest/scripts/cli/test_policy.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
#
-# Copyright (C) 2021 VyOS maintainers and contributors
+# Copyright (C) 2021-2022 VyOS maintainers and contributors
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or later as
@@ -711,13 +711,20 @@ class TestPolicy(VyOSUnitTestSHIM.TestCase):
large_community_list = 'bgp-large-community-123456'
prefix_list = 'foo-pfx-list'
- ipv6_nexthop = 'fe80::1'
+ ipv6_nexthop_address = 'fe80::1'
local_pref = '300'
metric = '50'
peer = '2.3.4.5'
+ peerv6 = '2001:db8::1'
tag = '6542'
goto = '25'
+ ipv4_nexthop_address= '192.0.2.2'
+ ipv4_prefix_len= '18'
+ ipv6_prefix_len= '122'
+ ipv4_nexthop_type= 'blackhole'
+ ipv6_nexthop_type= 'blackhole'
+
test_data = {
'foo-map-bar' : {
'rule' : {
@@ -785,7 +792,11 @@ class TestPolicy(VyOSUnitTestSHIM.TestCase):
'30' : {
'action' : 'permit',
'match' : {
- 'ipv6-nexthop' : ipv6_nexthop,
+ 'ipv6-nexthop-address' : ipv6_nexthop_address,
+ 'ipv6-nexthop-access-list' : access_list,
+ 'ipv6-nexthop-prefix-list' : prefix_list,
+ 'ipv6-nexthop-type' : ipv6_nexthop_type,
+ 'ipv6-address-pfx-len' : ipv6_prefix_len,
'large-community' : large_community_list,
'local-pref' : local_pref,
'metric': metric,
@@ -793,6 +804,33 @@ class TestPolicy(VyOSUnitTestSHIM.TestCase):
'peer' : peer,
},
},
+
+ '31' : {
+ 'action' : 'permit',
+ 'match' : {
+ 'peer' : peerv6,
+ },
+ },
+
+ '40' : {
+ 'action' : 'permit',
+ 'match' : {
+ 'ip-nexthop-addr' : ipv4_nexthop_address,
+ 'ip-address-pfx-len' : ipv4_prefix_len,
+ },
+ },
+ '42' : {
+ 'action' : 'deny',
+ 'match' : {
+ 'ip-nexthop-plen' : ipv4_prefix_len,
+ },
+ },
+ '44' : {
+ 'action' : 'permit',
+ 'match' : {
+ 'ip-nexthop-type' : ipv4_nexthop_type,
+ },
+ },
},
},
'complicated-configuration' : {
@@ -849,6 +887,35 @@ class TestPolicy(VyOSUnitTestSHIM.TestCase):
'evpn-vni' : '1234',
},
},
+ '20' : {
+ 'action' : 'permit',
+ 'set' : {
+ 'evpn-gateway-ipv4' : '192.0.2.99',
+ 'evpn-gateway-ipv6' : '2001:db8:f00::1',
+ },
+ },
+ },
+ },
+ 'relative-metric' : {
+ 'rule' : {
+ '10' : {
+ 'action' : 'permit',
+ 'match' : {
+ 'ip-nexthop-addr' : ipv4_nexthop_address,
+ },
+ 'set' : {
+ 'metric' : '+10',
+ },
+ },
+ '20' : {
+ 'action' : 'permit',
+ 'match' : {
+ 'ip-nexthop-addr' : ipv4_nexthop_address,
+ },
+ 'set' : {
+ 'metric' : '-20',
+ },
+ },
},
},
}
@@ -910,10 +977,18 @@ class TestPolicy(VyOSUnitTestSHIM.TestCase):
self.cli_set(path + ['rule', rule, 'match', 'ip', 'address', 'access-list', rule_config['match']['ip-address-acl']])
if 'ip-address-pfx' in rule_config['match']:
self.cli_set(path + ['rule', rule, 'match', 'ip', 'address', 'prefix-list', rule_config['match']['ip-address-pfx']])
+ if 'ip-address-pfx-len' in rule_config['match']:
+ self.cli_set(path + ['rule', rule, 'match', 'ip', 'address', 'prefix-len', rule_config['match']['ip-address-pfx-len']])
if 'ip-nexthop-acl' in rule_config['match']:
self.cli_set(path + ['rule', rule, 'match', 'ip', 'nexthop', 'access-list', rule_config['match']['ip-nexthop-acl']])
if 'ip-nexthop-pfx' in rule_config['match']:
self.cli_set(path + ['rule', rule, 'match', 'ip', 'nexthop', 'prefix-list', rule_config['match']['ip-nexthop-pfx']])
+ if 'ip-nexthop-addr' in rule_config['match']:
+ self.cli_set(path + ['rule', rule, 'match', 'ip', 'nexthop', 'address', rule_config['match']['ip-nexthop-addr']])
+ if 'ip-nexthop-plen' in rule_config['match']:
+ self.cli_set(path + ['rule', rule, 'match', 'ip', 'nexthop', 'prefix-len', rule_config['match']['ip-nexthop-plen']])
+ if 'ip-nexthop-type' in rule_config['match']:
+ self.cli_set(path + ['rule', rule, 'match', 'ip', 'nexthop', 'type', rule_config['match']['ip-nexthop-type']])
if 'ip-route-source-acl' in rule_config['match']:
self.cli_set(path + ['rule', rule, 'match', 'ip', 'route-source', 'access-list', rule_config['match']['ip-route-source-acl']])
if 'ip-route-source-pfx' in rule_config['match']:
@@ -922,8 +997,16 @@ class TestPolicy(VyOSUnitTestSHIM.TestCase):
self.cli_set(path + ['rule', rule, 'match', 'ipv6', 'address', 'access-list', rule_config['match']['ipv6-address-acl']])
if 'ipv6-address-pfx' in rule_config['match']:
self.cli_set(path + ['rule', rule, 'match', 'ipv6', 'address', 'prefix-list', rule_config['match']['ipv6-address-pfx']])
- if 'ipv6-nexthop' in rule_config['match']:
- self.cli_set(path + ['rule', rule, 'match', 'ipv6', 'nexthop', rule_config['match']['ipv6-nexthop']])
+ if 'ipv6-address-pfx-len' in rule_config['match']:
+ self.cli_set(path + ['rule', rule, 'match', 'ipv6', 'address', 'prefix-len', rule_config['match']['ipv6-address-pfx-len']])
+ if 'ipv6-nexthop-address' in rule_config['match']:
+ self.cli_set(path + ['rule', rule, 'match', 'ipv6', 'nexthop', 'address', rule_config['match']['ipv6-nexthop-address']])
+ if 'ipv6-nexthop-access-list' in rule_config['match']:
+ self.cli_set(path + ['rule', rule, 'match', 'ipv6', 'nexthop', 'access-list', rule_config['match']['ipv6-nexthop-access-list']])
+ if 'ipv6-nexthop-prefix-list' in rule_config['match']:
+ self.cli_set(path + ['rule', rule, 'match', 'ipv6', 'nexthop', 'prefix-list', rule_config['match']['ipv6-nexthop-prefix-list']])
+ if 'ipv6-nexthop-type' in rule_config['match']:
+ self.cli_set(path + ['rule', rule, 'match', 'ipv6', 'nexthop', 'type', rule_config['match']['ipv6-nexthop-type']])
if 'large-community' in rule_config['match']:
self.cli_set(path + ['rule', rule, 'match', 'large-community', 'large-community-list', rule_config['match']['large-community']])
if 'local-pref' in rule_config['match']:
@@ -996,6 +1079,10 @@ class TestPolicy(VyOSUnitTestSHIM.TestCase):
self.cli_set(path + ['rule', rule, 'set', 'tag', rule_config['set']['tag']])
if 'weight' in rule_config['set']:
self.cli_set(path + ['rule', rule, 'set', 'weight', rule_config['set']['weight']])
+ if 'evpn-gateway-ipv4' in rule_config['set']:
+ self.cli_set(path + ['rule', rule, 'set', 'evpn', 'gateway', 'ipv4', rule_config['set']['evpn-gateway-ipv4']])
+ if 'evpn-gateway-ipv6' in rule_config['set']:
+ self.cli_set(path + ['rule', rule, 'set', 'evpn', 'gateway', 'ipv6', rule_config['set']['evpn-gateway-ipv6']])
self.cli_commit()
@@ -1046,12 +1133,24 @@ class TestPolicy(VyOSUnitTestSHIM.TestCase):
if 'ip-address-pfx' in rule_config['match']:
tmp = f'match ip address prefix-list {rule_config["match"]["ip-address-pfx"]}'
self.assertIn(tmp, config)
+ if 'ip-address-pfx-len' in rule_config['match']:
+ tmp = f'match ip address prefix-len {rule_config["match"]["ip-address-pfx-len"]}'
+ self.assertIn(tmp, config)
if 'ip-nexthop-acl' in rule_config['match']:
tmp = f'match ip next-hop {rule_config["match"]["ip-nexthop-acl"]}'
self.assertIn(tmp, config)
if 'ip-nexthop-pfx' in rule_config['match']:
tmp = f'match ip next-hop prefix-list {rule_config["match"]["ip-nexthop-pfx"]}'
self.assertIn(tmp, config)
+ if 'ip-nexthop-addr' in rule_config['match']:
+ tmp = f'match ip next-hop address {rule_config["match"]["ip-nexthop-addr"]}'
+ self.assertIn(tmp, config)
+ if 'ip-nexthop-plen' in rule_config['match']:
+ tmp = f'match ip next-hop prefix-len {rule_config["match"]["ip-nexthop-plen"]}'
+ self.assertIn(tmp, config)
+ if 'ip-nexthop-type' in rule_config['match']:
+ tmp = f'match ip next-hop type {rule_config["match"]["ip-nexthop-type"]}'
+ self.assertIn(tmp, config)
if 'ip-route-source-acl' in rule_config['match']:
tmp = f'match ip route-source {rule_config["match"]["ip-route-source-acl"]}'
self.assertIn(tmp, config)
@@ -1064,8 +1163,20 @@ class TestPolicy(VyOSUnitTestSHIM.TestCase):
if 'ipv6-address-pfx' in rule_config['match']:
tmp = f'match ipv6 address prefix-list {rule_config["match"]["ipv6-address-pfx"]}'
self.assertIn(tmp, config)
- if 'ipv6-nexthop' in rule_config['match']:
- tmp = f'match ipv6 next-hop address {rule_config["match"]["ipv6-nexthop"]}'
+ if 'ipv6-address-pfx-len' in rule_config['match']:
+ tmp = f'match ipv6 address prefix-len {rule_config["match"]["ipv6-address-pfx-len"]}'
+ self.assertIn(tmp, config)
+ if 'ipv6-nexthop-address' in rule_config['match']:
+ tmp = f'match ipv6 next-hop address {rule_config["match"]["ipv6-nexthop-address"]}'
+ self.assertIn(tmp, config)
+ if 'ipv6-nexthop-access-list' in rule_config['match']:
+ tmp = f'match ipv6 next-hop {rule_config["match"]["ipv6-nexthop-access-list"]}'
+ self.assertIn(tmp, config)
+ if 'ipv6-nexthop-prefix-list' in rule_config['match']:
+ tmp = f'match ipv6 next-hop prefix-list {rule_config["match"]["ipv6-nexthop-prefix-list"]}'
+ self.assertIn(tmp, config)
+ if 'ipv6-nexthop-type' in rule_config['match']:
+ tmp = f'match ipv6 next-hop type {rule_config["match"]["ipv6-nexthop-type"]}'
self.assertIn(tmp, config)
if 'large-community' in rule_config['match']:
tmp = f'match large-community {rule_config["match"]["large-community"]}'
@@ -1155,6 +1266,10 @@ class TestPolicy(VyOSUnitTestSHIM.TestCase):
tmp += 'tag ' + rule_config['set']['tag']
elif 'weight' in rule_config['set']:
tmp += 'weight ' + rule_config['set']['weight']
+ elif 'vpn-gateway-ipv4' in rule_config['set']:
+ tmp += 'evpn gateway ipv4 ' + rule_config['set']['vpn-gateway-ipv4']
+ elif 'vpn-gateway-ipv6' in rule_config['set']:
+ tmp += 'evpn gateway ipv6 ' + rule_config['set']['vpn-gateway-ipv6']
self.assertIn(tmp, config)
diff --git a/smoketest/scripts/cli/test_policy_route.py b/smoketest/scripts/cli/test_policy_route.py
index 9035f0832..534cfb082 100755
--- a/smoketest/scripts/cli/test_policy_route.py
+++ b/smoketest/scripts/cli/test_policy_route.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
#
-# Copyright (C) 2021 VyOS maintainers and contributors
+# Copyright (C) 2021-2022 VyOS maintainers and contributors
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or later as
@@ -23,44 +23,88 @@ from vyos.util import cmd
mark = '100'
table_mark_offset = 0x7fffffff
table_id = '101'
+interface = 'eth0'
+interface_ip = '172.16.10.1/24'
class TestPolicyRoute(VyOSUnitTestSHIM.TestCase):
- def setUp(self):
- self.cli_set(['interfaces', 'ethernet', 'eth0', 'address', '172.16.10.1/24'])
- self.cli_set(['protocols', 'static', 'table', '101', 'route', '0.0.0.0/0', 'interface', 'eth0'])
+ @classmethod
+ def setUpClass(cls):
+ super(TestPolicyRoute, cls).setUpClass()
+
+ cls.cli_set(cls, ['interfaces', 'ethernet', interface, 'address', interface_ip])
+ cls.cli_set(cls, ['protocols', 'static', 'table', table_id, 'route', '0.0.0.0/0', 'interface', interface])
+
+ @classmethod
+ def tearDownClass(cls):
+ cls.cli_delete(cls, ['interfaces', 'ethernet', interface, 'address', interface_ip])
+ cls.cli_delete(cls, ['protocols', 'static', 'table', table_id])
+
+ super(TestPolicyRoute, cls).tearDownClass()
def tearDown(self):
- self.cli_delete(['interfaces', 'ethernet', 'eth0'])
- self.cli_delete(['protocols', 'static'])
+ self.cli_delete(['interfaces', 'ethernet', interface, 'policy'])
self.cli_delete(['policy', 'route'])
self.cli_delete(['policy', 'route6'])
self.cli_commit()
+ nftables_search = [
+ ['set N_smoketest_network'],
+ ['set N_smoketest_network1'],
+ ['chain VYOS_PBR_smoketest']
+ ]
+
+ self.verify_nftables(nftables_search, 'ip filter', inverse=True)
+
+ def verify_nftables(self, nftables_search, table, inverse=False):
+ nftables_output = cmd(f'sudo nft list table {table}')
+
+ for search in nftables_search:
+ matched = False
+ for line in nftables_output.split("\n"):
+ if all(item in line for item in search):
+ matched = True
+ break
+ self.assertTrue(not matched if inverse else matched, msg=search)
+
+ def test_pbr_group(self):
+ self.cli_set(['firewall', 'group', 'network-group', 'smoketest_network', 'network', '172.16.99.0/24'])
+ self.cli_set(['firewall', 'group', 'network-group', 'smoketest_network1', 'network', '172.16.101.0/24'])
+ self.cli_set(['firewall', 'group', 'network-group', 'smoketest_network1', 'include', 'smoketest_network'])
+
+ self.cli_set(['policy', 'route', 'smoketest', 'rule', '1', 'source', 'group', 'network-group', 'smoketest_network'])
+ self.cli_set(['policy', 'route', 'smoketest', 'rule', '1', 'destination', 'group', 'network-group', 'smoketest_network1'])
+ self.cli_set(['policy', 'route', 'smoketest', 'rule', '1', 'set', 'mark', mark])
+
+ self.cli_set(['interfaces', 'ethernet', interface, 'policy', 'route', 'smoketest'])
+
+ self.cli_commit()
+
+ nftables_search = [
+ [f'iifname "{interface}"','jump VYOS_PBR_smoketest'],
+ ['ip daddr @N_smoketest_network1', 'ip saddr @N_smoketest_network'],
+ ]
+
+ self.verify_nftables(nftables_search, 'ip mangle')
+
+ self.cli_delete(['firewall'])
+
def test_pbr_mark(self):
self.cli_set(['policy', 'route', 'smoketest', 'rule', '1', 'source', 'address', '172.16.20.10'])
self.cli_set(['policy', 'route', 'smoketest', 'rule', '1', 'destination', 'address', '172.16.10.10'])
self.cli_set(['policy', 'route', 'smoketest', 'rule', '1', 'set', 'mark', mark])
- self.cli_set(['interfaces', 'ethernet', 'eth0', 'policy', 'route', 'smoketest'])
+ self.cli_set(['interfaces', 'ethernet', interface, 'policy', 'route', 'smoketest'])
self.cli_commit()
mark_hex = "{0:#010x}".format(int(mark))
nftables_search = [
- ['iifname "eth0"', 'jump VYOS_PBR_smoketest'],
+ [f'iifname "{interface}"','jump VYOS_PBR_smoketest'],
['ip daddr 172.16.10.10', 'ip saddr 172.16.20.10', 'meta mark set ' + mark_hex],
]
- nftables_output = cmd('sudo nft list table ip mangle')
-
- for search in nftables_search:
- matched = False
- for line in nftables_output.split("\n"):
- if all(item in line for item in search):
- matched = True
- break
- self.assertTrue(matched)
+ self.verify_nftables(nftables_search, 'ip mangle')
def test_pbr_table(self):
self.cli_set(['policy', 'route', 'smoketest', 'rule', '1', 'protocol', 'tcp'])
@@ -72,8 +116,8 @@ class TestPolicyRoute(VyOSUnitTestSHIM.TestCase):
self.cli_set(['policy', 'route6', 'smoketest6', 'rule', '1', 'destination', 'port', '8888'])
self.cli_set(['policy', 'route6', 'smoketest6', 'rule', '1', 'set', 'table', table_id])
- self.cli_set(['interfaces', 'ethernet', 'eth0', 'policy', 'route', 'smoketest'])
- self.cli_set(['interfaces', 'ethernet', 'eth0', 'policy', 'route6', 'smoketest6'])
+ self.cli_set(['interfaces', 'ethernet', interface, 'policy', 'route', 'smoketest'])
+ self.cli_set(['interfaces', 'ethernet', interface, 'policy', 'route6', 'smoketest6'])
self.cli_commit()
@@ -82,36 +126,20 @@ class TestPolicyRoute(VyOSUnitTestSHIM.TestCase):
# IPv4
nftables_search = [
- ['iifname "eth0"', 'jump VYOS_PBR_smoketest'],
+ [f'iifname "{interface}"', 'jump VYOS_PBR_smoketest'],
['tcp flags & (syn | ack) == syn', 'tcp dport { 8888 }', 'meta mark set ' + mark_hex]
]
- nftables_output = cmd('sudo nft list table ip mangle')
-
- for search in nftables_search:
- matched = False
- for line in nftables_output.split("\n"):
- if all(item in line for item in search):
- matched = True
- break
- self.assertTrue(matched)
+ self.verify_nftables(nftables_search, 'ip mangle')
# IPv6
nftables6_search = [
- ['iifname "eth0"', 'jump VYOS_PBR6_smoketest'],
+ [f'iifname "{interface}"', 'jump VYOS_PBR6_smoketest'],
['meta l4proto { tcp, udp }', 'th dport { 8888 }', 'meta mark set ' + mark_hex]
]
- nftables6_output = cmd('sudo nft list table ip6 mangle')
-
- for search in nftables6_search:
- matched = False
- for line in nftables6_output.split("\n"):
- if all(item in line for item in search):
- matched = True
- break
- self.assertTrue(matched)
+ self.verify_nftables(nftables6_search, 'ip6 mangle')
# IP rule fwmark -> table
diff --git a/smoketest/scripts/cli/test_protocols_bgp.py b/smoketest/scripts/cli/test_protocols_bgp.py
index 6f92457b2..9c0c93779 100755
--- a/smoketest/scripts/cli/test_protocols_bgp.py
+++ b/smoketest/scripts/cli/test_protocols_bgp.py
@@ -887,6 +887,7 @@ class TestProtocolsBGP(VyOSUnitTestSHIM.TestCase):
remote_asn = str(int(ASN) + 150)
neighbor = '192.0.2.1'
peer_group = 'bar'
+ interface = 'eth0'
self.cli_set(base_path + ['local-as', ASN])
self.cli_set(base_path + ['neighbor', neighbor, 'remote-as', remote_asn])
@@ -898,6 +899,20 @@ class TestProtocolsBGP(VyOSUnitTestSHIM.TestCase):
self.cli_commit()
self.cli_delete(base_path + ['neighbor', neighbor, 'remote-as'])
+ # re-test with interface based peer-group
+ self.cli_set(base_path + ['neighbor', interface, 'interface', 'peer-group', peer_group])
+ self.cli_set(base_path + ['neighbor', interface, 'interface', 'remote-as', 'external'])
+ with self.assertRaises(ConfigSessionError):
+ self.cli_commit()
+ self.cli_delete(base_path + ['neighbor', interface, 'interface', 'remote-as'])
+
+ # re-test with interface based v6only peer-group
+ self.cli_set(base_path + ['neighbor', interface, 'interface', 'v6only', 'peer-group', peer_group])
+ self.cli_set(base_path + ['neighbor', interface, 'interface', 'v6only', 'remote-as', 'external'])
+ with self.assertRaises(ConfigSessionError):
+ self.cli_commit()
+ self.cli_delete(base_path + ['neighbor', interface, 'interface', 'v6only', 'remote-as'])
+
self.cli_commit()
frrconfig = self.getFRRconfig(f'router bgp {ASN}')
diff --git a/smoketest/scripts/cli/test_protocols_rip.py b/smoketest/scripts/cli/test_protocols_rip.py
index 80d4e79f9..11385adb5 100755
--- a/smoketest/scripts/cli/test_protocols_rip.py
+++ b/smoketest/scripts/cli/test_protocols_rip.py
@@ -31,26 +31,38 @@ route_map = 'FooBar123'
base_path = ['protocols', 'rip']
class TestProtocolsRIP(VyOSUnitTestSHIM.TestCase):
- def setUp(self):
- self.cli_set(['policy', 'access-list', acl_in, 'rule', '10', 'action', 'permit'])
- self.cli_set(['policy', 'access-list', acl_in, 'rule', '10', 'source', 'any'])
- self.cli_set(['policy', 'access-list', acl_in, 'rule', '10', 'destination', 'any'])
- self.cli_set(['policy', 'access-list', acl_out, 'rule', '20', 'action', 'deny'])
- self.cli_set(['policy', 'access-list', acl_out, 'rule', '20', 'source', 'any'])
- self.cli_set(['policy', 'access-list', acl_out, 'rule', '20', 'destination', 'any'])
- self.cli_set(['policy', 'prefix-list', prefix_list_in, 'rule', '100', 'action', 'permit'])
- self.cli_set(['policy', 'prefix-list', prefix_list_in, 'rule', '100', 'prefix', '192.0.2.0/24'])
- self.cli_set(['policy', 'prefix-list', prefix_list_out, 'rule', '200', 'action', 'deny'])
- self.cli_set(['policy', 'prefix-list', prefix_list_out, 'rule', '200', 'prefix', '192.0.2.0/24'])
- self.cli_set(['policy', 'route-map', route_map, 'rule', '10', 'action', 'permit'])
+ @classmethod
+ def setUpClass(cls):
+ super(TestProtocolsRIP, cls).setUpClass()
+
+ # ensure we can also run this test on a live system - so lets clean
+ # out the current configuration :)
+ cls.cli_delete(cls, base_path)
+
+ cls.cli_set(cls, ['policy', 'access-list', acl_in, 'rule', '10', 'action', 'permit'])
+ cls.cli_set(cls, ['policy', 'access-list', acl_in, 'rule', '10', 'source', 'any'])
+ cls.cli_set(cls, ['policy', 'access-list', acl_in, 'rule', '10', 'destination', 'any'])
+ cls.cli_set(cls, ['policy', 'access-list', acl_out, 'rule', '20', 'action', 'deny'])
+ cls.cli_set(cls, ['policy', 'access-list', acl_out, 'rule', '20', 'source', 'any'])
+ cls.cli_set(cls, ['policy', 'access-list', acl_out, 'rule', '20', 'destination', 'any'])
+ cls.cli_set(cls, ['policy', 'prefix-list', prefix_list_in, 'rule', '100', 'action', 'permit'])
+ cls.cli_set(cls, ['policy', 'prefix-list', prefix_list_in, 'rule', '100', 'prefix', '192.0.2.0/24'])
+ cls.cli_set(cls, ['policy', 'prefix-list', prefix_list_out, 'rule', '200', 'action', 'deny'])
+ cls.cli_set(cls, ['policy', 'prefix-list', prefix_list_out, 'rule', '200', 'prefix', '192.0.2.0/24'])
+ cls.cli_set(cls, ['policy', 'route-map', route_map, 'rule', '10', 'action', 'permit'])
+
+ @classmethod
+ def tearDownClass(cls):
+ cls.cli_delete(cls, ['policy', 'access-list', acl_in])
+ cls.cli_delete(cls, ['policy', 'access-list', acl_out])
+ cls.cli_delete(cls, ['policy', 'prefix-list', prefix_list_in])
+ cls.cli_delete(cls, ['policy', 'prefix-list', prefix_list_out])
+ cls.cli_delete(cls, ['policy', 'route-map', route_map])
+
+ super(TestProtocolsRIP, cls).tearDownClass()
def tearDown(self):
self.cli_delete(base_path)
- self.cli_delete(['policy', 'access-list', acl_in])
- self.cli_delete(['policy', 'access-list', acl_out])
- self.cli_delete(['policy', 'prefix-list', prefix_list_in])
- self.cli_delete(['policy', 'prefix-list', prefix_list_out])
- self.cli_delete(['policy', 'route-map', route_map])
self.cli_commit()
# Check for running process
@@ -146,5 +158,25 @@ class TestProtocolsRIP(VyOSUnitTestSHIM.TestCase):
frrconfig = self.getFRRconfig(zebra_route_map)
self.assertNotIn(zebra_route_map, frrconfig)
+ def test_rip_03_version(self):
+ rx_version = '1'
+ tx_version = '2'
+ interface = 'eth0'
+
+ self.cli_set(base_path + ['version', tx_version])
+ self.cli_set(base_path + ['interface', interface, 'send', 'version', tx_version])
+ self.cli_set(base_path + ['interface', interface, 'receive', 'version', rx_version])
+
+ # commit changes
+ self.cli_commit()
+
+ # Verify FRR configuration
+ frrconfig = self.getFRRconfig('router rip')
+ self.assertIn(f'version {tx_version}', frrconfig)
+
+ frrconfig = self.getFRRconfig(f'interface {interface}')
+ self.assertIn(f' ip rip receive version {rx_version}', frrconfig)
+ self.assertIn(f' ip rip send version {tx_version}', frrconfig)
+
if __name__ == '__main__':
unittest.main(verbosity=2)
diff --git a/smoketest/scripts/cli/test_service_dns_forwarding.py b/smoketest/scripts/cli/test_service_dns_forwarding.py
index 5929f8cba..65b676451 100755
--- a/smoketest/scripts/cli/test_service_dns_forwarding.py
+++ b/smoketest/scripts/cli/test_service_dns_forwarding.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
#
-# Copyright (C) 2019-2021 VyOS maintainers and contributors
+# Copyright (C) 2019-2022 VyOS maintainers and contributors
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or later as
@@ -39,7 +39,18 @@ def get_config_value(key, file=CONFIG_FILE):
return tmp[0]
class TestServicePowerDNS(VyOSUnitTestSHIM.TestCase):
+ @classmethod
+ def setUpClass(cls):
+ super(TestServicePowerDNS, cls).setUpClass()
+
+ # ensure we can also run this test on a live system - so lets clean
+ # out the current configuration :)
+ cls.cli_delete(cls, base_path)
+
def tearDown(self):
+ # Check for running process
+ self.assertTrue(process_named_running(PROCESS_NAME))
+
# Delete DNS forwarding configuration
self.cli_delete(base_path)
self.cli_commit()
@@ -100,9 +111,6 @@ class TestServicePowerDNS(VyOSUnitTestSHIM.TestCase):
tmp = get_config_value('serve-rfc1918')
self.assertEqual(tmp, 'yes')
- # Check for running process
- self.assertTrue(process_named_running(PROCESS_NAME))
-
def test_dnssec(self):
# DNSSEC option testing
@@ -121,9 +129,6 @@ class TestServicePowerDNS(VyOSUnitTestSHIM.TestCase):
tmp = get_config_value('dnssec')
self.assertEqual(tmp, option)
- # Check for running process
- self.assertTrue(process_named_running(PROCESS_NAME))
-
def test_external_nameserver(self):
# Externe Domain Name Servers (DNS) addresses
@@ -147,9 +152,6 @@ class TestServicePowerDNS(VyOSUnitTestSHIM.TestCase):
tmp = get_config_value('export-etc-hosts')
self.assertEqual(tmp, 'yes')
- # Check for running process
- self.assertTrue(process_named_running(PROCESS_NAME))
-
def test_domain_forwarding(self):
for network in allow_from:
self.cli_set(base_path + ['allow-from', network])
@@ -186,9 +188,6 @@ class TestServicePowerDNS(VyOSUnitTestSHIM.TestCase):
if domain == domains[1]:
self.assertIn(f'addNTA("{domain}", "static")', hosts_conf)
- # Check for running process
- self.assertTrue(process_named_running(PROCESS_NAME))
-
def test_no_rfc1918_forwarding(self):
for network in allow_from:
self.cli_set(base_path + ['allow-from', network])
@@ -204,9 +203,26 @@ class TestServicePowerDNS(VyOSUnitTestSHIM.TestCase):
tmp = get_config_value('serve-rfc1918')
self.assertEqual(tmp, 'no')
- # Check for running process
- self.assertTrue(process_named_running(PROCESS_NAME))
+ def test_dns64(self):
+ dns_prefix = '64:ff9b::/96'
+
+ for network in allow_from:
+ self.cli_set(base_path + ['allow-from', network])
+ for address in listen_adress:
+ self.cli_set(base_path + ['listen-address', address])
+
+ # Check dns64-prefix - must be prefix /96
+ self.cli_set(base_path + ['dns64-prefix', '2001:db8:aabb::/64'])
+ with self.assertRaises(ConfigSessionError):
+ self.cli_commit()
+ self.cli_set(base_path + ['dns64-prefix', dns_prefix])
+
+ # commit changes
+ self.cli_commit()
+
+ # verify dns64-prefix configuration
+ tmp = get_config_value('dns64-prefix')
+ self.assertEqual(tmp, dns_prefix)
if __name__ == '__main__':
unittest.main(verbosity=2)
-
diff --git a/smoketest/scripts/cli/test_service_monitoring_telegraf.py b/smoketest/scripts/cli/test_service_monitoring_telegraf.py
index 09937513e..f9d875e83 100755
--- a/smoketest/scripts/cli/test_service_monitoring_telegraf.py
+++ b/smoketest/scripts/cli/test_service_monitoring_telegraf.py
@@ -39,10 +39,10 @@ class TestMonitoringTelegraf(VyOSUnitTestSHIM.TestCase):
self.cli_commit()
def test_01_basic_config(self):
- self.cli_set(base_path + ['authentication', 'organization', org])
- self.cli_set(base_path + ['authentication', 'token', token])
- self.cli_set(base_path + ['port', port])
- self.cli_set(base_path + ['url', url])
+ self.cli_set(base_path + ['influxdb', 'authentication', 'organization', org])
+ self.cli_set(base_path + ['influxdb', 'authentication', 'token', token])
+ self.cli_set(base_path + ['influxdb', 'port', port])
+ self.cli_set(base_path + ['influxdb', 'url', url])
# commit changes
self.cli_commit()
diff --git a/smoketest/scripts/cli/test_service_router-advert.py b/smoketest/scripts/cli/test_service_router-advert.py
index 4875fb5d1..1168c05cd 100755
--- a/smoketest/scripts/cli/test_service_router-advert.py
+++ b/smoketest/scripts/cli/test_service_router-advert.py
@@ -17,6 +17,7 @@
import re
import unittest
+from vyos.configsession import ConfigSessionError
from base_vyostest_shim import VyOSUnitTestSHIM
from vyos.util import read_file
@@ -93,6 +94,7 @@ class TestServiceRADVD(VyOSUnitTestSHIM.TestCase):
def test_dns(self):
nameserver = ['2001:db8::1', '2001:db8::2']
dnssl = ['vyos.net', 'vyos.io']
+ ns_lifetime = '599'
self.cli_set(base_path + ['prefix', '::/64', 'valid-lifetime', 'infinity'])
self.cli_set(base_path + ['other-config-flag'])
@@ -102,6 +104,14 @@ class TestServiceRADVD(VyOSUnitTestSHIM.TestCase):
for sl in dnssl:
self.cli_set(base_path + ['dnssl', sl])
+ self.cli_set(base_path + ['name-server-lifetime', ns_lifetime])
+ # The value, if not 0, must be at least interval max (defaults to 600).
+ with self.assertRaises(ConfigSessionError):
+ self.cli_commit()
+
+ ns_lifetime = '600'
+ self.cli_set(base_path + ['name-server-lifetime', ns_lifetime])
+
# commit changes
self.cli_commit()
@@ -110,8 +120,12 @@ class TestServiceRADVD(VyOSUnitTestSHIM.TestCase):
tmp = 'RDNSS ' + ' '.join(nameserver) + ' {'
self.assertIn(tmp, config)
+ tmp = f'AdvRDNSSLifetime {ns_lifetime};'
+ self.assertIn(tmp, config)
+
tmp = 'DNSSL ' + ' '.join(dnssl) + ' {'
self.assertIn(tmp, config)
+
if __name__ == '__main__':
unittest.main(verbosity=2)
diff --git a/smoketest/scripts/cli/test_service_ssh.py b/smoketest/scripts/cli/test_service_ssh.py
index 77ad5bc0d..0b029dd00 100755
--- a/smoketest/scripts/cli/test_service_ssh.py
+++ b/smoketest/scripts/cli/test_service_ssh.py
@@ -213,5 +213,54 @@ class TestServiceSSH(VyOSUnitTestSHIM.TestCase):
usernames = [x[0] for x in getpwall()]
self.assertNotIn(test_user, usernames)
+ def test_ssh_dynamic_protection(self):
+ # check sshguard service
+
+ SSHGUARD_CONFIG = '/etc/sshguard/sshguard.conf'
+ SSHGUARD_WHITELIST = '/etc/sshguard/whitelist'
+ SSHGUARD_PROCESS = 'sshguard'
+ block_time = '123'
+ detect_time = '1804'
+ port = '22'
+ threshold = '10'
+ allow_list = ['192.0.2.0/24', '2001:db8::/48']
+
+ self.cli_set(base_path + ['dynamic-protection', 'block-time', block_time])
+ self.cli_set(base_path + ['dynamic-protection', 'detect-time', detect_time])
+ self.cli_set(base_path + ['dynamic-protection', 'threshold', threshold])
+ for allow in allow_list:
+ self.cli_set(base_path + ['dynamic-protection', 'allow-from', allow])
+
+ # commit changes
+ self.cli_commit()
+
+ # Check configured port
+ tmp = get_config_value('Port')
+ self.assertIn(port, tmp)
+
+ # Check sshgurad service
+ self.assertTrue(process_named_running(SSHGUARD_PROCESS))
+
+ sshguard_lines = [
+ f'THRESHOLD={threshold}',
+ f'BLOCK_TIME={block_time}',
+ f'DETECTION_TIME={detect_time}'
+ ]
+
+ tmp_sshguard_conf = read_file(SSHGUARD_CONFIG)
+ for line in sshguard_lines:
+ self.assertIn(line, tmp_sshguard_conf)
+
+ tmp_whitelist_conf = read_file(SSHGUARD_WHITELIST)
+ for allow in allow_list:
+ self.assertIn(allow, tmp_whitelist_conf)
+
+ # Delete service ssh dynamic-protection
+ # but not service ssh itself
+ self.cli_delete(base_path + ['dynamic-protection'])
+ self.cli_commit()
+
+ self.assertFalse(process_named_running(SSHGUARD_PROCESS))
+
if __name__ == '__main__':
unittest.main(verbosity=2)
diff --git a/smoketest/scripts/cli/test_system_flow-accounting.py b/smoketest/scripts/cli/test_system_flow-accounting.py
index 5a73ebc7d..a6eef3fb6 100755
--- a/smoketest/scripts/cli/test_system_flow-accounting.py
+++ b/smoketest/scripts/cli/test_system_flow-accounting.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
#
-# Copyright (C) 2021 VyOS maintainers and contributors
+# Copyright (C) 2021-2022 VyOS maintainers and contributors
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or later as
@@ -20,6 +20,8 @@ from base_vyostest_shim import VyOSUnitTestSHIM
from vyos.configsession import ConfigSessionError
from vyos.ifconfig import Section
+from vyos.template import bracketize_ipv6
+from vyos.template import is_ipv6
from vyos.util import cmd
from vyos.util import process_named_running
from vyos.util import read_file
@@ -103,14 +105,12 @@ class TestSystemFlowAccounting(VyOSUnitTestSHIM.TestCase):
agent_address = '192.0.2.2'
sflow_server = {
- '1.2.3.4' : {
- },
- '5.6.7.8' : {
- 'port' : '6000'
- }
+ '1.2.3.4' : { },
+ '5.6.7.8' : { 'port' : '6000' },
}
self.cli_set(['interfaces', 'dummy', dummy_if, 'address', agent_address + '/32'])
+ self.cli_set(['interfaces', 'dummy', dummy_if, 'address', source_address + '/32'])
self.cli_set(base_path + ['disable-imt'])
# You need to configure at least one interface for flow-accounting
@@ -155,6 +155,54 @@ class TestSystemFlowAccounting(VyOSUnitTestSHIM.TestCase):
self.cli_delete(['interfaces', 'dummy', dummy_if])
+ def test_sflow_ipv6(self):
+ sampling_rate = '100'
+ sflow_server = {
+ '2001:db8::1' : { },
+ '2001:db8::2' : { 'port' : '6000' },
+ }
+
+ self.cli_set(base_path + ['disable-imt'])
+
+ # You need to configure at least one interface for flow-accounting
+ with self.assertRaises(ConfigSessionError):
+ self.cli_commit()
+ for interface in Section.interfaces('ethernet'):
+ self.cli_set(base_path + ['interface', interface])
+
+
+ # You need to configure at least one sFlow or NetFlow protocol, or not
+ # set "disable-imt" for flow-accounting
+ with self.assertRaises(ConfigSessionError):
+ self.cli_commit()
+
+ self.cli_set(base_path + ['sflow', 'sampling-rate', sampling_rate])
+ for server, server_config in sflow_server.items():
+ self.cli_set(base_path + ['sflow', 'server', server])
+ if 'port' in server_config:
+ self.cli_set(base_path + ['sflow', 'server', server, 'port', server_config['port']])
+
+ # commit changes
+ self.cli_commit()
+
+ uacctd = read_file(uacctd_conf)
+
+ # when 'disable-imt' is not configured on the CLI it must be present
+ self.assertNotIn(f'imt_path: /tmp/uacctd.pipe', uacctd)
+ self.assertNotIn(f'imt_mem_pools_number: 169', uacctd)
+ self.assertNotIn(f'plugins: memory', uacctd)
+
+ for server, server_config in sflow_server.items():
+ tmp_srv = server
+ if is_ipv6(tmp_srv):
+ tmp_srv = tmp_srv.replace(':', '.')
+
+ if 'port' in server_config:
+ self.assertIn(f'sfprobe_receiver[sf_{tmp_srv}]: {bracketize_ipv6(server)}', uacctd)
+ else:
+ self.assertIn(f'sfprobe_receiver[sf_{tmp_srv}]: {bracketize_ipv6(server)}:6343', uacctd)
+ self.assertIn(f'sampling_rate[sf_{tmp_srv}]: {sampling_rate}', uacctd)
+
def test_netflow(self):
engine_id = '33'
max_flows = '667'
@@ -173,14 +221,13 @@ class TestSystemFlowAccounting(VyOSUnitTestSHIM.TestCase):
tmo_udp = '10'
netflow_server = {
- '11.22.33.44' : {
- },
- '55.66.77.88' : {
- 'port' : '6000'
- }
+ '11.22.33.44' : { },
+ '55.66.77.88' : { 'port' : '6000' },
+ '2001:db8::1' : { },
}
self.cli_set(['interfaces', 'dummy', dummy_if, 'address', agent_address + '/32'])
+ self.cli_set(['interfaces', 'dummy', dummy_if, 'address', source_address + '/32'])
for interface in Section.interfaces('ethernet'):
self.cli_set(base_path + ['interface', interface])
@@ -217,23 +264,30 @@ class TestSystemFlowAccounting(VyOSUnitTestSHIM.TestCase):
tmp = []
for server, server_config in netflow_server.items():
- tmp.append(f'nfprobe[nf_{server}]')
+ tmp_srv = server
+ if is_ipv6(tmp_srv):
+ tmp_srv = tmp_srv.replace(':', '.')
+ tmp.append(f'nfprobe[nf_{tmp_srv}]')
tmp.append('memory')
self.assertIn('plugins: ' + ','.join(tmp), uacctd)
for server, server_config in netflow_server.items():
- self.assertIn(f'nfprobe_engine[nf_{server}]: {engine_id}', uacctd)
- self.assertIn(f'nfprobe_maxflows[nf_{server}]: {max_flows}', uacctd)
- self.assertIn(f'sampling_rate[nf_{server}]: {sampling_rate}', uacctd)
- self.assertIn(f'nfprobe_source_ip[nf_{server}]: {source_address}', uacctd)
- self.assertIn(f'nfprobe_version[nf_{server}]: {version}', uacctd)
+ tmp_srv = server
+ if is_ipv6(tmp_srv):
+ tmp_srv = tmp_srv.replace(':', '.')
+
+ self.assertIn(f'nfprobe_engine[nf_{tmp_srv}]: {engine_id}', uacctd)
+ self.assertIn(f'nfprobe_maxflows[nf_{tmp_srv}]: {max_flows}', uacctd)
+ self.assertIn(f'sampling_rate[nf_{tmp_srv}]: {sampling_rate}', uacctd)
+ self.assertIn(f'nfprobe_source_ip[nf_{tmp_srv}]: {source_address}', uacctd)
+ self.assertIn(f'nfprobe_version[nf_{tmp_srv}]: {version}', uacctd)
if 'port' in server_config:
- self.assertIn(f'nfprobe_receiver[nf_{server}]: {server}', uacctd)
+ self.assertIn(f'nfprobe_receiver[nf_{tmp_srv}]: {bracketize_ipv6(server)}', uacctd)
else:
- self.assertIn(f'nfprobe_receiver[nf_{server}]: {server}:2055', uacctd)
+ self.assertIn(f'nfprobe_receiver[nf_{tmp_srv}]: {bracketize_ipv6(server)}:2055', uacctd)
- self.assertIn(f'nfprobe_timeouts[nf_{server}]: expint={tmo_expiry}:general={tmo_flow}:icmp={tmo_icmp}:maxlife={tmo_max}:tcp.fin={tmo_tcp_fin}:tcp={tmo_tcp_generic}:tcp.rst={tmo_tcp_rst}:udp={tmo_udp}', uacctd)
+ self.assertIn(f'nfprobe_timeouts[nf_{tmp_srv}]: expint={tmo_expiry}:general={tmo_flow}:icmp={tmo_icmp}:maxlife={tmo_max}:tcp.fin={tmo_tcp_fin}:tcp={tmo_tcp_generic}:tcp.rst={tmo_tcp_rst}:udp={tmo_udp}', uacctd)
self.cli_delete(['interfaces', 'dummy', dummy_if])
diff --git a/smoketest/scripts/cli/test_system_frr.py b/smoketest/scripts/cli/test_system_frr.py
new file mode 100755
index 000000000..331133ed4
--- /dev/null
+++ b/smoketest/scripts/cli/test_system_frr.py
@@ -0,0 +1,146 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2019-2020 VyOS maintainers and contributors
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 or later as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+import re
+import unittest
+from base_vyostest_shim import VyOSUnitTestSHIM
+from vyos.util import read_file
+
+config_file = '/etc/frr/daemons'
+base_path = ['system', 'frr']
+
+
+def daemons_config_parse(daemons_config):
+ # create regex for parsing daemons options
+ regex_daemon_config = re.compile(
+ r'^(?P<daemon_name>\w+)_options="(?P<daemon_options>.*)"$', re.M)
+ # create empty dict for config
+ daemons_config_dict = {}
+ # fill dictionary with actual config
+ for daemon in regex_daemon_config.finditer(daemons_config):
+ daemon_name = daemon.group('daemon_name')
+ daemon_options = daemon.group('daemon_options')
+ daemons_config_dict[daemon_name] = daemon_options
+
+ # return daemons config
+ return (daemons_config_dict)
+
+
+class TestSystemFRR(VyOSUnitTestSHIM.TestCase):
+
+ def tearDown(self):
+ self.cli_delete(base_path)
+ self.cli_commit()
+
+ def test_frr_snmp_multipledaemons(self):
+ # test SNMP integration for multiple daemons
+ test_daemon_names = ['ospfd', 'bgpd']
+ for test_daemon_name in test_daemon_names:
+ self.cli_set(base_path + ['snmp', test_daemon_name])
+ self.cli_commit()
+
+ # read the config file and check content
+ daemons_config = read_file(config_file)
+ daemons_config_dict = daemons_config_parse(daemons_config)
+ # prepare regex for matching SNMP integration
+ regex_snmp = re.compile(r'^.* -M snmp.*$')
+ for (daemon_name, daemon_options) in daemons_config_dict.items():
+ snmp_enabled = regex_snmp.match(daemon_options)
+ if daemon_name in test_daemon_names:
+ self.assertTrue(snmp_enabled)
+ else:
+ self.assertFalse(snmp_enabled)
+
+ def test_frr_snmp_addandremove(self):
+ # test enabling and disabling of SNMP integration
+ test_daemon_names = ['ospfd', 'bgpd']
+ for test_daemon_name in test_daemon_names:
+ self.cli_set(base_path + ['snmp', test_daemon_name])
+ self.cli_commit()
+
+ self.cli_delete(base_path)
+ self.cli_commit()
+
+ # read the config file and check content
+ daemons_config = read_file(config_file)
+ daemons_config_dict = daemons_config_parse(daemons_config)
+ # prepare regex for matching SNMP integration
+ regex_snmp = re.compile(r'^.* -M snmp.*$')
+ for test_daemon_name in test_daemon_names:
+ snmp_enabled = regex_snmp.match(
+ daemons_config_dict[test_daemon_name])
+ self.assertFalse(snmp_enabled)
+
+ def test_frr_snmp_empty(self):
+ # test empty config section
+ self.cli_set(base_path + ['snmp'])
+ self.cli_commit()
+
+ # read the config file and check content
+ daemons_config = read_file(config_file)
+ daemons_config_dict = daemons_config_parse(daemons_config)
+ # prepare regex for matching SNMP integration
+ regex_snmp = re.compile(r'^.* -M snmp.*$')
+ for daemon_options in daemons_config_dict.values():
+ snmp_enabled = regex_snmp.match(daemon_options)
+ self.assertFalse(snmp_enabled)
+
+ def test_frr_bmp(self):
+ # test BMP
+ self.cli_set(base_path + ['bmp'])
+ self.cli_commit()
+
+ # read the config file and check content
+ daemons_config = read_file(config_file)
+ daemons_config_dict = daemons_config_parse(daemons_config)
+ # prepare regex
+ regex_bmp = re.compile(r'^.* -M bmp.*$')
+ bmp_enabled = regex_bmp.match(daemons_config_dict['bgpd'])
+ self.assertTrue(bmp_enabled)
+
+ def test_frr_irdp(self):
+ # test IRDP
+ self.cli_set(base_path + ['irdp'])
+ self.cli_commit()
+
+ # read the config file and check content
+ daemons_config = read_file(config_file)
+ daemons_config_dict = daemons_config_parse(daemons_config)
+ # prepare regex
+ regex_irdp = re.compile(r'^.* -M irdp.*$')
+ irdp_enabled = regex_irdp.match(daemons_config_dict['zebra'])
+ self.assertTrue(irdp_enabled)
+
+ def test_frr_bmpandsnmp(self):
+ # test empty config section
+ self.cli_set(base_path + ['bmp'])
+ self.cli_set(base_path + ['snmp', 'bgpd'])
+ self.cli_commit()
+
+ # read the config file and check content
+ daemons_config = read_file(config_file)
+ daemons_config_dict = daemons_config_parse(daemons_config)
+ # prepare regex
+ regex_snmp = re.compile(r'^.* -M bmp.*$')
+ regex_snmp = re.compile(r'^.* -M snmp.*$')
+ bmp_enabled = regex_snmp.match(daemons_config_dict['bgpd'])
+ snmp_enabled = regex_snmp.match(daemons_config_dict['bgpd'])
+ self.assertTrue(bmp_enabled)
+ self.assertTrue(snmp_enabled)
+
+
+if __name__ == '__main__':
+ unittest.main(verbosity=2, failfast=True)
diff --git a/smoketest/scripts/cli/test_system_ip.py b/smoketest/scripts/cli/test_system_ip.py
index 83df9d99e..f71ef5b3f 100755
--- a/smoketest/scripts/cli/test_system_ip.py
+++ b/smoketest/scripts/cli/test_system_ip.py
@@ -28,7 +28,7 @@ class TestSystemIP(VyOSUnitTestSHIM.TestCase):
def test_system_ip_forwarding(self):
# Test if IPv4 forwarding can be disabled globally, default is '1'
- # which means forwearding enabled
+ # which means forwarding enabled
all_forwarding = '/proc/sys/net/ipv4/conf/all/forwarding'
self.assertEqual(read_file(all_forwarding), '1')
@@ -37,6 +37,17 @@ class TestSystemIP(VyOSUnitTestSHIM.TestCase):
self.assertEqual(read_file(all_forwarding), '0')
+ def test_system_ip_directed_broadcast_forwarding(self):
+ # Test if IPv4 directed broadcast forwarding can be disabled globally,
+ # default is '1' which means forwarding enabled
+ bc_forwarding = '/proc/sys/net/ipv4/conf/all/bc_forwarding'
+ self.assertEqual(read_file(bc_forwarding), '1')
+
+ self.cli_set(base_path + ['disable-directed-broadcast'])
+ self.cli_commit()
+
+ self.assertEqual(read_file(bc_forwarding), '0')
+
def test_system_ip_multipath(self):
# Test IPv4 multipathing options, options default to off -> '0'
use_neigh = '/proc/sys/net/ipv4/fib_multipath_use_neigh'
diff --git a/smoketest/scripts/cli/test_system_ntp.py b/smoketest/scripts/cli/test_system_ntp.py
index e2821687c..a0806acf0 100755
--- a/smoketest/scripts/cli/test_system_ntp.py
+++ b/smoketest/scripts/cli/test_system_ntp.py
@@ -108,5 +108,22 @@ class TestSystemNTP(VyOSUnitTestSHIM.TestCase):
for listen in listen_address:
self.assertIn(f'interface listen {listen}', config)
+ def test_03_ntp_interface(self):
+ interfaces = ['eth0', 'eth1']
+ for interface in interfaces:
+ self.cli_set(base_path + ['interface', interface])
+
+ servers = ['time1.vyos.net', 'time2.vyos.net']
+ for server in servers:
+ self.cli_set(base_path + ['server', server])
+
+ self.cli_commit()
+
+ # Check generated client address configuration
+ config = read_file(NTP_CONF)
+ self.assertIn('interface ignore wildcard', config)
+ for interface in interfaces:
+ self.assertIn(f'interface listen {interface}', config)
+
if __name__ == '__main__':
unittest.main(verbosity=2)
diff --git a/smoketest/scripts/cli/test_vpn_sstp.py b/smoketest/scripts/cli/test_vpn_sstp.py
index 24673278b..f58920b5b 100755
--- a/smoketest/scripts/cli/test_vpn_sstp.py
+++ b/smoketest/scripts/cli/test_vpn_sstp.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
#
-# Copyright (C) 2020 VyOS maintainers and contributors
+# Copyright (C) 2020-2022 VyOS maintainers and contributors
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or later as
@@ -17,7 +17,8 @@
import unittest
from base_accel_ppp_test import BasicAccelPPPTest
-from vyos.util import cmd
+from vyos.util import read_file
+
pki_path = ['pki']
cert_data = 'MIICFDCCAbugAwIBAgIUfMbIsB/ozMXijYgUYG80T1ry+mcwCgYIKoZIzj0EAwIwWTELMAkGA1UEBhMCR0IxEzARBgNVBAgMClNvbWUtU3RhdGUxEjAQBgNVBAcMCVNvbWUtQ2l0eTENMAsGA1UECgwEVnlPUzESMBAGA1UEAwwJVnlPUyBUZXN0MB4XDTIxMDcyMDEyNDUxMloXDTI2MDcxOTEyNDUxMlowWTELMAkGA1UEBhMCR0IxEzARBgNVBAgMClNvbWUtU3RhdGUxEjAQBgNVBAcMCVNvbWUtQ2l0eTENMAsGA1UECgwEVnlPUzESMBAGA1UEAwwJVnlPUyBUZXN0MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE01HrLcNttqq4/PtoMua8rMWEkOdBu7vP94xzDO7A8C92ls1v86eePy4QllKCzIw3QxBIoCuH2peGRfWgPRdFsKNhMF8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMBMB0GA1UdDgQWBBSu+JnU5ZC4mkuEpqg2+Mk4K79oeDAKBggqhkjOPQQDAgNHADBEAiBEFdzQ/Bc3LftzngrY605UhA6UprHhAogKgROv7iR4QgIgEFUxTtW3xXJcnUPWhhUFhyZoqfn8dE93+dm/LDnp7C0='
@@ -40,6 +41,7 @@ class TestVPNSSTPServer(BasicAccelPPPTest.TestCase):
self.cli_set(pki_path + ['ca', 'sstp', 'certificate', cert_data])
self.cli_set(pki_path + ['certificate', 'sstp', 'certificate', cert_data])
self.cli_set(pki_path + ['certificate', 'sstp', 'private', 'key', key_data])
+
# SSL is mandatory
self.set(['ssl', 'ca-certificate', 'sstp'])
self.set(['ssl', 'certificate', 'sstp'])
@@ -47,5 +49,15 @@ class TestVPNSSTPServer(BasicAccelPPPTest.TestCase):
super().basic_config()
+ def test_accel_local_authentication(self):
+ # Change default port
+ port = '8443'
+ self.set(['port', port])
+
+ super().test_accel_local_authentication()
+
+ config = read_file(self._config_file)
+ self.assertIn(f'port={port}', config)
+
if __name__ == '__main__':
unittest.main(verbosity=2)
diff --git a/smoketest/scripts/cli/test_vrf.py b/smoketest/scripts/cli/test_vrf.py
index ff18f7261..176c095fb 100755
--- a/smoketest/scripts/cli/test_vrf.py
+++ b/smoketest/scripts/cli/test_vrf.py
@@ -127,6 +127,9 @@ class VRFTest(VyOSUnitTestSHIM.TestCase):
for vrf in vrfs:
# Ensure VRF was created
self.assertIn(vrf, interfaces())
+ # Verify IP forwarding is 1 (enabled)
+ self.assertEqual(read_file(f'/proc/sys/net/ipv4/conf/{vrf}/forwarding'), '1')
+ self.assertEqual(read_file(f'/proc/sys/net/ipv6/conf/{vrf}/forwarding'), '1')
# Test for proper loopback IP assignment
for addr in loopbacks:
self.assertTrue(is_intf_addr_assigned(vrf, addr))
@@ -267,5 +270,26 @@ class VRFTest(VyOSUnitTestSHIM.TestCase):
self.cli_delete(['interfaces', 'dummy', interface])
self.cli_commit()
+ def test_vrf_disable_forwarding(self):
+ table = '2000'
+ for vrf in vrfs:
+ base = base_path + ['name', vrf]
+ self.cli_set(base + ['table', table])
+ self.cli_set(base + ['ip', 'disable-forwarding'])
+ self.cli_set(base + ['ipv6', 'disable-forwarding'])
+ table = str(int(table) + 1)
+
+ # commit changes
+ self.cli_commit()
+
+ # Verify VRF configuration
+ loopbacks = ['127.0.0.1', '::1']
+ for vrf in vrfs:
+ # Ensure VRF was created
+ self.assertIn(vrf, interfaces())
+ # Verify IP forwarding is 0 (disabled)
+ self.assertEqual(read_file(f'/proc/sys/net/ipv4/conf/{vrf}/forwarding'), '0')
+ self.assertEqual(read_file(f'/proc/sys/net/ipv6/conf/{vrf}/forwarding'), '0')
+
if __name__ == '__main__':
unittest.main(verbosity=2)