Addressing Tutorial

IP Address Management (IPAM) is one of the most interesting netlab features – it allows you to create full-blown fully configured networking labs without spending a millisecond on IP addressing scheme, assigning IP addresses to nodes and interfaces, or configuring them on network devices.

This document starts with an easy walk through simple addressing schemes, gets progressively more complex, and ends with crazy scenarios like stretched subnets.

Basics

netlab uses a two-step IP address allocation during the lab topology transformation process:

  • A prefix is assigned to every link in the lab topology

  • An IPv4/IPv6 address is assigned to every node attached to a link

Of course it’s a bit more complex than that:

  • A link prefix could could contain an IPv4 subnet, an IPv6 subnet, or both.

  • You can assign a static prefix to a link or let netlab get one from an address pool.

  • You can assign static IPv4 and/or IPv6 addresses to every interface connected to a link, or remove an address from a particular interface.

  • netlab also supports unnumbered IPv4 interface, LLA-only IPv6 interfaces, and links/interfaces without IPv4/IPv6 addresses (in case you want to test layer-2 functionality).

Don’t get scared by the plethora of options – getting started with built-in address pools is as easy as it can get.

Using Built-In Address Pools

netlab ships with seven built-in address pools:

l2only: {}
lan:
  ipv4: 172.16.0.0/16
  prefix: 24
loopback:
  ipv4: 10.0.0.0/24
  prefix: 32
mgmt:
  ipv4: 192.168.121.0/24
  mac: 08-4F-A9-00-00-00
  prefix: 24
  start: 100
p2p:
  ipv4: 10.1.0.0/16
  prefix: 30
router_id:
  ipv4: 10.0.0.0/24
  prefix: 32
vrf_loopback:
  ipv4: 10.2.0.0/24
  prefix: 32
  • loopback pool generates IP address for loopback interfaces

  • lan pool is used to assign prefixes to stub links1 and multi-access links2.

  • p2p pool is used to assign prefixes to point-to-point links3

  • mgmt pool contains management network addresses. It’s the only pool that uses mac addresses at the moment. Changing its definition is probably a bad idea.

  • l2only pool contains no addresses. You can use it on layer-2-only links – add pool: l2only attribute to the link.

  • router_id address pool is used to allocate BGP and OSPFv3 router IDs in IPv6-only networks.

  • vrf_loopback address pool is used for optional VRF loopback interfaces.

Loopback Addresses

Let’s start with the simplest possible process: assigning IP addresses to loopback interfaces. We’ll use the following lab topology to make it a bit more interesting:

nodes: [ r1, r2, r3, r4 ]

links:
- r1
- r1-r2
- r1-r3-r4
- r3:
  r4:
  type: lan

One of the first things netlab topology transformation code does is assign node identifiers to lab devices:

nodes:
  r1:
    id: 1
  r2:
    id: 2
  r3:
    id: 3
  r4:
    id: 4

The node identifiers are then used to generate loopback addresses from the loopback pool:

nodes:
  r1:
    id: 1
    loopback:
      ipv4: 10.0.0.1/32
  r2:
    id: 2
    loopback:
      ipv4: 10.0.0.2/32
  r3:
    id: 3
    loopback:
      ipv4: 10.0.0.3/32
  r4:
    id: 4
    loopback:
      ipv4: 10.0.0.4/32

Don’t like the automatic assignment of node identifiers? No problem, use id node attribute.

Imagine you want R1 to have ID 42. All you have to do is to specify the lab devices in the dictionary format (because you want to set node attributes) and set id on R1:

nodes:
  r1:
    id: 42
  r2:
  r3:
  r4:

links:
- r1
- r1-r2
- r1-r3-r4
- r3:
  r4:
  type: lan

The loopback interfaces immediate reflect the new node IDs. Please note that the auto-assigned IDs still start at one; as we don’t need an ID for R1 (it already has it), r2.id becomes 1.

Warning

Don’t count on this behavior, it might change in the future – we might try to set node IDs based on their position in the nodes dictionary, or start at two instead of one or…

nodes:
  r1:
    id: 42
    loopback:
      ipv4: 10.0.0.42/32
  r2:
    id: 1
    loopback:
      ipv4: 10.0.0.1/32
  r3:
    id: 2
    loopback:
      ipv4: 10.0.0.2/32
  r4:
    id: 3
    loopback:
      ipv4: 10.0.0.3/32

Customize Address Pools

Don’t like the built-in addressing rules? It’s extremely easy to:

  • Change built-in address pools

  • Define your own pools

  • Use user-defined pools on individual links

Change Built-In Address Pools

All netlab address pools are defined in the addressing section of lab topology file. The default value of that section (taken from system defaults) is:

