<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.5.2">Jekyll</generator><link href="https://ruissalo.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://ruissalo.github.io/" rel="alternate" type="text/html" /><updated>2017-08-17T03:45:32+00:00</updated><id>https://ruissalo.github.io/</id><title type="html">ruissalo and the net</title><subtitle>Hopefully one more search result for unimportant things</subtitle><entry><title type="html">Build your very own SRv6 probe</title><link href="https://ruissalo.github.io/spring/ipv6/2017/07/29/building-srv6-probe.html" rel="alternate" type="text/html" title="Build your very own SRv6 probe" /><published>2017-07-30T00:39:48+00:00</published><updated>2017-07-30T00:39:48+00:00</updated><id>https://ruissalo.github.io/spring/ipv6/2017/07/29/building-srv6-probe</id><content type="html" xml:base="https://ruissalo.github.io/spring/ipv6/2017/07/29/building-srv6-probe.html">&lt;p&gt;Yes, IPv6 strikes back!&lt;/p&gt;

&lt;p&gt;As it turns out SPRING can be instantiated in two different data planes: MPLS and IPv6 (SRv6). Most of the SR documentation you can find online is about MPLS and probably because that’s where networking vendors have put most of the effort. And indeed gains are huge when you apply SR to the MPLS dataplane, in particular for big operators. For years MPLS have been plagued with complex architectures that require a bunch of protocols and a huge amount of state… a scaling nightmare for those who want to do some serious traffic engineering. SR greatly simplifies some of these issues, although not without introducing some other  interesting problems in the process.&lt;/p&gt;

&lt;p&gt;My favorite aspect of SRv6 is that you don’t need expensive gear to experiment with it or to deploy it in production, and to demonstrate that is the case, in this post we’re gonna be playing with a simple client/server UDP application capable of sending SRv6 enabled packets throughout the network. If you’re wondering why would you want to use SRv6 in the first place, you can refer to this &lt;a href=&quot;https://tools.ietf.org/html/draft-ietf-spring-ipv6-use-cases-11&quot;&gt;draft&lt;/a&gt; where you can find some interesting use cases.&lt;/p&gt;

&lt;p&gt;In the first part of this post we’ll be talking about the SRv6 implementation in Linux and then we’ll move on to discuss some code to implement our example application. Not all details will be covered as some basic knowledge is assumed on segment routing and C but a list of useful reading materials will be provided in the &lt;a href=&quot;#references&quot;&gt;References&lt;/a&gt; section. In this post the terms SR and SPRING are used to refer to &lt;a href=&quot;draft-ietf-spring-segment-routing-12&quot;&gt;draft-ietf-spring-segment-routing-12&lt;/a&gt; and the term SRv6 is used to refer to &lt;a href=&quot;https://tools.ietf.org/html/draft-ietf-6man-segment-routing-header-07&quot;&gt;draft-ietf-6man-segment-routing-header-07&lt;/a&gt;&lt;/p&gt;

&lt;!-- TOC --&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;#topology&quot;&gt;Topology&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#part-1&quot;&gt;Part 1&lt;/a&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#linux&quot;&gt;Linux&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#iproute2&quot;&gt;Iproute2&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#srv6-and-the-ipv6-socket-api&quot;&gt;SRv6 and the IPv6 socket api&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#part-2&quot;&gt;Part 2&lt;/a&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#the-client&quot;&gt;The client&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#the-server&quot;&gt;The server&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#final-considerations&quot;&gt;Final considerations&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#references&quot;&gt;References&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;!-- /TOC --&gt;

&lt;h2 id=&quot;topology&quot;&gt;Topology&lt;/h2&gt;

&lt;p&gt;The image below shows the topology that we’ll be using throughout this post. All three nodes are Linux instances running the latest kernel. srv6-2-vm (node 2) acts as a routing bridge between srv6-vm (node 1) and srv6-3-vm (node 3). Nodes 1 and 3 don’t have any routes pointing at each other’s networks.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://ruissalo.github.io/assets/img/srv6.jpg&quot; alt=&quot;topology&quot; /&gt;&lt;/p&gt;

&lt;h1 id=&quot;part-1&quot;&gt;Part 1&lt;/h1&gt;

&lt;h3 id=&quot;linux&quot;&gt;Linux&lt;/h3&gt;

&lt;p&gt;SR was released in February this year as part of the Linux kernel 4.10 version through a series of changes submitted by David Lebrun : &lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=1ababeba4a21f3dba3da3523c670b207fb2feb62&quot;&gt;commit&lt;/a&gt;
&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=915d7e5e5930b4f01d0971d93b9b25ed17d221aa&quot;&gt;commit&lt;/a&gt;
&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=6c8702c60b88651072460f3f4026c7dfe2521d12&quot;&gt;commit&lt;/a&gt;
&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=bf355b8d2c30a289232042cacc1cfaea4923936c&quot;&gt;commit&lt;/a&gt;
&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=4f4853dc1c9c1994f6f756eabdcc25374ff271d9&quot;&gt;commit&lt;/a&gt;
&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=9baee83406d6a4b02222f5ee21511c3f4c19e39d&quot;&gt;commit&lt;/a&gt;
&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=613fa3ca9e9e6af57927dab238121010c510fe4c&quot;&gt;commit&lt;/a&gt;
&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=a149e7c7ce812561f0fdc7a86ddc42f294e5eb3e&quot;&gt;commit&lt;/a&gt;
&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=4f4853dc1c9c1994f6f756eabdcc25374ff271d9&quot;&gt;commit&lt;/a&gt;
&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=8bc66a4423dba1ffafddd52b68ddad4adff39648&quot;&gt;commit&lt;/a&gt;
&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=46738b1317e169b281ad74690276916e24d1be6d&quot;&gt;commit&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The implementation allows a SR enabled Linux machine to act as a segment Endpoint as well as an egress node. Both cases are defined by &lt;a href=&quot;https://tools.ietf.org/html/draft-ietf-6man-segment-routing-header-07&quot;&gt;draft-ietf-6man-segment-routing-header&lt;/a&gt; and the End functionality can be summarized as follows:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;table style=&quot;border-spacing: 0&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot; style=&quot;text-align: right&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;n&quot;&gt;IF&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SegmentsLeft&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;THEN&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;decrement&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SL&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;update&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;the&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IPv6&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;DA&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SRH&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;SL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;FIB&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lookup&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;on&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;updated&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;DA&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;forward&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;accordingly&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;the&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;matched&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;entry&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;ELSE&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;drop&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;the&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;packet&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;ul&gt;
  &lt;li&gt;SL: Segments Left&lt;/li&gt;
  &lt;li&gt;DA: Packet’s destination address&lt;/li&gt;
  &lt;li&gt;SRH: Type 4 routing header&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;SL and the Segment List array are members of the segment routing extension header (SRH4).&lt;/p&gt;

&lt;p&gt;In other words, an SRv6 enabled node receiving an IPv6 packet having a type 4 segment routing header (SRH) will check if the Segment Lefts field is &amp;gt; 0 (ie the node is not the packet’s final destination), if SL &amp;gt; 0, decrement the field and update the destination address of the IPv6 packet with the segment (IPv6 address) at index SL on the 
segments list. This is basically a swap operation between the segment list and the packet’s destination address. Once this is done follow the usual forwarding rules for
the packet on that host. Note that these actions will take place if the destination address of the received packet is locally listed as a SID (segment identifier) on that node’s “My Local SID Table” and the entry has the End function attached. As a reminder, an SRv6-capable node N maintains a “My Local SID Table” containing all the local SRv6 segments explicitly instantiated at node N. The table also specifies which instruction is bound to each of the instantiated SIDs. &lt;em&gt;End&lt;/em&gt; is one of those logical funtions.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;    End            Endpoint function
                   The SRv6 instantiation of a prefix SID
    End.X          Endpoint function with Layer-3 cross-connect
                   The SRv6 instantiation of a Adj SID
    End.T          Endpoint function with specific IPv6 table lookup
    End.DX2        Endpoint with decapsulation and Layer-2 cross-connect
                   L2VPN use-case
    End.DX6        Endpoint with decapsulation and IPv6 cross-connect
                   IPv6 L3VPN use (equivalent of a per-CE VPN label)
    End.DX4        Endpoint with decapsulation and IPv4 cross-connect
                   IPv4 L3VPN use (equivalent of a per-CE VPN label)
    End.DT6        Endpoint with decapsulation and IPv6 table lookup
                   IPv6 L3VPN use (equivalent of a per-VRF VPN label)
    End.DT4        Endpoint with decapsulation and IPv4 table lookup
                   IPv4 L3VPN use (equivalent of a per-VRF VPN label)
    End.B6         Endpoint bound to an SRv6 policy
                   SRv6 instantiation of a Binding SID
    End.B6.Encaps  Endpoint bound to an SRv6 encapsulation Policy
                   SRv6 instantiation of a Binding SID
    End.BM         Endpoint bound to an SR-MPLS Policy
                   SRv6/SR-MPLS instantiation of a Binding SID
    End.S          Endpoint in search of a target in table T
    End.AS         Endpoint to SR-unaware APP via static proxy
    End.AM         Endpoint to SR-unaware APP via masquerading
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Table. Not exhaustive list of well-known logical functions that can be attached to a SID in the “My Local SID Table”.&lt;/p&gt;

&lt;p&gt;A Linux kernel instance can then act as any of the following:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Source node: A node originating an IPv6 packet with an SRH (Type 4 segment routing header). This extension header may be injected “inline” or by encapsulating the original packet and adding an SRH.&lt;/li&gt;
  &lt;li&gt;Transit node: Basically any node not inspecting a type 4 SRH (eg the node it’s not in the packet’s destination address DA)&lt;/li&gt;
  &lt;li&gt;Endpoint node: A node receiving an IPv6 packet whose DA exists in the node’s local segment identifiers (SID) table.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As previously mentioned, an SRv6-capable node should maintain a local SID (segment identifier) table containing all the local SRv6 segments explicitly instantiated at node N; but the table isn’t necessarily populated by default with all the IPv6 interface addresses according the SRv6 draft. The approach taken by Linux is that, by default, according to the kernel &lt;a href=&quot;https://github.com/torvalds/linux/blob/8fa3b6f9392bf6d90cb7b908e07bd90166639f0a/Documentation/networking/seg6-sysctl.txt&quot;&gt;documentation&lt;/a&gt;, SRv6 processing is disabled on every interface and must be explicitly enabled via /proc/sys/net/ipv6/conf/&amp;lt;iface&amp;gt;/seg6_enabled. If a packet containing a SRH is received on a seg6-disabled interface, it’s discarded. This validation is enforced by &lt;a href=&quot;https://github.com/torvalds/linux/blob/bc78d646e708dabd1744ca98744dea316f459497/net/ipv6/exthdrs.c#L323&quot;&gt;ipv6_srh_rcv&lt;/a&gt;, in particular in these few lines:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;table style=&quot;border-spacing: 0&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot; style=&quot;text-align: right&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;	&lt;span class=&quot;n&quot;&gt;accept_seg6&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;net&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ipv6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;devconf_all&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;seg6_enabled&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;accept_seg6&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;idev&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cnf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;seg6_enabled&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;accept_seg6&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;idev&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cnf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;seg6_enabled&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;accept_seg6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;kfree_skb&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;skb&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
		&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Other implementations like &lt;a href=&quot;https://docs.fd.io/vpp/17.04/sr_doc.html&quot;&gt;FD.IO&lt;/a&gt; require explicit segment/logical_function instantiation in the “My Local SID Table”.&lt;/p&gt;

&lt;p&gt;There are basically two ways to inject, inspect or remove a type 4 SRH in the current kernel implementation: using the well known iproute2 interface or through the IPv6 socket API. The former is implemented via &lt;a href=&quot;https://lwn.net/Articles/650778/&quot;&gt;lightweight tunnels&lt;/a&gt;: this feature allows user space tools like iproute2 to customize the &lt;a href=&quot;https://github.com/torvalds/linux/blob/5518b69b76680a4f2df96b1deca260059db0c2de/net/ipv6/seg6_iptunnel.c#L234&quot;&gt;input&lt;/a&gt; and &lt;a href=&quot;https://github.com/torvalds/linux/blob/5518b69b76680a4f2df96b1deca260059db0c2de/net/ipv6/seg6_iptunnel.c#L275&quot;&gt;output&lt;/a&gt; function pointers that every route has in the linux kernel. Using &lt;a href=&quot;http://man7.org/linux/man-pages/man7/rtnetlink.7.html&quot;&gt;rtnetlink&lt;/a&gt; sockets, iproute2 passes the user specified SRH to the kernel so that after header &lt;a href=&quot;https://github.com/torvalds/linux/blob/5518b69b76680a4f2df96b1deca260059db0c2de/net/ipv6/seg6.c#L32&quot;&gt;validation&lt;/a&gt; the new input/ouput pointer functions can be installed. These functions do the heavy lifting of adding/removing/modifying the SR extension header. This is the same mechanism used by the MPLS and VXLAN &lt;a href=&quot;https://kernelnewbies.org/Linux_4.3#head-c5506dbfb2f3c214e689a53e1430873fe3ace52f&quot;&gt;implementations&lt;/a&gt; in the kernel.&lt;/p&gt;

&lt;h3 id=&quot;iproute2&quot;&gt;Iproute2&lt;/h3&gt;

&lt;p&gt;The use of iproute2 is pretty straightforward. Based on our three-node topology, let’s assume that we want to ping srv6-3-vm from srv6-vm, going through node srv6-2-vm. As noted before there are no routes designating srv6-2-vm as the default gateway on either side (srv6-3-vm and srv6-vm). The following command adds a SR path on srv6-vm with destination srv6-3-vm specifying 2001:db8::2 as the next segment.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sr6@sr6-vm:~$ sudo ip -6 route add  2001:db9::1/64 dev eth1 encap seg6 mode encap segs 2001:db8::2
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;After issuing the command above, the routing table now shows our new SRv6 route.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sr6@sr6-vm:~$ ip -6 route list
(...)
2001:db9::/64  encap seg6 mode encap segs 1 [ 2001:db8::2 ] dev eth1 metric 1024 pref medium
(...)
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;A similar command is executed on srv6-3-vm for the return path.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sr6@sr6-3-vm:~$ sudo ip -6 route add  2001:db8::1/64 dev eth1 encap seg6 mode encap segs 2001:db9::2
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;In the examples above, the keywords &lt;strong&gt;encap seg6&lt;/strong&gt; indicate that we want to use SRv6 and the option &lt;strong&gt;mode encap&lt;/strong&gt; tells the kernel that we want to use the encapsulation mode.&lt;/p&gt;

&lt;p&gt;Wireshark tells us a similar story:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;table style=&quot;border-spacing: 0&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot; style=&quot;text-align: right&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;n&quot;&gt;Frame&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;120&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;on&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;wire&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;960&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bits&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;120&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;captured&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;960&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bits&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;Linux&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cooked&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;capture&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;Internet&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Protocol&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Version&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Src&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2001&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;db8&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Dst&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2001&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;db9&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
    &lt;span class=&quot;mo&quot;&gt;0110&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;....&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Version&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;....&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;....&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;....&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;....&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;....&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;....&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Traffic&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;DSCP&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CS0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ECN&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Not&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ECT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;....&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;....&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;....&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0100&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0100&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0010&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0010&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Flow&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x40422&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Payload&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;64&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Next&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;header&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Routing&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Header&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IPv6&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;43&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Hop&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;limit&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;63&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Source&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2001&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;db8&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Destination&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2001&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;db9&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Source&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;GeoIP&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Unknown&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Destination&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;GeoIP&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Unknown&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Routing&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Header&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IPv6&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Segment&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Routing&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;Next&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Header&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UDP&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;17&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;Length&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Length&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;40&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bytes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;Type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Segment&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Routing&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;Segments&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Left&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;First&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;segment&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;Flags&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x0000&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;Reserved&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;Address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2001&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;db9&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;Address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2001&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;db8&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Segments&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Traversal&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Order&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Datagram&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Protocol&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Src&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Port&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;51129&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Dst&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Port&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2000&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Source&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Port&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;51129&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Destination&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Port&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2000&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Length&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;24&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Checksum&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x7e26&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;unverified&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Checksum&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Status&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Unverified&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Stream&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;Data&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bytes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Data&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;48656&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c6c6f2c2049276d20686572650a&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Length&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;From the output above we can easily see where this packet capture was taken. Note “Segments left” (line 19) is 0 and how the segment list (lines 23 and 24) is encoded in the reverse order of the traversed path.&lt;/p&gt;

&lt;h3 id=&quot;srv6-and-the-ipv6-socket-api&quot;&gt;SRv6 and the IPv6 socket api&lt;/h3&gt;

&lt;p&gt;The other way to interact with SRH4 in the kernel is through the sockets API. Depending on the socket type, control data related to a packet’s payload can be transmitted or received as ancillary data using the &lt;a href=&quot;https://linux.die.net/man/2/sendmsg&quot;&gt;sendmsg&lt;/a&gt; and &lt;a href=&quot;https://linux.die.net/man/2/recvmsg&quot;&gt;recvmsg&lt;/a&gt; system calls. However, for the purposes of this post, our UDP application will be injecting the same segment routing header to packets sent through the same socket, so instead of sending the SRH in every call to &lt;em&gt;sendmsg()&lt;/em&gt;, we’ll set the ancillary data as a socket option. This turns our extension header into a  &lt;em&gt;sticky&lt;/em&gt; option. Note that if you’re planning to use a TCP socket, ancillary data is never sent or received by &lt;em&gt;sendmsg()&lt;/em&gt; and &lt;em&gt;rcvmsg()&lt;/em&gt; calls. This is best explained by RFC 3542:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  It is not possible to use ancillary data to transmit the above
   options for TCP since there is not a one-to-one mapping between send
   operations and the TCP segments being transmitted.  Instead an
   application can use setsockopt to specify them as sticky options.
   When the application uses setsockopt to specify the above options it
   is expected that TCP will start using the new information when
   sending segments.  However, TCP may or may not use the new
   information when retransmitting segments that were originally sent
   when the old sticky options were in effect.

   It is unclear how a TCP application can use received information
   (such as extension headers) due to the lack of mapping between
   received TCP segments and receive operations.  In particular, the
   received information could not be used for access control purposes
   like on UDP and raw sockets.
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The &lt;a href=&quot;http://man7.org/linux/man-pages/man3/cmsg.3.html&quot;&gt;ancillary data structure&lt;/a&gt; can be a bit confusing at first. It basically consists of a series of &lt;em&gt;cmsghdr&lt;/em&gt; structures describing control information passed from the kernel to the userland interface or viceversa. The control data may be IP options, various fields in the IP header or data not sent on the wire, like the packet’s incoming interface. The actual data is usually consumed by POSIX defined macros to facilitate access to the underlying structures. One of the reasons why &lt;em&gt;cmsghdr&lt;/em&gt; can be confusing is because some of the fields are &lt;strong&gt;value-result&lt;/strong&gt;, which is just a fancy way of calling fields that take a pointer to a certain struct that the kernel will use to write data to. This data is then consumed by the userspace application. &lt;a href=&quot;https://www.amazon.com/Unix-Network-Programming-Sockets-Networking/dp/0131411551/ref=pd_lpo_sbs_14_t_0?_encoding=UTF8&amp;amp;psc=1&amp;amp;refRID=7V8D8GGFF0G25E1VC7TE&quot;&gt;Steven’s Unix Network Programming&lt;/a&gt; goes into a great deal of detail on this subject.&lt;/p&gt;

&lt;p&gt;The general idea used by our example app is that once the socket is created via  &lt;a href=&quot;http://man7.org/linux/man-pages/man2/socket.2.html&quot;&gt;socket()&lt;/a&gt;, we specify the IP option that we want to send or receive using a call to &lt;a href=&quot;https://linux.die.net/man/2/setsockopt&quot;&gt;setsockopt()&lt;/a&gt;. In our case, the client, which will be setting the SRH in inline mode, will use IPV6_RTHDR, while the server will call &lt;em&gt;setsockopt()&lt;/em&gt; with IPV6_RECVRTHDR to indicate the kernel that we want to receive the control information on our socket. This control information will give us access to the segment routing header that we want to process.&lt;/p&gt;

&lt;p&gt;One thing to keep in mind is that the existing &lt;a href=&quot;https://sourceware.org/git/?p=glibc.git;a=blob;f=inet/inet6_rth.c;h=917753da09f5897ffcd05c14195791e392edb81a;hb=HEAD&quot;&gt;glibc implementation&lt;/a&gt; contains a series of functions, first defined 20 yrs ago by Richard Stevens in &lt;a href=&quot;https://www.ietf.org/rfc/rfc2292.txt&quot;&gt;RFC 2292&lt;/a&gt; § 8 and then updated by &lt;a href=&quot;https://www.ietf.org/rfc/rfc3542.txt&quot;&gt;RFC 3542&lt;/a&gt; § 7, that were meant to abstract the handling of the IPv6 routing headers, but at the time SRH type 4 wasn’t defined yet!  This means that you won’t be able to take advantage of these functions to construct a SRv6 routing header.&lt;/p&gt;

&lt;h1 id=&quot;part-2&quot;&gt;Part 2&lt;/h1&gt;

&lt;h3 id=&quot;the-client&quot;&gt;The client&lt;/h3&gt;

&lt;p&gt;Our application consists of a client that injects a SRH with a user defined segment list (or hops to traverse) The server then parses the SRH received and prints the segment list (or traversed hops) to the screen. You can access the source code on &lt;a href=&quot;https://github.com/ruissalo/srv6_app&quot;&gt;github&lt;/a&gt; so we’ll discuss only a few  relevant sections here.&lt;/p&gt;

&lt;p&gt;The following struct is used to represent a segment routing extension header.  Line 11 represents the list of segments to traverse or segments traversed as an array of &lt;a href=&quot;http://man7.org/linux/man-pages/man7/ipv6.7.html&quot;&gt;in6_addr&lt;/a&gt; structures.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;table style=&quot;border-spacing: 0&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot; style=&quot;text-align: right&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
11
12&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ipv6_sr_hdr&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;__u8&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;nexthdr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;__u8&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;hdrlen&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;__u8&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;__u8&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;segments_left&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;__u8&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;first_segment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;__u8&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;flag_1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;__u8&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;flag_2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;__u8&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;reserved&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;in6_addr&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;segments&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;table style=&quot;border-spacing: 0&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot; style=&quot;text-align: right&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
11&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;    &lt;span class=&quot;n&quot;&gt;srh&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nexthdr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;17&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;srh&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hdrlen&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;srh&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;srh&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;segments_left&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;srh&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;first_segment&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;srh&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;flag_1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;srh&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;flag_2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;srh&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;reserved&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;memset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;srh&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;segments&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;in6_addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;inet_pton&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;AF_INET6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;segment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;srh&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;segments&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]);&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;In the previous code block we populate &lt;em&gt;srh&lt;/em&gt;, our &lt;em&gt;ipv6_sr_hdr&lt;/em&gt; struct, with the routing header information we want to attach to the packets. Since we’re traversing a single hop, &lt;em&gt;segmens_left&lt;/em&gt; is 1. In line 11 we convert the user provided segment (an IPv6 address or 2001:db8::2 in the three-node topology) into network form using &lt;a href=&quot;http://man7.org/linux/man-pages/man3/inet_pton.3.html&quot;&gt;inet_pton()&lt;/a&gt; and the result is stored in the segment list of the &lt;em&gt;srh&lt;/em&gt; struct.&lt;/p&gt;

&lt;p&gt;Next, line 1 creates the the UDP socket descriptor and finally line 2 sets the &lt;em&gt;srh&lt;/em&gt; struct as a sticky option on the socket. All the packets sent through this socket will now have a segment routing extension header following the 40 octets IPv6 header.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;table style=&quot;border-spacing: 0&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot; style=&quot;text-align: right&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;    &lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;socket&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;AF_INET6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SOCK_DGRAM&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;err&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;setsockopt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IPPROTO_IPV6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IPV6_RTHDR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;srh&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;srh_len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This last code block uses the &lt;a href=&quot;https://linux.die.net/man/2/sendto&quot;&gt;sendto()&lt;/a&gt; system call to relay a message to the server.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;table style=&quot;border-spacing: 0&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot; style=&quot;text-align: right&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;    &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sendto&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buffer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buffer_size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sockaddr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sin6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sin6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;perror&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Error sending UDP message&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h3 id=&quot;the-server&quot;&gt;The server&lt;/h3&gt;

&lt;p&gt;Just like our client, the server creates a socket and sets IPV6_RECVRTHDR to indicate the kernel that we want to receive ancillary data.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;table style=&quot;border-spacing: 0&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot; style=&quot;text-align: right&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;    &lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;socket&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;AF_INET6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SOCK_DGRAM&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;err&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;setsockopt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IPPROTO_IPV6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IPV6_RECVRTHDR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;err&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;perror&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;setsockopt error&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
   &lt;span class=&quot;n&quot;&gt;err&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bind&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sockaddr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sin6_bind&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sin6_bind&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This code block initializes the &lt;em&gt;cmsghdr&lt;/em&gt; and &lt;em&gt;msghdr&lt;/em&gt; structs used to store the received SRH. A call to &lt;em&gt;recvmsg()&lt;/em&gt; in line 26 passes &lt;em&gt;msg&lt;/em&gt; as a reference to store the data.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;table style=&quot;border-spacing: 0&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot; style=&quot;text-align: right&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;srh_print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sockfd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
   &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;rc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;msghdr&lt;/span&gt;  &lt;span class=&quot;n&quot;&gt;msg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cmsghdr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cmsg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;iov_number&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;iovec&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;iov_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buffer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1024&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
  
  &lt;span class=&quot;n&quot;&gt;bzero&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;msg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;msg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;iov_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;iov_base&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buffer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;iov_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;iov_len&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1024&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;iov_number&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;control&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1024&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sockaddr_in6&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;client_address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;msg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;msg_iov&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;iov_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;msg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;msg_iovlen&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;iov_number&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;msg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;msg_control&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;control&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;msg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;msg_controllen&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;control&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;msg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;msg_name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

   &lt;span class=&quot;n&quot;&gt;rc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;recvmsg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sockfd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;msg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Once &lt;em&gt;recvmsg()&lt;/em&gt; returns, we can iterate over the ancillary data returned by the kernel in &lt;em&gt;msg&lt;/em&gt; to print the traversed segments to the screen. CMSG_FIRSTHDR, CMSG_NXTHDR and CMSG_DATA are the macros defined in RFC 3542 that we mentioned in the previous section. Note that these macros turn the API into a functional interface, so the application doesn’t really need to bother about understanding the underlying structures. Lines 3 and 4 check the control message type is IPV6_RTHDR and then line 5 calls CMSG_DATA() to get a pointer to the data. The next line casts the data into our &lt;em&gt;ipv6_sr_hdr&lt;/em&gt; struct. Finally lines 7 and 8 convert the IPv6 segments from network to presentation before printing the addresses to the screen.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;table style=&quot;border-spacing: 0&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot; style=&quot;text-align: right&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
11
12
13
14&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;         &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cmsg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CMSG_FIRSTHDR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;msg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cmsg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
              &lt;span class=&quot;n&quot;&gt;cmsg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CMSG_NXTHDR&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;msg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cmsg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
             &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cmsg&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cmsg_level&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IPPROTO_IPV6&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;
                 &lt;span class=&quot;n&quot;&gt;cmsg&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cmsg_type&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IPV6_RTHDR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                  &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CMSG_DATA&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cmsg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
                  &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ipv6_sr_hdr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rthdr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ipv6_sr_hdr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
                  &lt;span class=&quot;n&quot;&gt;inet_ntop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;AF_INET6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rthdr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;segments&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
                  &lt;span class=&quot;n&quot;&gt;inet_ntop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;AF_INET6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rthdr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;segments&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;str1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;str1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
                  &lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;%s &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
                  &lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;%s &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;str1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
                 &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;msg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;msg_flags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MSG_CTRUNC&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                     &lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot; (control info truncated)&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
             &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;After running the client, the server handles the connection and prints the following information to the screen
before exiting.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;table style=&quot;border-spacing: 0&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot; style=&quot;text-align: right&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;n&quot;&gt;sr6&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sr6&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vm&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:~&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;server&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;out&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2001&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;db9&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3000&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;header&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;len&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;header&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;next&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;header&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;17&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;first&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;segment&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;reserved&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
&lt;span class=&quot;mi&quot;&gt;2001&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;db9&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; 
&lt;span class=&quot;mi&quot;&gt;2001&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;db8&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h1 id=&quot;final-considerations&quot;&gt;Final considerations&lt;/h1&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;While we used inline mode in this post, take into account that only endhosts should use this insertion mode. Encapsulation should otherwise be the prefered method when packets enter a SR domain.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Nothing prevents you from simultaneously installing SRv6 static routes (eg using iproute2) and having your application use different SRH values via the IPv6 socket API. You 
must enforce consistency between the system config and your applications.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;In general SPRING terminology a segment may carry topological meaning but it also may indicate a logical function provided by the host or the network (aka SRv6 Network Programming). This posts dealt exclusively with the Endpoint function. You can read more about SRv6 network programming functions in &lt;a href=&quot;https://tools.ietf.org/html/draft-filsfils-spring-srv6-network-programming-01&quot;&gt;draft-filsfils-spring-srv6-network-programming&lt;/a&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;This post purposely omits any comments or implementation details regarding the acquisition of segment ids (SIDS) from the network. In the next post we’ll discuss
some options to make this information available to a central controller for path computation and path programming on the probes.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;references&quot;&gt;References&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Linux SRv6 lwtunnels implementation can be mainly found &lt;a href=&quot;https://github.com/torvalds/linux/blob/5518b69b76680a4f2df96b1deca260059db0c2de/net/ipv6/seg6_iptunnel.c#L275&quot;&gt;here&lt;/a&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;For SRv6 socket options you can start &lt;a href=&quot;https://github.com/torvalds/linux/blob/5518b69b76680a4f2df96b1deca260059db0c2de/net/ipv6/exthdrs.c#L866&quot;&gt;here&lt;/a&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;A great resource to learn about UNIX sockets is &lt;a href=&quot;https://www.amazon.com/Unix-Network-Programming-Sockets-Networking/dp/0131411551/ref=pd_lpo_sbs_14_t_0?_encoding=UTF8&amp;amp;psc=1&amp;amp;refRID=7V8D8GGFF0G25E1VC7TE&quot;&gt;Steven’s Unix Network Programming&lt;/a&gt;. Highly recommended.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Advanced Sockets Application Program Interface (API) for IPv6. https://www.ietf.org/rfc/rfc3542.txt&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;IPv6 Segment Routing Header (SRH) https://tools.ietf.org/html/draft-ietf-6man-segment-routing-header-07&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;http://segment-routing.org/&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;IPv6 segment routing https://lwn.net/Articles/722804/&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;https://inl.info.ucl.ac.be/publications/implementing-ipv6-segment-routing-linux-kernel&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;https://www.amazon.com/Linux-Programming-Interface-System-Handbook/dp/1593272200&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;and special thanks to David Lebrun for answering my questions.&lt;/strong&gt;&lt;/p&gt;</content><author><name></name></author><summary type="html">Yes, IPv6 strikes back!</summary></entry><entry><title type="html">When old is the new new</title><link href="https://ruissalo.github.io/spring,/ipv6/2017/07/25/when-the-old-is-new.html" rel="alternate" type="text/html" title="When old is the new new" /><published>2017-07-26T00:39:48+00:00</published><updated>2017-07-26T00:39:48+00:00</updated><id>https://ruissalo.github.io/spring,/ipv6/2017/07/25/when-the-old-is-new</id><content type="html" xml:base="https://ruissalo.github.io/spring,/ipv6/2017/07/25/when-the-old-is-new.html">&lt;p&gt;As you well know technology comes and goes in cycles and sometimes it makes you wonder why certain things didn’t gain traction in the first place, only to have someone come in later and “discover” a brand new piece of tech. Maybe it’s the market, or the technology landscape that changes creating new opportunities, in any case, RFCs need to be published, scientific papers need to be written and vendors need to innovate constantly.&lt;/p&gt;

