Netdev List
 help / color / mirror / Atom feed
From: Andrea Mayer <andrea.mayer@uniroma2.it>
To: Anthony Doeraene <anthony.doeraene@uclouvain.be>
Cc: netdev@vger.kernel.org,
	Nicolas Dichtel <nicolas.dichtel@6wind.com>,
	stefano.salsano@uniroma2.it,
	Paolo Lungaroni <paolo.lungaroni@uniroma2.it>,
	Andrea Mayer <andrea.mayer@uniroma2.it>
Subject: Re: [Bug ?] Packet with End.X segment not correctly forwarded to nexthop
Date: Wed, 24 Jun 2026 19:18:50 +0200	[thread overview]
Message-ID: <20260624191850.55dd7be54ccc935743f5bc8a@uniroma2.it> (raw)
In-Reply-To: <3fe17ca9-25fa-4fb1-ba06-4463e0409a8b@uclouvain.be>

On Fri, 19 Jun 2026 15:25:09 +0200
Anthony Doeraene <anthony.doeraene@uclouvain.be> wrote:

> Hello,

Hi Anthony,
thanks for the description and the reproducer.

>
> I am currently experimenting with SRv6 and VRFs, and I found some weird
> interactions between the two.
>
> For the context, I need routers to have multiple VRFs, with each VRF
> having different routes to reach destinations.
> Our routers not only send packets to a specific nexthop, but also
> specify the VRF that the nexthop
> should use to forward these packets.
> To achieve this goal, routes in these VRFs push two segments: a local
> End.X segment, and a End.DT46 segment.
> Due to some implementation constraints, I want to have a single End.DT46
> segment shared by
> all routers in the network.
>
> Once packets are encapsulated by the VRF, the packet is sent in the main
> table to do a lookup for the nexthop.
> As the End.DT46 segment is shared between routers and can not be used to
> learn the nexthop, I decided to
> use an End.X segment to specify it.
>
> However, what I observe in this scenario is that End.X segment
> processing function is never called, resulting
> in the packet not being sent to the correct nexthop.

As I understand it, you are encapsulating a packet on r1 and you want to
decapsulate it on r2.

The first segment you want to apply on r1 is a local adjacency SID, bound to
the End.X behavior. When applied, it would force the encapsulated packet
onto the r1-r2 link toward your neighbour r2, and advance the segment list to
your next segment, the shared SID bound to End.DT46.

Anyway, as you have noticed, this is not what happens. The reason is that
the packet is generated locally on r1, so it is on the transmit path. An
SRv6 endpoint behavior is triggered by a SID in a packet the node receives,
not in one it originates and transmits. So the End.X behavior is never
triggered: the packet is just encapsulated and routed using the first
segment as its destination address, and not steered.

To steer the packet, you need to control the table in which the post-encap
lookup resolves the first segment. This need already came up for another
use case, originally introduced by Nicolas Dichtel. We referred to it as
'route leaking': the lookup must be done in the underlay table, so the
encapsulated traffic 'leaks' from the VRF to the underlay.

We worked on a patch for the seg6 encap that lets you choose the FIB table
for the post-encap lookup. I will post it when net-next reopens. You then
push only the shared SID and, in a table of your choice, add a route for it
via your next hop. The post-encap lookup resolves it there, and your next
hop receives that SID as the active SID and handles it:

  # next hop for the shared decap SID, in the table you pick
  ip -6 route add fc00:ffff:: via fc00::1:2 dev r1-r2 table 100

  # encap route: segment list is only the shared SID, resolved in table 100
  ip -6 route add fc00::2 encap seg6 mode encap segs fc00:ffff:: \
      lookup 100 table 10 dev X

- X is used just to determine the IPv6 SA of the encapsulated packet;
- table 10 is the encap route's table; if a VRF is bound to it, you can pass
  vrf <name> instead.

The lookup table can also be your VRF table, so the next-hop route sits next
to the encap route.

>
> I am wondering if this is an expected behavior (i.e. a node should never
> push a local segment), or if it is a real bug ?

It is expected, not a bug. A node may push a local segment. The point is
that an SRv6 endpoint behavior is not triggered on traffic the node
originates, as these behaviors run on the receive path.

>
> I am not well versed into the implementation details of SRv6 in the
> kernel, but I'm suspecting that this "bug" comes
> from the fact that seg6_output_core calls dst_output, which does not
> allow an SRv6 segment function to be called.

You understood the mechanism correctly. As explained above, seg6_output_core
ends with dst_output on the output path, so the seg6_local endpoint function
is not called there and this is by design.

>
> A minimal example is given below, which creates two namespaces (r1, r2) 
> and allows to reproduce this behavior.
> (tested on a kernel compiled on virtme-ng from commit
> e771677c937da5808f7b6c1f0e4a97ec1a84f8a8)
>
> Thank you in advance for the help and thanks for the SRv6 support on Linux,
> Doeraene Anthony
>
> File setup.sh
> ```
> # Topology under test:
> #
> #                    fc00::1:1       fc00::1:2
> # fc00::1 [ r1 ] ------------------------- [ r2 ] fc00::2
> #
> # Description:
> # ============
> #
> # Each node has an additional VRF, which it can use to provide different
> # routing decisions based on arbitrary rules (e.g. QoS aware forwarding)
> # Routes in this VRF will encapsulate the packets and push segments to
> # specify the nexthop (End.X) and the VRF the nexthop should use
> # (End.DT46). The same End.DT46 segment is shared by all nodes
> #
> # Problem:
> # ========
> #
> # Once segments are pushed, the End.X segment is never applied. As a
> # result, the segment is not popped from the SL, and the packet is sent
> # on an incorrect interface.
> #
> # Forwarding steps:
> # =================
> #
> # - R1 sends the packet to fc00::2 in its VRF `myvrf`
> # - This VRF encapsulates the packet and add two segments:
> #   1) End.X segment to force the transmission of the packet on r1-r2
> #   2) End.DT46 segment allowing r2 to know which VRF it should use
> #      to forward the packet.
> # - After encapsulation, r1 does a lookup in its main table for the
> #   End.X segment, but does not pop the segment. The packet is thus
> #   sent incorrectly on the dummy interface
> #
> [snip]
>
> ```
>

Ciao,
Andrea

      reply	other threads:[~2026-06-24 17:19 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-06-19 13:25 [Bug ?] Packet with End.X segment not correctly forwarded to nexthop Anthony Doeraene
2026-06-24 17:18 ` Andrea Mayer [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260624191850.55dd7be54ccc935743f5bc8a@uniroma2.it \
    --to=andrea.mayer@uniroma2.it \
    --cc=anthony.doeraene@uclouvain.be \
    --cc=netdev@vger.kernel.org \
    --cc=nicolas.dichtel@6wind.com \
    --cc=paolo.lungaroni@uniroma2.it \
    --cc=stefano.salsano@uniroma2.it \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox