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
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 administrative

View file

@ -27,8 +27,9 @@ extern "C" {
#else
#define OSPF_LS_REFRESH_TIME 1800
#endif
#define OSPF_MIN_LS_INTERVAL 5000 /* msec */
#define OSPF_MIN_LS_ARRIVAL 1000 /* in milliseconds */
#define OSPF_MIN_LS_INTERVAL 5000 /* 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_MAXAGE 3600
#define OSPF_CHECK_AGE 300

View file

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

View file

@ -225,12 +225,14 @@ enum lsid_status { LSID_AVAILABLE = 0, LSID_CHANGE, LSID_NOT_AVAILABLE };
/* Prototypes. */
/* XXX: Eek, time functions, similar are in lib/thread.c */
extern struct timeval int2tv(int);
extern struct timeval msec2tv(int a);
extern int tv2msec(struct timeval tv);
extern int get_age(struct ospf_lsa *lsa);
extern uint16_t ospf_lsa_checksum(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 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_id *oipi;
struct ospf_lsa *lsa;
struct ospf *top;
struct ospf *ospf;
int delay;
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;
}
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. */
switch (lsa->data->type) {
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);
break;
case OSPF_OPAQUE_AS_LSA:
top = ospf_lookup_by_vrf_id(VRF_DEFAULT);
if ((lsa0->area != NULL) && (lsa0->area->ospf != NULL))
top = lsa0->area->ospf;
ospf_ls_retransmit_delete_nbr_as(top, lsa);
ospf_ls_retransmit_delete_nbr_as(ospf, lsa);
break;
default:
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;
}
delay = ospf_lsa_refresh_delay(lsa);
delay = ospf_lsa_refresh_delay(ospf, lsa);
if (IS_DEBUG_OSPF_EVENT)
zlog_debug(
"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)),
GET_OPAQUE_ID(ntohl(lsa->data->id.s_addr)));
zlog_debug("Schedule Type-%u Opaque-LSA to REFRESH in %d msec later: [opaque-type=%u, opaque-id=%x]",
lsa->data->type, delay, 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_lsa_refresh_timer, oipi, delay * 1000);
OSPF_OPAQUE_TIMER_ON(oipi->t_opaque_lsa_self, ospf_opaque_lsa_refresh_timer, oipi, delay);
out:
return;
}

View file

@ -2307,34 +2307,9 @@ static int ospf_timers_spf_set(struct vty *vty, unsigned int delay,
return CMD_SUCCESS;
}
DEFUN (ospf_timers_min_ls_interval,
DEFPY (ospf_timers_min_ls_interval,
ospf_timers_min_ls_interval_cmd,
"timers throttle lsa all (0-5000)",
"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] timers throttle lsa all ![(0-5000)]$lsa_refresh_interval",
NO_STR
"Adjust routing timers\n"
"Throttling adaptive timer\n"
@ -2343,7 +2318,11 @@ DEFUN (no_ospf_timers_min_ls_interval,
"Delay (msec) between sending LSAs\n")
{
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;
}
@ -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,
"timers lsa min-arrival (0-600000)",
"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] timers lsa min-arrival ![(0-5000)]$min_arrival",
NO_STR
"Adjust routing 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")
{
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) {
minarrival = strtoul(argv[argc - 1]->arg, NULL, 10);
if (ospf->min_ls_arrival != minarrival
|| minarrival == OSPF_MIN_LS_ARRIVAL)
return CMD_SUCCESS;
}
ospf->min_ls_arrival = OSPF_MIN_LS_ARRIVAL;
DEFPY_HIDDEN (ospf_timers_lsa_min_arrival_deprecated,
ospf_timers_lsa_min_arrival_deprecated_cmd,
"timers lsa min-arrival [(5001-60000)]$min_arrival",
"Adjust routing timers\n"
"OSPF LSA timers\n"
"Minimum delay in receiving new version of an LSA\n"
"Deprecated delay in milliseconds - delays in this range default to 5000 msec\n")
{
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;
}
@ -13712,9 +13686,8 @@ void ospf_vty_init(void)
/* LSA timers commands */
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, &no_ospf_timers_lsa_min_arrival_cmd);
install_element(OSPF_NODE, &ospf_timers_lsa_min_arrival_deprecated_cmd);
/* refresh timer commands */
install_element(OSPF_NODE, &ospf_refresh_timer_cmd);