diff options
Diffstat (limited to 'proto/bgp/attrs.c')
-rw-r--r-- | proto/bgp/attrs.c | 53 |
1 files changed, 52 insertions, 1 deletions
diff --git a/proto/bgp/attrs.c b/proto/bgp/attrs.c index 73eb4040..3b88791d 100644 --- a/proto/bgp/attrs.c +++ b/proto/bgp/attrs.c @@ -1173,6 +1173,9 @@ bgp_community_filter(struct bgp_proto *p, rte *e) DBG("\tNO_EXPORT\n"); return 1; } + + if (!p->conn->peer_llgr_aware && int_set_contains(d, BGP_COMM_LLGR_STALE)) + return 1; } return 0; @@ -1233,6 +1236,19 @@ rte_resolvable(rte *rt) return (rd == RTD_ROUTER) || (rd == RTD_DEVICE) || (rd == RTD_MULTIPATH); } +static inline int +rte_stale(rte *r) +{ + if (r->u.bgp.stale < 0) + { + /* If staleness is unknown, compute and cache it */ + eattr *a = ea_find(r->attrs->eattrs, EA_CODE(EAP_BGP, BA_COMMUNITY)); + r->u.bgp.stale = a && int_set_contains(a->u.ptr, BGP_COMM_LLGR_STALE); + } + + return r->u.bgp.stale; +} + int bgp_rte_better(rte *new, rte *old) { @@ -1257,6 +1273,14 @@ bgp_rte_better(rte *new, rte *old) if (n < o) return 0; + /* LLGR draft - depreference stale routes */ + n = rte_stale(new); + o = rte_stale(old); + if (n > o) + return 0; + if (n < o) + return 1; + /* Start with local preferences */ x = ea_find(new->attrs->eattrs, EA_CODE(EAP_BGP, BA_LOCAL_PREF)); y = ea_find(old->attrs->eattrs, EA_CODE(EAP_BGP, BA_LOCAL_PREF)); @@ -1378,6 +1402,10 @@ bgp_rte_mergable(rte *pri, rte *sec) if (!rte_resolvable(sec)) return 0; + /* LLGR draft - depreference stale routes */ + if (rte_stale(pri) != rte_stale(sec)) + return 0; + /* Start with local preferences */ x = ea_find(pri->attrs->eattrs, EA_CODE(EAP_BGP, BA_LOCAL_PREF)); y = ea_find(sec->attrs->eattrs, EA_CODE(EAP_BGP, BA_LOCAL_PREF)); @@ -1580,6 +1608,27 @@ bgp_rte_recalculate(rtable *table, net *net, rte *new, rte *old, rte *old_best) return old_is_group_best; } +struct rte * +bgp_rte_modify_stale(struct rte *r, struct linpool *pool) +{ + eattr *a = ea_find(r->attrs->eattrs, EA_CODE(EAP_BGP, BA_COMMUNITY)); + struct adata *ad = a ? a->u.ptr : NULL; + + if (ad && int_set_contains(ad, BGP_COMM_NO_LLGR)) + return NULL; + + if (ad && int_set_contains(ad, BGP_COMM_LLGR_STALE)) + return r; + + r = rte_cow_rta(r, pool); + bgp_attach_attr(&(r->attrs->eattrs), pool, BA_COMMUNITY, + (uintptr_t) int_set_add(pool, ad, BGP_COMM_LLGR_STALE)); + r->u.bgp.stale = 1; + + return r; +} + + static struct adata * bgp_aggregator_convert_to_new(struct adata *old, struct linpool *pool) { @@ -1589,7 +1638,6 @@ bgp_aggregator_convert_to_new(struct adata *old, struct linpool *pool) return newa; } - /* Take last req_as ASNs from path old2 (in 2B format), convert to 4B format * and append path old4 (in 4B format). */ @@ -1985,6 +2033,9 @@ bgp_get_route_info(rte *e, byte *buf, ea_list *attrs) if (e->u.bgp.suppressed) buf += bsprintf(buf, "-"); + if (rte_stale(e)) + buf += bsprintf(buf, "s"); + if (e->attrs->hostentry) { if (!rte_resolvable(e)) |