Tag Archives: Ubuntu

Docker Registry with IPv6

If you have been following along, you know that I started a series of posts aimed at identifying IPv6 support for the various Docker components/services.

The first blog post was focused on Docker Engine, which has pretty reasonable support for basic IPv6.

The second blog post was focused on Docker Hub, which has zero IPv6 support. This is due to it being hosted on AWS and no IPv6-enabled front-end is deployed.

This blog post will focus on Docker Registry.

As I stated in the past two blog entries, I am not here to teach you Docker (what it is, how to deploy it, etc..). I am simply showing basic functionality of various Docker components/services when used with IPv6.

For information on setting up your own Docker Registry, check out:


I am using Docker version 1.8.3, Docker Compose version 1.4.2 and Docker Registry version 2.

I am using the same Ubuntu 14.04.3 hosts that I have used in the last two blog posts.

My setup uses two hosts with the following configuration:

  • docker-v6-1:
    • Role: Docker Registry
    • IPv6 Address: fd15:4ba5:5a2b:1009:20c:29ff:fef3:f848/64
  • docker-v6-2:
    • Role: Docker Host/Client
    • IPv6 Address: fd15:4ba5:5a2b:1009:20c:29ff:febb:cbf8/64

My Docker Registry (running on ‘docker-v6-1’) uses self-signed cert and is started using either the ‘docker run’ syntax or Docker Compose. I show both examples below:

docker run:

docker run -d -p 5000:5000 --restart=always --name registry \
  -v `pwd`/certs:/certs \
  -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt \
  -e REGISTRY_HTTP_TLS_KEY=/certs/domain.key \

Use Docker Compose to run Docker Registry
I am using a file named “docker-compose.yml” to launch my registry.

  restart: always
  image: registry:2
    - 5000:5000
    REGISTRY_HTTP_TLS_CERTIFICATE: /certs/domain.crt
    REGISTRY_HTTP_TLS_KEY: /certs/domain.key
    - /certs:/certs

Run Docker Compose:

docker-compose up -d

Verify Connectivity
On the Docker host/client (“docker-v6-2”),  verify that the Docker Registry host (“docker-v6-1”) can be reached over IPv6:

root@docker-v6-2:~# ping6 -n docker-v6-1.example.com
PING docker-v6-1.example.com(fd15:4ba5:5a2b:1009:20c:29ff:fef3:f848) 56 data bytes
64 bytes from fd15:4ba5:5a2b:1009:20c:29ff:fef3:f848: icmp_seq=1 ttl=64 time=0.402 ms
64 bytes from fd15:4ba5:5a2b:1009:20c:29ff:fef3:f848: icmp_seq=2 ttl=64 time=0.367 ms

Docker Registry Push/Pull Verification
Now that connectivity to the Docker Registry host is working, tag a local Docker image and then push it (over IPv6) to the Docker Registry:

root@docker-v6-2:~# docker tag ubuntu docker-v6-1.example.com:5000/ubuntu

root@docker-v6-2:~# docker push docker-v6-1.example.com:5000/ubuntu
The push refers to a repository [docker-v6-1.example.com:5000/ubuntu] (len: 1)
a005e6b7dd01: Image successfully pushed
002fa881df8a: Image successfully pushed
66395c31eb82: Image successfully pushed
0105f98ced6d: Image successfully pushed
latest: digest: sha256:167f1c34ead8f1779db7827a55de0d517b7f0e015d8f08cf032c7e5cd6979a84 size: 6800

A tcpdump on the Docker Registry shows traffic between docker-v6-1 and docker-v6-2 for the ‘push’ using the previously defined port 5000:

root@docker-v6-1:~# tcpdump -n -vvv ip6 -i eth0
tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
19:36:09.283820 IP6 (hlim 64, next-header TCP (6) payload length: 40) fd15:4ba5:5a2b:1009:20c:29ff:febb:cbf8.56066 > fd15:4ba5:5a2b:1009:20c:29ff:fef3:f848.5000: Flags [S], cksum 0x65b1 (correct), seq 2754754540, win 28800, options [mss 1440,sackOK,TS val 645579 ecr 0,nop,wscale 7], length 0
19:36:09.283930 IP6 (hlim 64, next-header TCP (6) payload length: 40) fd15:4ba5:5a2b:1009:20c:29ff:fef3:f848.5000 > fd15:4ba5:5a2b:1009:6540:bb36:2e23:f5a2.56066: Flags [S.], cksum 0xcd92 (incorrect -> 0x50bd), seq 1577491031, ack 2754754541, win 28560, options [mss 1440,sackOK,TS val 859496 ecr 645579,nop,wscale 7], length 0

