summaryrefslogtreecommitdiff
path: root/nest/rt-table.c
diff options
context:
space:
mode:
authorOndrej Zajicek <santiago@crfreenet.org>2014-03-20 14:07:12 +0100
committerOndrej Zajicek <santiago@crfreenet.org>2014-03-20 14:07:12 +0100
commit0c791f873aeb7c1052c97db7da4fe23873d69603 (patch)
tree48496c5965cb6e9f54d7863827c35054c3697c19 /nest/rt-table.c
parent4e398e34bf140baf73fe8dceaf81078fb343f65a (diff)
BGP graceful restart support.
Also significant core protocol state changes needed for that, global graceful restart recovery state and kernel proto support for recovery.
Diffstat (limited to 'nest/rt-table.c')
-rw-r--r--nest/rt-table.c100
1 files changed, 82 insertions, 18 deletions
diff --git a/nest/rt-table.c b/nest/rt-table.c
index 8c91ea0a..bc911729 100644
--- a/nest/rt-table.c
+++ b/nest/rt-table.c
@@ -55,8 +55,10 @@ static void rt_free_hostcache(rtable *tab);
static void rt_notify_hostcache(rtable *tab, net *net);
static void rt_update_hostcache(rtable *tab);
static void rt_next_hop_update(rtable *tab);
-
+static inline int rt_prune_table(rtable *tab);
static inline void rt_schedule_gc(rtable *tab);
+static inline void rt_schedule_prune(rtable *tab);
+
static inline struct ea_list *
make_tmp_attrs(struct rte *rt, struct linpool *pool)
@@ -570,7 +572,7 @@ rte_announce(rtable *tab, unsigned type, net *net, rte *new, rte *old, rte *befo
struct announce_hook *a;
WALK_LIST(a, tab->hooks)
{
- ASSERT(a->proto->core_state == FS_HAPPY || a->proto->core_state == FS_FEEDING);
+ ASSERT(a->proto->export_state != ES_DOWN);
if (a->proto->accept_ra_types == type)
if (type == RA_ACCEPTED)
rt_notify_accepted(a, net, new, old, before_old, tmpa, 0);
@@ -1108,6 +1110,46 @@ rt_examine(rtable *t, ip_addr prefix, int pxlen, struct proto *p, struct filter
return v > 0;
}
+void
+rt_refresh_begin(rtable *t, struct announce_hook *ah)
+{
+ net *n;
+ rte *e;
+
+ FIB_WALK(&t->fib, fn)
+ {
+ n = (net *) fn;
+ for (e = n->routes; e; e = e->next)
+ if (e->sender == ah)
+ e->flags |= REF_STALE;
+ }
+ FIB_WALK_END;
+}
+
+void
+rt_refresh_end(rtable *t, struct announce_hook *ah)
+{
+ int prune = 0;
+ net *n;
+ rte *e;
+
+ FIB_WALK(&t->fib, fn)
+ {
+ n = (net *) fn;
+ for (e = n->routes; e; e = e->next)
+ if ((e->sender == ah) && (e->flags & REF_STALE))
+ {
+ e->flags |= REF_DISCARD;
+ prune = 1;
+ }
+ }
+ FIB_WALK_END;
+
+ if (prune)
+ rt_schedule_prune(t);
+}
+
+
/**
* rte_dump - dump a route
* @e: &rte to be dumped
@@ -1170,6 +1212,13 @@ rt_dump_all(void)
}
static inline void
+rt_schedule_prune(rtable *tab)
+{
+ rt_mark_for_prune(tab);
+ ev_schedule(tab->rt_event);
+}
+
+static inline void
rt_schedule_gc(rtable *tab)
{
if (tab->gc_scheduled)
@@ -1199,6 +1248,7 @@ rt_schedule_nhu(rtable *tab)
tab->nhu_state |= 1;
}
+
static void
rt_prune_nets(rtable *tab)
{
@@ -1242,6 +1292,14 @@ rt_event(void *ptr)
if (tab->nhu_state)
rt_next_hop_update(tab);
+ if (tab->prune_state)
+ if (!rt_prune_table(tab))
+ {
+ /* Table prune unfinished */
+ ev_schedule(tab->rt_event);
+ return;
+ }
+
if (tab->gc_scheduled)
{
rt_prune_nets(tab);
@@ -1283,8 +1341,8 @@ rt_init(void)
}
-static inline int
-rt_prune_step(rtable *tab, int step, int *max_feed)
+static int
+rt_prune_step(rtable *tab, int step, int *limit)
{
static struct rate_limit rl_flush;
struct fib_iterator *fit = &tab->prune_fit;
@@ -1294,13 +1352,13 @@ rt_prune_step(rtable *tab, int step, int *max_feed)
fib_check(&tab->fib);
#endif
- if (tab->prune_state == 0)
+ if (tab->prune_state == RPS_NONE)
return 1;
- if (tab->prune_state == 1)
+ if (tab->prune_state == RPS_SCHEDULED)
{
FIB_ITERATE_INIT(fit, &tab->fib);
- tab->prune_state = 2;
+ tab->prune_state = RPS_RUNNING;
}
again:
@@ -1312,9 +1370,10 @@ again:
rescan:
for (e=n->routes; e; e=e->next)
if (e->sender->proto->flushing ||
+ (e->flags & REF_DISCARD) ||
(step && e->attrs->src->proto->flushing))
{
- if (*max_feed <= 0)
+ if (*limit <= 0)
{
FIB_ITERATE_PUT(fit, fn);
return 0;
@@ -1325,7 +1384,7 @@ again:
n->n.prefix, n->n.pxlen, e->attrs->src->proto->name, tab->name);
rte_discard(tab, e);
- (*max_feed)--;
+ (*limit)--;
goto rescan;
}
@@ -1342,10 +1401,17 @@ again:
fib_check(&tab->fib);
#endif
- tab->prune_state = 0;
+ tab->prune_state = RPS_NONE;
return 1;
}
+static inline int
+rt_prune_table(rtable *tab)
+{
+ int limit = 512;
+ return rt_prune_step(tab, 0, &limit);
+}
+
/**
* rt_prune_loop - prune routing tables
*
@@ -1364,19 +1430,19 @@ int
rt_prune_loop(void)
{
static int step = 0;
- int max_feed = 512;
+ int limit = 512;
rtable *t;
again:
WALK_LIST(t, routing_tables)
- if (! rt_prune_step(t, step, &max_feed))
+ if (! rt_prune_step(t, step, &limit))
return 0;
if (step == 0)
{
/* Prepare for the second step */
WALK_LIST(t, routing_tables)
- t->prune_state = 1;
+ t->prune_state = RPS_SCHEDULED;
step = 1;
goto again;
@@ -1721,7 +1787,7 @@ again:
(p->accept_ra_types == RA_ACCEPTED))
if (rte_is_valid(e))
{
- if (p->core_state != FS_FEEDING)
+ if (p->export_state != ES_FEEDING)
return 1; /* In the meantime, the protocol fell down. */
do_feed_baby(p, p->accept_ra_types, h, n, e);
max_feed--;
@@ -1730,7 +1796,7 @@ again:
if (p->accept_ra_types == RA_ANY)
for(e = n->routes; rte_is_valid(e); e = e->next)
{
- if (p->core_state != FS_FEEDING)
+ if (p->export_state != ES_FEEDING)
return 1; /* In the meantime, the protocol fell down. */
do_feed_baby(p, RA_ANY, h, n, e);
max_feed--;
@@ -2223,9 +2289,7 @@ rt_show_cont(struct cli *c)
cli_printf(c, 8004, "Stopped due to reconfiguration");
goto done;
}
- if (d->export_protocol &&
- d->export_protocol->core_state != FS_HAPPY &&
- d->export_protocol->core_state != FS_FEEDING)
+ if (d->export_protocol && (d->export_protocol->export_state == ES_DOWN))
{
cli_printf(c, 8005, "Protocol is down");
goto done;