Merge volatile/cumulus_ospf6d

Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
This commit is contained in:
David Lamparter 2014-03-18 17:04:25 +01:00
commit e708ed69aa
35 changed files with 2059 additions and 718 deletions

View File

@ -28,6 +28,44 @@ Bind interface to specified area, and start sending OSPF packets. @var{area} ca
be specified as 0.
@end deffn
@deffn {OSPF6 Command} {timers throttle spf @var{delay} @var{initial-holdtime} @var{max-holdtime}} {}
@deffnx {OSPF6 Command} {no timers throttle spf} {}
This command sets the initial @var{delay}, the @var{initial-holdtime}
and the @var{maximum-holdtime} between when SPF is calculated and the
event which triggered the calculation. The times are specified in
milliseconds and must be in the range of 0 to 600000 milliseconds.
The @var{delay} specifies the minimum amount of time to delay SPF
calculation (hence it affects how long SPF calculation is delayed after
an event which occurs outside of the holdtime of any previous SPF
calculation, and also serves as a minimum holdtime).
Consecutive SPF calculations will always be seperated by at least
'hold-time' milliseconds. The hold-time is adaptive and initially is
set to the @var{initial-holdtime} configured with the above command.
Events which occur within the holdtime of the previous SPF calculation
will cause the holdtime to be increased by @var{initial-holdtime}, bounded
by the @var{maximum-holdtime} configured with this command. If the adaptive
hold-time elapses without any SPF-triggering event occuring then
the current holdtime is reset to the @var{initial-holdtime}.
@example
@group
router ospf6
timers throttle spf 200 400 10000
@end group
@end example
In this example, the @var{delay} is set to 200ms, the @var{initial
holdtime} is set to 400ms and the @var{maximum holdtime} to 10s. Hence
there will always be at least 200ms between an event which requires SPF
calculation and the actual SPF calculation. Further consecutive SPF
calculations will always be seperated by between 400ms to 10s, the
hold-time increasing by 400ms each time an SPF-triggering event occurs
within the hold-time of the previous SPF calculation.
@end deffn
@node OSPF6 area
@section OSPF6 area
@ -60,6 +98,10 @@ Sets interface's Router Priority. Default value is 1.
Sets interface's Inf-Trans-Delay. Default value is 1.
@end deffn
@deffn {Interface Command} {ipv6 ospf6 network (broadcast|point-to-point)} {}
Set explicitly network type for specifed interface.
@end deffn
@node Redistribute routes to OSPF6
@section Redistribute routes to OSPF6

View File

@ -27,7 +27,7 @@ pkginclude_HEADERS = \
str.h stream.h table.h thread.h vector.h version.h vty.h zebra.h \
plist.h zclient.h sockopt.h smux.h md5.h if_rmap.h keychain.h \
privs.h sigevent.h pqueue.h jhash.h zassert.h memtypes.h \
workqueue.h route_types.h
workqueue.h route_types.h libospf.h
EXTRA_DIST = \
regex.c regex-gnu.h \

View File

@ -304,6 +304,30 @@ if_lookup_address (struct in_addr src)
return match;
}
/* Lookup interface by prefix */
struct interface *
if_lookup_prefix (struct prefix *prefix)
{
struct listnode *node;
struct prefix addr;
int bestlen = 0;
struct listnode *cnode;
struct interface *ifp;
struct connected *c;
for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
{
for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, c))
{
if (prefix_cmp(c->address, prefix) == 0)
{
return ifp;
}
}
}
return NULL;
}
/* Get interface by name if given name interface doesn't exist create
one. */
struct interface *

View File

@ -245,6 +245,7 @@ extern struct interface *if_create (const char *name, int namelen);
extern struct interface *if_lookup_by_index (unsigned int);
extern struct interface *if_lookup_exact_address (struct in_addr);
extern struct interface *if_lookup_address (struct in_addr);
extern struct interface *if_lookup_prefix (struct prefix *prefix);
/* These 2 functions are to be used when the ifname argument is terminated
by a '\0' character: */

92
lib/libospf.h Normal file
View File

@ -0,0 +1,92 @@
/*
* Defines and structures common to OSPFv2 and OSPFv3
* Copyright (C) 1998, 99, 2000 Kunihiro Ishiguro, Toshiaki Takada
*
* This file is part of GNU Zebra.
*
* GNU Zebra is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* GNU Zebra is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Zebra; see the file COPYING. If not, write to the Free
* Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifndef _LIBOSPFD_H
#define _LIBOSPFD_H
/* IP precedence. */
#ifndef IPTOS_PREC_INTERNETCONTROL
#define IPTOS_PREC_INTERNETCONTROL 0xC0
#endif /* IPTOS_PREC_INTERNETCONTROL */
/* Default protocol, port number. */
#ifndef IPPROTO_OSPFIGP
#define IPPROTO_OSPFIGP 89
#endif /* IPPROTO_OSPFIGP */
/* Architectual Constants */
#ifdef DEBUG
#define OSPF_LS_REFRESH_TIME 60
#else
#define OSPF_LS_REFRESH_TIME 1800
#endif
#define OSPF_MIN_LS_INTERVAL 5
#define OSPF_MIN_LS_ARRIVAL 1
#define OSPF_LSA_INITIAL_AGE 0 /* useful for debug */
#define OSPF_LSA_MAXAGE 3600
#define OSPF_CHECK_AGE 300
#define OSPF_LSA_MAXAGE_DIFF 900
#define OSPF_LS_INFINITY 0xffffff
#define OSPF_DEFAULT_DESTINATION 0x00000000 /* 0.0.0.0 */
#define OSPF_INITIAL_SEQUENCE_NUMBER 0x80000001
#define OSPF_MAX_SEQUENCE_NUMBER 0x7fffffff
/* OSPF Interface Types */
#define OSPF_IFTYPE_NONE 0
#define OSPF_IFTYPE_POINTOPOINT 1
#define OSPF_IFTYPE_BROADCAST 2
#define OSPF_IFTYPE_NBMA 3
#define OSPF_IFTYPE_POINTOMULTIPOINT 4
#define OSPF_IFTYPE_VIRTUALLINK 5
#define OSPF_IFTYPE_LOOPBACK 6
#define OSPF_IFTYPE_MAX 7
/* OSPF interface default values. */
#define OSPF_OUTPUT_COST_DEFAULT 10
#define OSPF_OUTPUT_COST_INFINITE UINT16_MAX
#define OSPF_ROUTER_DEAD_INTERVAL_DEFAULT 40
#define OSPF_ROUTER_DEAD_INTERVAL_MINIMAL 1
#define OSPF_HELLO_INTERVAL_DEFAULT 10
#define OSPF_ROUTER_PRIORITY_DEFAULT 1
#define OSPF_RETRANSMIT_INTERVAL_DEFAULT 5
#define OSPF_TRANSMIT_DELAY_DEFAULT 1
#define OSPF_DEFAULT_BANDWIDTH 10000 /* Kbps */
#define OSPF_DEFAULT_REF_BANDWIDTH 100000 /* Kbps */
#define OSPF_POLL_INTERVAL_DEFAULT 60
#define OSPF_NEIGHBOR_PRIORITY_DEFAULT 0
#define OSPF_MTU_IGNORE_DEFAULT 0
#define OSPF_FAST_HELLO_DEFAULT 0
#define OSPF_AREA_BACKBONE 0x00000000 /* 0.0.0.0 */
/* SPF Throttling timer values. */
#define OSPF_SPF_DELAY_DEFAULT 200
#define OSPF_SPF_HOLDTIME_DEFAULT 1000
#define OSPF_SPF_MAX_HOLDTIME_DEFAULT 10000
#define OSPF_LSA_MAXAGE_CHECK_INTERVAL 30
#define OSPF_LSA_MAXAGE_REMOVE_DELAY_DEFAULT 60
#endif /* _LIBOSPFD_H */

View File