It works!

Happy Dockering,


Tenant IPv6 Deployment in OpenStack Kilo Release

You folks know that I have been dancing to the IPv6 music for the last 12 years or so. IPv6 is so popular that I still earn about 75 cents a month on my book royalties. 🙂

I have been fairly disappointed in the deployment of IPv6 in an OpenStack environment.  Many individuals and companies have beat on IPv6 over the past couple of years to get it to where it is today in OpenStack and we should all be super greatful.  In this post I will go over some design and deployment considerations for IPv6 in the OpenStack Kilo release.

Note: I refer to the term “tenant” vs. what OpenStack calls a “project”.

Cloud and IPv6

IPv6 has had a rough go of it over the many years it has been around. It is usually a rough go when you try to inject it into any cloud deployment. And I do mean ANY cloud deployment.  The hard stuff with cloud and IPv6 includes (not an exhaustive list):

  • API Endpoints – Enabling IPv6 on the non-Tenant-facing portion of the cloud stack
  • Provisioning, Orchestration and Management – This includes CI/CD, bare-metal provisioning (i.e. Cobbler, Ironic), automation tools such as Ansible, Puppet, etc.. and the overall Data Center management tools
  • Management/communication protocol interoperability and support of IPv6
  • Support for IPv6 in both virtual and physical networking
  • Oh, let’s not forget – expertise

In this post I am not going to address all of the above as none of us have that kind of time.  What I will talk about is making a choice to enable ALL of OpenStack for IPv6 or settling for the really important part, which is the tenant-facing part and how that looks when configured.

There are two common ways of embracing IPv6 within OpenStack (I am not discussing IPv6-only options here):

  • Dual Stack everything
  • Conditional Dual Stack

Figure 1 shows an example of a “dual stack everything” approach. It is what is sounds like. Everything in the entire stack is both IPv4 and IPv6 enabled.  This includes the API endpoints, the DBs, the tools and systems that surround OpenStack (i.e. provisioning and automation).  This, kids, can be a real pain in the butt, especially if this is a brownfield deployment where you have to go in an muck around with database entries for IPv6 and so on.

Figure 1. Dual Stack Everything


This is where “conditional dual stack” comes in.  It allows you to control when and where IPv6 is enabled.  In many cases, it is just in the tenant space, at least initially.

Figure 2 shows an example of where we have an IPv4-only OpenStack control plane (API/DB/etc) but dual stack for anything that faces something a tenant would see/control/interact with.  Optionally, this is where you can begin experimenting (I stress that word) with IPv6-only tenant networks.

Figure 2. Conditional Dual Stack



No matter which path you go down (and there are variances to the two I have pointed out here), you will end up dealing with IPv6 in the tenant space.  So, let’s talk about that part.

Tenant IPv6 Address Options

There are many combinations to IPv6 address assignment and even the types of addresses you can use.  For tenant address types you can use:

You can use those independently or together.  As far as planning out the use of GUA, ULA or combination of the two you have to think about the requirements of the tenant.  Most of the time the tenant has no clue what ‘routable’ means or NAT and they shouldn’t.  In the context of IPv6, we don’t want to do NAT, ever. Well, with one exception – we may need, for a very temporary use case, NAT64 where we translating incoming IPv6 connections into back-end IPv4-only nodes.  This is an entirely different use case than wanting to translate between two IPv6 address spaces.  Don’t do that. 🙂

With all of that said, I tend to see two of MANY address options in production deployments:

  • Cloud provider assigned addressing – Provider owns and assigns IPv6 addressing
  • Tenant-provided addressing – Tenant brings their own IPv6 addressing and the cloud provider has to route it

