Merge pull request #17194 from LabNConsulting/aceelindem/ospf-ls-refresh-interval-fix

ospfd: Fix opaque LSA refresh interval and modify LSA cmds.
This commit is contained in:
Russ White 2024-11-01 11:37:32 -04:00 committed by GitHub
commit 77632a7ec3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 102 additions and 83 deletions

View File

@ -200,6 +200,44 @@ To start OSPF process you have to specify the OSPF router.
This command supersedes the *timers spf* command in previous FRR This command supersedes the *timers spf* command in previous FRR
releases. releases.
.. clicmd:: timers throttle lsa all (0-5000)
This command sets the minumum interval between originations of the
same LSA or the `minimum LSA refresh interval`. The time is specified
in milliseconds and the default is 5 seconds (5000 milliseconds) consistent
with the architectual constant MinLSInterval specified in Appendix D of
RFC 2328. When a self-originated LSA needs to be reoriginated, it may be
delayed for up to this interval.
.. code-block:: frr
router ospf
timers throttle lsa all 1000
In this example, the `mininum LSA refresh interval` is set to 1000ms. This
command reduces the delay between successive originations of a self-originated
LSA from 5000 milliseconds to 1000 milliseconds.
.. clicmd:: timers lsa min-arrival (0-5000)
This command sets the minumum interval between receptions of instances of
the same LSA or the `minimum LSA arrival interval`. The time is specified in
milliseconds and the default is 1 second (1000 milliseconds) consistent with
the architectual constant MinLSArrival specified in Appendix D of RFC 2328. If a
newer instance of the same LSA is received in less than this interval, it is
ignored.
.. code-block:: frr
router ospf
timers lsa min-arrival 50
In this example, the `minimum LSA arrival interval` is set to 50ms. This
command reduces the minimum interval required between instances of the same
LSA from 1000 milliseconds to 50 milliseconds.
.. clicmd:: max-metric router-lsa [on-startup (5-86400)|on-shutdown (5-100)] .. clicmd:: max-metric router-lsa [on-startup (5-86400)|on-shutdown (5-100)]
.. clicmd:: max-metric router-lsa administrative .. clicmd:: max-metric router-lsa administrative

View File

