diff options
-rw-r--r-- | data/templates/frr/policy.frr.tmpl | 12 | ||||
-rw-r--r-- | data/templates/ipsec/swanctl/remote_access.tmpl | 3 | ||||
-rw-r--r-- | interface-definitions/policy.xml.in | 38 | ||||
-rw-r--r-- | interface-definitions/vpn_ipsec.xml.in | 20 | ||||
-rw-r--r-- | op-mode-definitions/restart-frr.xml.in | 110 | ||||
-rw-r--r-- | python/vyos/ifconfig/pppoe.py | 8 | ||||
-rwxr-xr-x | smoketest/scripts/cli/test_policy.py | 33 | ||||
-rwxr-xr-x | src/conf_mode/vpn_ipsec.py | 24 | ||||
-rwxr-xr-x | src/op_mode/restart_frr.py | 2 |
9 files changed, 186 insertions, 64 deletions
diff --git a/data/templates/frr/policy.frr.tmpl b/data/templates/frr/policy.frr.tmpl index 57ab0f363..51adc1902 100644 --- a/data/templates/frr/policy.frr.tmpl +++ b/data/templates/frr/policy.frr.tmpl @@ -165,6 +165,18 @@ route-map {{ route_map }} {{ rule_config.action }} {{ rule }} {% if rule_config.match.extcommunity is defined and rule_config.match.extcommunity is not none %} match extcommunity {{ rule_config.match.extcommunity }} {% endif %} +{% if rule_config.match.evpn is defined and rule_config.match.evpn.default_route is defined %} + match evpn default-route +{% endif %} +{% if rule_config.match.evpn is defined and rule_config.match.evpn.rd is defined and rule_config.match.evpn.rd is not none %} + match evpn rd {{ rule_config.match.evpn.rd }} +{% endif %} +{% if rule_config.match.evpn is defined and rule_config.match.evpn.route_type is defined and rule_config.match.evpn.route_type is not none %} + match evpn route-type {{ rule_config.match.evpn.route_type }} +{% endif %} +{% if rule_config.match.evpn is defined and rule_config.match.evpn.vni is defined and rule_config.match.evpn.vni is not none %} + match evpn vni {{ rule_config.match.evpn.vni }} +{% endif %} {% if rule_config.match.interface is defined and rule_config.match.interface is not none %} match interface {{ rule_config.match.interface }} {% endif %} diff --git a/data/templates/ipsec/swanctl/remote_access.tmpl b/data/templates/ipsec/swanctl/remote_access.tmpl index f906836c6..4fdc2a276 100644 --- a/data/templates/ipsec/swanctl/remote_access.tmpl +++ b/data/templates/ipsec/swanctl/remote_access.tmpl @@ -10,7 +10,7 @@ send_certreq = no rekey_time = {{ ike.lifetime }}s keyingtries = 0 -{% if rw_conf.unique is defined and rw_conf.unique is not none %} +{% if rw_conf.unique is defined and rw_conf.unique is not none %} unique = {{ rw_conf.unique }} {% endif %} {% if rw_conf.pool is defined and rw_conf.pool is not none %} @@ -39,6 +39,7 @@ rekey_time = {{ esp.lifetime }}s rand_time = 540s dpd_action = clear + inactivity = {{ rw_conf.timeout }} {% set local_prefix = rw_conf.local.prefix if rw_conf.local is defined and rw_conf.local.prefix is defined else ['0.0.0.0/0', '::/0'] %} {% set local_port = rw_conf.local.port if rw_conf.local is defined and rw_conf.local.port is defined else '' %} {% set local_suffix = '[%any/{1}]'.format(local_port) if local_port else '' %} diff --git a/interface-definitions/policy.xml.in b/interface-definitions/policy.xml.in index bf1832832..cf65daf00 100644 --- a/interface-definitions/policy.xml.in +++ b/interface-definitions/policy.xml.in @@ -551,6 +551,44 @@ </leafNode> </children> </node> + <node name="evpn"> + <properties> + <help>Ethernet Virtual Private Network</help> + </properties> + <children> + <leafNode name="default-route"> + <properties> + <help>Default EVPN type-5 route</help> + <valueless/> + </properties> + </leafNode> + #include <include/bgp/route-distinguisher.xml.i> + <leafNode name="route-type"> + <properties> + <help>Match route-type</help> + <completionHelp> + <list>macip multicast prefix</list> + </completionHelp> + <valueHelp> + <format>macip</format> + <description>mac-ip route</description> + </valueHelp> + <valueHelp> + <format>multicast</format> + <description>IMET route</description> + </valueHelp> + <valueHelp> + <format>prefix</format> + <description>Prefix route</description> + </valueHelp> + <constraint> + <regex>^(macip|multicast|prefix)$</regex> + </constraint> + </properties> + </leafNode> + #include <include/vni.xml.i> + </children> + </node> <leafNode name="extcommunity"> <properties> <help>BGP extended community to match</help> diff --git a/interface-definitions/vpn_ipsec.xml.in b/interface-definitions/vpn_ipsec.xml.in index b28c86ae6..ed4941efc 100644 --- a/interface-definitions/vpn_ipsec.xml.in +++ b/interface-definitions/vpn_ipsec.xml.in @@ -757,11 +757,15 @@ <properties> <help>Timeout to close connection if no data is transmitted</help> <valueHelp> - <format>u32:10-86400</format> + <format>u32:0</format> + <description>Disable inactivity checks</description> + </valueHelp> + <valueHelp> + <format>u32:1-86400</format> <description>Timeout in seconds (default 28800)</description> </valueHelp> <constraint> - <validator name="numeric" argument="--range 10-86400"/> + <validator name="numeric" argument="--range 0-86400"/> </constraint> </properties> <defaultValue>28800</defaultValue> @@ -771,11 +775,19 @@ <help>Pool name used for IP address assignments</help> <completionHelp> <path>vpn ipsec remote-access pool</path> - <list>dhcp</list> + <list>dhcp radius</list> </completionHelp> <valueHelp> <format>txt</format> - <description>Pool name</description> + <description>Name of predefined IP pool</description> + </valueHelp> + <valueHelp> + <format>dhcp</format> + <description>Forward requests for virtual IP addresses to a DHCP server</description> + </valueHelp> + <valueHelp> + <format>radius</format> + <description>Forward requests for virtual IP addresses to a RADIUS server</description> </valueHelp> <multi/> </properties> diff --git a/op-mode-definitions/restart-frr.xml.in b/op-mode-definitions/restart-frr.xml.in index 96ad1a650..475bd1ee8 100644 --- a/op-mode-definitions/restart-frr.xml.in +++ b/op-mode-definitions/restart-frr.xml.in @@ -2,62 +2,66 @@ <interfaceDefinition> <node name="restart"> <children> - <node name="frr"> + <leafNode name="all"> <properties> - <help>Restart FRRouting daemons</help> + <help>Restart all routing daemons</help> </properties> <command>sudo ${vyos_op_scripts_dir}/restart_frr.py --action restart</command> - <children> - <leafNode name="bfdd"> - <properties> - <help>Restart Bidirectional Forwarding Detection daemon</help> - </properties> - <command>sudo ${vyos_op_scripts_dir}/restart_frr.py --action restart --daemon bfdd</command> - </leafNode> - <leafNode name="bgpd"> - <properties> - <help>Restart Border Gateway Protocol daemon</help> - </properties> - <command>sudo ${vyos_op_scripts_dir}/restart_frr.py --action restart --daemon bgpd</command> - </leafNode> - <leafNode name="ospfd"> - <properties> - <help>Restart OSPFv2 daemon</help> - </properties> - <command>sudo ${vyos_op_scripts_dir}/restart_frr.py --action restart --daemon ospfd</command> - </leafNode> - <leafNode name="ospf6d"> - <properties> - <help>Restart OSPFv3 daemon</help> - </properties> - <command>sudo ${vyos_op_scripts_dir}/restart_frr.py --action restart --daemon ospf6d</command> - </leafNode> - <leafNode name="ripd"> - <properties> - <help>Restart Routing Information Protocol daemon</help> - </properties> - <command>sudo ${vyos_op_scripts_dir}/restart_frr.py --action restart --daemon ripd</command> - </leafNode> - <leafNode name="ripngd"> - <properties> - <help>Restart RIPng daemon</help> - </properties> - <command>sudo ${vyos_op_scripts_dir}/restart_frr.py --action restart --daemon ripngd</command> - </leafNode> - <leafNode name="staticd"> - <properties> - <help>Restart Static Route daemon</help> - </properties> - <command>sudo ${vyos_op_scripts_dir}/restart_frr.py --action restart --daemon staticd</command> - </leafNode> - <leafNode name="zebra"> - <properties> - <help>Restart IP routing manager daemon</help> - </properties> - <command>sudo ${vyos_op_scripts_dir}/restart_frr.py --action restart --daemon zebra</command> - </leafNode> - </children> - </node> + </leafNode> + <leafNode name="bfd"> + <properties> + <help>Restart Bidirectional Forwarding Detection (BFD) daemon</help> + </properties> + <command>sudo ${vyos_op_scripts_dir}/restart_frr.py --action restart --daemon bfdd</command> + </leafNode> + <leafNode name="bgp"> + <properties> + <help>Restart Border Gateway Protocol (BGP) routing daemon</help> + </properties> + <command>sudo ${vyos_op_scripts_dir}/restart_frr.py --action restart --daemon bgpd</command> + </leafNode> + <leafNode name="isis"> + <properties> + <help>Restart Intermediate System to Intermediate System (IS-IS) routing daemon</help> + </properties> + <command>sudo ${vyos_op_scripts_dir}/restart_frr.py --action restart --daemon isisd</command> + </leafNode> + <leafNode name="ospf"> + <properties> + <help>Restart Open Shortest Path First (OSPF) routing daemon</help> + </properties> + <command>sudo ${vyos_op_scripts_dir}/restart_frr.py --action restart --daemon ospfd</command> + </leafNode> + <leafNode name="ospfv3"> + <properties> + <help>Restart IPv6 Open Shortest Path First (OSPFv3) routing daemon</help> + </properties> + <command>sudo ${vyos_op_scripts_dir}/restart_frr.py --action restart --daemon ospf6d</command> + </leafNode> + <leafNode name="rip"> + <properties> + <help>Restart Routing Information Protocol (RIP) routing daemon</help> + </properties> + <command>sudo ${vyos_op_scripts_dir}/restart_frr.py --action restart --daemon ripd</command> + </leafNode> + <leafNode name="ripng"> + <properties> + <help>Restart Routing Information Protocol NG (RIPng) routing daemon</help> + </properties> + <command>sudo ${vyos_op_scripts_dir}/restart_frr.py --action restart --daemon ripngd</command> + </leafNode> + <leafNode name="static"> + <properties> + <help>Restart static routing daemon</help> + </properties> + <command>sudo ${vyos_op_scripts_dir}/restart_frr.py --action restart --daemon staticd</command> + </leafNode> + <leafNode name="zebra"> + <properties> + <help>Restart Routing Information Base (RIB) manager daemon</help> + </properties> + <command>sudo ${vyos_op_scripts_dir}/restart_frr.py --action restart --daemon zebra</command> + </leafNode> </children> </node> </interfaceDefinition> diff --git a/python/vyos/ifconfig/pppoe.py b/python/vyos/ifconfig/pppoe.py index 9153863de..1d13264bf 100644 --- a/python/vyos/ifconfig/pppoe.py +++ b/python/vyos/ifconfig/pppoe.py @@ -75,6 +75,14 @@ class PPPoEIf(Interface): interface setup code and provide a single point of entry when workin on any interface. """ + # Cache the configuration - it will be reused inside e.g. DHCP handler + # XXX: maybe pass the option via __init__ in the future and rename this + # method to apply()? + # + # We need to copy this from super().update() as we utilize self.set_dhcpv6() + # before this is done by the base class. + self._config = config + # remove old routes from an e.g. old VRF assignment vrf = '' if 'vrf_old' in config: diff --git a/smoketest/scripts/cli/test_policy.py b/smoketest/scripts/cli/test_policy.py index 485cc274a..c2288a86a 100755 --- a/smoketest/scripts/cli/test_policy.py +++ b/smoketest/scripts/cli/test_policy.py @@ -804,6 +804,19 @@ class TestPolicy(VyOSUnitTestSHIM.TestCase): }, }, }, + 'evpn-configuration' : { + 'rule' : { + '10' : { + 'action' : 'permit', + 'match' : { + 'evpn-default-route' : '', + 'evpn-rd' : '100:300', + 'evpn-route-type' : 'prefix', + 'evpn-vni' : '1234', + }, + }, + }, + }, } self.cli_set(['policy', 'access-list', access_list, 'rule', '10', 'action', 'permit']) @@ -847,6 +860,14 @@ class TestPolicy(VyOSUnitTestSHIM.TestCase): if 'community' in rule_config['match']: self.cli_set(path + ['rule', rule, 'match', 'community', 'community-list', rule_config['match']['community']]) self.cli_set(path + ['rule', rule, 'match', 'community', 'exact-match']) + if 'evpn-default-route' in rule_config['match']: + self.cli_set(path + ['rule', rule, 'match', 'evpn', 'default-route']) + if 'evpn-rd' in rule_config['match']: + self.cli_set(path + ['rule', rule, 'match', 'evpn', 'rd', rule_config['match']['evpn-rd']]) + if 'evpn-route-type' in rule_config['match']: + self.cli_set(path + ['rule', rule, 'match', 'evpn', 'route-type', rule_config['match']['evpn-route-type']]) + if 'evpn-vni' in rule_config['match']: + self.cli_set(path + ['rule', rule, 'match', 'evpn', 'vni', rule_config['match']['evpn-vni']]) if 'extcommunity' in rule_config['match']: self.cli_set(path + ['rule', rule, 'match', 'extcommunity', rule_config['match']['extcommunity']]) if 'interface' in rule_config['match']: @@ -967,6 +988,18 @@ class TestPolicy(VyOSUnitTestSHIM.TestCase): if 'community' in rule_config['match']: tmp = f'match community {rule_config["match"]["community"]} exact-match' self.assertIn(tmp, config) + if 'evpn-default-route' in rule_config['match']: + tmp = f'match evpn default-route' + self.assertIn(tmp, config) + if 'evpn-rd' in rule_config['match']: + tmp = f'match evpn rd {rule_config["match"]["evpn-rd"]}' + self.assertIn(tmp, config) + if 'evpn-route-type' in rule_config['match']: + tmp = f'match evpn route-type {rule_config["match"]["evpn-route-type"]}' + self.assertIn(tmp, config) + if 'evpn-vni' in rule_config['match']: + tmp = f'match evpn vni {rule_config["match"]["evpn-vni"]}' + self.assertIn(tmp, config) if 'extcommunity' in rule_config['match']: tmp = f'match extcommunity {rule_config["match"]["extcommunity"]}' self.assertIn(tmp, config) diff --git a/src/conf_mode/vpn_ipsec.py b/src/conf_mode/vpn_ipsec.py index d3065fc47..ff6090e22 100755 --- a/src/conf_mode/vpn_ipsec.py +++ b/src/conf_mode/vpn_ipsec.py @@ -286,20 +286,34 @@ def verify(ipsec): if 'pre_shared_secret' not in ra_conf['authentication']: raise ConfigError(f"Missing pre-shared-key on {name} remote-access config") + if 'client_mode' not in ra_conf['authentication']: + raise ConfigError('Client authentication method is required!') - if 'client_mode' in ra_conf['authentication']: - if ra_conf['authentication']['client_mode'] == 'eap-radius': - if 'radius' not in ipsec['remote_access'] or 'server' not in ipsec['remote_access']['radius'] or len(ipsec['remote_access']['radius']['server']) == 0: - raise ConfigError('RADIUS authentication requires at least one server') + if dict_search('authentication.client_mode', ra_conf) == 'eap-radius': + if dict_search('remote_access.radius.server', ipsec) == None: + raise ConfigError('RADIUS authentication requires at least one server') if 'pool' in ra_conf: + if {'dhcp', 'radius'} <= set(ra_conf['pool']): + raise ConfigError(f'Can not use both DHCP and RADIUS for address allocation '\ + f'at the same time for "{name}"!') + if 'dhcp' in ra_conf['pool'] and len(ra_conf['pool']) > 1: - raise ConfigError(f'Can not use both DHCP and a predefined address pool for "{name}"!') + raise ConfigError(f'Can not use DHCP and a predefined address pool for "{name}"!') + + if 'radius' in ra_conf['pool'] and len(ra_conf['pool']) > 1: + raise ConfigError(f'Can not use RADIUS and a predefined address pool for "{name}"!') for pool in ra_conf['pool']: if pool == 'dhcp': if dict_search('remote_access.dhcp.server', ipsec) == None: raise ConfigError('IPSec DHCP server is not configured!') + elif pool == 'radius': + if dict_search('remote_access.radius.server', ipsec) == None: + raise ConfigError('IPSec RADIUS server is not configured!') + + if dict_search('authentication.client_mode', ra_conf) != 'eap-radius': + raise ConfigError('RADIUS IP pool requires eap-radius client authentication!') elif 'pool' not in ipsec['remote_access'] or pool not in ipsec['remote_access']['pool']: raise ConfigError(f'Requested pool "{pool}" does not exist!') diff --git a/src/op_mode/restart_frr.py b/src/op_mode/restart_frr.py index d1b66b33f..0b2322478 100755 --- a/src/op_mode/restart_frr.py +++ b/src/op_mode/restart_frr.py @@ -155,7 +155,7 @@ def _check_args_daemon(daemons): # define program arguments cmd_args_parser = argparse.ArgumentParser(description='restart frr daemons') cmd_args_parser.add_argument('--action', choices=['restart'], required=True, help='action to frr daemons') -cmd_args_parser.add_argument('--daemon', choices=['bfdd', 'bgpd', 'ospfd', 'ospf6d', 'ripd', 'ripngd', 'staticd', 'zebra'], required=False, nargs='*', help='select single or multiple daemons') +cmd_args_parser.add_argument('--daemon', choices=['bfdd', 'bgpd', 'ospfd', 'ospf6d', 'isisd', 'ripd', 'ripngd', 'staticd', 'zebra'], required=False, nargs='*', help='select single or multiple daemons') # parse arguments cmd_args = cmd_args_parser.parse_args() |