@ -253,7 +253,7 @@ ospf6_abr_originate_summary_to_area (struct ospf6_route *route,
}
/* do not generate if the route cost is greater or equal to LSInfinity */
if (route->path.cost >= LS_INFINITY)
if (route->path.cost >= OSPF_LS_INFINITY)
{
if (is_debug)
zlog_debug ("The cost exceeds LSInfinity, withdraw");
@ -296,7 +296,7 @@ ospf6_abr_originate_summary_to_area (struct ospf6_route *route,
/* ranges are ignored when originate backbone routes to transit area.
Otherwise, if ranges are configured, the route is suppressed. */
if (range && ! CHECK_FLAG (range->flag, OSPF6_ROUTE_REMOVE) &&
(route->path.area_id != BACKBONE_AREA_ID ||
(route->path.area_id != OSPF_AREA_BACKBONE ||
! IS_AREA_TRANSIT (area)))
{
if (is_debug)
@ -537,13 +537,13 @@ ospf6_abr_examin_summary (struct ospf6_lsa *lsa, struct ospf6_area *oa)
int i;
char buf[64];
int is_debug = 0;
struct ospf6_inter_prefix_lsa *prefix_lsa = NULL;
struct ospf6_inter_router_lsa *router_lsa = NULL;
memset (&prefix, 0, sizeof (prefix));
if (lsa->header->type == htons (OSPF6_LSTYPE_INTER_PREFIX))
{
struct ospf6_inter_prefix_lsa *prefix_lsa;
if (IS_OSPF6_DEBUG_EXAMIN (INTER_PREFIX))
{
is_debug++;
@ -564,8 +564,6 @@ ospf6_abr_examin_summary (struct ospf6_lsa *lsa, struct ospf6_area *oa)
}
else if (lsa->header->type == htons (OSPF6_LSTYPE_INTER_ROUTER))
{
struct ospf6_inter_router_lsa *router_lsa;
if (IS_OSPF6_DEBUG_EXAMIN (INTER_ROUTER))
{
is_debug++;
@ -604,7 +602,7 @@ ospf6_abr_examin_summary (struct ospf6_lsa *lsa, struct ospf6_area *oa)
}
/* (1) if cost == LSInfinity or if the LSA is MaxAge */
if (cost == LS_INFINITY)
if (cost == OSPF_LS_INFINITY)
{
if (is_debug)
zlog_debug ("cost is LS_INFINITY, ignore");
@ -632,6 +630,7 @@ ospf6_abr_examin_summary (struct ospf6_lsa *lsa, struct ospf6_area *oa)
}
/* (3) if the prefix is equal to an active configured address range */
/* or if the NU bit is set in the prefix */
if (lsa->header->type == htons (OSPF6_LSTYPE_INTER_PREFIX))
{
range = ospf6_route_lookup (&prefix, oa->range_table);
@ -643,6 +642,32 @@ ospf6_abr_examin_summary (struct ospf6_lsa *lsa, struct ospf6_area *oa)
ospf6_route_remove (old, table);
return;
}
if (CHECK_FLAG (prefix_lsa->prefix.prefix_options,
OSPF6_PREFIX_OPTION_NU) ||
CHECK_FLAG (prefix_lsa->prefix.prefix_options,
OSPF6_PREFIX_OPTION_LA))
{
if (is_debug)
zlog_debug ("Prefix has NU/LA bit set, ignore");
if (old)
ospf6_route_remove (old, table);
return;
}
}
if (lsa->header->type == htons (OSPF6_LSTYPE_INTER_ROUTER))
{
/* To pass test suites */
if (! OSPF6_OPT_ISSET (router_lsa->options, OSPF6_OPT_R) ||
! OSPF6_OPT_ISSET (router_lsa->options, OSPF6_OPT_V6))
{
if (is_debug)
zlog_debug ("Prefix has NU/LA bit set, ignore");
if (old)
ospf6_route_remove (old, table);
return;
}
}
/* (4) if the routing table entry for the ABR does not exist */
@ -764,12 +789,34 @@ ospf6_abr_reimport (struct ospf6_area *oa)
/* Display functions */
static char *
ospf6_inter_area_prefix_lsa_get_prefix_str (struct ospf6_lsa *lsa, char *buf,
int buflen, int pos)
{
struct ospf6_inter_prefix_lsa *prefix_lsa;
struct in6_addr in6;
if (lsa != NULL)
{
prefix_lsa = (struct ospf6_inter_prefix_lsa *)
OSPF6_LSA_HEADER_END (lsa->header);
ospf6_prefix_in6_addr (&in6, &prefix_lsa->prefix);
if (buf)
{
inet_ntop (AF_INET6, &in6, buf, buflen);
sprintf (&buf[strlen(buf)], "/%d", prefix_lsa->prefix.prefix_length);
}
}
return (buf);
}
static int
ospf6_inter_area_prefix_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
{
struct ospf6_inter_prefix_lsa *prefix_lsa;
struct in6_addr in6;
char buf[64];
char buf[INET6_ADDRSTRLEN];
prefix_lsa = (struct ospf6_inter_prefix_lsa *)
OSPF6_LSA_HEADER_END (lsa->header);
@ -781,14 +828,32 @@ ospf6_inter_area_prefix_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
buf, sizeof (buf));
vty_out (vty, " Prefix Options: %s%s", buf, VNL);
ospf6_prefix_in6_addr (&in6, &prefix_lsa->prefix);
inet_ntop (AF_INET6, &in6, buf, sizeof (buf));
vty_out (vty, " Prefix: %s/%d%s", buf,
prefix_lsa->prefix.prefix_length, VNL);
vty_out (vty, " Prefix: %s%s",
ospf6_inter_area_prefix_lsa_get_prefix_str (lsa, buf, sizeof(buf),
0), VNL);
return 0;
}
static char *
ospf6_inter_area_router_lsa_get_prefix_str (struct ospf6_lsa *lsa, char *buf,
int buflen, int pos)
{
struct ospf6_inter_router_lsa *router_lsa;
if (lsa != NULL)
{
router_lsa = (struct ospf6_inter_router_lsa *)
OSPF6_LSA_HEADER_END (lsa->header);
if (buf)
inet_ntop (AF_INET, &router_lsa->router_id, buf, buflen);
}
return (buf);
}
static int
ospf6_inter_area_router_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
{
@ -802,6 +867,7 @@ ospf6_inter_area_router_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
vty_out (vty, " Options: %s%s", buf, VNL);
vty_out (vty, " Metric: %lu%s",
(u_long) OSPF6_ABR_SUMMARY_METRIC (router_lsa), VNL);
inet_ntop (AF_INET, &router_lsa->router_id, buf, sizeof (buf));
vty_out (vty, " Destination Router ID: %s%s", buf, VNL);
@ -855,14 +921,18 @@ struct ospf6_lsa_handler inter_prefix_handler =
{
OSPF6_LSTYPE_INTER_PREFIX,
"Inter-Prefix",
ospf6_inter_area_prefix_lsa_show
"IAP",
ospf6_inter_area_prefix_lsa_show,
ospf6_inter_area_prefix_lsa_get_prefix_str,
};
struct ospf6_lsa_handler inter_router_handler =
{
OSPF6_LSTYPE_INTER_ROUTER,
"Inter-Router",
ospf6_inter_area_router_lsa_show
"IAR",
ospf6_inter_area_router_lsa_show,
ospf6_inter_area_router_lsa_get_prefix_str,
};
void

View File

@ -67,7 +67,8 @@ ospf6_area_lsdb_hook_add (struct ospf6_lsa *lsa)
zlog_debug ("Schedule SPF Calculation for %s",
OSPF6_AREA (lsa->lsdb->data)->name);
}
ospf6_spf_schedule (OSPF6_AREA (lsa->lsdb->data));
ospf6_spf_schedule (OSPF6_PROCESS(OSPF6_AREA (lsa->lsdb->data)->ospf6),
ospf6_lsadd_to_spf_reason(lsa));
break;
case OSPF6_LSTYPE_INTRA_PREFIX:
@ -97,7 +98,8 @@ ospf6_area_lsdb_hook_remove (struct ospf6_lsa *lsa)
zlog_debug ("Schedule SPF Calculation for %s",
OSPF6_AREA (lsa->lsdb->data)->name);
}
ospf6_spf_schedule (OSPF6_AREA (lsa->lsdb->data));
ospf6_spf_schedule (OSPF6_PROCESS(OSPF6_AREA (lsa->lsdb->data)->ospf6),
ospf6_lsremove_to_spf_reason(lsa));
break;
case OSPF6_LSTYPE_INTRA_PREFIX:
@ -164,9 +166,18 @@ ospf6_area_create (u_int32_t area_id, struct ospf6 *o)
oa->summary_router->scope = oa;
/* set default options */
OSPF6_OPT_SET (oa->options, OSPF6_OPT_V6);
if (CHECK_FLAG (o->flag, OSPF6_STUB_ROUTER))
{
OSPF6_OPT_CLEAR (oa->options, OSPF6_OPT_V6);
OSPF6_OPT_CLEAR (oa->options, OSPF6_OPT_R);
}
else
{
OSPF6_OPT_SET (oa->options, OSPF6_OPT_V6);
OSPF6_OPT_SET (oa->options, OSPF6_OPT_R);
}
OSPF6_OPT_SET (oa->options, OSPF6_OPT_E);
OSPF6_OPT_SET (oa->options, OSPF6_OPT_R);
oa->ospf6 = o;
listnode_add_sort (o->area_list, oa);
@ -182,18 +193,21 @@ ospf6_area_create (u_int32_t area_id, struct ospf6 *o)
void
ospf6_area_delete (struct ospf6_area *oa)
{
struct listnode *n, *nnode;
struct listnode *n;
struct ospf6_interface *oi;
ospf6_route_table_delete (oa->range_table);
ospf6_route_table_delete (oa->summary_prefix);
ospf6_route_table_delete (oa->summary_router);
/* ospf6 interface list */
for (ALL_LIST_ELEMENTS (oa->if_list, n, nnode, oi))
{
ospf6_interface_delete (oi);
}
/* The ospf6_interface structs store configuration
* information which should not be lost/reset when
* deleting an area.
* So just detach the interface from the area and
* keep it around. */
for (ALL_LIST_ELEMENTS_RO (oa->if_list, n, oi))
oi->area = NULL;
list_delete (oa->if_list);
ospf6_lsdb_delete (oa->lsdb);
@ -246,6 +260,7 @@ ospf6_area_enable (struct ospf6_area *oa)
for (ALL_LIST_ELEMENTS (oa->if_list, node, nnode, oi))
ospf6_interface_enable (oi);
ospf6_abr_enable_area (oa);
}
void
@ -258,6 +273,19 @@ ospf6_area_disable (struct ospf6_area *oa)
for (ALL_LIST_ELEMENTS (oa->if_list, node, nnode, oi))
ospf6_interface_disable (oi);
ospf6_abr_disable_area (oa);
ospf6_lsdb_remove_all (oa->lsdb);
ospf6_lsdb_remove_all (oa->lsdb_self);
ospf6_spf_table_finish(oa->spf_table);
ospf6_route_remove_all(oa->route_table);
THREAD_OFF (oa->thread_spf_calculation);
THREAD_OFF (oa->thread_route_calculation);
THREAD_OFF (oa->thread_router_lsa);
THREAD_OFF (oa->thread_intra_prefix_lsa);
}
@ -401,6 +429,7 @@ DEFUN (no_area_range,
}
ospf6_route_remove (range, oa->range_table);
return CMD_SUCCESS;
}

View File

@ -105,8 +105,6 @@ struct ospf6_area
#define OSPF6_AREA_TRANSIT 0x04 /* TransitCapability */
#define OSPF6_AREA_STUB 0x08
#define BACKBONE_AREA_ID (htonl (0))
#define IS_AREA_BACKBONE(oa) ((oa)->area_id == BACKBONE_AREA_ID)
#define IS_AREA_ENABLED(oa) (CHECK_FLAG ((oa)->flag, OSPF6_AREA_ENABLE))
#define IS_AREA_ACTIVE(oa) (CHECK_FLAG ((oa)->flag, OSPF6_AREA_ACTIVE))
#define IS_AREA_TRANSIT(oa) (CHECK_FLAG ((oa)->flag, OSPF6_AREA_TRANSIT))

View File

@ -174,13 +174,20 @@ ospf6_asbr_lsa_add (struct ospf6_lsa *lsa)
return;
}
if (OSPF6_ASBR_METRIC (external) == LS_INFINITY)
if (OSPF6_ASBR_METRIC (external) == OSPF_LS_INFINITY)
{
if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
zlog_debug ("Ignore LSA with LSInfinity Metric");
return;
}
if (CHECK_FLAG(external->prefix.prefix_options, OSPF6_PREFIX_OPTION_NU))
{
if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
zlog_debug ("Ignore LSA with NU bit set Metric");
return;
}
ospf6_linkstate_prefix (lsa->header->adv_router, htonl (0), &asbr_id);
asbr_entry = ospf6_route_lookup (&asbr_id, ospf6->brouter_table);
if (asbr_entry == NULL ||
@ -402,6 +409,8 @@ ospf6_asbr_redistribute_unset (int type)
ospf6_asbr_redistribute_remove (info->type, route->nexthop[0].ifindex,
&route->prefix);
}
ospf6_asbr_routemap_unset (type);
}
void
@ -629,7 +638,6 @@ DEFUN (ospf6_redistribute,
return CMD_WARNING;
ospf6_asbr_redistribute_unset (type);
ospf6_asbr_routemap_unset (type);
ospf6_asbr_redistribute_set (type);
return CMD_SUCCESS;
}
@ -670,7 +678,6 @@ DEFUN (no_ospf6_redistribute,
return CMD_WARNING;
ospf6_asbr_redistribute_unset (type);
ospf6_asbr_routemap_unset (type);
return CMD_SUCCESS;
}
@ -890,7 +897,7 @@ ospf6_routemap_rule_set_metric_compile (const char *arg)
u_int32_t metric;
char *endp;
metric = strtoul (arg, &endp, 0);
if (metric > LS_INFINITY || *endp != '\0')
if (metric > OSPF_LS_INFINITY || *endp != '\0')
return NULL;
return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
}
@ -1161,12 +1168,44 @@ ospf6_routemap_init (void)
/* Display functions */
static char *
ospf6_as_external_lsa_get_prefix_str (struct ospf6_lsa *lsa, char *buf,
int buflen, int pos)
{
struct ospf6_as_external_lsa *external;
struct in6_addr in6;
int prefix_length = 0;
if (lsa)
{
external = (struct ospf6_as_external_lsa *)
OSPF6_LSA_HEADER_END (lsa->header);
if (pos == 0)
{
ospf6_prefix_in6_addr (&in6, &external->prefix);
prefix_length = external->prefix.prefix_length;
}
else {
in6 = *((struct in6_addr *)
((caddr_t) external + sizeof (struct ospf6_as_external_lsa) +
OSPF6_PREFIX_SPACE (external->prefix.prefix_length)));
}
if (buf)
{
inet_ntop (AF_INET6, &in6, buf, buflen);
if (prefix_length)
sprintf (&buf[strlen(buf)], "/%d", prefix_length);
}
}
return (buf);
}
static int
ospf6_as_external_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
{
struct ospf6_as_external_lsa *external;
char buf[64];
struct in6_addr in6, *forwarding;
assert (lsa->header);
external = (struct ospf6_as_external_lsa *)
@ -1191,19 +1230,15 @@ ospf6_as_external_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
ntohs (external->prefix.prefix_refer_lstype),
VNL);
ospf6_prefix_in6_addr (&in6, &external->prefix);
inet_ntop (AF_INET6, &in6, buf, sizeof (buf));
vty_out (vty, " Prefix: %s/%d%s", buf,
external->prefix.prefix_length, VNL);
vty_out (vty, " Prefix: %s%s",
ospf6_as_external_lsa_get_prefix_str (lsa, buf, sizeof(buf), 0), VNL);
/* Forwarding-Address */
if (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_F))
{
forwarding = (struct in6_addr *)
((caddr_t) external + sizeof (struct ospf6_as_external_lsa) +
OSPF6_PREFIX_SPACE (external->prefix.prefix_length));
inet_ntop (AF_INET6, forwarding, buf, sizeof (buf));
vty_out (vty, " Forwarding-Address: %s%s", buf, VNL);
vty_out (vty, " Forwarding-Address: %s%s",
ospf6_as_external_lsa_get_prefix_str (lsa, buf, sizeof(buf), 1),
VNL);
}
return 0;
@ -1257,7 +1292,9 @@ struct ospf6_lsa_handler as_external_handler =
{
OSPF6_LSTYPE_AS_EXTERNAL,
"AS-External",
ospf6_as_external_lsa_show
"ASE",
ospf6_as_external_lsa_show,
ospf6_as_external_lsa_get_prefix_str
};
void
@ -1275,6 +1312,20 @@ ospf6_asbr_init (void)
install_element (OSPF6_NODE, &no_ospf6_redistribute_cmd);
}
void
ospf6_asbr_redistribute_reset (void)
{
int type;
for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
{
if (type == ZEBRA_ROUTE_OSPF6)
continue;
if (ospf6_zebra_is_redistribute (type))
ospf6_asbr_redistribute_unset(type);
}
}
void
ospf6_asbr_terminate (void)
{

View File

@ -89,6 +89,7 @@ extern void ospf6_asbr_redistribute_remove (int type, int ifindex,
extern int ospf6_redistribute_config_write (struct vty *vty);
extern void ospf6_asbr_init (void);
extern void ospf6_asbr_redistribute_reset (void);
extern void ospf6_asbr_terminate (void);
extern int config_write_ospf6_debug_asbr (struct vty *vty);

View File

@ -113,7 +113,7 @@ ospf6_lsa_originate (struct ospf6_lsa *lsa)
ospf6_lsdb_add (ospf6_lsa_copy (lsa), lsdb_self);
lsa->refresh = thread_add_timer (master, ospf6_lsa_refresh, lsa,
LS_REFRESH_TIME);
OSPF_LS_REFRESH_TIME);
if (IS_OSPF6_DEBUG_LSA_TYPE (lsa->header->type) ||
IS_OSPF6_DEBUG_ORIGINATE_TYPE (lsa->header->type))
@ -122,10 +122,8 @@ ospf6_lsa_originate (struct ospf6_lsa *lsa)
ospf6_lsa_header_print (lsa);
}
if (old)
ospf6_flood_clear (old);
ospf6_flood (NULL, lsa);
ospf6_install_lsa (lsa);
ospf6_flood (NULL, lsa);
}
void
@ -208,8 +206,8 @@ ospf6_decrement_retrans_count (struct ospf6_lsa *lsa)
void
ospf6_install_lsa (struct ospf6_lsa *lsa)
{
struct ospf6_lsa *old;
struct timeval now;
struct ospf6_lsa *old;
if (IS_OSPF6_DEBUG_LSA_TYPE (lsa->header->type) ||
IS_OSPF6_DEBUG_EXAMIN_TYPE (lsa->header->type))
@ -222,16 +220,36 @@ ospf6_install_lsa (struct ospf6_lsa *lsa)
if (old)
{
THREAD_OFF (old->expire);
THREAD_OFF (old->refresh);
ospf6_flood_clear (old);
}
quagga_gettime (QUAGGA_CLK_MONOTONIC, &now);
if (! OSPF6_LSA_IS_MAXAGE (lsa))
lsa->expire = thread_add_timer (master, ospf6_lsa_expire, lsa,
MAXAGE + lsa->birth.tv_sec - now.tv_sec);
OSPF_LSA_MAXAGE + lsa->birth.tv_sec - now.tv_sec);
else
lsa->expire = NULL;
if (OSPF6_LSA_IS_SEQWRAP(lsa) &&
! (CHECK_FLAG(lsa->flag,OSPF6_LSA_SEQWRAPPED) &&
lsa->header->seqnum == htonl(OSPF_MAX_SEQUENCE_NUMBER)))
{
if (IS_OSPF6_DEBUG_EXAMIN_TYPE (lsa->header->type))
zlog_debug("lsa install wrapping: sequence 0x%x",
ntohl(lsa->header->seqnum));
SET_FLAG(lsa->flag, OSPF6_LSA_SEQWRAPPED);
/* in lieu of premature_aging, since we do not want to recreate this lsa
* and/or mess with timers etc, we just want to wrap the sequence number
* and reflood the lsa before continuing.
* NOTE: Flood needs to be called right after this function call, by the
* caller
*/
lsa->header->seqnum = htonl (OSPF_MAX_SEQUENCE_NUMBER);
lsa->header->age = htons (OSPF_LSA_MAXAGE);
ospf6_lsa_checksum (lsa->header);
}
/* actually install */
lsa->installed = now;
ospf6_lsdb_add (lsa, lsa->lsdb);
@ -292,7 +310,7 @@ ospf6_flood_interface (struct ospf6_neighbor *from,
if (ospf6_lsa_compare (lsa, req) > 0)
{
if (is_debug)
zlog_debug ("Requesting is newer, next neighbor");
zlog_debug ("Requesting is older, next neighbor");
continue;
}
@ -300,18 +318,30 @@ ospf6_flood_interface (struct ospf6_neighbor *from,
examin next neighbor */
if (ospf6_lsa_compare (lsa, req) == 0)
{
if (is_debug)
zlog_debug ("Requesting the same, remove it, next neighbor");
if (is_debug)
zlog_debug ("Requesting the same, remove it, next neighbor");
if (req == on->last_ls_req)
{
ospf6_lsa_unlock (req);
on->last_ls_req = NULL;
}
ospf6_lsdb_remove (req, on->request_list);
ospf6_check_nbr_loading (on);
continue;
}
/* If the new LSA is more recent, delete from request-list */
if (ospf6_lsa_compare (lsa, req) < 0)
{
if (is_debug)
zlog_debug ("Received is newer, remove requesting");
if (is_debug)
zlog_debug ("Received is newer, remove requesting");
if (req == on->last_ls_req)
{
ospf6_lsa_unlock (req);
on->last_ls_req = NULL;
}
ospf6_lsdb_remove (req, on->request_list);
ospf6_check_nbr_loading (on);
/* fall through */
}
}
@ -358,17 +388,22 @@ ospf6_flood_interface (struct ospf6_neighbor *from,
/* (4) If the new LSA was received on this interface,
and the interface state is BDR, examin next interface */
if (from && from->ospf6_if == oi && oi->state == OSPF6_INTERFACE_BDR)
if (from && from->ospf6_if == oi)
{
if (is_debug)
zlog_debug ("Received is from the I/F, itself BDR, next interface");
return;
if (oi->state == OSPF6_INTERFACE_BDR)
{
if (is_debug)
zlog_debug ("Received is from the I/F, itself BDR, next interface");
return;
}
SET_FLAG(lsa->flag, OSPF6_LSA_FLOODBACK);
}
/* (5) flood the LSA out the interface. */
if (is_debug)
zlog_debug ("Schedule flooding for the interface");
if (if_is_broadcast (oi->interface))
if ((oi->type == OSPF_IFTYPE_BROADCAST) ||
(oi->type == OSPF_IFTYPE_POINTOPOINT))
{
ospf6_lsdb_add (ospf6_lsa_copy (lsa), oi->lsupdate_list);
if (oi->thread_send_lsupdate == NULL)
@ -530,15 +565,6 @@ ospf6_acknowledge_lsa_bdrouter (struct ospf6_lsa *lsa, int ismore_recent,
assert (from && from->ospf6_if);
oi = from->ospf6_if;
/* LSA has been flood back out receiving interface.
No acknowledgement sent. */
if (CHECK_FLAG (lsa->flag, OSPF6_LSA_FLOODBACK))
{
if (is_debug)
zlog_debug ("No acknowledgement (BDR & FloodBack)");
return;
}
/* LSA is more recent than database copy, but was not flooded
back out receiving interface. Delayed acknowledgement sent
if advertisement received from Designated Router,
@ -797,7 +823,7 @@ ospf6_receive_lsa (struct ospf6_neighbor *from,
{
/* log */
if (is_debug)
zlog_debug ("Drop MaxAge LSA with direct acknowledgement.");
zlog_debug ("Drop MaxAge LSA with direct acknowledgement.");
/* a) Acknowledge back to neighbor (Direct acknowledgement, 13.5) */
ospf6_lsdb_add (ospf6_lsa_copy (new), from->lsack_list);
@ -837,7 +863,7 @@ ospf6_receive_lsa (struct ospf6_neighbor *from,
struct timeval now, res;
quagga_gettime (QUAGGA_CLK_MONOTONIC, &now);
timersub (&now, &old->installed, &res);
if (res.tv_sec < MIN_LS_ARRIVAL)
if (res.tv_sec < OSPF_MIN_LS_ARRIVAL)
{
if (is_debug)
zlog_debug ("LSA can't be updated within MinLSArrival, discard");
@ -849,7 +875,11 @@ ospf6_receive_lsa (struct ospf6_neighbor *from,
quagga_gettime (QUAGGA_CLK_MONOTONIC, &new->received);
if (is_debug)
zlog_debug ("Flood, Install, Possibly acknowledge the received LSA");
zlog_debug ("Install, Flood, Possibly acknowledge the received LSA");
/* Remove older copies of this LSA from retx lists */
if (old)
ospf6_flood_clear (old);
/* (b) immediately flood and (c) remove from all retrans-list */
/* Prevent self-originated LSA to be flooded. this is to make
@ -858,10 +888,6 @@ ospf6_receive_lsa (struct ospf6_neighbor *from,
if (new->header->adv_router != from->ospf6_if->area->ospf6->router_id)
ospf6_flood (from, new);
/* (c) Remove the current database copy from all neighbors' Link
state retransmission lists. */
/* XXX, flood_clear ? */
/* (d), installing lsdb, which may cause routing
table calculation (replacing database copy) */
ospf6_install_lsa (new);
@ -944,15 +970,15 @@ ospf6_receive_lsa (struct ospf6_neighbor *from,
/* If database copy is in 'Seqnumber Wrapping',
simply discard the received LSA */
if (OSPF6_LSA_IS_MAXAGE (old) &&
old->header->seqnum == htonl (MAX_SEQUENCE_NUMBER))
old->header->seqnum == htonl (OSPF_MAX_SEQUENCE_NUMBER))
{
if (is_debug)
{
zlog_debug ("The LSA is in Seqnumber Wrapping");
zlog_debug ("MaxAge & MaxSeqNum, discard");
}
ospf6_lsa_delete (new);
return;
ospf6_lsa_delete (new);
return;
}
/* Otherwise, Send database copy of this LSA to this neighbor */
@ -969,8 +995,8 @@ ospf6_receive_lsa (struct ospf6_neighbor *from,
if (from->thread_send_lsupdate == NULL)
from->thread_send_lsupdate =
thread_add_event (master, ospf6_lsupdate_send_neighbor, from, 0);
ospf6_lsa_delete (new);
return;
ospf6_lsa_delete (new);
return;
}
return;
}

View File

@ -73,14 +73,20 @@ ospf6_interface_lookup_by_ifindex (int ifindex)
/* schedule routing table recalculation */
static void
ospf6_interface_lsdb_hook (struct ospf6_lsa *lsa)
ospf6_interface_lsdb_hook (struct ospf6_lsa *lsa, unsigned int reason)
{
struct ospf6_interface *oi;
if (lsa == NULL)
return;
oi = lsa->lsdb->data;
switch (ntohs (lsa->header->type))
{
case OSPF6_LSTYPE_LINK:
if (OSPF6_INTERFACE (lsa->lsdb->data)->state == OSPF6_INTERFACE_DR)
OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT (OSPF6_INTERFACE (lsa->lsdb->data));
ospf6_spf_schedule (OSPF6_INTERFACE (lsa->lsdb->data)->area);
if (oi->state == OSPF6_INTERFACE_DR)
OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT (oi);
ospf6_spf_schedule (oi->area->ospf6, reason);
break;
default:
@ -88,6 +94,29 @@ ospf6_interface_lsdb_hook (struct ospf6_lsa *lsa)
}
}
static void
ospf6_interface_lsdb_hook_add (struct ospf6_lsa *lsa)
{
ospf6_interface_lsdb_hook(lsa, ospf6_lsadd_to_spf_reason(lsa));
}
static void
ospf6_interface_lsdb_hook_remove (struct ospf6_lsa *lsa)
{
ospf6_interface_lsdb_hook(lsa, ospf6_lsremove_to_spf_reason(lsa));
}
static u_char
ospf6_default_iftype(struct interface *ifp)
{
if (if_is_pointopoint (ifp))
return OSPF_IFTYPE_POINTOPOINT;
else if (if_is_loopback (ifp))
return OSPF_IFTYPE_LOOPBACK;
else
return OSPF_IFTYPE_BROADCAST;
}
/* Create new ospf6 interface structure */
struct ospf6_interface *
ospf6_interface_create (struct interface *ifp)
@ -112,10 +141,11 @@ ospf6_interface_create (struct interface *ifp)
oi->transdelay = OSPF6_INTERFACE_TRANSDELAY;
oi->priority = OSPF6_INTERFACE_PRIORITY;
oi->hello_interval = OSPF6_INTERFACE_HELLO_INTERVAL;
oi->dead_interval = OSPF6_INTERFACE_DEAD_INTERVAL;
oi->rxmt_interval = OSPF6_INTERFACE_RXMT_INTERVAL;
oi->hello_interval = OSPF_HELLO_INTERVAL_DEFAULT;
oi->dead_interval = OSPF_ROUTER_DEAD_INTERVAL_DEFAULT;
oi->rxmt_interval = OSPF_RETRANSMIT_INTERVAL_DEFAULT;
oi->cost = OSPF6_INTERFACE_COST;
oi->type = ospf6_default_iftype (ifp);
oi->state = OSPF6_INTERFACE_DOWN;
oi->flag = 0;
oi->mtu_ignore = 0;
@ -134,8 +164,8 @@ ospf6_interface_create (struct interface *ifp)
oi->lsupdate_list = ospf6_lsdb_create (oi);
oi->lsack_list = ospf6_lsdb_create (oi);
oi->lsdb = ospf6_lsdb_create (oi);
oi->lsdb->hook_add = ospf6_interface_lsdb_hook;
oi->lsdb->hook_remove = ospf6_interface_lsdb_hook;
oi->lsdb->hook_add = ospf6_interface_lsdb_hook_add;
oi->lsdb->hook_remove = ospf6_interface_lsdb_hook_remove;
oi->lsdb_self = ospf6_lsdb_create (oi);
oi->route_connected = OSPF6_ROUTE_TABLE_CREATE (INTERFACE, CONNECTED_ROUTES);
@ -189,31 +219,28 @@ void
ospf6_interface_enable (struct ospf6_interface *oi)
{
UNSET_FLAG (oi->flag, OSPF6_INTERFACE_DISABLE);
oi->thread_send_hello =
thread_add_event (master, ospf6_hello_send, oi, 0);
ospf6_interface_state_update (oi->interface);
}
void
ospf6_interface_disable (struct ospf6_interface *oi)
{
struct listnode *node, *nnode;
struct ospf6_neighbor *on;
SET_FLAG (oi->flag, OSPF6_INTERFACE_DISABLE);
for (ALL_LIST_ELEMENTS (oi->neighbor_list, node, nnode, on))
ospf6_neighbor_delete (on);
list_delete_all_node (oi->neighbor_list);
thread_execute (master, interface_down, oi, 0);
ospf6_lsdb_remove_all (oi->lsdb);
ospf6_lsdb_remove_all (oi->lsdb_self);
ospf6_lsdb_remove_all (oi->lsupdate_list);
ospf6_lsdb_remove_all (oi->lsack_list);
THREAD_OFF (oi->thread_send_hello);
THREAD_OFF (oi->thread_send_lsupdate);
THREAD_OFF (oi->thread_send_lsack);
THREAD_OFF (oi->thread_network_lsa);
THREAD_OFF (oi->thread_link_lsa);
THREAD_OFF (oi->thread_intra_prefix_lsa);
}
static struct in6_addr *
@ -260,8 +287,7 @@ ospf6_interface_if_add (struct interface *ifp)
}
/* interface start */
if (oi->area)
thread_add_event (master, interface_up, oi, 0);
ospf6_interface_state_update(oi->interface);
}
void
@ -297,8 +323,12 @@ ospf6_interface_state_update (struct interface *ifp)
return;
if (oi->area == NULL)
return;
if (CHECK_FLAG (oi->flag, OSPF6_INTERFACE_DISABLE))
return;
if (if_is_up (ifp))
if (if_is_operative (ifp)
&& (ospf6_interface_get_linklocal_address(oi->interface)
|| if_is_loopback(oi->interface)))
thread_add_event (master, interface_up, oi, 0);
else
thread_add_event (master, interface_down, oi, 0);
@ -325,6 +355,9 @@ ospf6_interface_connected_route_update (struct interface *ifp)
if (oi->area == NULL)
return;
if (CHECK_FLAG (oi->flag, OSPF6_INTERFACE_DISABLE))
return;
/* update "route to advertise" interface route table */
ospf6_route_remove_all (oi->route_connected);
@ -401,6 +434,7 @@ ospf6_interface_state_change (u_char next_state, struct ospf6_interface *oi)
(next_state != OSPF6_INTERFACE_DR &&
next_state != OSPF6_INTERFACE_BDR))
ospf6_sso (oi->interface->ifindex, &alldrouters6, IPV6_LEAVE_GROUP);
if ((prev_state != OSPF6_INTERFACE_DR &&
prev_state != OSPF6_INTERFACE_BDR) &&
(next_state == OSPF6_INTERFACE_DR ||
@ -606,7 +640,7 @@ interface_up (struct thread *thread)
oi->interface->name);
/* check physical interface is up */
if (! if_is_up (oi->interface))
if (! if_is_operative (oi->interface))
{
if (IS_OSPF6_DEBUG_INTERFACE)
zlog_debug ("Interface %s is down, can't execute [InterfaceUp]",
@ -614,6 +648,16 @@ interface_up (struct thread *thread)
return 0;
}
/* check interface has a link-local address */
if (! (ospf6_interface_get_linklocal_address(oi->interface)
|| if_is_loopback(oi->interface)))
{
if (IS_OSPF6_DEBUG_INTERFACE)
zlog_debug ("Interface %s has no link local address, can't execute [InterfaceUp]",
oi->interface->name);
return 0;
}
/* if already enabled, do nothing */
if (oi->state > OSPF6_INTERFACE_DOWN)
{
@ -623,6 +667,14 @@ interface_up (struct thread *thread)
return 0;
}
/* If no area assigned, return */
if (oi->area == NULL)
{
zlog_debug ("%s: Not scheduleing Hello for %s as there is no area assigned yet", __func__,
oi->interface->name);
return 0;
}
/* Join AllSPFRouters */
ospf6_sso (oi->interface->ifindex, &allspfrouters6, IPV6_JOIN_GROUP);
@ -631,11 +683,13 @@ interface_up (struct thread *thread)
/* Schedule Hello */
if (! CHECK_FLAG (oi->flag, OSPF6_INTERFACE_PASSIVE))
thread_add_event (master, ospf6_hello_send, oi, 0);
oi->thread_send_hello = thread_add_event (master, ospf6_hello_send, oi, 0);
/* decide next interface state */
if (if_is_pointopoint (oi->interface))
if ((if_is_pointopoint (oi->interface)) ||
(oi->type == OSPF_IFTYPE_POINTOPOINT)) {
ospf6_interface_state_change (OSPF6_INTERFACE_POINTTOPOINT, oi);
}
else if (oi->priority == 0)
ospf6_interface_state_change (OSPF6_INTERFACE_DROTHER, oi);
else
@ -717,6 +771,9 @@ interface_down (struct thread *thread)
zlog_debug ("Interface Event %s: [InterfaceDown]",
oi->interface->name);
/* Stop Hellos */
THREAD_OFF (oi->thread_send_hello);
/* Leave AllSPFRouters */
if (oi->state > OSPF6_INTERFACE_DOWN)
ospf6_sso (oi->interface->ifindex, &allspfrouters6, IPV6_LEAVE_GROUP);
@ -728,6 +785,10 @@ interface_down (struct thread *thread)
list_delete_all_node (oi->neighbor_list);
/* When interface state is reset, also reset information about
* DR election, as it is no longer valid. */
oi->drouter = oi->prev_drouter = htonl(0);
oi->bdrouter = oi->prev_bdrouter = htonl(0);
return 0;
}
@ -758,7 +819,7 @@ ospf6_interface_show (struct vty *vty, struct interface *ifp)
type = "UNKNOWN";
vty_out (vty, "%s is %s, type %s%s",
ifp->name, updown[if_is_up (ifp)], type,
ifp->name, updown[if_is_operative (ifp)], type,
VNL);
vty_out (vty, " Interface ID: %d%s", ifp->ifindex, VNL);
@ -1292,7 +1353,10 @@ DEFUN (ipv6_ospf6_priority,
oi->priority = strtol (argv[0], NULL, 10);
if (oi->area)
if (oi->area &&
(oi->state == OSPF6_INTERFACE_DROTHER ||
oi->state == OSPF6_INTERFACE_BDR ||
oi->state == OSPF6_INTERFACE_DR))
ospf6_interface_state_change (dr_election (oi), oi);
return CMD_SUCCESS;
@ -1516,6 +1580,86 @@ DEFUN (no_ipv6_ospf6_advertise_prefix_list,
return CMD_SUCCESS;
}
DEFUN (ipv6_ospf6_network,
ipv6_ospf6_network_cmd,
"ipv6 ospf6 network (broadcast|point-to-point)",
IP6_STR
OSPF6_STR
"Network Type\n"
"Specify OSPFv6 broadcast network\n"
"Specify OSPF6 point-to-point network\n"
)
{
struct ospf6_interface *oi;
struct interface *ifp;
ifp = (struct interface *) vty->index;
assert (ifp);
oi = (struct ospf6_interface *) ifp->info;
if (oi == NULL) {
oi = ospf6_interface_create (ifp);
}
assert (oi);
if (strncmp (argv[0], "b", 1) == 0)
{
if (oi->type == OSPF_IFTYPE_BROADCAST)
return CMD_SUCCESS;
oi->type = OSPF_IFTYPE_BROADCAST;
}
else if (strncmp (argv[0], "point-to-p", 10) == 0)
{
if (oi->type == OSPF_IFTYPE_POINTOPOINT) {
return CMD_SUCCESS;
}
oi->type = OSPF_IFTYPE_POINTOPOINT;
}
/* Reset the interface */
thread_add_event (master, interface_down, oi, 0);
thread_add_event (master, interface_up, oi, 0);
return CMD_SUCCESS;
}
DEFUN (no_ipv6_ospf6_network,
no_ipv6_ospf6_network_cmd,
"no ipv6 ospf6 network",
NO_STR
IP6_STR
OSPF6_STR
"Network Type\n"
"Default to whatever interface type system specifies"
)
{
struct ospf6_interface *oi;
struct interface *ifp;
int type;
ifp = (struct interface *) vty->index;
assert (ifp);
oi = (struct ospf6_interface *) ifp->info;
if (oi == NULL) {
return CMD_SUCCESS;
}
type = ospf6_default_iftype (ifp);
if (oi->type == type)
{
return CMD_SUCCESS;
}
oi->type = type;
/* Reset the interface */
thread_add_event (master, interface_down, oi, 0);
thread_add_event (master, interface_up, oi, 0);
return CMD_SUCCESS;
}
static int
config_write_ospf6_interface (struct vty *vty)
{
@ -1575,6 +1719,11 @@ config_write_ospf6_interface (struct vty *vty)
if (oi->mtu_ignore)
vty_out (vty, " ipv6 ospf6 mtu-ignore%s", VNL);
if (oi->type == OSPF_IFTYPE_POINTOPOINT)
vty_out (vty, " ipv6 ospf6 network point-to-point%s", VNL);
else if (oi->type == OSPF_IFTYPE_BROADCAST)
vty_out (vty, " ipv6 ospf6 network broadcast%s", VNL);
vty_out (vty, "!%s", VNL);
}
return 0;
@ -1632,6 +1781,9 @@ ospf6_interface_init (void)
install_element (INTERFACE_NODE, &ipv6_ospf6_advertise_prefix_list_cmd);
install_element (INTERFACE_NODE, &no_ipv6_ospf6_advertise_prefix_list_cmd);
install_element (INTERFACE_NODE, &ipv6_ospf6_network_cmd);
install_element (INTERFACE_NODE, &no_ipv6_ospf6_network_cmd);
}
DEFUN (debug_ospf6_interface,

View File

@ -56,6 +56,9 @@ struct ospf6_interface
/* I/F transmission delay */
u_int32_t transdelay;
/* Network Type */
u_char type;
/* Router Priority */
u_char priority;

View File

@ -46,7 +46,7 @@
#include "ospf6_abr.h"
#include "ospf6_flood.h"
#include "ospf6d.h"
#include "ospf6_spf.h"
unsigned char conf_debug_ospf6_brouter = 0;
u_int32_t conf_debug_ospf6_brouter_specific_router_id;
@ -56,6 +56,42 @@ u_int32_t conf_debug_ospf6_brouter_specific_area_id;
/* RFC2740 3.4.3.1 Router-LSA */
/******************************/
static char *
ospf6_router_lsa_get_nbr_id (struct ospf6_lsa *lsa, char *buf, int buflen,
int pos)
{
struct ospf6_router_lsa *router_lsa;
struct ospf6_router_lsdesc *lsdesc;
char *start, *end;
char buf1[INET_ADDRSTRLEN], buf2[INET_ADDRSTRLEN];
if (lsa)
{
router_lsa = (struct ospf6_router_lsa *)
((char *) lsa->header + sizeof (struct ospf6_lsa_header));
start = (char *) router_lsa + sizeof (struct ospf6_router_lsa);
end = (char *) lsa->header + ntohs (lsa->header->length);
lsdesc = (struct ospf6_router_lsdesc *)
(start + pos*(sizeof (struct ospf6_router_lsdesc)));
if ((char *)lsdesc < end)
{
if (buf && (buflen > INET_ADDRSTRLEN*2))
{
inet_ntop (AF_INET, &lsdesc->neighbor_interface_id,
buf1, sizeof(buf1));
inet_ntop (AF_INET, &lsdesc->neighbor_router_id,
buf2, sizeof(buf2));
sprintf (buf, "%s/%s", buf2, buf1);
}
}
else
return NULL;
}
return buf;
}
static int
ospf6_router_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
{
@ -104,6 +140,29 @@ ospf6_router_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
return 0;
}
int
ospf6_router_is_stub_router (struct ospf6_lsa *lsa)
{
struct ospf6_router_lsa *rtr_lsa;
if (lsa != NULL && OSPF6_LSA_IS_TYPE (ROUTER, lsa))
{
rtr_lsa = (struct ospf6_router_lsa *)
((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header));
if (!OSPF6_OPT_ISSET (rtr_lsa->options, OSPF6_OPT_R))
{
return (OSPF6_IS_STUB_ROUTER);
}
else if (!OSPF6_OPT_ISSET (rtr_lsa->options, OSPF6_OPT_V6))
{
return (OSPF6_IS_STUB_ROUTER_V6);
}
}
return (OSPF6_NOT_STUB_ROUTER);
}
int
ospf6_router_lsa_originate (struct thread *thread)
{
@ -215,7 +274,7 @@ ospf6_router_lsa_originate (struct thread *thread)
}
/* Point-to-Point interfaces */
if (if_is_pointopoint (oi->interface))
if (oi->type == OSPF_IFTYPE_POINTOPOINT)
{
for (ALL_LIST_ELEMENTS_RO (oi->neighbor_list, j, on))
{
@ -233,7 +292,7 @@ ospf6_router_lsa_originate (struct thread *thread)
}
/* Broadcast and NBMA interfaces */
if (if_is_broadcast (oi->interface))
else if (oi->type == OSPF_IFTYPE_BROADCAST)
{
/* If this router is not DR,
and If this router not fully adjacent with DR,
@ -261,6 +320,10 @@ ospf6_router_lsa_originate (struct thread *thread)
lsdesc++;
}
else
{
assert (0); /* Unknown interface type */
}
/* Virtual links */
/* xxx */
@ -268,35 +331,26 @@ ospf6_router_lsa_originate (struct thread *thread)
/* xxx */
}
if ((caddr_t) lsdesc != (caddr_t) router_lsa +
sizeof (struct ospf6_router_lsa))
{
/* Fill LSA Header */
lsa_header->age = 0;
lsa_header->type = htons (OSPF6_LSTYPE_ROUTER);
lsa_header->id = htonl (link_state_id);
lsa_header->adv_router = oa->ospf6->router_id;
lsa_header->seqnum =
ospf6_new_ls_seqnum (lsa_header->type, lsa_header->id,
lsa_header->adv_router, oa->lsdb);
lsa_header->length = htons ((caddr_t) lsdesc - (caddr_t) buffer);
/* Fill LSA Header */
lsa_header->age = 0;
lsa_header->type = htons (OSPF6_LSTYPE_ROUTER);
lsa_header->id = htonl (link_state_id);
lsa_header->adv_router = oa->ospf6->router_id;
lsa_header->seqnum =
ospf6_new_ls_seqnum (lsa_header->type, lsa_header->id,
lsa_header->adv_router, oa->lsdb);
lsa_header->length = htons ((caddr_t) lsdesc - (caddr_t) buffer);
/* LSA checksum */
ospf6_lsa_checksum (lsa_header);
/* LSA checksum */
ospf6_lsa_checksum (lsa_header);
/* create LSA */
lsa = ospf6_lsa_create (lsa_header);
/* create LSA */
lsa = ospf6_lsa_create (lsa_header);
/* Originate */
ospf6_lsa_originate_area (lsa, oa);
/* Originate */
ospf6_lsa_originate_area (lsa, oa);
link_state_id ++;
}
else
{
if (IS_OSPF6_DEBUG_ORIGINATE (ROUTER))
zlog_debug ("Nothing to describe in Router-LSA, suppress");
}
link_state_id ++;
/* Do premature-aging of rest, undesired Router-LSAs */
type = ntohs (OSPF6_LSTYPE_ROUTER);
@ -316,6 +370,36 @@ ospf6_router_lsa_originate (struct thread *thread)
/* RFC2740 3.4.3.2 Network-LSA */
/*******************************/
static char *
ospf6_network_lsa_get_ar_id (struct ospf6_lsa *lsa, char *buf, int buflen,
int pos)
{
char *start, *end, *current;
struct ospf6_network_lsa *network_lsa;
struct ospf6_network_lsdesc *lsdesc;
if (lsa)
{
network_lsa = (struct ospf6_network_lsa *)
((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header));
start = (char *) network_lsa + sizeof (struct ospf6_network_lsa);
end = (char *) lsa->header + ntohs (lsa->header->length);
current = start + pos*(sizeof (struct ospf6_network_lsdesc));
if ((current + sizeof(struct ospf6_network_lsdesc)) <= end)
{
lsdesc = (struct ospf6_network_lsdesc *)current;
if (buf)
inet_ntop (AF_INET, &lsdesc->router_id, buf, buflen);
}
else
return NULL;
}
return (buf);
}
static int
ospf6_network_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
{
@ -462,6 +546,61 @@ ospf6_network_lsa_originate (struct thread *thread)
/* RFC2740 3.4.3.6 Link-LSA */
/****************************/
static char *
ospf6_link_lsa_get_prefix_str (struct ospf6_lsa *lsa, char *buf, int buflen,
int pos)
{
char *start, *end, *current;
struct ospf6_link_lsa *link_lsa;
struct in6_addr in6;
struct ospf6_prefix *prefix;
int cnt = 0, prefixnum;
if (lsa)
{
link_lsa = (struct ospf6_link_lsa *)
((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header));
if (pos == 0) {
inet_ntop (AF_INET6, &link_lsa->linklocal_addr, buf, buflen);
return (buf);
}
prefixnum = ntohl (link_lsa->prefix_num);
if (pos > prefixnum)
return (NULL);
start = (char *) link_lsa + sizeof (struct ospf6_link_lsa);
end = (char *) lsa->header + ntohs (lsa->header->length);
current = start;
do
{
prefix = (struct ospf6_prefix *) current;
if (prefix->prefix_length == 0 ||
current + OSPF6_PREFIX_SIZE (prefix) > end)
{
return (NULL);
}
if (cnt < pos)
{
current = start + pos*OSPF6_PREFIX_SIZE(prefix);
cnt++;
}
else
{
memset (&in6, 0, sizeof (in6));
memcpy (&in6, OSPF6_PREFIX_BODY (prefix),
OSPF6_PREFIX_SPACE (prefix->prefix_length));
inet_ntop (AF_INET6, &in6, buf, buflen);
return (buf);
}
} while (current <= end);
}
return (NULL);
}
static int
ospf6_link_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
{
@ -614,6 +753,56 @@ ospf6_link_lsa_originate (struct thread *thread)
/*****************************************/
/* RFC2740 3.4.3.7 Intra-Area-Prefix-LSA */
/*****************************************/
static char *
ospf6_intra_prefix_lsa_get_prefix_str (struct ospf6_lsa *lsa, char *buf,
int buflen, int pos)
{
char *start, *end, *current;
struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
struct in6_addr in6;
int prefixnum, cnt = 0;
struct ospf6_prefix *prefix;
if (lsa)
{
intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *)
((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header));
prefixnum = ntohs (intra_prefix_lsa->prefix_num);
if (pos > prefixnum)
return (NULL);
start = (char *) intra_prefix_lsa + sizeof (struct ospf6_intra_prefix_lsa);
end = (char *) lsa->header + ntohs (lsa->header->length);
current = start;
do
{
prefix = (struct ospf6_prefix *) current;
if (prefix->prefix_length == 0 ||
current + OSPF6_PREFIX_SIZE (prefix) > end)
{
return NULL;
}
if (cnt < pos)
{
current = start + pos*OSPF6_PREFIX_SIZE(prefix);
cnt++;
}
else
{
memset (&in6, 0, sizeof (in6));
memcpy (&in6, OSPF6_PREFIX_BODY (prefix),
OSPF6_PREFIX_SPACE (prefix->prefix_length));
inet_ntop (AF_INET6, &in6, buf, buflen);
sprintf(&buf[strlen(buf)], "/%d", prefix->prefix_length);
return (buf);
}
} while (current <= end);
}
return (buf);
}
static int
ospf6_intra_prefix_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
@ -1029,6 +1218,8 @@ ospf6_intra_prefix_lsa_add (struct ospf6_lsa *lsa)
struct ospf6_prefix *op;
char *start, *current, *end;
char buf[64];
struct interface *ifp;
int direct_connect = 0;
if (OSPF6_LSA_IS_MAXAGE (lsa))
return;
@ -1065,6 +1256,12 @@ ospf6_intra_prefix_lsa_add (struct ospf6_lsa *lsa)
return;
}
if (intra_prefix_lsa->ref_adv_router == oa->ospf6->router_id)
{
/* the intra-prefix are directly connected */
direct_connect = 1;
}
prefix_num = ntohs (intra_prefix_lsa->prefix_num);
start = (caddr_t) intra_prefix_lsa +
sizeof (struct ospf6_intra_prefix_lsa);
@ -1077,6 +1274,20 @@ ospf6_intra_prefix_lsa_add (struct ospf6_lsa *lsa)
if (end < current + OSPF6_PREFIX_SIZE (op))
break;
/* Appendix A.4.1.1 */
if (CHECK_FLAG(op->prefix_options, OSPF6_PREFIX_OPTION_NU) ||
CHECK_FLAG(op->prefix_options, OSPF6_PREFIX_OPTION_LA))
{
if (IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
{
ospf6_linkstate_prefix2str ((struct prefix *)OSPF6_PREFIX_BODY(op),
buf, sizeof (buf));
zlog_debug ("%s: Skipping Prefix %s has NU/LA option set",
__func__, buf);
}
continue;
}
route = ospf6_route_create ();
memset (&route->prefix, 0, sizeof (struct prefix));
@ -1095,9 +1306,18 @@ ospf6_intra_prefix_lsa_add (struct ospf6_lsa *lsa)
route->path.cost = ls_entry->path.cost +
ntohs (op->prefix_metric);
for (i = 0; ospf6_nexthop_is_set (&ls_entry->nexthop[i]) &&
i < OSPF6_MULTI_PATH_LIMIT; i++)
ospf6_nexthop_copy (&route->nexthop[i], &ls_entry->nexthop[i]);
if (direct_connect)
{
ifp = if_lookup_prefix(&route->prefix);
if (ifp)
route->nexthop[0].ifindex = ifp->ifindex;
}
else
{
for (i = 0; ospf6_nexthop_is_set (&ls_entry->nexthop[i]) &&
i < OSPF6_MULTI_PATH_LIMIT; i++)
ospf6_nexthop_copy (&route->nexthop[i], &ls_entry->nexthop[i]);
}
if (IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
{
@ -1342,6 +1562,10 @@ ospf6_intra_brouter_calculation (struct ospf6_area *oa)
! CHECK_FLAG (brouter->path.router_bits, OSPF6_ROUTER_BIT_B))
continue;
if (! OSPF6_OPT_ISSET (brouter->path.options, OSPF6_OPT_V6) ||
! OSPF6_OPT_ISSET (brouter->path.options, OSPF6_OPT_R))
continue;
copy = ospf6_route_copy (brouter);
copy->type = OSPF6_DEST_TYPE_ROUTER;
copy->path.area_id = oa->area_id;
@ -1419,28 +1643,36 @@ struct ospf6_lsa_handler router_handler =
{
OSPF6_LSTYPE_ROUTER,
"Router",
ospf6_router_lsa_show
"Rtr",
ospf6_router_lsa_show,
ospf6_router_lsa_get_nbr_id
};
struct ospf6_lsa_handler network_handler =
{
OSPF6_LSTYPE_NETWORK,
"Network",
ospf6_network_lsa_show
"Net",
ospf6_network_lsa_show,
ospf6_network_lsa_get_ar_id
};
struct ospf6_lsa_handler link_handler =
{
OSPF6_LSTYPE_LINK,
"Link",
ospf6_link_lsa_show
"Lnk",
ospf6_link_lsa_show,
ospf6_link_lsa_get_prefix_str
};
struct ospf6_lsa_handler intra_prefix_handler =
{
OSPF6_LSTYPE_INTRA_PREFIX,
"Intra-Prefix",
ospf6_intra_prefix_lsa_show
"INP",
ospf6_intra_prefix_lsa_show,
ospf6_intra_prefix_lsa_get_prefix_str
};
void

View File

@ -94,6 +94,13 @@ struct ospf6_router_lsdesc
#define OSPF6_ROUTER_LSDESC_STUB_NETWORK 3
#define OSPF6_ROUTER_LSDESC_VIRTUAL_LINK 4
enum stub_router_mode
{
OSPF6_NOT_STUB_ROUTER,
OSPF6_IS_STUB_ROUTER,
OSPF6_IS_STUB_ROUTER_V6,
};
#define ROUTER_LSDESC_IS_TYPE(t,x) \
((((struct ospf6_router_lsdesc *)(x))->type == \
OSPF6_ROUTER_LSDESC_ ## t) ? 1 : 0)
@ -149,32 +156,37 @@ struct ospf6_intra_prefix_lsa
#define OSPF6_ROUTER_LSA_SCHEDULE(oa) \
do { \
if (! (oa)->thread_router_lsa) \
if (! (oa)->thread_router_lsa \
&& CHECK_FLAG((oa)->flag, OSPF6_AREA_ENABLE)) \
(oa)->thread_router_lsa = \
thread_add_event (master, ospf6_router_lsa_originate, oa, 0); \
} while (0)
#define OSPF6_NETWORK_LSA_SCHEDULE(oi) \
do { \
if (! (oi)->thread_network_lsa) \
if (! (oi)->thread_network_lsa \
&& ! CHECK_FLAG((oi)->flag, OSPF6_INTERFACE_DISABLE)) \
(oi)->thread_network_lsa = \
thread_add_event (master, ospf6_network_lsa_originate, oi, 0); \
} while (0)
#define OSPF6_LINK_LSA_SCHEDULE(oi) \
do { \
if (! (oi)->thread_link_lsa) \
if (! (oi)->thread_link_lsa \
&& ! CHECK_FLAG((oi)->flag, OSPF6_INTERFACE_DISABLE)) \
(oi)->thread_link_lsa = \
thread_add_event (master, ospf6_link_lsa_originate, oi, 0); \
} while (0)
#define OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB(oa) \
do { \
if (! (oa)->thread_intra_prefix_lsa) \
if (! (oa)->thread_intra_prefix_lsa \
&& CHECK_FLAG((oa)->flag, OSPF6_AREA_ENABLE)) \
(oa)->thread_intra_prefix_lsa = \
thread_add_event (master, ospf6_intra_prefix_lsa_originate_stub, \
oa, 0); \
} while (0)
#define OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT(oi) \
do { \
if (! (oi)->thread_intra_prefix_lsa) \
if (! (oi)->thread_intra_prefix_lsa \
&& ! CHECK_FLAG((oi)->flag, OSPF6_INTERFACE_DISABLE)) \
(oi)->thread_intra_prefix_lsa = \
thread_add_event (master, ospf6_intra_prefix_lsa_originate_transit, \
oi, 0); \
@ -200,6 +212,7 @@ extern char *ospf6_router_lsdesc_lookup (u_char type, u_int32_t interface_id,
extern char *ospf6_network_lsdesc_lookup (u_int32_t router_id,
struct ospf6_lsa *lsa);
extern int ospf6_router_is_stub_router (struct ospf6_lsa *lsa);
extern int ospf6_router_lsa_originate (struct thread *);
extern int ospf6_network_lsa_originate (struct thread *);
extern int ospf6_link_lsa_originate (struct thread *);

View File

@ -75,7 +75,9 @@ struct ospf6_lsa_handler unknown_handler =
{
OSPF6_LSTYPE_UNKNOWN,
"Unknown",
"Unk",
ospf6_unknown_lsa_show,
NULL,
OSPF6_LSA_DEBUG,
};
@ -118,6 +120,20 @@ ospf6_lstype_name (u_int16_t type)
return buf;
}
const char *
ospf6_lstype_short_name (u_int16_t type)
{
static char buf[8];
struct ospf6_lsa_handler *handler;
handler = ospf6_get_lsa_handler (type);
if (handler && handler != &unknown_handler)
return handler->short_name;
snprintf (buf, sizeof (buf), "0x%04hx", ntohs (type));
return buf;
}
u_char
ospf6_lstype_debug (u_int16_t type)
{
@ -139,11 +155,11 @@ ospf6_lsa_is_differ (struct ospf6_lsa *lsa1,
ospf6_lsa_age_current (lsa1);
ospf6_lsa_age_current (lsa2);
if (ntohs (lsa1->header->age) == MAXAGE &&
ntohs (lsa2->header->age) != MAXAGE)
if (ntohs (lsa1->header->age) == OSPF_LSA_MAXAGE &&
ntohs (lsa2->header->age) != OSPF_LSA_MAXAGE)
return 1;
if (ntohs (lsa1->header->age) != MAXAGE &&
ntohs (lsa2->header->age) == MAXAGE)
if (ntohs (lsa1->header->age) != OSPF_LSA_MAXAGE &&
ntohs (lsa2->header->age) == OSPF_LSA_MAXAGE)
return 1;
/* compare body */
@ -218,19 +234,19 @@ ospf6_lsa_age_current (struct ospf6_lsa *lsa)
zlog_warn ("LSA: quagga_gettime failed, may fail LSA AGEs: %s",
safe_strerror (errno));
if (ntohs (lsa->header->age) >= MAXAGE)
if (ntohs (lsa->header->age) >= OSPF_LSA_MAXAGE)
{
/* ospf6_lsa_premature_aging () sets age to MAXAGE; when using
relative time, we cannot compare against lsa birth time, so
we catch this special case here. */
lsa->header->age = htons (MAXAGE);
return MAXAGE;
lsa->header->age = htons (OSPF_LSA_MAXAGE);
return OSPF_LSA_MAXAGE;
}
/* calculate age */
ulage = now.tv_sec - lsa->birth.tv_sec;
/* if over MAXAGE, set to it */
age = (ulage > MAXAGE ? MAXAGE : ulage);
age = (ulage > OSPF_LSA_MAXAGE ? OSPF_LSA_MAXAGE : ulage);
lsa->header->age = htons (age);
return age;
@ -243,8 +259,8 @@ ospf6_lsa_age_update_to_send (struct ospf6_lsa *lsa, u_int32_t transdelay)
unsigned short age;
age = ospf6_lsa_age_current (lsa) + transdelay;
if (age > MAXAGE)
age = MAXAGE;
if (age > OSPF_LSA_MAXAGE)
age = OSPF_LSA_MAXAGE;
lsa->header->age = htons (age);
}
@ -258,7 +274,30 @@ ospf6_lsa_premature_aging (struct ospf6_lsa *lsa)
THREAD_OFF (lsa->expire);
THREAD_OFF (lsa->refresh);
lsa->header->age = htons (MAXAGE);
/*
* We clear the LSA from the neighbor retx lists now because it
* will not get deleted later. Essentially, changing the age to
* MaxAge will prevent this LSA from being matched with its
* existing entries in the retx list thereby causing those entries
* to be silently replaced with its MaxAged version, but with ever
* increasing retx count causing this LSA to remain forever and
* for the MaxAge remover thread to be called forever too.
*
* The reason the previous entry silently disappears is that when
* entry is added to a neighbor's retx list, it replaces the existing
* entry. But since the ospf6_lsdb_add() routine is generic and not aware
* of the special semantics of retx count, the retx count is not
* decremented when its replaced. Attempting to add the incr and decr
* retx count routines as the hook_add and hook_remove for the retx lists
* have a problem because the hook_remove routine is called for MaxAge
* entries (as will be the case in a traditional LSDB, unlike in this case
* where an LSDB is used as an efficient tree structure to store all kinds
* of data) that are added instead of calling the hook_add routine.
*/
ospf6_flood_clear (lsa);
lsa->header->age = htons (OSPF_LSA_MAXAGE);
thread_execute (master, ospf6_lsa_expire, lsa, 0);
}
@ -297,15 +336,15 @@ ospf6_lsa_compare (struct ospf6_lsa *a, struct ospf6_lsa *b)
ageb = ospf6_lsa_age_current (b);
/* MaxAge check */
if (agea == MAXAGE && ageb != MAXAGE)
if (agea == OSPF_LSA_MAXAGE && ageb != OSPF_LSA_MAXAGE)
return -1;
else if (agea != MAXAGE && ageb == MAXAGE)
else if (agea != OSPF_LSA_MAXAGE && ageb == OSPF_LSA_MAXAGE)
return 1;
/* Age check */
if (agea > ageb && agea - ageb >= MAX_AGE_DIFF)
if (agea > ageb && agea - ageb >= OSPF_LSA_MAXAGE_DIFF)
return 1;
else if (agea < ageb && ageb - agea >= MAX_AGE_DIFF)
else if (agea < ageb && ageb - agea >= OSPF_LSA_MAXAGE_DIFF)
return -1;
/* neither recent */
@ -348,17 +387,19 @@ ospf6_lsa_header_print (struct ospf6_lsa *lsa)
void
ospf6_lsa_show_summary_header (struct vty *vty)
{
vty_out (vty, "%-12s %-15s %-15s %4s %8s %4s %4s %-8s%s",
vty_out (vty, "%-4s %-15s%-15s%4s %8s %30s%s",
"Type", "LSId", "AdvRouter", "Age", "SeqNum",
"Cksm", "Len", "Duration", VNL);
"Payload", VNL);
}
void
ospf6_lsa_show_summary (struct vty *vty, struct ospf6_lsa *lsa)
{
char adv_router[16], id[16];
struct timeval now, res;
char duration[16];
int type;
struct ospf6_lsa_handler *handler;
char buf[64], tmpbuf[80];
int cnt = 0;
assert (lsa);
assert (lsa->header);
@ -367,16 +408,38 @@ ospf6_lsa_show_summary (struct vty *vty, struct ospf6_lsa *lsa)
inet_ntop (AF_INET, &lsa->header->adv_router, adv_router,
sizeof (adv_router));
quagga_gettime (QUAGGA_CLK_MONOTONIC, &now);
timersub (&now, &lsa->installed, &res);
timerstring (&res, duration, sizeof (duration));
type = ntohs(lsa->header->type);
handler = ospf6_get_lsa_handler (lsa->header->type);
if ((type == OSPF6_LSTYPE_INTER_PREFIX) ||
(type == OSPF6_LSTYPE_INTER_ROUTER) ||
(type == OSPF6_LSTYPE_AS_EXTERNAL))
{
vty_out (vty, "%-4s %-15s%-15s%4hu %8lx %30s%s",
ospf6_lstype_short_name (lsa->header->type),
id, adv_router, ospf6_lsa_age_current (lsa),
(u_long) ntohl (lsa->header->seqnum),
handler->get_prefix_str(lsa, buf, sizeof(buf), 0), VNL);
}
else if (type != OSPF6_LSTYPE_UNKNOWN)
{
sprintf (tmpbuf, "%-4s %-15s%-15s%4hu %8lx",
ospf6_lstype_short_name (lsa->header->type),
id, adv_router, ospf6_lsa_age_current (lsa),
(u_long) ntohl (lsa->header->seqnum));
vty_out (vty, "%-12s %-15s %-15s %4hu %8lx %04hx %4hu %8s%s",
ospf6_lstype_name (lsa->header->type),
id, adv_router, ospf6_lsa_age_current (lsa),
(u_long) ntohl (lsa->header->seqnum),
ntohs (lsa->header->checksum), ntohs (lsa->header->length),
duration, VNL);
while (handler->get_prefix_str(lsa, buf, sizeof(buf), cnt) != NULL)
{
vty_out (vty, "%s %30s%s", tmpbuf, buf, VNL);
cnt++;
}
}
else
{
vty_out (vty, "%-4s %-15s%-15s%4hu %8lx%s",
ospf6_lstype_short_name (lsa->header->type),
id, adv_router, ospf6_lsa_age_current (lsa),
(u_long) ntohl (lsa->header->seqnum), VNL);
}
}
void
@ -427,8 +490,11 @@ ospf6_lsa_show_internal (struct vty *vty, struct ospf6_lsa *lsa)
vty_out (vty, "CheckSum: %#06hx Length: %hu%s",
ntohs (lsa->header->checksum),
ntohs (lsa->header->length), VNL);
vty_out (vty, " Prev: %p This: %p Next: %p%s",
lsa->prev, lsa, lsa->next, VNL);
vty_out (vty, "Flag: %x %s", lsa->flag, VNL);
vty_out (vty, "Lock: %d %s", lsa->lock, VNL);
vty_out (vty, "ReTx Count: %d%s", lsa->retrans_count, VNL);
vty_out (vty, "Threads: Expire: %x, Refresh: %x %s",
lsa->expire, lsa->refresh, VNL);
vty_out (vty, "%s", VNL);
return;
}
@ -438,6 +504,8 @@ ospf6_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
{
char adv_router[64], id[64];
struct ospf6_lsa_handler *handler;
struct timeval now, res;
char duration[16];
assert (lsa && lsa->header);
@ -445,6 +513,10 @@ ospf6_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
inet_ntop (AF_INET, &lsa->header->adv_router,
adv_router, sizeof (adv_router));
quagga_gettime (QUAGGA_CLK_MONOTONIC, &now);
timersub (&now, &lsa->installed, &res);
timerstring (&res, duration, sizeof (duration));
vty_out (vty, "Age: %4hu Type: %s%s", ospf6_lsa_age_current (lsa),
ospf6_lstype_name (lsa->header->type), VNL);
vty_out (vty, "Link State ID: %s%s", id, VNL);
@ -454,6 +526,7 @@ ospf6_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
vty_out (vty, "CheckSum: %#06hx Length: %hu%s",
ntohs (lsa->header->checksum),
ntohs (lsa->header->length), VNL);
vty_out (vty, "Duration: %s%s", duration, VNL);
handler = ospf6_get_lsa_handler (lsa->header->type);
if (handler->show == NULL)
@ -558,6 +631,7 @@ ospf6_lsa_copy (struct ospf6_lsa *lsa)
copy->received = lsa->received;
copy->installed = lsa->installed;
copy->lsdb = lsa->lsdb;
copy->rn = NULL;
return copy;
}
@ -608,12 +682,12 @@ ospf6_lsa_expire (struct thread *thread)
if (CHECK_FLAG (lsa->flag, OSPF6_LSA_HEADERONLY))
return 0; /* dbexchange will do something ... */
/* reflood lsa */
ospf6_flood (NULL, lsa);
/* reinstall lsa */
ospf6_install_lsa (lsa);
/* reflood lsa */
ospf6_flood (NULL, lsa);
/* schedule maxage remover */
ospf6_maxage_remove (ospf6);
@ -653,7 +727,7 @@ ospf6_lsa_refresh (struct thread *thread)
new = ospf6_lsa_create (self->header);
new->lsdb = old->lsdb;
new->refresh = thread_add_timer (master, ospf6_lsa_refresh, new,
LS_REFRESH_TIME);
OSPF_LS_REFRESH_TIME);
/* store it in the LSDB for self-originated LSAs */
ospf6_lsdb_add (ospf6_lsa_copy (new), lsdb_self);
@ -664,9 +738,8 @@ ospf6_lsa_refresh (struct thread *thread)
ospf6_lsa_header_print (new);
}
ospf6_flood_clear (old);
ospf6_flood (NULL, new);
ospf6_install_lsa (new);
ospf6_flood (NULL, new);
return 0;
}
@ -725,7 +798,7 @@ ospf6_lsa_handler_name (struct ospf6_lsa_handler *h)
unsigned int i;
unsigned int size = strlen (h->name);
if (!strcmp(h->name, "Unknown") &&
if (!strcmp(h->name, "unknown") &&
h->type != OSPF6_LSTYPE_UNKNOWN)
{
snprintf (buf, sizeof (buf), "%#04hx", h->type);
@ -745,7 +818,7 @@ ospf6_lsa_handler_name (struct ospf6_lsa_handler *h)
DEFUN (debug_ospf6_lsa_type,
debug_ospf6_lsa_hex_cmd,
"debug ospf6 lsa XXXX/0xXXXX",
"debug ospf6 lsa (router|network|inter-prefix|inter-router|as-ext|grp-mbr|type7|link|intra-prefix|unknown)",
DEBUG_STR
OSPF6_STR
"Debug Link State Advertisements (LSAs)\n"
@ -754,44 +827,21 @@ DEFUN (debug_ospf6_lsa_type,
{
unsigned int i;
struct ospf6_lsa_handler *handler = NULL;
unsigned long val;
char *endptr = NULL;
u_int16_t type = 0;
assert (argc);
if ((strlen (argv[0]) == 6 && ! strncmp (argv[0], "0x", 2)) ||
(strlen (argv[0]) == 4))
{
val = strtoul (argv[0], &endptr, 16);
if (*endptr == '\0')
type = val;
}
for (i = 0; i < vector_active (ospf6_lsa_handler_vector); i++)
{
handler = vector_slot (ospf6_lsa_handler_vector, i);
if (handler == NULL)
continue;
if (type && handler->type == type)
if (strncmp (argv[0], ospf6_lsa_handler_name(handler), strlen(argv[0])) == 0)
break;
if (! strcasecmp (argv[0], handler->name))
break;
handler = NULL;
}
if (type && handler == NULL)
{
handler = (struct ospf6_lsa_handler *)
malloc (sizeof (struct ospf6_lsa_handler));
memset (handler, 0, sizeof (struct ospf6_lsa_handler));
handler->type = type;
handler->name = "Unknown";
handler->show = ospf6_unknown_lsa_show;
vector_set_index (ospf6_lsa_handler_vector,
handler->type & OSPF6_LSTYPE_FCODE_MASK, handler);
}
if (handler == NULL)
handler = &unknown_handler;
@ -799,7 +849,7 @@ DEFUN (debug_ospf6_lsa_type,
{
if (! strcmp (argv[1], "originate"))
SET_FLAG (handler->debug, OSPF6_LSA_DEBUG_ORIGINATE);
if (! strcmp (argv[1], "examin"))
if (! strcmp (argv[1], "examine"))
SET_FLAG (handler->debug, OSPF6_LSA_DEBUG_EXAMIN);
if (! strcmp (argv[1], "flooding"))
SET_FLAG (handler->debug, OSPF6_LSA_DEBUG_FLOOD);
@ -810,9 +860,18 @@ DEFUN (debug_ospf6_lsa_type,
return CMD_SUCCESS;
}
ALIAS (debug_ospf6_lsa_type,
debug_ospf6_lsa_hex_detail_cmd,
"debug ospf6 lsa (router|network|inter-prefix|inter-router|as-ext|grp-mbr|type7|link|intra-prefix|unknown) (originate|examine|flooding)",
DEBUG_STR
OSPF6_STR
"Debug Link State Advertisements (LSAs)\n"
"Specify LS type as Hexadecimal\n"
)
DEFUN (no_debug_ospf6_lsa_type,
no_debug_ospf6_lsa_hex_cmd,
"no debug ospf6 lsa XXXX/0xXXXX",
"no debug ospf6 lsa (router|network|inter-prefix|inter-router|as-ext|grp-mbr|type7|link|intra-prefix|unknown)",
NO_STR
DEBUG_STR
OSPF6_STR
@ -822,26 +881,15 @@ DEFUN (no_debug_ospf6_lsa_type,
{
u_int i;
struct ospf6_lsa_handler *handler = NULL;
unsigned long val;
char *endptr = NULL;
u_int16_t type = 0;
assert (argc);
if ((strlen (argv[0]) == 6 && ! strncmp (argv[0], "0x", 2)) ||
(strlen (argv[0]) == 4))
{
val = strtoul (argv[0], &endptr, 16);
if (*endptr == '\0')
type = val;
}
for (i = 0; i < vector_active (ospf6_lsa_handler_vector); i++)
{
handler = vector_slot (ospf6_lsa_handler_vector, i);
if (handler == NULL)
continue;
if (type && handler->type == type)
if (strncmp (argv[0], ospf6_lsa_handler_name(handler), strlen(argv[0])) == 0)
break;
if (! strcasecmp (argv[0], handler->name))
break;
@ -854,7 +902,7 @@ DEFUN (no_debug_ospf6_lsa_type,
{
if (! strcmp (argv[1], "originate"))
UNSET_FLAG (handler->debug, OSPF6_LSA_DEBUG_ORIGINATE);
if (! strcmp (argv[1], "examin"))
if (! strcmp (argv[1], "examine"))
UNSET_FLAG (handler->debug, OSPF6_LSA_DEBUG_EXAMIN);
if (! strcmp (argv[1], "flooding"))
UNSET_FLAG (handler->debug, OSPF6_LSA_DEBUG_FLOOD);
@ -862,120 +910,30 @@ DEFUN (no_debug_ospf6_lsa_type,
else
UNSET_FLAG (handler->debug, OSPF6_LSA_DEBUG);
if (handler->debug == 0 &&
!strcmp(handler->name, "Unknown") && type != OSPF6_LSTYPE_UNKNOWN)
{
free (handler);
vector_slot (ospf6_lsa_handler_vector, i) = NULL;
}
return CMD_SUCCESS;
}
struct cmd_element debug_ospf6_lsa_type_cmd;
struct cmd_element debug_ospf6_lsa_type_detail_cmd;
struct cmd_element no_debug_ospf6_lsa_type_cmd;
struct cmd_element no_debug_ospf6_lsa_type_detail_cmd;
ALIAS (no_debug_ospf6_lsa_type,
no_debug_ospf6_lsa_hex_detail_cmd,
"no debug ospf6 lsa (router|network|inter-prefix|inter-router|as-ext|grp-mbr|type7|link|intra-prefix) (originate|examine|flooding)",
NO_STR
DEBUG_STR
OSPF6_STR
"Debug Link State Advertisements (LSAs)\n"
"Specify LS type as Hexadecimal\n"
)
void
install_element_ospf6_debug_lsa (void)
{
u_int i;
struct ospf6_lsa_handler *handler;
#define STRSIZE 256
#define DOCSIZE 1024
static char strbuf[STRSIZE];
static char docbuf[DOCSIZE];
static char detail_strbuf[STRSIZE];
static char detail_docbuf[DOCSIZE];
char *str, *no_str;
char *doc, *no_doc;
strbuf[0] = '\0';
no_str = &strbuf[strlen (strbuf)];
strncat (strbuf, "no ", STRSIZE - strlen (strbuf));
str = &strbuf[strlen (strbuf)];
strncat (strbuf, "debug ospf6 lsa (", STRSIZE - strlen (strbuf));
for (i = 0; i < vector_active (ospf6_lsa_handler_vector); i++)
{
handler = vector_slot (ospf6_lsa_handler_vector, i);
if (handler == NULL)
continue;
strncat (strbuf, ospf6_lsa_handler_name (handler),
STRSIZE - strlen (strbuf));
strncat (strbuf, "|", STRSIZE - strlen (strbuf));
}
strbuf[strlen (strbuf) - 1] = ')';
strbuf[strlen (strbuf)] = '\0';
docbuf[0] = '\0';
no_doc = &docbuf[strlen (docbuf)];
strncat (docbuf, NO_STR, DOCSIZE - strlen (docbuf));
doc = &docbuf[strlen (docbuf)];
strncat (docbuf, DEBUG_STR, DOCSIZE - strlen (docbuf));
strncat (docbuf, OSPF6_STR, DOCSIZE - strlen (docbuf));
strncat (docbuf, "Debug Link State Advertisements (LSAs)\n",
DOCSIZE - strlen (docbuf));
for (i = 0; i < vector_active (ospf6_lsa_handler_vector); i++)
{
handler = vector_slot (ospf6_lsa_handler_vector, i);
if (handler == NULL)
continue;
strncat (docbuf, "Debug ", DOCSIZE - strlen (docbuf));
strncat (docbuf, handler->name, DOCSIZE - strlen (docbuf));
strncat (docbuf, "-LSA\n", DOCSIZE - strlen (docbuf));
}
docbuf[strlen (docbuf)] = '\0';
debug_ospf6_lsa_type_cmd.string = str;
debug_ospf6_lsa_type_cmd.func = debug_ospf6_lsa_type;
debug_ospf6_lsa_type_cmd.doc = doc;
no_debug_ospf6_lsa_type_cmd.string = no_str;
no_debug_ospf6_lsa_type_cmd.func = no_debug_ospf6_lsa_type;
no_debug_ospf6_lsa_type_cmd.doc = no_doc;
strncpy (detail_strbuf, strbuf, STRSIZE);
strncat (detail_strbuf, " (originate|examin|flooding)",
STRSIZE - strlen (detail_strbuf));
detail_strbuf[strlen (detail_strbuf)] = '\0';
no_str = &detail_strbuf[0];
str = &detail_strbuf[strlen ("no ")];
strncpy (detail_docbuf, docbuf, DOCSIZE);
strncat (detail_docbuf, "Debug Originating LSA\n",
DOCSIZE - strlen (detail_docbuf));
strncat (detail_docbuf, "Debug Examining LSA\n",
DOCSIZE - strlen (detail_docbuf));
strncat (detail_docbuf, "Debug Flooding LSA\n",
DOCSIZE - strlen (detail_docbuf));
detail_docbuf[strlen (detail_docbuf)] = '\0';
no_doc = &detail_docbuf[0];
doc = &detail_docbuf[strlen (NO_STR)];
debug_ospf6_lsa_type_detail_cmd.string = str;
debug_ospf6_lsa_type_detail_cmd.func = debug_ospf6_lsa_type;
debug_ospf6_lsa_type_detail_cmd.doc = doc;
no_debug_ospf6_lsa_type_detail_cmd.string = no_str;
no_debug_ospf6_lsa_type_detail_cmd.func = no_debug_ospf6_lsa_type;
no_debug_ospf6_lsa_type_detail_cmd.doc = no_doc;
install_element (ENABLE_NODE, &debug_ospf6_lsa_hex_cmd);
install_element (ENABLE_NODE, &debug_ospf6_lsa_type_cmd);
install_element (ENABLE_NODE, &debug_ospf6_lsa_type_detail_cmd);
install_element (ENABLE_NODE, &debug_ospf6_lsa_hex_detail_cmd);
install_element (ENABLE_NODE, &no_debug_ospf6_lsa_hex_cmd);
install_element (ENABLE_NODE, &no_debug_ospf6_lsa_type_cmd);
install_element (ENABLE_NODE, &no_debug_ospf6_lsa_type_detail_cmd);
install_element (ENABLE_NODE, &no_debug_ospf6_lsa_hex_detail_cmd);
install_element (CONFIG_NODE, &debug_ospf6_lsa_hex_cmd);
install_element (CONFIG_NODE, &debug_ospf6_lsa_type_cmd);
install_element (CONFIG_NODE, &debug_ospf6_lsa_type_detail_cmd);
install_element (CONFIG_NODE, &debug_ospf6_lsa_hex_detail_cmd);
install_element (CONFIG_NODE, &no_debug_ospf6_lsa_hex_cmd);
install_element (CONFIG_NODE, &no_debug_ospf6_lsa_type_cmd);
install_element (CONFIG_NODE, &no_debug_ospf6_lsa_type_detail_cmd);
install_element (CONFIG_NODE, &no_debug_ospf6_lsa_hex_detail_cmd);
}
int
@ -996,7 +954,7 @@ config_write_ospf6_debug_lsa (struct vty *vty)
vty_out (vty, "debug ospf6 lsa %s originate%s",
ospf6_lsa_handler_name (handler), VNL);
if (CHECK_FLAG (handler->debug, OSPF6_LSA_DEBUG_EXAMIN))
vty_out (vty, "debug ospf6 lsa %s examin%s",
vty_out (vty, "debug ospf6 lsa %s examine%s",
ospf6_lsa_handler_name (handler), VNL);
if (CHECK_FLAG (handler->debug, OSPF6_LSA_DEBUG_FLOOD))
vty_out (vty, "debug ospf6 lsa %s flooding%s",

View File

@ -107,15 +107,16 @@ struct ospf6_lsa_header
((L)->header->adv_router == (a) && (L)->header->id == (i) && \
(L)->header->type == (t))
#define OSPF6_LSA_IS_DIFFER(L1, L2) ospf6_lsa_is_differ (L1, L2)
#define OSPF6_LSA_IS_MAXAGE(L) (ospf6_lsa_age_current (L) == MAXAGE)
#define OSPF6_LSA_IS_MAXAGE(L) (ospf6_lsa_age_current (L) == OSPF_LSA_MAXAGE)
#define OSPF6_LSA_IS_CHANGED(L1, L2) ospf6_lsa_is_changed (L1, L2)
#define OSPF6_LSA_IS_SEQWRAP(L) ((L)->header->seqnum == htonl(OSPF_MAX_SEQUENCE_NUMBER + 1))
struct ospf6_lsa
{
char name[64]; /* dump string */
struct ospf6_lsa *prev;
struct ospf6_lsa *next;
struct route_node *rn;
unsigned char lock; /* reference counter */
unsigned char flag; /* special meaning (e.g. floodback) */
@ -140,12 +141,15 @@ struct ospf6_lsa
#define OSPF6_LSA_FLOODBACK 0x02
#define OSPF6_LSA_DUPLICATE 0x04
#define OSPF6_LSA_IMPLIEDACK 0x08
#define OSPF6_LSA_SEQWRAPPED 0x20
struct ospf6_lsa_handler
{
u_int16_t type; /* host byte order */
const char *name;
const char *short_name;
int (*show) (struct vty *, struct ospf6_lsa *);
char *(*get_prefix_str) (struct ospf6_lsa *, char *buf, int buflen, int pos);
u_char debug;
};
@ -208,6 +212,7 @@ extern struct ospf6_lsa_handler unknown_handler;
/* Function Prototypes */
extern const char *ospf6_lstype_name (u_int16_t type);
extern const char *ospf6_lstype_short_name (u_int16_t type);
extern u_char ospf6_lstype_debug (u_int16_t type);
extern int ospf6_lsa_is_differ (struct ospf6_lsa *lsa1, struct ospf6_lsa *lsa2);
extern int ospf6_lsa_is_changed (struct ospf6_lsa *lsa1, struct ospf6_lsa *lsa2);

View File

@ -54,9 +54,12 @@ ospf6_lsdb_create (void *data)
void
ospf6_lsdb_delete (struct ospf6_lsdb *lsdb)
{
ospf6_lsdb_remove_all (lsdb);
route_table_finish (lsdb->table);
XFREE (MTYPE_OSPF6_LSDB, lsdb);
if (lsdb != NULL)
{
ospf6_lsdb_remove_all (lsdb);
route_table_finish (lsdb->table);
XFREE (MTYPE_OSPF6_LSDB, lsdb);
}
}
static void
@ -70,7 +73,7 @@ ospf6_lsdb_set_key (struct prefix_ipv6 *key, void *value, int len)
key->prefixlen += len * 8;
}
#ifndef NDEBUG
#ifdef DEBUG
static void
_lsdb_count_assert (struct ospf6_lsdb *lsdb)
{
@ -94,16 +97,16 @@ _lsdb_count_assert (struct ospf6_lsdb *lsdb)
assert (num == lsdb->count);
}
#define ospf6_lsdb_count_assert(t) (_lsdb_count_assert (t))
#else /*NDEBUG*/
#else /*DEBUG*/
#define ospf6_lsdb_count_assert(t) ((void) 0)
#endif /*NDEBUG*/
#endif /*DEBUG*/
void
ospf6_lsdb_add (struct ospf6_lsa *lsa, struct ospf6_lsdb *lsdb)
{
struct prefix_ipv6 key;
struct route_node *current, *nextnode, *prevnode;
struct ospf6_lsa *next, *prev, *old = NULL;
struct route_node *current;
struct ospf6_lsa *old = NULL;
memset (&key, 0, sizeof (key));
ospf6_lsdb_set_key (&key, &lsa->header->type, sizeof (lsa->header->type));
@ -114,55 +117,25 @@ ospf6_lsdb_add (struct ospf6_lsa *lsa, struct ospf6_lsdb *lsdb)
current = route_node_get (lsdb->table, (struct prefix *) &key);
old = current->info;
current->info = lsa;
lsa->rn = current;
ospf6_lsa_lock (lsa);
if (old)
if (!old)
{
if (old->prev)
old->prev->next = lsa;
if (old->next)
old->next->prev = lsa;
lsa->next = old->next;
lsa->prev = old->prev;
lsdb->count++;
if (OSPF6_LSA_IS_MAXAGE (lsa))
{
if (lsdb->hook_remove)
(*lsdb->hook_remove) (lsa);
}
else
{
if (lsdb->hook_add)
(*lsdb->hook_add) (lsa);
}
}
else
{
/* next link */
nextnode = current;
route_lock_node (nextnode);
do {
nextnode = route_next (nextnode);
} while (nextnode && nextnode->info == NULL);
if (nextnode == NULL)
lsa->next = NULL;
else
{
next = nextnode->info;
lsa->next = next;
next->prev = lsa;
route_unlock_node (nextnode);
}
/* prev link */
prevnode = current;
route_lock_node (prevnode);
do {
prevnode = route_prev (prevnode);
} while (prevnode && prevnode->info == NULL);
if (prevnode == NULL)
lsa->prev = NULL;
else
{
prev = prevnode->info;
lsa->prev = prev;
prev->next = lsa;
route_unlock_node (prevnode);
}
lsdb->count++;
}
if (old)
{
if (OSPF6_LSA_IS_CHANGED (old, lsa))
{
@ -187,20 +160,8 @@ ospf6_lsdb_add (struct ospf6_lsa *lsa, struct ospf6_lsdb *lsdb)
(*lsdb->hook_add) (lsa);
}
}
ospf6_lsa_unlock (old);
}
else if (OSPF6_LSA_IS_MAXAGE (lsa))
{
if (lsdb->hook_remove)
(*lsdb->hook_remove) (lsa);
}
else
{
if (lsdb->hook_add)
(*lsdb->hook_add) (lsa);
}
if (old)
ospf6_lsa_unlock (old);
ospf6_lsdb_count_assert (lsdb);
}
@ -220,19 +181,15 @@ ospf6_lsdb_remove (struct ospf6_lsa *lsa, struct ospf6_lsdb *lsdb)
node = route_node_lookup (lsdb->table, (struct prefix *) &key);
assert (node && node->info == lsa);
if (lsa->prev)
lsa->prev->next = lsa->next;
if (lsa->next)
lsa->next->prev = lsa->prev;
node->info = NULL;
lsdb->count--;
if (lsdb->hook_remove)
(*lsdb->hook_remove) (lsa);
route_unlock_node (node); /* to free the lookup lock */
route_unlock_node (node); /* to free the original lock */
ospf6_lsa_unlock (lsa);
route_unlock_node (node);
ospf6_lsdb_count_assert (lsdb);
}
@ -255,6 +212,8 @@ ospf6_lsdb_lookup (u_int16_t type, u_int32_t id, u_int32_t adv_router,
node = route_node_lookup (lsdb->table, (struct prefix *) &key);
if (node == NULL || node->info == NULL)
return NULL;
route_unlock_node (node);
return (struct ospf6_lsa *) node->info;
}
@ -306,21 +265,9 @@ ospf6_lsdb_lookup_next (u_int16_t type, u_int32_t id, u_int32_t adv_router,
if (prefix_same (&node->p, p))
{
struct route_node *prev = node;
struct ospf6_lsa *lsa_prev;
struct ospf6_lsa *lsa_next;
node = route_next (node);
while (node && node->info == NULL)
node = route_next (node);
lsa_prev = prev->info;
lsa_next = (node ? node->info : NULL);
assert (lsa_prev);
assert (lsa_prev->next == lsa_next);
if (lsa_next)
assert (lsa_next->prev == lsa_prev);
zlog_debug ("lsdb_lookup_next: assert OK with previous LSA");
}
if (! node)
@ -346,7 +293,6 @@ ospf6_lsdb_head (struct ospf6_lsdb *lsdb)
if (node == NULL)
return NULL;
route_unlock_node (node);
if (node->info)
ospf6_lsa_lock ((struct ospf6_lsa *) node->info);
return (struct ospf6_lsa *) node->info;
@ -355,12 +301,20 @@ ospf6_lsdb_head (struct ospf6_lsdb *lsdb)
struct ospf6_lsa *
ospf6_lsdb_next (struct ospf6_lsa *lsa)
{
struct ospf6_lsa *next = lsa->next;
struct route_node *node = lsa->rn;
struct ospf6_lsa *next = NULL;
do {
node = route_next (node);
} while (node && node->info == NULL);
if ((node != NULL) && (node->info != NULL))
{
next = node->info;
ospf6_lsa_lock (next);
}
ospf6_lsa_unlock (lsa);
if (next)
ospf6_lsa_lock (next);
return next;
}
@ -390,8 +344,6 @@ ospf6_lsdb_type_router_head (u_int16_t type, u_int32_t adv_router,
if (node == NULL)
return NULL;
else
route_unlock_node (node);
if (! prefix_match ((struct prefix *) &key, &node->p))
return NULL;
@ -406,18 +358,19 @@ struct ospf6_lsa *
ospf6_lsdb_type_router_next (u_int16_t type, u_int32_t adv_router,
struct ospf6_lsa *lsa)
{
struct ospf6_lsa *next = lsa->next;
struct ospf6_lsa *next = ospf6_lsdb_next(lsa);
if (next)
{
if (next->header->type != type ||
next->header->adv_router != adv_router)
next = NULL;
{
route_unlock_node (next->rn);
ospf6_lsa_unlock (next);
next = NULL;
}
}
if (next)
ospf6_lsa_lock (next);
ospf6_lsa_unlock (lsa);
return next;
}
@ -444,8 +397,6 @@ ospf6_lsdb_type_head (u_int16_t type, struct ospf6_lsdb *lsdb)
if (node == NULL)
return NULL;
else
route_unlock_node (node);
if (! prefix_match ((struct prefix *) &key, &node->p))
return NULL;
@ -459,17 +410,18 @@ ospf6_lsdb_type_head (u_int16_t type, struct ospf6_lsdb *lsdb)
struct ospf6_lsa *
ospf6_lsdb_type_next (u_int16_t type, struct ospf6_lsa *lsa)
{
struct ospf6_lsa *next = lsa->next;
struct ospf6_lsa *next = ospf6_lsdb_next (lsa);
if (next)
{
if (next->header->type != type)
next = NULL;
{
route_unlock_node (next->rn);
ospf6_lsa_unlock (next);
next = NULL;
}
}
if (next)
ospf6_lsa_lock (next);
ospf6_lsa_unlock (lsa);
return next;
}
@ -477,10 +429,61 @@ void
ospf6_lsdb_remove_all (struct ospf6_lsdb *lsdb)
{
struct ospf6_lsa *lsa;
if (lsdb == NULL)
return;
for (lsa = ospf6_lsdb_head (lsdb); lsa; lsa = ospf6_lsdb_next (lsa))
ospf6_lsdb_remove (lsa, lsdb);
}
void
ospf6_lsdb_lsa_unlock (struct ospf6_lsa *lsa)
{
if (lsa != NULL)
{
if (lsa->rn != NULL)
route_unlock_node (lsa->rn);
ospf6_lsa_unlock (lsa);
}
}
int
ospf6_lsdb_maxage_remover (struct ospf6_lsdb *lsdb)
{
int reschedule = 0;
struct ospf6_lsa *lsa;
for (lsa = ospf6_lsdb_head (lsdb); lsa; lsa = ospf6_lsdb_next (lsa))
{
if (! OSPF6_LSA_IS_MAXAGE (lsa))
continue;
if (lsa->retrans_count != 0)
{
reschedule = 1;
continue;
}
if (IS_OSPF6_DEBUG_LSA_TYPE (lsa->header->type))
zlog_debug ("Remove MaxAge %s", lsa->name);
if (CHECK_FLAG(lsa->flag, OSPF6_LSA_SEQWRAPPED))
{
UNSET_FLAG(lsa->flag, OSPF6_LSA_SEQWRAPPED);
/*
* lsa->header->age = 0;
*/
lsa->header->seqnum = htonl(OSPF_MAX_SEQUENCE_NUMBER + 1);
ospf6_lsa_checksum (lsa->header);
THREAD_OFF(lsa->refresh);
thread_execute (master, ospf6_lsa_refresh, lsa, 0);
} else {
ospf6_lsdb_remove (lsa, lsdb);
}
}
return (reschedule);
}
void
ospf6_lsdb_show (struct vty *vty, int level,
u_int16_t *type, u_int32_t *id, u_int32_t *adv_router,
@ -551,7 +554,7 @@ ospf6_new_ls_id (u_int16_t type, u_int32_t adv_router,
continue;
if (ntohl (lsa->header->id) > id)
{
ospf6_lsa_unlock (lsa);
ospf6_lsdb_lsa_unlock (lsa);
break;
}
id++;
@ -572,7 +575,7 @@ ospf6_new_ls_seqnum (u_int16_t type, u_int32_t id, u_int32_t adv_router,
/* if current database copy not found, return InitialSequenceNumber */
lsa = ospf6_lsdb_lookup (type, id, adv_router, lsdb);
if (lsa == NULL)
seqnum = INITIAL_SEQUENCE_NUMBER;
seqnum = OSPF_INITIAL_SEQUENCE_NUMBER;
else
seqnum = (signed long) ntohl (lsa->header->seqnum) + 1;

View File

@ -34,21 +34,6 @@ struct ospf6_lsdb
void (*hook_remove) (struct ospf6_lsa *);
};
#define OSPF6_LSDB_MAXAGE_REMOVER(lsdb) \
do { \
struct ospf6_lsa *lsa; \
for (lsa = ospf6_lsdb_head (lsdb); lsa; lsa = ospf6_lsdb_next (lsa)) \
{ \
if (! OSPF6_LSA_IS_MAXAGE (lsa)) \
continue; \
if (lsa->retrans_count != 0) \
continue; \
if (IS_OSPF6_DEBUG_LSA_TYPE (lsa->header->type)) \
zlog_debug ("Remove MaxAge %s", lsa->name); \
ospf6_lsdb_remove (lsa, lsdb); \
} \
} while (0)
/* Function Prototypes */
extern struct ospf6_lsdb *ospf6_lsdb_create (void *data);
extern void ospf6_lsdb_delete (struct ospf6_lsdb *lsdb);
@ -79,6 +64,7 @@ extern struct ospf6_lsa *ospf6_lsdb_type_next (u_int16_t type,
struct ospf6_lsa *lsa);
extern void ospf6_lsdb_remove_all (struct ospf6_lsdb *lsdb);
extern void ospf6_lsdb_lsa_unlock (struct ospf6_lsa *lsa);
#define OSPF6_LSDB_SHOW_LEVEL_NORMAL 0
#define OSPF6_LSDB_SHOW_LEVEL_DETAIL 1
@ -94,5 +80,6 @@ extern u_int32_t ospf6_new_ls_id (u_int16_t type, u_int32_t adv_router,
extern u_int32_t ospf6_new_ls_seqnum (u_int16_t type, u_int32_t id,
u_int32_t adv_router,
struct ospf6_lsdb *lsdb);
extern int ospf6_lsdb_maxage_remover (struct ospf6_lsdb *lsdb);
#endif /* OSPF6_LSDB_H */

View File

@ -41,6 +41,8 @@
#include "ospf6_message.h"
#include "ospf6_asbr.h"
#include "ospf6_lsa.h"
#include "ospf6_interface.h"
#include "ospf6_zebra.h"
/* Default configuration file name for ospf6d. */
#define OSPF6_DEFAULT_CONFIG "ospf6d.conf"
@ -134,12 +136,16 @@ Report bugs to %s\n", progname, ZEBRA_BUG_ADDRESS);
static void __attribute__ ((noreturn))
ospf6_exit (int status)
{
extern struct ospf6 *ospf6;
extern struct zclient *zclient;
struct listnode *node;
struct interface *ifp;
if (ospf6)
ospf6_delete (ospf6);
for (ALL_LIST_ELEMENTS_RO(iflist, node, ifp))
if (ifp->info != NULL)
ospf6_interface_delete(ifp->info);
ospf6_message_terminate ();
ospf6_asbr_terminate ();
ospf6_lsa_terminate ();

View File

@ -517,20 +517,20 @@ ospf6_dbdesc_recv_master (struct ospf6_header *oh,
{
if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
zlog_debug ("Add request (No database copy)");
ospf6_lsdb_add (his, on->request_list);
ospf6_lsdb_add (ospf6_lsa_copy(his), on->request_list);
}
else if (ospf6_lsa_compare (his, mine) < 0)
{
if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
zlog_debug ("Add request (Received MoreRecent)");
ospf6_lsdb_add (his, on->request_list);
ospf6_lsdb_add (ospf6_lsa_copy(his), on->request_list);
}
else
{
if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
zlog_debug ("Discard (Existing MoreRecent)");
ospf6_lsa_delete (his);
}
ospf6_lsa_delete (his);
}
assert (p == OSPF6_MESSAGE_END (oh));
@ -539,7 +539,7 @@ ospf6_dbdesc_recv_master (struct ospf6_header *oh,
on->dbdesc_seqnum ++;
/* schedule send lsreq */
if (on->thread_send_lsreq == NULL)
if (on->request_list->count && (on->thread_send_lsreq == NULL))
on->thread_send_lsreq =
thread_add_event (master, ospf6_lsreq_send, on, 0);
@ -735,10 +735,9 @@ ospf6_dbdesc_recv_slave (struct ospf6_header *oh,
{
if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
zlog_debug ("Add request-list: %s", his->name);
ospf6_lsdb_add (his, on->request_list);
ospf6_lsdb_add (ospf6_lsa_copy(his), on->request_list);
}
else
ospf6_lsa_delete (his);
ospf6_lsa_delete (his);
}
assert (p == OSPF6_MESSAGE_END (oh));
@ -747,7 +746,8 @@ ospf6_dbdesc_recv_slave (struct ospf6_header *oh,
on->dbdesc_seqnum = ntohl (dbdesc->seqnum);
/* schedule send lsreq */
if (on->thread_send_lsreq == NULL)
if ((on->thread_send_lsreq == NULL) &&
(on->request_list->count))
on->thread_send_lsreq =
thread_add_event (master, ospf6_lsreq_send, on, 0);
@ -1282,7 +1282,7 @@ ospf6_rxpacket_examin (struct ospf6_interface *oi, struct ospf6_header *oh, cons
{
if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
{
if (oh->area_id == BACKBONE_AREA_ID)
if (oh->area_id == OSPF_AREA_BACKBONE)
zlog_debug ("%s: Message may be via Virtual Link: not supported", __func__);
else
zlog_debug
@ -1351,19 +1351,6 @@ ospf6_lsupdate_recv (struct in6_addr *src, struct in6_addr *dst,
assert (p == OSPF6_MESSAGE_END (oh));
/* RFC2328 Section 10.9: When the neighbor responds to these requests
with the proper Link State Update packet(s), the Link state request
list is truncated and a new Link State Request packet is sent. */
/* send new Link State Request packet if this LS Update packet
can be recognized as a response to our previous LS Request */
if (! IN6_IS_ADDR_MULTICAST (dst) &&
(on->state == OSPF6_NEIGHBOR_EXCHANGE ||
on->state == OSPF6_NEIGHBOR_LOADING))
{
THREAD_OFF (on->thread_send_lsreq);
on->thread_send_lsreq =
thread_add_event (master, ospf6_lsreq_send, on, 0);
}
}
static void
@ -1556,7 +1543,7 @@ ospf6_receive (struct thread *thread)
}
oi = ospf6_interface_lookup_by_ifindex (ifindex);
if (oi == NULL || oi->area == NULL)
if (oi == NULL || oi->area == NULL || CHECK_FLAG(oi->flag, OSPF6_INTERFACE_DISABLE))
{
zlog_debug ("Message received on disabled interface");
return 0;
@ -1785,6 +1772,7 @@ ospf6_dbdesc_send (struct thread *thread)
struct ospf6_dbdesc *dbdesc;
u_char *p;
struct ospf6_lsa *lsa;
struct in6_addr *dst;
on = (struct ospf6_neighbor *) THREAD_ARG (thread);
on->thread_send_dbdesc = (struct thread *) NULL;
@ -1809,7 +1797,8 @@ ospf6_dbdesc_send (struct thread *thread)
sizeof (struct ospf6_header));
/* if this is initial one, initialize sequence number for DbDesc */
if (CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT))
if (CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT) &&
(on->dbdesc_seqnum == 0))
{
struct timeval tv;
if (quagga_gettime (QUAGGA_CLK_MONOTONIC, &tv) < 0)
@ -1837,7 +1826,7 @@ ospf6_dbdesc_send (struct thread *thread)
if (p - sendbuf + sizeof (struct ospf6_lsa_header) >
ospf6_packet_max(on->ospf6_if))
{
ospf6_lsa_unlock (lsa);
ospf6_lsdb_lsa_unlock (lsa);
break;
}
memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header));
@ -1848,8 +1837,14 @@ ospf6_dbdesc_send (struct thread *thread)
oh->type = OSPF6_MESSAGE_TYPE_DBDESC;
oh->length = htons (p - sendbuf);
ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
on->ospf6_if, oh);
if (on->ospf6_if->state == OSPF6_INTERFACE_POINTTOPOINT)
dst = &allspfrouters6;
else
dst = &on->linklocal_addr;
ospf6_send (on->ospf6_if->linklocal_addr, dst, on->ospf6_if, oh);
return 0;
}
@ -1871,7 +1866,7 @@ ospf6_dbdesc_send_newone (struct thread *thread)
{
if (size + sizeof (struct ospf6_lsa_header) > ospf6_packet_max(on->ospf6_if))
{
ospf6_lsa_unlock (lsa);
ospf6_lsdb_lsa_unlock (lsa);
break;
}
@ -1900,7 +1895,7 @@ ospf6_lsreq_send (struct thread *thread)
struct ospf6_header *oh;
struct ospf6_lsreq_entry *e;
u_char *p;
struct ospf6_lsa *lsa;
struct ospf6_lsa *lsa, *last_req;
on = (struct ospf6_neighbor *) THREAD_ARG (thread);
on->thread_send_lsreq = (struct thread *) NULL;
@ -1922,13 +1917,9 @@ ospf6_lsreq_send (struct thread *thread)
return 0;
}
/* set next thread */
on->thread_send_lsreq =
thread_add_timer (master, ospf6_lsreq_send, on,
on->ospf6_if->rxmt_interval);
memset (sendbuf, 0, iobuflen);
oh = (struct ospf6_header *) sendbuf;
last_req = NULL;
/* set Request entries in lsreq */
p = (u_char *)((caddr_t) oh + sizeof (struct ospf6_header));
@ -1938,7 +1929,7 @@ ospf6_lsreq_send (struct thread *thread)
/* MTU check */
if (p - sendbuf + sizeof (struct ospf6_lsreq_entry) > ospf6_packet_max(on->ospf6_if))
{
ospf6_lsa_unlock (lsa);
ospf6_lsdb_lsa_unlock (lsa);
break;
}
@ -1947,13 +1938,37 @@ ospf6_lsreq_send (struct thread *thread)
e->id = lsa->header->id;
e->adv_router = lsa->header->adv_router;
p += sizeof (struct ospf6_lsreq_entry);
last_req = lsa;
}
if (last_req != NULL)
{
if (on->last_ls_req != NULL)
{
ospf6_lsa_unlock (on->last_ls_req);
}
ospf6_lsa_lock (last_req);
on->last_ls_req = last_req;
}
oh->type = OSPF6_MESSAGE_TYPE_LSREQ;
oh->length = htons (p - sendbuf);
ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
if (on->ospf6_if->state == OSPF6_INTERFACE_POINTTOPOINT)
ospf6_send (on->ospf6_if->linklocal_addr, &allspfrouters6,
on->ospf6_if, oh);
else
ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
on->ospf6_if, oh);
/* set next thread */
if (on->request_list->count != 0)
{
on->thread_send_lsreq =
thread_add_timer (master, ospf6_lsreq_send, on,
on->ospf6_if->rxmt_interval);
}
return 0;
}
@ -1964,7 +1979,7 @@ ospf6_lsupdate_send_neighbor (struct thread *thread)
struct ospf6_header *oh;
struct ospf6_lsupdate *lsupdate;
u_char *p;
int num;
int lsa_cnt;
struct ospf6_lsa *lsa;
on = (struct ospf6_neighbor *) THREAD_ARG (thread);
@ -1981,22 +1996,13 @@ ospf6_lsupdate_send_neighbor (struct thread *thread)
return 0;
}
/* if we have nothing to send, return */
if (on->lsupdate_list->count == 0 &&
on->retrans_list->count == 0)
{
if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
zlog_debug ("Quit to send (nothing to send)");
return 0;
}
memset (sendbuf, 0, iobuflen);
oh = (struct ospf6_header *) sendbuf;
lsupdate = (struct ospf6_lsupdate *)
((caddr_t) oh + sizeof (struct ospf6_header));
p = (u_char *)((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
num = 0;
lsa_cnt = 0;
/* lsupdate_list lists those LSA which doesn't need to be
retransmitted. remove those from the list */
@ -2005,58 +2011,85 @@ ospf6_lsupdate_send_neighbor (struct thread *thread)
{
/* MTU check */
if ( (p - sendbuf + (unsigned int)OSPF6_LSA_SIZE (lsa->header))
> ospf6_packet_max(on->ospf6_if))
{
ospf6_lsa_unlock (lsa);
break;
}
> ospf6_packet_max(on->ospf6_if))
{
ospf6_lsdb_lsa_unlock (lsa);
break;
}
ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header));
p += OSPF6_LSA_SIZE (lsa->header);
num++;
lsa_cnt++;
assert (lsa->lock == 2);
ospf6_lsdb_remove (lsa, on->lsupdate_list);
}
if (lsa_cnt)
{
oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
oh->length = htons (p - sendbuf);
lsupdate->lsa_number = htonl (lsa_cnt);
if ((on->ospf6_if->state == OSPF6_INTERFACE_POINTTOPOINT) ||
(on->ospf6_if->state == OSPF6_INTERFACE_DR) ||
(on->ospf6_if->state == OSPF6_INTERFACE_BDR))
ospf6_send (on->ospf6_if->linklocal_addr, &allspfrouters6,
on->ospf6_if, oh);
else
ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
on->ospf6_if, oh);
}
/* The addresses used for retransmissions are different from those sent the
first time and so we need to separate them here.
*/
memset (sendbuf, 0, iobuflen);
oh = (struct ospf6_header *) sendbuf;
lsupdate = (struct ospf6_lsupdate *)
((caddr_t) oh + sizeof (struct ospf6_header));
p = (u_char *)((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
lsa_cnt = 0;
for (lsa = ospf6_lsdb_head (on->retrans_list); lsa;
lsa = ospf6_lsdb_next (lsa))
{
/* MTU check */
if ( (p - sendbuf + (unsigned int)OSPF6_LSA_SIZE (lsa->header))
> ospf6_packet_max(on->ospf6_if))
{
ospf6_lsa_unlock (lsa);
break;
}
> ospf6_packet_max(on->ospf6_if))
{
ospf6_lsdb_lsa_unlock (lsa);
break;
}
ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header));
p += OSPF6_LSA_SIZE (lsa->header);
num++;
lsa_cnt++;
}
lsupdate->lsa_number = htonl (num);
oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
oh->length = htons (p - sendbuf);
ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
on->ospf6_if, oh);
if (on->lsupdate_list->count != 0 ||
on->retrans_list->count != 0)
if (lsa_cnt)
{
if (on->lsupdate_list->count != 0)
on->thread_send_lsupdate =
thread_add_event (master, ospf6_lsupdate_send_neighbor, on, 0);
oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
oh->length = htons (p - sendbuf);
lsupdate->lsa_number = htonl (lsa_cnt);
if (on->ospf6_if->state == OSPF6_INTERFACE_POINTTOPOINT)
ospf6_send (on->ospf6_if->linklocal_addr, &allspfrouters6,
on->ospf6_if, oh);
else
on->thread_send_lsupdate =
thread_add_timer (master, ospf6_lsupdate_send_neighbor, on,
on->ospf6_if->rxmt_interval);
ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
on->ospf6_if, oh);
}
if (on->lsupdate_list->count != 0)
on->thread_send_lsupdate =
thread_add_event (master, ospf6_lsupdate_send_neighbor, on, 0);
else if (on->retrans_list->count != 0)
on->thread_send_lsupdate =
thread_add_timer (master, ospf6_lsupdate_send_neighbor, on,
on->ospf6_if->rxmt_interval);
return 0;
}
@ -2067,7 +2100,7 @@ ospf6_lsupdate_send_interface (struct thread *thread)
struct ospf6_header *oh;
struct ospf6_lsupdate *lsupdate;
u_char *p;
int num;
int lsa_cnt;
struct ospf6_lsa *lsa;
oi = (struct ospf6_interface *) THREAD_ARG (thread);
@ -2088,41 +2121,46 @@ ospf6_lsupdate_send_interface (struct thread *thread)
memset (sendbuf, 0, iobuflen);
oh = (struct ospf6_header *) sendbuf;
lsupdate = (struct ospf6_lsupdate *)((caddr_t) oh +
sizeof (struct ospf6_header));
sizeof (struct ospf6_header));
p = (u_char *)((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
num = 0;
lsa_cnt = 0;
for (lsa = ospf6_lsdb_head (oi->lsupdate_list); lsa;
lsa = ospf6_lsdb_next (lsa))
{
/* MTU check */
if ( (p - sendbuf + ((unsigned int)OSPF6_LSA_SIZE (lsa->header)))
> ospf6_packet_max(oi))
{
ospf6_lsa_unlock (lsa);
break;
}
> ospf6_packet_max(oi))
{
ospf6_lsdb_lsa_unlock (lsa);
break;
}
ospf6_lsa_age_update_to_send (lsa, oi->transdelay);
memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header));
p += OSPF6_LSA_SIZE (lsa->header);
num++;
lsa_cnt++;
assert (lsa->lock == 2);
ospf6_lsdb_remove (lsa, oi->lsupdate_list);
}
lsupdate->lsa_number = htonl (num);
if (lsa_cnt)
{
lsupdate->lsa_number = htonl (lsa_cnt);
oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
oh->length = htons (p - sendbuf);
oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
oh->length = htons (p - sendbuf);
if (oi->state == OSPF6_INTERFACE_DR ||
oi->state == OSPF6_INTERFACE_BDR)
ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh);
else
ospf6_send (oi->linklocal_addr, &alldrouters6, oi, oh);
if ((oi->state == OSPF6_INTERFACE_POINTTOPOINT) ||
(oi->state == OSPF6_INTERFACE_DR) ||
(oi->state == OSPF6_INTERFACE_BDR))
ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh);
else
ospf6_send (oi->linklocal_addr, &alldrouters6, oi, oh);
}
if (oi->lsupdate_list->count > 0)
{
@ -2140,6 +2178,7 @@ ospf6_lsack_send_neighbor (struct thread *thread)
struct ospf6_header *oh;
u_char *p;
struct ospf6_lsa *lsa;
int lsa_cnt = 0;
on = (struct ospf6_neighbor *) THREAD_ARG (thread);
on->thread_send_lsack = (struct thread *) NULL;
@ -2166,16 +2205,16 @@ ospf6_lsack_send_neighbor (struct thread *thread)
{
/* MTU check */
if (p - sendbuf + sizeof (struct ospf6_lsa_header) > ospf6_packet_max(on->ospf6_if))
{
/* if we run out of packet size/space here,
better to try again soon. */
THREAD_OFF (on->thread_send_lsack);
on->thread_send_lsack =
thread_add_event (master, ospf6_lsack_send_neighbor, on, 0);
{
/* if we run out of packet size/space here,
better to try again soon. */
THREAD_OFF (on->thread_send_lsack);
on->thread_send_lsack =
thread_add_event (master, ospf6_lsack_send_neighbor, on, 0);
ospf6_lsa_unlock (lsa);
break;
}
ospf6_lsdb_lsa_unlock (lsa);
break;
}
ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header));
@ -2183,13 +2222,24 @@ ospf6_lsack_send_neighbor (struct thread *thread)
assert (lsa->lock == 2);
ospf6_lsdb_remove (lsa, on->lsack_list);
lsa_cnt++;
}
oh->type = OSPF6_MESSAGE_TYPE_LSACK;
oh->length = htons (p - sendbuf);
if (lsa_cnt)
{
oh->type = OSPF6_MESSAGE_TYPE_LSACK;
oh->length = htons (p - sendbuf);
ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
on->ospf6_if, oh);
}
if (on->thread_send_lsack == NULL && on->lsack_list->count > 0)
{
on->thread_send_lsack =
thread_add_event (master, ospf6_lsack_send_neighbor, on, 0);
}
ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
on->ospf6_if, oh);
return 0;
}
@ -2200,6 +2250,7 @@ ospf6_lsack_send_interface (struct thread *thread)
struct ospf6_header *oh;
u_char *p;
struct ospf6_lsa *lsa;
int lsa_cnt = 0;
oi = (struct ospf6_interface *) THREAD_ARG (thread);
oi->thread_send_lsack = (struct thread *) NULL;
@ -2226,16 +2277,16 @@ ospf6_lsack_send_interface (struct thread *thread)
{
/* MTU check */
if (p - sendbuf + sizeof (struct ospf6_lsa_header) > ospf6_packet_max(oi))
{
/* if we run out of packet size/space here,
better to try again soon. */
THREAD_OFF (oi->thread_send_lsack);
oi->thread_send_lsack =
thread_add_event (master, ospf6_lsack_send_interface, oi, 0);
{
/* if we run out of packet size/space here,
better to try again soon. */
THREAD_OFF (oi->thread_send_lsack);
oi->thread_send_lsack =
thread_add_event (master, ospf6_lsack_send_interface, oi, 0);
ospf6_lsa_unlock (lsa);
break;
}
ospf6_lsdb_lsa_unlock (lsa);
break;
}
ospf6_lsa_age_update_to_send (lsa, oi->transdelay);
memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header));
@ -2243,16 +2294,21 @@ ospf6_lsack_send_interface (struct thread *thread)
assert (lsa->lock == 2);
ospf6_lsdb_remove (lsa, oi->lsack_list);
lsa_cnt++;
}
oh->type = OSPF6_MESSAGE_TYPE_LSACK;
oh->length = htons (p - sendbuf);
if (lsa_cnt)
{
oh->type = OSPF6_MESSAGE_TYPE_LSACK;
oh->length = htons (p - sendbuf);
if (oi->state == OSPF6_INTERFACE_DR ||
oi->state == OSPF6_INTERFACE_BDR)
ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh);
else
ospf6_send (oi->linklocal_addr, &alldrouters6, oi, oh);
if ((oi->state == OSPF6_INTERFACE_POINTTOPOINT) ||
(oi->state == OSPF6_INTERFACE_DR) ||
(oi->state == OSPF6_INTERFACE_BDR))
ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh);
else
ospf6_send (oi->linklocal_addr, &alldrouters6, oi, oh);
}
if (oi->thread_send_lsack == NULL && oi->lsack_list->count > 0)
{

View File

@ -98,7 +98,6 @@ ospf6_neighbor_create (u_int32_t router_id, struct ospf6_interface *oi)
on->retrans_list = ospf6_lsdb_create (on);
on->dbdesc_list = ospf6_lsdb_create (on);
on->lsreq_list = ospf6_lsdb_create (on);
on->lsupdate_list = ospf6_lsdb_create (on);
on->lsack_list = ospf6_lsdb_create (on);
@ -121,7 +120,6 @@ ospf6_neighbor_delete (struct ospf6_neighbor *on)
}
ospf6_lsdb_remove_all (on->dbdesc_list);
ospf6_lsdb_remove_all (on->lsreq_list);
ospf6_lsdb_remove_all (on->lsupdate_list);
ospf6_lsdb_remove_all (on->lsack_list);
@ -130,7 +128,6 @@ ospf6_neighbor_delete (struct ospf6_neighbor *on)
ospf6_lsdb_delete (on->retrans_list);
ospf6_lsdb_delete (on->dbdesc_list);
ospf6_lsdb_delete (on->lsreq_list);
ospf6_lsdb_delete (on->lsupdate_list);
ospf6_lsdb_delete (on->lsack_list);
@ -145,7 +142,7 @@ ospf6_neighbor_delete (struct ospf6_neighbor *on)
}
static void
ospf6_neighbor_state_change (u_char next_state, struct ospf6_neighbor *on)
ospf6_neighbor_state_change (u_char next_state, struct ospf6_neighbor *on, int event)
{
u_char prev_state;
@ -161,11 +158,23 @@ ospf6_neighbor_state_change (u_char next_state, struct ospf6_neighbor *on)
/* log */
if (IS_OSPF6_DEBUG_NEIGHBOR (STATE))
{
zlog_debug ("Neighbor state change %s: [%s]->[%s]", on->name,
zlog_debug ("Neighbor state change %s: [%s]->[%s] (%s)", on->name,
ospf6_neighbor_state_str[prev_state],
ospf6_neighbor_state_str[next_state]);
ospf6_neighbor_state_str[next_state],
ospf6_neighbor_event_string(event));
}
/* Optionally notify about adjacency changes */
if (CHECK_FLAG(on->ospf6_if->area->ospf6->config_flags,
OSPF6_LOG_ADJACENCY_CHANGES) &&
(CHECK_FLAG(on->ospf6_if->area->ospf6->config_flags,
OSPF6_LOG_ADJACENCY_DETAIL) ||
(next_state == OSPF6_NEIGHBOR_FULL) || (next_state < prev_state)))
zlog_notice("AdjChg: Nbr %s: %s -> %s (%s)", on->name,
ospf6_neighbor_state_str[prev_state],
ospf6_neighbor_state_str[next_state],
ospf6_neighbor_event_string(event));
if (prev_state == OSPF6_NEIGHBOR_FULL || next_state == OSPF6_NEIGHBOR_FULL)
{
OSPF6_ROUTER_LSA_SCHEDULE (on->ospf6_if->area);
@ -226,7 +235,8 @@ hello_received (struct thread *thread)
on->ospf6_if->dead_interval);
if (on->state <= OSPF6_NEIGHBOR_DOWN)
ospf6_neighbor_state_change (OSPF6_NEIGHBOR_INIT, on);
ospf6_neighbor_state_change (OSPF6_NEIGHBOR_INIT, on,
OSPF6_NEIGHBOR_EVENT_HELLO_RCVD);
return 0;
}
@ -249,11 +259,13 @@ twoway_received (struct thread *thread)
if (! need_adjacency (on))
{
ospf6_neighbor_state_change (OSPF6_NEIGHBOR_TWOWAY, on);
ospf6_neighbor_state_change (OSPF6_NEIGHBOR_TWOWAY, on,
OSPF6_NEIGHBOR_EVENT_TWOWAY_RCVD);
return 0;
}
ospf6_neighbor_state_change (OSPF6_NEIGHBOR_EXSTART, on);
ospf6_neighbor_state_change (OSPF6_NEIGHBOR_EXSTART, on,
OSPF6_NEIGHBOR_EVENT_TWOWAY_RCVD);
SET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT);
SET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT);
SET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT);
@ -330,7 +342,8 @@ negotiation_done (struct thread *thread)
}
UNSET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT);
ospf6_neighbor_state_change (OSPF6_NEIGHBOR_EXCHANGE, on);
ospf6_neighbor_state_change (OSPF6_NEIGHBOR_EXCHANGE, on,
OSPF6_NEIGHBOR_EVENT_NEGOTIATION_DONE);
return 0;
}
@ -358,13 +371,45 @@ exchange_done (struct thread *thread)
*/
if (on->request_list->count == 0)
ospf6_neighbor_state_change (OSPF6_NEIGHBOR_FULL, on);
ospf6_neighbor_state_change (OSPF6_NEIGHBOR_FULL, on,
OSPF6_NEIGHBOR_EVENT_EXCHANGE_DONE);
else
ospf6_neighbor_state_change (OSPF6_NEIGHBOR_LOADING, on);
{
ospf6_neighbor_state_change (OSPF6_NEIGHBOR_LOADING, on,
OSPF6_NEIGHBOR_EVENT_EXCHANGE_DONE);
if (on->thread_send_lsreq == NULL)
on->thread_send_lsreq =
thread_add_event (master, ospf6_lsreq_send, on, 0);
}
return 0;
}
/* Check loading state. */
void
ospf6_check_nbr_loading (struct ospf6_neighbor *on)
{
/* RFC2328 Section 10.9: When the neighbor responds to these requests
with the proper Link State Update packet(s), the Link state request
list is truncated and a new Link State Request packet is sent.
*/
if ((on->state == OSPF6_NEIGHBOR_LOADING) ||
(on->state == OSPF6_NEIGHBOR_EXCHANGE))
{
if (on->request_list->count == 0)
thread_add_event (master, loading_done, on, 0);
else if (on->last_ls_req == NULL)
{
if (on->thread_send_lsreq != NULL)
THREAD_OFF (on->thread_send_lsreq);
on->thread_send_lsreq =
thread_add_event (master, ospf6_lsreq_send, on, 0);
}
}
}
int
loading_done (struct thread *thread)
{
@ -381,7 +426,8 @@ loading_done (struct thread *thread)
assert (on->request_list->count == 0);
ospf6_neighbor_state_change (OSPF6_NEIGHBOR_FULL, on);
ospf6_neighbor_state_change (OSPF6_NEIGHBOR_FULL, on,
OSPF6_NEIGHBOR_EVENT_LOADING_DONE);
return 0;
}
@ -400,7 +446,8 @@ adj_ok (struct thread *thread)
if (on->state == OSPF6_NEIGHBOR_TWOWAY && need_adjacency (on))
{
ospf6_neighbor_state_change (OSPF6_NEIGHBOR_EXSTART, on);
ospf6_neighbor_state_change (OSPF6_NEIGHBOR_EXSTART, on,
OSPF6_NEIGHBOR_EVENT_ADJ_OK);
SET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT);
SET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT);
SET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT);
@ -413,7 +460,8 @@ adj_ok (struct thread *thread)
else if (on->state >= OSPF6_NEIGHBOR_EXSTART &&
! need_adjacency (on))
{
ospf6_neighbor_state_change (OSPF6_NEIGHBOR_TWOWAY, on);
ospf6_neighbor_state_change (OSPF6_NEIGHBOR_TWOWAY, on,
OSPF6_NEIGHBOR_EVENT_ADJ_OK);
ospf6_lsdb_remove_all (on->summary_list);
ospf6_lsdb_remove_all (on->request_list);
for (lsa = ospf6_lsdb_head (on->retrans_list); lsa;
@ -442,7 +490,8 @@ seqnumber_mismatch (struct thread *thread)
if (IS_OSPF6_DEBUG_NEIGHBOR (EVENT))
zlog_debug ("Neighbor Event %s: *SeqNumberMismatch*", on->name);
ospf6_neighbor_state_change (OSPF6_NEIGHBOR_EXSTART, on);
ospf6_neighbor_state_change (OSPF6_NEIGHBOR_EXSTART, on,
OSPF6_NEIGHBOR_EVENT_SEQNUMBER_MISMATCH);
SET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT);
SET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT);
SET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT);
@ -457,6 +506,8 @@ seqnumber_mismatch (struct thread *thread)
}
THREAD_OFF (on->thread_send_dbdesc);
on->dbdesc_seqnum++; /* Incr seqnum as per RFC2328, sec 10.3 */
on->thread_send_dbdesc =
thread_add_event (master, ospf6_dbdesc_send, on, 0);
@ -478,7 +529,8 @@ bad_lsreq (struct thread *thread)
if (IS_OSPF6_DEBUG_NEIGHBOR (EVENT))
zlog_debug ("Neighbor Event %s: *BadLSReq*", on->name);
ospf6_neighbor_state_change (OSPF6_NEIGHBOR_EXSTART, on);
ospf6_neighbor_state_change (OSPF6_NEIGHBOR_EXSTART, on,
OSPF6_NEIGHBOR_EVENT_BAD_LSREQ);
SET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT);
SET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT);
SET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT);
@ -493,6 +545,8 @@ bad_lsreq (struct thread *thread)
}
THREAD_OFF (on->thread_send_dbdesc);
on->dbdesc_seqnum++; /* Incr seqnum as per RFC2328, sec 10.3 */
on->thread_send_dbdesc =
thread_add_event (master, ospf6_dbdesc_send, on, 0);
@ -514,7 +568,8 @@ oneway_received (struct thread *thread)
if (IS_OSPF6_DEBUG_NEIGHBOR (EVENT))
zlog_debug ("Neighbor Event %s: *1Way-Received*", on->name);
ospf6_neighbor_state_change (OSPF6_NEIGHBOR_INIT, on);
ospf6_neighbor_state_change (OSPF6_NEIGHBOR_INIT, on,
OSPF6_NEIGHBOR_EVENT_ONEWAY_RCVD);
thread_add_event (master, neighbor_change, on->ospf6_if, 0);
ospf6_lsdb_remove_all (on->summary_list);
@ -549,7 +604,8 @@ inactivity_timer (struct thread *thread)
on->drouter = on->prev_drouter = 0;
on->bdrouter = on->prev_bdrouter = 0;
ospf6_neighbor_state_change (OSPF6_NEIGHBOR_DOWN, on);
ospf6_neighbor_state_change (OSPF6_NEIGHBOR_DOWN, on,
OSPF6_NEIGHBOR_EVENT_INACTIVITY_TIMER);
thread_add_event (master, neighbor_change, on->ospf6_if, 0);
listnode_delete (on->ospf6_if->neighbor_list, on);
@ -727,10 +783,10 @@ ospf6_neighbor_show_detail (struct vty *vty, struct ospf6_neighbor *on)
timersub (&on->thread_send_lsreq->u.sands, &now, &res);
timerstring (&res, duration, sizeof (duration));
vty_out (vty, " %d Pending LSAs for LSReq in Time %s [thread %s]%s",
on->lsreq_list->count, duration,
on->request_list->count, duration,
(on->thread_send_lsreq ? "on" : "off"),
VNL);
for (lsa = ospf6_lsdb_head (on->lsreq_list); lsa;
for (lsa = ospf6_lsdb_head (on->request_list); lsa;
lsa = ospf6_lsdb_next (lsa))
vty_out (vty, " %s%s", lsa->name, VNL);

View File

@ -86,6 +86,8 @@ struct ospf6_neighbor
struct ospf6_lsdb *lsupdate_list;
struct ospf6_lsdb *lsack_list;
struct ospf6_lsa *last_ls_req;
/* Inactivity timer */
struct thread *inactivity_timer;
@ -106,6 +108,44 @@ struct ospf6_neighbor
#define OSPF6_NEIGHBOR_LOADING 7
#define OSPF6_NEIGHBOR_FULL 8
/* Neighbor Events */
#define OSPF6_NEIGHBOR_EVENT_NO_EVENT 0
#define OSPF6_NEIGHBOR_EVENT_HELLO_RCVD 1
#define OSPF6_NEIGHBOR_EVENT_TWOWAY_RCVD 2
#define OSPF6_NEIGHBOR_EVENT_NEGOTIATION_DONE 3
#define OSPF6_NEIGHBOR_EVENT_EXCHANGE_DONE 4
#define OSPF6_NEIGHBOR_EVENT_LOADING_DONE 5
#define OSPF6_NEIGHBOR_EVENT_ADJ_OK 6
#define OSPF6_NEIGHBOR_EVENT_SEQNUMBER_MISMATCH 7
#define OSPF6_NEIGHBOR_EVENT_BAD_LSREQ 8
#define OSPF6_NEIGHBOR_EVENT_ONEWAY_RCVD 9
#define OSPF6_NEIGHBOR_EVENT_INACTIVITY_TIMER 10
#define OSPF6_NEIGHBOR_EVENT_MAX_EVENT 11
static const char *ospf6_neighbor_event_str[] =
{
"NoEvent",
"HelloReceived",
"2-WayReceived",
"NegotiationDone",
"ExchangeDone",
"LoadingDone",
"AdjOK?",
"SeqNumberMismatch",
"BadLSReq",
"1-WayReceived",
"InactivityTimer",
};
static const char *ospf6_neighbor_event_string (int event)
{
#define OSPF6_NEIGHBOR_UNKNOWN_EVENT_STRING "UnknownEvent"
if (event < OSPF6_NEIGHBOR_EVENT_MAX_EVENT)
return ospf6_neighbor_event_str[event];
return OSPF6_NEIGHBOR_UNKNOWN_EVENT_STRING;
}
extern const char *ospf6_neighbor_state_str[];
@ -130,6 +170,7 @@ extern int seqnumber_mismatch (struct thread *);
extern int bad_lsreq (struct thread *);
extern int oneway_received (struct thread *);
extern int inactivity_timer (struct thread *);
extern void ospf6_check_nbr_loading (struct ospf6_neighbor *);
extern void ospf6_neighbor_init (void);
extern int config_write_ospf6_debug_neighbor (struct vty *vty);

View File

@ -27,6 +27,7 @@
#include "sockopt.h"
#include "privs.h"
#include "libospf.h"
#include "ospf6_proto.h"
#include "ospf6_network.h"
@ -205,7 +206,7 @@ ospf6_sendmsg (struct in6_addr *src, struct in6_addr *dst,
smsghdr.msg_name = (caddr_t) &dst_sin6;
smsghdr.msg_namelen = sizeof (struct sockaddr_in6);
smsghdr.msg_control = (caddr_t) cmsgbuf;
smsghdr.msg_controllen = sizeof (cmsgbuf);
smsghdr.msg_controllen = scmsgp->cmsg_len;
retval = sendmsg (ospf6_sock, &smsghdr, 0);
if (retval != iov_totallen (message))

View File

@ -26,33 +26,12 @@
/* OSPF protocol version */
#define OSPFV3_VERSION 3
/* OSPF protocol number. */
#ifndef IPPROTO_OSPFIGP
#define IPPROTO_OSPFIGP 89
#endif
/* TOS field normaly null */
#define DEFAULT_TOS_VALUE 0x0
/* Architectural Constants */
#define LS_REFRESH_TIME 1800 /* 30 min */
#define MIN_LS_INTERVAL 5
#define MIN_LS_ARRIVAL 1
#define MAXAGE 3600 /* 1 hour */
#define CHECK_AGE 300 /* 5 min */
#define MAX_AGE_DIFF 900 /* 15 min */
#define LS_INFINITY 0xffffff /* 24-bit binary value */
#define INITIAL_SEQUENCE_NUMBER 0x80000001 /* signed 32-bit integer */
#define MAX_SEQUENCE_NUMBER 0x7fffffff /* signed 32-bit integer */
#define ALLSPFROUTERS6 "ff02::5"
#define ALLDROUTERS6 "ff02::6"
/* Configurable Constants */
#define DEFAULT_HELLO_INTERVAL 10
#define DEFAULT_ROUTER_DEAD_INTERVAL 40
#define OSPF6_ROUTER_BIT_W (1 << 3)
#define OSPF6_ROUTER_BIT_V (1 << 2)
#define OSPF6_ROUTER_BIT_E (1 << 1)

View File

@ -304,7 +304,7 @@ ospf6_route_lookup_bestmatch (struct prefix *prefix,
return route;
}
#ifndef NDEBUG
#ifdef DEBUG
static void
route_table_assert (struct ospf6_route_table *table)
{
@ -350,7 +350,7 @@ route_table_assert (struct ospf6_route_table *table)
#define ospf6_route_table_assert(t) (route_table_assert (t))
#else
#define ospf6_route_table_assert(t) ((void) 0)
#endif /*NDEBUG*/
#endif /*DEBUG*/
struct ospf6_route *
ospf6_route_add (struct ospf6_route *route,

View File

@ -377,6 +377,36 @@ ospf6_spf_table_finish (struct ospf6_route_table *result_table)
}
}
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)
{
int 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 */
/* RFC2740 3.8.1. Calculating the shortest path tree for an area */
void
@ -424,6 +454,11 @@ ospf6_spf_calculation (u_int32_t router_id,
if (ospf6_spf_install (v, result_table) < 0)
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 */
size = (VERTEX_IS_TYPE (ROUTER, v) ?
sizeof (struct ospf6_router_lsdesc) :
@ -506,39 +541,146 @@ static int
ospf6_spf_calculation_thread (struct thread *t)
{
struct ospf6_area *oa;
struct ospf6 *ospf6;
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);
oa->thread_spf_calculation = 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);
ospf6 = (struct ospf6 *)THREAD_ARG (t);
ospf6->t_spf_calc = NULL;
/* execute SPF calculation */
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);
timersub (&end, &start, &runtime);
ospf6->ts_spf_duration = runtime;
ospf6_spf_reason_string(ospf6->spf_reason, rbuf, sizeof(rbuf));
if (IS_OSPF6_DEBUG_SPF (PROCESS) || IS_OSPF6_DEBUG_SPF (TIME))
zlog_debug ("SPF runtime: %ld sec %ld usec",
runtime.tv_sec, runtime.tv_usec);
ospf6_intra_route_calculation (oa);
ospf6_intra_brouter_calculation (oa);
zlog_info("SPF processing: # Areas: %d, SPF runtime: %ld sec %ld usec, "
"Reason: %s\n", areas_processed, runtime.tv_sec, runtime.tv_usec,
rbuf);
ospf6->last_spf_reason = ospf6->spf_reason;
ospf6_reset_spf_reason(ospf6);
return 0;
}
/* Add schedule for SPF calculation. To avoid frequenst SPF calc, we
set timer for SPF calc. */
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;
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",
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
@ -666,6 +808,59 @@ DEFUN (no_debug_ospf6_spf_database,
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
config_write_ospf6_debug_spf (struct vty *vty)
{
@ -678,6 +873,19 @@ config_write_ospf6_debug_spf (struct vty *vty)
return 0;
}
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)
{
@ -698,6 +906,6 @@ install_element_ospf6_debug_spf (void)
void
ospf6_spf_init (void)
{
install_element (OSPF6_NODE, &ospf6_timers_throttle_spf_cmd);
install_element (OSPF6_NODE, &no_ospf6_timers_throttle_spf_cmd);
}

View File

@ -22,6 +22,8 @@
#ifndef OSPF6_SPF_H
#define OSPF6_SPF_H
#include "ospf6_top.h"
/* Debug option */
extern unsigned char conf_debug_ospf6_spf;
#define OSPF6_DEBUG_SPF_PROCESS 0x01
@ -77,18 +79,86 @@ struct ospf6_vertex
#define VERTEX_IS_TYPE(t, v) \
((v)->type == OSPF6_VERTEX_TYPE_ ## t ? 1 : 0)
/* What triggered the SPF? */
#define OSPF6_SPF_FLAGS_ROUTER_LSA_ADDED (1 << 0)
#define OSPF6_SPF_FLAGS_ROUTER_LSA_REMOVED (1 << 1)
#define OSPF6_SPF_FLAGS_NETWORK_LSA_ADDED (1 << 2)
#define OSPF6_SPF_FLAGS_NETWORK_LSA_REMOVED (1 << 3)
#define OSPF6_SPF_FLAGS_LINK_LSA_ADDED (1 << 4)
#define OSPF6_SPF_FLAGS_LINK_LSA_REMOVED (1 << 5)
#define OSPF6_SPF_FLAGS_ROUTER_LSA_ORIGINATED (1 << 6)
#define OSPF6_SPF_FLAGS_NETWORK_LSA_ORIGINATED (1 << 7)
static inline void
ospf6_set_spf_reason (struct ospf6* ospf, unsigned int reason)
{
ospf->spf_reason |= reason;
}
static inline void
ospf6_reset_spf_reason (struct ospf6 *ospf)
{
ospf->spf_reason = 0;
}
static inline unsigned int
ospf6_lsadd_to_spf_reason (struct ospf6_lsa *lsa)
{
unsigned int reason = 0;
switch (ntohs (lsa->header->type))
{
case OSPF6_LSTYPE_ROUTER:
reason = OSPF6_SPF_FLAGS_ROUTER_LSA_ADDED;
break;
case OSPF6_LSTYPE_NETWORK:
reason = OSPF6_SPF_FLAGS_NETWORK_LSA_ADDED;
break;
case OSPF6_LSTYPE_LINK:
reason = OSPF6_SPF_FLAGS_LINK_LSA_ADDED;
break;
default:
break;
}
return (reason);
}
static inline unsigned int
ospf6_lsremove_to_spf_reason (struct ospf6_lsa *lsa)
{
unsigned int reason = 0;
switch (ntohs (lsa->header->type))
{
case OSPF6_LSTYPE_ROUTER:
reason = OSPF6_SPF_FLAGS_ROUTER_LSA_REMOVED;
break;
case OSPF6_LSTYPE_NETWORK:
reason = OSPF6_SPF_FLAGS_NETWORK_LSA_REMOVED;
break;
case OSPF6_LSTYPE_LINK:
reason = OSPF6_SPF_FLAGS_LINK_LSA_REMOVED;
break;
default:
break;
}
return (reason);
}
extern void ospf6_spf_table_finish (struct ospf6_route_table *result_table);
extern void ospf6_spf_calculation (u_int32_t router_id,
struct ospf6_route_table *result_table,
struct ospf6_area *oa);
extern void ospf6_spf_schedule (struct ospf6_area *oa);
extern void ospf6_spf_schedule (struct ospf6 *ospf, unsigned int reason);
extern void ospf6_spf_display_subtree (struct vty *vty, const char *prefix,
int rest, struct ospf6_vertex *v);
extern void ospf6_spf_config_write (struct vty *vty);
extern int config_write_ospf6_debug_spf (struct vty *vty);
extern void install_element_ospf6_debug_spf (void);
extern void ospf6_spf_init (void);
extern void ospf6_spf_reason_string (unsigned int reason, char *buf, int size);
#endif /* OSPF6_SPF_H */

View File

@ -46,6 +46,7 @@
#include "ospf6_asbr.h"
#include "ospf6_abr.h"
#include "ospf6_intra.h"
#include "ospf6_spf.h"
#include "ospf6d.h"
/* global ospf6d variable */
@ -127,6 +128,11 @@ ospf6_create (void)
o->lsdb->hook_add = ospf6_top_lsdb_hook_add;
o->lsdb->hook_remove = ospf6_top_lsdb_hook_remove;
o->spf_delay = OSPF_SPF_DELAY_DEFAULT;
o->spf_holdtime = OSPF_SPF_HOLDTIME_DEFAULT;
o->spf_max_holdtime = OSPF_SPF_MAX_HOLDTIME_DEFAULT;
o->spf_hold_multiplier = 1;
o->route_table = OSPF6_ROUTE_TABLE_CREATE (GLOBAL, ROUTES);
o->route_table->scope = o;
o->route_table->hook_add = ospf6_top_route_hook_add;
@ -155,6 +161,8 @@ ospf6_delete (struct ospf6 *o)
for (ALL_LIST_ELEMENTS (o->area_list, node, nnode, oa))
ospf6_area_delete (oa);
list_delete (o->area_list);
ospf6_lsdb_delete (o->lsdb);
@ -196,13 +204,20 @@ ospf6_disable (struct ospf6 *o)
for (ALL_LIST_ELEMENTS (o->area_list, node, nnode, oa))
ospf6_area_disable (oa);
/* XXX: This also changes persistent settings */
ospf6_asbr_redistribute_reset();
ospf6_lsdb_remove_all (o->lsdb);
ospf6_route_remove_all (o->route_table);
ospf6_route_remove_all (o->brouter_table);
THREAD_OFF(o->maxage_remover);
THREAD_OFF(o->t_spf_calc);
THREAD_OFF(o->t_ase_calc);
}
}
static int
int
ospf6_maxage_remover (struct thread *thread)
{
struct ospf6 *o = (struct ospf6 *) THREAD_ARG (thread);
@ -210,6 +225,7 @@ ospf6_maxage_remover (struct thread *thread)
struct ospf6_interface *oi;
struct ospf6_neighbor *on;
struct listnode *i, *j, *k;
int reschedule = 0;
o->maxage_remover = (struct thread *) NULL;
@ -221,8 +237,9 @@ ospf6_maxage_remover (struct thread *thread)
{
if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
on->state != OSPF6_NEIGHBOR_LOADING)
continue;
continue;
ospf6_maxage_remove (o);
return 0;
}
}
@ -231,11 +248,28 @@ ospf6_maxage_remover (struct thread *thread)
for (ALL_LIST_ELEMENTS_RO (o->area_list, i, oa))
{
for (ALL_LIST_ELEMENTS_RO (oa->if_list, j, oi))
OSPF6_LSDB_MAXAGE_REMOVER (oi->lsdb);
{
if (ospf6_lsdb_maxage_remover (oi->lsdb))
{
reschedule = 1;
}
}
OSPF6_LSDB_MAXAGE_REMOVER (oa->lsdb);
if (ospf6_lsdb_maxage_remover (oa->lsdb))
{
reschedule = 1;
}
}
if (ospf6_lsdb_maxage_remover (o->lsdb))
{
reschedule = 1;
}
if (reschedule)
{
ospf6_maxage_remove (o);
}
OSPF6_LSDB_MAXAGE_REMOVER (o->lsdb);
return 0;
}
@ -244,7 +278,8 @@ void
ospf6_maxage_remove (struct ospf6 *o)
{
if (o && ! o->maxage_remover)
o->maxage_remover = thread_add_event (master, ospf6_maxage_remover, o, 0);
o->maxage_remover = thread_add_timer (master, ospf6_maxage_remover, o,
OSPF_LSA_MAXAGE_REMOVE_DELAY_DEFAULT);
}
/* start ospf6 */
@ -256,8 +291,6 @@ DEFUN (router_ospf6,
{
if (ospf6 == NULL)
ospf6 = ospf6_create ();
if (CHECK_FLAG (ospf6->flag, OSPF6_DISABLED))
ospf6_enable (ospf6);
/* set current ospf point. */
vty->node = OSPF6_NODE;
@ -273,10 +306,13 @@ DEFUN (no_router_ospf6,
NO_STR
OSPF6_ROUTER_STR)
{
if (ospf6 == NULL || CHECK_FLAG (ospf6->flag, OSPF6_DISABLED))
vty_out (vty, "OSPFv3 is not running%s", VNL);
if (ospf6 == NULL)
vty_out (vty, "OSPFv3 is not configured%s", VNL);
else
ospf6_disable (ospf6);
{
ospf6_delete (ospf6);
ospf6 = NULL;
}
/* return to config node . */
vty->node = CONFIG_NODE;
@ -312,6 +348,56 @@ DEFUN (ospf6_router_id,
return CMD_SUCCESS;
}
DEFUN (ospf6_log_adjacency_changes,
ospf6_log_adjacency_changes_cmd,
"log-adjacency-changes",
"Log changes in adjacency state\n")
{
struct ospf6 *ospf6 = vty->index;
SET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_CHANGES);
return CMD_SUCCESS;
}
DEFUN (ospf6_log_adjacency_changes_detail,
ospf6_log_adjacency_changes_detail_cmd,
"log-adjacency-changes detail",
"Log changes in adjacency state\n"
"Log all state changes\n")
{
struct ospf6 *ospf6 = vty->index;
SET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_CHANGES);
SET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_DETAIL);
return CMD_SUCCESS;
}
DEFUN (no_ospf6_log_adjacency_changes,
no_ospf6_log_adjacency_changes_cmd,
"no log-adjacency-changes",
NO_STR
"Log changes in adjacency state\n")
{
struct ospf6 *ospf6 = vty->index;
UNSET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_DETAIL);
UNSET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_CHANGES);
return CMD_SUCCESS;
}
DEFUN (no_ospf6_log_adjacency_changes_detail,
no_ospf6_log_adjacency_changes_detail_cmd,
"no log-adjacency-changes detail",
NO_STR
"Log changes in adjacency state\n"
"Log all state changes\n")
{
struct ospf6 *ospf6 = vty->index;
UNSET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_DETAIL);
return CMD_SUCCESS;
}
DEFUN (ospf6_interface_area,
ospf6_interface_area_cmd,
"interface IFNAME area A.B.C.D",
@ -359,8 +445,12 @@ DEFUN (ospf6_interface_area,
SET_FLAG (oa->flag, OSPF6_AREA_ENABLE);
/* ospf6 process is currently disabled, not much more to do */
if (CHECK_FLAG (o->flag, OSPF6_DISABLED))
return CMD_SUCCESS;
/* start up */
thread_add_event (master, interface_up, oi, 0);
ospf6_interface_enable (oi);
/* If the router is ABR, originate summary routes */
if (ospf6_is_router_abr (o))
@ -438,13 +528,109 @@ DEFUN (no_ospf6_interface_area,
return CMD_SUCCESS;
}
DEFUN (ospf6_stub_router_admin,
ospf6_stub_router_admin_cmd,
"stub-router administrative",
"Make router a stub router\n"
"Advertise inability to be a transit router\n"
"Administratively applied, for an indefinite period\n")
{
struct listnode *node;
struct ospf6_area *oa;
if (!CHECK_FLAG (ospf6->flag, OSPF6_STUB_ROUTER))
{
for (ALL_LIST_ELEMENTS_RO (ospf6->area_list, node, oa))
{
OSPF6_OPT_CLEAR (oa->options, OSPF6_OPT_V6);
OSPF6_OPT_CLEAR (oa->options, OSPF6_OPT_R);
OSPF6_ROUTER_LSA_SCHEDULE (oa);
}
SET_FLAG (ospf6->flag, OSPF6_STUB_ROUTER);
}
return CMD_SUCCESS;
}
DEFUN (no_ospf6_stub_router_admin,
no_ospf6_stub_router_admin_cmd,
"no stub-router administrative",
NO_STR
"Make router a stub router\n"
"Advertise ability to be a transit router\n"
"Administratively applied, for an indefinite period\n")
{
struct listnode *node;
struct ospf6_area *oa;
if (CHECK_FLAG (ospf6->flag, OSPF6_STUB_ROUTER))
{
for (ALL_LIST_ELEMENTS_RO (ospf6->area_list, node, oa))
{
OSPF6_OPT_SET (oa->options, OSPF6_OPT_V6);
OSPF6_OPT_SET (oa->options, OSPF6_OPT_R);
OSPF6_ROUTER_LSA_SCHEDULE (oa);
}
UNSET_FLAG (ospf6->flag, OSPF6_STUB_ROUTER);
}
return CMD_SUCCESS;
}
DEFUN (ospf6_stub_router_startup,
ospf6_stub_router_startup_cmd,
"stub-router on-startup <5-86400>",
"Make router a stub router\n"
"Advertise inability to be a transit router\n"
"Automatically advertise as stub-router on startup of OSPF6\n"
"Time (seconds) to advertise self as stub-router\n")
{
return CMD_SUCCESS;
}
DEFUN (no_ospf6_stub_router_startup,
no_ospf6_stub_router_startup_cmd,
"no stub-router on-startup",
NO_STR
"Make router a stub router\n"
"Advertise inability to be a transit router\n"
"Automatically advertise as stub-router on startup of OSPF6\n"
"Time (seconds) to advertise self as stub-router\n")
{
return CMD_SUCCESS;
}
DEFUN (ospf6_stub_router_shutdown,
ospf6_stub_router_shutdown_cmd,
"stub-router on-shutdown <5-86400>",
"Make router a stub router\n"
"Advertise inability to be a transit router\n"
"Automatically advertise as stub-router before shutdown\n"
"Time (seconds) to advertise self as stub-router\n")
{
return CMD_SUCCESS;
}
DEFUN (no_ospf6_stub_router_shutdown,
no_ospf6_stub_router_shutdown_cmd,
"no stub-router on-shutdown",
NO_STR
"Make router a stub router\n"
"Advertise inability to be a transit router\n"
"Automatically advertise as stub-router before shutdown\n"
"Time (seconds) to advertise self as stub-router\n")
{
return CMD_SUCCESS;
}
static void
ospf6_show (struct vty *vty, struct ospf6 *o)
{
struct listnode *n;
struct ospf6_area *oa;
char router_id[16], duration[32];
struct timeval now, running;
struct timeval now, running, result;
char buf[32], rbuf[32];
/* process id, router id */
inet_ntop (AF_INET, &o->router_id, router_id, sizeof (router_id));
@ -460,6 +646,35 @@ ospf6_show (struct vty *vty, struct ospf6 *o)
/* Redistribute configuration */
/* XXX */
/* Show SPF parameters */
vty_out(vty, " Initial SPF scheduling delay %d millisec(s)%s"
" Minimum hold time between consecutive SPFs %d millsecond(s)%s"
" Maximum hold time between consecutive SPFs %d millsecond(s)%s"
" Hold time multiplier is currently %d%s",
o->spf_delay, VNL,
o->spf_holdtime, VNL,
o->spf_max_holdtime, VNL,
o->spf_hold_multiplier, VNL);
vty_out(vty, " SPF algorithm ");
if (o->ts_spf.tv_sec || o->ts_spf.tv_usec)
{
timersub(&now, &o->ts_spf, &result);
timerstring(&result, buf, sizeof(buf));
ospf6_spf_reason_string(o->last_spf_reason, rbuf, sizeof(rbuf));
vty_out(vty, "last executed %s ago, reason %s%s", buf, rbuf, VNL);
vty_out (vty, " Last SPF duration %ld sec %ld usec%s",
o->ts_spf_duration.tv_sec, o->ts_spf_duration.tv_usec, VNL);
}
else
vty_out(vty, "has not been run$%s", VNL);
threadtimer_string(now, o->t_spf_calc, buf, sizeof(buf));
vty_out (vty, " SPF timer %s%s%s",
(o->t_spf_calc ? "due in " : "is "), buf, VNL);
if (CHECK_FLAG (o->flag, OSPF6_STUB_ROUTER))
vty_out (vty, " Router Is Stub Router%s", VNL);
/* LSAs */
vty_out (vty, " Number of AS scoped LSAs is %u%s",
o->lsdb->count, VNL);
@ -468,6 +683,16 @@ ospf6_show (struct vty *vty, struct ospf6 *o)
vty_out (vty, " Number of areas in this router is %u%s",
listcount (o->area_list), VNL);
if (CHECK_FLAG(o->config_flags, OSPF6_LOG_ADJACENCY_CHANGES))
{
if (CHECK_FLAG(o->config_flags, OSPF6_LOG_ADJACENCY_DETAIL))
vty_out(vty, " All adjacency changes are logged%s",VTY_NEWLINE);
else
vty_out(vty, " Adjacency changes are logged%s",VTY_NEWLINE);
}
vty_out (vty, "%s",VTY_NEWLINE);
for (ALL_LIST_ELEMENTS_RO (o->area_list, n, oa))
ospf6_area_show (vty, oa);
}
@ -628,6 +853,16 @@ DEFUN (show_ipv6_ospf6_route_type_detail,
return CMD_SUCCESS;
}
static void
ospf6_stub_router_config_write (struct vty *vty)
{
if (CHECK_FLAG (ospf6->flag, OSPF6_STUB_ROUTER))
{
vty_out (vty, " stub-router administrative%s", VNL);
}
return;
}
/* OSPF configuration write function. */
static int
config_write_ospf6 (struct vty *vty)
@ -640,16 +875,25 @@ config_write_ospf6 (struct vty *vty)
/* OSPFv6 configuration. */
if (ospf6 == NULL)
return CMD_SUCCESS;
if (CHECK_FLAG (ospf6->flag, OSPF6_DISABLED))
return CMD_SUCCESS;
inet_ntop (AF_INET, &ospf6->router_id_static, router_id, sizeof (router_id));
vty_out (vty, "router ospf6%s", VNL);
if (ospf6->router_id_static != 0)
vty_out (vty, " router-id %s%s", router_id, VNL);
/* log-adjacency-changes flag print. */
if (CHECK_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_CHANGES))
{
vty_out(vty, " log-adjacency-changes");
if (CHECK_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_DETAIL))
vty_out(vty, " detail");
vty_out(vty, "%s", VTY_NEWLINE);
}
ospf6_stub_router_config_write (vty);
ospf6_redistribute_config_write (vty);
ospf6_area_config_write (vty);
ospf6_spf_config_write (vty);
for (ALL_LIST_ELEMENTS_RO (ospf6->area_list, j, oa))
{
@ -700,8 +944,20 @@ ospf6_top_init (void)
install_default (OSPF6_NODE);
install_element (OSPF6_NODE, &ospf6_router_id_cmd);
install_element (OSPF6_NODE, &ospf6_log_adjacency_changes_cmd);
install_element (OSPF6_NODE, &ospf6_log_adjacency_changes_detail_cmd);
install_element (OSPF6_NODE, &no_ospf6_log_adjacency_changes_cmd);
install_element (OSPF6_NODE, &no_ospf6_log_adjacency_changes_detail_cmd);
install_element (OSPF6_NODE, &ospf6_interface_area_cmd);
install_element (OSPF6_NODE, &no_ospf6_interface_area_cmd);
install_element (OSPF6_NODE, &ospf6_stub_router_admin_cmd);
install_element (OSPF6_NODE, &no_ospf6_stub_router_admin_cmd);
/* For a later time
install_element (OSPF6_NODE, &ospf6_stub_router_startup_cmd);
install_element (OSPF6_NODE, &no_ospf6_stub_router_startup_cmd);
install_element (OSPF6_NODE, &ospf6_stub_router_shutdown_cmd);
install_element (OSPF6_NODE, &no_ospf6_stub_router_shutdown_cmd);
*/
}

