mirror of
https://gitlab.labs.nic.cz/labs/bird.git
synced 2024-05-11 16:54:54 +00:00
BGP: Long-lived graceful restart
The patch implements long-lived graceful restart for BGP, namely draft-uttaro-idr-bgp-persistence-03.
This commit is contained in:
@@ -229,6 +229,7 @@ struct proto {
|
||||
int (*rte_better)(struct rte *, struct rte *);
|
||||
int (*rte_same)(struct rte *, struct rte *);
|
||||
int (*rte_mergable)(struct rte *, struct rte *);
|
||||
struct rte * (*rte_modify)(struct rte *, struct linpool *);
|
||||
void (*rte_insert)(struct network *, struct rte *);
|
||||
void (*rte_remove)(struct network *, struct rte *);
|
||||
|
||||
|
@@ -231,6 +231,7 @@ typedef struct rte {
|
||||
#ifdef CONFIG_BGP
|
||||
struct {
|
||||
u8 suppressed; /* Used for deterministic MED comparison */
|
||||
s8 stale; /* Route is LLGR_STALE, -1 if unknown */
|
||||
} bgp;
|
||||
#endif
|
||||
#ifdef CONFIG_BABEL
|
||||
@@ -254,6 +255,7 @@ typedef struct rte {
|
||||
#define REF_FILTERED 2 /* Route is rejected by import filter */
|
||||
#define REF_STALE 4 /* Route is stale in a refresh cycle */
|
||||
#define REF_DISCARD 8 /* Route is scheduled for discard */
|
||||
#define REF_MODIFY 16 /* Route is scheduled for modify */
|
||||
|
||||
/* Route is valid for propagation (may depend on other flags in the future), accepts NULL */
|
||||
static inline int rte_is_valid(rte *r) { return r && !(r->flags & REF_FILTERED); }
|
||||
@@ -297,6 +299,7 @@ int rt_examine(rtable *t, net_addr *a, struct proto *p, struct filter *filter);
|
||||
rte *rt_export_merged(struct channel *c, net *net, rte **rt_free, linpool *pool, int silent);
|
||||
void rt_refresh_begin(rtable *t, struct channel *c);
|
||||
void rt_refresh_end(rtable *t, struct channel *c);
|
||||
void rt_modify_stale(rtable *t, struct channel *c);
|
||||
void rt_schedule_prune(rtable *t);
|
||||
void rte_dump(rte *);
|
||||
void rte_free(rte *);
|
||||
|
@@ -1437,6 +1437,28 @@ rte_discard(rte *old) /* Non-filtered route deletion, used during garbage collec
|
||||
rte_update_unlock();
|
||||
}
|
||||
|
||||
/* Modify existing route by protocol hook, used for long-lived graceful restart */
|
||||
static inline void
|
||||
rte_modify(rte *old)
|
||||
{
|
||||
rte_update_lock();
|
||||
|
||||
rte *new = old->sender->proto->rte_modify(old, rte_update_pool);
|
||||
if (new != old)
|
||||
{
|
||||
if (new)
|
||||
{
|
||||
if (!rta_is_cached(new->attrs))
|
||||
new->attrs = rta_lookup(new->attrs);
|
||||
new->flags = (old->flags & ~REF_MODIFY) | REF_COW;
|
||||
}
|
||||
|
||||
rte_recalculate(old->sender, old->net, new, old->attrs->src);
|
||||
}
|
||||
|
||||
rte_update_unlock();
|
||||
}
|
||||
|
||||
/* Check rtable for best route to given net whether it would be exported do p */
|
||||
int
|
||||
rt_examine(rtable *t, net_addr *a, struct proto *p, struct filter *filter)
|
||||
@@ -1521,6 +1543,26 @@ rt_refresh_end(rtable *t, struct channel *c)
|
||||
rt_schedule_prune(t);
|
||||
}
|
||||
|
||||
void
|
||||
rt_modify_stale(rtable *t, struct channel *c)
|
||||
{
|
||||
int prune = 0;
|
||||
|
||||
FIB_WALK(&t->fib, net, n)
|
||||
{
|
||||
rte *e;
|
||||
for (e = n->routes; e; e = e->next)
|
||||
if ((e->sender == c) && (e->flags & REF_STALE) && !(e->flags & REF_FILTERED))
|
||||
{
|
||||
e->flags |= REF_MODIFY;
|
||||
prune = 1;
|
||||
}
|
||||
}
|
||||
FIB_WALK_END;
|
||||
|
||||
if (prune)
|
||||
rt_schedule_prune(t);
|
||||
}
|
||||
|
||||
/**
|
||||
* rte_dump - dump a route
|
||||
@@ -1712,6 +1754,7 @@ again:
|
||||
|
||||
rescan:
|
||||
for (e=n->routes; e; e=e->next)
|
||||
{
|
||||
if (e->sender->flush_active || (e->flags & REF_DISCARD))
|
||||
{
|
||||
if (limit <= 0)
|
||||
@@ -1727,6 +1770,22 @@ again:
|
||||
goto rescan;
|
||||
}
|
||||
|
||||
if (e->flags & REF_MODIFY)
|
||||
{
|
||||
if (limit <= 0)
|
||||
{
|
||||
FIB_ITERATE_PUT(fit);
|
||||
ev_schedule(tab->rt_event);
|
||||
return;
|
||||
}
|
||||
|
||||
rte_modify(e);
|
||||
limit--;
|
||||
|
||||
goto rescan;
|
||||
}
|
||||
}
|
||||
|
||||
if (!n->routes) /* Orphaned FIB entry */
|
||||
{
|
||||
FIB_ITERATE_PUT(fit);
|
||||
|
Reference in New Issue
Block a user