[PATCH] filter: Add bgp_next_hop_global and bgp_next_hop_ll for independent IPv6 next hop access
Maria Matejka
maria.matejka at nic.cz
Wed Apr 22 13:28:46 CEST 2026
Hi KusakabeShi,
thank you for your patch. We are not going to merge it for several
reasons, not listed in any particular order:
- it lacks an appropriate test in `filter/test.conf`
- it lacks documentation in `doc/bird.sgml`
- the commit message is absolutely not sufficient at all
- you have obviously not even tried to merge it with BIRD 3
- you have either not tried or not documented the behavior
of this feature when fed by IPv4
- you are not checking the LL address for actually being link-local
- it is a brutal hack into an already complicated filter system,
perusing the bit item of the attribute specification without saying
anything about that
This issue will be handled by an upcoming rework of the filter type
system, which we are expecting to continue on working in several months,
after releasing EVPN support and other more pushing stuff. We do know
that the current implementation is limited. We also have non-triviaĺ
experience maintaining old filter language quirks, and adding a new one
just adds more maintenance work long-term.
If you really need this, we may, theoretically, consider merging a patch
implementing a _method_ atop `bgp_next_hop`, e.g.
bgp_next_hop.set_global(3fff::);
bgp_next_hop.set_local(fe80::);
Yet, that has another list of weird problems under the hood, which will
be, again, solved by the type system rework. One of the reasons why the
type system rework takes so long (and didn't start until recently)
is actually this pre-existing quirk of bgp next hop for IPv6.
Thank you for your understanding.
Maria
On Tue, Apr 21, 2026 at 07:34:17PM +0800, Shi Kusakabe via Bird-users wrote:
> Hi,
>
>
>
> The current bgp_next_hop filter attribute only accesses nh[0] (the
> global address) of the BA_NEXT_HOP eattr. The link-local address stored
> in nh[1] is completely invisible to filters. Worse, set bgp_next_hop
> allocates a new 16-byte adata, silently discarding any existing
> link-local next hop.
>
>
>
> This makes it impossible to:
>
> - Inspect the link-local next hop in a filter
>
> - Modify only the global next hop while preserving the link-local
>
> - Set a link-local next hop independently
>
>
>
> This patch adds two new filter attributes, bgp_next_hop_global and
> bgp_next_hop_ll, which provide independent read/write access to nh[0]
> and nh[1] of the BGP next hop. Setting one does not affect other.
>
>
>
> The existing bgp_next_hop behavior is completely unchanged.
>
>
>
> Implementation:
>
>
>
> Both new attributes map to the same BA_NEXT_HOP ea_code, differentiated
> by the bit field of struct f_dynamic_attr (which was previously unused
> for EAF_TYPE_IP_ADDRESS):
>
>
>
> - bgp_next_hop — bit=0, original behavior (default from zero-init)
>
> - bgp_next_hop_global — bit=1, reads/writes nh[0]
>
> - bgp_next_hop_ll — bit=2, reads/writes nh[1]
>
>
>
> GET (FI_EA_GET):
>
> - bit=2: returns nh[1] if adata->length >= 32, otherwise IPA_NONE
>
> - bit=0,1: returns nh[0] (same as before)
>
>
>
> SET (FI_EA_SET):
>
> - bit=0: allocates new 16-byte adata with only the assigned IP (original
> behavior, nh[1] is lost)
>
> - bit=1,2: read-modify-write — reads the existing BA_NEXT_HOP from
> eattrs, updates only the target slot, preserves the other. If nh[1] is
> zero after the update, length is set to 16; otherwise 32.
>
>
>
> Usage example:
>
>
>
> # Read
>
> print bgp_next_hop_global; # 2404:f4c0:f70e:1980::202:881
>
> print bgp_next_hop_ll; # fe80::ff:fe20:2881
>
>
>
> # Modify global only, link-local preserved
>
> bgp_next_hop_global = 2001:db8::1;
>
>
>
> # Modify link-local only, global preserved
>
> bgp_next_hop_ll = fe80::99;
>
>
>
> Files changed:
>
> https://github.com/KusakabeShi/bird/commit/b5af9bc2eefbcc9e6f96432dd43fc6422f5f33c8
>
>
>
> - proto/bgp/config.Y — new keywords and dynamic_attr rules
>
> - filter/f-inst.c — GET/SET handling for partial next hop access
>
>
>
> The patch applies against the v2.18 release branch. Feedback welcome.
>
>
>
> Thanks,
>
> KusakabeShi
On Wed, Apr 22, 2026 at 08:50:25AM +0000, KSKB SHI wrote:
> Hi,
>
> The current bgp_next_hop filter attribute only accesses nh[0] (the global address) of the BA_NEXT_HOP eattr.
> The link-local address stored in nh[1] is completely invisible to filters.
>
> see this image:
> https://upload.cc/i1/2026/04/22/0Nj4E8.png
>
> Worse, set bgp_next_hop allocates a new 16-byte adata, silently discarding any existing link-local next hop.
>
> This makes it impossible to:
> - Inspect the link-local next hop in a filter
> - Modify only the global next hop while preserving the link-local
> - Set a link-local next hop independently
>
> This patch adds two new filter attributes, bgp_next_hop_global and bgp_next_hop_ll, which provide independent read/write access to nh[0] and nh[1] of the BGP next hop. Setting one does not affect other.
>
> The existing bgp_next_hop behavior is completely unchanged.
>
> Implementation:
>
> Both new attributes map to the same BA_NEXT_HOP ea_code, differentiated by the bit field of struct f_dynamic_attr (which was previously unused for EAF_TYPE_IP_ADDRESS):
>
> - bgp_next_hop — bit=0, original behavior (default from zero-init)
> - bgp_next_hop_global — bit=1, reads/writes nh[0]
> - bgp_next_hop_ll — bit=2, reads/writes nh[1]
>
> GET (FI_EA_GET):
> - bit=2: returns nh[1] if adata->length >= 32, otherwise IPA_NONE
> - bit=0,1: returns nh[0] (same as before)
>
> SET (FI_EA_SET):
> - bit=0: allocates new 16-byte adata with only the assigned IP (original behavior, nh[1] is lost)
> - bit=1,2: read-modify-write — reads the existing BA_NEXT_HOP from eattrs, updates only the target slot, preserves the other. If nh[1] is zero after the update, length is set to 16; otherwise 32.
>
> Usage example:
>
> # Read
> print bgp_next_hop_global; # 2404:f4c0:f70e:1980::202:881
> print bgp_next_hop_ll; # fe80::ff:fe20:2881
>
> # Modify global only, link-local preserved
> bgp_next_hop_global = 2001:db8::1;
>
> # Modify link-local only, global preserved
> bgp_next_hop_ll = fe80::99;
>
> Files changed:
> https://github.com/KusakabeShi/bird/commit/b5af9bc2eefbcc9e6f96432dd43fc6422f5f33c8
>
> - proto/bgp/config.Y — new keywords and dynamic_attr rules
> - filter/f-inst.c — GET/SET handling for partial next hop access
>
> The patch applies against the v2.18 release branch. Feedback welcome.
>
> Thanks,
> KusakabeShi
--
Maria Matejka (she/her) | BIRD Team Leader | CZ.NIC, z.s.p.o.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://trubka.network.cz/pipermail/bird-users/attachments/20260422/48f093bc/attachment.htm>
More information about the Bird-users
mailing list