version 1.1.1.3, 2013/07/21 23:54:40
|
version 1.1.1.4, 2016/11/02 10:09:11
|
Line 40
|
Line 40
|
#include "ospf6_intra.h" |
#include "ospf6_intra.h" |
#include "ospf6_interface.h" |
#include "ospf6_interface.h" |
#include "ospf6d.h" |
#include "ospf6d.h" |
|
#include "ospf6_abr.h" |
|
|
unsigned char conf_debug_ospf6_spf = 0; |
unsigned char conf_debug_ospf6_spf = 0; |
|
|
Line 224 static void
|
Line 225 static void
|
ospf6_nexthop_calc (struct ospf6_vertex *w, struct ospf6_vertex *v, |
ospf6_nexthop_calc (struct ospf6_vertex *w, struct ospf6_vertex *v, |
caddr_t lsdesc) |
caddr_t lsdesc) |
{ |
{ |
int i, ifindex; | int i; |
| ifindex_t ifindex; |
struct ospf6_interface *oi; |
struct ospf6_interface *oi; |
u_int16_t type; |
u_int16_t type; |
u_int32_t adv_router; |
u_int32_t adv_router; |
Line 234 ospf6_nexthop_calc (struct ospf6_vertex *w, struct osp
|
Line 236 ospf6_nexthop_calc (struct ospf6_vertex *w, struct osp
|
|
|
assert (VERTEX_IS_TYPE (ROUTER, w)); |
assert (VERTEX_IS_TYPE (ROUTER, w)); |
ifindex = (VERTEX_IS_TYPE (NETWORK, v) ? v->nexthop[0].ifindex : |
ifindex = (VERTEX_IS_TYPE (NETWORK, v) ? v->nexthop[0].ifindex : |
ROUTER_LSDESC_GET_IFID (lsdesc)); | /* v is the local router & the interface_id is a local ifindex */ |
| (ifindex_t) ROUTER_LSDESC_GET_IFID (lsdesc)); |
| assert (ifindex >= 0); |
| |
oi = ospf6_interface_lookup_by_ifindex (ifindex); |
oi = ospf6_interface_lookup_by_ifindex (ifindex); |
if (oi == NULL) |
if (oi == NULL) |
{ |
{ |
Line 377 ospf6_spf_table_finish (struct ospf6_route_table *resu
|
Line 382 ospf6_spf_table_finish (struct ospf6_route_table *resu
|
} |
} |
} |
} |
|
|
|
static const char *ospf6_spf_reason_str[] = |
|
{ |
|
"R+", |
|
"R-", |
|
"N+", |
|
"N-", |
|
"L+", |
|
"L-", |
|
"R*", |
|
"N*", |
|
}; |
|
|
|
void ospf6_spf_reason_string (unsigned int reason, char *buf, int size) |
|
{ |
|
size_t bit; |
|
int len = 0; |
|
|
|
if (!buf) |
|
return; |
|
|
|
for (bit = 0; bit <= (sizeof(ospf6_spf_reason_str) / sizeof(char *)); bit++) |
|
{ |
|
if ((reason & (1 << bit)) && (len < size)) |
|
{ |
|
len += snprintf((buf + len), (size - len), "%s%s", |
|
(len > 0) ? ", " : "", ospf6_spf_reason_str[bit]); |
|
} |
|
} |
|
} |
|
|
/* RFC2328 16.1. Calculating the shortest-path tree for an area */ |
/* RFC2328 16.1. Calculating the shortest-path tree for an area */ |
/* RFC2740 3.8.1. Calculating the shortest path tree for an area */ |
/* RFC2740 3.8.1. Calculating the shortest path tree for an area */ |
void |
void |
Line 424 ospf6_spf_calculation (u_int32_t router_id,
|
Line 459 ospf6_spf_calculation (u_int32_t router_id,
|
if (ospf6_spf_install (v, result_table) < 0) |
if (ospf6_spf_install (v, result_table) < 0) |
continue; |
continue; |
|
|
|
/* Skip overloaded routers */ |
|
if ((OSPF6_LSA_IS_TYPE (ROUTER, v->lsa) && |
|
ospf6_router_is_stub_router (v->lsa))) |
|
continue; |
|
|
/* For each LS description in the just-added vertex V's LSA */ |
/* For each LS description in the just-added vertex V's LSA */ |
size = (VERTEX_IS_TYPE (ROUTER, v) ? |
size = (VERTEX_IS_TYPE (ROUTER, v) ? |
sizeof (struct ospf6_router_lsdesc) : |
sizeof (struct ospf6_router_lsdesc) : |
Line 506 static int
|
Line 546 static int
|
ospf6_spf_calculation_thread (struct thread *t) |
ospf6_spf_calculation_thread (struct thread *t) |
{ |
{ |
struct ospf6_area *oa; |
struct ospf6_area *oa; |
|
struct ospf6 *ospf6; |
struct timeval start, end, runtime; |
struct timeval start, end, runtime; |
|
struct listnode *node; |
|
struct ospf6_route *route; |
|
int areas_processed = 0; |
|
char rbuf[32]; |
|
|
oa = (struct ospf6_area *) THREAD_ARG (t); | ospf6 = (struct ospf6 *)THREAD_ARG (t); |
oa->thread_spf_calculation = NULL; | ospf6->t_spf_calc = NULL; |
|
|
if (IS_OSPF6_DEBUG_SPF (PROCESS)) |
|
zlog_debug ("SPF calculation for Area %s", oa->name); |
|
if (IS_OSPF6_DEBUG_SPF (DATABASE)) |
|
ospf6_spf_log_database (oa); |
|
|
|
/* execute SPF calculation */ |
/* execute SPF calculation */ |
quagga_gettime (QUAGGA_CLK_MONOTONIC, &start); |
quagga_gettime (QUAGGA_CLK_MONOTONIC, &start); |
ospf6_spf_calculation (oa->ospf6->router_id, oa->spf_table, oa); | |
| for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa)) |
| { |
| |
| if (oa == ospf6->backbone) |
| continue; |
| |
| if (IS_OSPF6_DEBUG_SPF (PROCESS)) |
| zlog_debug ("SPF calculation for Area %s", oa->name); |
| if (IS_OSPF6_DEBUG_SPF (DATABASE)) |
| ospf6_spf_log_database (oa); |
| |
| ospf6_spf_calculation (ospf6->router_id, oa->spf_table, oa); |
| ospf6_intra_route_calculation (oa); |
| ospf6_intra_brouter_calculation (oa); |
| |
| areas_processed++; |
| } |
| |
| if (ospf6->backbone) |
| { |
| if (IS_OSPF6_DEBUG_SPF (PROCESS)) |
| zlog_debug ("SPF calculation for Backbone area %s", |
| ospf6->backbone->name); |
| if (IS_OSPF6_DEBUG_SPF (DATABASE)) |
| ospf6_spf_log_database(ospf6->backbone); |
| |
| ospf6_spf_calculation(ospf6->router_id, ospf6->backbone->spf_table, |
| ospf6->backbone); |
| ospf6_intra_route_calculation(ospf6->backbone); |
| ospf6_intra_brouter_calculation(ospf6->backbone); |
| areas_processed++; |
| } |
| |
| /* Redo summaries if required */ |
| for (route = ospf6_route_head (ospf6->route_table); route; |
| route = ospf6_route_next (route)) |
| ospf6_abr_originate_summary(route); |
| |
quagga_gettime (QUAGGA_CLK_MONOTONIC, &end); |
quagga_gettime (QUAGGA_CLK_MONOTONIC, &end); |
timersub (&end, &start, &runtime); |
timersub (&end, &start, &runtime); |
|
|
if (IS_OSPF6_DEBUG_SPF (PROCESS) || IS_OSPF6_DEBUG_SPF (TIME)) | ospf6->ts_spf_duration = runtime; |
zlog_debug ("SPF runtime: %ld sec %ld usec", | |
runtime.tv_sec, runtime.tv_usec); | |
|
|
ospf6_intra_route_calculation (oa); | ospf6_spf_reason_string(ospf6->spf_reason, rbuf, sizeof(rbuf)); |
ospf6_intra_brouter_calculation (oa); | |
|
|
|
if (IS_OSPF6_DEBUG_SPF (PROCESS) || IS_OSPF6_DEBUG_SPF (TIME)) |
|
zlog_debug ("SPF runtime: %lld sec %lld usec", |
|
(long long)runtime.tv_sec, (long long)runtime.tv_usec); |
|
|
|
zlog_info("SPF processing: # Areas: %d, SPF runtime: %lld sec %lld usec, " |
|
"Reason: %s\n", areas_processed, |
|
(long long)runtime.tv_sec, (long long)runtime.tv_usec, |
|
rbuf); |
|
ospf6->last_spf_reason = ospf6->spf_reason; |
|
ospf6_reset_spf_reason(ospf6); |
return 0; |
return 0; |
} |
} |
|
|
|
/* Add schedule for SPF calculation. To avoid frequenst SPF calc, we |
|
set timer for SPF calc. */ |
void |
void |
ospf6_spf_schedule (struct ospf6_area *oa) | ospf6_spf_schedule (struct ospf6 *ospf6, unsigned int reason) |
{ |
{ |
if (oa->thread_spf_calculation) | unsigned long delay, elapsed, ht; |
| struct timeval now, result; |
| |
| ospf6_set_spf_reason(ospf6, reason); |
| |
| if (IS_OSPF6_DEBUG_SPF(PROCESS) || IS_OSPF6_DEBUG_SPF (TIME)) |
| { |
| char rbuf[32]; |
| ospf6_spf_reason_string(reason, rbuf, sizeof(rbuf)); |
| zlog_debug ("SPF: calculation timer scheduled (reason %s)", rbuf); |
| } |
| |
| /* OSPF instance does not exist. */ |
| if (ospf6 == NULL) |
return; |
return; |
oa->thread_spf_calculation = | |
thread_add_event (master, ospf6_spf_calculation_thread, oa, 0); | /* SPF calculation timer is already scheduled. */ |
| if (ospf6->t_spf_calc) |
| { |
| if (IS_OSPF6_DEBUG_SPF(PROCESS) || IS_OSPF6_DEBUG_SPF (TIME)) |
| zlog_debug ("SPF: calculation timer is already scheduled: %p", |
| (void *)ospf6->t_spf_calc); |
| return; |
| } |
| |
| /* XXX Monotic timers: we only care about relative time here. */ |
| now = recent_relative_time (); |
| timersub (&now, &ospf6->ts_spf, &result); |
| |
| elapsed = (result.tv_sec * 1000) + (result.tv_usec / 1000); |
| ht = ospf6->spf_holdtime * ospf6->spf_hold_multiplier; |
| |
| if (ht > ospf6->spf_max_holdtime) |
| ht = ospf6->spf_max_holdtime; |
| |
| /* Get SPF calculation delay time. */ |
| if (elapsed < ht) |
| { |
| /* Got an event within the hold time of last SPF. We need to |
| * increase the hold_multiplier, if it's not already at/past |
| * maximum value, and wasn't already increased.. |
| */ |
| if (ht < ospf6->spf_max_holdtime) |
| ospf6->spf_hold_multiplier++; |
| |
| /* always honour the SPF initial delay */ |
| if ( (ht - elapsed) < ospf6->spf_delay) |
| delay = ospf6->spf_delay; |
| else |
| delay = ht - elapsed; |
| } |
| else |
| { |
| /* Event is past required hold-time of last SPF */ |
| delay = ospf6->spf_delay; |
| ospf6->spf_hold_multiplier = 1; |
| } |
| |
| if (IS_OSPF6_DEBUG_SPF(PROCESS) || IS_OSPF6_DEBUG_SPF (TIME)) |
| zlog_debug ("SPF: calculation timer delay = %ld", delay); |
| |
| zlog_info ("SPF: Scheduled in %ld msec", delay); |
| |
| ospf6->t_spf_calc = |
| thread_add_timer_msec (master, ospf6_spf_calculation_thread, ospf6, delay); |
} |
} |
|
|
void |
void |
Line 666 DEFUN (no_debug_ospf6_spf_database,
|
Line 814 DEFUN (no_debug_ospf6_spf_database,
|
return CMD_SUCCESS; |
return CMD_SUCCESS; |
} |
} |
|
|
|
static int |
|
ospf6_timers_spf_set (struct vty *vty, unsigned int delay, |
|
unsigned int hold, |
|
unsigned int max) |
|
{ |
|
struct ospf6 *ospf = vty->index; |
|
|
|
ospf->spf_delay = delay; |
|
ospf->spf_holdtime = hold; |
|
ospf->spf_max_holdtime = max; |
|
|
|
return CMD_SUCCESS; |
|
} |
|
|
|
DEFUN (ospf6_timers_throttle_spf, |
|
ospf6_timers_throttle_spf_cmd, |
|
"timers throttle spf <0-600000> <0-600000> <0-600000>", |
|
"Adjust routing timers\n" |
|
"Throttling adaptive timer\n" |
|
"OSPF6 SPF timers\n" |
|
"Delay (msec) from first change received till SPF calculation\n" |
|
"Initial hold time (msec) between consecutive SPF calculations\n" |
|
"Maximum hold time (msec)\n") |
|
{ |
|
unsigned int delay, hold, max; |
|
|
|
if (argc != 3) |
|
{ |
|
vty_out (vty, "Insufficient arguments%s", VTY_NEWLINE); |
|
return CMD_WARNING; |
|
} |
|
|
|
VTY_GET_INTEGER_RANGE ("SPF delay timer", delay, argv[0], 0, 600000); |
|
VTY_GET_INTEGER_RANGE ("SPF hold timer", hold, argv[1], 0, 600000); |
|
VTY_GET_INTEGER_RANGE ("SPF max-hold timer", max, argv[2], 0, 600000); |
|
|
|
return ospf6_timers_spf_set (vty, delay, hold, max); |
|
} |
|
|
|
DEFUN (no_ospf6_timers_throttle_spf, |
|
no_ospf6_timers_throttle_spf_cmd, |
|
"no timers throttle spf", |
|
NO_STR |
|
"Adjust routing timers\n" |
|
"Throttling adaptive timer\n" |
|
"OSPF6 SPF timers\n") |
|
{ |
|
return ospf6_timers_spf_set (vty, |
|
OSPF_SPF_DELAY_DEFAULT, |
|
OSPF_SPF_HOLDTIME_DEFAULT, |
|
OSPF_SPF_MAX_HOLDTIME_DEFAULT); |
|
} |
|
|
int |
int |
config_write_ospf6_debug_spf (struct vty *vty) |
config_write_ospf6_debug_spf (struct vty *vty) |
{ |
{ |
Line 679 config_write_ospf6_debug_spf (struct vty *vty)
|
Line 880 config_write_ospf6_debug_spf (struct vty *vty)
|
} |
} |
|
|
void |
void |
|
ospf6_spf_config_write (struct vty *vty) |
|
{ |
|
|
|
if (ospf6->spf_delay != OSPF_SPF_DELAY_DEFAULT || |
|
ospf6->spf_holdtime != OSPF_SPF_HOLDTIME_DEFAULT || |
|
ospf6->spf_max_holdtime != OSPF_SPF_MAX_HOLDTIME_DEFAULT) |
|
vty_out (vty, " timers throttle spf %d %d %d%s", |
|
ospf6->spf_delay, ospf6->spf_holdtime, |
|
ospf6->spf_max_holdtime, VTY_NEWLINE); |
|
|
|
} |
|
|
|
void |
install_element_ospf6_debug_spf (void) |
install_element_ospf6_debug_spf (void) |
{ |
{ |
install_element (ENABLE_NODE, &debug_ospf6_spf_process_cmd); |
install_element (ENABLE_NODE, &debug_ospf6_spf_process_cmd); |
Line 698 install_element_ospf6_debug_spf (void)
|
Line 912 install_element_ospf6_debug_spf (void)
|
void |
void |
ospf6_spf_init (void) |
ospf6_spf_init (void) |
{ |
{ |
|
install_element (OSPF6_NODE, &ospf6_timers_throttle_spf_cmd); |
|
install_element (OSPF6_NODE, &no_ospf6_timers_throttle_spf_cmd); |
} |
} |
|
|
|
|