diff options
22 files changed, 297 insertions, 111 deletions
diff --git a/data/templates/firewall/nftables-offload.j2 b/data/templates/firewall/nftables-offload.j2 index 6afcd79f7..a893e05b2 100644 --- a/data/templates/firewall/nftables-offload.j2 +++ b/data/templates/firewall/nftables-offload.j2 @@ -1,11 +1,9 @@ -{% macro render_flowtable(name, devices, priority='filter', hardware_offload=false, with_counter=true) %} -flowtable {{ name }} { - hook ingress priority {{ priority }}; devices = { {{ devices | join(', ') }} }; -{% if hardware_offload %} - flags offload; +{% macro flowtable(name, config) %} + flowtable VYOS_FLOWTABLE_{{ name }} { + hook ingress priority 0; devices = { {{ config.interface | join(', ') }} }; +{% if config.offload is vyos_defined('hardware') %} + flags offload; {% endif %} -{% if with_counter %} - counter -{% endif %} -} + counter + } {% endmacro %} diff --git a/data/templates/firewall/nftables.j2 b/data/templates/firewall/nftables.j2 index 1564b3ef8..75800ee3d 100644 --- a/data/templates/firewall/nftables.j2 +++ b/data/templates/firewall/nftables.j2 @@ -2,7 +2,7 @@ {% import 'firewall/nftables-defines.j2' as group_tmpl %} {% import 'firewall/nftables-bridge.j2' as bridge_tmpl %} -{% import 'firewall/nftables-offload.j2' as offload %} +{% import 'firewall/nftables-offload.j2' as offload_tmpl %} flush chain raw vyos_global_rpfilter flush chain ip6 raw vyos_global_rpfilter @@ -34,6 +34,12 @@ delete table ip vyos_filter {% endif %} table ip vyos_filter { {% if ipv4 is vyos_defined %} +{% if flowtable is vyos_defined %} +{% for name, flowtable_conf in flowtable.items() %} +{{ offload_tmpl.flowtable(name, flowtable_conf) }} +{% endfor %} +{% endif %} + {% set ns = namespace(sets=[]) %} {% if ipv4.forward is vyos_defined %} {% for prior, conf in ipv4.forward.items() %} @@ -153,6 +159,12 @@ delete table ip6 vyos_filter {% endif %} table ip6 vyos_filter { {% if ipv6 is vyos_defined %} +{% if flowtable is vyos_defined %} +{% for name, flowtable_conf in flowtable.items() %} +{{ offload_tmpl.flowtable(name, flowtable_conf) }} +{% endfor %} +{% endif %} + {% set ns = namespace(sets=[]) %} {% if ipv6.forward is vyos_defined %} {% for prior, conf in ipv6.forward.items() %} @@ -255,29 +267,7 @@ table ip6 vyos_filter { {% if first_install is not vyos_defined %} delete table bridge vyos_filter {% endif %} -{% if bridge is vyos_defined %} table bridge vyos_filter { {{ bridge_tmpl.bridge(bridge) }} {{ group_tmpl.groups(group, False, False) }} } -{% endif %} - -{% if first_install is not vyos_defined %} -delete table inet vyos_offload -{% endif %} -table inet vyos_offload { -{% if global_options.flow_offload.hardware.interface is vyos_defined %} - {{- offload.render_flowtable('VYOS_FLOWTABLE_hardware', global_options.flow_offload.hardware.interface | list, priority='filter - 2', hardware_offload=true) }} - chain VYOS_OFFLOAD_hardware { - type filter hook forward priority filter - 2; policy accept; - ct state { established, related } meta l4proto { tcp, udp } flow add @VYOS_FLOWTABLE_hardware - } -{% endif %} -{% if global_options.flow_offload.software.interface is vyos_defined %} - {{- offload.render_flowtable('VYOS_FLOWTABLE_software', global_options.flow_offload.software.interface | list, priority='filter - 1') }} - chain VYOS_OFFLOAD_software { - type filter hook forward priority filter - 1; policy accept; - ct state { established, related } meta l4proto { tcp, udp } flow add @VYOS_FLOWTABLE_software - } -{% endif %} -} diff --git a/data/templates/frr/bgpd.frr.j2 b/data/templates/frr/bgpd.frr.j2 index e1c102e16..d724dbd79 100644 --- a/data/templates/frr/bgpd.frr.j2 +++ b/data/templates/frr/bgpd.frr.j2 @@ -29,13 +29,14 @@ neighbor {{ neighbor }} bfd profile {{ config.bfd.profile }} {% endif %} {% endif %} -{% if config.capability is vyos_defined %} -{% if config.capability.dynamic is vyos_defined %} +{% if config.capability.dynamic is vyos_defined %} neighbor {{ neighbor }} capability dynamic -{% endif %} -{% if config.capability.extended_nexthop is vyos_defined %} +{% endif %} +{% if config.capability.extended_nexthop is vyos_defined %} neighbor {{ neighbor }} capability extended-nexthop -{% endif %} +{% endif %} +{% if config.capability.software_version is vyos_defined %} + neighbor {{ neighbor }} capability software-version {% endif %} {% if config.description is vyos_defined %} neighbor {{ neighbor }} description {{ config.description }} @@ -77,6 +78,9 @@ {% if config.path_attribute.discard is vyos_defined %} neighbor {{ neighbor }} path-attribute discard {{ config.path_attribute.discard }} {% endif %} +{% if config.path_attribute.treat_as_withdraw is vyos_defined %} + neighbor {{ neighbor }} path-attribute treat-as-withdraw {{ config.path_attribute.treat_as_withdraw }} +{% endif %} {% if config.port is vyos_defined %} neighbor {{ neighbor }} port {{ config.port }} {% endif %} diff --git a/data/templates/frr/isisd.frr.j2 b/data/templates/frr/isisd.frr.j2 index 3c37e28b9..dbb8c7305 100644 --- a/data/templates/frr/isisd.frr.j2 +++ b/data/templates/frr/isisd.frr.j2 @@ -58,6 +58,12 @@ exit ! router isis VyOS {{ 'vrf ' + vrf if vrf is vyos_defined }} net {{ net }} +{% if advertise_high_metrics is vyos_defined %} +advertise-high-metrics +{% endif %} +{% if advertise_passive_only is vyos_defined %} +advertise-passive-only +{% endif %} {% if dynamic_hostname is vyos_defined %} hostname dynamic {% endif %} @@ -191,4 +197,4 @@ router isis VyOS {{ 'vrf ' + vrf if vrf is vyos_defined }} is-type {{ level }} {% endif %} exit -!
\ No newline at end of file +! diff --git a/interface-definitions/firewall.xml.in b/interface-definitions/firewall.xml.in index 8e462f3eb..81e6b89ea 100644 --- a/interface-definitions/firewall.xml.in +++ b/interface-definitions/firewall.xml.in @@ -7,6 +7,46 @@ </properties> <children> #include <include/firewall/global-options.xml.i> + <tagNode name="flowtable"> + <properties> + <help>Flowtable</help> + <constraint> + <regex>[a-zA-Z0-9][\w\-\.]*</regex> + </constraint> + </properties> + <children> + #include <include/generic-description.xml.i> + <leafNode name="interface"> + <properties> + <help>Interfaces to use this flowtable</help> + <completionHelp> + <script>${vyos_completion_dir}/list_interfaces</script> + </completionHelp> + <multi/> + </properties> + </leafNode> + <leafNode name="offload"> + <properties> + <help>Offloading method</help> + <completionHelp> + <list>hardware software</list> + </completionHelp> + <valueHelp> + <format>hardware</format> + <description>Hardware offload</description> + </valueHelp> + <valueHelp> + <format>software</format> + <description>Software offload</description> + </valueHelp> + <constraint> + <regex>(hardware|software)</regex> + </constraint> + </properties> + <defaultValue>software</defaultValue> + </leafNode> + </children> + </tagNode> <node name="group"> <properties> <help>Firewall group</help> diff --git a/interface-definitions/include/bgp/neighbor-capability.xml.i b/interface-definitions/include/bgp/neighbor-capability.xml.i index 2bbfadf1f..c5ed3c840 100644 --- a/interface-definitions/include/bgp/neighbor-capability.xml.i +++ b/interface-definitions/include/bgp/neighbor-capability.xml.i @@ -16,6 +16,12 @@ <valueless/> </properties> </leafNode> + <leafNode name="software-version"> + <properties> + <help>Advertise Software Version capability to the peer</help> + <valueless/> + </properties> + </leafNode> </children> </node> <!-- include end --> diff --git a/interface-definitions/include/bgp/neighbor-path-attribute.xml.i b/interface-definitions/include/bgp/neighbor-path-attribute.xml.i index f4f2fcfa9..30568d8c6 100644 --- a/interface-definitions/include/bgp/neighbor-path-attribute.xml.i +++ b/interface-definitions/include/bgp/neighbor-path-attribute.xml.i @@ -16,6 +16,18 @@ </constraint> </properties> </leafNode> + <leafNode name="treat-as-withdraw"> + <properties> + <help>Treat-as-withdraw any incoming BGP UPDATE messages that contain the specified attribute</help> + <valueHelp> + <format>u32:1-255</format> + <description>Attribute number</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 1-255"/> + </constraint> + </properties> + </leafNode> </children> </node> <!-- include end --> diff --git a/interface-definitions/include/firewall/action-forward.xml.i b/interface-definitions/include/firewall/action-forward.xml.i new file mode 100644 index 000000000..f61e51887 --- /dev/null +++ b/interface-definitions/include/firewall/action-forward.xml.i @@ -0,0 +1,45 @@ +<!-- include start from firewall/action-forward.xml.i --> +<leafNode name="action"> + <properties> + <help>Rule action</help> + <completionHelp> + <list>accept continue jump reject return drop queue offload</list> + </completionHelp> + <valueHelp> + <format>accept</format> + <description>Accept matching entries</description> + </valueHelp> + <valueHelp> + <format>continue</format> + <description>Continue parsing next rule</description> + </valueHelp> + <valueHelp> + <format>jump</format> + <description>Jump to another chain</description> + </valueHelp> + <valueHelp> + <format>reject</format> + <description>Reject matching entries</description> + </valueHelp> + <valueHelp> + <format>return</format> + <description>Return from the current chain and continue at the next rule of the last chain</description> + </valueHelp> + <valueHelp> + <format>drop</format> + <description>Drop matching entries</description> + </valueHelp> + <valueHelp> + <format>queue</format> + <description>Enqueue packet to userspace</description> + </valueHelp> + <valueHelp> + <format>offload</format> + <description>Offload packet via flowtable</description> + </valueHelp> + <constraint> + <regex>(accept|continue|jump|reject|return|drop|queue|offload)</regex> + </constraint> + </properties> +</leafNode> +<!-- include end --> diff --git a/interface-definitions/include/firewall/flow-offload.xml.i b/interface-definitions/include/firewall/flow-offload.xml.i deleted file mode 100644 index 706836362..000000000 --- a/interface-definitions/include/firewall/flow-offload.xml.i +++ /dev/null @@ -1,47 +0,0 @@ -<!-- include start from firewall/flow-offload.xml.i --> -<node name="flow-offload"> - <properties> - <help>Configurable flow offload options</help> - </properties> - <children> - <leafNode name="disable"> - <properties> - <help>Disable flow offload</help> - <valueless/> - </properties> - </leafNode> - <node name="software"> - <properties> - <help>Software offload</help> - </properties> - <children> - <leafNode name="interface"> - <properties> - <help>Interfaces to enable</help> - <completionHelp> - <script>${vyos_completion_dir}/list_interfaces</script> - </completionHelp> - <multi/> - </properties> - </leafNode> - </children> - </node> - <node name="hardware"> - <properties> - <help>Hardware offload</help> - </properties> - <children> - <leafNode name="interface"> - <properties> - <help>Interfaces to enable</help> - <completionHelp> - <script>${vyos_completion_dir}/list_interfaces</script> - </completionHelp> - <multi/> - </properties> - </leafNode> - </children> - </node> - </children> -</node> -<!-- include end --> diff --git a/interface-definitions/include/firewall/global-options.xml.i b/interface-definitions/include/firewall/global-options.xml.i index 03c07e657..e655cd6ac 100644 --- a/interface-definitions/include/firewall/global-options.xml.i +++ b/interface-definitions/include/firewall/global-options.xml.i @@ -271,7 +271,6 @@ </properties> <defaultValue>disable</defaultValue> </leafNode> - #include <include/firewall/flow-offload.xml.i> </children> </node> <!-- include end --> diff --git a/interface-definitions/include/firewall/ipv4-hook-forward.xml.i b/interface-definitions/include/firewall/ipv4-hook-forward.xml.i index 08ee96419..70c0adb77 100644 --- a/interface-definitions/include/firewall/ipv4-hook-forward.xml.i +++ b/interface-definitions/include/firewall/ipv4-hook-forward.xml.i @@ -24,8 +24,10 @@ <constraintErrorMessage>Firewall rule number must be between 1 and 999999</constraintErrorMessage> </properties> <children> + #include <include/firewall/action-forward.xml.i> #include <include/firewall/common-rule-ipv4.xml.i> #include <include/firewall/inbound-interface.xml.i> + #include <include/firewall/offload-target.xml.i> #include <include/firewall/outbound-interface.xml.i> </children> </tagNode> diff --git a/interface-definitions/include/firewall/ipv6-hook-forward.xml.i b/interface-definitions/include/firewall/ipv6-hook-forward.xml.i index 20ab8dbe8..d83827161 100644 --- a/interface-definitions/include/firewall/ipv6-hook-forward.xml.i +++ b/interface-definitions/include/firewall/ipv6-hook-forward.xml.i @@ -24,8 +24,10 @@ <constraintErrorMessage>Firewall rule number must be between 1 and 999999</constraintErrorMessage> </properties> <children> + #include <include/firewall/action-forward.xml.i> #include <include/firewall/common-rule-ipv6.xml.i> #include <include/firewall/inbound-interface.xml.i> + #include <include/firewall/offload-target.xml.i> #include <include/firewall/outbound-interface.xml.i> </children> </tagNode> diff --git a/interface-definitions/include/firewall/offload-target.xml.i b/interface-definitions/include/firewall/offload-target.xml.i new file mode 100644 index 000000000..940ed8091 --- /dev/null +++ b/interface-definitions/include/firewall/offload-target.xml.i @@ -0,0 +1,10 @@ +<!-- include start from firewall/offload-target.xml.i --> +<leafNode name="offload-target"> + <properties> + <help>Set flowtable offload target. Action offload must be defined to use this setting</help> + <completionHelp> + <path>firewall flowtable</path> + </completionHelp> + </properties> +</leafNode> +<!-- include end --> diff --git a/interface-definitions/include/isis/protocol-common-config.xml.i b/interface-definitions/include/isis/protocol-common-config.xml.i index 4ca7061db..648f2b319 100644 --- a/interface-definitions/include/isis/protocol-common-config.xml.i +++ b/interface-definitions/include/isis/protocol-common-config.xml.i @@ -1,4 +1,16 @@ <!-- include start from isis/protocol-common-config.xml.i --> +<leafNode name="advertise-high-metrics"> + <properties> + <help>Advertise high metric value on all interfaces</help> + <valueless/> + </properties> +</leafNode> +<leafNode name="advertise-passive-only"> + <properties> + <help>Advertise prefixes of passive interfaces only</help> + <valueless/> + </properties> +</leafNode> <node name="area-password"> <properties> <help>Configure the authentication password for an area</help> diff --git a/interface-definitions/interfaces-ethernet.xml.in b/interface-definitions/interfaces-ethernet.xml.in index 3669336fd..5aaa7095c 100644 --- a/interface-definitions/interfaces-ethernet.xml.in +++ b/interface-definitions/interfaces-ethernet.xml.in @@ -80,6 +80,12 @@ <valueless/> </properties> </leafNode> + <leafNode name="hw-tc-offload"> + <properties> + <help>Enable Hardware Flow Offload</help> + <valueless/> + </properties> + </leafNode> <leafNode name="lro"> <properties> <help>Enable Large Receive Offload</help> diff --git a/python/vyos/ethtool.py b/python/vyos/ethtool.py index ca3bcfc3d..f19632719 100644 --- a/python/vyos/ethtool.py +++ b/python/vyos/ethtool.py @@ -172,6 +172,9 @@ class Ethtool: def get_generic_segmentation_offload(self): return self._get_generic('generic-segmentation-offload') + def get_hw_tc_offload(self): + return self._get_generic('hw-tc-offload') + def get_large_receive_offload(self): return self._get_generic('large-receive-offload') diff --git a/python/vyos/firewall.py b/python/vyos/firewall.py index 69ad11d1d..3ca7a25b9 100644 --- a/python/vyos/firewall.py +++ b/python/vyos/firewall.py @@ -401,20 +401,24 @@ def parse_rule(rule_conf, hook, fw_name, rule_id, ip_name): if 'action' in rule_conf: # Change action=return to action=action # #output.append(nft_action(rule_conf['action'])) - output.append(f'{rule_conf["action"]}') - if 'jump' in rule_conf['action']: - target = rule_conf['jump_target'] - output.append(f'NAME{def_suffix}_{target}') + if rule_conf['action'] == 'offload': + offload_target = rule_conf['offload_target'] + output.append(f'flow add @VYOS_FLOWTABLE_{offload_target}') + else: + output.append(f'{rule_conf["action"]}') - if 'queue' in rule_conf['action']: - if 'queue' in rule_conf: - target = rule_conf['queue'] - output.append(f'num {target}') + if 'jump' in rule_conf['action']: + target = rule_conf['jump_target'] + output.append(f'NAME{def_suffix}_{target}') - if 'queue_options' in rule_conf: - queue_opts = ','.join(rule_conf['queue_options']) - output.append(f'{queue_opts}') + if 'queue' in rule_conf['action']: + if 'queue' in rule_conf: + target = rule_conf['queue'] + output.append(f'num {target}') + if 'queue_options' in rule_conf: + queue_opts = ','.join(rule_conf['queue_options']) + output.append(f'{queue_opts}') else: output.append('return') diff --git a/python/vyos/ifconfig/ethernet.py b/python/vyos/ifconfig/ethernet.py index 24ce3a803..285542057 100644 --- a/python/vyos/ifconfig/ethernet.py +++ b/python/vyos/ifconfig/ethernet.py @@ -57,6 +57,10 @@ class EthernetIf(Interface): 'validate': lambda v: assert_list(v, ['on', 'off']), 'possible': lambda i, v: EthernetIf.feature(i, 'gso', v), }, + 'hw-tc-offload': { + 'validate': lambda v: assert_list(v, ['on', 'off']), + 'possible': lambda i, v: EthernetIf.feature(i, 'hw-tc-offload', v), + }, 'lro': { 'validate': lambda v: assert_list(v, ['on', 'off']), 'possible': lambda i, v: EthernetIf.feature(i, 'lro', v), @@ -222,6 +226,25 @@ class EthernetIf(Interface): print('Adapter does not support changing generic-segmentation-offload settings!') return False + def set_hw_tc_offload(self, state): + """ + Enable hardware TC flow offload. State can be either True or False. + Example: + >>> from vyos.ifconfig import EthernetIf + >>> i = EthernetIf('eth0') + >>> i.set_hw_tc_offload(True) + """ + if not isinstance(state, bool): + raise ValueError('Value out of range') + + enabled, fixed = self.ethtool.get_hw_tc_offload() + if enabled != state: + if not fixed: + return self.set_interface('hw-tc-offload', 'on' if state else 'off') + else: + print('Adapter does not support changing hw-tc-offload settings!') + return False + def set_lro(self, state): """ Enable Large Receive offload. State can be either True or False. @@ -358,6 +381,9 @@ class EthernetIf(Interface): # GSO (generic segmentation offload) self.set_gso(dict_search('offload.gso', config) != None) + # GSO (generic segmentation offload) + self.set_hw_tc_offload(dict_search('offload.hw-tc-offload', config) != None) + # LRO (large receive offload) self.set_lro(dict_search('offload.lro', config) != None) diff --git a/smoketest/scripts/cli/test_firewall.py b/smoketest/scripts/cli/test_firewall.py index 75d6e9bb1..72e04847a 100755 --- a/smoketest/scripts/cli/test_firewall.py +++ b/smoketest/scripts/cli/test_firewall.py @@ -603,17 +603,39 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase): with open(path, 'r') as f: self.assertNotEqual(f.read().strip(), conf['default'], msg=path) - def test_flow_offload_software(self): - self.cli_set(['firewall', 'global-options', 'flow-offload', 'software', 'interface', 'eth0']) + def test_flow_offload(self): + self.cli_set(['firewall', 'flowtable', 'smoketest', 'interface', 'eth0']) + self.cli_set(['firewall', 'flowtable', 'smoketest', 'offload', 'hardware']) + + # QEMU virtual NIC does not support hw-tc-offload + with self.assertRaises(ConfigSessionError): + self.cli_commit() + + self.cli_set(['firewall', 'flowtable', 'smoketest', 'offload', 'software']) + + self.cli_set(['firewall', 'ipv4', 'forward', 'filter', 'rule', '1', 'action', 'offload']) + self.cli_set(['firewall', 'ipv4', 'forward', 'filter', 'rule', '1', 'offload-target', 'smoketest']) + self.cli_set(['firewall', 'ipv4', 'forward', 'filter', 'rule', '1', 'protocol', 'tcp_udp']) + self.cli_set(['firewall', 'ipv4', 'forward', 'filter', 'rule', '1', 'state', 'established', 'enable']) + self.cli_set(['firewall', 'ipv4', 'forward', 'filter', 'rule', '1', 'state', 'related', 'enable']) + + self.cli_set(['firewall', 'ipv6', 'forward', 'filter', 'rule', '1', 'action', 'offload']) + self.cli_set(['firewall', 'ipv6', 'forward', 'filter', 'rule', '1', 'offload-target', 'smoketest']) + self.cli_set(['firewall', 'ipv6', 'forward', 'filter', 'rule', '1', 'protocol', 'tcp_udp']) + self.cli_set(['firewall', 'ipv6', 'forward', 'filter', 'rule', '1', 'state', 'established', 'enable']) + self.cli_set(['firewall', 'ipv6', 'forward', 'filter', 'rule', '1', 'state', 'related', 'enable']) + self.cli_commit() + nftables_search = [ - ['flowtable VYOS_FLOWTABLE_software'], - ['hook ingress priority filter - 1'], + ['flowtable VYOS_FLOWTABLE_smoketest'], + ['hook ingress priority filter'], ['devices = { eth0 }'], - ['flow add @VYOS_FLOWTABLE_software'], + ['ct state { established, related }', 'meta l4proto { tcp, udp }', 'flow add @VYOS_FLOWTABLE_smoketest'], ] - self.verify_nftables(nftables_search, 'inet vyos_offload') + self.verify_nftables(nftables_search, 'ip vyos_filter') + self.verify_nftables(nftables_search, 'ip6 vyos_filter') if __name__ == '__main__': unittest.main(verbosity=2) diff --git a/smoketest/scripts/cli/test_protocols_bgp.py b/smoketest/scripts/cli/test_protocols_bgp.py index 77952d8d9..967958cab 100755 --- a/smoketest/scripts/cli/test_protocols_bgp.py +++ b/smoketest/scripts/cli/test_protocols_bgp.py @@ -44,6 +44,7 @@ neighbor_config = { 'bfd' : '', 'cap_dynamic' : '', 'cap_ext_next' : '', + 'cap_ext_sver' : '', 'remote_as' : '100', 'adv_interv' : '400', 'passive' : '', @@ -71,6 +72,7 @@ neighbor_config = { 'pfx_list_out' : prefix_list_out, 'no_send_comm_std' : '', 'local_role' : 'rs-client', + 'p_attr_taw' : '200', }, '192.0.2.3' : { 'advertise_map' : route_map_in, @@ -87,6 +89,7 @@ neighbor_config = { 'exist_map' : route_map_out, 'cap_dynamic' : '', 'cap_ext_next' : '', + 'cap_ext_sver' : '', 'remote_as' : '123', 'adv_interv' : '400', 'passive' : '', @@ -137,6 +140,7 @@ peer_group_config = { 'remote_as' : '111', 'graceful_rst_no' : '', 'port' : '667', + 'p_attr_taw' : '126', }, 'foo-bar' : { 'advertise_map' : route_map_in, @@ -217,6 +221,8 @@ class TestProtocolsBGP(VyOSUnitTestSHIM.TestCase): self.assertIn(f' neighbor {peer} capability dynamic', frrconfig) if 'cap_ext_next' in peer_config: self.assertIn(f' neighbor {peer} capability extended-nexthop', frrconfig) + if 'cap_ext_sver' in peer_config: + self.assertIn(f' neighbor {peer} capability software-version', frrconfig) if 'description' in peer_config: self.assertIn(f' neighbor {peer} description {peer_config["description"]}', frrconfig) if 'no_cap_nego' in peer_config: @@ -264,6 +270,8 @@ class TestProtocolsBGP(VyOSUnitTestSHIM.TestCase): self.assertIn(f' neighbor {peer} addpath-tx-all-paths', frrconfig) if 'p_attr_discard' in peer_config: self.assertIn(f' neighbor {peer} path-attribute discard {peer_config["p_attr_discard"]}', frrconfig) + if 'p_attr_taw' in peer_config: + self.assertIn(f' neighbor {peer} path-attribute treat-as-withdraw {peer_config["p_attr_taw"]}', frrconfig) if 'addpath_per_as' in peer_config: self.assertIn(f' neighbor {peer} addpath-tx-bestpath-per-AS', frrconfig) if 'advertise_map' in peer_config: @@ -390,6 +398,8 @@ class TestProtocolsBGP(VyOSUnitTestSHIM.TestCase): self.cli_set(base_path + ['neighbor', peer, 'capability', 'dynamic']) if 'cap_ext_next' in peer_config: self.cli_set(base_path + ['neighbor', peer, 'capability', 'extended-nexthop']) + if 'cap_ext_sver' in peer_config: + self.cli_set(base_path + ['neighbor', peer, 'capability', 'software-version']) if 'description' in peer_config: self.cli_set(base_path + ['neighbor', peer, 'description', peer_config["description"]]) if 'no_cap_nego' in peer_config: @@ -424,6 +434,8 @@ class TestProtocolsBGP(VyOSUnitTestSHIM.TestCase): self.cli_set(base_path + ['neighbor', peer, 'update-source', peer_config["update_src"]]) if 'p_attr_discard' in peer_config: self.cli_set(base_path + ['neighbor', peer, 'path-attribute', 'discard', peer_config["p_attr_discard"]]) + if 'p_attr_taw' in peer_config: + self.cli_set(base_path + ['neighbor', peer, 'path-attribute', 'treat-as-withdraw', peer_config["p_attr_taw"]]) if 'route_map_in' in peer_config: self.cli_set(base_path + ['neighbor', peer, 'address-family', afi, 'route-map', 'import', peer_config["route_map_in"]]) if 'route_map_out' in peer_config: @@ -490,6 +502,8 @@ class TestProtocolsBGP(VyOSUnitTestSHIM.TestCase): self.cli_set(base_path + ['peer-group', peer_group, 'capability', 'dynamic']) if 'cap_ext_next' in config: self.cli_set(base_path + ['peer-group', peer_group, 'capability', 'extended-nexthop']) + if 'cap_ext_sver' in config: + self.cli_set(base_path + ['peer-group', peer_group, 'capability', 'software-version']) if 'description' in config: self.cli_set(base_path + ['peer-group', peer_group, 'description', config["description"]]) if 'no_cap_nego' in config: @@ -544,6 +558,8 @@ class TestProtocolsBGP(VyOSUnitTestSHIM.TestCase): self.cli_set(base_path + ['peer-group', peer_group, 'disable-connected-check']) if 'p_attr_discard' in config: self.cli_set(base_path + ['peer-group', peer_group, 'path-attribute', 'discard', config["p_attr_discard"]]) + if 'p_attr_taw' in config: + self.cli_set(base_path + ['peer-group', peer_group, 'path-attribute', 'treat-as-withdraw', config["p_attr_taw"]]) # Conditional advertisement if 'advertise_map' in config: diff --git a/smoketest/scripts/cli/test_protocols_isis.py b/smoketest/scripts/cli/test_protocols_isis.py index 5ab7fae14..747fb5e80 100755 --- a/smoketest/scripts/cli/test_protocols_isis.py +++ b/smoketest/scripts/cli/test_protocols_isis.py @@ -100,6 +100,8 @@ class TestProtocolsISIS(VyOSUnitTestSHIM.TestCase): self.cli_set(vrf_base + ['table', table]) self.cli_set(vrf_base + ['protocols', 'isis', 'net', net]) self.cli_set(vrf_base + ['protocols', 'isis', 'interface', vrf_iface]) + self.cli_set(vrf_base + ['protocols', 'isis', 'advertise-high-metrics']) + self.cli_set(vrf_base + ['protocols', 'isis', 'advertise-passive-only']) self.cli_set(['interfaces', 'ethernet', vrf_iface, 'vrf', vrf]) # Also set a default VRF IS-IS config @@ -115,6 +117,8 @@ class TestProtocolsISIS(VyOSUnitTestSHIM.TestCase): tmp = self.getFRRconfig(f'router isis {domain} vrf {vrf}', daemon='isisd') self.assertIn(f'router isis {domain} vrf {vrf}', tmp) self.assertIn(f' net {net}', tmp) + self.assertIn(f' advertise-high-metrics', tmp) + self.assertIn(f' advertise-passive-only', tmp) self.cli_delete(['vrf', 'name', vrf]) self.cli_delete(['interfaces', 'ethernet', vrf_iface, 'vrf']) diff --git a/src/conf_mode/firewall.py b/src/conf_mode/firewall.py index d999b2a64..3d799318e 100755 --- a/src/conf_mode/firewall.py +++ b/src/conf_mode/firewall.py @@ -27,6 +27,7 @@ from vyos.configdict import node_changed from vyos.configdiff import get_config_diff, Diff from vyos.configdep import set_dependents, call_dependents from vyos.configverify import verify_interface_exists +from vyos.ethtool import Ethtool from vyos.firewall import fqdn_config_parse from vyos.firewall import geoip_update from vyos.template import render @@ -163,6 +164,15 @@ def verify_rule(firewall, rule_conf, ipv6): if target not in dict_search_args(firewall, 'ipv6', 'name'): raise ConfigError(f'Invalid jump-target. Firewall ipv6 name {target} does not exist on the system') + if rule_conf['action'] == 'offload': + if 'offload_target' not in rule_conf: + raise ConfigError('Action set to offload, but no offload-target specified') + + offload_target = rule_conf['offload_target'] + + if not dict_search_args(firewall, 'flowtable', offload_target): + raise ConfigError(f'Invalid offload-target. Flowtable "{offload_target}" does not exist on the system') + if 'queue_options' in rule_conf: if 'queue' not in rule_conf['action']: raise ConfigError('queue-options defined, but action queue needed and it is not defined') @@ -282,7 +292,31 @@ def verify_nested_group(group_name, group, groups, seen): if 'include' in groups[g]: verify_nested_group(g, groups[g], groups, seen) +def verify_hardware_offload(ifname): + ethtool = Ethtool(ifname) + enabled, fixed = ethtool.get_hw_tc_offload() + + if not enabled and fixed: + raise ConfigError(f'Interface "{ifname}" does not support hardware offload') + + if not enabled: + raise ConfigError(f'Interface "{ifname}" requires "offload hw-tc-offload"') + def verify(firewall): + if 'flowtable' in firewall: + for flowtable, flowtable_conf in firewall['flowtable'].items(): + if 'interface' not in flowtable_conf: + raise ConfigError(f'Flowtable "{flowtable}" requires at least one interface') + + for ifname in flowtable_conf['interface']: + verify_interface_exists(ifname) + + if dict_search_args(flowtable_conf, 'offload') == 'hardware': + interfaces = flowtable_conf['interface'] + + for ifname in interfaces: + verify_hardware_offload(ifname) + if 'group' in firewall: for group_type in nested_group_types: if group_type in firewall['group']: @@ -330,14 +364,6 @@ def verify(firewall): for rule_id, rule_conf in name_conf['rule'].items(): verify_rule(firewall, rule_conf, True) - # Verify flow offload options - flow_offload = dict_search_args(firewall, 'global_options', 'flow_offload') - for offload_type in ('software', 'hardware'): - interfaces = dict_search_args(flow_offload, offload_type, 'interface') or [] - for interface in interfaces: - # nft will raise an error when adding a non-existent interface to a flowtable - verify_interface_exists(interface) - return None def generate(firewall): |