mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-04-28 21:20:48 +00:00
Merge pull request #3230 from opensourcerouting/feature/isis-improve-lsp-scheduling
Feature: IS-IS improve lsp scheduling
This commit is contained in:
commit
a8afa9e786
@ -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) {
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user