Skip to content

bgpd: Route reflector omits NEXT_HOP when reflecting an ipv4 labeled-unicast path to an ipv4-unicast-only client #22569

Description

@nImEHuntet

Description

When a route reflector (RR) learns a prefix over an ipv4 labeled-unicast (SAFI 4) session and reflects it to a client activated only for ipv4 unicast (SAFI 1). The resulting UPDATE is encoded as a plain IPv4 unicast NLRI with the mandatory NEXT_HOP path attribute (type 3) missing entirely. The receiving unicast-only peer discards the update. A unicast NLRI without NEXT_HOP is malformed per RFC 4271, so the prefix never installs.

Additionally, the next-hop is present and correct in the RR's own Adj-RIB-Out (show ip bgp neighbors X advertised-routes.) It is only lost during UPDATE serialization.

The label→unicast translation already runs but has a serialization defect specific to the labeled-unicast-origin → unicast-egress path.

Cisco IOS-XE performs the same translation and sets the next hop correctly in the same topology, which is the behavior we expected.

Topology

Three iBGP routers, single AS, RR design:

  TEST-LU (10.0.0.13)  --- ipv4 labeled-unicast --->  RR1 (10.0.0.10)  --- ipv4 unicast --->  TEST-unicast (10.0.0.12)
  originates 10.0.0.13/32                            route reflector                            unicast-only RR client
  into labeled-unicast                                 (LU client + unicast client)
  • TEST-LU is an RR client activated for ipv4 labeled-unicast only, originating its loopback 10.0.0.13/32.
  • TEST-unicast is an RR client activated for ipv4 unicast only.
  • RR1 reflects between them. This is two separate neighbors, each with a single SAFI.

Loopback reachability is via OSPF; all sessions establish normally.

Version

FRRouting 10.5.2 (RR1) on Linux(6.6.128-vyos).
Copyright 1996-2005 Kunihiro Ishiguro, et al.
configured with:
    '--build=x86_64-linux-gnu' '--prefix=/usr' '--includedir=${prefix}/include' '--mandir=${prefix}/share/man' '--infodir=${prefix}/share/info' '--sysconfdir=/etc' '--localstatedir=/var' '--disable-option-checking' '--disable-silent-rules' '--libdir=${prefix}/lib/x86_64-linux-gnu' '--libexecdir=${prefix}/lib/x86_64-linux-gnu' '--disable-maintainer-mode' '--sbindir=/usr/lib/frr' '--with-vtysh-pager=/usr/bin/pager' '--libdir=/usr/lib/x86_64-linux-gnu/frr' '--with-moduledir=/usr/lib/x86_64-linux-gnu/frr/modules' '--disable-dependency-tracking' '--enable-rpki' '--enable-scripting' '--enable-pim6d' '--disable-grpc' '--disable-address-sanitizer' '--with-libpam' '--enable-doc' '--enable-doc-html' '--enable-snmp' '--enable-fpm' '--disable-protobuf' '--disable-zeromq' '--enable-ospfapi' '--enable-bgp-vnc' '--enable-multipath=256' '--enable-user=frr' '--enable-group=frr' '--enable-vty-group=frrvty' '--enable-configfile-mask=0640' '--enable-logfile-mask=0640' '--enable-pcre2posix' 'build_alias=x86_64-linux-gnu' 'PYTHON=python3'

Also with:
FRRouting 10.6.1 (RR1) on Linux(6.17.0-1016-oracle).
Copyright 1996-2005 Kunihiro Ishiguro, et al.
configured with:
    '--build=x86_64-linux-gnu' '--prefix=/usr' '--includedir=${prefix}/include' '--mandir=${prefix}/share/man' '--infodir=${prefix}/share/info' '--sysconfdir=/etc' '--localstatedir=/var' '--disable-option-checking' '--disable-silent-rules' '--libdir=${prefix}/lib/x86_64-linux-gnu' '--libexecdir=${prefix}/lib/x86_64-linux-gnu' '--disable-maintainer-mode' '--sbindir=/usr/lib/frr' '--with-vtysh-pager=/usr/bin/pager' '--libdir=/usr/lib/x86_64-linux-gnu/frr' '--with-moduledir=/usr/lib/x86_64-linux-gnu/frr/modules' '--disable-dependency-tracking' '--enable-rpki' '--disable-scripting' '--enable-pim6d' '--disable-grpc' '--disable-address-sanitizer' '--with-libpam' '--enable-doc' '--enable-doc-html' '--enable-snmp' '--enable-fpm' '--disable-protobuf' '--disable-zeromq' '--enable-ospfapi' '--enable-bgp-vnc' '--enable-multipath=256' '--enable-pcre2posix' '--enable-user=frr' '--enable-group=frr' '--enable-vty-group=frrvty' '--enable-configfile-mask=0640' '--enable-logfile-mask=0640' 'build_alias=x86_64-linux-gnu' 'PYTHON=python3'

How to reproduce

TEST-LU:

!
ip prefix-list RTR-LO seq 10 permit 10.0.0.13/32
!
router bgp 65001
 no bgp ebgp-requires-policy
 no bgp reject-as-sets
 no bgp default ipv4-unicast
 no bgp network import-check
 neighbor RR peer-group
 neighbor RR remote-as 65001
 no neighbor RR enforce-first-as
 neighbor RR update-source lo
 neighbor 10.0.0.10 peer-group RR
 no neighbor 10.0.0.10 enforce-first-as
 !
 address-family ipv4 labeled-unicast
  network 10.0.0.13/32
  neighbor RR activate
  neighbor RR prefix-list RTR-LO out
 exit-address-family
exit

RR1:

router bgp 65001
 bgp log-neighbor-changes
 no bgp ebgp-requires-policy
 no bgp reject-as-sets
 no bgp default ipv4-unicast
 bgp route-reflector allow-outbound-policy
 no bgp network import-check
 neighbor Internet peer-group
 neighbor Internet remote-as 65001
 no neighbor Internet enforce-first-as
 neighbor Internet update-source lo
 neighbor MPLS peer-group
 neighbor MPLS remote-as 65001
 no neighbor MPLS enforce-first-as
 neighbor MPLS update-source lo
 neighbor 10.0.0.12 peer-group Internet
 no neighbor 10.0.0.12 enforce-first-as
 neighbor 10.0.0.13 peer-group MPLS
 no neighbor 10.0.0.13 enforce-first-as
 !
 address-family ipv4 unicast
  neighbor Internet activate
  neighbor Internet route-reflector-client
 exit-address-family
 !
 address-family ipv4 labeled-unicast
  neighbor MPLS activate
  neighbor MPLS route-reflector-client
 exit-address-family
exit

TEST-unicast:

router bgp 65001
 bgp log-neighbor-changes
 no bgp ebgp-requires-policy
 no bgp reject-as-sets
 no bgp default ipv4-unicast
 no bgp network import-check
 neighbor RR peer-group
 neighbor RR remote-as 65001
 no neighbor RR enforce-first-as
 neighbor RR update-source lo
 neighbor 10.0.0.10 peer-group RR
 no neighbor 10.0.0.10 enforce-first-as
 !
 address-family ipv4 unicast
  redistribute connected
  neighbor RR activate
  neighbor RR soft-reconfiguration inbound
 exit-address-family
exit

Expected behavior

RR1 reflects 10.0.0.13/32 to TEST-unicast as a plain IPv4 unicast route, deriving the NEXT_HOP from the inbound labeled path. The next hop was carried in the MP_REACH_NLRI of the labeled UPDATE and written into the NEXT_HOP path attribute. This is the label-removal direction described in commit 9bedbb1.

Actual behavior

RR1 has the route as a single labeled path in the shared unicast/LU table

RR1# sh ip bgp ipv4 10.0.0.13/32
BGP routing table entry for 10.0.0.13/32, version 6
Local label: 3
Paths: (1 available, best #1, table default)
  Advertised to peers:
  10.0.0.12 10.0.0.13
  Local
    10.0.0.13 (metric 1) from 10.0.0.13 (10.0.0.13)
      Origin incomplete, metric 0, localpref 100, valid, internal, best (First path received)
      Remote labels: 3
      Last update: Mon Jul  6 10:06:04 2026

RR1's UNICAST Adj-RIB-Out for the client HAS the next-hop populated

RR1# sh ip bgp neighbors 10.0.0.12 advertised-routes
BGP table version is 7, local router ID is 10.0.0.10, vrf id 0
Default local pref 100, local AS 65001
Status codes:  s suppressed, d damped, h history, u unsorted, * valid, > best, = multipath,
               i internal, r RIB-failure, S Stale, R Removed
Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self
Origin codes:  i - IGP, e - EGP, ? - incomplete
RPKI validation codes: V valid, I invalid, N Not found

     Network          Next Hop            Metric LocPrf Weight Path
 *>i 10.0.0.12/32   10.0.0.12              0    100      0 ?
 *>i 10.0.0.13/32   10.0.0.13              0    100      0 ?
 *>i 10.1.1.0/24  10.0.0.12              0    100      0 ?

Total number of prefixes 3

Packet Capture of UPDATE, RR1 (10.0.0.10) → TEST-unicast (10.0.0.12):

UPDATE
  NLRI (legacy IPv4 unicast): 10.0.0.13/32
  Path attributes present (type codes): 1 (ORIGIN), 2 (AS_PATH), 4 (MED),
                                        5 (LOCAL_PREF), 9 (ORIGINATOR_ID), 10 (CLUSTER_LIST)
  NEXT_HOP (type 3): ABSENT
  MP_REACH_NLRI (type 14): ABSENT

Client rejects / never installs

TEST-unicast# sh ip bgp 10.0.0.13/32
% Network not in table

Jul 06 10:17:53 TEST-unicast bgpd[1335]: [EC 33554482] 10.0.0.10 Missing well-known attribute NEXT_HOP.
Jul 06 10:17:53 TEST-unicast bgpd[1335]: [EC 33554455] 10.0.0.10(RR1) rcvd UPDATE with errors in attr(s)!! Withdrawing route.

Additional context

No response

Checklist

  • I have searched the open issues for this bug.
  • I have not included sensitive information in this report.

Metadata

Metadata

Assignees

No one assigned

    Labels

    triageNeeds further investigation

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions