Skip to content

Ping the SID: OAM and the five failures that actually happen

S3·E2The SID that answered with an error · Customer NOC, 23:40, the night after the bridge call

S3·E2Analyze~30 minsources checked todaylab mutates hardwareverified against RFC 9259, RFC 8986, RFC 8754, RFC 9352 and RFC 8200 (rfc-editor) re-checked 2026-09-07; iproute2 ip-route.8.in and Linux seg6 sysctl docs 2026-09-07; Cumulus Linux 5.18 Segment Routing page and SONiC SRv6 HLD 2026-09-07

Builds on: L3VPN and EVPN services over SRv6, SRv6 in the Linux kernel: seg6 and seg6local

Before you read: what do you already know?

3 quick questions. Wrong answers are fine and expected; trying first makes the lesson stick.

After this lesson you can

  • Interpret the three outcomes of pinging a SID and explain why ICMP Parameter Problem Code 4 is a success signal.
  • Locate the O-flag in the SRH and state what a node does and does not do with it.
  • Diagnose the five recurring SRv6 failures from their evidence rather than from symptoms.
  • Map per-SID counters across Linux seg6local, Cumulus Linux and community SONiC to the same three questions.

Episode 2 — The SID that answered with an error

The situation · Customer NOC, 23:40, the night after the bridge call

Ninety minutes of window left and a junior engineer has typed “SRv6 is broken” into the incident channel. His evidence: he pinged a segment identifier on the endpoint and got an ICMP Parameter Problem back instead of an echo reply. The Dell SE watches the clock; everything in his promise spreadsheet is downstream of this window. The night-shift operator waits with the label maker.

You ask for the code number. It is 4. That is the best news all night, because Code 4 is SR Upper-layer Header Error, generated by the target node itself after it matched the destination address to a locally programmed SID and ran the behavior far enough to inspect the upper-layer header.[2] The SID exists. ICMPv6 is simply not a permitted upper-layer header on it, and the same section notes that operators may enable local configuration to allow it so SIDs can be pinged.[2] “Show me the counter,” says the network lead, unmoved, notebook already open.

SRv6 OAM exists so that nobody has to deploy a new protocol to answer that question. RFC 9259 describes how the existing IPv6 ping and traceroute mechanisms are used in an SRv6 network, and states plainly that ping can be used to check SID reachability and to validate that a SID is locally programmed at the target node.[1] A segment is an address, so the tools that test addresses test segments.

An ICMP error from the far end is evidence; silence is the absence of it.

The next SID in their list answers nothing at all. That is segment 1.

1Pinging a SID: three outcomes, one of which looks like a failure

RFC 9259 describes “how the existing IPv6 mechanisms for ping and traceroute can be used in an SRv6 network” and specifies the OAM flag for “controllable and predictable flow sampling from segment endpoints.”[1] Its Appendix A is the practical part: pinging an IPv6 address via a segment list, pinging a SID, traceroute via a segment list, traceroute to a SID, hybrid OAM using the O-flag, and monitoring of SRv6 paths.[1]

The sentence to internalise is that “the ping mechanism described above can also be used to perform SID reachability checks and to validate that the SID is locally programmed at the target node.”[1] That only works when the endpoint’s configuration permits ICMPv6 as an upper-layer header on that SID.[2]

Which produces three outcomes, not two:

Outcome What it proves What to do next
Echo reply The SID is programmed and ICMPv6 is permitted on it Move to the next SID in the list
ICMP Parameter Problem, Code 4 The SID is programmed; ICMPv6 is not a permitted upper-layer header Nothing. This is a pass. Record it and move on
Silence No evidence the SID exists at that node Start diagnosing here

Code 4 is “SR Upper-layer Header Error” from RFC 8986 section 4.1.1, and the same section notes that operators “may enable local configuration to allow Upper-Layer header type 58 (ICMPv6)” precisely so SIDs can be pinged.[2] A customer who reads Code 4 as a failure will spend an afternoon fixing a working endpoint.

3 segments · 96 B overhead
PE1 · Linux + FRRingress, the only node with per-flow statesource · PUSHDA fcbb:bbbb:2::1SL 2DELL · dell_sonic:4.5.1no SRv6 configuration at alltransitDA ?SL ?R2 · FRR endpointfirst segmentendpointDA ?SL ?R3 · FRR endpointsecond segmentendpointDA ?SL ?PE4 · egress PElast segment — decapsulationendpointDA ?SL ?CE · VM in vrf100the packet that was carrieddeliveredDA ?SL ?
hop 1 / 6
containerlab Linux/FRR · Full SRH

1. PE1 · Linux + FRR

SR source nodePUSH

Encapsulate: outer Destination Address = the first segment, fcbb:bbbb:2::1. The SRH carries 3 entries in reverse — Segment List[0] = fcbb:bbbb:4::100, the LAST segment of the policy.

The SR source node encapsulates: it pushes an outer IPv6 header whose Destination Address is the FIRST segment, and (for the uncompressed encodings) an SRH holding the rest. RFC 8402 calls this PUSH. The inner packet's Hop Limit is decremented once, here.

Packet state after this hop
Destination Address fcbb:bbbb:2::1
Segments Left 2
SRH Last Entry 2 · Hdr Ext Len 6 · Routing Type 4
Encapsulation overhead 96 B

FAE angle: "SR supports per-flow explicit routing while maintaining per-flow state only at the ingress nodes to the SR domain" (RFC 8402 §1). The fabric holds no policy state — that is the whole scaling argument against RSVP-TE.

sysctl -w net.ipv6.conf.all.seg6_enabled=1 net.ipv6.conf.eth1.seg6_enabled=1
ip -6 route add 2001:db8:cafe::/64 encap seg6 mode encap \
  segs fcbb:bbbb:2::1,fcbb:bbbb:3::1,fcbb:bbbb:4::100 dev eth1
# mode encap.red for the reduced SRH. segs are written in SR-policy order;
# the kernel reverses them into the Segment List.
Full SRH

H.Encaps / ip -6 route … mode encap. All n segments ride in the SRH, stored in reverse: Segment List[0] holds the LAST segment of the policy. Segments Left = n-1, Last Entry = n-1, Hdr Ext Len = 2n. Overhead 40 + 8 + 16n.

Same path, three encodings: full SRH 96 B · reduced 80 B · uSID 40 B. The IPv6 floor is 1280 octets, so this is the number the MTU conversation turns on.

Four FRR nodes around a vrnetlab/dell_sonic:4.5.1 node that is pure IPv6 transit. Three segments.

Predict the destination address after each hop before revealing it. Transit hops change nothing - that is the point.

2The O-flag, and how to write up a negative result

The O-flag sits at bit 2 of the SRH Flags octet, in a field RFC 8754 itself declares entirely unused and reserved.[1][3] Its semantics are narrow and worth quoting: it is “used as a marking bit in user packets to trigger telemetry data collection and export at the segment endpoints”, and processing inserts one step into the endpoint pseudocode — “(a) Make a copy of the packet. (b) Send the copied packet, along with a timestamp, to the OAM process for telemetry data collection and export.”[1]

Two properties make it safe to enable and useless to guess about. First, “timestamp and any other metadata are not carried in the packet forwarded to the next hop”, so the forwarded packet is byte-identical to one without OAM processing.[1] Second, “implementation of the O-flag is OPTIONAL. If a node does not support the O-flag, then it simply ignores it upon reception. If a node supports the O-flag, it can optionally advertise its potential via control plane protocol(s)” — and that advertisement is the O-flag bit in the IS-IS SRv6 Capabilities sub-TLV type 25, whose 2 octets of flags currently define nothing else.[1][4]

The RFC assumes IPFIX as the export protocol “without the loss of generality.”[1]

So when you craft an SRH with the O-flag in scapy, aim it at a Linux endpoint and nothing happens, the correct write-up is not “bug”. It is: the specification makes implementation optional and unsupporting nodes ignore the flag, this node produced no OAM output, therefore this node does not implement the O-flag. That sentence is publishable. “SRv6 OAM is broken on Linux” is not.

3The five failures that actually happen

Symptoms in an SRv6 domain are almost always the same — “it pings the underlay but the service does not work” — so triage has to run on evidence, not on symptoms. These are the five, each with the command that produces its evidence.

1. MSD advertised as zero. RFC 9352 registers four MSD types: 41 SRH Max Segments Left, 42 SRH Max End Pop, 44 SRH Max H.encaps and 45 SRH Max End D.[4] Each has the same brutal default: “if no value is advertised, the supported value is 0”, and for type 44 specifically, a zero means “the headend can apply an SR Policy that only contains one segment without inserting any SRH header.”[4] A headend computing a six-segment path against a receiver that advertised nothing produces drops at the endpoint and nothing useful in a log. Evidence: dump the IS-IS LSPs and confirm all four types are present and non-zero on every node in the path.[4]

2. MTU, with no PMTUD relief inside the domain. The arithmetic is 40 bytes of outer IPv6 plus 8 bytes of SRH base plus 16 bytes per segment, so an uncompressed three-segment encapsulation costs 96 bytes; the same path as a single uSID carrier costs 40 with no SRH at all.[3][11] IPv6 guarantees only that “every link in the Internet have an MTU of 1280 octets or greater”, which is a floor and not a budget.[9] Evidence: sweep the inner payload size until it passes, and compare against the smallest interface MTU on the path. The classic report — “it broke when I added a fourth segment” — is this, almost every time.

3. An unroutable service SID. RFC 9252 says the SRv6 Service SID SHOULD be routable within the AS of the egress PE, and it is that reachability, not the advertisement, that the ingress PE depends on.[12] FRR turns the SHOULD into a hard local rule: “in MPLS-VPN or SRv6-VPN, an L3VPN next-hop entry requires that the path chosen respectively contains a labelled path or a valid SID IPv6 address”, so the path is present and the prefix still does not install.[13] Evidence: the nexthop view on the ingress PE, covered in the previous lesson.

4. seg6_enabled left at 0. The per-interface sysctl “accept or drop SR-enabled IPv6 packets on this interface. Relevant packets are those with SRH present and DA = local”, and it defaults to 0.[6] A lab node with a perfect seg6local route silently drops everything until it is set. The practical enable line is sysctl -w net.ipv6.conf.all.seg6_enabled=1 net.ipv6.conf.default.seg6_enabled=1 net.ipv6.conf.eth1.seg6_enabled=1; whether the all knob alone is sufficient is [UNVERIFIED] against a kernel document, so set the specific interface too and test it yourself.[6] Evidence: read the sysctl on the receiving interface, not on all.

5. An unresolved uA or End.X next hop. In Linux, End.X requires SEG6_LOCAL_NH6, so a missing next hop is a configuration rejection.[10] In community SONiC it is worse because it looks healthy: “when IP NextHop doesn’t exist, SRV6_MY_SID_TABLE objects are programmed with Drop action and notify NeighOrch to resolve IP NextHop. When that NextHop is resolved, SRV6Orchagent updates SRV6_MY_SID_TABLE with valid IP NextHop handle and Forward action.”[8] The entry exists, the SID is programmed, and the action is Drop. On Cumulus, uA next-hop learning is by router advertisement, and “if the adjacent device is a non-Spectrum switch, you need to enable router advertisements on the adjacent device on the connected interface to ensure proper next hop discovery.”[7] That last one is a real interop footgun in a mixed Dell and NVIDIA rack.

SymptomBlueField-3 on a Dell Pow…SymptomSRv6: a SID is configured…SymptomPing to a SID does not an…CheckWhat exactly comes back?
Symptom

Ping to a SID does not answer

Start at the ping ladder and follow the branch your outcome selects. Each leaf names the command that produces the evidence.

4Counters as evidence, in three dialects

Every implementation answers the same three questions — how many packets hit this SID, how many bytes, how many failed — with different words.

Linux. Add count to the seg6local route. That enables “1) packets correctly processed; 2) bytes correctly processed; 3) packets that cause a processing error (i.e., missing SID List, wrong SID List, etc). To retrieve the counters … use the -s flag in the show command.”[5] The kernel names are SEG6_LOCAL_CNT_PACKETS, SEG6_LOCAL_CNT_BYTES and SEG6_LOCAL_CNT_ERRORS, where errors count “packets that have NOT been properly processed by an SRv6 Behavior instance.”[10]

Cumulus Linux. nv show router segment-routing srv6 stats gives per-SID Hit Counters as SID and Packets, plus a Drop Counters section with “Total no-sid-dropped packets”; there are also stats sid <sid> and stats no-sid-drops forms, and nv action clear router segment-routing srv6 stats to zero them.[7] Two caveats: there are no byte counters in the documented output, and “when you enable packet trimming with segment routing, Cumulus Linux counts the trimmed packet twice in the SRv6 statistics.”[7]

Community SONiC. MySID counters use the flex-counter infrastructure with a default polling interval of 10 seconds, gated on the SAI attribute capability, and the CLI is counterpoll srv6 {enable|disable|interval}, sonic-clear srv6counters, show srv6 stats and show srv6 stats <MySID>, with columns MySID, Packets and Bytes.[8]

The mapping is the useful artefact:

Question Linux Cumulus Linux Community SONiC
Packets that hit this SID count + ip -s -6 route show nv show ... srv6 stats Packets column show srv6 stats Packets column
Bytes Yes, SEG6_LOCAL_CNT_BYTES Not in the documented output Yes, Bytes column
Packets that failed the behavior SEG6_LOCAL_CNT_ERRORS No per-SID error counter documented Not documented in the base HLD
Packets for a SID that does not exist Not exposed per-SID no-sid-drops total Not documented in the base HLD

Note what the table does not say. A blank cell means the documentation fetched on 2026-09-07 does not describe that counter, not that the platform lacks it.

5Produce all three outcomes on purpose

The three-outcome ping ladder: worked, faded, problem

Setup. Three Linux endpoints in containerlab, one segment list, one host generating traffic.

Outcome 1, a clean reply. On endpoint B, program a SID and permit ICMPv6 on it, then ping the SID address from A. Expected: normal echo replies. This proves the SID is programmed and that the local policy allows ICMPv6 as an upper-layer header.[1][2]

Outcome 2, Parameter Problem Code 4. On endpoint C, program a SID with the default upper-layer policy, so ICMPv6 is not permitted on it. Ping it from A. Expected: ICMPv6 parameter problem with code 4 rather than an echo reply. Read it as: the SID exists and is programmed, ICMP is not allowed on it, nothing to fix.[2]

Outcome 3, silence. Ping an address inside the SID block that no node instantiates. Expected: no answer at all. This is the only outcome that starts an investigation.

Traceroute through the list. Run a traceroute through the three-segment list and account for each hop’s TTL source. Transit nodes are ordinary IPv6 forwarders under RFC 8754 section 3.2 and do nothing SR-specific; only the endpoints run the behavior, decrement Segments Left and rewrite the destination address.[3]

The O-flag experiment. Craft an SRH with bit 2 of the Flags octet set and send it at endpoint B.[1] Expected on Linux: the packet is processed exactly as if the flag were clear, with no OAM copy anywhere, because implementation is OPTIONAL and an unsupporting node ignores it.[1] Write that down as a dated negative result naming the kernel version.

Counters. Add count to every seg6local route, re-run each ping, and build a per-SID table from ip -s -6 route show.[5] Expected: the Code-4 SID shows non-zero packets, which is the numeric confirmation that Code 4 means processed.

Ninety minutes, and the fifth failure

How it ended

The silent SID was seg6_enabled left at 0 on the receiving interface, which defaults to 0 and drops SR-enabled packets with nothing in any log to say so.[6] The operator labels that port before anyone can argue with him. The last twenty minutes go to dumping IS-IS LSPs and confirming all four MSD types are present and non-zero, because a receiver that advertised nothing is read as zero and neither end reports anything.[4] What you say to the network lead: “Nothing here was broken. One sysctl was off, and the error your engineer escalated was proof the other endpoint works.” At 07:20 the Dell SE finds you in the hotel lobby. The customer wants one word by nine: does Dell do SRv6.

Lab

Mutating steps ahead. Needs a maintenance window, out-of-band access (BMC/iDRAC/rshim console) and a rollback path. Record the pre-flight inventory before changing anything. Never on a production host.

Pre-flight inventory (read-only). On the Dell-lab x86 host and the BlueField-3 Arm: uname -r, ip -br addr, ip -6 route show | grep seg6local, sysctl net.ipv6.conf.all.seg6_enabled, and the MTU of every interface on the intended path (ip -br link). Write the MTU list down; you are about to change one of them.

  1. Ping ladder across real hardware. Reproduce all three outcomes between the x86 host and an Arm-side endpoint. Expected: identical semantics to the containerlab run.[1][2] If not: compare seg6_enabled on the Arm’s receiving interface against the host’s.[6] Rollback: ip -6 route del <sid>/128 for every seg6local route you added on the Arm and on the host, restore any upper-layer/ICMPv6 permission you changed on a SID, re-apply the seg6_enabled values from the pre-flight capture, then diff ip -6 route show against that capture — it must match.
  2. Set an intermediate MTU. Force a 1500-byte MTU on one interface in the path with ip link set <ifname> mtu 1500. Expected: large encapsulated packets start failing. Rollback: ip link set <ifname> mtu <original> from the pre-flight list, and confirm with ip -br link.
  3. Sweep, uncompressed. Find the largest inner payload that survives a three-segment uncompressed path. Expected: the failure point sits about 96 bytes below the plain-IPv6 limit — 40 outer plus 8 SRH base plus 48 for three segments.[3]
  4. Sweep, uSID. Repeat with the same path expressed as one uSID carrier. Expected: the failure point moves up by roughly the SRH and the extra segments you removed.[11] Record both numbers; that comparison is the strongest single argument for uSID you can hand a customer.
  5. Restore. Put the MTU back, re-run one large-payload test, and confirm it passes again.
  6. Optional, customer lab only. On a Spectrum-4 running Cumulus Linux 5.14 or later, drive traffic at a SID that does not exist and read nv show router segment-routing srv6 stats no-sid-drops.[7] Read-only. Note the packet-trimming double-count caveat in your write-up if trimming is enabled on that switch.[7]

Retrieval check

10 questions from memory. Answer before looking anything up; misses become flashcards.

Explain it to a Dell SE

Explain to a Dell SE, in five sentences, why an ICMP error can be the best news you get when troubleshooting an SRv6 path.

14 flashcards for this lesson — 0 in deck. Spaced review lives at /review.

Sources

Facts in this lesson were checked against RFC 9259, RFC 8986, RFC 8754, RFC 9352 and RFC 8200 (rfc-editor) re-checked 2026-09-07; iproute2 ip-route.8.in and Linux seg6 sysctl docs 2026-09-07; Cumulus Linux 5.18 Segment Routing page and SONiC SRv6 HLD 2026-09-07. Dates are when each page was fetched.

  1. RFC 9259 — OAM in Segment Routing over IPv6 (SRv6) · fetched 2026-09-07
  2. RFC 8986 — SRv6 Network Programming · fetched 2026-09-07
  3. RFC 8754 — IPv6 Segment Routing Header (SRH) · fetched 2026-09-07
  4. RFC 9352 — IS-IS Extensions to Support Segment Routing over the IPv6 Data Plane · fetched 2026-09-07
  5. iproute2 man source: ip-route.8.in (main) · fetched 2026-09-07
  6. Linux kernel doc: Seg6 Sysfs variables · fetched 2026-09-07
  7. Segment Routing | Cumulus Linux 5.18 · fetched 2026-09-07
  8. SONiC HLD: Segment Routing over IPv6 (SRv6) · fetched 2026-09-07
  9. RFC 8200 — Internet Protocol Version 6 (IPv6) Specification · fetched 2026-09-07
  10. Linux kernel source: net/ipv6/seg6_local.c (master) · fetched 2026-09-07
  11. RFC 9800 — Compressed SRv6 Segment List Encoding · fetched 2026-09-07
  12. RFC 9252 — BGP Overlay Services Based on Segment Routing over IPv6 (SRv6) · fetched 2026-09-07
  13. FRR documentation — BGP (latest) · fetched 2026-09-07

The same idea elsewhere

Other lessons that cover this ground, sometimes from another course's angle.