mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-11-08 12:18:42 +00:00
Table maintenance is now done in coroutines
This commit is contained in:
parent
8d7fbf911a
commit
c7befcb695
@ -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 */
|
||||||
|
|
||||||
|
101
nest/rt-table.c
101
nest/rt-table.c
@ -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,50 +1755,62 @@ 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);
|
||||||
|
|
||||||
if (tab->hcu_scheduled)
|
the_bird_lock();
|
||||||
rt_update_hostcache(tab);
|
|
||||||
|
|
||||||
if (tab->nhu_state)
|
if (tab->hcu_scheduled)
|
||||||
rt_next_hop_update(tab);
|
rt_update_hostcache(tab);
|
||||||
|
|
||||||
if (tab->prune_state)
|
if (tab->nhu_state)
|
||||||
rt_prune_table(tab);
|
rt_next_hop_update(tab);
|
||||||
|
|
||||||
rt_unlock_table(tab);
|
if (tab->prune_state)
|
||||||
|
rt_prune_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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user