diff --git a/doc/user/ospfd.rst b/doc/user/ospfd.rst index b80adba7f046..2261e4d2fc96 100644 --- a/doc/user/ospfd.rst +++ b/doc/user/ospfd.rst @@ -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-60000) + + 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 diff --git a/lib/libospf.h b/lib/libospf.h index 8a208beb3c33..5becc1594ee0 100644 --- a/lib/libospf.h +++ b/lib/libospf.h @@ -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 diff --git a/ospfd/ospf_lsa.c b/ospfd/ospf_lsa.c index f125fa93b1e4..a99021e5d8e7 100644 --- a/ospfd/ospf_lsa.c +++ b/ospfd/ospf_lsa.c @@ -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); } diff --git a/ospfd/ospf_lsa.h b/ospfd/ospf_lsa.h index d5ca0694ccb2..27be1ceb3b9a 100644 --- a/ospfd/ospf_lsa.h +++ b/ospfd/ospf_lsa.h @@ -226,11 +226,12 @@ enum lsid_status { LSID_AVAILABLE = 0, LSID_CHANGE, LSID_NOT_AVAILABLE }; /* XXX: Eek, time functions, similar are in lib/thread.c */ extern struct timeval int2tv(int); extern struct timeval msec2tv(int); +extern int tv2msec(struct timeval tv); extern int get_age(struct ospf_lsa *); extern uint16_t ospf_lsa_checksum(struct lsa_header *); extern int ospf_lsa_checksum_valid(struct lsa_header *); -extern int ospf_lsa_refresh_delay(struct ospf_lsa *); +extern int ospf_lsa_refresh_delay(struct ospf *ospf, struct ospf_lsa *lsa); extern const char *dump_lsa_key(struct ospf_lsa *); extern uint32_t lsa_seqnum_increment(struct ospf_lsa *); diff --git a/ospfd/ospf_opaque.c b/ospfd/ospf_opaque.c index 5d2d65658f6e..962d1aa4fbc3 100644 --- a/ospfd/ospf_opaque.c +++ b/ospfd/ospf_opaque.c @@ -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,10 @@ void ospf_opaque_lsa_refresh_schedule(struct ospf_lsa *lsa0) goto out; } + ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT); + if ((lsa0->area != NULL) && (lsa0->area->ospf != NULL)) + ospf = lsa0->area->ospf; + /* Delete this lsa from neighbor retransmit-list. */ switch (lsa->data->type) { case OSPF_OPAQUE_LINK_LSA: @@ -2083,10 +2087,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 +2095,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; } diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c index b7261da261ed..ef6771d78922 100644 --- a/ospfd/ospf_vty.c +++ b/ospfd/ospf_vty.c @@ -2302,34 +2302,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" @@ -2338,7 +2313,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; } @@ -2387,40 +2366,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)", + "[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); - ospf->min_ls_arrival = strtoul(argv[argc - 1]->arg, NULL, 10); + if (no) + ospf->min_ls_arrival = OSPF_MIN_LS_ARRIVAL; + else + ospf->min_ls_arrival = strtoul(min_arrival_str, 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 - "Adjust routing timers\n" - "OSPF LSA timers\n" - "Minimum delay in receiving new version of a LSA\n" - "Delay in milliseconds\n") +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); - unsigned int minarrival; - - 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; + 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; } @@ -13707,9 +13681,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);