Problem redistributing routes from iBGP to OSPF

Pete Heist pete.heist at lbcfree.net
Thu Jul 10 10:33:18 CEST 2025


Hi,

I'm seeing a problem with route redistribution that I hope someone can
help with...

When redistributing a default route from iBGP to OSPF, other OSPF
routers do not seem to respect the value of ospf_metric2 set on
exported routes. If I define the default route in a static protocol
instead of redistributing it, I do not see the problem.

I *think* I see a clue in the output from "show ospf state" below in
the two cases. When using a static protocol, there are different route
distances for each default route- 0 and 10. When doing route
redistribution, both routers show a distance of 65535. That seems odd,
and I'm not sure why it is. Also note that all iBGP peerings are IPv6,
so BGP-MP is in use.

The topology is as follows:

           ^                                                 ^
           |                                                 |
          eBGP                                             eBGP
           |                                                 |
        +------+                                         +------+
        | gw1  |-----------------------------------------| gw2  |
        +--+---+                        <-- 0.0.0.0/0 ---+---+--+
           |  | \                             iBGP      / |  |
           |  |   \                                   /   |  |
           |  |     \                               /     |  |
           |  |       \                           /       |  |
           | 0.0.0.0/0  \                       /  0.0.0.0/0 |
           | |  iBGP  \   \                   /   /  iBGP  | |
           | v          v   \               /   v          v |
           |                  \           /                  |
           |                    \       /                    |
           |                      \   /                      |
           |                        x                        |
           |                      /   \                      |
           |                    /       \                    |
           |                  /           \                  |
           | ^          ^   /               \   ^          ^ |
           | |  iBGP  /   /                   \   \  iBGP  | |
           | A.B.C.D/X  /                       \  A.B.C.D/X |
           |  |       /                           \       |  |
           |  |     /                               \     |  |
           |  |   /                                   \   |  |
           |  | /                                       \ |  |
        +--+---+                                         +---+--+
        | nat1 |-----------------------------------------| nat2 |
        +------+                                         +------+
           |                                                 |
          OSPF                                             OSPF
      E2 metric 10                                    E2 metric 100
       0.0.0.0/0                                         0.0.0.0/0
           |                                                 |
           v                                                 v

* Four routers in an iBGP full mesh
  * gw1 and gw2 are the ASBRs, with full BGP tables
  * nat1 and nat2 are core routers doing NAT44
  * NOTE: all iBGP peerings are IPv6 only, so BGP-MP is in use
* Default route:
  * exported by gw1 and gw2 using iBGP
  * imported by nat1 and nat2 using iBGP
  * redistributed by nat1 and nat2 using OSPF into the LAN
* Different metrics from nat1 and nat2 seem not to be respected
* Problem occurs on both BIRD 2.0.12 and 2.17.1

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

STATIC PROTOCOL (what works)

If I define default routes in a static protocol on nat1 and nat2, and
set ospf_metric2 on an export filter, it works as expected. Routers on
the LAN respect the metric and prefer the route from nat1.

#
# Routing table on another OSPF host running BIRD
#
# Regardless of which order nat1 and nat2 are started in, the
# default route chosen is the one with the lower metric, as expected.
#

bird> show ospf state ospf4

area 0.0.0.0

	router <gw1 IPv4 IP>
		distance 0
		...
		external 0.0.0.0/0 metric2 10

	router <gw2 IPv4 IP>
		distance 10
		...
		external 0.0.0.0/0 metric2 100

bird> show route for 0.0.0.0/0 all
Table master4:
0.0.0.0/0            unicast [ospf4 09:26:57.341] * E2 (150/65535/10)
[<gw1 IPv4 IP>]
	via <gw1 IPv4 IP> on eth0
	Type: OSPF-E2 univ
	OSPF.metric1: 65535
	OSPF.metric2: 10
	OSPF.tag: 0x00000000
	OSPF.router_id: <gw1 IPv4 IP>

#
# Partial config from gw1/gw2...
#

# NO_KERNEL_EXPORT, if defined, flags a route for NOT exporting to the
# kernel.
attribute int NO_KERNEL_EXPORT;

# IBGP_EXPORT, if defined, flags a route for export to iBGP peers.
attribute int IBGP_EXPORT;

ipv4 table Tibgp4;

# default route injected on gw1/gw2 with static protocol into custom
table
protocol static Sibgp4 {
    ipv4 {
        table Tibgp4;
        import filter {
            IBGP_EXPORT = 1;
            NO_KERNEL_EXPORT = 1;
            accept;
        };
    };
    route 0.0.0.0/0 unreachable;
}

