diff options
27 files changed, 270 insertions, 109 deletions
diff --git a/.github/workflows/mergifyio_backport.yml b/.github/workflows/mergifyio_backport.yml new file mode 100644 index 000000000..f1f4312c4 --- /dev/null +++ b/.github/workflows/mergifyio_backport.yml @@ -0,0 +1,22 @@ +name: Mergifyio backport + +on: [issue_comment] + +jobs: + mergifyio_backport: + if: github.repository == 'vyos/vyos-1x' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + - uses: actions-ecosystem/action-regex-match@v2 + id: regex-match + with: + text: ${{ github.event.comment.body }} + regex: '[Mm]ergifyio backport ' + + - uses: actions-ecosystem/action-add-labels@v1 + if: ${{ steps.regex-match.outputs.match != '' }} + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + labels: backport @@ -62,7 +62,6 @@ op_mode_definitions: $(op_xml_obj) rm -f $(OP_TMPL_DIR)/delete/node.def rm -f $(OP_TMPL_DIR)/generate/node.def rm -f $(OP_TMPL_DIR)/set/node.def - rm -f $(OP_TMPL_DIR)/show/tech-support/node.def # XXX: ping and traceroute must be able to recursivly call itself as the # options are provided from the script itself diff --git a/data/templates/conntrack/sysctl.conf.j2 b/data/templates/conntrack/sysctl.conf.j2 index 075402c04..3d6fc43f2 100644 --- a/data/templates/conntrack/sysctl.conf.j2 +++ b/data/templates/conntrack/sysctl.conf.j2 @@ -24,3 +24,4 @@ net.netfilter.nf_conntrack_tcp_timeout_time_wait = {{ timeout.tcp.time_wait }} net.netfilter.nf_conntrack_udp_timeout = {{ timeout.udp.other }} net.netfilter.nf_conntrack_udp_timeout_stream = {{ timeout.udp.stream }} +net.netfilter.nf_conntrack_acct = {{ '1' if flow_accounting is vyos_defined else '0' }} diff --git a/data/templates/firewall/nftables-offload.j2 b/data/templates/firewall/nftables-offload.j2 new file mode 100644 index 000000000..6afcd79f7 --- /dev/null +++ b/data/templates/firewall/nftables-offload.j2 @@ -0,0 +1,11 @@ +{% 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; +{% endif %} +{% if with_counter %} + counter +{% endif %} +} +{% endmacro %} diff --git a/data/templates/firewall/nftables.j2 b/data/templates/firewall/nftables.j2 index 87630940b..1b764c9da 100644 --- a/data/templates/firewall/nftables.j2 +++ b/data/templates/firewall/nftables.j2 @@ -2,6 +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 %} flush chain raw FW_CONNTRACK flush chain ip6 raw FW_CONNTRACK @@ -271,3 +272,26 @@ table bridge vyos_filter { {{ group_tmpl.groups(group, False, False) }} } {% endif %} +{{ group_tmpl.groups(group, True) }} +} + +table inet vyos_offload +delete table inet vyos_offload +table inet vyos_offload { +{% if flowtable_enabled %} +{% 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 %} +{% endif %} +} diff --git a/data/templates/frr/bgpd.frr.j2 b/data/templates/frr/bgpd.frr.j2 index 7fa974254..e1c102e16 100644 --- a/data/templates/frr/bgpd.frr.j2 +++ b/data/templates/frr/bgpd.frr.j2 @@ -170,7 +170,7 @@ {% endif %} {% endif %} {% if afi_config.remove_private_as is vyos_defined %} - neighbor {{ neighbor }} remove-private-AS + neighbor {{ neighbor }} remove-private-AS {{ 'all' if afi_config.remove_private_as.all is vyos_defined }} {% endif %} {% if afi_config.route_reflector_client is vyos_defined %} neighbor {{ neighbor }} route-reflector-client diff --git a/data/templates/frr/daemons.frr.tmpl b/data/templates/frr/daemons.frr.tmpl index e09c7d1d2..fe2610724 100644 --- a/data/templates/frr/daemons.frr.tmpl +++ b/data/templates/frr/daemons.frr.tmpl @@ -17,40 +17,41 @@ bfdd=yes staticd=yes vtysh_enable=yes -zebra_options=" -s 90000000 --daemon -A 127.0.0.1 +zebra_options=" --daemon -A 127.0.0.1 -s 90000000 {%- if irdp is defined %} -M irdp{% endif -%} {%- if snmp is defined and snmp.zebra is defined %} -M snmp{% endif -%} " -bgpd_options=" --daemon -A 127.0.0.1 +bgpd_options=" --daemon -A 127.0.0.1 -M rpki {%- if bmp is defined %} -M bmp{% endif -%} {%- if snmp is defined and snmp.bgpd is defined %} -M snmp{% endif -%} " -ospfd_options=" --daemon -A 127.0.0.1 +ospfd_options=" --daemon -A 127.0.0.1 {%- if snmp is defined and snmp.ospfd is defined %} -M snmp{% endif -%} " -ospf6d_options=" --daemon -A ::1 +ospf6d_options=" --daemon -A ::1 {%- if snmp is defined and snmp.ospf6d is defined %} -M snmp{% endif -%} " -ripd_options=" --daemon -A 127.0.0.1 +ripd_options=" --daemon -A 127.0.0.1 {%- if snmp is defined and snmp.ripd is defined %} -M snmp{% endif -%} " -ripngd_options=" --daemon -A ::1" -isisd_options=" --daemon -A 127.0.0.1 +ripngd_options=" --daemon -A ::1" +isisd_options=" --daemon -A 127.0.0.1 {%- if snmp is defined and snmp.isisd is defined %} -M snmp{% endif -%} " -pimd_options=" --daemon -A 127.0.0.1" -pim6d_options=" --daemon -A ::1" -ldpd_options=" --daemon -A 127.0.0.1 +pimd_options=" --daemon -A 127.0.0.1" +pim6d_options=" --daemon -A ::1" +ldpd_options=" --daemon -A 127.0.0.1 {%- if snmp is defined and snmp.ldpd is defined %} -M snmp{% endif -%} " -mgmtd_options=" --daemon -A 127.0.0.1" -nhrpd_options=" --daemon -A 127.0.0.1" +mgmtd_options=" --daemon -A 127.0.0.1" +nhrpd_options=" --daemon -A 127.0.0.1" eigrpd_options=" --daemon -A 127.0.0.1" babeld_options=" --daemon -A 127.0.0.1" sharpd_options=" --daemon -A 127.0.0.1" -pbrd_options=" --daemon -A 127.0.0.1" -staticd_options=" --daemon -A 127.0.0.1" -bfdd_options=" --daemon -A 127.0.0.1" +pbrd_options=" --daemon -A 127.0.0.1" +staticd_options=" --daemon -A 127.0.0.1" +bfdd_options=" --daemon -A 127.0.0.1" watchfrr_enable=no valgrind_enable=no + diff --git a/data/templates/openvpn/server.conf.j2 b/data/templates/openvpn/server.conf.j2 index f76fbbe79..2eb9416fe 100644 --- a/data/templates/openvpn/server.conf.j2 +++ b/data/templates/openvpn/server.conf.j2 @@ -74,7 +74,7 @@ topology {{ server.topology }} {% endif %} {% for subnet in server.subnet %} {% if subnet | is_ipv4 %} -server {{ subnet | address_from_cidr }} {{ subnet | netmask_from_cidr }} nopool +server {{ subnet | address_from_cidr }} {{ subnet | netmask_from_cidr }} {{ 'nopool' if server.client_ip_pool is vyos_defined and server.client_ip_pool.disable is not vyos_defined else '' }} {# First ip address is used as gateway. It's allows to use metrics #} {% if server.push_route is vyos_defined %} {% for route, route_config in server.push_route.items() %} @@ -85,15 +85,6 @@ push "route-ipv6 {{ route }}" {% endif %} {% endfor %} {% endif %} -{# OpenVPN assigns the first IP address to its local interface so the pool used #} -{# in net30 topology - where each client receives a /30 must start from the second subnet #} -{% if server.topology is vyos_defined('net30') %} -ifconfig-pool {{ subnet | inc_ip('4') }} {{ subnet | last_host_address | dec_ip('1') }} {{ subnet | netmask_from_cidr if device_type == 'tap' else '' }} -{% else %} -{# OpenVPN assigns the first IP address to its local interface so the pool must #} -{# start from the second address and end on the last address #} -ifconfig-pool {{ subnet | first_host_address | inc_ip('1') }} {{ subnet | last_host_address | dec_ip('1') }} {{ subnet | netmask_from_cidr if device_type == 'tun' else '' }} -{% endif %} {% elif subnet | is_ipv6 %} server-ipv6 {{ subnet }} {% endif %} diff --git a/debian/vyos-1x.preinst b/debian/vyos-1x.preinst index e355ffa84..16c118cb7 100644 --- a/debian/vyos-1x.preinst +++ b/debian/vyos-1x.preinst @@ -10,3 +10,4 @@ dpkg-divert --package vyos-1x --add --no-rename /etc/skel/.profile dpkg-divert --package vyos-1x --add --no-rename /etc/sysctl.d/80-vpp.conf dpkg-divert --package vyos-1x --add --no-rename /etc/netplug/netplugd.conf dpkg-divert --package vyos-1x --add --no-rename /etc/netplug/netplug +dpkg-divert --package vyos-1x --add --no-rename /etc/rsyslog.d/45-frr.conf diff --git a/interface-definitions/include/bgp/neighbor-afi-ipv4-ipv6-common.xml.i b/interface-definitions/include/bgp/neighbor-afi-ipv4-ipv6-common.xml.i index 75221a348..9ec513da9 100644 --- a/interface-definitions/include/bgp/neighbor-afi-ipv4-ipv6-common.xml.i +++ b/interface-definitions/include/bgp/neighbor-afi-ipv4-ipv6-common.xml.i @@ -1,4 +1,5 @@ <!-- include start from bgp/neighbor-afi-ipv4-ipv6-common.xml.i --> + <leafNode name="addpath-tx-all"> <properties> <help>Use addpath to advertise all paths to a neighbor</help> @@ -156,12 +157,19 @@ </properties> </leafNode> #include <include/bgp/afi-nexthop-self.xml.i> -<leafNode name="remove-private-as"> +<node name="remove-private-as"> <properties> <help>Remove private AS numbers from AS path in outbound route updates</help> - <valueless/> </properties> -</leafNode> + <children> + <leafNode name="all"> + <properties> + <help>Remove private AS numbers to all AS numbers in outbound route updates</help> + <valueless/> + </properties> + </leafNode> + </children> +</node> #include <include/bgp/afi-route-map.xml.i> #include <include/bgp/afi-route-reflector-client.xml.i> #include <include/bgp/afi-route-server-client.xml.i> diff --git a/interface-definitions/include/firewall/flow-offload.xml.i b/interface-definitions/include/firewall/flow-offload.xml.i new file mode 100644 index 000000000..706836362 --- /dev/null +++ b/interface-definitions/include/firewall/flow-offload.xml.i @@ -0,0 +1,47 @@ +<!-- 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 e655cd6ac..03c07e657 100644 --- a/interface-definitions/include/firewall/global-options.xml.i +++ b/interface-definitions/include/firewall/global-options.xml.i @@ -271,6 +271,7 @@ </properties> <defaultValue>disable</defaultValue> </leafNode> + #include <include/firewall/flow-offload.xml.i> </children> </node> <!-- include end --> diff --git a/interface-definitions/system-conntrack.xml.in b/interface-definitions/system-conntrack.xml.in index 3abf9bbf0..78d19090c 100644 --- a/interface-definitions/system-conntrack.xml.in +++ b/interface-definitions/system-conntrack.xml.in @@ -9,6 +9,12 @@ <priority>218</priority> </properties> <children> + <leafNode name="flow-accounting"> + <properties> + <help>Enable connection tracking flow accounting</help> + <valueless/> + </properties> + </leafNode> <leafNode name="expect-table-size"> <properties> <help>Size of connection tracking expect table</help> diff --git a/op-mode-definitions/ntp.xml.in b/op-mode-definitions/ntp.xml.in new file mode 100644 index 000000000..b8d0c43ec --- /dev/null +++ b/op-mode-definitions/ntp.xml.in @@ -0,0 +1,49 @@ +<?xml version="1.0"?> +<interfaceDefinition> + <node name="show"> + <children> + <node name="ntp"> + <properties> + <help>Show peer status of NTP daemon</help> + </properties> + <command>${vyos_op_scripts_dir}/show_ntp.sh --sourcestats</command> + <children> + <node name="system"> + <properties> + <help>Show parameters about the system clock performance</help> + </properties> + <command>${vyos_op_scripts_dir}/show_ntp.sh --tracking</command> + </node> + </children> + </node> + </children> + </node> + <node name="force"> + <children> + <node name="ntp"> + <properties> + <help>NTP (Network Time Protocol) operations</help> + </properties> + <children> + <node name="synchronization"> + <properties> + <help>Force NTP time synchronization</help> + </properties> + <children> + <tagNode name="vrf"> + <properties> + <help>Force NTP time synchronization in given VRF</help> + <completionHelp> + <path>vrf name</path> + </completionHelp> + </properties> + <command>sudo ip vrf exec $5 chronyc makestep</command> + </tagNode> + </children> + <command>sudo chronyc makestep</command> + </node> + </children> + </node> + </children> + </node> +</interfaceDefinition> diff --git a/op-mode-definitions/show-ip.xml.in b/op-mode-definitions/show-ip.xml.in index d5dbb7850..3caf1f1ea 100644 --- a/op-mode-definitions/show-ip.xml.in +++ b/op-mode-definitions/show-ip.xml.in @@ -33,6 +33,12 @@ </tagNode> </children> </node> + <leafNode name="nht"> + <properties> + <help>Show IPv4 nexthop tracking table</help> + </properties> + <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> + </leafNode> </children> </node> </children> diff --git a/op-mode-definitions/show-ntp.xml.in b/op-mode-definitions/show-ntp.xml.in deleted file mode 100644 index 0907722af..000000000 --- a/op-mode-definitions/show-ntp.xml.in +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0"?> -<interfaceDefinition> - <node name="show"> - <children> - <node name="ntp"> - <properties> - <help>Show peer status of NTP daemon</help> - </properties> - <command>${vyos_op_scripts_dir}/show_ntp.sh --sourcestats</command> - <children> - <node name="system"> - <properties> - <help>Show parameters about the system clock performance</help> - </properties> - <command>${vyos_op_scripts_dir}/show_ntp.sh --tracking</command> - </node> - </children> - </node> - </children> - </node> -</interfaceDefinition> diff --git a/op-mode-definitions/show-techsupport_report.xml.in b/op-mode-definitions/show-techsupport_report.xml.in index aa51eacd9..ef051e940 100644 --- a/op-mode-definitions/show-techsupport_report.xml.in +++ b/op-mode-definitions/show-techsupport_report.xml.in @@ -3,6 +3,9 @@ <node name="show"> <children> <node name="tech-support"> + <properties> + <help>Show tech-support report</help> + </properties> <children> <node name="report"> <properties> diff --git a/python/vyos/template.py b/python/vyos/template.py index c1b57b883..add4d3ce5 100644 --- a/python/vyos/template.py +++ b/python/vyos/template.py @@ -671,7 +671,8 @@ def conntrack_ignore_rule(rule_conf, rule_id, ipv6=False): if 'inbound_interface' in rule_conf: ifname = rule_conf['inbound_interface'] - output.append(f'iifname {ifname}') + if ifname != 'any': + output.append(f'iifname {ifname}') if 'protocol' in rule_conf: proto = rule_conf['protocol'] diff --git a/smoketest/scripts/cli/test_firewall.py b/smoketest/scripts/cli/test_firewall.py index f74ce4b72..391ef03ff 100755 --- a/smoketest/scripts/cli/test_firewall.py +++ b/smoketest/scripts/cli/test_firewall.py @@ -603,5 +603,17 @@ 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']) + self.cli_commit() + nftables_search = [ + ['flowtable VYOS_FLOWTABLE_software'], + ['hook ingress priority filter - 1'], + ['devices = { eth0 }'], + ['flow add @VYOS_FLOWTABLE_software'], + ] + self.verify_nftables(nftables_search, 'inet vyos_offload') + + if __name__ == '__main__': unittest.main(verbosity=2) diff --git a/smoketest/scripts/cli/test_nat.py b/smoketest/scripts/cli/test_nat.py index 31dfcef87..703e5ab28 100755 --- a/smoketest/scripts/cli/test_nat.py +++ b/smoketest/scripts/cli/test_nat.py @@ -155,11 +155,6 @@ class TestNAT(VyOSUnitTestSHIM.TestCase): rule = '5' self.cli_set(src_path + ['rule', rule, 'source', 'address', '192.0.2.0/24']) - # check validate() - outbound-interface must be defined - with self.assertRaises(ConfigSessionError): - self.cli_commit() - self.cli_set(src_path + ['rule', rule, 'outbound-interface', 'eth0']) - # check validate() - translation address not specified with self.assertRaises(ConfigSessionError): self.cli_commit() diff --git a/src/conf_mode/firewall.py b/src/conf_mode/firewall.py index c3b1ee015..769cc598f 100755 --- a/src/conf_mode/firewall.py +++ b/src/conf_mode/firewall.py @@ -26,7 +26,7 @@ from vyos.config import Config 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.configverify import verify_interface_exists from vyos.firewall import fqdn_config_parse from vyos.firewall import geoip_update from vyos.template import render @@ -38,6 +38,7 @@ from vyos.utils.process import process_named_running from vyos.utils.process import rc_cmd from vyos import ConfigError from vyos import airbag + airbag.enable() nat_conf_script = 'nat.py' @@ -100,7 +101,7 @@ def geoip_updated(conf, firewall): elif (path[0] == 'ipv6'): set_name = f'GEOIP_CC6_{path[1]}_{path[2]}_{path[4]}' out['ipv6_name'].append(set_name) - + updated = True if 'delete' in node_diff: @@ -140,6 +141,14 @@ def get_config(config=None): fqdn_config_parse(firewall) + firewall['flowtable_enabled'] = False + flow_offload = dict_search_args(firewall, 'global_options', 'flow_offload') + if flow_offload and 'disable' not in flow_offload: + for offload_type in ('software', 'hardware'): + if dict_search_args(flow_offload, offload_type, 'interface'): + firewall['flowtable_enabled'] = True + break + return firewall def verify_rule(firewall, rule_conf, ipv6): @@ -327,6 +336,14 @@ 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): @@ -336,13 +353,15 @@ def generate(firewall): # Determine if conntrack is needed firewall['ipv4_conntrack_action'] = 'return' firewall['ipv6_conntrack_action'] = 'return' - - for rules, path in dict_search_recursive(firewall, 'rule'): - if any(('state' in rule_conf or 'connection_status' in rule_conf) for rule_conf in rules.values()): - if path[0] == 'ipv4': - firewall['ipv4_conntrack_action'] = 'accept' - elif path[0] == 'ipv6': - firewall['ipv6_conntrack_action'] = 'accept' + if firewall['flowtable_enabled']: # Netfilter's flowtable offload requires conntrack + firewall['ipv4_conntrack_action'] = 'accept' + firewall['ipv6_conntrack_action'] = 'accept' + else: # Check if conntrack is needed by firewall rules + for proto in ('ipv4', 'ipv6'): + for rules, _ in dict_search_recursive(firewall.get(proto, {}), 'rule'): + if any(('state' in rule_conf or 'connection_status' in rule_conf) for rule_conf in rules.values()): + firewall[f'{proto}_conntrack_action'] = 'accept' + break render(nftables_conf, 'firewall/nftables.j2', firewall) return None diff --git a/src/conf_mode/interfaces-openvpn.py b/src/conf_mode/interfaces-openvpn.py index 1d0feb56f..9f4de990c 100755 --- a/src/conf_mode/interfaces-openvpn.py +++ b/src/conf_mode/interfaces-openvpn.py @@ -344,9 +344,6 @@ def verify(openvpn): if v6_subnets > 1: raise ConfigError('Cannot specify more than 1 IPv6 server subnet') - if v6_subnets > 0 and v4_subnets == 0: - raise ConfigError('IPv6 server requires an IPv4 server subnet') - for subnet in tmp: if is_ipv4(subnet): subnet = IPv4Network(subnet) @@ -388,6 +385,10 @@ def verify(openvpn): for v4PoolNet in v4PoolNets: if IPv4Address(client['ip'][0]) in v4PoolNet: print(f'Warning: Client "{client["name"]}" IP {client["ip"][0]} is in server IP pool, it is not reserved for this client.') + # configuring a client_ip_pool will set 'server ... nopool' which is currently incompatible with 'server-ipv6' (probably to be fixed upstream) + for subnet in (dict_search('server.subnet', openvpn) or []): + if is_ipv6(subnet): + raise ConfigError(f'Setting client-ip-pool is incompatible having an IPv6 server subnet.') for subnet in (dict_search('server.subnet', openvpn) or []): if is_ipv6(subnet): diff --git a/src/conf_mode/nat.py b/src/conf_mode/nat.py index 08e96f10b..e37a7011c 100755 --- a/src/conf_mode/nat.py +++ b/src/conf_mode/nat.py @@ -195,11 +195,10 @@ def verify(nat): if dict_search('source.rule', nat): for rule, config in dict_search('source.rule', nat).items(): err_msg = f'Source NAT configuration error in rule {rule}:' - if 'outbound_interface' not in config: - raise ConfigError(f'{err_msg} outbound-interface not specified') - if config['outbound_interface'] not in 'any' and config['outbound_interface'] not in interfaces(): - Warning(f'rule "{rule}" interface "{config["outbound_interface"]}" does not exist on this system') + if 'outbound_interface' in config: + if config['outbound_interface'] not in 'any' and config['outbound_interface'] not in interfaces(): + Warning(f'rule "{rule}" interface "{config["outbound_interface"]}" does not exist on this system') if not dict_search('translation.address', config) and not dict_search('translation.port', config): if 'exclude' not in config and 'backend' not in config['load_balance']: @@ -218,11 +217,9 @@ def verify(nat): for rule, config in dict_search('destination.rule', nat).items(): err_msg = f'Destination NAT configuration error in rule {rule}:' - if 'inbound_interface' not in config: - raise ConfigError(f'{err_msg}\n' \ - 'inbound-interface not specified') - elif config['inbound_interface'] not in 'any' and config['inbound_interface'] not in interfaces(): - Warning(f'rule "{rule}" interface "{config["inbound_interface"]}" does not exist on this system') + if 'inbound_interface' in config: + if config['inbound_interface'] not in 'any' and config['inbound_interface'] not in interfaces(): + Warning(f'rule "{rule}" interface "{config["inbound_interface"]}" does not exist on this system') if not dict_search('translation.address', config) and not dict_search('translation.port', config) and 'redirect' not in config['translation']: if 'exclude' not in config and 'backend' not in config['load_balance']: diff --git a/src/conf_mode/system_frr.py b/src/conf_mode/system_frr.py index fb252238a..d8224b3c3 100755 --- a/src/conf_mode/system_frr.py +++ b/src/conf_mode/system_frr.py @@ -22,17 +22,14 @@ from vyos import airbag from vyos.config import Config from vyos.logger import syslog from vyos.template import render_to_string +from vyos.utils.boot import boot_configuration_complete from vyos.utils.file import read_file from vyos.utils.file import write_file -from vyos.utils.process import run +from vyos.utils.process import call airbag.enable() # path to daemons config and config status files config_file = '/etc/frr/daemons' -vyos_status_file = '/tmp/vyos-config-status' -# path to watchfrr for FRR control -watchfrr = '/usr/lib/frr/watchfrr.sh' - def get_config(config=None): if config: @@ -45,12 +42,10 @@ def get_config(config=None): return frr_config - def verify(frr_config): # Nothing to verify here pass - def generate(frr_config): # read daemons config file daemons_config_current = read_file(config_file) @@ -62,25 +57,21 @@ def generate(frr_config): write_file(config_file, daemons_config_new) frr_config['config_file_changed'] = True - def apply(frr_config): - # check if this is initial commit during boot or intiated by CLI - # if the file exists, this must be CLI commit - commit_type_cli = Path(vyos_status_file).exists() # display warning to user - if commit_type_cli and frr_config.get('config_file_changed'): + if boot_configuration_complete() and frr_config.get('config_file_changed'): # Since FRR restart is not safe thing, better to give # control over this to users print(''' You need to reboot a router (preferred) or restart FRR to apply changes in modules settings ''') - # restart FRR automatically. DUring the initial boot this should be - # safe in most cases - if not commit_type_cli and frr_config.get('config_file_changed'): - syslog.warning('Restarting FRR to apply changes in modules') - run(f'{watchfrr} restart') + # restart FRR automatically + # During initial boot this should be safe in most cases + if not boot_configuration_complete() and frr_config.get('config_file_changed'): + syslog.warning('Restarting FRR to apply changes in modules') + call(f'systemctl restart frr.service') if __name__ == '__main__': try: diff --git a/src/etc/sysctl.d/30-vyos-router.conf b/src/etc/sysctl.d/30-vyos-router.conf index ad43390bb..fcdc1b21d 100644 --- a/src/etc/sysctl.d/30-vyos-router.conf +++ b/src/etc/sysctl.d/30-vyos-router.conf @@ -98,15 +98,6 @@ net.ipv6.route.skip_notify_on_dev_down=1 # Default value of 20 seems to interfere with larger OSPF and VRRP setups net.ipv4.igmp_max_memberships = 512 -# Increase default garbage collection thresholds -net.ipv4.neigh.default.gc_thresh1 = 1024 -net.ipv4.neigh.default.gc_thresh2 = 4096 -net.ipv4.neigh.default.gc_thresh3 = 8192 -# -net.ipv6.neigh.default.gc_thresh1 = 1024 -net.ipv6.neigh.default.gc_thresh2 = 4096 -net.ipv6.neigh.default.gc_thresh3 = 8192 - # Enable global RFS (Receive Flow Steering) configuration. RFS is inactive # until explicitly configured at the interface level net.core.rps_sock_flow_entries = 32768 @@ -114,3 +105,4 @@ net.core.rps_sock_flow_entries = 32768 # Congestion control net.core.default_qdisc=fq net.ipv4.tcp_congestion_control=bbr + diff --git a/src/init/vyos-router b/src/init/vyos-router index a5d1a31fa..9ef1fa335 100755 --- a/src/init/vyos-router +++ b/src/init/vyos-router @@ -340,16 +340,14 @@ start () nfct helper add tns inet6 tcp nft -f /usr/share/vyos/vyos-firewall-init.conf || log_failure_msg "could not initiate firewall rules" - rm -f /etc/hostname - ${vyos_conf_scripts_dir}/host_name.py || log_failure_msg "could not reset host-name" - systemctl start frr.service - # As VyOS does not execute commands that are not present in the CLI we call # the script by hand to have a single source for the login banner and MOTD ${vyos_conf_scripts_dir}/system_console.py || log_failure_msg "could not reset serial console" ${vyos_conf_scripts_dir}/system-login.py || log_failure_msg "could not reset system login" ${vyos_conf_scripts_dir}/system-login-banner.py || log_failure_msg "could not reset motd and issue files" ${vyos_conf_scripts_dir}/system-option.py || log_failure_msg "could not reset system option files" + ${vyos_conf_scripts_dir}/system-ip.py || log_failure_msg "could not reset system IPv4 options" + ${vyos_conf_scripts_dir}/system-ipv6.py || log_failure_msg "could not reset system IPv6 options" ${vyos_conf_scripts_dir}/conntrack.py || log_failure_msg "could not reset conntrack subsystem" ${vyos_conf_scripts_dir}/container.py || log_failure_msg "could not reset container subsystem" @@ -376,6 +374,13 @@ start () && chgrp ${GROUP} ${vyatta_configdir} log_action_end_msg $? + rm -f /etc/hostname + ${vyos_conf_scripts_dir}/host_name.py || log_failure_msg "could not reset host-name" + ${vyos_conf_scripts_dir}/system_frr.py || log_failure_msg "could not reset FRR config" + # If for any reason FRR was not started by system_frr.py - start it anyways. + # This is a safety net! + systemctl start frr.service + disabled bootfile || init_bootfile cleanup_post_commit_hooks diff --git a/src/systemd/vyos-router.service b/src/systemd/vyos-router.service index 6f683cebb..7a1638f11 100644 --- a/src/systemd/vyos-router.service +++ b/src/systemd/vyos-router.service @@ -1,7 +1,6 @@ [Unit] Description=VyOS Router After=systemd-journald-dev-log.socket time-sync.target local-fs.target cloud-config.service -Requires=frr.service Conflicts=shutdown.target Before=systemd-user-sessions.service |