From d5b58517f88358c686e6c8ea039a7a9a64d6c6ee Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Mon, 25 May 2020 21:02:35 +0200 Subject: dhcpv6-pd: pppoe: T2506: restructure CLI Rename the CLI nodes for prefix delegation from "dhcpv6-options delegate " to "dhcpv6-options prefix-delegation interface ". The change is required to add the possibility to request for specific prefix sized via the CLI. That option was not possible with the old configuration tree. --- data/templates/dhcp-client/ipv6.tmpl | 6 +- data/templates/pppoe/ip-down.script.tmpl | 2 +- data/templates/pppoe/ipv6-up.script.tmpl | 2 +- interface-definitions/include/dhcpv6-options.xml.i | 85 +++++++++++++--------- python/vyos/configdict.py | 4 +- python/vyos/ifconfig/dhcp.py | 3 +- python/vyos/ifconfig_vlan.py | 4 +- src/conf_mode/interfaces-bonding.py | 4 +- src/conf_mode/interfaces-bridge.py | 4 +- src/conf_mode/interfaces-ethernet.py | 4 +- src/conf_mode/interfaces-pppoe.py | 20 +++-- src/conf_mode/interfaces-pseudo-ethernet.py | 4 +- src/conf_mode/interfaces-wireless.py | 4 +- src/migration-scripts/interfaces/9-to-10 | 65 +++++++++++++++++ 14 files changed, 150 insertions(+), 61 deletions(-) create mode 100755 src/migration-scripts/interfaces/9-to-10 diff --git a/data/templates/dhcp-client/ipv6.tmpl b/data/templates/dhcp-client/ipv6.tmpl index 6cfe24d3e..8957516e2 100644 --- a/data/templates/dhcp-client/ipv6.tmpl +++ b/data/templates/dhcp-client/ipv6.tmpl @@ -10,7 +10,7 @@ interface {{ ifname }} { {% if not dhcpv6_temporary %} send ia-na 1; # non-temporary address {% endif %} -{% if dhcpv6_pd %} +{% if dhcpv6_pd_interfaces %} send ia-pd 2; # prefix delegation {% endif %} }; @@ -21,9 +21,9 @@ id-assoc na 1 { }; {% endif %} -{% if dhcpv6_pd %} +{% if dhcpv6_pd_interfaces %} id-assoc pd 2 { -{% for intf in dhcpv6_pd %} +{% for intf in dhcpv6_pd_interfaces %} prefix-interface {{ intf.ifname }} { {% if intf.sla_id %} sla-id {{ intf.sla_id }}; diff --git a/data/templates/pppoe/ip-down.script.tmpl b/data/templates/pppoe/ip-down.script.tmpl index fe8fd7584..c4e11b6b4 100644 --- a/data/templates/pppoe/ip-down.script.tmpl +++ b/data/templates/pppoe/ip-down.script.tmpl @@ -27,7 +27,7 @@ fi vtysh -c "conf t" ${VRF_NAME} -c "no ip route 0.0.0.0/0 {{ intf }} ${VRF_NAME}" {% endif %} -{% if dhcpv6_pd %} +{% if dhcpv6_pd_interfaces %} # Start wide dhcpv6 client systemctl stop dhcp6c@{{ intf }}.service {% endif %} diff --git a/data/templates/pppoe/ipv6-up.script.tmpl b/data/templates/pppoe/ipv6-up.script.tmpl index 90873229a..e795d5b0c 100644 --- a/data/templates/pppoe/ipv6-up.script.tmpl +++ b/data/templates/pppoe/ipv6-up.script.tmpl @@ -40,7 +40,7 @@ echo 2 > /proc/sys/net/ipv6/conf/{{ intf }}/accept_ra echo 1 > /proc/sys/net/ipv6/conf/{{ intf }}/autoconfigure {% endif %} -{% if dhcpv6_pd %} +{% if dhcpv6_pd_interfaces %} # Start wide dhcpv6 client systemctl start dhcp6c@{{ intf }}.service {% endif %} diff --git a/interface-definitions/include/dhcpv6-options.xml.i b/interface-definitions/include/dhcpv6-options.xml.i index 2c5058d2c..98a87dba2 100644 --- a/interface-definitions/include/dhcpv6-options.xml.i +++ b/interface-definitions/include/dhcpv6-options.xml.i @@ -3,52 +3,71 @@ DHCPv6 options - + - Delegate IPv6 prefix from provider to this interface - - - + DHCPv6 Prefix Delegation Options - + - Interface address identifier + Request IPv6 prefix length from peer - 0- - Used to form IPv6 interface address (default: EUI-64) - - - - - - - - - Interface site-Level aggregator (SLA) - - 0-128 - Decimal integer which fits in the length of SLA IDs + 32-64 + Length of delegated prefix - + - + - Site-Level aggregator (SLA) length - - 0-128 - Length of delegated prefix - - - - + Delegate IPv6 prefix from provider to this interface + + + - + + + + Local interface address assigned to interface + + >0 + Used to form IPv6 interface address (default: EUI-64) + + + + + + + + + Interface site-Level aggregator (SLA) + + 0-128 + Decimal integer which fits in the length of SLA IDs + + + + + + + + + Site-Level aggregator (SLA) length + + 0-128 + Length of delegated prefix + + + + + + + + - + Acquire only config parameters, no address diff --git a/python/vyos/configdict.py b/python/vyos/configdict.py index eec64e964..6afc78039 100644 --- a/python/vyos/configdict.py +++ b/python/vyos/configdict.py @@ -112,7 +112,7 @@ interface_default_data = { 'dhcp_vendor_class_id': '', 'dhcpv6_prm_only': False, 'dhcpv6_temporary': False, - 'dhcpv6_pd': [], + 'dhcpv6_pd_interfaces': [], 'disable': False, 'disable_link_detect': 1, 'ip_disable_arp_filter': 1, @@ -248,7 +248,7 @@ def intf_to_dict(conf, default): if conf.exists(['interface-id']): pd['if_id'] = conf.return_value(['interface-id']) - intf['dhcpv6_pd'].append(pd) + intf['dhcpv6_pd_interfaces'].append(pd) # re-set config level conf.set_level(current_level) diff --git a/python/vyos/ifconfig/dhcp.py b/python/vyos/ifconfig/dhcp.py index f8fdeb6a9..a8b9a2a87 100644 --- a/python/vyos/ifconfig/dhcp.py +++ b/python/vyos/ifconfig/dhcp.py @@ -86,7 +86,8 @@ class _DHCPv6 (Control): 'ifname': ifname, 'dhcpv6_prm_only': False, 'dhcpv6_temporary': False, - 'dhcpv6_pd': [], + 'dhcpv6_pd_interfaces': [], + 'dhcpv6_pd_length': '' }) self._conf_file = f'/run/dhcp6c/dhcp6c.{ifname}.conf' diff --git a/python/vyos/ifconfig_vlan.py b/python/vyos/ifconfig_vlan.py index a53136ebf..ec4d1da42 100644 --- a/python/vyos/ifconfig_vlan.py +++ b/python/vyos/ifconfig_vlan.py @@ -87,8 +87,8 @@ def apply_vlan_config(vlan, config): if config['dhcpv6_temporary']: vlan.dhcp.v6.options['dhcpv6_temporary'] = True - if config['dhcpv6_pd']: - vlan.dhcp.v6.options['dhcpv6_pd'] = config['dhcpv6_pd'] + if config['dhcpv6_pd_interfaces']: + vlan.dhcp.v6.options['dhcpv6_pd_interfaces'] = config['dhcpv6_pd_interfaces'] # update interface description used e.g. within SNMP vlan.set_alias(config['description']) diff --git a/src/conf_mode/interfaces-bonding.py b/src/conf_mode/interfaces-bonding.py index bdca9d170..b531e97fc 100755 --- a/src/conf_mode/interfaces-bonding.py +++ b/src/conf_mode/interfaces-bonding.py @@ -299,8 +299,8 @@ def apply(bond): if bond['dhcpv6_temporary']: b.dhcp.v6.options['dhcpv6_temporary'] = True - if bond['dhcpv6_pd']: - b.dhcp.v6.options['dhcpv6_pd'] = bond['dhcpv6_pd'] + if bond['dhcpv6_pd_interfaces']: + b.dhcp.v6.options['dhcpv6_pd_interfaces'] = bond['dhcpv6_pd_interfaces'] # ignore link state changes b.set_link_detect(bond['disable_link_detect']) diff --git a/src/conf_mode/interfaces-bridge.py b/src/conf_mode/interfaces-bridge.py index 3ff339f0f..865d8a999 100755 --- a/src/conf_mode/interfaces-bridge.py +++ b/src/conf_mode/interfaces-bridge.py @@ -321,8 +321,8 @@ def apply(bridge): if bridge['dhcpv6_temporary']: br.dhcp.v6.options['dhcpv6_temporary'] = True - if bridge['dhcpv6_pd']: - br.dhcp.v6.options['dhcpv6_pd'] = br['dhcpv6_pd'] + if bridge['dhcpv6_pd_interfaces']: + br.dhcp.v6.options['dhcpv6_pd_interfaces'] = br['dhcpv6_pd_interfaces'] # assign/remove VRF br.set_vrf(bridge['vrf']) diff --git a/src/conf_mode/interfaces-ethernet.py b/src/conf_mode/interfaces-ethernet.py index 0d73a30f1..8ffefc7cf 100755 --- a/src/conf_mode/interfaces-ethernet.py +++ b/src/conf_mode/interfaces-ethernet.py @@ -201,8 +201,8 @@ def apply(eth): if eth['dhcpv6_temporary']: e.dhcp.v6.options['dhcpv6_temporary'] = True - if eth['dhcpv6_pd']: - e.dhcp.v6.options['dhcpv6_pd'] = eth['dhcpv6_pd'] + if eth['dhcpv6_pd_interfaces']: + e.dhcp.v6.options['dhcpv6_pd_interfaces'] = eth['dhcpv6_pd_interfaces'] # ignore link state changes e.set_link_detect(eth['disable_link_detect']) diff --git a/src/conf_mode/interfaces-pppoe.py b/src/conf_mode/interfaces-pppoe.py index 6cde850c9..e8aeb810f 100755 --- a/src/conf_mode/interfaces-pppoe.py +++ b/src/conf_mode/interfaces-pppoe.py @@ -36,7 +36,7 @@ default_config_data = { 'deleted': False, 'description': '\0', 'disable': False, - 'dhcpv6_pd': [], + 'dhcpv6_pd_interfaces': [], 'intf': '', 'idle_timeout': '', 'ipv6_autoconf': False, @@ -137,15 +137,19 @@ def get_config(): if conf.exists('vrf'): pppoe['vrf'] = conf.return_value(['vrf']) - if conf.exists(['dhcpv6-options', 'delegate']): - for interface in conf.list_nodes(['dhcpv6-options', 'delegate']): + if conf.exists(['dhcpv6-options', 'prefix-delegation']): + dhcpv6_pd_path = base_path + [pppoe['intf'], + 'dhcpv6-options', 'prefix-delegation'] + conf.set_level(dhcpv6_pd_path) + + for interface in conf.list_nodes(['interface']): + conf.set_level(dhcpv6_pd_path + ['interface', interface]) pd = { 'ifname': interface, 'sla_id': '', 'sla_len': '', 'if_id': '' } - conf.set_level(base_path + [pppoe['intf'], 'dhcpv6-options', 'delegate', interface]) if conf.exists(['sla-id']): pd['sla_id'] = conf.return_value(['sla-id']) @@ -153,10 +157,10 @@ def get_config(): if conf.exists(['sla-len']): pd['sla_len'] = conf.return_value(['sla-len']) - if conf.exists(['interface-id']): - pd['if_id'] = conf.return_value(['interface-id']) + if conf.exists(['address']): + pd['if_id'] = conf.return_value(['address']) - pppoe['dhcpv6_pd'].append(pd) + pppoe['dhcpv6_pd_interfaces'].append(pd) return pppoe @@ -223,7 +227,7 @@ def generate(pppoe): render(script_pppoe_ipv6_up, 'pppoe/ipv6-up.script.tmpl', pppoe, trim_blocks=True, permission=0o755) - if len(pppoe['dhcpv6_pd']) > 0: + if len(pppoe['dhcpv6_pd_interfaces']) > 0: # ipv6.tmpl relies on ifname - this should be made consitent in the # future better then double key-ing the same value pppoe['ifname'] = intf diff --git a/src/conf_mode/interfaces-pseudo-ethernet.py b/src/conf_mode/interfaces-pseudo-ethernet.py index 3e036a753..c1f52d42c 100755 --- a/src/conf_mode/interfaces-pseudo-ethernet.py +++ b/src/conf_mode/interfaces-pseudo-ethernet.py @@ -171,8 +171,8 @@ def apply(peth): if peth['dhcpv6_temporary']: p.dhcp.v6.options['dhcpv6_temporary'] = True - if peth['dhcpv6_pd']: - p.dhcp.v6.options['dhcpv6_pd'] = peth['dhcpv6_pd'] + if peth['dhcpv6_pd_interfaces']: + p.dhcp.v6.options['dhcpv6_pd_interfaces'] = peth['dhcpv6_pd_interfaces'] # ignore link state changes p.set_link_detect(peth['disable_link_detect']) diff --git a/src/conf_mode/interfaces-wireless.py b/src/conf_mode/interfaces-wireless.py index 0fa20c5f4..54420acd1 100755 --- a/src/conf_mode/interfaces-wireless.py +++ b/src/conf_mode/interfaces-wireless.py @@ -591,8 +591,8 @@ def apply(wifi): if wifi['dhcpv6_temporary']: w.dhcp.v6.options['dhcpv6_temporary'] = True - if wifi['dhcpv6_pd']: - w.dhcp.v6.options['dhcpv6_pd'] = wifi['dhcpv6_pd'] + if wifi['dhcpv6_pd_interfaces']: + w.dhcp.v6.options['dhcpv6_pd_interfaces'] = wifi['dhcpv6_pd_interfaces'] # ignore link state changes w.set_link_detect(wifi['disable_link_detect']) diff --git a/src/migration-scripts/interfaces/9-to-10 b/src/migration-scripts/interfaces/9-to-10 new file mode 100755 index 000000000..ce28627b8 --- /dev/null +++ b/src/migration-scripts/interfaces/9-to-10 @@ -0,0 +1,65 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2020 VyOS maintainers and contributors +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 or later as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# - rename CLI node 'dhcpv6-options delgate' to 'dhcpv6-options prefix-delegation +# interface' +# - rename CLI node 'interface-id' for prefix-delegation to 'address' as it +# represents the local interface IPv6 address assigned by DHCPv6-PD + +from sys import exit, argv +from vyos.configtree import ConfigTree + +if __name__ == '__main__': + if (len(argv) < 1): + print("Must specify file name!") + exit(1) + + file_name = argv[1] + with open(file_name, 'r') as f: + config_file = f.read() + + config = ConfigTree(config_file) + + for intf_type in config.list_nodes(['interfaces']): + for intf in config.list_nodes(['interfaces', intf_type]): + # cache current config tree + base_path = ['interfaces', intf_type, intf, 'dhcpv6-options', + 'delegate'] + + if config.exists(base_path): + # cache new config tree + new_path = ['interfaces', intf_type, intf, 'dhcpv6-options', + 'prefix-delegation'] + if not config.exists(new_path): + config.set(new_path) + + # copy to new node + config.copy(base_path, new_path + ['interface']) + print(new_path + ['interface']) + + # rename interface-id to address + for interface in config.list_nodes(new_path + ['interface']): + config.rename(new_path + ['interface', interface, 'interface-id'], 'address') + + # delete old noe + config.delete(base_path) + + try: + with open(file_name, 'w') as f: + f.write(config.to_string()) + except OSError as e: + print("Failed to save the modified config: {}".format(e)) + exit(1) -- cgit v1.2.3