From 98c2c5e0585e0806099a353de207f392223eff9a Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sat, 22 Aug 2020 23:15:29 +0200 Subject: dhcpv6-pd: T2677: optimize CLI interface for PD configuration The current CLI did not support multiple prefix-delegations per interface. Some ISPs only send one /64 to a client per prefix-delegation request, but they allow the customer to request multiple prefixes. The 'dhcpv6-options prefix-delegation' node has been renamed and converted to a tag node named 'dhcpv6-options pd'. The tag node specifies a PD request (>=0). In the past the user needed to know what prefix will be assigned and required to calculate the sla-len by himself. The 'sla-len' node was dropped and is now calculated in the background from the 'dhcpv6-options pd 0 length' node. It is no longer mandatory to supply the 'sla-id' node, if sla-id is not specified it is 'guessed' by counting upwards. Example configuration: ---------------------- ethernet eth1 { address dhcpv6 dhcpv6-options { pd 0 { length 56 interface eth2 { address 1 } } } } This will request a /56 assignment from the ISP and will delegate a /64 network to interface eth2. VyOS will use the interface address ::1 on the delegate interface (eth2) as its local address. --- data/templates/dhcp-client/ipv6.tmpl | 48 ++++++++++++++++++++---------------- 1 file changed, 27 insertions(+), 21 deletions(-) (limited to 'data/templates/dhcp-client/ipv6.tmpl') diff --git a/data/templates/dhcp-client/ipv6.tmpl b/data/templates/dhcp-client/ipv6.tmpl index 9673f302b..e9285d86b 100644 --- a/data/templates/dhcp-client/ipv6.tmpl +++ b/data/templates/dhcp-client/ipv6.tmpl @@ -8,37 +8,43 @@ interface {{ ifname }} { information-only; {% endif %} {% if dhcpv6_options is not defined or dhcpv6_options.temporary is not defined %} - send ia-na 1; # non-temporary address + send ia-na 0; # non-temporary address {% endif %} -{% if dhcpv6_options is defined and dhcpv6_options.prefix_delegation is defined %} - send ia-pd 2; # prefix delegation +{% if dhcpv6_options is defined and dhcpv6_options.pd is defined %} +{% for pd in dhcpv6_options.pd %} + send ia-pd {{ pd }}; # prefix delegation #{{ pd }} +{% endfor %} {% endif %} }; {% if dhcpv6_options is not defined or dhcpv6_options.temporary is not defined %} -id-assoc na 1 { - # Identity association NA +id-assoc na 0 { + # Identity association for non temporary address }; {% endif %} -{% if dhcpv6_options is defined and dhcpv6_options.prefix_delegation is defined %} -id-assoc pd 2 { -{% if dhcpv6_options.prefix_delegation.length is defined %} - prefix ::/{{ dhcpv6_options.prefix_delegation.length }} infinity; -{% endif %} -{% for interface in dhcpv6_options.prefix_delegation.interface %} +{% if dhcpv6_options is defined and dhcpv6_options.pd is defined %} +{% for pd in dhcpv6_options.pd %} +id-assoc pd {{ pd }} { +{# length got a default value #} + prefix ::/{{ dhcpv6_options.pd[pd].length }} infinity; +{% set sla_len = 64 - dhcpv6_options.pd[pd].length|int %} +{% set count = namespace(value=0) %} +{% for interface in dhcpv6_options.pd[pd].interface if dhcpv6_options.pd[pd].interface is defined %} prefix-interface {{ interface }} { -{% if dhcpv6_options.prefix_delegation.interface[interface].sla_id is defined %} - sla-id {{ dhcpv6_options.prefix_delegation.interface[interface].sla_id }}; -{% endif %} -{% if dhcpv6_options.prefix_delegation.interface[interface].sla_len is defined %} - sla-len {{ dhcpv6_options.prefix_delegation.interface[interface].sla_len }}; -{% endif %} -{% if dhcpv6_options.prefix_delegation.interface[interface].address is defined %} - ifid {{ dhcpv6_options.prefix_delegation.interface[interface].address }}; -{% endif %} + sla-len {{ sla_len }}; +{% if dhcpv6_options.pd[pd].interface[interface].sla_id is defined and dhcpv6_options.pd[pd].interface[interface].sla_id is not none %} + sla-id {{ dhcpv6_options.pd[pd].interface[interface].sla_id }}; +{% else %} + sla-id {{ count.value }}; +{% endif %} +{% if dhcpv6_options.pd[pd].interface[interface].address is defined and dhcpv6_options.pd[pd].interface[interface].address is not none %} + ifid {{ dhcpv6_options.pd[pd].interface[interface].address }}; +{% endif %} }; -{% endfor %} +{% set count.value = count.value + 1 %} +{% endfor %} }; +{% endfor %} {% endif %} -- cgit v1.2.3 From ec1cf7dd1508e4a84d99818c7e34d093242b3331 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sun, 23 Aug 2020 00:04:09 +0200 Subject: dhcpv6-pd: T2821: support dhcpv6-pd without "address dhcpv6" Currently DHCPv6-PD requires an interface address configured to dhcpv6 on the CLI. This is not required also sometimes there is either no dhcpv6 interface addressing available (PPPoE) or wanted. This limitation was artificial due to the old interface code. Change the implementation to spawn the DHCPv6 client and request a prefix even when there is no address request configured. --- data/templates/dhcp-client/ipv6.tmpl | 12 ++++++++---- python/vyos/ifconfig/interface.py | 17 +++++++++++++---- 2 files changed, 21 insertions(+), 8 deletions(-) (limited to 'data/templates/dhcp-client/ipv6.tmpl') diff --git a/data/templates/dhcp-client/ipv6.tmpl b/data/templates/dhcp-client/ipv6.tmpl index e9285d86b..85841fe94 100644 --- a/data/templates/dhcp-client/ipv6.tmpl +++ b/data/templates/dhcp-client/ipv6.tmpl @@ -2,13 +2,15 @@ # man https://www.unix.com/man-page/debian/5/dhcp6c.conf/ interface {{ ifname }} { +{% if address is defined and 'dhcpv6' in address %} request domain-name-servers; request domain-name; -{% if dhcpv6_options is defined and dhcpv6_options.parameters_only is defined %} +{% if dhcpv6_options is defined and dhcpv6_options.parameters_only is defined %} information-only; -{% endif %} -{% if dhcpv6_options is not defined or dhcpv6_options.temporary is not defined %} +{% endif %} +{% if dhcpv6_options is not defined or dhcpv6_options.temporary is not defined %} send ia-na 0; # non-temporary address +{% endif %} {% endif %} {% if dhcpv6_options is defined and dhcpv6_options.pd is defined %} {% for pd in dhcpv6_options.pd %} @@ -17,10 +19,12 @@ interface {{ ifname }} { {% endif %} }; -{% if dhcpv6_options is not defined or dhcpv6_options.temporary is not defined %} +{% if address is defined and 'dhcpv6' in address %} +{% if dhcpv6_options is not defined or dhcpv6_options.temporary is not defined %} id-assoc na 0 { # Identity association for non temporary address }; +{% endif %} {% endif %} {% if dhcpv6_options is defined and dhcpv6_options.pd is defined %} diff --git a/python/vyos/ifconfig/interface.py b/python/vyos/ifconfig/interface.py index 892495dec..537c4bc2d 100644 --- a/python/vyos/ifconfig/interface.py +++ b/python/vyos/ifconfig/interface.py @@ -901,10 +901,15 @@ class Interface(Control): if isinstance(new_addr, str): new_addr = [new_addr] - # ensure DHCP/DHCPv6 is stopped (when not configured explicitly) - for proto in ['dhcp', 'dhcpv6']: - if proto not in new_addr: - self.del_addr(proto) + # always ensure DHCP client is stopped (when not configured explicitly) + if 'dhcp' not in new_addr: + self.del_addr('dhcp') + + # always ensure DHCPv6 client is stopped (when not configured as client + # for IPv6 address or prefix delegation + dhcpv6pd = jmespath.search('dhcpv6_options.pd', config) + if 'dhcpv6' not in new_addr or dhcpv6pd == None: + self.del_addr('dhcpv6') # determine IP addresses which are assigned to the interface and build a # list of addresses which are no longer in the dict so they can be removed @@ -915,6 +920,10 @@ class Interface(Control): for addr in new_addr: self.add_addr(addr) + # start DHCPv6 client when only PD was configured + if dhcpv6pd != None: + self.set_dhcpv6(True) + # There are some items in the configuration which can only be applied # if this instance is not bound to a bridge. This should be checked # by the caller but better save then sorry! -- cgit v1.2.3 From a574a01ab5c02aeb90c6d099dce482c1bf8be096 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sun, 23 Aug 2020 00:16:45 +0200 Subject: dhcpv6-pd: T2677: add support for rapid-commit option When rapid-commit is specified, dhcp6c will include a rapid-commit option in solicit messages and wait for an immediate reply instead of advertisements. --- data/templates/dhcp-client/ipv6.tmpl | 3 +++ interface-definitions/include/dhcpv6-options.xml.i | 8 +++++++- 2 files changed, 10 insertions(+), 1 deletion(-) (limited to 'data/templates/dhcp-client/ipv6.tmpl') diff --git a/data/templates/dhcp-client/ipv6.tmpl b/data/templates/dhcp-client/ipv6.tmpl index 85841fe94..68f668117 100644 --- a/data/templates/dhcp-client/ipv6.tmpl +++ b/data/templates/dhcp-client/ipv6.tmpl @@ -11,6 +11,9 @@ interface {{ ifname }} { {% if dhcpv6_options is not defined or dhcpv6_options.temporary is not defined %} send ia-na 0; # non-temporary address {% endif %} +{% if dhcpv6_options is defined and dhcpv6_options.rapid_commit is defined %} + send rapid-commit; # wait for immediate reply instead of advertisements +{% endif %} {% endif %} {% if dhcpv6_options is defined and dhcpv6_options.pd is defined %} {% for pd in dhcpv6_options.pd %} diff --git a/interface-definitions/include/dhcpv6-options.xml.i b/interface-definitions/include/dhcpv6-options.xml.i index 5d088b83d..b0a806806 100644 --- a/interface-definitions/include/dhcpv6-options.xml.i +++ b/interface-definitions/include/dhcpv6-options.xml.i @@ -70,9 +70,15 @@ + + + Wait for immediate reply instead of advertisements + + + - IPv6 "temporary" address + IPv6 temporary address -- cgit v1.2.3