Merge pull request #3230 from opensourcerouting/feature/isis-improve-lsp-scheduling

Feature: IS-IS improve lsp scheduling
This commit is contained in:
Donald Sharp 2018-10-24 07:49:50 -04:00 committed by GitHub
commit a8afa9e786
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 77 additions and 59 deletions

View File

@ -59,8 +59,7 @@
#include "isisd/fabricd.h"
#include "isisd/isis_tx_queue.h"
static int lsp_l1_refresh(struct thread *thread);
static int lsp_l2_refresh(struct thread *thread);
static int lsp_refresh(struct thread *thread);
static int lsp_l1_refresh_pseudo(struct thread *thread);
static int lsp_l2_refresh_pseudo(struct thread *thread);
@ -1251,12 +1250,9 @@ int lsp_generate(struct isis_area *area, int level)
THREAD_TIMER_OFF(area->t_lsp_refresh[level - 1]);
area->lsp_regenerate_pending[level - 1] = 0;
if (level == IS_LEVEL_1)
thread_add_timer(master, lsp_l1_refresh, area, refresh_time,
&area->t_lsp_refresh[level - 1]);
else if (level == IS_LEVEL_2)
thread_add_timer(master, lsp_l2_refresh, area, refresh_time,
&area->t_lsp_refresh[level - 1]);
thread_add_timer(master, lsp_refresh,
&area->lsp_refresh_arg[level - 1], refresh_time,
&area->t_lsp_refresh[level - 1]);
if (isis->debugs & DEBUG_UPDATE_PACKETS) {
zlog_debug("ISIS-Upd (%s): Building L%d LSP %s, len %" PRIu16
@ -1323,12 +1319,9 @@ static int lsp_regenerate(struct isis_area *area, int level)
lsp_seqno_update(lsp);
refresh_time = lsp_refresh_time(lsp, rem_lifetime);
if (level == IS_LEVEL_1)
thread_add_timer(master, lsp_l1_refresh, area, refresh_time,
&area->t_lsp_refresh[level - 1]);
else if (level == IS_LEVEL_2)
thread_add_timer(master, lsp_l2_refresh, area, refresh_time,
&area->t_lsp_refresh[level - 1]);
thread_add_timer(master, lsp_refresh,
&area->lsp_refresh_arg[level - 1], refresh_time,
&area->t_lsp_refresh[level - 1]);
area->lsp_regenerate_pending[level - 1] = 0;
if (isis->debugs & DEBUG_UPDATE_PACKETS) {
@ -1350,45 +1343,42 @@ static int lsp_regenerate(struct isis_area *area, int level)
/*
* Something has changed or periodic refresh -> regenerate LSP
*/
static int lsp_l1_refresh(struct thread *thread)
static int lsp_refresh(struct thread *thread)
{
struct isis_area *area;
struct lsp_refresh_arg *arg = THREAD_ARG(thread);
assert(arg);
struct isis_area *area = arg->area;
area = THREAD_ARG(thread);
assert(area);
area->t_lsp_refresh[0] = NULL;
area->lsp_regenerate_pending[0] = 0;
int level = arg->level;
if ((area->is_type & IS_LEVEL_1) == 0)
area->t_lsp_refresh[level - 1] = NULL;
area->lsp_regenerate_pending[level - 1] = 0;
if ((area->is_type & level) == 0)
return ISIS_ERROR;
sched_debug(
"ISIS (%s): LSP L1 refresh timer expired. Refreshing LSP...",
area->area_tag);
return lsp_regenerate(area, IS_LEVEL_1);
}
static int lsp_l2_refresh(struct thread *thread)
{
struct isis_area *area;
area = THREAD_ARG(thread);
assert(area);
area->t_lsp_refresh[1] = NULL;
area->lsp_regenerate_pending[1] = 0;
if ((area->is_type & IS_LEVEL_2) == 0)
return ISIS_ERROR;
if (monotime_since(&area->last_lsp_refresh_event[level - 1], NULL) < 50000L) {
sched_debug("ISIS (%s): Still unstable, postpone LSP L%d refresh",
area->area_tag, level);
_lsp_regenerate_schedule(area, level, 0, false,
__func__, __FILE__, __LINE__);
return 0;
}
sched_debug(
"ISIS (%s): LSP L2 refresh timer expired. Refreshing LSP...",
area->area_tag);
return lsp_regenerate(area, IS_LEVEL_2);
"ISIS (%s): LSP L%d refresh timer expired. Refreshing LSP...",
area->area_tag, level);
return lsp_regenerate(area, level);
}
int lsp_regenerate_schedule(struct isis_area *area, int level, int all_pseudo)
int _lsp_regenerate_schedule(struct isis_area *area, int level,
int all_pseudo, bool postpone,
const char *func, const char *file,
int line)
{
struct isis_lsp *lsp;
uint8_t id[ISIS_SYS_ID_LEN + 2];
@ -1402,9 +1392,11 @@ int lsp_regenerate_schedule(struct isis_area *area, int level, int all_pseudo)
return ISIS_ERROR;
sched_debug(
"ISIS (%s): Scheduling regeneration of %s LSPs, %sincluding PSNs",
"ISIS (%s): Scheduling regeneration of %s LSPs, %sincluding PSNs"
" Caller: %s %s:%d",
area->area_tag, circuit_t2string(level),
all_pseudo ? "" : "not ");
all_pseudo ? "" : "not ",
func, file, line);
memcpy(id, isis->sysid, ISIS_SYS_ID_LEN);
LSP_PSEUDO_ID(id) = LSP_FRAGMENT(id) = 0;
@ -1414,6 +1406,10 @@ int lsp_regenerate_schedule(struct isis_area *area, int level, int all_pseudo)
if (!((level & lvl) && (area->is_type & lvl)))
continue;
if (postpone) {
monotime(&area->last_lsp_refresh_event[lvl - 1]);
}
sched_debug(
"ISIS (%s): Checking whether L%d needs to be scheduled",
area->area_tag, lvl);
@ -1468,15 +1464,10 @@ int lsp_regenerate_schedule(struct isis_area *area, int level, int all_pseudo)
}
area->lsp_regenerate_pending[lvl - 1] = 1;
if (lvl == IS_LEVEL_1) {
thread_add_timer_msec(master, lsp_l1_refresh, area,
timeout,
&area->t_lsp_refresh[lvl - 1]);
} else if (lvl == IS_LEVEL_2) {
thread_add_timer_msec(master, lsp_l2_refresh, area,
timeout,
&area->t_lsp_refresh[lvl - 1]);
}
thread_add_timer_msec(master, lsp_refresh,
&area->lsp_refresh_arg[lvl - 1],
timeout,
&area->t_lsp_refresh[lvl - 1]);
}
if (all_pseudo) {

View File

@ -54,7 +54,12 @@ void lsp_db_destroy(dict_t *lspdb);
int lsp_tick(struct thread *thread);
int lsp_generate(struct isis_area *area, int level);
int lsp_regenerate_schedule(struct isis_area *area, int level, int all_pseudo);
#define lsp_regenerate_schedule(area, level, all_pseudo) \
_lsp_regenerate_schedule((area), (level), (all_pseudo), true, \
__func__, __FILE__, __LINE__)
int _lsp_regenerate_schedule(struct isis_area *area, int level,
int all_pseudo, bool postpone,
const char *func, const char *file, int line);
int lsp_generate_pseudo(struct isis_circuit *circuit, int level);
int lsp_regenerate_schedule_pseudo(struct isis_circuit *circuit, int level);

View File

@ -1248,7 +1248,8 @@ static struct isis_spf_run *isis_run_spf_arg(struct isis_area *area, int level)
return run;
}
int isis_spf_schedule(struct isis_area *area, int level)
int _isis_spf_schedule(struct isis_area *area, int level,
const char *func, const char *file, int line)
{
struct isis_spftree *spftree = area->spftree[SPFTREE_IPV4][level - 1];
time_t now = monotime(NULL);
@ -1257,10 +1258,12 @@ int isis_spf_schedule(struct isis_area *area, int level)
assert(diff >= 0);
assert(area->is_type & level);
if (isis->debugs & DEBUG_SPF_EVENTS)
if (isis->debugs & DEBUG_SPF_EVENTS) {
zlog_debug(
"ISIS-Spf (%s) L%d SPF schedule called, lastrun %d sec ago",
area->area_tag, level, diff);
"ISIS-Spf (%s) L%d SPF schedule called, lastrun %d sec ago"
" Caller: %s %s:%d",
area->area_tag, level, diff, func, file, line);
}
if (area->spf_delay_ietf[level - 1]) {
/* Need to call schedule function also if spf delay is running

View File

@ -34,7 +34,11 @@ void isis_spftree_del(struct isis_spftree *spftree);
void spftree_area_init(struct isis_area *area);
void spftree_area_del(struct isis_area *area);
void spftree_area_adj_del(struct isis_area *area, struct isis_adjacency *adj);
int isis_spf_schedule(struct isis_area *area, int level);
#define isis_spf_schedule(area, level) \
_isis_spf_schedule((area), (level), __func__, \
__FILE__, __LINE__)
int _isis_spf_schedule(struct isis_area *area, int level,
const char *func, const char *file, int line);
void isis_spf_cmds_init(void);
void isis_spf_print(struct isis_spftree *spftree, struct vty *vty);
struct isis_spftree *isis_run_hopcount_spf(struct isis_area *area,

View File

@ -160,6 +160,13 @@ struct isis_area *isis_area_create(const char *area_tag)
if (fabricd)
area->fabricd = fabricd_new(area);
area->lsp_refresh_arg[0].area = area;
area->lsp_refresh_arg[0].level = IS_LEVEL_1;
area->lsp_refresh_arg[1].area = area;
area->lsp_refresh_arg[1].level = IS_LEVEL_2;
QOBJ_REG(area, isis_area);
return area;

View File

@ -90,6 +90,11 @@ enum spf_tree_id {
SPFTREE_COUNT
};
struct lsp_refresh_arg {
struct isis_area *area;
int level;
};
struct isis_area {
struct isis *isis; /* back pointer */
dict_t *lspdb[ISIS_LEVELS]; /* link-state dbs */
@ -100,6 +105,7 @@ struct isis_area {
struct flags flags;
struct thread *t_tick; /* LSP walker */
struct thread *t_lsp_refresh[ISIS_LEVELS];
struct timeval last_lsp_refresh_event[ISIS_LEVELS];
/* t_lsp_refresh is used in two ways:
* a) regular refresh of LSPs
* b) (possibly throttled) updates to LSPs
@ -160,6 +166,8 @@ struct isis_area {
parameters*/
struct thread *spf_timer[ISIS_LEVELS];
struct lsp_refresh_arg lsp_refresh_arg[ISIS_LEVELS];
QOBJ_FIELDS
};
DECLARE_QOBJ_TYPE(isis_area)