bgpd: conditional default-originate using route-map

Incorporate a patch by Svetozar Mihailov which implements
default-originate route-maps to behave as expected, i.e. allowing
the default route to be advertised conditionally, depending on a
criterion given by the route-map.

I am aware that the performance attributes of the following implementation
are far from optimal. However, this affects only code paths belonging to
a feature that is broken without this patch, therefore, it seems reasonable
to me to have this in the mainline for now.

Cc: Svetozar Mihailov <quagga@j.zarhi.com>
Reported-by: Sébastien Cramatte <scramatte@gmail.com>
Signed-off-by: Christian Franke <chris@opensourcerouting.org>
Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
This commit is contained in:
Christian Franke 2012-12-07 16:45:52 +00:00 committed by David Lamparter
parent 86998bc2bc
commit dcab1bb822
3 changed files with 47 additions and 12 deletions

5
NEWS
View File

@ -1,5 +1,10 @@
Note: this file lists major user-visible changes only. Note: this file lists major user-visible changes only.
- [bgpd] The semantics of default-originate route-map have changed.
The route-map is now used to advertise the default route conditionally.
The old behaviour which allowed to set attributes on the originated
default route is no longer supported.
* Changes in Quagga 0.99.21 * Changes in Quagga 0.99.21
- [bgpd] BGP multipath support has been merged - [bgpd] BGP multipath support has been merged

View File

@ -506,6 +506,16 @@ bgp_scan (afi_t afi, safi_t safi)
else if (afi == AFI_IP6) else if (afi == AFI_IP6)
zlog_debug ("scanning IPv6 Unicast routing tables"); zlog_debug ("scanning IPv6 Unicast routing tables");
} }
/* Reevaluate default-originate route-maps and announce/withdraw
* default route if neccesary. */
for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
{
if (peer->status == Established
&& CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)
&& peer->default_rmap[afi][safi].name)
bgp_default_originate (peer, afi, safi, 0);
}
} }
/* BGP scan thread. This thread check nexthop reachability. */ /* BGP scan thread. This thread check nexthop reachability. */

View File

@ -2462,8 +2462,9 @@ bgp_default_originate (struct peer *peer, afi_t afi, safi_t safi, int withdraw)
struct attr attr; struct attr attr;
struct aspath *aspath; struct aspath *aspath;
struct prefix p; struct prefix p;
struct bgp_info binfo;
struct peer *from; struct peer *from;
struct bgp_node *rn;
struct bgp_info *ri;
int ret = RMAP_DENYMATCH; int ret = RMAP_DENYMATCH;
if (!(afi == AFI_IP || afi == AFI_IP6)) if (!(afi == AFI_IP || afi == AFI_IP6))
@ -2505,21 +2506,37 @@ bgp_default_originate (struct peer *peer, afi_t afi, safi_t safi, int withdraw)
if (peer->default_rmap[afi][safi].name) if (peer->default_rmap[afi][safi].name)
{ {
binfo.peer = bgp->peer_self;
binfo.attr = &attr;
SET_FLAG (bgp->peer_self->rmap_type, PEER_RMAP_TYPE_DEFAULT); SET_FLAG (bgp->peer_self->rmap_type, PEER_RMAP_TYPE_DEFAULT);
for (rn = bgp_table_top(bgp->rib[afi][safi]); rn; rn = bgp_route_next(rn))
{
for (ri = rn->info; ri; ri = ri->next)
{
struct attr dummy_attr;
struct attr_extra dummy_extra;
struct bgp_info info;
ret = route_map_apply (peer->default_rmap[afi][safi].map, &p, /* Provide dummy so the route-map can't modify the attributes */
RMAP_BGP, &binfo); dummy_attr.extra = &dummy_extra;
bgp_attr_dup(&dummy_attr, ri->attr);
info.peer = ri->peer;
info.attr = &dummy_attr;
ret = route_map_apply(peer->default_rmap[afi][safi].map, &rn->p,
RMAP_BGP, &info);
/* The route map might have set attributes. If we don't flush them
* here, they will be leaked. */
bgp_attr_flush(&dummy_attr);
if (ret != RMAP_DENYMATCH)
break;
}
if (ret != RMAP_DENYMATCH)
break;
}
bgp->peer_self->rmap_type = 0; bgp->peer_self->rmap_type = 0;
if (ret == RMAP_DENYMATCH) if (ret == RMAP_DENYMATCH)
{ withdraw = 1;
bgp_attr_flush (&attr);
withdraw = 1;
}
} }
if (withdraw) if (withdraw)
@ -2530,8 +2547,11 @@ bgp_default_originate (struct peer *peer, afi_t afi, safi_t safi, int withdraw)
} }
else else
{ {
SET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_DEFAULT_ORIGINATE); if (! CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_DEFAULT_ORIGINATE))
bgp_default_update_send (peer, &attr, afi, safi, from); {
SET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_DEFAULT_ORIGINATE);
bgp_default_update_send (peer, &attr, afi, safi, from);
}
} }
bgp_attr_extra_free (&attr); bgp_attr_extra_free (&attr);