Relaxed handling of OTC attribute
Hi Bird team, We are currently evaluating the implementation of RFC9234 for our IXP route servers. Looking at it naively, one just needs to set local role rs_server in the protocol. And indeed, routes from peers will be rejected and this is logged. Instead of just logging, we would really like to apply our "blame and shame" policy, i.e. make the invalid routes (in our case, anything with an OTC set) visible in our looking glass (similar to RPKI invalids). To do so, we'd need the "ineligible" routes to be imported into the main table, tagged in a sensible way. I understand that RFC9234 section 5 mandates that the behaviour wrt OTC attribute handling shall not be configurable by the operator. But ineligible does not require the route to be invisible (see section 3). Would it be possible to implement a more relaxed behaviour by allowing the import of ineligible routes (but never export)? Our current alternative is to avoid using BGP roles capability, but only implement OTC handling in filters. Thanks and best wishes, André -- André Grüneberg, Managing Director andre.grueneberg@bcix.de +49 30 2332195 42 BCIX Management GmbH Albrechtstr. 110 12103 Berlin Germany Geschäftsführer/Managing Directors: Jens Lietzmann, André Grüneberg Handelsregister: Amtsgericht Charlottenburg, HRB 143581 B
On Thu, 12 Jun 2025, at 15:33, André Grüneberg wrote:
Hi Bird team,
We are currently evaluating the implementation of RFC9234 for our IXP route servers. Looking at it naively, one just needs to set local role rs_server in the protocol. And indeed, routes from peers will be rejected and this is logged.
Instead of just logging, we would really like to apply our "blame and shame" policy, i.e. make the invalid routes (in our case, anything with an OTC set) visible in our looking glass (similar to RPKI invalids). To do so, we'd need the "ineligible" routes to be imported into the main table, tagged in a sensible way.
I understand that RFC9234 section 5 mandates that the behaviour wrt OTC attribute handling shall not be configurable by the operator. But ineligible does not require the route to be invisible (see section 3).
Does "import keep filtered on" preserve these routes (when viewed with "show route filtered")? (Now, I think that leaves questions around identifying the reason why a route was filtered etc. But that might be [the start of] an approach) Now, I admit that swicthing to that for all filtering reasons probably involves quite a bunch of changes to the bird configs that IXPs use today, which is definitely a bit unnerving.
Would it be possible to implement a more relaxed behaviour by allowing the import of ineligible routes (but never export)?
Our current alternative is to avoid using BGP roles capability, but only implement OTC handling in filters.
A disadvantage of that, of course, is that you lose peer role checking (although peers supporting roles are very rare today - despite having run with OTC support enabled ourselves for a couple of years now, we have only one bilat on BCIX which advertises role support towards us) - Erin
On 12 Jun 2025, at 16:12, Erin Shepherd <bird-users@erinshepherd.net> wrote:
A disadvantage of that, of course, is that you lose peer role checking (although peers supporting roles are very rare today - despite having run with OTC support enabled ourselves for a couple of years now, we have only one bilat on BCIX which advertises role support towards us)
Hi, You can always check/modify/whatever the OTC attribute for a peer that does not have a role assigned. The point is: - have the RS signal their role (rs_server) - if the peer supports roles, enforce the correct one (rs_client, NOT peer, NOT customer) - set the OTC, preferably automatically, not by hand - still have the routes received with OTC, even if discarded/inactive, instead of having them treated as “withdraw” - I may also want to re-announce these routes (as invalid as they are) to some internal collector. - include routes with OTC within “receive limit” ???? - do something other than having 2 log lines for each route received with OTC when it shouldn’t We still have 1 or 2 pees that still take the routes from one RS (with OTC attribute) and re-announce them to the other RS. -- Radu-Adrian FEURDEAN Web : www.franceix.net
Hi Erin, On Thu, 12 Jun 2025 at 16:16, Erin Shepherd <bird-users@erinshepherd.net> wrote:
Instead of just logging, we would really like to apply our "blame and shame" policy, i.e. make the invalid routes (in our case, anything with an OTC set) visible in our looking glass (similar to RPKI invalids). To do so, we'd need the "ineligible" routes to be imported into the main table, tagged in a sensible way. I understand that RFC9234 section 5 mandates that the behaviour wrt OTC attribute handling shall not be configurable by the operator. But ineligible does not require the route to be invisible (see section 3). Does "import keep filtered on" preserve these routes (when viewed with "show route filtered")? (Now, I think that leaves questions around identifying the reason why a route was filtered etc. But that might be [the start of] an approach)
Looking at the code (calling WITHDRAW()) I couldn't find any interaction with 'import keep filtered'.
Our current alternative is to avoid using BGP roles capability, but only implement OTC handling in filters. A disadvantage of that, of course, is that you lose peer role checking (although peers supporting roles are very rare today - despite having run with OTC support enabled ourselves for a couple of years now, we have only one bilat on BCIX which advertises role support towards us)
Indeed, I'd miss the role validation in the session. Having thought about it, I am missing to see the advantage of that. For proper handling of the OTC I need to know my role -- and I do, I am rs_server. Provided the other side implements RFC9234 and has a local role set, we can look at the consequences of them setting their local role incorrectly: - rs_client (as should be): they do not set OTC -> we will accept, we set OTC -> they will accept - peer: they set OTC -> we will drop, we set OTC -> they will accept - provider: they set OTC -> we will drop, we set OTC -> they will drop - customer: they do not set OTC -> we will accept routes as expected, we set OTC -> they will accept - rs_server: they set OTC -> we will drop, we set OTC -> they will drop A misconfiguration of their role may cause routes not to be accepted, but since we are always flagging with OTC on export, we will not create additional route leaks. I'd call that fail-safe?! As a reference: OpenBGPd 7.8+ distinguishes between setting the local role (and thus implementing OTC handling) and announcing the BGP roles capability. André -- André Grüneberg, Managing Director andre.grueneberg@bcix.de +49 30 2332195 42 BCIX Management GmbH Albrechtstr. 110 12103 Berlin Germany Geschäftsführer/Managing Directors: Jens Lietzmann, André Grüneberg Handelsregister: Amtsgericht Charlottenburg, HRB 143581 B
Hello André, there is no such feature you are looking for. The rest of this message is my personal speculation which I may just later say strict no-no-no-never to after discussing with the rest of the team. I'm thinking about a controversial approach, kinda disgusting, kinda blasphemy, a configuration knob which you could set in BGP channel (if implemented), e.g. like this import invalid; and then you would get all routes including the bad ones, just marked with another attribute like "invalidity reason" which could be probably even displayable in the table. These routes would stay rejected even if you call "accept" on them by mistake. Or, if you wanna go really messy, you could import invalid allow accept; and you already probably know what happens. That's very cursed though and there will be certain people yelling at me for even thinking about this. Obviously you need import keep filtered for all this to work well. I'm absolutely unknown whether this sacrilegious abomination ever gets even slightly more thoughts on our side… but simply by looking at your email, this may be something you may probably theoretically like to go for. Happy routing! Maria On June 12, 2025 3:33:37 PM GMT+02:00, "André Grüneberg" <andre.grueneberg@bcix.de> wrote:
Hi Bird team,
We are currently evaluating the implementation of RFC9234 for our IXP route servers. Looking at it naively, one just needs to set local role rs_server in the protocol. And indeed, routes from peers will be rejected and this is logged.
Instead of just logging, we would really like to apply our "blame and shame" policy, i.e. make the invalid routes (in our case, anything with an OTC set) visible in our looking glass (similar to RPKI invalids). To do so, we'd need the "ineligible" routes to be imported into the main table, tagged in a sensible way.
I understand that RFC9234 section 5 mandates that the behaviour wrt OTC attribute handling shall not be configurable by the operator. But ineligible does not require the route to be invisible (see section 3).
Would it be possible to implement a more relaxed behaviour by allowing the import of ineligible routes (but never export)?
Our current alternative is to avoid using BGP roles capability, but only implement OTC handling in filters.
Thanks and best wishes, André -- André Grüneberg, Managing Director andre.grueneberg@bcix.de +49 30 2332195 42
BCIX Management GmbH Albrechtstr. 110 12103 Berlin Germany
Geschäftsführer/Managing Directors: Jens Lietzmann, André Grüneberg Handelsregister: Amtsgericht Charlottenburg, HRB 143581 B
-- Maria Matejka (she/her) | BIRD Team Leader | CZ.NIC, z.s.p.o.
Hi Maria, I was considering your "personal speculation" and came to the conclusion that I agree, this should not be implemented. For a lot of errors in UPDATE messages, it's perfectly fine to treat those as an error and do Treat-as-withdraw (as described in RFC7606). This includes checking the length of the OTC attribute. I am not asking to see routes with protocol errors in the routing table. As far as I can see RFC9234 does not mandate handling a route leak with Treat-as-widthdraw. It just refers to leaking routes to be ineligible (for further use). My understanding: a leaked route should be present in Adj-RIB-In, but not into Loc-RIB. I do understand that Bird does not follow the traditional path of other BGP speakers and has no Adj-RIB-In/Out. In a multi-table route server setup Adj-RIB-In/Out is mimicked by the per-peer-table. In a single-table setup, the leaked route would go into the main table. So the question is: Could you imagine another way (i.e. different from Treat-as-withdraw) of handling "ineligible" routes? How do you treat routes that do not pass next-hop lookup? Shouldn't these be ineligible as well? How about doing something similar for "ineligible by OTC"? Best regards, André On Fri, 13 Jun 2025 at 00:50, Maria Matejka <maria.matejka@nic.cz> wrote:
Hello André,
there is no such feature you are looking for.
The rest of this message is my personal speculation which I may just later say strict no-no-no-never to after discussing with the rest of the team.
I'm thinking about a controversial approach, kinda disgusting, kinda blasphemy, a configuration knob which you could set in BGP channel (if implemented), e.g. like this
import invalid;
and then you would get all routes including the bad ones, just marked with another attribute like "invalidity reason" which could be probably even displayable in the table. These routes would stay rejected even if you call "accept" on them by mistake.
Or, if you wanna go really messy, you could
import invalid allow accept;
and you already probably know what happens. That's very cursed though and there will be certain people yelling at me for even thinking about this.
Obviously you need import keep filtered for all this to work well.
I'm absolutely unknown whether this sacrilegious abomination ever gets even slightly more thoughts on our side… but simply by looking at your email, this may be something you may probably theoretically like to go for.
Happy routing! Maria
On June 12, 2025 3:33:37 PM GMT+02:00, "André Grüneberg" < andre.grueneberg@bcix.de> wrote:
Hi Bird team,
We are currently evaluating the implementation of RFC9234 for our IXP route servers. Looking at it naively, one just needs to set local role rs_server in the protocol. And indeed, routes from peers will be rejected and this is logged.
Instead of just logging, we would really like to apply our "blame and shame" policy, i.e. make the invalid routes (in our case, anything with an OTC set) visible in our looking glass (similar to RPKI invalids). To do so, we'd need the "ineligible" routes to be imported into the main table, tagged in a sensible way.
I understand that RFC9234 section 5 mandates that the behaviour wrt OTC attribute handling shall not be configurable by the operator. But ineligible does not require the route to be invisible (see section 3).
Would it be possible to implement a more relaxed behaviour by allowing the import of ineligible routes (but never export)?
Our current alternative is to avoid using BGP roles capability, but only implement OTC handling in filters.
Thanks and best wishes, André
-- Maria Matejka (she/her) | BIRD Team Leader | CZ.NIC, z.s.p.o.
-- André Grüneberg, Managing Director andre.grueneberg@bcix.de +49 30 2332195 42 BCIX Management GmbH Albrechtstr. 110 12103 Berlin Germany Geschäftsführer/Managing Directors: Jens Lietzmann, André Grüneberg Handelsregister: Amtsgericht Charlottenburg, HRB 143581 B
On Fri, 13 Jun 2025, at 12:31, André Grüneberg wrote:
As far as I can see RFC9234 does not mandate handling a route leak with Treat-as-widthdraw. It just refers to leaking routes to be ineligible (for further use).
My understanding: a leaked route should be present in Adj-RIB-In, but not into Loc-RIB.
I do understand that Bird does not follow the traditional path of other BGP speakers and has no Adj-RIB-In/Out. In a multi-table route server setup Adj-RIB-In/Out is mimicked by the per-peer-table. In a single-table setup, the leaked route would go into the main table. So the question is: Could you imagine another way (i.e. different from Treat-as-withdraw) of handling "ineligible" routes?
Bird normally operates without Adj-RIB-In, but can be configured to operate with one:
`import table *switch*` A BGP import table contains all received routes from given BGP neighbor, before application of import filters. It is also called *Adj-RIB-In* in BGP terminology. BIRD BGP by default operates without import tables, in which case received routes are just processed by import filters, accepted ones are stored in the master table, and the rest is forgotten. Enabling `import table` allows to store unprocessed routes, which can be examined later by `show route`, and can be used to reconfigure import filters without full route refresh. Default: off.
(I assume this contains routes discarded because of an incorrect OTC attribute but I have not verified this. Even then I'm not sure Bird can (currently) use it to give you information on why routes were filtered) - Erin
Hi Erin, On Fri, 13 Jun 2025 at 12:48, Erin Shepherd <bird-users@erinshepherd.net> wrote:
Bird normally operates without Adj-RIB-In, but can be configured to operate with one:
import table *switch* A BGP import table contains all received routes from given BGP neighbor, before application of import filters. It is also called *Adj-RIB-In* in BGP terminology. BIRD BGP by default operates without import tables, in which case received routes are just processed by import filters, accepted ones are stored in the master table, and the rest is forgotten. Enabling import table allows to store unprocessed routes, which can be examined later by show route, and can be used to reconfigure import filters without full route refresh. Default: off.
(I assume this contains routes discarded because of an incorrect OTC attribute but I have not verified this. Even then I'm not sure Bird can (currently) use it to give you information on why routes were filtered)
From having read the code, I can tell you Bird would not even accept a leaked route into the import table due to Treat-as-withdraw.
André -- André Grüneberg, Managing Director andre.grueneberg@bcix.de +49 30 2332195 42 BCIX Management GmbH Albrechtstr. 110 12103 Berlin Germany Geschäftsführer/Managing Directors: Jens Lietzmann, André Grüneberg Handelsregister: Amtsgericht Charlottenburg, HRB 143581 B
I don't know much... But I imagined a solution along the lines you mentioned, Erin Shepherd. What I thought of is actually a step backwards, because from what I know all IXPs have tried to avoid Multi-RIB. But I imagined a Multi-RIB where the peer does not impose RFC9234 on the participant peers in each respective RIB, and when it comes time to leak from the per-participant RIB to the main one, then it does impose OTC and similarities. This seems like total overkill to me, but I imagine it could work. Em sex., 13 de jun. de 2025 às 07:47, Erin Shepherd < bird-users@erinshepherd.net> escreveu:
On Fri, 13 Jun 2025, at 12:31, André Grüneberg wrote:
As far as I can see RFC9234 does not mandate handling a route leak with Treat-as-widthdraw. It just refers to leaking routes to be ineligible (for further use).
My understanding: a leaked route should be present in Adj-RIB-In, but not into Loc-RIB.
I do understand that Bird does not follow the traditional path of other BGP speakers and has no Adj-RIB-In/Out. In a multi-table route server setup Adj-RIB-In/Out is mimicked by the per-peer-table. In a single-table setup, the leaked route would go into the main table. So the question is: Could you imagine another way (i.e. different from Treat-as-withdraw) of handling "ineligible" routes?
Bird normally operates without Adj-RIB-In, but can be configured to operate with one:
import table *switch* A BGP import table contains all received routes from given BGP neighbor, before application of import filters. It is also called *Adj-RIB-In* in BGP terminology. BIRD BGP by default operates without import tables, in which case received routes are just processed by import filters, accepted ones are stored in the master table, and the rest is forgotten. Enabling import table allows to store unprocessed routes, which can be examined later by show route, and can be used to reconfigure import filters without full route refresh. Default: off.
(I assume this contains routes discarded because of an incorrect OTC attribute but I have not verified this. Even then I'm not sure Bird can (currently) use it to give you information on why routes were filtered)
- Erin
-- Douglas Fernando Fischer Engº de Controle e Automação
BMP might be the answer? It seems to me one should be able to observe those routes there. On Fri, Jun 13, 2025 at 1:41 PM Douglas Fischer <fischerdouglas@gmail.com> wrote:
I don't know much... But I imagined a solution along the lines you mentioned, Erin Shepherd.
What I thought of is actually a step backwards, because from what I know all IXPs have tried to avoid Multi-RIB. But I imagined a Multi-RIB where the peer does not impose RFC9234 on the participant peers in each respective RIB, and when it comes time to leak from the per-participant RIB to the main one, then it does impose OTC and similarities.
This seems like total overkill to me, but I imagine it could work.
Em sex., 13 de jun. de 2025 às 07:47, Erin Shepherd < bird-users@erinshepherd.net> escreveu:
On Fri, 13 Jun 2025, at 12:31, André Grüneberg wrote:
As far as I can see RFC9234 does not mandate handling a route leak with Treat-as-widthdraw. It just refers to leaking routes to be ineligible (for further use).
My understanding: a leaked route should be present in Adj-RIB-In, but not into Loc-RIB.
I do understand that Bird does not follow the traditional path of other BGP speakers and has no Adj-RIB-In/Out. In a multi-table route server setup Adj-RIB-In/Out is mimicked by the per-peer-table. In a single-table setup, the leaked route would go into the main table. So the question is: Could you imagine another way (i.e. different from Treat-as-withdraw) of handling "ineligible" routes?
Bird normally operates without Adj-RIB-In, but can be configured to operate with one:
import table *switch* A BGP import table contains all received routes from given BGP neighbor, before application of import filters. It is also called *Adj-RIB-In* in BGP terminology. BIRD BGP by default operates without import tables, in which case received routes are just processed by import filters, accepted ones are stored in the master table, and the rest is forgotten. Enabling import table allows to store unprocessed routes, which can be examined later by show route, and can be used to reconfigure import filters without full route refresh. Default: off.
(I assume this contains routes discarded because of an incorrect OTC attribute but I have not verified this. Even then I'm not sure Bird can (currently) use it to give you information on why routes were filtered)
- Erin
-- Douglas Fernando Fischer Engº de Controle e Automação
BMP is only for those that receive the BMP Stream. And BMP stream is not to be sent publicly. I guess the bigger pain here is to make those routes appear on Alice-LG. And it will only appear on Alice if the routes are on RIB. Remembering that Alice's connector can be deployed: - Directly on RS, as in DE-CIX. This brings much more useful info, but can cause some extra effort on RSs. - In a reflected RS, as in AMS-IX. This protects production RSs from query-floods, but lose several infos. P.S.: As a network operator, I don't like this method. Other points are the route collectors that need to get those routes also via BGP. For example(if I'm not mistaken) it is through this way that MANRS get their infos to do some reporting of routing security. Em sex., 13 de jun. de 2025 às 08:52, Alexander Zubkov <green@qrator.net> escreveu:
BMP might be the answer? It seems to me one should be able to observe those routes there.
On Fri, Jun 13, 2025 at 1:41 PM Douglas Fischer <fischerdouglas@gmail.com> wrote:
I don't know much... But I imagined a solution along the lines you mentioned, Erin Shepherd.
What I thought of is actually a step backwards, because from what I know all IXPs have tried to avoid Multi-RIB. But I imagined a Multi-RIB where the peer does not impose RFC9234 on the participant peers in each respective RIB, and when it comes time to leak from the per-participant RIB to the main one, then it does impose OTC and similarities.
This seems like total overkill to me, but I imagine it could work.
Em sex., 13 de jun. de 2025 às 07:47, Erin Shepherd < bird-users@erinshepherd.net> escreveu:
On Fri, 13 Jun 2025, at 12:31, André Grüneberg wrote:
As far as I can see RFC9234 does not mandate handling a route leak with Treat-as-widthdraw. It just refers to leaking routes to be ineligible (for further use).
My understanding: a leaked route should be present in Adj-RIB-In, but not into Loc-RIB.
I do understand that Bird does not follow the traditional path of other BGP speakers and has no Adj-RIB-In/Out. In a multi-table route server setup Adj-RIB-In/Out is mimicked by the per-peer-table. In a single-table setup, the leaked route would go into the main table. So the question is: Could you imagine another way (i.e. different from Treat-as-withdraw) of handling "ineligible" routes?
Bird normally operates without Adj-RIB-In, but can be configured to operate with one:
import table *switch* A BGP import table contains all received routes from given BGP neighbor, before application of import filters. It is also called *Adj-RIB-In* in BGP terminology. BIRD BGP by default operates without import tables, in which case received routes are just processed by import filters, accepted ones are stored in the master table, and the rest is forgotten. Enabling import table allows to store unprocessed routes, which can be examined later by show route, and can be used to reconfigure import filters without full route refresh. Default: off.
(I assume this contains routes discarded because of an incorrect OTC attribute but I have not verified this. Even then I'm not sure Bird can (currently) use it to give you information on why routes were filtered)
- Erin
-- Douglas Fernando Fischer Engº de Controle e Automação
-- Douglas Fernando Fischer Engº de Controle e Automação
On Fri, Jun 13, 2025 at 01:51:59PM +0200, Alexander Zubkov via Bird-users wrote:
BMP might be the answer? It seems to me one should be able to observe those routes there.
BMP is sending the same paths that are visible in BIRD (i.e., pre-filter or post-filter, but no invalid). -- Elen sila lumenn' omentielvo Ondrej 'Santiago' Zajicek (email: santiago@crfreenet.org) "To err is human -- to blame it on a computer is even more so."
On Fri, Jun 13, 2025 at 12:31:09PM +0200, André Grüneberg wrote:
For a lot of errors in UPDATE messages, it's perfectly fine to treat those as an error and do Treat-as-withdraw (as described in RFC7606). This includes checking the length of the OTC attribute. I am not asking to see routes with protocol errors in the routing table.
As far as I can see RFC9234 does not mandate handling a route leak with Treat-as-widthdraw. It just refers to leaking routes to be ineligible (for further use). My understanding: a leaked route should be present in Adj-RIB-In, but not into Loc-RIB.
You are right, we do not have clear concept of 'route is ineligible' and in most cases (like OTC mismatch or AS path loop) we do treat-as-withdraw. One exception is unresolvable next hop, which can be transient and therefore such route cannot be removed. This is handled by just setting it as unreachable and de-preferencing it in best path selection (but it would still be selected and announced if no other route is available).
I do understand that Bird does not follow the traditional path of other BGP speakers and has no Adj-RIB-In/Out.
That is true that we do not have Adj-RIB-In by default, but note that routes kept by BIRD in regular tables are not just Loc-RIB (as that would be just the selected best routes), but any routes that passed import filters. In that case changing the behavior to have explicit 'route is ineligible' and importing such routes (but not selecting or exporting them to other protocols) would make sense. -- Elen sila lumenn' omentielvo Ondrej 'Santiago' Zajicek (email: santiago@crfreenet.org) "To err is human -- to blame it on a computer is even more so."
Hi Ondrej, On Fri, 13 Jun 2025 at 16:12, Ondrej Zajicek <santiago@crfreenet.org> wrote:
On Fri, Jun 13, 2025 at 12:31:09PM +0200, André Grüneberg wrote:
As far as I can see RFC9234 does not mandate handling a route leak with Treat-as-widthdraw. It just refers to leaking routes to be ineligible (for further use). My understanding: a leaked route should be present in Adj-RIB-In, but not into Loc-RIB. You are right, we do not have clear concept of 'route is ineligible' and in most cases (like OTC mismatch or AS path loop) we do treat-as-withdraw. One exception is unresolvable next hop, which can be transient and therefore such route cannot be removed. This is handled by just setting it as unreachable and de-preferencing it in best path selection (but it would still be selected and announced if no other route is available).
Oops, it seems like I opened a can of worms. Looking at RFC4271 section 3.2 b), any route in Loc-RIB must have a resolvable next hop.
I do understand that Bird does not follow the traditional path of other BGP
speakers and has no Adj-RIB-In/Out. That is true that we do not have Adj-RIB-In by default, but note that routes kept by BIRD in regular tables are not just Loc-RIB (as that would be just the selected best routes), but any routes that passed import filters.
IMO Loc-RIB is not only the best path, but accepted routes = those that passed the import filters. And RFC4271 does not mandate you to have a strict distinction between these tables, but uses those for explaining the logic.
In that case changing the behavior to have explicit 'route is ineligible' and importing such routes (but not selecting or exporting them to other protocols) would make sense.
Thinking about all this, I can imagine an (internal) attribute that identifies ineligible (but otherwise valid) routes. Maybe values being a bit set for various reasons? 0x1 = next_hop unresolvable 0x2 = OTC route leak 0x4 = route damped ... As long as the attribute is non-zero, the route is not going anywhere (accept means reject). Of course, those of us feeling lucky could modify the value of the attribute in a filter. Would that be a major undertaking? We would not need the configuration parameters suggested by Maria (as non-Bird-developer :). The effects should be the same, unless someone programming filters (!= operator as per RFC9234) has any insane ideas. Have a pleasant weekend, André -- André Grüneberg, Managing Director andre.grueneberg@bcix.de +49 30 2332195 42 BCIX Management GmbH Albrechtstr. 110 12103 Berlin Germany Geschäftsführer/Managing Directors: Jens Lietzmann, André Grüneberg Handelsregister: Amtsgericht Charlottenburg, HRB 143581 B
Hi Maria, Ondrej, Bird community, We have now (silently) implemented OTC handling in our route servers without setting the role in the protocol. For the reference, we extended the ingress filter with: define IXP_LC_FILTERED_ROUTE_LEAK_DETECTED = ( routeserverasn, 1101, 50 ); if defined( bgp_otc ) then { bgp_large_community.add( IXP_LC_FILTERED_ROUTE_LEAK_DETECTED ); } The egress filter (which already implicitly rejects routes with the community above) was enhanced with: if ! defined( bgp_otc ) then { bgp_otc = routeserverasn; } [actually it's a bit more complex, but this is due to non-standard route server features for BCIX Outreach] BTW: I have already created a feature request for Alice-LG to display the OTC attribute (https://github.com/alice-lg/alice-lg/issues/174). I'd really love to also announce the roles capability, but we'd need some way in Bird to say "do not treat-as-withdraw". Is there any chance we can get this functionality? Best wishes, André On Fri, 13 Jun 2025 at 17:19, André Grüneberg <andre.grueneberg@bcix.de> wrote:
Hi Ondrej,
On Fri, 13 Jun 2025 at 16:12, Ondrej Zajicek <santiago@crfreenet.org> wrote:
On Fri, Jun 13, 2025 at 12:31:09PM +0200, André Grüneberg wrote:
As far as I can see RFC9234 does not mandate handling a route leak with Treat-as-widthdraw. It just refers to leaking routes to be ineligible (for further use). My understanding: a leaked route should be present in Adj-RIB-In, but not into Loc-RIB. You are right, we do not have clear concept of 'route is ineligible' and in most cases (like OTC mismatch or AS path loop) we do treat-as-withdraw. One exception is unresolvable next hop, which can be transient and therefore such route cannot be removed. This is handled by just setting it as unreachable and de-preferencing it in best path selection (but it would still be selected and announced if no other route is available).
Oops, it seems like I opened a can of worms. Looking at RFC4271 section 3.2 b), any route in Loc-RIB must have a resolvable next hop.
I do understand that Bird does not follow the traditional path of other BGP
speakers and has no Adj-RIB-In/Out. That is true that we do not have Adj-RIB-In by default, but note that routes kept by BIRD in regular tables are not just Loc-RIB (as that would be just the selected best routes), but any routes that passed import filters.
IMO Loc-RIB is not only the best path, but accepted routes = those that passed the import filters. And RFC4271 does not mandate you to have a strict distinction between these tables, but uses those for explaining the logic.
In that case changing the behavior to have explicit 'route is ineligible' and importing such routes (but not selecting or exporting them to other protocols) would make sense.
Thinking about all this, I can imagine an (internal) attribute that identifies ineligible (but otherwise valid) routes. Maybe values being a bit set for various reasons? 0x1 = next_hop unresolvable 0x2 = OTC route leak 0x4 = route damped ...
As long as the attribute is non-zero, the route is not going anywhere (accept means reject). Of course, those of us feeling lucky could modify the value of the attribute in a filter.
Would that be a major undertaking? We would not need the configuration parameters suggested by Maria (as non-Bird-developer :). The effects should be the same, unless someone programming filters (!= operator as per RFC9234) has any insane ideas.
Have a pleasant weekend, André -- André Grüneberg, Managing Director andre.grueneberg@bcix.de +49 30 2332195 42
BCIX Management GmbH Albrechtstr. 110 12103 Berlin Germany
Geschäftsführer/Managing Directors: Jens Lietzmann, André Grüneberg Handelsregister: Amtsgericht Charlottenburg, HRB 143581 B
-- André Grüneberg, Managing Director andre.grueneberg@bcix.de +49 30 2332195 42 BCIX Management GmbH Albrechtstr. 110 12103 Berlin Germany Geschäftsführer/Managing Directors: Jens Lietzmann, André Grüneberg Handelsregister: Amtsgericht Charlottenburg, HRB 143581 B
Hello André, (with my BIRD Team hat on) On Thu, Jun 26, 2025 at 12:27:04PM +0200, André Grüneberg wrote:
We have now (silently) implemented OTC handling in our route servers without setting the role in the protocol.
Oh nice!
For the reference, we extended the ingress filter with:
define IXP_LC_FILTERED_ROUTE_LEAK_DETECTED = ( routeserverasn, 1101, 50 ); if defined( bgp_otc ) then { bgp_large_community.add( IXP_LC_FILTERED_ROUTE_LEAK_DETECTED ); }
The egress filter (which already implicitly rejects routes with the community above) was enhanced with: if ! defined( bgp_otc ) then { bgp_otc = routeserverasn; }
Looks feasible and correct on first sight.
I'd really love to also announce the roles capability, but we'd need some way in Bird to say "do not treat-as-withdraw". Is there any chance we can get this functionality?
We are expecting to implement this. Considering current short-term planning, it may come back to our table in the late autumn. (This is not a deadline promise.) We could obviously implement this as a non-systematic hack like tomorrow or so, but that would make our code much less maintainable. Thank you for the feature request, have a nice summer! Maria -- Maria Matejka (she/her) | BIRD Team Leader | CZ.NIC, z.s.p.o.
Hi André,
I was considering your "personal speculation" and came to the conclusion that I agree, this should not be implemented.
For a lot of errors in UPDATE messages, it's perfectly fine to treat those as an error and do Treat-as-withdraw (as described in RFC7606). This includes checking the length of the OTC attribute. I am not asking to see routes with protocol errors in the routing table.
Oh there could be many different options … maybe this way? (Still speculating in my personal capacity, it's weekend and the next team meeting is on tuesday.) allow leaks [off/filtered/on] allow invalid next hop [off/filtered/on] allow as sets [off/filtered/on] allow malformed [off/filtered/on] ... Here `off` would reject these altogether (default option), `filtered` would pass them to filters but always reject, and `on` would allow accepting them to the table?
As far as I can see RFC9234 does not mandate handling a route leak with Treat-as-widthdraw. It just refers to leaking routes to be ineligible (for further use).
Oh yes, but it's kinda similar to rejecting AS sets ... :wink:
My understanding: a leaked route should be present in Adj-RIB-In, but not into Loc-RIB.
That's what would actually be possible with that `allow leaks filtered`.
I do understand that Bird does not follow the traditional path of other BGP speakers and has no Adj-RIB-In/Out. In a multi-table route server setup Adj-RIB-In/Out is mimicked by the per-peer-table. In a single-table setup, the leaked route would go into the main table. So the question is: Could you imagine another way (i.e. different from Treat-as-withdraw) of handling "ineligible" routes?
Not with the current implementation, but it's doable e.g. in the way shown above.
How do you treat routes that do not pass next-hop lookup? Shouldn't these be ineligible as well? How about doing something similar for "ineligible by OTC"?
Well, errmhm … these with unreachable nexthops are usually ineligible but kept in the table (just not selected). Usually. Some nexthops are also considered malformed (e.g. a zero nexthop) and rejected without reaching filters. Occassionally we open this can of worms in our office, find out that there are much more worms than we expected, see that some of them are holding holy hand grenades, and we wisely decide to let the whole thing sleep for several more years. Have a nice day! Maria -- Maria Matejka (she/her) | BIRD Team Leader | CZ.NIC, z.s.p.o.
participants (7)
-
Alexander Zubkov -
André Grüneberg -
Douglas Fischer -
Erin Shepherd -
Maria Matejka -
Ondrej Zajicek -
Radu-Adrian Feurdean