VyOSI · Networking Foundations for Routing EngineersLayer 2 and Layer 3 foundations
IPv4, IPv6, CIDR and subnetting — the arithmetic the routing engineer must do in their head
What you'll learn
- Convert between dotted-decimal, hex, and CIDR notation without hesitation
- Compute network, broadcast, host range, and gateway for any /N prefix
- Aggregate adjacent prefixes into the smallest covering prefix
- Plan IPv6 addressing for a site (link-local, ULA, global unicast, prefix delegation)
- Recognise the addressing failure modes that surface as routing or firewall incidents on VyOS
Prerequisites
Verified against VyOS 1.5.x LTS (circinus) · VyOS 1.4.x (sagitta) — legacy · FRRouting 10.x (VyOS 1.5) · Linux kernel 6.6 LTS (VyOS 1.5 base) · strongSwan 5.9.x (IPsec) · WireGuard 1.0.x (kernel module + userspace tooling) · 2026-08-19
Routing is the act of choosing the next hop. Choosing the next
hop requires understanding prefixes. Understanding prefixes
requires understanding CIDR. The routing engineer who has to reach
for a calculator to determine whether 192.0.2.65/26 is in the
same subnet as 192.0.2.70/26 is the routing engineer who will
make a configuration error during an outage and not notice.
This lesson is the arithmetic the routing engineer must do in their head: how CIDR notation maps to address ranges, how to plan subnets from a prefix, how IPv6’s 128-bit space changes the arithmetic, and the addressing failure modes that surface as routing or firewall incidents.
IPv4 addressing, end to end
An IPv4 address is 32 bits, conventionally written as four
dotted-decimal octets (a.b.c.d). Each octet is eight bits and
takes the value 0-255. The bits are usually grouped from left to
right, with the most significant bit of the leftmost octet being
the network portion and the least significant bit of the
rightmost octet being the host portion.
A prefix length (/N) declares how many of the leftmost bits
identify the network. The remaining 32-N bits identify the host
within that network.
flowchart LR
subgraph "192.0.2.0/26"
A["Network: 192.0.2.0\n(26 bits fixed)"] --> B["First host: 192.0.2.1"]
A --> C["Last host: 192.0.2.62"]
A --> D["Broadcast: 192.0.2.63"]
end
For 192.0.2.0/26:
| Field | Value | Calculation |
|---|---|---|
| Network address | 192.0.2.0 | lowest IP, host bits all zero |
| First usable host | 192.0.2.1 | network + 1 |
| Last usable host | 192.0.2.62 | broadcast - 1 |
| Broadcast | 192.0.2.63 | highest IP, host bits all one |
| Host count | 62 | 2^(32-26) - 2 |
| Subnet mask | 255.255.255.192 | /26 mask |
CIDR aggregation in practice
When a service provider owns 192.0.2.0/24 and advertises it to
the Internet, the BGP advertisement carries the prefix. When the
provider has eight sites and wants to advertise one summary,
they aggregate the eight sites into the smallest covering prefix.
flowchart TB
subgraph "8 sites /27 each"
S1["192.0.2.0/27"]
S2["192.0.2.32/27"]
S3["192.0.2.64/27"]
S4["192.0.2.96/27"]
S5["192.0.2.128/27"]
S6["192.0.2.160/27"]
S7["192.0.2.192/27"]
S8["192.0.2.224/27"]
end
S1 & S2 & S3 & S4 & S5 & S6 & S7 & S8 --> AGG["192.0.2.0/24\n(summary)"]
The smallest prefix that covers all eight /27s is 192.0.2.0/24.
The arithmetic is: the eight /27s are consecutive in the last
octet, the smallest prefix that has the same high bits is /24.
Equivalently, the first three octets are identical (192.0.2),
the last octet spans 0-255.
VyOS exposes this in BGP via aggregate-address. On the 1.4/1.5
tree the local ASN sits under system-as and the aggregate sits
under the address family rather than under an ASN node:
configure
set protocols bgp system-as 65000
set protocols bgp address-family ipv4-unicast aggregate-address 192.0.2.0/24 summary-only
commit
save
summary-only suppresses the contributing more-specifics, so only
the /24 leaves the router. Drop summary-only and both the /24 and
the eight /27s are advertised, which leaks the internal topology to
every peer that receives them.
One property of aggregate-address surprises operators the first
time they meet it: FRR only originates the aggregate while at least
one contributing more-specific is present in the BGP table. A
connected or static route is not in the BGP table until something —
a network statement, a redistribute, or a peer — puts it there.
So if show ip bgp 192.0.2.0/24 is empty after the commit, the
missing piece is almost always the contributor rather than the
aggregate statement.
IPv6 addressing, end to end
IPv6 addresses are 128 bits, conventionally written as eight
colon-separated groups of four hex digits. Leading zeros in a
group can be omitted; one run of consecutive all-zero groups can
be replaced by ::.
2001:0db8:85a3:0000:0000:8a2e:0370:7334 full form
2001:db8:85a3::8a2e:370:7334 compressed form
fe80::1 link-local
::1 loopback
:: unspecified
CIDR for IPv6 works exactly like CIDR for IPv4: a prefix length
declares how many bits identify the network. The host portion is
the remaining bits. There is no broadcast in IPv6 — the broadcast
role is filled by multicast to ff02::1 (all-nodes) and
ff02::2 (all-routers).
flowchart LR
subgraph "2001:db8::/48 site allocation"
A["2001:db8:0001::/48\nSite 1"] --> A1["2001:db8:1::/64\nLAN 1"]
A --> A2["2001:db8:1:1::/64\nLAN 2"]
A --> A3["2001:db8:1:2::/64\nDMZ"]
end
subgraph "Reserved"
LL["fe80::/10\nLink-local"]
ULA["fc00::/7\nULA (private)"]
MG["ff00::/8\nMulticast"]
end
The three address classes a VyOS operator handles daily:
- Global unicast (
2000::/3) — the public Internet. RIRs allocate from2001::/16and2002::/16(6to4) etc. The documentation prefix2001:db8::/32(RFC 3849) is what examples and RFCs use. - Unique local address (ULA) (
fc00::/7) — IPv6’s private address space. Randomly generated /48s, intended for site-internal use. - Link-local (
fe80::/10) — every IPv6 interface has one. The IPv6 equivalent of ARP; NDP operates over link-local. Routers do not forward link-local traffic.
Prefix delegation: ISP to customer
The common production pattern is that an ISP allocates a /48 to the customer via DHCPv6-PD, and the customer’s VyOS router subdivides that /48 across its internal subnets using SLAAC or DHCPv6.
sequenceDiagram
autonumber
participant ISP as ISP DHCPv6 server
participant C as Customer VyOS
participant LAN as LAN client
C->>ISP: Solicit to ff02::1:2 (IA_PD, prefix-length hint 48)
ISP-->>C: Advertise (offers 2001:db8:abcd::/48)
C->>ISP: Request (IA_PD)
ISP-->>C: Reply (delegates 2001:db8:abcd::/48)
Note over C: sla-id carves /64s out of the /48<br/>sla-id 1 to eth1, sla-id 2 to eth2
C->>LAN: Router Advertisement (prefix 2001:db8:abcd:1::/64)
Note over LAN: forms its own address by SLAAC<br/>from the advertised /64
LAN->>C: outbound traffic, source inside 2001:db8:abcd:1::/64
The VyOS configuration. The client runs on the WAN interface; the
pd node then hands slices of the delegated prefix to the LAN
interfaces, so the LAN addresses are not written down anywhere:
configure
set interfaces ethernet eth0 address dhcpv6
set interfaces ethernet eth0 dhcpv6-options pd 0 length 48
set interfaces ethernet eth0 dhcpv6-options pd 0 interface eth1 sla-id 1
set interfaces ethernet eth0 dhcpv6-options pd 0 interface eth1 address 1
set interfaces ethernet eth1 ipv6 router-advert prefix '2001:db8:abcd:1::/64'
set interfaces ethernet eth1 ipv6 router-advert prefix '2001:db8:abcd:1::/64' autonomous-flag 'on'
commit
save
Read the pd stanza left to right. pd 0 is the identifier of one
delegation request — a router can hold more than one. length 48 is
the prefix length asked of the server; it is a hint, and a server that
only delegates /56 will delegate a /56. interface eth1 sla-id 1
selects which /64 out of the delegated prefix lands on eth1, and
address 1 is the interface identifier VyOS gives itself inside that
/64, producing 2001:db8:abcd:1::1.
IPv4 vs IPv6: what the operator has to remember
| Concern | IPv4 | IPv6 |
|---|---|---|
| Address length | 32 bits | 128 bits |
| Notation | dotted-decimal | colon-hex |
| CIDR | yes | yes |
| Private ranges | 10/8, 172.16/12, 192.168/16 | fc00::/7 (ULA) |
| Loopback | 127.0.0.1 | ::1 |
| Anycast | rare | common (subnet-router anycast) |
| Broadcast | yes (last address in subnet) | no — replaced by multicast |
| ARP | yes | no — replaced by NDP |
| NAT | ubiquitous, often broken | discouraged, often unnecessary |
| Firewall rules | per-source IP | usually per-source subnet (prefix) |
Operational commands
Addressing is read from VyOS operational mode:
show interfaces
show interfaces ethernet eth0
show ipv6 neighbors
and, because VyOS is Debian underneath, from the shell with the
same iproute2 commands used everywhere else:
ip -br addr
ip -4 addr show dev eth0
ip -6 addr show dev eth0
For the arithmetic itself, python3 ships in the VyOS image and its
ipaddress module answers every question in this lesson:
python3 -c "import ipaddress; n = ipaddress.ip_network('192.0.2.0/24'); print(n.num_addresses)"
python3 -c "import ipaddress; print(list(ipaddress.ip_network('192.0.2.0/24').subnets(new_prefix=26)))"
python3 -c "import ipaddress; print(ipaddress.ip_address('192.0.2.65') in ipaddress.ip_network('192.0.2.64/26'))"
ipcalc and sipcalc are the more ergonomic subnet calculators, but
neither is part of the VyOS image — they belong on the workstation
where the addressing plan is written, not on the router. Plan there;
verify on the router with python3 and ip.
Validation
The diagnostic checklist when a host cannot reach another host on what should be the same subnet:
- Both hosts have addresses in the same prefix (
ip -br addr). - The prefix length is the same on both —
ip -br addrprints it, and192.0.2.65/26and192.0.2.65/24are different subnets with the same address. - The two addresses are not the same.
- Neither address is the network or broadcast address (for IPv4).
- The interface MTU accommodates the largest expected packet.
- The firewall allows the traffic in both directions.
If every check passes and traffic still does not flow, the problem is Layer 2 (neighbour resolution), and the routing engine will not be able to see it.
Cross-course references
- The Linux course’s
XIX-Linux-NetFoundationscovers the same IPv4/IPv6 model from the host perspective. - The OPNsense course covers the IPv6 firewall-specific topics, including
ip6tables-equivalent state tracking and the FreeBSD quirks that differ from Linux’snftables. - The Proxmox course covers the VM-side IPv6 including Cloud-Init’s IPv6 support and the implications of random SLAAC inside a VM.
Quiz
Knowledge check · 4 questions
Q1. A VyOS operator is given `192.0.2.0/24` and needs to create four subnets of equal size for four office sites. What is the prefix length per subnet and what are the network addresses?
You have `192.0.2.0/24` and need to split it into four equal subnets. You must use the entire prefix — no leftover address space — and each subnet must have at least 50 usable host addresses.
Q2. Which statement about IPv6 link-local addresses is correct?
Q3. DHCPv6-PD allows a customer router to receive an IPv6 prefix from an ISP and subdivide it across internal subnets.
Q4. An ISP summarises four customer /24 prefixes into one /22 for upstream advertisement. Three of the four /24s are routed through the same border router; the fourth is routed through a different border router. What is the most likely production failure?
Customer A: 198.51.100.0/24 → BR1 Customer B: 198.51.101.0/24 → BR1 Customer C: 198.51.102.0/24 → BR1 Customer D: 198.51.103.0/24 → BR2 Aggregate: 198.51.100.0/22 advertised by both BR1 and BR2.
Passing score: 75%. Answers are checked in this browser.
Production discipline
CIDR arithmetic is the foundation for everything else in this course. The routing engineer who skips the arithmetic to “save time” will burn the saved time and more on the first incident where a host cannot reach its gateway, where a BGP summary blackholes a site, where an IPv6 prefix delegation fails to subnet the way the LAN expects.
Plan the addressing once. Plan it well. Document the plan. Commit the plan to the change-management record. Then configure.