What I mean by “cloud provider assigned addressing” is that the owner of the system (the cloud provider – which could be a public provider or just an Enterprise IT shop) will obtain a Provider Independent (PI) or Provider Assigned (PA) IPv6 address block, design an address plan and then assign blocks out of that plan to each tenant. This works well, is easy to do and is the way you should do it.

Tenant-provided addressing is possible, but messy.  In the Enterprise space, this is not something that usually happens unless you are dealing with a merger & acquisition (M&A) situation where an acquired company wants their existing IPv6 addressing to be used in the acquiring company’s cloud service.  This is something that is requested when an Enterprise or another SP is using another public cloud provider.  Again, it is totally doable but it requires a lot of planning with BGP, address space design, etc..

From an address assignment perspective, you can use:

  • Static/manual configuration
  • StateLess Address AutoConfiguration (SLAAC) – IPv6 prefix (i.e /64) is assigned to the end node via a router advertisement (RA) and the node self-constructs the interface ID (IID) portion of the address (i.e. the last /64 bits)
  • Stateful DHCPv6 – Just like IPv4 DHCP, a DHCPv6 server hands out full IPv6 addressing and any configured options
  • Stateless DHCPv6 – A combination of SLAAC (for address assignment) and DHCPv6 (for option assignment – DNS name, domain name)

In the OpenStack Kilo release we have functional support for SLAAC, Stateful DHCPv6 and Stateless DHCPv6.  I will cover the configuration of all three in this post.

Example Topology

The lab setup I am using for this post includes:

  • Kilo
  • Devstack – only because I did this testing before packages were available for RDO/Packstack, Ubuntu/Juju/MaaS or any other intaller
  • All-in-one node (although in another lab I have I did this same setup on 7 nodes and it worked as expected)
  • The lab I did this test in did not have external IPv6 connectivity to the Internet, but I do have IPv6 throughout that lab so I could verify proper routing beyond OpenStack

Figure 3 shows a basic topology of the example setup.  The all-in-one (AIO) has a management network interface (eth0) and an OpenStack public network interface (eth1).  Both interfaces are connected to a Top-of-Rack (ToR) switch which has an uplink to the Data Center Aggregation Layer switches (via trunked VLANs).  The Aggregation Layer switches have VLAN interfaces for each network and are providing IPv4 and IPv6 routing for the rest of the lab. There are IPv6 routes configured on the Aggregation Layer switches for each IPv6 prefix within the OpenStack tenant space.  Off of the ToR is a DNS server that is IPv4 and IPv6 enabled.

Figure 3. Example Topology


Before I walk through each address assignment type, I will create the public network and subnets as the cloud admin. This can be done in the dashboard or via the Neutron client CLI. In this example a “public” network is created and the upstream Data Center L3 switches (–router:external) will be used as the gateway. An IPv4 subnet is created with an allocation range so that the addresses assigned do not collide with IPv4 addresses assigned on the Data Center L3 switches. An IPv6 subnet is created which also has an allocation range defined. If you have an upstream gateway address that is not .1 (v4) or ::1 (v6) then you need to identify the real gateway address using the “–gateway” option:

neutron net-create public --router:external

neutron subnet-create --name public-subnet --allocation-pool start=,end= public

neutron subnet-create --ip-version=6 --name=public-v6-subnet --allocation-pool start=2001:db8:cafe:d::5,end=2001:db8:cafe:d:ffff:ffff:ffff:fffe --disable-dhcp public 2001:db8:cafe:d::/64

Let’s walk through SLAAC, Stateful DHCPv6 and Stateless DHCPv6.


Figure 4 gives a topology view of the SLAAC example I am referencing.  The Neutron router has a private network with IPv4 and IPv6 subnets and a public network with gateway connections (Also, dual stack) to the Data Center. The instance will have a dual stack connection and receive DHCPv4 address assigned from DNSMASQ and IPv6 address assignment via radvd in SLAAC mode:

Figure 4. SLAAC Topology Example


