summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Rossberg <michael.rossberg@tu-ilmenau.de>2015-07-27 07:56:25 +0200
committerPaul Jakma <paul@quagga.net>2015-09-24 15:26:41 +0100
commit2ef762ed9b88e5745012c5829f8f526c95443ddf (patch)
tree8b2867c9c5938551f7e86881104dad61be3f18b6
parentc920e510d09c6c4ab63a3da5375009442a950f82 (diff)
downloadquagga-2ef762ed9b88e5745012c5829f8f526c95443ddf.tar.bz2
quagga-2ef762ed9b88e5745012c5829f8f526c95443ddf.tar.xz
ospfd: Fast OSPF convergence
When considering small networks that have extreme requirements on availability and thus convergence delay, the timers given in the OSPF RFC seem a little “conservative”, i.e., the delay between accepted LSAs and the rate at which LSAs are sent. Cisco introduced two commands 'timers throttle lsa all’ and 'timers lsa arrival’, which allow operators to tune these parameters. I have been writing a patch to also support 'timers lsa arrival’ fully and ‘timers throttle lsa all’ (without the throttling part) also in quagga.
-rw-r--r--lib/libospf.h4
-rw-r--r--ospfd/ospf_flood.c2
-rw-r--r--ospfd/ospf_lsa.c15
-rw-r--r--ospfd/ospf_lsa.h1
-rw-r--r--ospfd/ospf_opaque.c26
-rw-r--r--ospfd/ospf_packet.c6
-rw-r--r--ospfd/ospf_vty.c91
-rw-r--r--ospfd/ospf_zebra.c6
-rw-r--r--ospfd/ospfd.c4
-rw-r--r--ospfd/ospfd.h4
10 files changed, 134 insertions, 25 deletions
diff --git a/lib/libospf.h b/lib/libospf.h
index 2796209d..e8db5c13 100644
--- a/lib/libospf.h
+++ b/lib/libospf.h
@@ -39,8 +39,8 @@
#else
#define OSPF_LS_REFRESH_TIME 1800
#endif
-#define OSPF_MIN_LS_INTERVAL 5
-#define OSPF_MIN_LS_ARRIVAL 1
+#define OSPF_MIN_LS_INTERVAL 5000 /* msec */
+#define OSPF_MIN_LS_ARRIVAL 1000 /* msec */
#define OSPF_LSA_INITIAL_AGE 0 /* useful for debug */
#define OSPF_LSA_MAXAGE 3600
#define OSPF_CHECK_AGE 300
diff --git a/ospfd/ospf_flood.c b/ospfd/ospf_flood.c
index 0e42ff54..df19adff 100644
--- a/ospfd/ospf_flood.c
+++ b/ospfd/ospf_flood.c
@@ -266,7 +266,7 @@ ospf_flood (struct ospf *ospf, struct ospf_neighbor *nbr,
; /* Accept this LSA for quick LSDB resynchronization. */
}
else if (tv_cmp (tv_sub (recent_relative_time (), current->tv_recv),
- int2tv (OSPF_MIN_LS_ARRIVAL)) < 0)
+ msec2tv (ospf->min_ls_arrival)) < 0)
{
if (IS_DEBUG_OSPF_EVENT)
zlog_debug ("LSA[Flooding]: LSA is received recently.");
diff --git a/ospfd/ospf_lsa.c b/ospfd/ospf_lsa.c
index f032601a..e62a4e7b 100644
--- a/ospfd/ospf_lsa.c
+++ b/ospfd/ospf_lsa.c
@@ -108,6 +108,17 @@ int2tv (int a)
}
struct timeval
+msec2tv (int a)
+{
+ struct timeval ret;
+
+ ret.tv_sec = 0;
+ ret.tv_usec = a * 1000;
+
+ return tv_adjust (ret);
+}
+
+struct timeval
tv_add (struct timeval a, struct timeval b)
{
struct timeval ret;
@@ -145,9 +156,9 @@ ospf_lsa_refresh_delay (struct ospf_lsa *lsa)
quagga_gettime (QUAGGA_CLK_MONOTONIC, &now);
delta = tv_sub (now, lsa->tv_orig);
- if (tv_cmp (delta, int2tv (OSPF_MIN_LS_INTERVAL)) < 0)
+ if (tv_cmp (delta, msec2tv (OSPF_MIN_LS_INTERVAL)) < 0)
{
- delay = tv_ceil (tv_sub (int2tv (OSPF_MIN_LS_INTERVAL), delta));
+ delay = tv_ceil (tv_sub (msec2tv (OSPF_MIN_LS_INTERVAL), delta));
if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
zlog_debug ("LSA[Type%d:%s]: Refresh timer delay %d seconds",
diff --git a/ospfd/ospf_lsa.h b/ospfd/ospf_lsa.h
index c71877da..dd3b91a5 100644
--- a/ospfd/ospf_lsa.h
+++ b/ospfd/ospf_lsa.h
@@ -237,6 +237,7 @@ extern struct timeval tv_adjust (struct timeval);
extern int tv_ceil (struct timeval);
extern int tv_floor (struct timeval);
extern struct timeval int2tv (int);
+extern struct timeval msec2tv (int);
extern struct timeval tv_add (struct timeval, struct timeval);
extern struct timeval tv_sub (struct timeval, struct timeval);
extern int tv_cmp (struct timeval, struct timeval);
diff --git a/ospfd/ospf_opaque.c b/ospfd/ospf_opaque.c
index f584fc71..64284803 100644
--- a/ospfd/ospf_opaque.c
+++ b/ospfd/ospf_opaque.c
@@ -1331,10 +1331,10 @@ ospf_opaque_lsa_originate_schedule (struct ospf_interface *oi, int *delay0)
&& oi->t_opaque_lsa_self == NULL)
{
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug ("Schedule Type-9 Opaque-LSA origination in %d sec later.", delay);
+ zlog_debug ("Schedule Type-9 Opaque-LSA origination in %d ms later.", delay);
oi->t_opaque_lsa_self =
- thread_add_timer (master, ospf_opaque_type9_lsa_originate, oi, delay);
- delay += OSPF_MIN_LS_INTERVAL;
+ thread_add_timer_msec (master, ospf_opaque_type9_lsa_originate, oi, delay);
+ delay += top->min_ls_interval;
}
if (! list_isempty (ospf_opaque_type10_funclist)
@@ -1347,11 +1347,11 @@ ospf_opaque_lsa_originate_schedule (struct ospf_interface *oi, int *delay0)
* again and again.
*/
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug ("Schedule Type-10 Opaque-LSA origination in %d sec later.", delay);
+ zlog_debug ("Schedule Type-10 Opaque-LSA origination in %d ms later.", delay);
area->t_opaque_lsa_self =
- thread_add_timer (master, ospf_opaque_type10_lsa_originate,
+ thread_add_timer_msec (master, ospf_opaque_type10_lsa_originate,
area, delay);
- delay += OSPF_MIN_LS_INTERVAL;
+ delay += top->min_ls_interval;
}
if (! list_isempty (ospf_opaque_type11_funclist)
@@ -1364,11 +1364,11 @@ ospf_opaque_lsa_originate_schedule (struct ospf_interface *oi, int *delay0)
* again and again.
*/
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug ("Schedule Type-11 Opaque-LSA origination in %d sec later.", delay);
+ zlog_debug ("Schedule Type-11 Opaque-LSA origination in %d ms later.", delay);
top->t_opaque_lsa_self =
- thread_add_timer (master, ospf_opaque_type11_lsa_originate,
+ thread_add_timer_msec (master, ospf_opaque_type11_lsa_originate,
top, delay);
- delay += OSPF_MIN_LS_INTERVAL;
+ delay += top->min_ls_interval;
}
/*
@@ -1646,7 +1646,7 @@ ospf_opaque_lsa_refresh (struct ospf_lsa *lsa)
#define OSPF_OPAQUE_TIMER_ON(T,F,L,V) \
if (!(T)) \
- (T) = thread_add_timer (master, (F), (L), (V))
+ (T) = thread_add_timer_msec (master, (F), (L), (V))
static struct ospf_lsa *pseudo_lsa (struct ospf_interface *oi, struct ospf_area *area, u_char lsa_type, u_char opaque_type);
static int ospf_opaque_type9_lsa_reoriginate_timer (struct thread *t);
@@ -1794,11 +1794,11 @@ ospf_opaque_lsa_reoriginate_schedule (void *lsa_type_dependent,
* it is highly possible that these conditions might not be satisfied
* at the time of re-origination function is to be called.
*/
- delay = OSPF_MIN_LS_INTERVAL; /* XXX */
+ delay = top->min_ls_interval; /* XXX */
if (IS_DEBUG_OSPF_EVENT)
zlog_debug ("Schedule Type-%u Opaque-LSA to RE-ORIGINATE in %d"
- " sec later: [opaque-type=%u]",
+ " ms later: [opaque-type=%u]",
lsa_type, delay,
GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)));
@@ -2024,7 +2024,7 @@ ospf_opaque_lsa_refresh_schedule (struct ospf_lsa *lsa0)
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)));
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:
return;
}
diff --git a/ospfd/ospf_packet.c b/ospfd/ospf_packet.c
index c6cd0184..73111e87 100644
--- a/ospfd/ospf_packet.c
+++ b/ospfd/ospf_packet.c
@@ -1703,7 +1703,7 @@ ospf_upd_list_clean (struct list *lsas)
/* OSPF Link State Update message read -- RFC2328 Section 13. */
static void
-ospf_ls_upd (struct ip *iph, struct ospf_header *ospfh,
+ospf_ls_upd (struct ospf *ospf, struct ip *iph, struct ospf_header *ospfh,
struct stream *s, struct ospf_interface *oi, u_int16_t size)
{
struct ospf_neighbor *nbr;
@@ -2046,7 +2046,7 @@ ospf_ls_upd (struct ip *iph, struct ospf_header *ospfh,
quagga_gettime (QUAGGA_CLK_MONOTONIC, &now);
if (tv_cmp (tv_sub (now, current->tv_orig),
- int2tv (OSPF_MIN_LS_ARRIVAL)) >= 0)
+ msec2tv (ospf->min_ls_arrival)) >= 0)
/* Trap NSSA type later.*/
ospf_ls_upd_send_lsa (nbr, current, OSPF_SEND_PACKET_DIRECT);
DISCARD_LSA (lsa, 8);
@@ -2932,7 +2932,7 @@ ospf_read (struct thread *thread)
ospf_ls_req (iph, ospfh, ibuf, oi, length);
break;
case OSPF_MSG_LS_UPD:
- ospf_ls_upd (iph, ospfh, ibuf, oi, length);
+ ospf_ls_upd (ospf, iph, ospfh, ibuf, oi, length);
break;
case OSPF_MSG_LS_ACK:
ospf_ls_ack (iph, ospfh, ibuf, oi, length);
diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c
index 9d04892c..e5e56319 100644
--- a/ospfd/ospf_vty.c
+++ b/ospfd/ospf_vty.c
@@ -2233,6 +2233,83 @@ ospf_timers_spf_set (struct vty *vty, unsigned int delay,
return CMD_SUCCESS;
}
+DEFUN (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"
+ NO_STR
+ "Delay (msec) between sending LSAs\n")
+{
+ struct ospf *ospf = vty->index;
+ unsigned int interval;
+
+ if (argc != 1)
+ {
+ vty_out (vty, "Insufficient arguments%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ VTY_GET_INTEGER ("LSA interval", interval, argv[0]);
+
+ 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",
+ NO_STR
+ "Adjust routing timers\n"
+ "Throttling adaptive timer\n"
+ "LSA delay between transmissions\n")
+{
+ struct ospf *ospf = vty->index;
+ ospf->min_ls_interval = OSPF_MIN_LS_INTERVAL;
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (ospf_timers_min_ls_arrival,
+ ospf_timers_min_ls_arrival_cmd,
+ "timers lsa arrival <0-1000>",
+ "Adjust routing timers\n"
+ "Throttling link state advertisement delays\n"
+ "OSPF minimum arrival interval delay\n"
+ "Delay (msec) between accepted LSAs\n")
+{
+ struct ospf *ospf = vty->index;
+ unsigned int arrival;
+
+ if (argc != 1)
+ {
+ vty_out (vty, "Insufficient arguments%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ VTY_GET_INTEGER_RANGE ("minimum LSA inter-arrival time", arrival, argv[0], 0, 1000);
+
+ ospf->min_ls_arrival = arrival;
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_ospf_timers_min_ls_arrival,
+ no_ospf_timers_min_ls_arrival_cmd,
+ "no timers lsa arrival",
+ NO_STR
+ "Adjust routing timers\n"
+ "Throttling link state advertisement delays\n"
+ "OSPF minimum arrival interval delay\n")
+{
+ struct ospf *ospf = vty->index;
+ ospf->min_ls_arrival = OSPF_MIN_LS_ARRIVAL;
+
+ return CMD_SUCCESS;
+}
+
DEFUN (ospf_timers_throttle_spf,
ospf_timers_throttle_spf_cmd,
"timers throttle spf <0-600000> <0-600000> <0-600000>",
@@ -7289,6 +7366,14 @@ ospf_config_write (struct vty *vty)
ospf->ref_bandwidth / 1000, VTY_NEWLINE);
}
+ /* LSA timers */
+ if (ospf->min_ls_interval != OSPF_MIN_LS_INTERVAL)
+ vty_out (vty, " timers throttle lsa all %d%s",
+ ospf->min_ls_interval, VTY_NEWLINE);
+ if (ospf->min_ls_arrival != OSPF_MIN_LS_ARRIVAL)
+ vty_out (vty, " timers lsa arrival %d%s",
+ ospf->min_ls_arrival, VTY_NEWLINE);
+
/* SPF timers print. */
if (ospf->spf_delay != OSPF_SPF_DELAY_DEFAULT ||
ospf->spf_holdtime != OSPF_SPF_HOLDTIME_DEFAULT ||
@@ -7700,6 +7785,12 @@ ospf_vty_init (void)
install_element (OSPF_NODE, &ospf_area_import_list_cmd);
install_element (OSPF_NODE, &no_ospf_area_import_list_cmd);
+ /* LSA timer 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_min_ls_arrival_cmd);
+ install_element (OSPF_NODE, &no_ospf_timers_min_ls_arrival_cmd);
+
/* SPF timer commands */
install_element (OSPF_NODE, &ospf_timers_spf_cmd);
install_element (OSPF_NODE, &no_ospf_timers_spf_cmd);
diff --git a/ospfd/ospf_zebra.c b/ospfd/ospf_zebra.c
index 27041003..588f0fb5 100644
--- a/ospfd/ospf_zebra.c
+++ b/ospfd/ospf_zebra.c
@@ -1007,8 +1007,6 @@ ospf_distribute_list_update_timer (struct thread *thread)
return 0;
}
-#define OSPF_DISTRIBUTE_UPDATE_DELAY 5
-
/* Update distribute-list and set timer to apply access-list. */
void
ospf_distribute_list_update (struct ospf *ospf, uintptr_t type)
@@ -1025,8 +1023,8 @@ ospf_distribute_list_update (struct ospf *ospf, uintptr_t type)
/* Set timer. */
ospf->t_distribute_update =
- thread_add_timer (master, ospf_distribute_list_update_timer,
- (void *) type, OSPF_DISTRIBUTE_UPDATE_DELAY);
+ thread_add_timer_msec (master, ospf_distribute_list_update_timer,
+ (void *) type, ospf->min_ls_interval);
}
/* If access-list is updated, apply some check. */
diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c
index 1a549c3a..8c7d1c2f 100644
--- a/ospfd/ospfd.c
+++ b/ospfd/ospfd.c
@@ -199,6 +199,10 @@ ospf_new (void)
new->default_metric = -1;
new->ref_bandwidth = OSPF_DEFAULT_REF_BANDWIDTH;
+ /* LSA timers */
+ new->min_ls_interval = OSPF_MIN_LS_INTERVAL;
+ new->min_ls_arrival = OSPF_MIN_LS_ARRIVAL;
+
/* SPF timer value init. */
new->spf_delay = OSPF_SPF_DELAY_DEFAULT;
new->spf_holdtime = OSPF_SPF_HOLDTIME_DEFAULT;
diff --git a/ospfd/ospfd.h b/ospfd/ospfd.h
index 06841b83..c50e615f 100644
--- a/ospfd/ospfd.h
+++ b/ospfd/ospfd.h
@@ -147,6 +147,10 @@ struct ospf
#define OSPF_STUB_MAX_METRIC_SUMMARY_COST 0x00ff0000
+ /* LSA timers */
+ unsigned int min_ls_interval; /* minimum delay between LSAs (in msec) */
+ unsigned int min_ls_arrival; /* minimum interarrival time between LSAs (in msec) */
+
/* SPF parameters */
unsigned int spf_delay; /* SPF delay time. */
unsigned int spf_holdtime; /* SPF hold time. */