Skip to content

Support for ISIS SRv6 as per RFC9352 - #483

Open
SuryyaKrJana wants to merge 9 commits into
masterfrom
isis-srv6-review
Open

Support for ISIS SRv6 as per RFC9352#483
SuryyaKrJana wants to merge 9 commits into
masterfrom
isis-srv6-review

Conversation

@SuryyaKrJana

@SuryyaKrJana SuryyaKrJana commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Feature Overview

  • Related Issue: (e.g., Fixes #<issue_number>)
  • Brief Description:
    Support of ISIS SRv6 Capabilities, Node SIDs and Adjacency SIDs in OTG-Model and Snappi-IxNetwork

Feature Details

  • Redocly docs for this feature

  • New Locations/Nomenclature:

  • ISIS SRv6 Reference: RFC 9352
    isis.segment_routing.
    isis.interfaces.srv6_adjacency_sids

  • Dev-Snappi branch reference

  • Example command to fetch the dev-snappi branch:

    go get github.com/open-traffic-generator/snappi/gosnappi@<isis-srv6-review>
    

Code snippets

Control plane:
r1 (Port 1): locator fc00:0:1::/48, End SID fc00:0:1:1:: (behavior=End, code=1)
r2 (Port 2): locator fc00:0:2::/48, End SID fc00:0:2:1:: (behavior=End, code=1)
Both adjacencies (r1↔DUT, r2↔DUT) must form; DUT re-floods LSPs.
Wire: r1's LSP (re-flooded by DUT) and r2's own LSP both captured on p2.

Data plane (device-based, via DUT):
tx=d1_v6, rx=d2_v6 — IxN resolves DUT MAC via NDP automatically
Outer IPv6 src=2001:0:1::1 dst=fc00:0:10:1:: (DUT End SID) nh=43
SRH: routing_type=4, segments_left=1, last_entry=1
seg[0]=fc00:0:2:1:: seg[1]=fc00:0:10:1::
Inner: IPv4 TCP src=10.1.1.1 dst=10.2.2.2 sport=1234 dport=80
DUT End processing: sl 1→0, outer dst→fc00:0:2:1::, forwarded to p2.

 # ---- Devices and Ethernet ------------------------------------------------
# p1 and p2 face DIFFERENT DUT interfaces — each is on its own /64 subnet.
    # d1 (p1 side): IxN=2001:0:1::1, DUT port-1=2001:0:1::2
    # d2 (p2 side): IxN=2001:0:2::1, DUT port-2=2001:0:2::2
    DUT_END_SID     = "fc00:0:10:1::"      # DUT End SID — update to match DUT IS-IS SRv6 config.
    d1_eth                      = d1.ethernets.add()
    d1_eth.name                 = "d1_eth"
    d1_eth.connection.port_name = p1.name
    d1_eth.mac                  = "00:00:00:01:01:01"
    d1_v6         = d1_eth.ipv6_addresses.add()
    d1_v6.name    = "d1_ipv6"
    d1_v6.address = "2001:0:1::1"   # IxN port-1 address
    d1_v6.gateway = "2001:0:1::2"   # DUT interface connected to port 1
    d1_v6.prefix  = 64

    d2_eth                      = d2.ethernets.add()
    d2_eth.name                 = "d2_eth"
    d2_eth.connection.port_name = p2.name
    d2_eth.mac                  = "00:00:00:02:02:02"
    d2_v6         = d2_eth.ipv6_addresses.add()
    d2_v6.name    = "d2_ipv6"
    d2_v6.address = "2001:0:2::1"   # IxN port-2 address
    d2_v6.gateway = "2001:0:2::2"   # DUT interface connected to port 2
    d2_v6.prefix  = 64

    # ---- IS-IS router r1 — Port 1 ↔ DUT -------------------------------------
    r1                              = d1.isis
    r1.name                         = "r1"
    r1.system_id                    = "650000000001"
    r1.advanced.area_addresses      = ["490001"]
   
    r1_intf                                          = r1.interfaces.add()
    r1_intf.eth_name                                 = "d1_eth"
    r1_intf.name                                     = "r1_intf"
    r1_intf.network_type                             = "point_to_point"
    r1_intf.level_type                               = "level_2"
   
    r1.segment_routing.router_capability.srv6_capability.c_flag = True
    r1_loc                                              = r1.segment_routing.srv6_locators.add()
    r1_loc.locator_name                                 = "loc1"
    r1_loc.locator                                      = "fc00:0:1::"
    r1_loc.prefix_length                                = 48
    r1_loc.algorithm                                    = 0
    r1_loc.metric                                       = 10
    r1_loc.d_flag                                       = False
    r1_loc.sid_structure.locator_block_length           = 32
    r1_loc.sid_structure.locator_node_length            = 16
    r1_loc.sid_structure.function_length                = 16
    r1_loc.sid_structure.argument_length                = 0
    r1_loc.advertise_locator_as_prefix.route_metric     = 10
    r1_loc.advertise_locator_as_prefix.redistribution_type = "up"
    r1_loc.advertise_locator_as_prefix.route_origin    = "internal"

    r1_sid                    = r1_loc.end_sids.add()   # fc00:0:1:1:: End (code 1)
    r1_sid.function           = "0001"
    r1_sid.argument           = "0000"
    r1_sid.endpoint_behavior  = "end"
    r1_sid.c_flag             = True

    r1_routes         = r1.v6_routes.add()
    r1_routes.name    = "r1_v6_routes"
    r1_addr           = r1_routes.addresses.add()
    r1_addr.address   = "fd00:0:1::1"
    r1_addr.prefix    = 64
    r1_addr.count     = 1

    # ---- IS-IS router r2 — Port 2 ↔ DUT -------------------------------------
    r2                              = d2.isis
    r2.name                         = "r2"
    r2.system_id                    = "650000000002"
    r2.advanced.area_addresses      = ["490001"]
   
    r2_intf                                          = r2.interfaces.add()
    r2_intf.eth_name                                 = "d2_eth"
    r2_intf.name                                     = "r2_intf"
    r2_intf.network_type                             = "point_to_point"
    r2_intf.level_type                               = "level_2"

    r2.segment_routing.router_capability.srv6_capability.c_flag = True
    r2_loc                                            = r2.segment_routing.srv6_locators.add()
    r2_loc.locator_name                      = "loc2"
    r2_loc.locator                                 = "fc00:0:2::"
    r2_loc.prefix_length                                = 48
    r2_loc.algorithm                                    = 0
    r2_loc.metric                                       = 10
    r2_loc.d_flag                                       = False
    r2_loc.sid_structure.locator_block_length           = 32
    r2_loc.sid_structure.locator_node_length            = 16
    r2_loc.sid_structure.function_length                = 16
    r2_loc.sid_structure.argument_length                = 0
    r2_loc.advertise_locator_as_prefix.route_metric     = 10
    r2_loc.advertise_locator_as_prefix.redistribution_type = "up"
    r2_loc.advertise_locator_as_prefix.route_origin    = "internal"

    r2_sid                    = r2_loc.end_sids.add()   # fc00:0:2:1:: End (code 1)
    r2_sid.function           = "0001"
    r2_sid.argument           = "0000"
    r2_sid.endpoint_behavior  = "end"
    r2_sid.c_flag             = True

    r2_routes         = r2.v6_routes.add()
    r2_routes.name    = "r2_v6_routes"
    r2_addr           = r2_routes.addresses.add()
    r2_addr.address   = "fd00:0:2::1"
    r2_addr.prefix    = 64
    r2_addr.count     = 1

    # ---- SRH device-based flow: d1 → DUT → d2 ----------------------------------
    # tx=d1_v6 / rx=d2_v6: IxN resolves the DUT's MAC via NDP (no hardcoded MAC).
    # Outer IPv6 dst = DUT End SID; DUT applies End:
    #   sl 1→0, outer dst ← seg[0] = fc00:0:2:1::, forwards out port 2.
    # Capture on p2 verifies: sl=0, segments unchanged, inner TCP intact.
    f1                                = cfg.flows.add()
    f1.name                           = "srh_pdp1"
    f1.tx_rx.device.tx_names          = [d1_v6.name]
    f1.tx_rx.device.rx_names          = [d2_v6.name]
    f1.rate.pps                       = 100
    f1.duration.fixed_packets.packets = 200
    f1.metrics.enable                 = True

    ip6_1                       = f1.packet.add().ipv6
    ip6_1.src.value             = "2001:0:1::1"
    ip6_1.dst.value             = _DUT_END_SID    # DUT End SID: sl pointer
    ip6_1.next_header.value     = 43              # SRH

    sr1                         = f1.packet.add().ipv6_extension_header.routing.segment_routing
    sr1.segments_left.value     = 1               # points to seg[1] = DUT End SID
    sr1.last_entry.value        = 1               # 2-segment list (0-indexed)
    sr1.flags.protected.value   = 0
    sr1.flags.oam.value         = 0
    sr1.flags.alert.value       = 0
    sr1.tag.value               = 0
    seg                         = sr1.segment_list.segment()[-1]
    seg.segment.value           = "fc00:0:2:1::"  # seg[0]: next hop after DUT
    seg                         = sr1.segment_list.segment()[-1]
    seg.segment.value           = _DUT_END_SID    # seg[1]: DUT End SID (current)

    ip4_inner                   = f1.packet.add().ipv4
    ip4_inner.src.value         = "10.1.1.1"
    ip4_inner.dst.value         = "10.2.2.2"
    ip4_inner.protocol.value    = 6              # TCP

    tcp_inner                   = f1.packet.add().tcp
    tcp_inner.src_port.value    = 1234
    tcp_inner.dst_port.value    = 80

@apratimmukherjee apratimmukherjee changed the title Isis srv6 review Support for ISIS SRv6 as per RFC9352 Jul 10, 2026
@SuryyaKrJana
SuryyaKrJana marked this pull request as ready for review July 13, 2026 06:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants