0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2024-12-22 09:41:54 +00:00

Table maintenance is now done in coroutines

This commit is contained in:
Maria Matejka 2021-03-22 01:12:10 +01:00
parent 8d7fbf911a
commit c7befcb695
2 changed files with 58 additions and 48 deletions

View File

@ -174,14 +174,17 @@ typedef struct rtable {
* delete as soon as use_count becomes 0 and remove * delete as soon as use_count becomes 0 and remove
* obstacle from this routing table. * obstacle from this routing table.
*/ */
struct event *rt_event; /* Routing table event */
btime last_rt_change; /* Last time when route changed */ btime last_rt_change; /* Last time when route changed */
btime base_settle_time; /* Start time of rtable settling interval */ btime base_settle_time; /* Start time of rtable settling interval */
btime gc_time; /* Time of last GC */ btime gc_time; /* Time of last GC */
int gc_counter; /* Number of operations since last GC */ int gc_counter; /* Number of operations since last GC */
struct coroutine *maint_coro; /* Maintenance coroutine */
struct bsem *maint_sem; /* Maintenance semaphore */
byte prune_state; /* Table prune state, 1 -> scheduled, 2-> running */ byte prune_state; /* Table prune state, 1 -> scheduled, 2-> running */
byte hcu_scheduled; /* Hostcache update is scheduled */ byte hcu_scheduled; /* Hostcache update is scheduled */
byte nhu_state; /* Next Hop Update state */ byte nhu_state; /* Next Hop Update state */
struct fib_iterator prune_fit; /* Rtable prune FIB iterator */ struct fib_iterator prune_fit; /* Rtable prune FIB iterator */
struct fib_iterator nhu_fit; /* Next Hop Update FIB iterator */ struct fib_iterator nhu_fit; /* Next Hop Update FIB iterator */

View File

@ -35,7 +35,8 @@
#include "nest/protocol.h" #include "nest/protocol.h"
#include "nest/iface.h" #include "nest/iface.h"
#include "lib/resource.h" #include "lib/resource.h"
#include "lib/event.h" #include "lib/coro.h"
#include "lib/locking.h"
#include "lib/timer.h" #include "lib/timer.h"
#include "lib/string.h" #include "lib/string.h"
#include "conf/conf.h" #include "conf/conf.h"
@ -1754,39 +1755,43 @@ rt_schedule_hcu(rtable *tab)
return; return;
tab->hcu_scheduled = 1; tab->hcu_scheduled = 1;
ev_schedule(tab->rt_event); bsem_post(tab->maint_sem);
} }
static inline void static inline void
rt_schedule_nhu(rtable *tab) rt_schedule_nhu(rtable *tab)
{ {
if (tab->nhu_state == NHU_CLEAN)
ev_schedule(tab->rt_event);
/* state change: /* state change:
* NHU_CLEAN -> NHU_SCHEDULED * NHU_CLEAN -> NHU_SCHEDULED
* NHU_RUNNING -> NHU_DIRTY * NHU_RUNNING -> NHU_DIRTY
*/ */
tab->nhu_state |= NHU_SCHEDULED; tab->nhu_state |= NHU_SCHEDULED;
if (tab->nhu_state == NHU_SCHEDULED)
bsem_post(tab->maint_sem);
} }
void void
rt_schedule_prune(rtable *tab) rt_schedule_prune(rtable *tab)
{ {
if (tab->prune_state == 0)
ev_schedule(tab->rt_event);
/* state change 0->1, 2->3 */ /* state change 0->1, 2->3 */
tab->prune_state |= 1; tab->prune_state |= 1;
if (tab->prune_state == 1)
bsem_post(tab->maint_sem);
} }
static void static void
rt_event(void *ptr) rt_maint(void *ptr)
{ {
rtable *tab = ptr; rtable *tab = ptr;
rt_lock_table(tab); for (_Bool finished = 0; !finished; )
{
bsem_wait(tab->maint_sem);
the_bird_lock();
if (tab->hcu_scheduled) if (tab->hcu_scheduled)
rt_update_hostcache(tab); rt_update_hostcache(tab);
@ -1797,7 +1802,15 @@ rt_event(void *ptr)
if (tab->prune_state) if (tab->prune_state)
rt_prune_table(tab); rt_prune_table(tab);
rt_unlock_table(tab); if (!tab->use_count && tab->deleted)
{
rfree(tab);
the_bird_unlock();
return;
}
the_bird_unlock();
}
} }
@ -1876,6 +1889,7 @@ static void
rt_free(resource *_r) rt_free(resource *_r)
{ {
rtable *r = (rtable *) _r; rtable *r = (rtable *) _r;
struct config *conf = r->deleted;
DBG("Deleting routing table %s\n", r->name); DBG("Deleting routing table %s\n", r->name);
ASSERT_DIE(r->use_count == 0); ASSERT_DIE(r->use_count == 0);
@ -1883,19 +1897,15 @@ rt_free(resource *_r)
if (r->internal) if (r->internal)
return; return;
r->config->table = NULL;
rem_node(&r->n);
if (r->hostcache) if (r->hostcache)
rt_free_hostcache(r); rt_free_hostcache(r);
/* Freed automagically by the resource pool r->config->table = NULL;
fib_free(&r->fib); rem_node(&r->n);
hmap_free(&r->id_map);
rfree(r->rt_event); rfree(r->rp);
rfree(r->settle_timer);
mb_free(r); config_del_obstacle(conf);
*/
} }
static void static void
@ -1940,10 +1950,12 @@ rt_setup(pool *pp, struct rtable_config *cf)
hmap_init(&t->id_map, p, 1024); hmap_init(&t->id_map, p, 1024);
hmap_set(&t->id_map, 0); hmap_set(&t->id_map, 0);
t->last_rt_change = t->gc_time = current_time();
init_list(&t->subscribers); init_list(&t->subscribers);
t->rt_event = ev_new_init(p, rt_event, t); t->maint_sem = bsem_new(p);
t->last_rt_change = t->gc_time = current_time(); t->maint_coro = coro_run(p, rt_maint, t);
} }
return t; return t;
@ -1971,7 +1983,7 @@ rt_init(void)
* *
* The prune loop scans routing tables and removes routes belonging to flushing * The prune loop scans routing tables and removes routes belonging to flushing
* protocols, discarded routes and also stale network entries. It is called from * protocols, discarded routes and also stale network entries. It is called from
* rt_event(). The event is rescheduled if the current iteration do not finish * rt_maint(). This loop is rescheduled if the current iteration do not finish
* the table. The pruning is directed by the prune state (@prune_state), * the table. The pruning is directed by the prune state (@prune_state),
* specifying whether the prune cycle is scheduled or running, and there * specifying whether the prune cycle is scheduled or running, and there
* is also a persistent pruning iterator (@prune_fit). * is also a persistent pruning iterator (@prune_fit).
@ -2021,7 +2033,7 @@ again:
if (limit <= 0) if (limit <= 0)
{ {
FIB_ITERATE_PUT(fit); FIB_ITERATE_PUT(fit);
ev_schedule(tab->rt_event); bsem_post(tab->maint_sem);
return; return;
} }
@ -2036,7 +2048,7 @@ again:
if (limit <= 0) if (limit <= 0)
{ {
FIB_ITERATE_PUT(fit); FIB_ITERATE_PUT(fit);
ev_schedule(tab->rt_event); bsem_post(tab->maint_sem);
return; return;
} }
@ -2067,7 +2079,7 @@ again:
tab->prune_state &= 1; tab->prune_state &= 1;
if (tab->prune_state > 0) if (tab->prune_state > 0)
ev_schedule(tab->rt_event); bsem_post(tab->maint_sem);
/* FIXME: This should be handled in a better way */ /* FIXME: This should be handled in a better way */
rt_prune_sources(); rt_prune_sources();
@ -2310,7 +2322,7 @@ rt_next_hop_update(rtable *tab)
if (max_feed <= 0) if (max_feed <= 0)
{ {
FIB_ITERATE_PUT(fit); FIB_ITERATE_PUT(fit);
ev_schedule(tab->rt_event); bsem_post(tab->maint_sem);
return; return;
} }
max_feed -= rt_next_hop_update_net(tab, n); max_feed -= rt_next_hop_update_net(tab, n);
@ -2324,7 +2336,7 @@ rt_next_hop_update(rtable *tab)
tab->nhu_state &= 1; tab->nhu_state &= 1;
if (tab->nhu_state != NHU_CLEAN) if (tab->nhu_state != NHU_CLEAN)
ev_schedule(tab->rt_event); bsem_post(tab->maint_sem);
} }
@ -2374,21 +2386,17 @@ rt_lock_table(rtable *r)
* rt_unlock_table - unlock a routing table * rt_unlock_table - unlock a routing table
* @r: routing table to be unlocked * @r: routing table to be unlocked
* *
* Unlock a routing table formerly locked by rt_lock_table(), * Unlock a routing table formerly locked by rt_lock_table().
* that is decrease its use count and delete it if it's scheduled * If scheduled for deletion, ping the maintenance coroutine to delete
* for deletion by configuration changes. * the table and finish.
*/ */
void void
rt_unlock_table(rtable *r) rt_unlock_table(rtable *r)
{ {
if (!--r->use_count && r->deleted) r->use_count--;
{
struct config *conf = r->deleted;
/* Delete the routing table by freeing its pool */ if (!r->use_count && r->deleted)
rt_shutdown(r); bsem_post(r->maint_sem);
config_del_obstacle(conf);
}
} }
static struct rtable_config * static struct rtable_config *
@ -2438,8 +2446,7 @@ rt_commit(struct config *new, struct config *old)
DBG("\t%s: deleted\n", o->name); DBG("\t%s: deleted\n", o->name);
ot->deleted = old; ot->deleted = old;
config_add_obstacle(old); config_add_obstacle(old);
rt_lock_table(ot); bsem_post(ot->maint_sem); /* Allow the maint_coro to finish. */
rt_unlock_table(ot);
} }
} }
} }