BGP Unnumbered (RFC 5549) Design and Verification - 夜莺博客

BGP Unnumbered (RFC 5549) Design and Verification

BGP unnumbered removes the single most tedious part of building a spine-leaf fabric: allocating and tracking a point-to-point IP subnet for every link. Interfaces peer over their IPv6 link-local addresses, IPv4 prefixes ride along using RFC 5549 (RFC 8950) next hops, and a new leaf is added by plugging it in and copying a template. The idea is the same everywhere, but the implementation differs per vendor. This article covers the mechanics, a working configuration model, and the checks that tell you the session is genuinely carrying IPv4 traffic.

The two mechanisms behind one idea

  • Peering over link-local addresses — the neighbour address is the interface itself rather than a configured IPv4/IPv6 address. No subnet planning per link, no IP exhaustion, and the configuration is identical on every fabric port.
  • IPv4 routes with IPv6 next hops (RFC 5549) — the address family is IPv4 unicast, but the next hop is an IPv6 link-local address. The forwarding plane resolves the next hop to a MAC address through IPv6 neighbour discovery, so the IPv4 prefix needs no IPv4 interface address at all.

Both are needed together for the full benefit. Peering over link-local addresses alone still forces IPv4 next-hop tracking per link; RFC 5549 alone still leaves you allocating point-to-point addresses.

A configuration model

On FRR-based platforms (Cumulus Linux, SONiC's bgp container, any Linux BGP speaker) the configuration is explicit about "this neighbour is an interface":

router bgp 65100
 bgp router-id 10.0.0.1
 neighbor eth0 interface remote-as external
 !
 address-family ipv4 unicast
  neighbor eth0 activate
  maximum-paths 16
 exit-address-family

Vendors with their own CLI express the same intent with a neighbour statement that names the interface, for example neighbor interface Ethernet1 remote-as 65001 on an EOS or NX-OS leaf, and a peer-group construct to apply one policy to every fabric port at once. On SONiC the FRR daemon is reached through vtysh, and the configuration is persisted with write:

sonic# configure
sonic(config)# router bgp 65100
sonic(config-router)# neighbor eth0 interface remote-as external
sonic(config-router)# address-family ipv4 unicast
sonic(config-router-af)# neighbor eth0 activate
sonic(config-router-af)# end
sonic# write

Peer groups keep it manageable

The value of unnumbered BGP is in the template. Build the policy once — timers, address families, send-community, soft-reconfiguration, route map — and apply it to a peer group, then attach every interface neighbour to that group:

sonic(config)# router bgp 65000
sonic(config-router)# neighbor PG1 remote-as 65002
sonic(config-router)# neighbor PG1 timers 2 8
sonic(config-router)# address-family ipv4
sonic(config-router-af)# neighbor PG1 send-community
sonic(config-router-af)# neighbor PG1 send-community extended
sonic(config-router-af)# neighbor PG1 soft-reconfiguration inbound
sonic(config-router-af)# exit
sonic(config-router)# neighbor eth0 peer-group PG1
sonic(config-router)# neighbor eth1 peer-group PG1

Verification that actually proves IPv4 is working

sonic# show bgp summary
sonic# show bgp ipv4 unicast summary
sonic# show bgp neighbors eth0
sonic# ip -6 neighbor show dev eth0
sonic# ip route show
sonic# show bgp ipv4 unicast detail | include Next
  • show bgp summary confirms the session reached Established and is exchanging prefixes.
  • ip -6 neighbor show confirms the link-local resolution is present — without a resolved neighbour entry, RFC 5549 next hops cannot be programmed.
  • In the IPv4 detail output, check that the next hop is displayed as an IPv6 link-local address. If it shows an IPv4 address, you are looking at a classic numbered session and the unnumbered change was not applied.

Failure modes worth knowing

  • Session never comes up — the interface has no link-local address, or IPv6 has been disabled on it. BGP unnumbered needs IPv6 on the link even when every prefix carried is IPv4.
  • Session up, IPv4 prefixes present, no forwarding — the platform is not programming IPv6 next hops for IPv4 routes. Verify the platform actually supports RFC 5549 for the hardware forwarding path, not just in the control plane.
  • Duplicate router-id — with no interface addresses, router IDs are not derived automatically on every platform. Set bgp router-id explicitly on every fabric node.
  • Asymmetric accepted-versus-advertised policy — eBGP peers reject prefixes they have no policy for on some platforms; keep the route map consistent on both ends of every fabric link.
  • Scale surprises — every link is now a BGP session, so a 64-port leaf has 64 sessions. Confirm the control-plane and ECMP scale numbers before using unnumbered BGP at the spine.

Because the configuration is uniform, an unnumbered fabric is also far easier to template with automation: one Jinja-style snippet per node, parametrised only by router-id and neighbour interfaces. That consistency — not the address saving — is why the design has become the default in modern data centres.

See also: BGP dynamic neighbours with listen range, leaf-spine oversubscription and ECMP design, and BGP next-hop-self and third-party next hop.

原文链接:https://blog.bott.im/bgp-unnumbered-in-2025-same-idea-different-implementations/