When you use SLAAC mode in the tenant space, the Router Advertisement Daemon (radvd) is used to send router advertisements (RAs) in response to Router Solicitations (RS) as well as at a regular interval.  When you create a Neutron network and subnet for IPv6 you have to select the “IPv6 Address Configuration Mode” from the “Subnet Details” screen in the dashboard. In this case you would select “SLAAC: Address discovered from OpenStack Router”.  If you were doing this via CLI, you would use the option arguments of “–ipv6-address-mode=slaac –ipv6-ra-mode=slaac” when you create the subnet.  In the example below, a new Neutron network (“private”) is created along with the IPv6 subnet creation (IPv4 subnet creation is not shown). The option arguments are added to identify SLAAC mode. Also, no DNS servers are added here as that information for IPv6 would not get injected into the instance and the instance (since it is set for SLAAC-only) would not ask for DNS and other options:

neutron net-create private
neutron subnet-create --ip-version=6 --name=private_v6_subnet --ipv6-address-mode=slaac --ipv6-ra-mode=slaac private 2001:db8:cafe::/64

Created a new subnet:
| Field             | Value                                                          |
| allocation_pools  | {"start": "2001:db8:cafe::2", "end": "2001:db8:cafe:0:ffff:ffff:ffff:fffe"}|
| cidr              | 2001:db8:cafe::/64                                             |
| dns_nameservers   |                                                                |
| enable_dhcp       | True                                                           |
| gateway_ip        | 2001:db8:cafe::1                                               |
| host_routes       |                                                                |
| id                | 42cc3dbc-938b-4ad6-b12e-59aef7618477                           |
| ip_version        | 6                                                              |
| ipv6_address_mode | slaac                                                          |
| ipv6_ra_mode      | slaac                                                          |
| name              | private_v6_subnet                                              |
| network_id        | 7166ce15-c581-4195-9479-ad2283193d06                           |
| subnetpool_id     |                                                                |
| tenant_id         | f057804eb39b4618b40e06196e16265b                               |

Inside the tenant (as a tenant member or admin) a Neutron router needs to be created along with attaching the router to the public network and the two subnets:

neutron router-create router

neutron router-gateway-set router public

neutron router-interface-add router private_v4_subnet

neutron router-interface-add router private_v6_subnet

When an instance boots inside the tenant and attaches to the “private” network it will have access to both the IPv4 and the IPv6 subnets that were defined previously. Note: Both Windows (since Windows 7/Server 2008) and Linux (from a long time ago) support SLAAC out of the box just so basic IPv6 protocol support is enabled.  The instance will receive and IPv4 address via DNSMASQ and an IPv6 address via radvd. Note: The host will NOT receive any kind of IPv6 DNS entry from OpenStack. There are a couple of considerations to understand with this. An instance can get both IPv4 and IPv6 DNS information for a host over IPv4 transport. You don’t need to access a DNS server natively over IPv6 in order to receive IPv6 host information in a lookup. But, if you do want to have an IPv6 entry in the /etc/resolv.conf file then, in SLAAC mode, you will need to configure it manually, setup cloud-init to inject it or just bake that entry into the image that is booted.

A highly summarized view of a tcpdump capture reveals the basic flow of a SLAAC exchange.  The ICMPv6 Flags field states “none” and the Prefix Information Flag field has “auto” enabled. The combination of “none” (Managed and Other bits = 0) and “auto” (Auto bit = 1) indicates SLAAC is used and DHCPv6 is not used. You can read more on this in RFC 4861:

IP6 (hlim 255, next-header ICMPv6 (58) payload length: 16) fe80::f816:3eff:fe79:5acc > ff02::2: [icmp6 sum ok] ICMP6, router solicitation, length 16
	  source link-address option (1), length 8 (1): fa:16:3e:79:5a:cc
	    0x0000:  fa16 3e79 5acc

IP6 (hlim 255, next-header ICMPv6 (58) payload length: 56) fe80::f816:3eff:fec3:17b4 > ff02::1: [icmp6 sum ok] ICMP6, router advertisement, length 56
	hop limit 64, Flags [none], pref medium, router lifetime 30s, reachable time 0s, retrans time 0s
	  prefix info option (3), length 32 (4): 2001:db8:cafe::/64, Flags [onlink, auto], valid time 86400s, pref. time 14400s
	    0x0000:  40c0 0001 5180 0000 3840 0000 0000 2001
	    0x0010:  0db8 cafe 0000 0000 0000 0000 0000
	  source link-address option (1), length 8 (1): fa:16:3e:c3:17:b4
	    0x0000:  fa16 3ec3 17b4

The instance will send out a router solicitation and the router will reply with a router advertisement. In that RA, the router will send various bits of information (various lifetimes and other stuff) and, in the case of SLAAC, it will send out a “Flags [none]”, indicating that it is not giving out anything other than a prefix. In that RA is the prefix from the subnet that was configured earlier (2001:db8:cafe::/64). The instance will use that prefix, along with its own IID (discussed earlier) to come up with a valid 128-bit IPv6 address. The instance will use the router’s link-local address as its gateway.  After the host has the IPv6 address it will go through a series of events such as Duplicate Address Detection (DAD) and so on. I won’t be explaining all of that stuff here. 😉

Stateful DHCPv6

Figure 5 is a topology view of the Stateful DHCPv6 layout. It is pretty much the same as with SLAAC only using a different IPv4 and IPv6 prefix.

Figure 5. Stateful DHCPv6 Topology Example


Just like with SLAAC mode, radvd is used with Stateful DHCPv6 mode.  Instead of using the prefix announcement (Auto bit set to 1) in the RA to assist with IPv6 address assignment (SLAAC mode), Stateful DHCPv6 uses the Managed bit (set to 1) and the Auto bit (set to 0) to instruct the instance to perform a  DHCPv6 solicit for both address assignment and other options.

Configuring OpenStack to use Stateful DHCPv6 is done using the same process as was shown in the SLAAC example only with different options. In the dashboard, “DHCPv6 stateful: Address discovered from OpenStack DHCP” is selected in the “subnet details” screen.  Unlike with SLAAC, a DNS name server entry can be added and it will be sent to the instance.  If the Neutron client CLI is used then the option arguments would be: “–ipv6-address-mode=dhcpv6-stateful –ipv6-ra-mode=dhcpv6-stateful”.  Here’s an example:

neutron net-create private-dhcpv6
neutron subnet-create --ip-version=6 --name=private_dhcpv6_subnet --ipv6-address-mode=dhcpv6-stateful --ipv6-ra-mode=dhcpv6-stateful private-dhcpv6 2001:db8:cafe:1::/64 --dns-nameserver 2001:db8:cafe:a::e
Created a new subnet:
| Field             | Value                                                          |
| allocation_pools  | {"start": "2001:db8:cafe:1::2", "end": "2001:db8:cafe:1:ffff:ffff:ffff:fffe"} |
| cidr              | 2001:db8:cafe:1::/64                                           |
| dns_nameservers   | 2001:db8:cafe:a::e                                             |
| enable_dhcp       | True                                                           |
| gateway_ip        | 2001:db8:cafe:1::1                                             |
| host_routes       |                                                                |
| id                | 545ea206-9d14-4dca-8bae-7940719bdab5                           |
| ip_version        | 6                                                              |
| ipv6_address_mode | dhcpv6-stateful                                                |
| ipv6_ra_mode      | dhcpv6-stateful                                                |
| name              | private_dhcpv6_subnet                                          |
| network_id        | 55ed8333-2876-400a-92c1-ef49bc10aa2b                           |
| subnetpool_id     |                                                                |
| tenant_id         | f057804eb39b4618b40e06196e16265b                               |

After performing “neutron router-interface-add” for each subnet (see SLAAC example), it’s time to setup the instance operating system for DHCPv6 operation. To learn about how Microsoft Windows supports IPv6 address assignment check out this blog.  No Linux version that I have ever worked with is configured, by default, to use DHCPv6.  For Ubuntu you have to add the “inet6 dhcp” line in the /etc/network/interfaces file:

auto eth0
iface eth0 inet dhcp
iface eth0 inet6 dhcp

I have tested CentOS 7 and Fedora 21 in this test bed and the following configuration works on those (add to the appropriate interface in /etc/sysconfig/network-scripts/):