# pipe to master
protocol pipe Pibgp4 {
    table master4;
    peer table Tibgp4;
    import where !defined(NO_KERNEL_EXPORT);
    export where defined(IBGP_EXPORT);
}

# sample peering for nat1, with a bunch of things left out
protocol bgp nat1 from IBGP {
    ipv4 {
        ...
        table Tibgp4;
        export where defined(IBGP_EXPORT);
    };
    ipv6 {
        ...
        table Tibgp6;
        export where defined(IBGP_EXPORT);
    };
    # anonymized addresses below, but shows that IPv6 LLA is used
    interface "bond0.A";
    source address fe80::A:1;
    neighbor fe80::A:2 internal;
    ...
}

#
# Partial config for nat1/nat2...
#

# Default route added in a static protocol. This works.
protocol static Sospf4 {
    ipv4 {
        table Tospf4;
        import filter {
            OSPF_EXPORT = 1;
            accept;
        };
    };
    route 0.0.0.0/0 unreachable;
}

# ospf_metric2 set on an export filter.
protocol ospf v2 ospf4 {
    ipv4 {
        table Tospf4;
        import all;
        export filter {
            if !defined(OSPF_EXPORT) then reject;
            ospf_metric2 = 10; # for nat1, or 100 for nat2
            accept;
        };
    };
    ...
}

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

ROUTE REDISTRIBUTION (what does not work)

#
# Routing table on another OSPF host running BIRD
#
# !!! Even though nat1 and nat2 are both running, and nat2 has a
# lower value for OSPF.metric2, its default route is not chosen.
# The default route in the OSPF database is from the router that
# started first.

bird> show ospf state ospf4

area 0.0.0.0
	...
	router <gw1 IPv4 IP>
		# !!! distance is 65535- with static protocol it's 0
		distance 65535
 		...
		# default route not present when started second

	router <gw2 IPv4 IP>
		# !!! distance is 65535- with static protocol it's 10
		distance 65535
 		...
		# external default route with higher metric 100 is
used
		external 0.0.0.0/0 metric2 100

# The default route is gw2, which is unexpected when it has a
# higher metric2.
bird> show route for 0.0.0.0/0 all
Table master4:
0.0.0.0/0            unicast [ospf4 08:37:10.342] * E2 (150/65535/100)
[<gw2
IPv4 IP>]
	via <gw2 IPv4 IP> on eth0
	Type: OSPF-E2 univ
	OSPF.metric1: 65535
	OSPF.metric2: 100
	OSPF.tag: 0x00000000
	OSPF.router_id: <gw2 IPv4 IP>

#
# Config for gw1/gw2 is same as above, when using static protocol...
#

#
# Partial config from nat1/nat2...
#

# OSPF_EXPORT, if defined, flags a route for export via OSPF.
attribute int OSPF_EXPORT;

ipv4 table Tibgp4;

# ibgp_in_primary4 filters primary IPv4 routes imported via iBGP.
filter ibgp_in_primary4 {
    if net = 0.0.0.0/0 then {
        OSPF_EXPORT = 1;
    }
    bgp_local_pref = 100;
    accept;
}

# pipe to master
protocol pipe Pibgp4 {
    table master4;
    peer table Tibgp4;
    import all;
    export where defined(IBGP_EXPORT);
}

protocol bgp gw1 from IBGP {
    description "gw1 - VLAN 3313";
    ipv4 {
        table Tibgp4;
        import filter ibgp_in_primary4;
        export where defined(IBGP_EXPORT);
        ...
    };
    ipv6 {
        table Tibgp6;
        import filter ibgp_in_primary6;
        export where defined(IBGP_EXPORT);
        ...
    };
    interface "bond0.A";
    source address fe80::A:2;
    neighbor fe80::A:1 internal;
    ...
}

# ospf_metric2 set on an export filter the same as with the static
# protocol case, but the metric seems to not be respected when
# the route is redistributed from iBGP.
protocol ospf v2 ospf4 {
    ipv4 {
        table Tospf4;
        import all;
        export filter {
            if !defined(OSPF_EXPORT) then reject;
            ospf_metric2 = 10; # 10 for nat1, 100 for nat2
            accept;
        };
    };
    ...
}

Thanks in advance for any help...

Pete



More information about the Bird-users mailing list