summaryrefslogtreecommitdiff
path: root/smoketest
diff options
context:
space:
mode:
Diffstat (limited to 'smoketest')
-rw-r--r--smoketest/configs/basic-qos194
-rw-r--r--smoketest/configs/dialup-router-medium-vpn24
-rw-r--r--smoketest/configs/qos-basic38
-rwxr-xr-xsmoketest/scripts/cli/test_firewall.py21
-rwxr-xr-xsmoketest/scripts/cli/test_interfaces_dummy.py1
-rwxr-xr-xsmoketest/scripts/cli/test_policy_route.py21
-rwxr-xr-xsmoketest/scripts/cli/test_protocols_ospf.py4
-rwxr-xr-xsmoketest/scripts/cli/test_qos.py547
-rwxr-xr-xsmoketest/scripts/cli/test_service_dhcp-server.py23
-rwxr-xr-xsmoketest/scripts/cli/test_service_router-advert.py39
-rwxr-xr-xsmoketest/scripts/cli/test_vpn_ipsec.py7
11 files changed, 657 insertions, 262 deletions
diff --git a/smoketest/configs/basic-qos b/smoketest/configs/basic-qos
deleted file mode 100644
index d9baa4a1f..000000000
--- a/smoketest/configs/basic-qos
+++ /dev/null
@@ -1,194 +0,0 @@
-interfaces {
- ethernet eth0 {
- address 100.64.0.1/20
- duplex auto
- smp-affinity auto
- speed auto
- }
- ethernet eth1 {
- duplex auto
- speed auto
- vif 10 {
- traffic-policy {
- in M2
- }
- }
- vif 20 {
- traffic-policy {
- out FS
- }
- }
- vif 30 {
- traffic-policy {
- out MY-HTB
- }
- }
- vif 40 {
- traffic-policy {
- out SHAPER-FOO
- }
- }
- }
-}
-system {
- config-management {
- commit-revisions 100
- }
- console {
- device ttyS0 {
- speed 115200
- }
- }
- host-name vyos
- login {
- user vyos {
- authentication {
- encrypted-password $6$O5gJRlDYQpj$MtrCV9lxMnZPMbcxlU7.FI793MImNHznxGoMFgm3Q6QP3vfKJyOSRCt3Ka/GzFQyW1yZS4NS616NLHaIPPFHc0
- plaintext-password ""
- }
- }
- }
- name-server 192.168.0.1
- syslog {
- global {
- archive {
- file 5
- size 512
- }
- facility all {
- level info
- }
- }
- }
- time-zone Europe/Berlin
-}
-traffic-policy {
- limiter M2 {
- class 10 {
- bandwidth 120mbit
- burst 15k
- match ADDRESS10 {
- ip {
- dscp CS4
- }
- }
- priority 20
- }
- default {
- bandwidth 100mbit
- burst 15k
- }
- }
- shaper FS {
- bandwidth auto
- class 10 {
- bandwidth 100%
- burst 15k
- match ADDRESS10 {
- ip {
- source {
- address 172.17.1.2/32
- }
- }
- }
- queue-type fair-queue
- set-dscp CS4
- }
- class 20 {
- bandwidth 100%
- burst 15k
- match ADDRESS20 {
- ip {
- source {
- address 172.17.1.3/32
- }
- }
- }
- queue-type fair-queue
- set-dscp CS5
- }
- class 30 {
- bandwidth 100%
- burst 15k
- match ADDRESS30 {
- ip {
- source {
- address 172.17.1.4/32
- }
- }
- }
- queue-type fair-queue
- set-dscp CS6
- }
- default {
- bandwidth 10%
- burst 15k
- ceiling 100%
- priority 7
- queue-type fair-queue
- }
- }
- shaper MY-HTB {
- bandwidth 10mbit
- class 30 {
- bandwidth 10%
- burst 15k
- ceiling 50%
- match ADDRESS30 {
- ip {
- source {
- address 10.1.1.0/24
- }
- }
- }
- priority 5
- queue-type fair-queue
- }
- class 40 {
- bandwidth 90%
- burst 15k
- ceiling 100%
- match ADDRESS40 {
- ip {
- dscp CS4
- source {
- address 10.2.1.0/24
- }
- }
- }
- priority 5
- queue-type fair-queue
- }
- class 50 {
- bandwidth 100%
- burst 15k
- match ADDRESS50 {
- ip {
- dscp CS5
- }
- }
- queue-type fair-queue
- set-dscp CS7
- }
- default {
- bandwidth 10%
- burst 15k
- ceiling 100%
- priority 7
- queue-type fair-queue
- set-dscp CS1
- }
- }
- shaper SHAPER-FOO {
- bandwidth 1000mbit
- default {
- bandwidth 100mbit
- burst 15k
- queue-type fair-queue
- set-dscp CS4
- }
- }
-}
-// Warning: Do not remove the following line.
-// vyos-config-version: "broadcast-relay@1:cluster@1:config-management@1:conntrack@3:conntrack-sync@2:dhcp-relay@2:dhcp-server@6:dhcpv6-server@1:dns-forwarding@3:firewall@5:https@2:interfaces@22:ipoe-server@1:ipsec@5:isis@1:l2tp@3:lldp@1:mdns@1:nat@5:ntp@1:pppoe-server@5:pptp@2:qos@1:quagga@8:rpki@1:salt@1:snmp@2:ssh@2:sstp@3:system@21:vrrp@2:vyos-accel-ppp@2:wanloadbalance@3:webproxy@2:zone-policy@1"
-// Release version: 1.3.2
diff --git a/smoketest/configs/dialup-router-medium-vpn b/smoketest/configs/dialup-router-medium-vpn
index 56722d222..503280017 100644
--- a/smoketest/configs/dialup-router-medium-vpn
+++ b/smoketest/configs/dialup-router-medium-vpn
@@ -68,9 +68,6 @@ interfaces {
mtu 1500
name-server auto
password password
- traffic-policy {
- out shape-17mbit
- }
user-id vyos
password vyos
}
@@ -96,9 +93,6 @@ interfaces {
}
smp-affinity auto
speed auto
- traffic-policy {
- out shape-94mbit
- }
}
loopback lo {
}
@@ -719,24 +713,6 @@ system {
}
time-zone Pacific/Auckland
}
-traffic-policy {
- shaper shape-17mbit {
- bandwidth 17mbit
- default {
- bandwidth 100%
- burst 15k
- queue-type fq-codel
- }
- }
- shaper shape-94mbit {
- bandwidth 94mbit
- default {
- bandwidth 100%
- burst 15k
- queue-type fq-codel
- }
- }
-}
/* Warning: Do not remove the following line. */
/* === vyatta-config-version: "broadcast-relay@1:cluster@1:config-management@1:conntrack-sync@1:conntrack@1:dhcp-relay@2:dhcp-server@5:dns-forwarding@1:firewall@5:ipsec@5:l2tp@1:mdns@1:nat@4:ntp@1:pptp@1:qos@1:quagga@6:snmp@1:ssh@1:system@9:vrrp@2:wanloadbalance@3:webgui@1:webproxy@1:webproxy@2:zone-policy@1" === */
/* Release version: 1.2.6 */
diff --git a/smoketest/configs/qos-basic b/smoketest/configs/qos-basic
index f94a5650d..c279cbf67 100644
--- a/smoketest/configs/qos-basic
+++ b/smoketest/configs/qos-basic
@@ -16,19 +16,14 @@ interfaces {
traffic-policy {
out MY-HTB
}
- }
- loopback lo {
- }
-}
-protocols {
- static {
- route 0.0.0.0/0 {
- next-hop 10.9.9.2 {
- }
- next-hop 10.1.1.1 {
+ vif 200 {
+ traffic-policy {
+ out foo-emulate
}
}
}
+ loopback lo {
+ }
}
system {
config-management {
@@ -84,13 +79,14 @@ traffic-policy {
class 10 {
bandwidth 100%
burst 15k
- match ADDRESS10 {
+ match ssh4 {
ip {
- dscp CS4
+ destination {
+ port 22
+ }
}
}
queue-type fair-queue
- set-dscp CS5
}
default {
bandwidth 10mbit
@@ -120,7 +116,6 @@ traffic-policy {
ceiling 100%
match ADDRESS40 {
ip {
- dscp CS4
source {
address 10.2.1.0/24
}
@@ -133,12 +128,13 @@ traffic-policy {
bandwidth 100%
burst 15k
match ADDRESS50 {
- ip {
- dscp CS5
+ ipv6 {
+ source {
+ address "2001:db8::1/64"
+ }
}
}
queue-type fair-queue
- set-dscp CS7
}
default {
bandwidth 10%
@@ -146,7 +142,6 @@ traffic-policy {
ceiling 100%
priority 7
queue-type fair-queue
- set-dscp CS1
}
}
shaper FS {
@@ -162,7 +157,6 @@ traffic-policy {
}
}
queue-type fair-queue
- set-dscp CS4
}
class 20 {
bandwidth 100%
@@ -175,7 +169,6 @@ traffic-policy {
}
}
queue-type fair-queue
- set-dscp CS5
}
class 30 {
bandwidth 100%
@@ -188,7 +181,6 @@ traffic-policy {
}
}
queue-type fair-queue
- set-dscp CS6
}
default {
bandwidth 10%
@@ -198,6 +190,10 @@ traffic-policy {
queue-type fair-queue
}
}
+ network-emulator foo-emulate {
+ bandwidth 300mbit
+ burst 20000
+ }
}
// Warning: Do not remove the following line.
// vyos-config-version: "broadcast-relay@1:cluster@1:config-management@1:conntrack@3:conntrack-sync@2:dhcp-relay@2:dhcp-server@6:dhcpv6-server@1:dns-forwarding@3:firewall@5:https@2:interfaces@22:ipoe-server@1:ipsec@5:isis@1:l2tp@3:lldp@1:mdns@1:nat@5:ntp@1:pppoe-server@5:pptp@2:qos@1:quagga@8:rpki@1:salt@1:snmp@2:ssh@2:sstp@3:system@21:vrrp@2:vyos-accel-ppp@2:wanloadbalance@3:webproxy@2:zone-policy@1"
diff --git a/smoketest/scripts/cli/test_firewall.py b/smoketest/scripts/cli/test_firewall.py
index 09b520b72..f1c18d761 100755
--- a/smoketest/scripts/cli/test_firewall.py
+++ b/smoketest/scripts/cli/test_firewall.py
@@ -124,6 +124,8 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase):
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', 'group', 'interface-group', 'smoketest_interface', 'interface', 'eth0'])
+ self.cli_set(['firewall', 'group', 'interface-group', 'smoketest_interface', 'interface', 'vtun0'])
self.cli_set(['firewall', 'name', 'smoketest', 'rule', '1', 'action', 'accept'])
self.cli_set(['firewall', 'name', 'smoketest', 'rule', '1', 'source', 'group', 'network-group', 'smoketest_network'])
@@ -134,6 +136,8 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase):
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(['firewall', 'name', 'smoketest', 'rule', '4', 'action', 'accept'])
+ self.cli_set(['firewall', 'name', 'smoketest', 'rule', '4', 'outbound-interface', 'interface-group', 'smoketest_interface'])
self.cli_set(['firewall', 'interface', 'eth0', 'in', 'name', 'smoketest'])
@@ -151,7 +155,8 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase):
['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']
+ ['ip saddr @D_smoketest_domain', 'return'],
+ ['oifname @I_smoketest_interface', 'return']
]
self.verify_nftables(nftables_search, 'ip vyos_filter')
@@ -194,6 +199,7 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase):
name = 'smoketest'
interface = 'eth0'
mss_range = '501-1460'
+ conn_mark = '555'
self.cli_set(['firewall', 'name', name, 'default-action', 'drop'])
self.cli_set(['firewall', 'name', name, 'enable-default-log'])
@@ -225,15 +231,18 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase):
self.cli_set(['firewall', 'name', name, 'rule', '5', 'protocol', 'tcp'])
self.cli_set(['firewall', 'name', name, 'rule', '5', 'tcp', 'flags', 'syn'])
self.cli_set(['firewall', 'name', name, 'rule', '5', 'tcp', 'mss', mss_range])
- self.cli_set(['firewall', 'name', name, 'rule', '5', 'inbound-interface', interface])
+ self.cli_set(['firewall', 'name', name, 'rule', '5', 'inbound-interface', 'interface-name', interface])
self.cli_set(['firewall', 'name', name, 'rule', '6', 'action', 'return'])
self.cli_set(['firewall', 'name', name, 'rule', '6', 'protocol', 'gre'])
- self.cli_set(['firewall', 'name', name, 'rule', '6', 'outbound-interface', interface])
+ self.cli_set(['firewall', 'name', name, 'rule', '6', 'outbound-interface', 'interface-name', interface])
+ self.cli_set(['firewall', 'name', name, 'rule', '6', 'connection-mark', conn_mark])
self.cli_set(['firewall', 'interface', interface, 'in', 'name', name])
self.cli_commit()
+ mark_hex = "{0:#010x}".format(int(conn_mark))
+
nftables_search = [
[f'iifname "{interface}"', f'jump NAME_{name}'],
['saddr 172.16.20.10', 'daddr 172.16.10.10', 'log prefix "[smoketest-1-A]" level debug', 'ip ttl 15', 'return'],
@@ -242,7 +251,7 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase):
['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'],
['tcp flags & syn == syn', f'tcp option maxseg size {mss_range}', f'iifname "{interface}"'],
- ['meta l4proto gre', f'oifname "{interface}"', 'return']
+ ['meta l4proto gre', f'oifname "{interface}"', f'ct mark {mark_hex}', 'return']
]
self.verify_nftables(nftables_search, 'ip vyos_filter')
@@ -340,11 +349,11 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase):
self.cli_set(['firewall', 'ipv6-name', name, 'rule', '2', 'action', 'reject'])
self.cli_set(['firewall', 'ipv6-name', name, 'rule', '2', 'protocol', 'tcp_udp'])
self.cli_set(['firewall', 'ipv6-name', name, 'rule', '2', 'destination', 'port', '8888'])
- self.cli_set(['firewall', 'ipv6-name', name, 'rule', '2', 'inbound-interface', interface])
+ self.cli_set(['firewall', 'ipv6-name', name, 'rule', '2', 'inbound-interface', 'interface-name', interface])
self.cli_set(['firewall', 'ipv6-name', name, 'rule', '3', 'action', 'return'])
self.cli_set(['firewall', 'ipv6-name', name, 'rule', '3', 'protocol', 'gre'])
- self.cli_set(['firewall', 'ipv6-name', name, 'rule', '3', 'outbound-interface', interface])
+ self.cli_set(['firewall', 'ipv6-name', name, 'rule', '3', 'outbound-interface', 'interface-name', interface])
self.cli_set(['firewall', 'interface', interface, 'in', 'ipv6-name', name])
diff --git a/smoketest/scripts/cli/test_interfaces_dummy.py b/smoketest/scripts/cli/test_interfaces_dummy.py
index d96ec2c5d..a79e4cb1b 100755
--- a/smoketest/scripts/cli/test_interfaces_dummy.py
+++ b/smoketest/scripts/cli/test_interfaces_dummy.py
@@ -21,6 +21,7 @@ from base_interfaces_test import BasicInterfaceTest
class DummyInterfaceTest(BasicInterfaceTest.TestCase):
@classmethod
def setUpClass(cls):
+ cls._test_mtu = True
cls._base_path = ['interfaces', 'dummy']
cls._interfaces = ['dum435', 'dum8677', 'dum0931', 'dum089']
# call base-classes classmethod
diff --git a/smoketest/scripts/cli/test_policy_route.py b/smoketest/scripts/cli/test_policy_route.py
index 11b3c678e..cb48a84ff 100755
--- a/smoketest/scripts/cli/test_policy_route.py
+++ b/smoketest/scripts/cli/test_policy_route.py
@@ -21,6 +21,8 @@ from base_vyostest_shim import VyOSUnitTestSHIM
from vyos.util import cmd
mark = '100'
+conn_mark = '555'
+conn_mark_set = '111'
table_mark_offset = 0x7fffffff
table_id = '101'
interface = 'eth0'
@@ -122,6 +124,25 @@ class TestPolicyRoute(VyOSUnitTestSHIM.TestCase):
self.verify_nftables(nftables_search, 'ip vyos_mangle')
+ def test_pbr_mark_connection(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', 'connection-mark', conn_mark])
+ self.cli_set(['policy', 'route', 'smoketest', 'rule', '1', 'set', 'connection-mark', conn_mark_set])
+ self.cli_set(['policy', 'route', 'smoketest', 'interface', interface])
+
+ self.cli_commit()
+
+ mark_hex = "{0:#010x}".format(int(conn_mark))
+ mark_hex_set = "{0:#010x}".format(int(conn_mark_set))
+
+ nftables_search = [
+ [f'iifname "{interface}"','jump VYOS_PBR_smoketest'],
+ ['ip daddr 172.16.10.10', 'ip saddr 172.16.20.10', 'ct mark ' + mark_hex, 'ct mark set ' + mark_hex_set],
+ ]
+
+ self.verify_nftables(nftables_search, 'ip vyos_mangle')
+
def test_pbr_table(self):
self.cli_set(['policy', 'route', 'smoketest', 'rule', '1', 'protocol', 'tcp'])
self.cli_set(['policy', 'route', 'smoketest', 'rule', '1', 'destination', 'port', '8888'])
diff --git a/smoketest/scripts/cli/test_protocols_ospf.py b/smoketest/scripts/cli/test_protocols_ospf.py
index 339713bf6..62e5f2134 100755
--- a/smoketest/scripts/cli/test_protocols_ospf.py
+++ b/smoketest/scripts/cli/test_protocols_ospf.py
@@ -272,6 +272,10 @@ class TestProtocolsOSPF(VyOSUnitTestSHIM.TestCase):
# commit changes
self.cli_commit()
+ frrconfig = self.getFRRconfig('router ospf')
+ self.assertIn(f'router ospf', frrconfig)
+ self.assertIn(f' passive-interface default', frrconfig)
+
for interface in interfaces:
config = self.getFRRconfig(f'interface {interface}')
self.assertIn(f'interface {interface}', config)
diff --git a/smoketest/scripts/cli/test_qos.py b/smoketest/scripts/cli/test_qos.py
new file mode 100755
index 000000000..0092473d6
--- /dev/null
+++ b/smoketest/scripts/cli/test_qos.py
@@ -0,0 +1,547 @@
+#!/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
+
+from json import loads
+from base_vyostest_shim import VyOSUnitTestSHIM
+
+from vyos.configsession import ConfigSessionError
+from vyos.ifconfig import Section
+from vyos.util import cmd
+
+base_path = ['qos']
+
+def get_tc_qdisc_json(interface) -> dict:
+ tmp = cmd(f'tc -detail -json qdisc show dev {interface}')
+ tmp = loads(tmp)
+ return next(iter(tmp))
+
+def get_tc_filter_json(interface, direction) -> list:
+ if direction not in ['ingress', 'egress']:
+ raise ValueError()
+ tmp = cmd(f'tc -detail -json filter show dev {interface} {direction}')
+ tmp = loads(tmp)
+ return tmp
+
+class TestQoS(VyOSUnitTestSHIM.TestCase):
+ @classmethod
+ def setUpClass(cls):
+ super(TestQoS, 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)
+
+ # We only test on physical interfaces and not VLAN (sub-)interfaces
+ cls._interfaces = []
+ if 'TEST_ETH' in os.environ:
+ tmp = os.environ['TEST_ETH'].split()
+ cls._interfaces = tmp
+ else:
+ for tmp in Section.interfaces('ethernet', vlan=False):
+ cls._interfaces.append(tmp)
+
+ def tearDown(self):
+ # delete testing SSH config
+ self.cli_delete(base_path)
+ self.cli_commit()
+
+ def test_01_cake(self):
+ bandwidth = 1000000
+ rtt = 200
+
+ for interface in self._interfaces:
+ policy_name = f'qos-policy-{interface}'
+ self.cli_set(base_path + ['interface', interface, 'egress', policy_name])
+ self.cli_set(base_path + ['policy', 'cake', policy_name, 'bandwidth', str(bandwidth)])
+ self.cli_set(base_path + ['policy', 'cake', policy_name, 'rtt', str(rtt)])
+ self.cli_set(base_path + ['policy', 'cake', policy_name, 'flow-isolation', 'dual-src-host'])
+
+ bandwidth += 1000000
+ rtt += 20
+
+ # commit changes
+ self.cli_commit()
+
+ bandwidth = 1000000
+ rtt = 200
+ for interface in self._interfaces:
+ tmp = get_tc_qdisc_json(interface)
+
+ self.assertEqual('cake', tmp['kind'])
+ # TC store rates as a 32-bit unsigned integer in bps (Bytes per second)
+ self.assertEqual(int(bandwidth *125), tmp['options']['bandwidth'])
+ # RTT internally is in us
+ self.assertEqual(int(rtt *1000), tmp['options']['rtt'])
+ self.assertEqual('dual-srchost', tmp['options']['flowmode'])
+ self.assertFalse(tmp['options']['ingress'])
+ self.assertFalse(tmp['options']['nat'])
+ self.assertTrue(tmp['options']['raw'])
+
+ bandwidth += 1000000
+ rtt += 20
+
+ def test_02_drop_tail(self):
+ queue_limit = 50
+
+ first = True
+ for interface in self._interfaces:
+ policy_name = f'qos-policy-{interface}'
+
+ if first:
+ self.cli_set(base_path + ['interface', interface, 'ingress', policy_name])
+ # verify() - selected QoS policy on interface only supports egress
+ with self.assertRaises(ConfigSessionError):
+ self.cli_commit()
+ self.cli_delete(base_path + ['interface', interface, 'ingress', policy_name])
+ first = False
+
+ self.cli_set(base_path + ['interface', interface, 'egress', policy_name])
+ self.cli_set(base_path + ['policy', 'drop-tail', policy_name, 'queue-limit', str(queue_limit)])
+
+ queue_limit += 10
+
+ # commit changes
+ self.cli_commit()
+
+ queue_limit = 50
+ for interface in self._interfaces:
+ tmp = get_tc_qdisc_json(interface)
+
+ self.assertEqual('pfifo', tmp['kind'])
+ self.assertEqual(queue_limit, tmp['options']['limit'])
+
+ queue_limit += 10
+
+ def test_03_fair_queue(self):
+ hash_interval = 10
+ queue_limit = 5
+ policy_type = 'fair-queue'
+
+ first = True
+ for interface in self._interfaces:
+ policy_name = f'qos-policy-{interface}'
+
+ if first:
+ self.cli_set(base_path + ['interface', interface, 'ingress', policy_name])
+ # verify() - selected QoS policy on interface only supports egress
+ with self.assertRaises(ConfigSessionError):
+ self.cli_commit()
+ self.cli_delete(base_path + ['interface', interface, 'ingress', policy_name])
+ first = False
+
+ self.cli_set(base_path + ['interface', interface, 'egress', policy_name])
+ self.cli_set(base_path + ['policy', policy_type, policy_name, 'hash-interval', str(hash_interval)])
+ self.cli_set(base_path + ['policy', policy_type, policy_name, 'queue-limit', str(queue_limit)])
+
+ hash_interval += 1
+ queue_limit += 1
+
+ # commit changes
+ self.cli_commit()
+
+ hash_interval = 10
+ queue_limit = 5
+ for interface in self._interfaces:
+ tmp = get_tc_qdisc_json(interface)
+
+ self.assertEqual('sfq', tmp['kind'])
+ self.assertEqual(hash_interval, tmp['options']['perturb'])
+ self.assertEqual(queue_limit, tmp['options']['limit'])
+
+ hash_interval += 1
+ queue_limit += 1
+
+ def test_04_fq_codel(self):
+ policy_type = 'fq-codel'
+ codel_quantum = 1500
+ flows = 512
+ interval = 100
+ queue_limit = 2048
+ target = 5
+
+ first = True
+ for interface in self._interfaces:
+ policy_name = f'qos-policy-{interface}'
+
+ if first:
+ self.cli_set(base_path + ['interface', interface, 'ingress', policy_name])
+ # verify() - selected QoS policy on interface only supports egress
+ with self.assertRaises(ConfigSessionError):
+ self.cli_commit()
+ self.cli_delete(base_path + ['interface', interface, 'ingress', policy_name])
+ first = False
+
+ self.cli_set(base_path + ['interface', interface, 'egress', policy_name])
+ self.cli_set(base_path + ['policy', policy_type, policy_name, 'codel-quantum', str(codel_quantum)])
+ self.cli_set(base_path + ['policy', policy_type, policy_name, 'flows', str(flows)])
+ self.cli_set(base_path + ['policy', policy_type, policy_name, 'interval', str(interval)])
+ self.cli_set(base_path + ['policy', policy_type, policy_name, 'queue-limit', str(queue_limit)])
+ self.cli_set(base_path + ['policy', policy_type, policy_name, 'target', str(target)])
+
+ codel_quantum += 10
+ flows += 2
+ interval += 10
+ queue_limit += 512
+ target += 1
+
+ # commit changes
+ self.cli_commit()
+
+ codel_quantum = 1500
+ flows = 512
+ interval = 100
+ queue_limit = 2048
+ target = 5
+ for interface in self._interfaces:
+ tmp = get_tc_qdisc_json(interface)
+
+ self.assertEqual('fq_codel', tmp['kind'])
+ self.assertEqual(codel_quantum, tmp['options']['quantum'])
+ self.assertEqual(flows, tmp['options']['flows'])
+ self.assertEqual(queue_limit, tmp['options']['limit'])
+
+ # due to internal rounding we need to substract 1 from interval and target after converting to milliseconds
+ # configuration of:
+ # tc qdisc add dev eth0 root fq_codel quantum 1500 flows 512 interval 100ms limit 2048 target 5ms noecn
+ # results in: tc -j qdisc show dev eth0
+ # [{"kind":"fq_codel","handle":"8046:","root":true,"refcnt":3,"options":{"limit":2048,"flows":512,
+ # "quantum":1500,"target":4999,"interval":99999,"memory_limit":33554432,"drop_batch":64}}]
+ self.assertAlmostEqual(tmp['options']['interval'], interval *1000, delta=1)
+ self.assertAlmostEqual(tmp['options']['target'], target *1000 -1, delta=1)
+
+ codel_quantum += 10
+ flows += 2
+ interval += 10
+ queue_limit += 512
+ target += 1
+
+ def test_05_limiter(self):
+ qos_config = {
+ '1' : {
+ 'bandwidth' : '1000000',
+ 'match4' : {
+ 'ssh' : { 'dport' : '22', },
+ },
+ },
+ '2' : {
+ 'bandwidth' : '1000000',
+ 'match6' : {
+ 'ssh' : { 'dport' : '22', },
+ },
+ },
+ }
+
+ first = True
+ for interface in self._interfaces:
+ policy_name = f'qos-policy-{interface}'
+
+ if first:
+ self.cli_set(base_path + ['interface', interface, 'egress', policy_name])
+ # verify() - selected QoS policy on interface only supports egress
+ with self.assertRaises(ConfigSessionError):
+ self.cli_commit()
+ self.cli_delete(base_path + ['interface', interface, 'egress', policy_name])
+ first = False
+
+ self.cli_set(base_path + ['interface', interface, 'ingress', policy_name])
+ # set default bandwidth parameter for all remaining connections
+ self.cli_set(base_path + ['policy', 'limiter', policy_name, 'default', 'bandwidth', '500000'])
+
+ for qos_class, qos_class_config in qos_config.items():
+ qos_class_base = base_path + ['policy', 'limiter', policy_name, 'class', qos_class]
+
+ if 'match4' in qos_class_config:
+ for match, match_config in qos_class_config['match4'].items():
+ if 'dport' in match_config:
+ self.cli_set(qos_class_base + ['match', match, 'ip', 'destination', 'port', match_config['dport']])
+
+ if 'match6' in qos_class_config:
+ for match, match_config in qos_class_config['match6'].items():
+ if 'dport' in match_config:
+ self.cli_set(qos_class_base + ['match', match, 'ipv6', 'destination', 'port', match_config['dport']])
+
+ if 'bandwidth' in qos_class_config:
+ self.cli_set(qos_class_base + ['bandwidth', qos_class_config['bandwidth']])
+
+
+ # commit changes
+ self.cli_commit()
+
+ for interface in self._interfaces:
+ for filter in get_tc_filter_json(interface, 'ingress'):
+ # bail out early if filter has no attached action
+ if 'options' not in filter or 'actions' not in filter['options']:
+ continue
+
+ for qos_class, qos_class_config in qos_config.items():
+ # Every flowid starts with ffff and we encopde the class number after the colon
+ if 'flowid' not in filter['options'] or filter['options']['flowid'] != f'ffff:{qos_class}':
+ continue
+
+ ip_hdr_offset = 20
+ if 'match6' in qos_class_config:
+ ip_hdr_offset = 40
+
+ self.assertEqual(ip_hdr_offset, filter['options']['match']['off'])
+ if 'dport' in match_config:
+ dport = int(match_config['dport'])
+ self.assertEqual(f'{dport:x}', filter['options']['match']['value'])
+
+ def test_06_network_emulator(self):
+ policy_type = 'network-emulator'
+
+ bandwidth = 1000000
+ corruption = 1
+ delay = 2
+ duplicate = 3
+ loss = 4
+ queue_limit = 5
+ reordering = 6
+
+ first = True
+ for interface in self._interfaces:
+ policy_name = f'qos-policy-{interface}'
+
+ if first:
+ self.cli_set(base_path + ['interface', interface, 'ingress', policy_name])
+ # verify() - selected QoS policy on interface only supports egress
+ with self.assertRaises(ConfigSessionError):
+ self.cli_commit()
+ self.cli_delete(base_path + ['interface', interface, 'ingress', policy_name])
+ first = False
+
+ self.cli_set(base_path + ['interface', interface, 'egress', policy_name])
+
+ self.cli_set(base_path + ['policy', policy_type, policy_name, 'bandwidth', str(bandwidth)])
+ self.cli_set(base_path + ['policy', policy_type, policy_name, 'corruption', str(corruption)])
+ self.cli_set(base_path + ['policy', policy_type, policy_name, 'delay', str(delay)])
+ self.cli_set(base_path + ['policy', policy_type, policy_name, 'duplicate', str(duplicate)])
+ self.cli_set(base_path + ['policy', policy_type, policy_name, 'loss', str(loss)])
+ self.cli_set(base_path + ['policy', policy_type, policy_name, 'queue-limit', str(queue_limit)])
+ self.cli_set(base_path + ['policy', policy_type, policy_name, 'reordering', str(reordering)])
+
+ bandwidth += 1000000
+ corruption += 1
+ delay += 1
+ duplicate +=1
+ loss += 1
+ queue_limit += 1
+ reordering += 1
+
+ # commit changes
+ self.cli_commit()
+
+ bandwidth = 1000000
+ corruption = 1
+ delay = 2
+ duplicate = 3
+ loss = 4
+ queue_limit = 5
+ reordering = 6
+ for interface in self._interfaces:
+ tmp = get_tc_qdisc_json(interface)
+ self.assertEqual('netem', tmp['kind'])
+
+ self.assertEqual(int(bandwidth *125), tmp['options']['rate']['rate'])
+ # values are in %
+ self.assertEqual(corruption/100, tmp['options']['corrupt']['corrupt'])
+ self.assertEqual(duplicate/100, tmp['options']['duplicate']['duplicate'])
+ self.assertEqual(loss/100, tmp['options']['loss-random']['loss'])
+ self.assertEqual(reordering/100, tmp['options']['reorder']['reorder'])
+ self.assertEqual(delay/1000, tmp['options']['delay']['delay'])
+
+ self.assertEqual(queue_limit, tmp['options']['limit'])
+
+ bandwidth += 1000000
+ corruption += 1
+ delay += 1
+ duplicate += 1
+ loss += 1
+ queue_limit += 1
+ reordering += 1
+
+ def test_07_priority_queue(self):
+ priorities = ['1', '2', '3', '4', '5']
+
+ first = True
+ for interface in self._interfaces:
+ policy_name = f'qos-policy-{interface}'
+
+ if first:
+ self.cli_set(base_path + ['interface', interface, 'ingress', policy_name])
+ # verify() - selected QoS policy on interface only supports egress
+ with self.assertRaises(ConfigSessionError):
+ self.cli_commit()
+ self.cli_delete(base_path + ['interface', interface, 'ingress', policy_name])
+ first = False
+
+ self.cli_set(base_path + ['interface', interface, 'egress', policy_name])
+ self.cli_set(base_path + ['policy', 'priority-queue', policy_name, 'default', 'queue-limit', '10'])
+
+ for priority in priorities:
+ prio_base = base_path + ['policy', 'priority-queue', policy_name, 'class', priority]
+ self.cli_set(prio_base + ['match', f'prio-{priority}', 'ip', 'destination', 'port', str(1000 + int(priority))])
+
+ # commit changes
+ self.cli_commit()
+
+ def test_08_random_detect(self):
+ self.skipTest('tc returns invalid JSON here - needs iproute2 fix')
+ bandwidth = 5000
+
+ first = True
+ for interface in self._interfaces:
+ policy_name = f'qos-policy-{interface}'
+
+ if first:
+ self.cli_set(base_path + ['interface', interface, 'ingress', policy_name])
+ # verify() - selected QoS policy on interface only supports egress
+ with self.assertRaises(ConfigSessionError):
+ self.cli_commit()
+ self.cli_delete(base_path + ['interface', interface, 'ingress', policy_name])
+ first = False
+
+ self.cli_set(base_path + ['interface', interface, 'egress', policy_name])
+ self.cli_set(base_path + ['policy', 'random-detect', policy_name, 'bandwidth', str(bandwidth)])
+
+ bandwidth += 1000
+
+ # commit changes
+ self.cli_commit()
+
+ bandwidth = 5000
+ for interface in self._interfaces:
+ tmp = get_tc_qdisc_json(interface)
+ import pprint
+ pprint.pprint(tmp)
+
+ def test_09_rate_control(self):
+ bandwidth = 5000
+ burst = 20
+ latency = 5
+
+ first = True
+ for interface in self._interfaces:
+ policy_name = f'qos-policy-{interface}'
+
+ if first:
+ self.cli_set(base_path + ['interface', interface, 'ingress', policy_name])
+ # verify() - selected QoS policy on interface only supports egress
+ with self.assertRaises(ConfigSessionError):
+ self.cli_commit()
+ self.cli_delete(base_path + ['interface', interface, 'ingress', policy_name])
+ first = False
+
+ self.cli_set(base_path + ['interface', interface, 'egress', policy_name])
+ self.cli_set(base_path + ['policy', 'rate-control', policy_name, 'bandwidth', str(bandwidth)])
+ self.cli_set(base_path + ['policy', 'rate-control', policy_name, 'burst', str(burst)])
+ self.cli_set(base_path + ['policy', 'rate-control', policy_name, 'latency', str(latency)])
+
+ bandwidth += 1000
+ burst += 5
+ latency += 1
+ # commit changes
+ self.cli_commit()
+
+ bandwidth = 5000
+ burst = 20
+ latency = 5
+ for interface in self._interfaces:
+ tmp = get_tc_qdisc_json(interface)
+
+ self.assertEqual('tbf', tmp['kind'])
+ self.assertEqual(0, tmp['options']['mpu'])
+ # TC store rates as a 32-bit unsigned integer in bps (Bytes per second)
+ self.assertEqual(int(bandwidth * 125), tmp['options']['rate'])
+
+ bandwidth += 1000
+ burst += 5
+ latency += 1
+
+ def test_10_round_robin(self):
+ qos_config = {
+ '1' : {
+ 'match4' : {
+ 'ssh' : { 'dport' : '22', },
+ },
+ },
+ '2' : {
+ 'match6' : {
+ 'ssh' : { 'dport' : '22', },
+ },
+ },
+ }
+
+ first = True
+ for interface in self._interfaces:
+ policy_name = f'qos-policy-{interface}'
+
+ if first:
+ self.cli_set(base_path + ['interface', interface, 'ingress', policy_name])
+ # verify() - selected QoS policy on interface only supports egress
+ with self.assertRaises(ConfigSessionError):
+ self.cli_commit()
+ self.cli_delete(base_path + ['interface', interface, 'ingress', policy_name])
+ first = False
+
+ self.cli_set(base_path + ['interface', interface, 'egress', policy_name])
+
+ for qos_class, qos_class_config in qos_config.items():
+ qos_class_base = base_path + ['policy', 'round-robin', policy_name, 'class', qos_class]
+
+ if 'match4' in qos_class_config:
+ for match, match_config in qos_class_config['match4'].items():
+ if 'dport' in match_config:
+ self.cli_set(qos_class_base + ['match', match, 'ip', 'destination', 'port', match_config['dport']])
+
+ if 'match6' in qos_class_config:
+ for match, match_config in qos_class_config['match6'].items():
+ if 'dport' in match_config:
+ self.cli_set(qos_class_base + ['match', match, 'ipv6', 'destination', 'port', match_config['dport']])
+
+
+ # commit changes
+ self.cli_commit()
+
+ for interface in self._interfaces:
+ import pprint
+ tmp = get_tc_qdisc_json(interface)
+ self.assertEqual('drr', tmp['kind'])
+
+ for filter in get_tc_filter_json(interface, 'ingress'):
+ # bail out early if filter has no attached action
+ if 'options' not in filter or 'actions' not in filter['options']:
+ continue
+
+ for qos_class, qos_class_config in qos_config.items():
+ # Every flowid starts with ffff and we encopde the class number after the colon
+ if 'flowid' not in filter['options'] or filter['options']['flowid'] != f'ffff:{qos_class}':
+ continue
+
+ ip_hdr_offset = 20
+ if 'match6' in qos_class_config:
+ ip_hdr_offset = 40
+
+ self.assertEqual(ip_hdr_offset, filter['options']['match']['off'])
+ if 'dport' in match_config:
+ dport = int(match_config['dport'])
+ self.assertEqual(f'{dport:x}', filter['options']['match']['value'])
+
+if __name__ == '__main__':
+ unittest.main(verbosity=2, failfast=True)
diff --git a/smoketest/scripts/cli/test_service_dhcp-server.py b/smoketest/scripts/cli/test_service_dhcp-server.py
index 9c9d6d9f1..64ba100a2 100755
--- a/smoketest/scripts/cli/test_service_dhcp-server.py
+++ b/smoketest/scripts/cli/test_service_dhcp-server.py
@@ -102,16 +102,17 @@ class TestServiceDHCPServer(VyOSUnitTestSHIM.TestCase):
def test_dhcp_single_pool_options(self):
shared_net_name = 'SMOKE-0815'
- range_0_start = inc_ip(subnet, 10)
- range_0_stop = inc_ip(subnet, 20)
- smtp_server = '1.2.3.4'
- time_server = '4.3.2.1'
- tftp_server = 'tftp.vyos.io'
- search_domains = ['foo.vyos.net', 'bar.vyos.net']
- bootfile_name = 'vyos'
- bootfile_server = '192.0.2.1'
- wpad = 'http://wpad.vyos.io/foo/bar'
- server_identifier = bootfile_server
+ range_0_start = inc_ip(subnet, 10)
+ range_0_stop = inc_ip(subnet, 20)
+ smtp_server = '1.2.3.4'
+ time_server = '4.3.2.1'
+ tftp_server = 'tftp.vyos.io'
+ search_domains = ['foo.vyos.net', 'bar.vyos.net']
+ bootfile_name = 'vyos'
+ bootfile_server = '192.0.2.1'
+ wpad = 'http://wpad.vyos.io/foo/bar'
+ server_identifier = bootfile_server
+ ipv6_only_preferred = '300'
pool = base_path + ['shared-network-name', shared_net_name, 'subnet', subnet]
# we use the first subnet IP address as default gateway
@@ -132,6 +133,7 @@ class TestServiceDHCPServer(VyOSUnitTestSHIM.TestCase):
self.cli_set(pool + ['server-identifier', server_identifier])
self.cli_set(pool + ['static-route', '10.0.0.0/24', 'next-hop', '192.0.2.1'])
+ self.cli_set(pool + ['ipv6-only-preferred', ipv6_only_preferred])
# check validate() - No DHCP address range or active static-mapping set
with self.assertRaises(ConfigSessionError):
@@ -169,6 +171,7 @@ class TestServiceDHCPServer(VyOSUnitTestSHIM.TestCase):
self.assertIn(f'max-lease-time 86400;', config)
self.assertIn(f'range {range_0_start} {range_0_stop};', config)
self.assertIn(f'set shared-networkname = "{shared_net_name}";', config)
+ self.assertIn(f'option rfc8925-ipv6-only-preferred {ipv6_only_preferred};', config)
# weird syntax for those static routes
self.assertIn(f'option rfc3442-static-route 24,10,0,0,192,0,2,1, 0,192,0,2,1;', config)
diff --git a/smoketest/scripts/cli/test_service_router-advert.py b/smoketest/scripts/cli/test_service_router-advert.py
index 873be7df0..0169b7934 100755
--- a/smoketest/scripts/cli/test_service_router-advert.py
+++ b/smoketest/scripts/cli/test_service_router-advert.py
@@ -37,7 +37,6 @@ def get_config_value(key):
return tmp[0].split()[0].replace(';','')
class TestServiceRADVD(VyOSUnitTestSHIM.TestCase):
-
@classmethod
def setUpClass(cls):
super(TestServiceRADVD, cls).setUpClass()
@@ -114,7 +113,6 @@ class TestServiceRADVD(VyOSUnitTestSHIM.TestCase):
tmp = get_config_value('DecrementLifetimes')
self.assertEqual(tmp, 'off')
-
def test_dns(self):
nameserver = ['2001:db8::1', '2001:db8::2']
dnssl = ['vyos.net', 'vyos.io']
@@ -150,7 +148,6 @@ class TestServiceRADVD(VyOSUnitTestSHIM.TestCase):
tmp = 'DNSSL ' + ' '.join(dnssl) + ' {'
self.assertIn(tmp, config)
-
def test_deprecate_prefix(self):
self.cli_set(base_path + ['prefix', prefix, 'valid-lifetime', 'infinity'])
self.cli_set(base_path + ['prefix', prefix, 'deprecate-prefix'])
@@ -159,13 +156,45 @@ class TestServiceRADVD(VyOSUnitTestSHIM.TestCase):
# commit changes
self.cli_commit()
- config = read_file(RADVD_CONF)
-
tmp = get_config_value('DeprecatePrefix')
self.assertEqual(tmp, 'on')
tmp = get_config_value('DecrementLifetimes')
self.assertEqual(tmp, 'on')
+ def test_route(self):
+ route = '2001:db8:1000::/64'
+
+ self.cli_set(base_path + ['prefix', prefix])
+ self.cli_set(base_path + ['route', route])
+
+ # commit changes
+ self.cli_commit()
+
+ config = read_file(RADVD_CONF)
+
+ tmp = f'route {route}' + ' {'
+ self.assertIn(tmp, config)
+
+ self.assertIn('AdvRouteLifetime 1800;', config)
+ self.assertIn('AdvRoutePreference medium;', config)
+ self.assertIn('RemoveRoute on;', config)
+
+ def test_rasrcaddress(self):
+ ra_src = ['fe80::1', 'fe80::2']
+
+ self.cli_set(base_path + ['prefix', prefix])
+ for src in ra_src:
+ self.cli_set(base_path + ['source-address', src])
+
+ # commit changes
+ self.cli_commit()
+
+ config = read_file(RADVD_CONF)
+ self.assertIn('AdvRASrcAddress {', config)
+ for src in ra_src:
+ self.assertIn(f' {src};', config)
+
+
if __name__ == '__main__':
unittest.main(verbosity=2)
diff --git a/smoketest/scripts/cli/test_vpn_ipsec.py b/smoketest/scripts/cli/test_vpn_ipsec.py
index bd242104f..46db0bbf5 100755
--- a/smoketest/scripts/cli/test_vpn_ipsec.py
+++ b/smoketest/scripts/cli/test_vpn_ipsec.py
@@ -39,6 +39,7 @@ vif = '100'
esp_group = 'MyESPGroup'
ike_group = 'MyIKEGroup'
secret = 'MYSECRETKEY'
+PROCESS_NAME = 'charon'
ca_pem = """
MIIDSzCCAjOgAwIBAgIUQHK+ZgTUYZksvXY2/MyW+Jiels4wDQYJKoZIhvcNAQEL
@@ -137,14 +138,14 @@ class TestVPNIPsec(VyOSUnitTestSHIM.TestCase):
def tearDown(self):
# Check for running process
- self.assertTrue(process_named_running('charon'))
+ self.assertTrue(process_named_running(PROCESS_NAME))
self.cli_delete(base_path)
self.cli_delete(tunnel_path)
self.cli_commit()
# Check for no longer running process
- self.assertFalse(process_named_running('charon'))
+ self.assertFalse(process_named_running(PROCESS_NAME))
def test_01_dhcp_fail_handling(self):
# Interface for dhcp-interface
@@ -166,6 +167,8 @@ class TestVPNIPsec(VyOSUnitTestSHIM.TestCase):
dhcp_waiting = read_file(dhcp_waiting_file)
self.assertIn(f'{interface}.{vif}', dhcp_waiting) # Ensure dhcp-failed interface was added for dhclient hook
+ self.cli_delete(ethernet_path + [interface, 'vif', vif, 'address'])
+
def test_02_site_to_site(self):
self.cli_set(base_path + ['ike-group', ike_group, 'key-exchange', 'ikev2'])