addressing:
  l2only: {}
  lan:
    ipv4: 172.16.0.0/16
    prefix: 24
  loopback:
    ipv4: 10.0.0.0/24
    prefix: 32
  mgmt:
    ipv4: 192.168.121.0/24
    mac: 08-4F-A9-00-00-00
    prefix: 24
    start: 100
  p2p:
    ipv4: 10.1.0.0/16
    prefix: 30
  vrf_loopback:
    ipv4: 10.2.0.0/24
    prefix: 32

Tip

To display address pools used by your lab topology, use netlab create -o yaml:addressing command.

To change the system defaults, specify addressing section in your lab topology. System defaults are always deep-merged with topology file settings, allowing you to specify just the changes you want to make.

For example, to use default AWS CIDR block for LAN segments, specify addressing.lan.ipv4 parameter:

addressing.lan.ipv4: 172.31.0.0/16

Obviously you could use the more traditional dictionary hierarchy if you prefer longer YAML files:

addressing:
  lan:
    ipv4: 172.31.0.0/16

Likewise, it takes a single line to change the default IPv4 prefix size of point-to-point address pools to /28:

addressing.p2p.prefix: 28

Custom Address Pools

To specify custom address pools, add keys to addressing dictionary, for example:

addressing:
  core:
    ipv4: 10.2.0.0/16
    prefix: 28

To use the core address pool, set link pool to core, for example:

nodes: [ r1, r2 ]
links:
- r1:
  r2:
  pool: core

You’ll find more details in Topology Address Pools document.

Static Addresses

Don’t like the built-in IPAM rules? Take the matters in your hands and use static IP addresses. We’re also assuming you’re ready to dive deeper into the netlab bowels and will use commands like netlab create -o yaml:links or netlab create -o yaml:nodes (or explore Ansible inventory created with netlab create) to inspect the results of your experiments.

Static Node Addressing

Sometimes you want to have even more control over interface IP addresses. Sure, why not: use ipv4 and/or ipv6 interface attributes to set the IP addresses of individual interfaces.

We’ll give you as much rope as you need (to make your troubleshooting miserable): you can specify IP addresses outside of link prefix, use different subnet masks, have IPv4 addresses on some nodes and IPv6 addresses on other nodes connected to the same link…

Let’s say you want to experiment with Proxy ARP, so you need different subnet masks on end hosts than on intermediate routers. No big deal:

nodes: [ h1, h2, r ]
links:
- h1:
    ipv4: 10.0.1.3/24
  r:
    ipv4: 10.0.1.1/28
- h2:
    ipv4: 10.0.1.67/24
  r:
    ipv4: 10.0.1.65/28

You could make the example a bit more convoluted by combining host IP addresses (with too-large subnet masks) with link prefixes:

nodes:
  r:
    id: 1    # Just to make sure it gets .1 address in every subnet
  h1:
  h2:
links:
- h1:
    ipv4: 10.0.1.3/24
  r:
  prefix:
    ipv4: 10.0.1.0/28
- h2:
    ipv4: 10.0.1.67/24
  r:
  prefix:
    ipv4: 10.0.1.64/28

Static ID-Based Interface Addresses

Looking for something less drastic like setting the router’s IP address to be the first IP address in the link subnet? We got you covered: use a number (instead of an IPv4/IPv6 address) in ipv4 or ipv6 interface attribute.

Remember the stub link example where I mentioned the router might not get the first IP address on the link? Let’s fix that:

nodes:
  r1:
    id: 42

links:
- r1:
    ipv4: 1

Regardless of what prefix gets assigned to the link, R1 will always get the first IP address in that prefix, even though its device ID is 42. Here’s what you get as a result of the above topology file:

links:
- bridge: X_1
  interfaces:
  - ifindex: 1
    ifname: eth1
    ipv4: 172.16.0.1/24
    node: r1
  linkindex: 1
  node_count: 1
  prefix:
    ipv4: 172.16.0.0/24
  type: stub
nodes:
  r1:
    af:
      ipv4: true
    id: 42
    interfaces:
    - bridge: X_1
      ifindex: 1
      ifname: eth1
      ipv4: 172.16.0.1/24
      linkindex: 1
      name: r1 -> stub
      neighbors: []
      type: stub
    loopback:
      ipv4: 10.0.0.42/32

IPv6 Support

netlab tries to be an equal-opportunity transformation tool: IPv4 and IPv6 are treated in exactly the same way7… it’s just that the system defaults are IPv4-only, but even that’s easy to fix.

Adding IPv6 Prefixes to Default Pools

Want to build a dual-stack lab? All you have to do is to add IPv6 prefixes to default address pools, for example:

addressing:
  loopback:
    ipv6: 2001:db8:0::/48
  lan:
    ipv6: 2001:db8:1::/48
  p2p:
    ipv6: 2001:db8:2::/48

nodes: [ r1 ]

The final address pools are a combination of system defaults (IPv4 prefixes) and IPv6 prefixes you specified in the topology file.

addressing:
  l2only: {}
  lan:
    ipv4: 172.16.0.0/16
    ipv6: 2001:db8:1::/48
    prefix: 24
  loopback:
    ipv4: 10.0.0.0/24
    ipv6: 2001:db8:0::/48
    prefix: 32
  mgmt:
    ipv4: 192.168.121.0/24
    mac: 08-4F-A9-00-00-00
    prefix: 24
    start: 100
  p2p:
    ipv4: 10.1.0.0/16
    ipv6: 2001:db8:2::/48
    prefix: 30

Every single address allocation feature described so far works as expected. For example, the loopback interface on R1 gets an IPv4 and an IPv6 address:

nodes:
  r1:
    box: none
    device: none
    id: 1
    loopback:
      ipv4: 10.0.0.1/32
      ipv6: 2001:db8:0:1::1/64
    mgmt:
      ifname: eth0
      ipv4: 192.168.121.101
      mac: 08-4F-A9-00-00-01

Tip

The IPAM logic creates /64 IPv6 prefixes from address pools. You cannot specify target IPv6 prefix size like you could with IPv4. To build a network with non-/64 IPv6 prefixes you’ll have to use static link prefixes.

IPv6-Only Networks

If you want to build an IPv6-only network, you have to remove IPv4 prefixes from the default pools – use ipv4: key without a value, for example:

addressing:
  loopback:
    ipv4:
    ipv6: 2001:db8:0::/48
  lan:
    ipv4:
    ipv6: 2001:db8:1::/48
  p2p:
    ipv4:
    ipv6: 2001:db8:2::/48

nodes: [ r1 ]

The resulting address pools have no IPv4 prefixes (don’t worry about the prefix attribute, it’s not used without the ipv4 attribute):

addressing:
  l2only: {}
  lan:
    ipv6: 2001:db8:1::/48
    prefix: 24
  loopback:
    ipv6: 2001:db8:0::/48
    prefix: 32
  mgmt:
    ipv4: 192.168.121.0/24
    mac: 08-4F-A9-00-00-00
    prefix: 24
    start: 100
  p2p:
    ipv6: 2001:db8:2::/48
    prefix: 30

Complex Addressing Scenarios

In the IPv6 section we described how to enable IPv6 on an interface without assigning a static address to it. netlab provides similar functionality for IPv4 – when setting ipv4 attribute to True, the device configuration modules try to configure unnumbered IPv4 Ethernet interfaces8.

Now that you’ve seen that you can set ipv4 or ipv6 attribute to True you might wonder what happens if you set it to False. Should you do that, the affected interface (or link) gets no IPv4/IPv6 address.

Now let’s see how you can use these features in real-life scenarios.

Devices Without IP Addresses

Several ways of building layer-2 only networks have been described in this document (address pools, static prefixes), but what if you want to connect a segment of IP hosts to a bridge (with no IP address)? Remove the IP addresses from the bridge interface with ipv4: False and/or ipv6: False9.

Imagine a network with four hosts and a bridge connecting two parts of the same subnet. You could describe the network with the following lab topology:

nodes: [ h1, h2, h3, h4, b ]

links:
- prefix: 10.42.42.0/24
  h1:
  h2:
  b:
    ipv4: False
- prefix: 10.42.42.0/24
  h3:
  h4:
  b:
    ipv4: False

Notes:

  • The bridge B connects two parts of the same subnet. Such a topology is not supported by netlab IP address pools unless you use VLAN configuration module; you have to use the same static prefix on both links.

  • Hosts will get IP addresses assigned from the link prefix based on their node ID (h1: 10.42.42.1/24 through h4: 10.42.42.4/24)

  • Bridge B would get the same IP address (10.42.42.5/24) assigned to both interface. Most network operating systems wouldn’t agree with such an approach.

  • To make the topology work, remove the IPv4 address from bridge interfaces with ipv4: False interface attribute.


1(1,2)

Links with a single non-host node attached to them or links that have type: stub attribute.

2

Links with more than two non-host nodes attached to them or links that have type: lan attribute.

3

Links with exactly two non-host nodes and no hosts attached to them

4

You can also specify the pool to use with pool link attribute; we’ll cover that a bit later.

5

You can also use /31 IPv4 prefixes to number P2P links.

6

If you skipped those sections, you might want to read them now.

7

OK, there’s a single exception: management network uses IPv4 addresses. You can fix that if you wish; I prefer long hikes over solving imaginary problems.

8

Some network operating systems do not support unnumbered IPv4 Ethernet interfaces. In some other cases, device configuration templates don’t provide that functionality. netlab tries to warn you about those exceptions.

9

You should probably use the VLAN configuration module and set vlan.mode to bridge, but if you want to test technologies not yet supported by netlab like bridging over SRv6, you might have to use unaddressed interfaces.