Included below is a highly summarized output from a tcpdump capture of a Stateful DHCPv6 exchange.  There is a lot more going on here than in the SLAAC example.  Just like the SLAAC example, there is a RS/RA exchange but that is where the similarity ends.  In the RA below, the ICMPv6 Flags field is set to “managed” (M bit = 1). Note: that when the M bit is set to 1, the O bit, per RFC 4861 is redundant and can be ignored.  The instance will receive the RA and see that the “managed” flag is set and will then begin the DHCPv6 client process.  The instance will send a DHCPv6 Solicit to the ‘all DHCP servers’ well-known IPv6 multicast address (ff02::1:2).  Radvd will do a DHCPv6 advertise with all of the good stuff (address and options). The instance will do a DHCPv6 request for options (it processed the address info from the advertise) and the server will finish the sequence with a DHCPv6 reply.  You can read a summary view of this process here:

IP6 (hlim 255, next-header ICMPv6 (58) payload length: 24) fe80::f816:3eff:fe77:e5a0 > ff02::1: [icmp6 sum ok] ICMP6, router advertisement, length 24
	hop limit 64, Flags [managed], pref medium, router lifetime 30s, reachable time 0s, retrans time 0s
	  source link-address option (1), length 8 (1): fa:16:3e:77:e5:a0
	    0x0000:  fa16 3e77 e5a0

IP6 (hlim 1, next-header UDP (17) payload length: 64) fe80::f816:3eff:fe22:386b.546 > ff02::1:2.547: [udp sum ok] dhcp6 solicit (xid=85680b (client-ID hwaddr/time type 1 time 482446373 fa163e22386b) (option-request DNS-server DNS-search-list Client-FQDN SNTP-servers) (elapsed-time 101) (IA_NA IAID:1042430059 T1:3600 T2:5400))

IP6 (class 0xc0, hlim 64, next-header UDP (17) payload length: 175) fe80::f816:3eff:fe06:176f.547 > fe80::f816:3eff:fe22:386b.546: [udp sum ok] dhcp6 advertise (xid=85680b (client-ID hwaddr/time type 1 time 482446373 fa163e22386b) (server-ID hwaddr type 1 fa163e06176f) (IA_NA IAID:1042430059 T1:43200 T2:75600 (IA_ADDR 2001:db8:cafe:1::4 pltime:86400 vltime:86400)) (status-code success) (preference 255) (DNS-search-list openstacklocal.) (DNS-server 2001:db8:cafe:a::e) (Client-FQDN))

IP6 (hlim 1, next-header UDP (17) payload length: 106) fe80::f816:3eff:fe22:386b.546 > ff02::1:2.547: [udp sum ok] dhcp6 request (xid=9cb172 (client-ID hwaddr/time type 1 time 482446373 fa163e22386b) (server-ID hwaddr type 1 fa163e06176f) (option-request DNS-server DNS-search-list Client-FQDN SNTP-servers) (elapsed-time 0) (IA_NA IAID:1042430059 T1:3600 T2:5400 (IA_ADDR 2001:db8:cafe:1::4 pltime:7200 vltime:7500)))

IP6 (class 0xc0, hlim 64, next-header UDP (17) payload length: 186) fe80::f816:3eff:fe06:176f.547 > fe80::f816:3eff:fe22:386b.546: [udp sum ok] dhcp6 reply (xid=9cb172 (client-ID hwaddr/time type 1 time 482446373 fa163e22386b) (server-ID hwaddr type 1 fa163e06176f) (IA_NA IAID:1042430059 T1:3600 T2:6300 (IA_ADDR 2001:db8:cafe:1::4 pltime:7200 vltime:7500)) (status-code success) (DNS-search-list openstacklocal.) (DNS-server 2001:db8:cafe:a::e) (Client-FQDN))

Stateless DHCPv6

Stateless DHCPv6 is a combo of SLAAC (for address assignment) and DHCPv6 (for options).  For the sake of consistency with the last two sections, here is a topology sample for Stateless DHCPv6:

Figure 6. Stateless DHCPv6 Sample Topology


The configuration of Stateless DHCPv6 is similar to that of Stateful DHCPv6.  In the dashboard, select “DHCPv6 stateless: Address discovered from OpenStack Router and additional information from OpenStack DHCP” from the “subnet details” screen.  The options argument changes if using the Neutron client CLI: “–ipv6-address-mode=dhcpv6-stateless –ipv6-ra-mode=dhcpv6-stateless private-dhcpv6-stateless”.  Here is an example:

