Overlays and multicast, walked field by field: MPLS L3VPN, IPv6, EVPN/VXLAN, PIM.
A continuation of the field-by-field walkthrough. Same rules: at every hop write down what changes, what stays, and why. The principle tying all five scenarios below together:
As soon as encapsulation appears (MPLS, VXLAN), you get two independent forwarding layers. The outer layer lives PE-to-PE (or VTEP-to-VTEP) and is handled by transit nodes. The inner layer doesn't change at all and only "wakes up" at the egress. A transit node physically never looks inside.
CE1 ── SW1 ── PE1 ══ P1 ══ P2 ══ PE2 ── SW2 ── CE2
access dot1q IS-IS / MPLS / MP-BGP dot1q access
VLAN100 VLAN100
CE1: 192.168.10.1 network behind CE2: 192.168.20.0/24
PE1: sub-if .100 = 192.168.10.254, VRF CUST-A, loopback 10.0.0.1
PE2: sub-if .100 = 192.168.20.254, VRF CUST-A, loopback 10.0.0.2
RD 65000:100, RT 65000:100
This is the first thing to separate out loud, or the answer turns to mush:
| Protocol | What it does |
|---|---|
| IS-IS | reachability of the PE and P loopbacks inside the core; it knows only the infrastructure and is unaware of customers |
| LDP / SR-MPLS | transport label to PE2's loopback (in SR the label = prefix-SID, distributed by IS-IS itself, no separate protocol needed) |
| MP-BGP (VPNv4) | customer prefixes with RD, RT and a service label; the session runs only between PEs, the core knows nothing about it |
The key idea: P routers hold not a single customer route. They switch on the outer label. That is the whole point of the model: the core does not scale with the number of customers.
192.168.20.0/24 from CE2 in VRF CUST-A.65000:100:192.168.20.0/24,
attaches RT 65000:100 and assigns a VPN label (e.g. 24002).10.0.0.2 (PE2's loopback).10.0.0.2 and takes the transport label for it (e.g. 16002).The RD makes the prefix unique (different customers may use the same 192.168.10.0/24),
the RT controls import/export. People confuse them constantly — separate them explicitly.
CE1 → SW1 → PE1 — ordinary L3 traffic; on the trunk a tag appears:
| Field | Value |
|---|---|
| DST MAC | MAC of PE1's sub-interface |
| 802.1Q | VID 100 |
| SRC IP / DST IP | 192.168.10.1 / 192.168.20.5 |
| TTL | 64 |
PE1 → P1 — the main event: a push of two labels:
| Field | Value |
|---|---|
| DST MAC / SRC MAC | MAC of P1 / MAC of PE1 |
| EtherType | 0x8847 (MPLS unicast) |
| Outer label (transport) | 16002, S=0, TTL=255 |
| Inner label (VPN) | 24002, S=1, TTL=255 |
| Inner IP | 192.168.10.1 → 192.168.20.5, TTL 63 |
The S (Bottom of Stack) bit = 1 on the last label — that's how a node knows where the stack ends. Each label is exactly 4 bytes.
P1 → P2 — swap of the outer label (e.g. 16002 → another local index); the inner label is neither touched nor examined, the IP header is not inspected at all, the label TTL is decremented.
P2 → PE2 — PHP (Penultimate Hop Popping): PE2 advertised implicit-null (label 3), so the penultimate node pops the transport label. Only the VPN-labeled packet goes onto the link:
| Field | Value |
|---|---|
| Label | 24002, S=1 |
| IP | unchanged, TTL 63 |
The point of PHP: PE2 shouldn't do a double lookup (pop a label, then another) — it saves an operation on the egress node.
PE2 → SW2 → CE2 — the VPN label is popped, its value points directly at the VRF (or at a specific next-hop, depending on the allocation mode), a lookup is done in VRF CUST-A, a new L2 header is built, VLAN 100 tag, TTL −1.
| Hop | Encapsulation | Labels | Inner IP TTL |
|---|---|---|---|
| CE1 → PE1 | Eth + dot1q | — | 64 |
| PE1 → P1 | Eth + MPLS×2 | 16002 / 24002 | 63 |
| P1 → P2 | Eth + MPLS×2 | swap / 24002 | 63 |
| P2 → PE2 | Eth + MPLS×1 | 24002 (PHP) | 63 |
| PE2 → CE2 | Eth + dot1q | — | 62 |
Note: the inner TTL decreased only twice — at the ingress and egress PE. To the customer, the core looks like a single hop.
H1 ─── Leaf1 ═══ Spine ═══ Leaf2 ─── H2
2001:db8:0:10::11/64 2001:db8:0:20::22/64
Links between Leaf and Spine are either /127 or fully unnumbered (BGP over link-local).
| Aspect | IPv4 | IPv6 |
|---|---|---|
| Neighbor resolution | ARP (broadcast) | NDP: NS/NA over ICMPv6 to multicast |
| Default gateway | DHCP / static | RA (Router Advertisement), usually a link-local address |
| Header checksum | present, recomputed each hop | absent |
| TTL | TTL | Hop Limit (same logic) |
| Fragmentation in transit | possible | forbidden, source-only after PMTUD |
| Broadcast | yes | no, multicast only |
Dropping the header checksum was deliberate: L2 (FCS) and L4 already compute one, and recomputing at every hop was pure wasted work.
Instead of broadcast ARP — a Neighbor Solicitation to the
solicited-node multicast address ff02::1:ff + the low 24 bits of the target:
| Field | Value |
|---|---|
| DST MAC | 33:33:ff:00:00:22 (33:33 + low 32 bits of the group) |
| DST IPv6 | ff02::1:ff00:22 |
| SRC IPv6 | sender's link-local (fe80::…) |
| ICMPv6 type | 135 (NS), reply 136 (NA) |
The gain: the frame reaches essentially only the target node, not the whole segment — everyone else's NIC filters it by MAC. It's a "smart ARP."
The IPv6 next-hop is almost always a link-local address (fe80::…),
even for global prefixes. Hence:
| Hop | DST MAC | SRC IPv6 | DST IPv6 | Hop Limit |
|---|---|---|---|---|
| H1 → Leaf1 | MAC Leaf1 (learned via RA/NDP) | 2001:db8:0:10::11 | 2001:db8:0:20::22 | 64 |
| Leaf1 → Spine | MAC Spine | unchanged | unchanged | 63 |
| Spine → Leaf2 | MAC Leaf2 | unchanged | unchanged | 62 |
| Leaf2 → H2 | MAC H2 | unchanged | unchanged | 61 |
Same logic as IPv4: L2 is rewritten, L3 doesn't change. The differences are the resolution
mechanics, the absence of a checksum recompute, and that fe80::… as next-hop never
appears in the packet itself — it only decides which MAC to use.
/64 per segment is an enormous space; scanning
floods the neighbor table. Mitigated by limits, ND suppression and sane segment sizing./127 on p2p links (RFC 6164) — the direct analog of /31.H1 ─── Leaf1 ═══ Spine ═══ Leaf2 ─── H2
10.0.10.11/24 (underlay: loopbacks and IP only) 10.0.20.22/24
VNI 10010 VTEP1 = 10.255.0.1 VTEP2 = 10.255.0.2 VNI 10020
L3VNI 50000, VRF TENANT-A
We walk inter-subnet traffic (symmetric IRB) — the most instructive case.
H1 sees that 10.0.20.22 is in a different subnet → sends to the gateway MAC. The
gateway is an anycast gateway: the same IP and MAC (00:00:5e:00:01:01 or
vendor-specific) on every leaf. The host never notices moves and never reconfigures.
The ARP for the gateway likely won't even leave the leaf: ARP suppression — the leaf answers itself, knowing the mapping from EVPN Type-2.
10.0.20.0/24 learned from EVPN Type-5 (or Type-2
with IP), next-hop = VTEP2 10.255.0.2, label = L3VNI 50000.| Layer | Field | Value |
|---|---|---|
| Outer Eth | DST/SRC MAC | MAC Spine / MAC Leaf1 |
| Outer IP | SRC → DST | 10.255.0.1 → 10.255.0.2 (VTEP loopbacks) |
| TTL | 64 (its own, independent) | |
| UDP | SRC port | hash of inner fields — entropy for ECMP |
| DST port | 4789 | |
| VXLAN | VNI | 50000 (L3VNI) |
| Inner Eth | DST/SRC MAC | Leaf2 router MAC / Leaf1 router MAC |
| Inner IP | SRC → DST | 10.0.10.11 → 10.0.20.22, TTL 63 |
Overhead: +50 bytes (14 + 20 + 8 + 8). Hence an underlay MTU of 9216 or at least 1550.
The Spine is an ordinary IP router. It:
10.255.0.2), does a lookup, TTL−1 on the outer header;This is the central architectural point of EVPN/VXLAN: the spine holds no tenant state. Just like a P router in the MPLS scenario.
10.0.20.22 is a local host.Result: the customer TTL decreased twice — at the ingress and egress leaf. To the host the fabric looks like a single router, no matter how many spines. A full analogy with L3VPN.
S 10.1.1.10 ── FHR ══ R2(RP 10.255.0.9) ══ LHR ── Receiver 10.2.2.20
group G = 239.1.1.1
The destination MAC is computed deterministically from the group address:
01:00:5e + the low 23 bits of the group IP.
239.1.1.1 → 01:00:5e:01:01:01
An important consequence people like to ask about: the high bit of the fourth octet is lost, so
32 different groups map to one MAC (e.g. 239.1.1.1 and
239.129.1.1). The host receives the extra traffic and drops it at the IP layer — i.e. it burns CPU.
Phase 1 — source registration. The FHR receives the first packet from S, encapsulates it in a PIM Register (unicast, IP protocol 103) and sends it to the RP. If there are no receivers, the RP immediately replies with Register-Stop.
Phase 2 — shared tree (RPT). The receiver sends an IGMP Report to the
LHR. The LHR sends a PIM (*,G) Join toward the RP (along the unicast route
to the RP), and each node on the path creates a (*, G) entry with an outgoing interface list
(OIL). Traffic flows S → FHR → RP → LHR → receiver.
Phase 3 — switch to the shortest path (SPT switchover). From the arriving packets the LHR learns S's real address and sends an (S,G) Join toward the source. Once the tree is built, the LHR sends an (S,G,rpt) Prune toward the RP, and the RP sends Register-Stop to the FHR. Traffic flows directly S → LHR.
| Field | Along the whole path |
|---|---|
| DST MAC | 01:00:5e:01:01:01 — unchanged, computed from the group |
| SRC MAC | MAC of the current egress interface — changes at every hop |
| SRC IP | 10.1.1.10 — the source's unicast address, unchanged |
| DST IP | 239.1.1.1 — unchanged |
| TTL | −1 at every router |
Two differences from unicast to call out:
S 10.1.1.10 ── R1 ══ R2 ══ LHR ── Receiver
group G = 232.1.1.1 (SSM range: 232.0.0.0/8)
The receiver knows the source address in advance (from app config, the feed spec, DNS). Therefore:
(S,G) Join along the RPF path to the source;After the tree is built, forwarding is identical to Scenario G: the same computed multicast MAC, the same unchanged source SRC IP, the same OIL replication, the same RPF check, TTL−1 per hop.
The whole difference is in the control plane, and that's exactly how to phrase it.
232.1.1.1 → the same 01:00:5e:01:01:01: the MAC overlap hasn't gone anywhere, you still have to plan group addresses carefully.
The list to be able to rattle off:
| PIM-SM | PIM-SSM | |
|---|---|---|
| RP | needed | not needed |
| Tree | (*,G), then (S,G) | immediately (S,G) |
| IGMP | v2 is enough | v3 required |
| Register/Register-Stop | yes | no |
| Range | 224/4, usually 239/8 | 232/8 |
| Source | discovered by the network | known to the application |
| Use | enterprise, many-to-many | market data, IPTV, one-to-many |
Notice the recurring pattern — the best note to end on:
| Scenario | Outer layer (who looks at it) | Inner layer |
|---|---|---|
| L3VPN | MPLS label, examined by P routers | customer IP, TTL−1 only at the PE |
| EVPN/VXLAN | outer VTEP→VTEP IP, examined by the spine | customer frame/IP, TTL−1 only at the leaf |
| Multicast | — (no encapsulation) | tree forwarding, RPF instead of a DST lookup |
In both MPLS and VXLAN the same architectural principle holds: tenant state lives only at the edge, the core stays dumb and scalable. Say this as your conclusion and the walkthrough turns from a list of fields into a demonstration of architectural understanding.