@ -27,8 +27,9 @@ extern "C" {
#else #else
#define OSPF_LS_REFRESH_TIME 1800 #define OSPF_LS_REFRESH_TIME 1800
#endif #endif
#define OSPF_MIN_LS_INTERVAL 5000 /* msec */ #define OSPF_MIN_LS_INTERVAL 5000 /* milliseconds */
#define OSPF_MIN_LS_ARRIVAL 1000 /* in milliseconds */ #define OSPF_MIN_LS_ARRIVAL 1000 /* milliseconds */
#define OSPF_MIN_LS_ARRIVAL_MAX 5000 /* milliseconds */
#define OSPF_LSA_INITIAL_AGE 0 /* useful for debug */ #define OSPF_LSA_INITIAL_AGE 0 /* useful for debug */
#define OSPF_LSA_MAXAGE 3600 #define OSPF_LSA_MAXAGE 3600
#define OSPF_CHECK_AGE 300 #define OSPF_CHECK_AGE 300

View File

@ -101,24 +101,30 @@ struct timeval msec2tv(int a)
return ret; return ret;
} }
int ospf_lsa_refresh_delay(struct ospf_lsa *lsa) int tv2msec(struct timeval tv)
{
int msecs;
msecs = tv.tv_sec * 1000;
msecs += tv.tv_usec / 1000;
return msecs;
}
int ospf_lsa_refresh_delay(struct ospf *ospf, struct ospf_lsa *lsa)
{ {
struct timeval delta; struct timeval delta;
int delay = 0; int delay = 0;
if (monotime_since(&lsa->tv_orig, &delta) if (monotime_since(&lsa->tv_orig, &delta) < ospf->min_ls_interval * 1000LL) {
< OSPF_MIN_LS_INTERVAL * 1000LL) { struct timeval minv = msec2tv(ospf->min_ls_interval);
struct timeval minv = msec2tv(OSPF_MIN_LS_INTERVAL);
timersub(&minv, &delta, &minv);
/* TBD: remove padding to full sec, return timeval instead */ timersub(&minv, &delta, &minv);
delay = minv.tv_sec + !!minv.tv_usec; delay = tv2msec(minv);
if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) if (IS_DEBUG_OSPF(lsa, LSA_GENERATE))
zlog_debug( zlog_debug("LSA[Type%d:%pI4]: Refresh timer delay %d milliseconds",
"LSA[Type%d:%pI4]: Refresh timer delay %d seconds", lsa->data->type, &lsa->data->id, delay);
lsa->data->type, &lsa->data->id,
delay);
assert(delay > 0); assert(delay > 0);
} }

View File

@ -225,12 +225,14 @@ enum lsid_status { LSID_AVAILABLE = 0, LSID_CHANGE, LSID_NOT_AVAILABLE };
/* Prototypes. */ /* Prototypes. */
/* XXX: Eek, time functions, similar are in lib/thread.c */ /* XXX: Eek, time functions, similar are in lib/thread.c */
extern struct timeval int2tv(int); extern struct timeval int2tv(int);
extern struct timeval msec2tv(int a); extern struct timeval msec2tv(int a);
extern int tv2msec(struct timeval tv);
extern int get_age(struct ospf_lsa *lsa); extern int get_age(struct ospf_lsa *lsa);
extern uint16_t ospf_lsa_checksum(struct lsa_header *lsah); extern uint16_t ospf_lsa_checksum(struct lsa_header *lsah);
extern int ospf_lsa_checksum_valid(struct lsa_header *lsah); extern int ospf_lsa_checksum_valid(struct lsa_header *lsah);
extern int ospf_lsa_refresh_delay(struct ospf_lsa *lsa); extern int ospf_lsa_refresh_delay(struct ospf *ospf, struct ospf_lsa *lsa);
extern const char *dump_lsa_key(struct ospf_lsa *lsa); extern const char *dump_lsa_key(struct ospf_lsa *lsa);
extern uint32_t lsa_seqnum_increment(struct ospf_lsa *lsa); extern uint32_t lsa_seqnum_increment(struct ospf_lsa *lsa);

View File

@ -2051,7 +2051,7 @@ void ospf_opaque_lsa_refresh_schedule(struct ospf_lsa *lsa0)
struct opaque_info_per_type *oipt; struct opaque_info_per_type *oipt;
struct opaque_info_per_id *oipi; struct opaque_info_per_id *oipi;
struct ospf_lsa *lsa; struct ospf_lsa *lsa;
struct ospf *top; struct ospf *ospf;
int delay; int delay;
if ((oipt = lookup_opaque_info_by_type(lsa0)) == NULL if ((oipt = lookup_opaque_info_by_type(lsa0)) == NULL
@ -2076,6 +2076,11 @@ void ospf_opaque_lsa_refresh_schedule(struct ospf_lsa *lsa0)
goto out; goto out;
} }
if ((lsa0->area != NULL) && (lsa0->area->ospf != NULL))
ospf = lsa0->area->ospf;
else
ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
/* Delete this lsa from neighbor retransmit-list. */ /* Delete this lsa from neighbor retransmit-list. */
switch (lsa->data->type) { switch (lsa->data->type) {
case OSPF_OPAQUE_LINK_LSA: case OSPF_OPAQUE_LINK_LSA:
@ -2083,10 +2088,7 @@ void ospf_opaque_lsa_refresh_schedule(struct ospf_lsa *lsa0)
ospf_ls_retransmit_delete_nbr_area(lsa->area, lsa); ospf_ls_retransmit_delete_nbr_area(lsa->area, lsa);
break; break;
case OSPF_OPAQUE_AS_LSA: case OSPF_OPAQUE_AS_LSA:
top = ospf_lookup_by_vrf_id(VRF_DEFAULT); ospf_ls_retransmit_delete_nbr_as(ospf, lsa);
if ((lsa0->area != NULL) && (lsa0->area->ospf != NULL))
top = lsa0->area->ospf;
ospf_ls_retransmit_delete_nbr_as(top, lsa);
break; break;
default: default:
flog_warn(EC_OSPF_LSA_UNEXPECTED, "%s: Unexpected LSA-type(%u)", flog_warn(EC_OSPF_LSA_UNEXPECTED, "%s: Unexpected LSA-type(%u)",
@ -2094,17 +2096,14 @@ void ospf_opaque_lsa_refresh_schedule(struct ospf_lsa *lsa0)
goto out; goto out;
} }
delay = ospf_lsa_refresh_delay(lsa); delay = ospf_lsa_refresh_delay(ospf, lsa);
if (IS_DEBUG_OSPF_EVENT) if (IS_DEBUG_OSPF_EVENT)
zlog_debug( zlog_debug("Schedule Type-%u Opaque-LSA to REFRESH in %d msec later: [opaque-type=%u, opaque-id=%x]",
"Schedule Type-%u Opaque-LSA to REFRESH in %d sec later: [opaque-type=%u, opaque-id=%x]", lsa->data->type, delay, GET_OPAQUE_TYPE(ntohl(lsa->data->id.s_addr)),
lsa->data->type, delay, GET_OPAQUE_ID(ntohl(lsa->data->id.s_addr)));
GET_OPAQUE_TYPE(ntohl(lsa->data->id.s_addr)),
GET_OPAQUE_ID(ntohl(lsa->data->id.s_addr)));
OSPF_OPAQUE_TIMER_ON(oipi->t_opaque_lsa_self, OSPF_OPAQUE_TIMER_ON(oipi->t_opaque_lsa_self, ospf_opaque_lsa_refresh_timer, oipi, delay);
ospf_opaque_lsa_refresh_timer, oipi, delay * 1000);
out: out:
return; return;
} }

View File

@ -2307,34 +2307,9 @@ static int ospf_timers_spf_set(struct vty *vty, unsigned int delay,
return CMD_SUCCESS; return CMD_SUCCESS;
} }
DEFUN (ospf_timers_min_ls_interval, DEFPY (ospf_timers_min_ls_interval,
ospf_timers_min_ls_interval_cmd, ospf_timers_min_ls_interval_cmd,
"timers throttle lsa all (0-5000)", "[no] timers throttle lsa all ![(0-5000)]$lsa_refresh_interval",
"Adjust routing timers\n"
"Throttling adaptive timer\n"
"LSA delay between transmissions\n"
"All LSA types\n"
"Delay (msec) between sending LSAs\n")
{
VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
int idx_number = 4;
unsigned int interval;
if (argc < 5) {
vty_out(vty, "Insufficient arguments\n");
return CMD_WARNING_CONFIG_FAILED;
}
interval = strtoul(argv[idx_number]->arg, NULL, 10);
ospf->min_ls_interval = interval;
return CMD_SUCCESS;
}
DEFUN (no_ospf_timers_min_ls_interval,
no_ospf_timers_min_ls_interval_cmd,
"no timers throttle lsa all [(0-5000)]",
NO_STR NO_STR
"Adjust routing timers\n" "Adjust routing timers\n"
"Throttling adaptive timer\n" "Throttling adaptive timer\n"
@ -2343,7 +2318,11 @@ DEFUN (no_ospf_timers_min_ls_interval,
"Delay (msec) between sending LSAs\n") "Delay (msec) between sending LSAs\n")
{ {
VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
ospf->min_ls_interval = OSPF_MIN_LS_INTERVAL;
if (no)
ospf->min_ls_interval = OSPF_MIN_LS_INTERVAL;
else
ospf->min_ls_interval = strtoul(lsa_refresh_interval_str, NULL, 10);
return CMD_SUCCESS; return CMD_SUCCESS;
} }
@ -2392,40 +2371,35 @@ DEFUN (no_ospf_timers_throttle_spf,
} }
DEFUN (ospf_timers_lsa_min_arrival, DEFPY (ospf_timers_lsa_min_arrival,
ospf_timers_lsa_min_arrival_cmd, ospf_timers_lsa_min_arrival_cmd,
"timers lsa min-arrival (0-600000)", "[no] timers lsa min-arrival ![(0-5000)]$min_arrival",
"Adjust routing timers\n"
"OSPF LSA timers\n"
"Minimum delay in receiving new version of a LSA\n"
"Delay in milliseconds\n")
{
VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
ospf->min_ls_arrival = strtoul(argv[argc - 1]->arg, NULL, 10);
return CMD_SUCCESS;
}
DEFUN (no_ospf_timers_lsa_min_arrival,
no_ospf_timers_lsa_min_arrival_cmd,
"no timers lsa min-arrival [(0-600000)]",
NO_STR NO_STR
"Adjust routing timers\n" "Adjust routing timers\n"
"OSPF LSA timers\n" "OSPF LSA timers\n"
"Minimum delay in receiving new version of a LSA\n" "Minimum delay in receiving new version of an LSA\n"
"Delay in milliseconds\n") "Delay in milliseconds\n")
{ {
VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
unsigned int minarrival; if (no)
ospf->min_ls_arrival = OSPF_MIN_LS_ARRIVAL;
else
ospf->min_ls_arrival = strtoul(min_arrival_str, NULL, 10);
return CMD_SUCCESS;
}
if (argc > 4) { DEFPY_HIDDEN (ospf_timers_lsa_min_arrival_deprecated,
minarrival = strtoul(argv[argc - 1]->arg, NULL, 10); ospf_timers_lsa_min_arrival_deprecated_cmd,
"timers lsa min-arrival [(5001-60000)]$min_arrival",
if (ospf->min_ls_arrival != minarrival "Adjust routing timers\n"
|| minarrival == OSPF_MIN_LS_ARRIVAL) "OSPF LSA timers\n"
return CMD_SUCCESS; "Minimum delay in receiving new version of an LSA\n"
} "Deprecated delay in milliseconds - delays in this range default to 5000 msec\n")
{
ospf->min_ls_arrival = OSPF_MIN_LS_ARRIVAL; VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
vty_out(vty, "%% OSPF `timers lsa min-arrival` set to the maximum of %u milliseconds\n",
OSPF_MIN_LS_ARRIVAL_MAX);
ospf->min_ls_arrival = OSPF_MIN_LS_ARRIVAL_MAX;
return CMD_SUCCESS; return CMD_SUCCESS;
} }
@ -13712,9 +13686,8 @@ void ospf_vty_init(void)
/* LSA timers commands */ /* LSA timers commands */
install_element(OSPF_NODE, &ospf_timers_min_ls_interval_cmd); install_element(OSPF_NODE, &ospf_timers_min_ls_interval_cmd);
install_element(OSPF_NODE, &no_ospf_timers_min_ls_interval_cmd);
install_element(OSPF_NODE, &ospf_timers_lsa_min_arrival_cmd); install_element(OSPF_NODE, &ospf_timers_lsa_min_arrival_cmd);
install_element(OSPF_NODE, &no_ospf_timers_lsa_min_arrival_cmd); install_element(OSPF_NODE, &ospf_timers_lsa_min_arrival_deprecated_cmd);
/* refresh timer commands */ /* refresh timer commands */
install_element(OSPF_NODE, &ospf_refresh_timer_cmd); install_element(OSPF_NODE, &ospf_refresh_timer_cmd);