View File

@ -38,6 +38,7 @@ struct ospf6
/* list of areas */
struct list *area_list;
struct ospf6_area *backbone;
/* AS scope link state database */
struct ospf6_lsdb *lsdb;
@ -59,10 +60,30 @@ struct ospf6
u_char flag;
/* Configured flags */
u_char config_flags;
#define OSPF6_LOG_ADJACENCY_CHANGES (1 << 0)
#define OSPF6_LOG_ADJACENCY_DETAIL (1 << 1)
/* SPF parameters */
unsigned int spf_delay; /* SPF delay time. */
unsigned int spf_holdtime; /* SPF hold time. */
unsigned int spf_max_holdtime; /* SPF maximum-holdtime */
unsigned int spf_hold_multiplier; /* Adaptive multiplier for hold time */
unsigned int spf_reason; /* reason bits while scheduling SPF */
struct timeval ts_spf; /* SPF calculation time stamp. */
struct timeval ts_spf_duration; /* Execution time of last SPF */
unsigned int last_spf_reason; /* Last SPF reason */
/* Threads */
struct thread *t_spf_calc; /* SPF calculation timer. */
struct thread *t_ase_calc; /* ASE calculation timer. */
struct thread *maxage_remover;
};
#define OSPF6_DISABLED 0x01
#define OSPF6_STUB_ROUTER 0x02
/* global pointer for OSPF top data structure */
extern struct ospf6 *ospf6;

