Segment routing is a source-routing architecture: the ingress router encodes the entire forwarding path as an ordered list of instructions — segments — and every other router just follows them. No LDP, no RSVP-TE, no per-flow state in the core. The IGP (IS-IS or OSPF) already floods the topology, so segment routing extends it to also flood segment identifiers (SIDs), and the network forwards on those. This lab builds segment routing two ways — SR-MPLS (SIDs are MPLS labels) and SRv6 (SIDs are 128-bit IPv6 addresses) — across FRR (built-in), Nokia SR Linux (built-in), and a Cisco IOL (BYOI) node, so you can see both data planes side by side.
Bottom line: A segment routing lab means an IGP with SR extensions, a Segment Routing Global Block, prefix-SIDs on every loopback, and — for SRv6 — a locator block and micro-SID config. That's a lot to wire across vendors by hand. As of 2026, NetPilot generates and deploys this exact topology with real CLIs in ~2 minutes — grab the prompt at the bottom and adapt it for SR.
What is segment routing? (and SR-MPLS vs SRv6)
Traditional MPLS needs a separate label-distribution protocol — LDP for hop-by-hop labels, or RSVP-TE for traffic-engineered tunnels — running alongside the IGP. Segment routing deletes that protocol entirely. Instead, each router advertises its own SIDs inside the IGP, and the ingress imposes a stack of segments that steers the packet. Two kinds of segment do most of the work:
- Prefix-SID (node-SID): a globally unique label/SID for a loopback. "Get this packet to router R5" is one segment. Forwarded along the IGP shortest path via ECMP.
- Adjacency-SID: a locally significant label/SID for one specific link. Used to pin a packet onto an exact hop for traffic engineering.
Stack a few prefix-SIDs and adjacency-SIDs together and you have an explicit path — SR-TE (segment routing traffic engineering) — with zero per-flow state in the transit routers.
| SR-MPLS | SRv6 | |
|---|---|---|
| SID format | 20-bit MPLS label | 128-bit IPv6 address |
| Data plane | MPLS (label switching) | Plain IPv6 (SRH) |
| SID structure | Index into the SRGB | LOCATOR:FUNCTION:ARGUMENT |
| Needs MPLS in core | ✅ Yes | ❌ No — IPv6 only |
| Global block | SRGB (e.g. 16000–23999) | Locator block (e.g. fc00:0:N::/48) |
| Best for | Existing MPLS networks | Greenfield / IPv6-native, 5G |
The one-line difference: in SR-MPLS a SID is a label that indexes into a shared SRGB; in SRv6 a SID is a routable IPv6 address shaped as
LOCATOR:FUNCTION:ARGUMENT, so the SID itself encodes both where (locator) and what to do (function) — which is why SRv6 needs no MPLS data plane at all.
Segment routing vs MPLS is therefore slightly the wrong framing: SR-MPLS is MPLS, just with the IGP distributing labels instead of LDP/RSVP. SRv6 is the bigger departure — it drops MPLS for native IPv6 forwarding, which is why 5G transport designs lean on it.
Lab topology
A four-router IS-IS core. We run SR-MPLS on the whole fabric, then layer SRv6 on the two routers that support it.
[R1 FRR]======[R2 SR Linux]======[R3 FRR]======[R4 Cisco IOL]
1.1.1.1 2.2.2.2 3.3.3.3 4.4.4.4
prefix-SID prefix-SID prefix-SID prefix-SID
index 1 index 2 index 3 index 4
| |
| (SR-TE policy forces the long way R1->R2->R3->R4)
| |
+================ direct R1-R4 link =============+
10.0.14.x — IGP shortest path to 4.4.4.4
<-------------- IS-IS level-2, SR extensions -------------->
<-------------- SRv6 locators on R1 + R2 (uSID) ---------->The R1↔R4 direct link is the key to seeing SR-TE actually steer. Without it the chain is linear and the only path to R4 is via R2/R3 — so an SR-TE policy "via R2" would be identical to the IGP default and nothing would visibly change. With the direct link, the IGP shortest path from R1 to 4.4.4.4 is the one-hop direct link, and the SR-TE policy explicitly forces the longer R1→R2→R3→R4 path — so the label trace and traceroute genuinely differ from the default.
- IGP: IS-IS level-2 across all five links (the R1-R2-R3-R4 chain plus the direct R1-R4 link), flooding the topology and the SIDs.
- SR-MPLS: SRGB
16000–23999; prefix-SID index N maps to label16000 + N. - SR-TE: an explicit policy on R1 that forces traffic to R4 along the longer path R1→R2→R3→R4, overriding the IGP shortest path (the direct R1-R4 link), using a prefix-SID segment list.
- SRv6: locators
fcbb:bb00:1::/48(R1) andfcbb:bb00:2::/48(R2), micro-SID (uSID) flavor.
R1 — FRR (SR-MPLS)
FRR runs IS-IS with segment routing natively. The loopback carries the prefix-SID; MPLS forwarding has to be enabled on the kernel data plane interfaces.
interface lo
ip address 1.1.1.1/32
ip router isis CORE
!
interface eth1
description to R2
ip address 10.0.12.1/24
ip router isis CORE
isis network point-to-point
mpls enable
!
interface eth2
description direct to R4 (IGP shortest path)
ip address 10.0.14.1/24
ip router isis CORE
isis network point-to-point
mpls enable
!
router isis CORE
net 49.0001.0000.0000.0001.00
is-type level-2-only
segment-routing on
segment-routing global-block 16000 23999
segment-routing prefix 1.1.1.1/32 index 1segment-routing global-block 16000 23999defines the SRGB; it must match on every node so a given index resolves to the same label fabric-wide.segment-routing prefix 1.1.1.1/32 index 1advertises R1's node-SID. Any router can now reach R1 by pushing label16001.mpls enableon each transit interface lets FRR program MPLS label operations into the Linux data plane — forget it and the SIDs flood but nothing forwards.eth2is the direct R1↔R4 link (10.0.14.x) — also enrolled in IS-IS and MPLS/SR. Because it is a single hop, IS-IS makes it R1's shortest path to4.4.4.4, which is exactly what the SR-TE policy below will override.
R2 — Nokia SR Linux (SR-MPLS)
SR Linux is built-in and speaks IS-IS with SR. The SRGB is bound to an MPLS label range, then SR is enabled per IS-IS instance.
set / interface ethernet-1/1 admin-state enable
set / interface ethernet-1/1 subinterface 0 admin-state enable
set / interface ethernet-1/1 subinterface 0 ipv4 address 10.0.12.2/24
set / interface ethernet-1/2 admin-state enable
set / interface ethernet-1/2 subinterface 0 admin-state enable
set / interface ethernet-1/2 subinterface 0 ipv4 address 10.0.23.2/24
set / interface system0 admin-state enable
set / interface system0 subinterface 0 admin-state enable
set / interface system0 subinterface 0 ipv4 address 2.2.2.2/32
set / network-instance default interface ethernet-1/1.0
set / network-instance default interface ethernet-1/2.0
set / network-instance default interface system0.0
set / network-instance default segment-routing mpls label-blocks static SRGB start-label 16000 end-label 23999
set / network-instance default protocols isis instance CORE level-capability L2
set / network-instance default protocols isis instance CORE net [ 49.0001.0000.0000.0002.00 ]
set / network-instance default protocols isis instance CORE interface ethernet-1/1.0 circuit-type point-to-point
set / network-instance default protocols isis instance CORE interface ethernet-1/2.0 circuit-type point-to-point
set / network-instance default protocols isis instance CORE interface system0.0 passive true
set / network-instance default protocols isis instance CORE segment-routing mpls status enable
set / network-instance default protocols isis instance CORE segment-routing mpls label-blocks [ SRGB ]
set / network-instance default protocols isis instance CORE ipv4-unicast prefix-sid-index 2 prefix system0.0- The
label-blocks static SRGB(16000–23999) is the same range as R1 — that consistency is the whole point of a global block. prefix-sid-index 2ties R2'ssystem0loopback to node-SID index 2, i.e. label16002.- R2 has two core links:
ethernet-1/1toward R1 (10.0.12.2/24) andethernet-1/2toward R3 (10.0.23.2/24) — both run IS-IS so the fabric stays contiguous R1→R2→R3→R4. - SR Linux keeps SR config under the IS-IS instance, where FRR splits it across
router isisand interface stanzas — exactly the per-vendor naming the agent normalizes for you.
R3 — FRR (SR-MPLS)
R3 sits in the middle of the fabric, so it carries two core links — one back to R2, one forward to R4. Same FRR/IS-IS/SR pattern as R1, just with both transit interfaces in the IGP and MPLS enabled on each.
interface lo
ip address 3.3.3.3/32
ip router isis CORE
!
interface eth1
description to R2
ip address 10.0.23.3/24
ip router isis CORE
isis network point-to-point
mpls enable
!
interface eth2
description to R4
ip address 10.0.34.3/24
ip router isis CORE
isis network point-to-point
mpls enable
!
router isis CORE
net 49.0001.0000.0000.0003.00
is-type level-2-only
segment-routing on
segment-routing global-block 16000 23999
segment-routing prefix 3.3.3.3/32 index 3- The same SRGB
16000 23999as every other node — index 3 resolves to label16003fabric-wide. segment-routing prefix 3.3.3.3/32 index 3advertises R3's node-SID; any router reaches R3 by pushing16003.- Both transit interfaces (
eth1to R2 on10.0.23.x,eth2to R4 on10.0.34.x) run IS-IS andmpls enable— R3 is the transit hop that swaps labels for traffic crossing the core, so missingmpls enablehere silently black-holes the R1→R4 path.
R4 — Cisco IOL (SR-MPLS)
interface Loopback0
ip address 4.4.4.4 255.255.255.255
ip router isis CORE
!
interface Ethernet0/0
description to R3
ip address 10.0.34.4 255.255.255.0
ip router isis CORE
isis network point-to-point
!
interface Ethernet0/1
description direct to R1 (IGP shortest path)
ip address 10.0.14.4 255.255.255.0
ip router isis CORE
isis network point-to-point
!
router isis CORE
net 49.0001.0000.0000.0004.00
is-type level-2-only
metric-style wide
segment-routing mpls
connected-prefix-sid-map
address-family ipv4
4.4.4.4/32 index 4 range 1
!
segment-routing mpls
global-block 16000 23999metric-style wideis required — IS-IS SR extensions ride in wide-metric TLVs; narrow metrics silently drop the SID sub-TLVs.- The global SRGB lives in the top-level
segment-routing mplsblock; the per-prefix index is mapped under the IS-IS instance viaconnected-prefix-sid-map. - Index 4 → label
16004, reachable from every other node along the IS-IS shortest path. Ethernet0/1is the direct R1↔R4 link (10.0.14.x), in IS-IS and MPLS/SR. With equal link metrics this single hop is the IGP shortest path between R1 and R4 — so by default R1 reaches4.4.4.4straight across it, and traffic only takes the R2/R3 chain when the SR-TE policy forces it.
Why multi-vendor matters here: the concept (SRGB 16000–23999, prefix-SID index N) is identical on all three, but FRR, SR Linux, and IOS each express it in different stanzas. Describe it once in plain English and the agent emits the correct syntax per box — that's the moat single-vendor docs can't cover.
Verify SR-MPLS
Lead with the agent — one prompt walks the SR control plane across every vendor and translates each show for you:
"Verify SR-MPLS across all four routers: IS-IS adjacencies up, the SRGB is consistent, every loopback has a prefix-SID, and the MPLS label forwarding table has the SR labels (16001–16004). Flag any node missing a SID."
NetPilot runs the right command per device in parallel — FRR's vtysh-wrapped show, SR Linux's show syntax, IOS' show mpls forwarding-table — and returns a consolidated table with anomalies flagged. Direct CLI is always available too — SSH into any router and check by hand:
# R1 (FRR) — drop into vtysh
vtysh -c "show isis segment-routing prefix-sids"
vtysh -c "show mpls table"
vtysh -c "show isis neighbor"! R4 (Cisco IOL)
show isis segment-routing label-table
show mpls forwarding-table
show ip route isisExpected: IS-IS level-2 adjacencies up on every link, and an MPLS forwarding entry where label 16004 (R4's node-SID) resolves toward R4. A packet labeled 16004 injected at R1 follows the IS-IS shortest path — which, thanks to the direct R1-R4 link, is the single-hop direct path (label popped at R1 via PHP, delivered straight to R4) — with no LDP anywhere in the box. Hold onto that default: the SR-TE policy below deliberately steers off it.
Add an SR-TE policy
Default SR forwarding follows the IGP shortest path — and here that default is the direct R1→R4 link (10.0.14.x), one hop to 4.4.4.4. SR-TE pins an explicit path instead, with a segment list. We force R1→R4 traffic off the direct link and onto the longer chain R1→R2→R3→R4 — a stack of node (prefix) SIDs, one per hop.
! R1 (FRR) — an SR-TE policy to R4 (4.4.4.4) steered the long way via R2 and R3
segment-routing
traffic-eng
segment-list VIA_R2_R3
index 10 mpls label 16002
index 20 mpls label 16003
index 30 mpls label 16004
policy color 100 endpoint 4.4.4.4
candidate-path preference 100 name LONG_PATH explicit segment-list VIA_R2_R3- The segment list says: first reach R2 (
16002), then R3 (16003), then R4 (16004). Each hop is adjacent to the last, so each prefix-SID resolves over one physical link: R1→R2, R2→R3, R3→R4. That deliberately walks the packet down the chain instead of taking the direct R1-R4 link the IGP would pick. - Why all three SIDs? Without the
16002/16003steers, a bare16004would just follow the IGP shortest path — straight across the direct link — and the policy would change nothing. Pushing R2 then R3 first is what pins traffic onto the long path. Each pop happens at the owning node (R2 pops16002, R3 pops16003, R4 pops16004via PHP), so the next SID surfaces exactly where it should. policy color 100 endpoint 4.4.4.4is the SR-TE policy key — itsendpointis the destination (R4's4.4.4.4, from R1's headend perspective), and any traffic colored 100 toward that endpoint binds to this policy. The explicitcandidate-paththen names theVIA_R2_R3segment list as the path to install.- For a strict link-pinned path you'd swap these node-SIDs for adjacency-SIDs (locally significant, one per link); list the adjacency-SIDs of the exact links to traverse. On this topology the node-SID chain already diverges from the IGP default, which is all we need to see the steer.
"Add an SR-TE policy on R1 that steers traffic to R4 the long way through R2 and R3, then prove the path changed versus the IGP default (the direct R1-R4 link)."
The agent builds the policy, activates it, and runs a traceroute/label trace before and after so you can see the path move — the default hops straight R1→R4 over 10.0.14.x, while the steered path now shows R1→R2→R3→R4 with the 16002/16003/16004 label stack. To check the active path by hand:
# R1 (FRR)
vtysh -c "show sr-te policy"
vtysh -c "show mpls table"Add SRv6 (locators + micro-SIDs)
Now the IPv6 data plane. SRv6 replaces the MPLS label stack with an IPv6 Segment Routing Header (SRH) carrying a list of 128-bit SIDs. Each SID is LOCATOR:FUNCTION:ARGUMENT:
- Locator — a routable IPv6 prefix that gets the packet to the owning node (advertised in IS-IS like any prefix).
- Function — the behavior to run on arrival (
End= forward to next SID,End.DT4= decapsulate into an IPv4 VRF, etc.). - Argument — optional, used by some functions.
Micro-SIDs (uSID) compress several SIDs into one 128-bit address so a long path fits in a single IPv6 destination address — fewer bytes on the wire, simpler hardware. The block (e.g. fcbb:bb00::/32) carries a sequence of 16-bit uSIDs.
! R1 (FRR) — SRv6 with a uSID-style locator
interface lo
ipv6 address fcbb:bb00:1::1/128
!
router isis CORE
segment-routing srv6
locator MAIN
!
segment-routing srv6
locators
locator MAIN
prefix fcbb:bb00:1::/48! R2 (Nokia SR Linux) — SRv6 locator under the network-instance
set / interface system0 subinterface 0 ipv6 address fcbb:bb00:2::1/128
set / network-instance default segment-routing v6 locators locator MAIN prefix fcbb:bb00:2::/48
set / network-instance default protocols isis instance CORE segment-routing v6 locators locator MAIN- R1 owns
fcbb:bb00:1::/48, R2 ownsfcbb:bb00:2::/48— both share thefcbb:bb00::/32uSID block, so the high bits identify the block and the next 16 bits select the node. - IS-IS floods each locator as a routable IPv6 prefix; reaching a SID is just IPv6 routing to its locator — no MPLS anywhere.
- An SRv6 packet from R1 to R2 carries destination
fcbb:bb00:2:e000::(R2'sEnduSID), and R2 runs theEndbehavior to forward to the next SID in the list.
Verify SRv6
"Verify SRv6 on R1 and R2: each locator is advertised in IS-IS, both nodes have installed each other's locator as an IPv6 route, and the SRv6 SID table lists the End function. Confirm an IPv6 ping between loopbacks works."
The agent checks the locator advertisement, the IPv6 RIB, and the local SID table on both nodes, then runs the ping — aggregating two different vendor syntaxes into one report. By hand:
# R1 (FRR)
vtysh -c "show segment-routing srv6 locator"
vtysh -c "show ipv6 route isis"
ping fcbb:bb00:2::1 source fcbb:bb00:1::1Expected: R2's locator fcbb:bb00:2::/48 in R1's IPv6 route table (via IS-IS), R1's local SID table showing the MAIN locator with the End behavior, and a successful loopback-to-loopback IPv6 ping carried natively — no label stack at all.
Common segment routing gotchas
- SRGB mismatch. If one node uses
16000–23999and another100000–199999, prefix-SID indices still match but the resulting labels don't — forwarding breaks at the boundary. Keep the SRGB identical fabric-wide. - Narrow IS-IS metrics. SR sub-TLVs ride in wide-metric TLVs. Without
metric-style wide(Cisco) or the equivalent, SIDs flood but never install. - MPLS data plane not enabled. On FRR you need
mpls enableper interface; the control plane can be perfect while the kernel drops every labeled packet. - Locator not advertised. In SRv6, if the locator prefix isn't redistributed into IS-IS, remote nodes can't route to the SID — the SID table looks fine locally but is unreachable.
- uSID block vs locator confusion. The uSID block (
/32) is shared; each node's locator (/48) is unique within it. Mixing the two is the SRv6 equivalent of the SR-MPLS index-vs-label slip.
Build this lab with AI
Skip the four-router IS-IS + SR wiring and describe the fabric:
"Build a multi-vendor segment routing lab. Four IS-IS level-2 routers — R1 and R3 on FRR, R2 on Nokia SR Linux, R4 on Cisco IOL — in a chain R1-R2-R3-R4 plus a direct R1-R4 link (subnet 10.0.14.x in IS-IS and MPLS/SR). Enable SR-MPLS with SRGB 16000–23999 and a prefix-SID per loopback (index 1–4). Add an SR-TE policy on R1 that steers traffic to R4 the long way via R2 and R3 (prefix-SID list 16002, 16003, 16004), overriding the IGP default of the direct R1-R4 link. Then layer SRv6 with uSID locators on R1 and R2. Verify the SR label table, that the SR-TE path differs from the IGP shortest path, and an SRv6 IPv6 ping."
NetPilot generates the IS-IS core, the per-vendor SR config, the SR-TE policy, and the SRv6 locators, deploys to cloud ContainerLab, and confirms the label and SID forwarding — then you SSH in and trace a segment list yourself. For the underlying MP-BGP and label mechanics, see the MPLS L3VPN lab; for the FRR data-plane details, the FRRouting cloud guide; and for the IGP/BGP multi-vendor baseline, the multi-vendor BGP lab.
Copy-paste ready: Grab the Segment Routing (SR-MPLS) prompt from our example library — prefix-SIDs and an SR-TE policy included — or the SRv6 prompt for the uSID variant.
Want to lab segment routing without the setup? Run it in an online network lab, or let the AI network emulator generate the SR-MPLS and SRv6 configs from a prompt. Try NetPilot — describe any SR or SRv6 topology and get a working multi-vendor lab in ~2 minutes.