neutron net-create private-dhcpv6-stateless

neutron subnet-create --ip-version=6 --name=private_dhcpv6_stateless_subnet --ipv6-address-mode=dhcpv6-stateless --ipv6-ra-mode=dhcpv6-stateless private-dhcpv6-stateless 2001:db8:cafe:2::/64 --dns-nameserver 2001:db8:cafe:a::e
Created a new subnet:
| Field             | Value                                                        |
| allocation_pools  | {"start": "2001:db8:cafe:2::2", "end": "2001:db8:cafe:2:ffff:ffff:ffff:fffe"} |
| cidr              | 2001:db8:cafe:2::/64                                         |
| dns_nameservers   | 2001:db8:cafe:a::e                                           |
| enable_dhcp       | True                                                         |
| gateway_ip        | 2001:db8:cafe:2::1                                           |
| host_routes       |                                                              |
| id                | edd1d404-e949-4cdf-9812-334bbf0e5cec                         |
| ip_version        | 6                                                            |
| ipv6_address_mode | dhcpv6-stateless                                             |
| ipv6_ra_mode      | dhcpv6-stateless                                             |
| name              | private_dhcpv6_stateless_subnet                              |
| network_id        | f65c6e60-d31e-4a1c-8136-599c3855b86a                         |
| subnetpool_id     |                                                              |
| tenant_id         | f057804eb39b4618b40e06196e16265b                             |

After performing “neutron router-interface-add” for each subnet (again, see the SLAAC example), edits need to be made to the instance operating system for Stateless DHCPv6 operation. In the Ubuntu /etc/network/interfaces file, ensure the “inet6” line is set to “auto” and enable the stateless flag:

iface eth0 inet6 auto
dhcp 1

Again, I only tested CentOS7 and Fedora 21 with this setup so your mileage may vary but for those OSes, set the following for the appropriate interface in /etc/sysconfig/network-scripts/:


Below is the output from tcpdump for the Stateless DHCPv6 exchange.  Radvd sends out the RS with the ICMPv6 Flags field set with the O bit set to 1 and the Prefix Information Flag field has “auto” enabled. This combination basically says “I, the router, will provide you, the instance,  a prefix via SLAAC and you come back asking for options”.  The instance will issue a “dhcp6 inf-req” to get the options and radvd will reply:

IP6 (hlim 255, next-header ICMPv6 (58) payload length: 56) fe80::f816:3eff:fec1:bc52 > ff02::1: [icmp6 sum ok] ICMP6, router advertisement, length 56
	hop limit 64, Flags [other stateful], pref medium, router lifetime 30s, reachable time 0s, retrans time 0s
	  prefix info option (3), length 32 (4): 2001:db8:cafe:2::/64, Flags [onlink, auto], valid time 86400s, pref. time 14400s
	    0x0000:  40c0 0001 5180 0000 3840 0000 0000 2001
	    0x0010:  0db8 cafe 0002 0000 0000 0000 0000
	  source link-address option (1), length 8 (1): fa:16:3e:c1:bc:52
	    0x0000:  fa16 3ec1 bc52

IP6 (hlim 1, next-header UDP (17) payload length: 44) fe80::f816:3eff:fefe:d157.546 > ff02::1:2.547: [udp sum ok] dhcp6 inf-req (xid=d2dbc8 (client-ID hwaddr type 1 fa163efed157) (option-request DNS-server DNS-search-list Client-FQDN SNTP-servers) (elapsed-time 94))

IP6 (class 0xc0, hlim 64, next-header UDP (17) payload length: 88) fe80::f816:3eff:fe2d:a6de.547 > fe80::f816:3eff:fefe:d157.546: [udp sum ok] dhcp6 reply (xid=d2dbc8 (client-ID hwaddr type 1 fa163efed157) (server-ID hwaddr type 1 fa163e2da6de) (DNS-search-list openstacklocal.) (DNS-server 2001:db8:cafe:a::e) (lifetime 86400))

I am sorry for the legnth of the blog post. In retrospect I should have broken this post into multiple posts but oh well.

I hope this was helpful.