View File

@ -117,7 +117,9 @@ ospf6_zebra_if_del (int command, struct zclient *zclient, zebra_size_t length)
ifp->name, ifp->ifindex, ifp->mtu6);
#if 0
/* Why is this commented out? */
/* XXX: ospf6_interface_if_del is not the right way to handle this,
* because among other thinkable issues, it will also clear all
* settings as they are contained in the struct ospf6_interface. */
ospf6_interface_if_del (ifp);
#endif /*0*/
@ -163,8 +165,10 @@ ospf6_zebra_if_address_update_add (int command, struct zclient *zclient,
buf, sizeof (buf)), c->address->prefixlen);
if (c->address->family == AF_INET6)
ospf6_interface_connected_route_update (c->ifp);
{
ospf6_interface_state_update (c->ifp);
ospf6_interface_connected_route_update (c->ifp);
}
return 0;
}
@ -186,7 +190,10 @@ ospf6_zebra_if_address_update_delete (int command, struct zclient *zclient,
buf, sizeof (buf)), c->address->prefixlen);
if (c->address->family == AF_INET6)
ospf6_interface_connected_route_update (c->ifp);
{
ospf6_interface_connected_route_update (c->ifp);
ospf6_interface_state_update (c->ifp);
}
return 0;
}

View File

