Missing route that is shown in filter used by eBGP

Nico Schottelius nico.schottelius at ungleich.ch
Thu Nov 20 13:59:48 CET 2025


Hello,

today I have a related issue with missing route export:

- In a bgp instance I use the filter "from_our_place_to_internet"
- If I run "show route filter from_our_place_to_internet" all correct
  routes match
- However if I check on the other eBGP end, the route is actually *not*
  received (it's not filtered, it is really not received)
- If I "hack" the filter as follows, bird DOES export the route:
  # Hack 2025-11-20
  if ( net ~ [ 185.203.114.0/23+ ] ) then {
     print "Exporting 185.203.114.0 to internet";
     accept;
  }

- Some thoughts:
  - The route is direct, static and babel received
  - Our filter matches RTS_STATIC
  - However bird seems to "prefer" the direct route
  - We do not export direct marked routes, but static routes
  - Is that the cause of the problem? But it is also static...

However it does not make sense to me, thus wondering:

- Why does bird show the route in the filter output?
- Why does bird show not export it via eBGP?
- Why does my hack then make it work in the end?


Details below, any help appreciated as this is driving me nuts.

Best regards,

Nico

--------------------------------------------------------------------------------

a) the affected route

bird> show route all 185.203.114.0/23
Table master4:
185.203.114.0/23     unicast [direct1 2025-11-07] * (240)
        dev eth4
        Type: device univ
                     unicast [place6_10_v4 2025-11-07] (200)
        dev eth4
        Type: static univ
                     unicast [babel1 12:47:44.565 from fe80::3eec:efff:fecb:d81b] (130/96) [00:00:00:00:93:4e:c2:43]
        via 147.78.194.67 on eth1
        Type: Babel univ
        Babel.metric: 96
        Babel.router_id: 00:00:00:00:93:4e:c2:43
bird>

b) the show route output

bird> show route filter from_our_place_to_internet
Table master4:
185.203.114.0/23     unicast [place6_10_v4 2025-11-07] (200)
        dev eth4
...


c) the filter itself

filter from_our_place_to_internet {
  if(!has_internet_length()) then reject;
  if(is_default_route()) then reject;


  if(is_from_local_asn() ||
     is_emitted_by_one_of_our_asn_directly() ||
     should_export_to_internet_from_customer()
     ) then accept;

  reject;

}

... where the related functions are:


function has_internet_length() -> bool
{
  if ((net.type = NET_IP6 && net.len > 48) ||
      (net.type = NET_IP4 && net.len > 24)) then {
          return false;
  }
  return true;
}

function is_v6_default() -> bool
{
  if (net = ::/0) then return true;
  return false;
}

function is_v4_default() -> bool
{
  if (net = 0.0.0.0/0) then return true;
  return false;
}

function is_default_route() -> bool
{
  if(is_v6_default() || is_v4_default()) then return true;
  return false;
}

function is_from_local_asn() -> bool
{
  if(source = RTS_STATIC) then return true;
  if(source = RTS_BGP && bgp_path.len = 0) then return true;

  return false;
}

function emitted_from_one_of_our_asn() -> bool
{
  if(bgp_path.last ~ our_asn) then return true;
  return false;
}

function should_export_to_internet_from_customer() -> bool
{
  # We don't consider non-internet networks
  if(!has_internet_length()) then return false;

  if (
     (bgp_path.first ~ our_asn) &&   # received from one of our asn
     (bgp_path.len = 2)         &&   # one of our ASNs received it
     (bgp_path.last ~ customer_asn)  # one of our customers emitted it and we accept it
     ) then return true;

   if (
      (bgp_path.len = 1)         &&   # we ASNs received it directly
      (bgp_path.last ~ customer_asn)  # one of our customers emitted it and we accept it
      ) then return true;

   return false;
}


--
Sustainable and modern Infrastructures by ungleich.ch


More information about the Bird-users mailing list