How to create SRv6 traffic using Ostinato

Ostinato Team bio photo By Ostinato Team

Segment Routing over IPv6 (SRv6) enables source routing by encoding path information directly in IPv6 packet headers. It uses the Segment Routing Header (SRH) - IPv6 extension header to carry a list of segments (identified by a segment-id SID) that define the network path. Each segment represents a network instruction, allowing precise control over packet forwarding through the network.

We’ll not go into more details about SRv6 here - if you are here you likely already know what it is and how it works.

What you want to know is how to create SRv6 traffic.

Ostinato doesn’t support SRv6 natively, but we can use a Ostinato protocol script to create the SRH.

Let’s start with the SRv6 packet structure.

SRv6 Packet Structure

A SRv6 packet is a IPv6 packet with a SRv6 header (SRH) following the IPv6 header.

+----------+------+-----+--------//-------+
| Ethernet | IPv6 | SRH |     Payload     |
+----------+------+-----+--------//-------+

The SRH structure is specified in RFC8754 as follows -

  0                   1                   2                   3
  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | Next Header   |  Hdr Ext Len  | Routing Type  | Segments Left |
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 |  Last Entry   |     Flags     |              Tag              |
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 |                                                               |
 |            Segment List[0] (128-bit IPv6 address)             |
 |                                                               |
 |                                                               |
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 |                                                               |
 |                                                               |
 |                             ...
 |                                                               |
 |                                                               |
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 |                                                               |
 |            Segment List[n] (128-bit IPv6 address)             |
 |                                                               |
 |                                                               |
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 //                                                             //
 //         Optional Type Length Value objects (variable)       //
 //                                                             //
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

To create a SRv6 packet in Ostinato, follow these steps -

  1. Create a new stream and select the protocols Mac | EthII | IPv6 | UDP | Payload
  2. Go to Advanced mode of selecting protocols and insert Userscript in between IPv6 and UDP
  3. Configure other protocol fields (e.g. IPv6 src/dest) and stream fields (e.g. frame size)

SRv6 Packet Headers

SRv6 Protocol Script

Go to Protocol Data tab and enter the below script in the UserScript header.

const sids = [
    0x0001020304050607, 0x08090a0b0c0d0e1f,
    0x0001020304050607, 0x08090a0b0c0d0e2f,
    0x0001020304050607, 0x08090a0b0c0d0e4f,
    0x0001020304050607, 0x08090a0b0c0d0e4f,
    0x0001020304050607, 0x08090a0b0c0d0e5f
 ];

protocol.name = "SRv6 SRH"

protocol.protocolFrameSize = function() { return 8 + sids.length*8; }

protocol.protocolId = function(id_type)
{
    if (id_type == Protocol.ProtocolIdIp)
        return 43;
    return 0;
}

protocol.protocolFrameValue = function(index)
{
    var segmentsLeft = sids.length/2-1;
    var tag = 0xabcd;

    var pfv = new Array(protocol.protocolFrameSize());

    // next header (8)
    pfv[0] = protocol.payloadProtocolId(Protocol.ProtocolIdIp);

    // hdr ext len (8)
    pfv[1] = sids.length; // 2 quad-words per SID

    // routing type (8)
    pfv[2] = 4;

    // segments left (8)
    pfv[3] = segmentsLeft;

    // last entry (8)
    pfv[4] = sids.length/2-1;

    // flags (8)
    pfv[5] = 0;

    // Tag (16)
    pfv[6] = (tag >>  8) & 0xFF;
    pfv[7] = (tag >>  0) & 0xFF;

    return pfv;
}

Change the sids array to the list of SRv6 segments you want to use.

  • Each element in the sids array is a 128-bit IPv6 address
  • The tag is a 16-bit value that is used to identify the SRv6 packet

⚜️ If you want to understand what the script does, see the Ostinato User-Script documentation.

Apply the stream changes and start transmitting the SRv6 packets.

SRv6 Packet Verification

To verify the SRv6 packets, start a packet capture and view them in Wireshark.

Ostinato generated SRv6 in Wireshark

You should see the SRv6 packets with the SRH and the segments.

Something not as expected? Reach out to us.