@ -24,6 +24,9 @@
#define OSPF6_DAEMON_VERSION "0.9.7r"
#include "libospf.h"
#include "thread.h"
/* global variables */
extern struct thread_master *master;
@ -98,6 +101,17 @@ extern struct thread_master *master;
zlog_warn ("strftime error"); \
} while (0)
#define threadtimer_string(now, t, buf, size) \
do { \
struct timeval result; \
if (!t) \
snprintf(buf, size, "inactive"); \
else { \
timersub(&t->u.sands, &now, &result); \
timerstring(&result, buf, size); \
} \
} while (0)
/* for commands */
#define OSPF6_AREA_STR "Area information\n"
#define OSPF6_AREA_ID_STR "Area ID (as an IPv4 notation)\n"

View File

@ -140,14 +140,6 @@ struct ospf_interface
/* OSPF Network Type. */
u_char type;
#define OSPF_IFTYPE_NONE 0
#define OSPF_IFTYPE_POINTOPOINT 1
#define OSPF_IFTYPE_BROADCAST 2
#define OSPF_IFTYPE_NBMA 3
#define OSPF_IFTYPE_POINTOMULTIPOINT 4
#define OSPF_IFTYPE_VIRTUALLINK 5
#define OSPF_IFTYPE_LOOPBACK 6
#define OSPF_IFTYPE_MAX 7
/* State of Interface State Machine. */
u_char state;

View File

@ -200,7 +200,7 @@ ospf_new (void)
new->spf_hold_multiplier = 1;
/* MaxAge init. */
new->maxage_delay = OSFP_LSA_MAXAGE_REMOVE_DELAY_DEFAULT;
new->maxage_delay = OSPF_LSA_MAXAGE_REMOVE_DELAY_DEFAULT;
new->maxage_lsa = route_table_init();
new->t_maxage_walker =
thread_add_timer (master, ospf_lsa_maxage_walker,

View File

@ -24,22 +24,13 @@
#define _ZEBRA_OSPFD_H
#include <zebra.h>
#include "libospf.h"
#include "filter.h"
#include "log.h"
#define OSPF_VERSION 2
/* Default protocol, port number. */
#ifndef IPPROTO_OSPFIGP
#define IPPROTO_OSPFIGP 89
#endif /* IPPROTO_OSPFIGP */
/* IP precedence. */
#ifndef IPTOS_PREC_INTERNETCONTROL
#define IPTOS_PREC_INTERNETCONTROL 0xC0
#endif /* IPTOS_PREC_INTERNETCONTROL */
/* VTY port number. */
#define OSPF_VTY_PORT 2604
@ -50,29 +41,11 @@
/* Default configuration file name for ospfd. */
#define OSPF_DEFAULT_CONFIG "ospfd.conf"
/* Architectual Constants */
#ifdef DEBUG
#define OSPF_LS_REFRESH_TIME 60
#else
#define OSPF_LS_REFRESH_TIME 1800
#endif
#define OSPF_MIN_LS_INTERVAL 5
#define OSPF_MIN_LS_ARRIVAL 1
#define OSPF_LSA_INITIAL_AGE 0 /* useful for debug */
#define OSPF_LSA_MAXAGE 3600
#define OSPF_CHECK_AGE 300
#define OSPF_LSA_MAXAGE_DIFF 900
#define OSPF_LS_INFINITY 0xffffff
#define OSPF_DEFAULT_DESTINATION 0x00000000 /* 0.0.0.0 */
#define OSPF_INITIAL_SEQUENCE_NUMBER 0x80000001
#define OSPF_MAX_SEQUENCE_NUMBER 0x7fffffff
#define OSPF_NSSA_TRANS_STABLE_DEFAULT 40
#define OSPF_ALLSPFROUTERS 0xe0000005 /* 224.0.0.5 */
#define OSPF_ALLDROUTERS 0xe0000006 /* 224.0.0.6 */
#define OSPF_AREA_BACKBONE 0x00000000 /* 0.0.0.0 */
/* OSPF Authentication Type. */
#define OSPF_AUTH_NULL 0
@ -85,30 +58,6 @@
been given or not in VLink command handlers */
#define OSPF_AUTH_CMD_NOTSEEN -2
/* OSPF SPF timer values. */
#define OSPF_SPF_DELAY_DEFAULT 200
#define OSPF_SPF_HOLDTIME_DEFAULT 1000
#define OSPF_SPF_MAX_HOLDTIME_DEFAULT 10000
/* OSPF interface default values. */
#define OSPF_OUTPUT_COST_DEFAULT 10
#define OSPF_OUTPUT_COST_INFINITE UINT16_MAX
#define OSPF_ROUTER_DEAD_INTERVAL_DEFAULT 40
#define OSPF_ROUTER_DEAD_INTERVAL_MINIMAL 1
#define OSPF_HELLO_INTERVAL_DEFAULT 10
#define OSPF_ROUTER_PRIORITY_DEFAULT 1
#define OSPF_RETRANSMIT_INTERVAL_DEFAULT 5
#define OSPF_TRANSMIT_DELAY_DEFAULT 1
#define OSPF_DEFAULT_BANDWIDTH 10000 /* Kbps */
#define OSPF_DEFAULT_REF_BANDWIDTH 100000 /* Kbps */
#define OSPF_POLL_INTERVAL_DEFAULT 60
#define OSPF_NEIGHBOR_PRIORITY_DEFAULT 0
#define OSPF_MTU_IGNORE_DEFAULT 0
#define OSPF_FAST_HELLO_DEFAULT 0
/* OSPF options. */
#define OSPF_OPTION_T 0x01 /* TOS. */
#define OSPF_OPTION_E 0x02
@ -262,10 +211,8 @@ struct ospf
struct thread *t_opaque_lsa_self; /* Type-11 Opaque-LSAs origin event. */
#endif /* HAVE_OPAQUE_LSA */
#define OSFP_LSA_MAXAGE_REMOVE_DELAY_DEFAULT 60
unsigned int maxage_delay; /* Delay on Maxage remover timer, sec */
struct thread *t_maxage; /* MaxAge LSA remover timer. */
#define OSPF_LSA_MAXAGE_CHECK_INTERVAL 30
struct thread *t_maxage_walker; /* MaxAge LSA checking timer. */
struct thread *t_deferred_shutdown; /* deferred/stub-router shutdown timer*/