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 addresses for loopback interfaces

  • stub pool (when defined) is used to assign prefixes to stub links[1]

  • p2p pool is used to assign prefixes to point-to-point links between routers.

  • lan pool is used to assign prefixes to all other links, including links with hosts and multi-access links (more details).

  • mgmt pool contains management network addresses. It’s the only pool that uses mac addresses. 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:
  pool: 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

If you don’t like the built-in addressing rules, it’s extremely easy to:

  • Change built-in address pools

  • Define additional address pools

  • Use user-defined pools on individual links

Change Built-In Address Pools

All netlab address pools are defined in the addressing section of the 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 the netlab create -o yaml:addressing command.

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

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

addressing.lan.ipv4: 172.31.0.0/16

You could also 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 the 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

Read the Topology Address Pools document for more details.

Static Addresses

Don’t like the built-in IPAM rules? Take matters into your own hands and use static IP addresses. We’re also assuming you’re ready to dive deeper into the netlab bowels and 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 the link prefix, use different subnet masks, or have IPv4 addresses on some nodes and IPv6 addresses on others connected to the same link.

Let’s assume 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

Do you want to do something less drastic, like setting the router’s IP address to be the first IP address in the link subnet? We’ve got you covered: use a number (instead of an IPv4 or IPv6 address) in the 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 way[5]… 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 combine 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. To change the target IPv6 prefix size, use the ‌prefix6 pool attribute. For example, you could set prefix6: 128 on the loopback pool to have /128 loopback IPv6 addresses.

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 interfaces[6].

Now that you’ve seen that you can set the ipv4 or ipv6 attribute to True, you might wonder what happens if you set it to False. If you do that, netlab does not assign an IPv4/IPv6 address to the affected interface (or link).

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: False.

Tip

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

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:

  • netlab will not configure bridging between the two links on B; you must use a custom configuration template to provision layer-2 functionality. Use VLAN configuration module to implement bridging with netlab.

  • The bridge B connects two parts of the same subnet. netlab IPAM implementation does not support such a topology unless you use VLAN configuration module. You must use the same static prefix on both links to make the above example work.

  • 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.