&lt;p&gt;Segment routing is a very good example of something old, at least the basic idea around it, that is now becoming a trend. The concept of source routing was discussed and covered some 35 years ago by RFC 791 and implemented as IP option 131. Basically this option allows the originating system to specify intermediate systems a packet must traverse to get to its destination &lt;sup id=&quot;fnref:1&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;. Later on a number of thread vectors were identified, notably described by RFC 6274  &lt;sup id=&quot;fnref:2&quot;&gt;&lt;a href=&quot;#fn:2&quot; class=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;, and the option is basically deprecated today.&lt;/p&gt;

&lt;p&gt;IPv6 also had a similar feature in the form of an extension header. Before SR, there were two main types of this routing header: RH0 and RH2&lt;sup id=&quot;fnref:4&quot;&gt;&lt;a href=&quot;#fn:4&quot; class=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;. RH0 was also deprecated due to similar security concerns&lt;sup id=&quot;fnref:5&quot;&gt;&lt;a href=&quot;#fn:5&quot; class=&quot;footnote&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;Fast forward to 2015, the first version of SPRING &lt;sup id=&quot;fnref:3&quot;&gt;&lt;a href=&quot;#fn:3&quot; class=&quot;footnote&quot;&gt;5&lt;/a&gt;&lt;/sup&gt; appears and the first segment routing presentations start popping up on youtube. SPRING leverages the same source routing paradigm that allows a node to direct packets through an ordered list of segments. One notable difference with the old IP option 131 is the fact these segments may represent not only topological information but also a service of some sort, which in turn can have local (node only) or global (network-wide) significance.&lt;/p&gt;

&lt;p&gt;SPRING’s architecture is basically meant to operate within the boundaries of a single administrative domain where all nodes are trusted, in theory at least, so the  thread model and attacks that applied to the original IP option are not the same anymore. Moreover, the presence of an HMAC TLV field in the IPv6 segment routing header allows nodes to determine the validity of a given segment routing header.&lt;/p&gt;

&lt;p&gt;And by the way, IPv6 just resuscitated from the dead this month, checkout RFC 8200.&lt;/p&gt;

&lt;div class=&quot;footnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot;&gt;
      &lt;p&gt;https://tools.ietf.org/html/rfc791&amp;nbsp;&lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:2&quot;&gt;
      &lt;p&gt;https://tools.ietf.org/html/rfc6274&amp;nbsp;&lt;a href=&quot;#fnref:2&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:4&quot;&gt;
      &lt;p&gt;https://tools.ietf.org/html/rfc6554&amp;nbsp;&lt;a href=&quot;#fnref:4&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:5&quot;&gt;
      &lt;p&gt;https://tools.ietf.org/html/rfc5095&amp;nbsp;&lt;a href=&quot;#fnref:5&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:3&quot;&gt;
      &lt;p&gt;https://tools.ietf.org/html/draft-ietf-spring-segment-routing-12&amp;nbsp;&lt;a href=&quot;#fnref:3&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;</content><author><name></name></author><summary type="html">As you well know technology comes and goes in cycles and sometimes it makes you wonder why certain things didn’t gain traction in the first place, only to have someone come in later and “discover” a brand new piece of tech. Maybe it’s the market, or the technology landscape that changes creating new opportunities, in any case, RFCs need to be published, scientific papers need to be written and vendors need to innovate constantly.</summary></entry><entry><title type="html">You are an L1 router</title><link href="https://ruissalo.github.io/2016/09/23/you-are-an-l1-router.html" rel="alternate" type="text/html" title="You are an L1 router" /><published>2016-09-24T06:48:35+00:00</published><updated>2016-09-24T06:48:35+00:00</updated><id>https://ruissalo.github.io/2016/09/23/you-are-an-l1-router</id><content type="html" xml:base="https://ruissalo.github.io/2016/09/23/you-are-an-l1-router.html">&lt;p&gt;If you are reading this chances are you’re familiar with what IS-IS is and how it works.
I don’t know about you but I’ve always wondered about the exact meaning of the Attributes 
section in the isis database output of Junos devices. Let’s take a look.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ruissalo@r1_re0&amp;gt; show isis database 
IS-IS level 1 link-state database:
  0 LSPs

IS-IS level 2 link-state database:
LSP ID                      Sequence Checksum Lifetime Attributes
R1_re0.00-00           0x1ca5d   0x5ba9     1051 L1 L2
R2_re0.00-00            0xf91a   0x65fa      611 L1 L2
R3_re0.00-00           0x11e1f   0x2da6     1187 L1 L2
R9_re0.00-00           0x23fb7   0xac86     1079 L1 L2
(...)
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;According to the level 1 section output, we could assume this particular level was
disabled on the device because no router is currently injecting LSPs into this topology, at least from R1’s perspective. 
This theory can be easily confirmed by looking at the configuration:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ruissalo@r1_re0&amp;gt; show configuration protocols isis | display set | display inheritance no-comments 
set protocols isis level 2 wide-metrics-only
set protocols isis level 1 disable
(...)
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;As we expected level 1 has been disabled making this an L2 only router; this same config 
knob can also be found on  R2, R3 and R9. - Many engineers choose to run L2 only deployments to 
eliminate chances of default routes installed towards L2L1 routers with the Attached bit set -
&lt;strong&gt;&lt;em&gt;So if this is an L2 only device, why is it that the output shows the L1 and L2 
flags on each of the LSPs?&lt;/em&gt;&lt;/strong&gt; Entry details also show the same.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ruissalo@r1_re0&amp;gt; show isis database r1_re0.00-00 extensive | match Attributes 
    Checksum: 0xad86, Sequence: 0x5fed4, Attributes: 0x3 &amp;lt;L1 L2&amp;gt;

&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Where is this information coming from anyway?&lt;/p&gt;

&lt;p&gt;The Attribute block is nothing more than the last octet on both L1 and L2 link-state PDUs -
packet types 18 and 20. It’s worth noting that the IS-IS decision process will consider this 
octet only when it’s present in the first fragment (in case multiple fragments were needed to achieve
full synchronization)&lt;/p&gt;

&lt;p&gt;The diagram below shows the PDU header composed of the ISIS 
common header followed by the Lifetime, LSP ID and Sequence Number, all three values
displayed in the router’s isis database output we saw before.&lt;/p&gt;

&lt;pre&gt;
                                       No. of Octets

   ----------------------------------
  |      Common Fixed Header        |     8
   ----------------------------------
   ----------------------------------
  |          PDU Length             |     2
   ----------------------------------
  |      Remaining Lifetime	        |     2
   ----------------------------------
  |           LSP ID                |  ID Length + 2
   ----------------------------------
  |      Sequence Number            |     4
   ----------------------------------
  |           Checksum              |     2
   ----------------------------------
  |  P | ATT | LSPDBOL | *IS Type*  |     1
   ----------------------------------
   ----------------------------------
  |             TLVs                |    Variable
  -----------------------------------

&lt;/pre&gt;

&lt;p&gt;To understand the exact meaning of the information conveyed by the last
octet let’s see what ISO 10589, available &lt;a href=&quot;ftp://ftp.juniper.net/pub/isis/10589.PDF&quot;&gt;here&lt;/a&gt;, has to say about that:&lt;/p&gt;

&lt;p&gt;P - Bit 8 when set, indicates support for Partition repair. This is
    an optional functionality, meaning neither Juniper nor Cisco implements it :)&lt;/p&gt;

&lt;p&gt;ATT - Bits 7-4 indicate, when set, the issuing Intermediate System is “attached” to other areas. Why 4 
			bits? in the 1980s designers thought it was a good idea to support multiple topologies based on 
      different metrics like delay, expense and error. Because complexity is never a good thing, this
      multidimensional approach wasn’t adopted and use of bits 5,6 and 7 is deprecated today.&lt;/p&gt;

&lt;p&gt;LSPDBOL - Bit 3 is used to ‘overload’ the database.&lt;/p&gt;

&lt;p&gt;And finally we get to meet the IS Type bits. As it turns out these 2 bits indicate the type of Intermediate System that
generated the LSP&lt;sup id=&quot;fnref:1&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;! And this is the source of the information shown in the Attributes Block on the isis database output 
we saw previously. According to ISO 10589 allowed values are as follow:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;0 - Unused value&lt;/li&gt;
  &lt;li&gt;1 - bit 1 set means Level 1 Intermediate System&lt;/li&gt;
  &lt;li&gt;2 - Unused value&lt;/li&gt;
  &lt;li&gt;3 - bits 1 and 2 set, Level 2 Intermediate System&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Remember in IS-IS we can have three types of routers: L1 only, L2 only and L1-L2, but with only 2 values to choose from 
(1 or 3 - bit 1 must always be set) there is no way to make the difference between an L2 only system and an L1L2 system
by looking at the Attributes block from an L2 LSP PDU. So while L1L2 routers will designate a System as “IS Type” 3 on both 
type 18 and type 20 LSP PDUs, L2 only routers will do the same when generating type 20 PDUs.&lt;/p&gt;

&lt;p&gt;To make things even more confusing, we saw how Juniper’s database uses the ‘L1L2’ output to designate IS Type 3 LSPs entries.
Now, let’s see what our dear friend Wireshark is telling us.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://ruissalo.github.io/assets/img/L2L1-Device-L1-LSP.png&quot; alt=&quot;LSP capture&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The image shows a type 20 PDU (L2 LSP) from an L1L2 adjacency between two devices, note how Wireshark decodes IS Type 3 
with a “Level 2” string.&lt;/p&gt;

&lt;p&gt;Why IS-IS protocol designers made this decision seems to be related to how CLNP worked at that time: There was no such a thing as an L2-only router in the early days
of the protocol - this restriction relaxed later for IP.&lt;/p&gt;

&lt;p&gt;In any case, always remember to check the actual content of the database, or simply the adjancency list, before arriving to any conclusions 
about the IGP topology: don’t be fooled by the LSPs Attributes block.&lt;/p&gt;

&lt;div class=&quot;footnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot;&gt;
      &lt;p&gt;A system’s IS Type also plays an interesting role when an router is determining the adjacency usage type. You can read more about this in section 8.4.3.2 of ISO 10589.&amp;nbsp;&lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;</content><author><name>ruissalo</name></author><summary type="html">If you are reading this chances are you’re familiar with what IS-IS is and how it works. I don’t know about you but I’ve always wondered about the exact meaning of the Attributes section in the isis database output of Junos devices. Let’s take a look.</summary></entry></feed>