[RFC] Unnumbered BGP automatic peering based on IPv6 ND
Dear BIRD dev-team and community, By looking at the project code (and corroborated by this [0] earlier RFC) it seems that currently the feature of auto-discovering BGP neighbors leveraging the IPv6 ND protocol is not currently fully supported by BIRD. I would like to start working on a patch proposal to close this gap. Many of the required pieces seem to be already in-place, like support for IPv6 link-local peer addresses and support of RFC-8950 for extended next-hop. There is also the dynamic BGP implementation which seems useful for the purpose of achieving dynamic connections based on received RAs. The problem is that dynamic BGP works in a passive/reactive model only, as it waits for peers within a specified range to connect, an idea would be to integrate with this implementation but also trigger a peer connection on a RA arrival (after checking if the advertised IP is within the desired range). Since I am still new to the project codebase and contributing for the first time, I would like to outline the idea for the implementation of the feature and hear what you think of it before going through the implementation. Any suggestions on best practices, style and common pitfalls would be also very welcome. - Introduce a new configuration option (e.g. automatic_lladdr_peering, or similar) to trigger this feature. This will provide a way to avoid modifying the current behavior if not needed. The rest of the configuration will also have to contain a neighbour range of fe80::/12 and an interface for the link-local feature (both of these are already supported). The resulting configuration preamble would look something like this: local as 65532; neighbor range fe80::/12%eth0 as 65534; dynamic name "link_local_"; automatic lladdr peering on; To make the configuration tidier we could, alternatively, introduce a new value for neighbor, like “neighbor auto” or “neighbor discover” to enable the feature. - When the above configuration is found, open a L2 socket on the provided device during the bgp_startup phase. This socket will then be used to send a RS to ff02::2 (all-routers multicast) to trigger the RAs used for peer discovery on remote routers. Another option would be to start sending out unsolicited RAs for the other peers to receive for discovery, this will make sure that we are not dependent on the peer being able to answer RSs and can rely entirely on the BGP implementation. This method would require to keep sending unsolicited RAs with a certain cadence, which could be set as a timer parameter in the added configuration option. - On the rx_hook of this socket listen for incoming ICMPv6 packets with type 134 (RA) and check if they contain a link-local address (i.e. inside the range provided in the configuration). If so, initiate a new BGP connection, using the now discovered LL remote address. This will follow the same path as if the remote peer address was statically provided in the configuration (sets remote_ip, calls bgp_active). As an added failover, we could remain listening on the L2 socket and try connecting to a new peer if a new address is discovered and we are in state BS_IDLE. - After a connection is established, if it becomes stale (after hold timer elapses) we can then trigger a new RS and relative discovery as outlined above to try and connect to a new remote LL address. This will not be needed if using the unsolicited RAs variant. The rest of the connection management and BGP message handling via the TCP socket will remain the same. This idea for the implementation is the one that reuses as much of the current codebase while introducing as little new procedures as possible that I could come up with, but I think it can still be refined with more insight with the internals. One thing that I am not sure about is the introduction of a new socket and connected logic on the BGP module, but I cannot really find an alternative. There is already an implementation of a packet engine for RAs that could maybe be reused for the processing of the ICMPv6 packets, but I think it will be easier to decouple the logic and implement everything on the BGP state machine (even if it will mean some code duplication, which is not ideal). Another variant could be establishing a connection for every discovered address, as in the case of incoming connections for the dynamic BGP implementation. Maybe this is a more general solution, but since the current implementation expects an incoming request it will maybe introduce too much logic to try and fit it in. Let me know your opinion on if and if it seems a proper way to proceed (and, of course, if there is any interest in having this feature upstream). Thank you in advance for your time and feedback. Best Regards, Matteo 0: https://bird.network.cz/pipermail/bird-users/2022-July/016233.html
Hi Matteo, There's some prior art in other routing implementations which you might be interested in looking at. FRR already has similar functionality for automatic peering via IPv6 link-local addresses, as does Nokia's SR Linux platform (there may be others, but those are the ones I know). FRR uses IPv6 router advertisements for peer discovery, by periodically sending RAs to announce itself on a given interface and listening for RAs from other hosts on the same link to discover other peers. BGP sessions are then established via link-local addresses automatically when a new peer on the link becomes known. Off the top of my head I'm not sure how FRR handles established sessions with peers which stop sending RAs (I'm on holiday and don't have access to my work notes right now, I might have looked at that when I last worked on automatic peer discovery in the lab). This scheme in FRR appears to have been developed for uses cases like routed datacentre fabrics with point-to-point connections between routers rather than shared L2 segments where multiple routers are present. I'm not sure if the implementation in FRR would handle multiple peers on the same L2 correctly. Nokia SR Linux implements the same scheme using IPv6 RAs and is compatible with FRR -- an FRR instance and a Nokia device on opposite sides of the same link will recognise each other's presence and attempt to establish sessions with each other. As far as I'm aware this is a non-standard feature of FRR which has been copied and reimplemented by at least Nokia, if not other vendors. It would be practical if Bird were also compatible with this scheme of course, though in an ideal world there would be an RFC specifying this behaviour rather than implementers all reverse engineering FRR independently. Best wishes, --mm.
Den 17.11.2025 17:06, skreiv Molly Miller via Bird-users:
There's some prior art in other routing implementations which you might be interested in looking at. FRR already has similar functionality for automatic peering via IPv6 link-local addresses, as does Nokia's SR Linux platform (there may be others, but those are the ones I know).
Another point worth mentioning is that BGP updates containing only link-local next-hops aren't properly standardised at the moment, so there is no guarantee that two implementations will interoperate well. There is an active effort to fix this problem though, see https://datatracker.ietf.org/doc/draft-ietf-idr-linklocal-capability/. Tore
Hello Matteo! See inline and below please. TL;DR: We want this but in a different way. Thank you so much for writing this meesage. This is exactly the right way to go when implementing something new which needs a design process. On Mon, Nov 17, 2025 at 11:31:17AM +0100, Matteo Perin wrote:
Dear BIRD dev-team and community,
By looking at the project code (and corroborated by this [0] earlier RFC) it seems that currently the feature of auto-discovering BGP neighbors leveraging the IPv6 ND protocol is not currently fully supported by BIRD. I would like to start working on a patch proposal to close this gap.
Indeed it is not. [...]
There is also the dynamic BGP implementation which seems useful for the purpose of achieving dynamic connections based on received RAs. The problem is that dynamic BGP works in a passive/reactive model only, as it waits for peers within a specified range to connect, an idea would be to integrate with this implementation but also trigger a peer connection on a RA arrival (after checking if the advertised IP is within the desired range).
Well, the dynamic BGP implementation is kinda already hack-ish itself, and this seems to be kinda hack-hack-ish. It would probably work the way you propose, yet we don't like mixing RAdv into BGP. [...]
This idea for the implementation is the one that reuses as much of the current codebase while introducing as little new procedures as possible that I could come up with, but I think it can still be refined with more insight with the internals.
One thing that I am not sure about is the introduction of a new socket and connected logic on the BGP module, but I cannot really find an alternative. There is already an implementation of a packet engine for RAs that could maybe be reused for the processing of the ICMPv6 packets, but I think it will be easier to decouple the logic and implement everything on the BGP state machine (even if it will mean some code duplication, which is not ideal).
Another variant could be establishing a connection for every discovered address, as in the case of incoming connections for the dynamic BGP implementation. Maybe this is a more general solution, but since the current implementation expects an incoming request it will maybe introduce too much logic to try and fit it in.
Let me know your opinion on if and if it seems a proper way to proceed (and, of course, if there is any interest in having this feature upstream). Thank you in advance for your time and feedback.
First of all, there is an interest in having this feature upstream, please do it, unless you are too scared. Second, there is a _heavy_ interest in having this feature RFC'd, and as Molly wrote, there are already FRR and Nokia implementations. For me, it looks like it is a good way to go on the network side, at least for now. I'm also going to ping the FRR people about possibly RFC-ing this behavior, but that's out of scope of this e-mail. There is also a BGP Hello draft[1] but it's kinda dusty. That _might_ be a way to go in future but not now. Well, how to do this now? We have an actual interest in receiving the RA's systematically. With that, the desired path would be: - update the RAdv protocol so that it can also read RAs - create route-like objects from the RA contents - store these objects into a table - add a new channel type to BGP, probably named like `peers from` - exporting to that BGP channel (allowed only in dynamic BGP) would trigger spawning of a new session - RA expiration would withdraw the object from the table, possibly triggering the BGP session shutdown (unless configured otherwise with something like `persist` in the `peers` channel) This would allow: - inspecting the received RAs - filtering them - using the received RAs for different purposes later on - implementing different sources for peer discovery later on I would suppose that this machinery might be better to do in BIRD 3 only, considering that the dynamic spawning has seen some changes between 2 and 3. Also, in BIRD 3 the channel can be unidirectional, in this case export only for BGP and import only for the RAdv protocol. Is that a journey you are willing to pursue? Feel free to ask more questions or request clarifications. There are definitely some rough corners one would need to navigate, and I have not checked the whole path for dangerous elements. No refactoring should be needed, though. Thank you again for your query. Looking forward to hearing from you again. Maria [1] https://datatracker.ietf.org/doc/html/draft-xu-idr-neighbor-autodiscovery -- Maria Matejka (she/her) | BIRD Team Leader | CZ.NIC, z.s.p.o.
participants (4)
-
Maria Matejka -
Matteo Perin -
Molly Miller -
Tore Anderson