Page MenuHomeVyOS Platform

Proposal for clearer DHCPv6-PD configuration options
Closed, ResolvedPublicFEATURE REQUEST

Description

Description

Currently, you must know what prefix is assigned to your router by an upstream device or via DHCPv6 in order to create prefix delegation unless you specify prefix-length:

[interfaces ethernet eth0]
address dhcp
address dhcpv6
description "WAN_PORT"
dhcpv6-options {
    prefix-delegation {
        prefix-length 56
        interface eth1 {
            address 1
            sla-id 0
            sla-len 8
        }
    }
}

In the above example, I must know that I receive a /56 and not a /48 or /60 from my upstream DHCPv6 server.

I can specify the prefix-length option to request a /56 explicitly, but if my DHCPv6 server is assigning correctly this is unnecessary. In addition, I may wish to have my configuration work in multiple environments, regardless of specific prefix-length given to delegate from.

In the past I have used EdgeOS and they handle the same configuration in the following manner:

[interfaces ethernet eth0]
address dhcp
address dhcpv6
description WAN_PORT
dhcpv6-pd {
    pd 0 {
        interface eth1 {
            host-address ::1
            prefix-id :1
        }
    }
}

Note that the prefix-length is set to 56 by my upstream DHCPv6 server, but no equivalent to sla-len is required. EdgeOS assumes a /64 is desired unless something else is specified, likely based on RFC7242 and the default expectations of neighbor discovery.

It does not care as long as the netmask is smaller than /64 and can have /64 networks delegated from it.


Proposal

I would like to propose the following syntax change to make configuration of DHCPv6 more clear in VyOS:

  1. Assume that an interface created with set dhcpv6-options prefix-delegation interface will be assigned a netmask of /64 unless the sla-len exists already
  2. Allow an alternative option to sla-len that allows specifying the netmask, such as sla-mask /64
    • If sla-len remains, create validation error for when sla-mask and sla-len are both specified and prefix-delegation prefix-length added to sla-len does not equal sla-mask
    • If sla-len does not make sense or is ambiguous to remain with sla-mask, create validation error that allows one or the other
  3. (Optional) Allow the address syntax to accept a netmask, consistent with how one would be set in interface ethernet iface_name address, e.g. address ::1/64

Examples

Conditions:

  • User does not know what prefix will be assigned by upstream DHCPv6 server
  • User does not wish to set netmask explicitly
  • User wishes to set address of VyOS as ::1/64

Configuration:

[interfaces ethernet eth0]
dhcpv6-options {
    prefix-delegation {
        interface eth1 {
            address ::1
            sla-id 0
        }
    }
}

Conditions:

  • User does not know what prefix will be assigned by upstream DHCPv6 server
  • User wishes to explicitly use a netmask of /64
  • User wishes to set address of VyOS as ::1/64

Configuration:

[interfaces ethernet eth0]
dhcpv6-options {
    prefix-delegation {
        interface eth1 {
            address ::1/64
            sla-id 0
        }
    }
}

Conditions:

  • User wishes to request a specific prefix of /56 from upstream DHCPv6 server
  • User assumes netmask will be /64 on LAN
  • User does not care what address of VyOS is

Configuration:

[interfaces ethernet eth0]
dhcpv6-options {
    prefix-delegation {
        prefix-length 56
        interface eth1 {
            sla-id 0
        }
    }
}

Conditions:

  • User wishes to request a specific prefix of /60
  • User wishes to explicitly use a netmask of /64
  • User does not care what address of VyOS is

Configuration:

[interfaces ethernet eth0]
dhcpv6-options {
    prefix-delegation {
        prefix-length 60
        interface eth1 {
            sla-mask /64
            sla-id 0
        }
    }
}

Details

Version
-
Is it a breaking change?
Config syntax change (migratable)
Issue type
Feature (new functionality)

Event Timeline

At the request of @c-po, going to mention that this may have relevance to T2653 since the order of how interfaces are handled may be effected by this and/or the proposal here may make sense to change based on their work.

c-po changed the task status from Open to In progress.Jul 3 2020, 3:26 PM
c-po claimed this task.
c-po triaged this task as Low priority.
c-po moved this task from Need Triage to In Progress on the VyOS 1.3 Equuleus board.
c-po moved this task from In Progress to Backlog on the VyOS 1.3 Equuleus board.

Reading the UBNT source code I see:

foreach my $pd (@pds) {
     $output .= "id-assoc pd $pd {\n";
     $config->setLevel("$path dhcpv6-pd pd $pd");
     my $prefix = $config->returnValue('prefix-length');
     $prefix = 64 if !defined $prefix;
     $prefix =~ s/\///;
     my $sla_len = 64 - $prefix;
     $output .= "\tprefix ::/$prefix infinity;\n";
     my @intfs = $config->listNodes('interface');
     my $count = 0;
     foreach my $intf (@intfs) {
         $output .= "\tprefix-interface $intf {\n";
         $config->setLevel("$path dhcpv6-pd pd $pd interface $intf");
         my $prefix_id = $config->returnValue('prefix-id');
         if (defined $prefix_id) {
             $prefix_id = validate_sla_id($sla_len, $prefix_id);
             $output .= "\t\tsla-id $prefix_id;\n";
         } else {
             $output .= "\t\tsla-id $count;\n";
         }
         $output .= "\t\tsla-len $sla_len;\n";
         my $host_addr = $config->returnValue('host-address');
         if (defined $host_addr) {
             $host_addr = validate_ifid($host_addr);
             $output .= "\t\tifid $host_addr;\n";
         }

         $output .= "\t};\n";
         $count++;
     }
     $output .= "};\n\n";
 }

Also some variable validation is done by:

# prefix-id :1
sub validate_sla_id {
    my ($sla_len, $sla_id) = @_;

    $sla_id =~ s/^[:]+//;
    my $ip = new6 NetAddr::IP("::$sla_id");
    if (!defined $ip) {
        die "Invalid IPv6 ID\n";
    }
    my $dec_sla_id = $ip->numeric();
    if (!defined $dec_sla_id) {
        die "Unable to convert prefix-id\n";
    }
    my $size = (2 ** $sla_len) - 1;
    if ($dec_sla_id > $size) {
        my $prefix = 64 - $sla_len;
        my $hex_size = sprintf("%x", $size);
        $ip = new6 NetAddr::IP("$size");
        if (!defined $ip) {
            die "failed to convert $size\n";
        }
        my $limit = $ip->short();
        die "prefix-id must be less than $limit for prefix /$prefix\n";
    }
    return $dec_sla_id;
}

# host-address ::1
sub validate_ifid {
    my ($ifid) = @_;

    $ifid =~ s/^[:]+//;
    my $ip = new6 NetAddr::IP("::$ifid");
    if (!defined $ip) {
        die "Invalid IPv6 host address\n";
    }
    my $dec_sla_id = $ip->numeric();
    if (!defined $dec_sla_id) {
        die "Unable to convert IPv6 host address\n";
    }
    $ip = new6 NetAddr::IP("::ffff:ffff:ffff:ffff");
    my $max = $ip->numeric();
    if ($dec_sla_id > $max) {
        my $host_addr_max = $ip->short();
        die "host-address must be less than $host_addr_max\n";
    }
    return $dec_sla_id;                                                                                                                                                                                                                     }
  • prefix-length is 64 unless defined otherwise
  • Multiple PDs can be requested - this will be useful if ISP only hands out one /64 per PD - should be added
  • sla-id will auto increment when not defined (makes sense)
  • sla-len is auto calculated and can never be set by user (less trouble - should adopt that)
  • The call address host-address on the CLI - I like our term more as we always use address

I've done the following hacking to get multiple delegations, FWIW.

Config syntax XML:
https://github.com/jmbwell/vyos-1x/blob/dddde13cc0ef35326364246cfcd9447b8f3f7c28/interface-definitions/include/dhcpv6-options.xml.i

ipv6.tmpl for dhcp6c config:
https://github.com/jmbwell/vyos-1x/blob/dddde13cc0ef35326364246cfcd9447b8f3f7c28/data/templates/dhcp-client/ipv6.tmpl

Example usage:

set interfaces ethernet eth0 dhcpv6-options prefix-delegation id 0 interface eth1 sla-id 0
set interfaces ethernet eth0 dhcpv6-options prefix-delegation id 0 interface eth1 sla-len 16
  • In the XML, I can't tell how to represent multiple children of prefix-delegation without specifying an id as a node tag
  • This hierarchy mimics the structure of dhcp6c.conf. This approach is wordy. Would it be more vyos-y to put this in the configuration of the child/target interface instead, something like set interfaces ethernet eth1 prefix-delegation parent-interface eth0 ia-pd 0 sla-id 0
  • Specifying defaults, calculating defaults, and auto-incrementing values would need to be added to interface.py?
  • Validation needs to be implemented/fixed

@jmbwell thanks for the PoC. Please not that this will break existing configurations as this alters the syntax and thus a migrator is required (e.g. https://github.com/vyos/vyos-1x/blob/current/src/migration-scripts/interfaces/9-to-10)

I'm thinking of the following syntax:

  • set interface ethernet eth0 dhcpv6-pd 0 length <48-64>
  • set interface ethernet eth0 dhcpv6-pd 0 interface eth1 address
  • set interface ethernet eth0 dhcpv6-pd 0 interface eth1 sla-id

sla-len could be dropped and auto calculated from length as mentioned above.

I would like to split dhcpv6-options and dhcpv6-pd as those are two different pairs of shoes.

About default values: They can now be specified in XML under the <defaultValue> node, just grep around.

erkin set Issue type to Feature (new functionality).Aug 29 2021, 1:57 PM
erkin removed a subscriber: Global Notifications.