Merge volatile/cumulus_ospf6d
Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
diff --git a/doc/ospf6d.texi b/doc/ospf6d.texi
index 6667221..d981820 100644
--- a/doc/ospf6d.texi
+++ b/doc/ospf6d.texi
@@ -28,6 +28,44 @@
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 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
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 44d95bb..bd21092 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -27,7 +27,7 @@
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 \
diff --git a/lib/if.c b/lib/if.c
index e26aa04..6348403 100644
--- a/lib/if.c
+++ b/lib/if.c
@@ -304,6 +304,30 @@
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 *
diff --git a/lib/if.h b/lib/if.h
index 13cc254..8081be8 100644
--- a/lib/if.h
+++ b/lib/if.h
@@ -245,6 +245,7 @@
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: */
diff --git a/lib/libospf.h b/lib/libospf.h
new file mode 100644
index 0000000..856c76d
--- /dev/null
+++ b/lib/libospf.h
@@ -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 */
diff --git a/ospf6d/ospf6_abr.c b/ospf6d/ospf6_abr.c
index c3a63fe..54404ab 100644
--- a/ospf6d/ospf6_abr.c
+++ b/ospf6d/ospf6_abr.c
@@ -253,7 +253,7 @@
}
/* 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 @@
/* 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 @@
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 @@
}
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 @@
}
/* (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 @@
}
/* (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_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 @@
/* 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 @@
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 @@
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 @@
{
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
diff --git a/ospf6d/ospf6_area.c b/ospf6d/ospf6_area.c
index 9934e6b..9a4e30e 100644
--- a/ospf6d/ospf6_area.c
+++ b/ospf6d/ospf6_area.c
@@ -67,7 +67,8 @@
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 @@
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 @@
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 @@
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 @@
for (ALL_LIST_ELEMENTS (oa->if_list, node, nnode, oi))
ospf6_interface_enable (oi);
+ ospf6_abr_enable_area (oa);
}
void
@@ -258,6 +273,19 @@
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 @@
}
ospf6_route_remove (range, oa->range_table);
+
return CMD_SUCCESS;
}
diff --git a/ospf6d/ospf6_area.h b/ospf6d/ospf6_area.h
index e8a4fbd..655967a 100644
--- a/ospf6d/ospf6_area.h
+++ b/ospf6d/ospf6_area.h
@@ -105,8 +105,6 @@
#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))
diff --git a/ospf6d/ospf6_asbr.c b/ospf6d/ospf6_asbr.c
index ae0a286..3605e3f 100644
--- a/ospf6d/ospf6_asbr.c
+++ b/ospf6d/ospf6_asbr.c
@@ -174,13 +174,20 @@
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_remove (info->type, route->nexthop[0].ifindex,
&route->prefix);
}
+
+ ospf6_asbr_routemap_unset (type);
}
void
@@ -629,7 +638,6 @@
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 @@
return CMD_WARNING;
ospf6_asbr_redistribute_unset (type);
- ospf6_asbr_routemap_unset (type);
return CMD_SUCCESS;
}
@@ -890,7 +897,7 @@
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 @@
/* 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 @@
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 @@
{
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
@@ -1276,6 +1313,20 @@
}
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)
{
route_map_finish ();
diff --git a/ospf6d/ospf6_asbr.h b/ospf6d/ospf6_asbr.h
index 72e4914..73770cc 100644
--- a/ospf6d/ospf6_asbr.h
+++ b/ospf6d/ospf6_asbr.h
@@ -89,6 +89,7 @@
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);
diff --git a/ospf6d/ospf6_flood.c b/ospf6d/ospf6_flood.c
index b815972..49ed6e2 100644
--- a/ospf6d/ospf6_flood.c
+++ b/ospf6d/ospf6_flood.c
@@ -113,7 +113,7 @@
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_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 @@
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 @@
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 @@
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 @@
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 @@
/* (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 @@
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 @@
{
/* 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 @@
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 @@
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 @@
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 @@
/* 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 @@
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;
}
diff --git a/ospf6d/ospf6_interface.c b/ospf6d/ospf6_interface.c
index 40cda24..b0f1119 100644
--- a/ospf6d/ospf6_interface.c
+++ b/ospf6d/ospf6_interface.c
@@ -73,14 +73,20 @@
/* 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 @@
}
}
+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 @@
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 @@
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 @@
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 @@
}
/* interface start */
- if (oi->area)
- thread_add_event (master, interface_up, oi, 0);
+ ospf6_interface_state_update(oi->interface);
}
void
@@ -297,8 +323,12 @@
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 @@
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 @@
(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 @@
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 @@
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 @@
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 @@
/* 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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,
diff --git a/ospf6d/ospf6_interface.h b/ospf6d/ospf6_interface.h
index d80b073..808f096 100644
--- a/ospf6d/ospf6_interface.h
+++ b/ospf6d/ospf6_interface.h
@@ -56,6 +56,9 @@
/* I/F transmission delay */
u_int32_t transdelay;
+ /* Network Type */
+ u_char type;
+
/* Router Priority */
u_char priority;
diff --git a/ospf6d/ospf6_intra.c b/ospf6d/ospf6_intra.c
index 9bc603b..4ad7521 100644
--- a/ospf6d/ospf6_intra.c
+++ b/ospf6d/ospf6_intra.c
@@ -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 @@
/* 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)
{
@@ -105,6 +141,29 @@
}
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)
{
struct ospf6_area *oa;
@@ -215,7 +274,7 @@
}
/* 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 @@
}
/* 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 @@
lsdesc++;
}
+ else
+ {
+ assert (0); /* Unknown interface type */
+ }
/* Virtual links */
/* xxx */
@@ -268,35 +331,26 @@
/* 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 @@
/* 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 @@
/* 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 @@
/*****************************************/
/* 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 @@
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 @@
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 @@
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 @@
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 @@
! 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 @@
{
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
diff --git a/ospf6d/ospf6_intra.h b/ospf6d/ospf6_intra.h
index 3810174..e909da2 100644
--- a/ospf6d/ospf6_intra.h
+++ b/ospf6d/ospf6_intra.h
@@ -94,6 +94,13 @@
#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 @@
#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_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 *);
diff --git a/ospf6d/ospf6_lsa.c b/ospf6d/ospf6_lsa.c
index ff061df..4aa2b12 100644
--- a/ospf6d/ospf6_lsa.c
+++ b/ospf6d/ospf6_lsa.c
@@ -75,7 +75,9 @@
{
OSPF6_LSTYPE_UNKNOWN,
"Unknown",
+ "Unk",
ospf6_unknown_lsa_show,
+ NULL,
OSPF6_LSA_DEBUG,
};
@@ -118,6 +120,20 @@
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_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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
{
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 @@
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 @@
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 @@
copy->received = lsa->received;
copy->installed = lsa->installed;
copy->lsdb = lsa->lsdb;
+ copy->rn = NULL;
return copy;
}
@@ -608,12 +682,12 @@
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 @@
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_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 @@
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 @@
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 @@
{
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 @@
{
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 @@
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 @@
{
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 @@
{
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 @@
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 @@
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",
diff --git a/ospf6d/ospf6_lsa.h b/ospf6d/ospf6_lsa.h
index 263411f..aed89df 100644
--- a/ospf6d/ospf6_lsa.h
+++ b/ospf6d/ospf6_lsa.h
@@ -107,15 +107,16 @@
((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 @@
#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 @@
/* 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);
diff --git a/ospf6d/ospf6_lsdb.c b/ospf6d/ospf6_lsdb.c
index 280bdf9..707afc6 100644
--- a/ospf6d/ospf6_lsdb.c
+++ b/ospf6d/ospf6_lsdb.c
@@ -54,9 +54,12 @@
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 @@
key->prefixlen += len * 8;
}
-#ifndef NDEBUG
+#ifdef DEBUG
static void
_lsdb_count_assert (struct ospf6_lsdb *lsdb)
{
@@ -94,16 +97,16 @@
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,56 +117,26 @@
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))
{
if (OSPF6_LSA_IS_MAXAGE (lsa))
@@ -187,20 +160,8 @@
(*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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
if (node == NULL)
return NULL;
- else
- route_unlock_node (node);
if (! prefix_match ((struct prefix *) &key, &node->p))
return NULL;
@@ -406,18 +358,19 @@
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 @@
if (node == NULL)
return NULL;
- else
- route_unlock_node (node);
if (! prefix_match ((struct prefix *) &key, &node->p))
return NULL;
@@ -459,17 +410,18 @@
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,11 +429,62 @@
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,
struct ospf6_lsdb *lsdb)
@@ -551,7 +554,7 @@
continue;
if (ntohl (lsa->header->id) > id)
{
- ospf6_lsa_unlock (lsa);
+ ospf6_lsdb_lsa_unlock (lsa);
break;
}
id++;
@@ -572,7 +575,7 @@
/* 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;
diff --git a/ospf6d/ospf6_lsdb.h b/ospf6d/ospf6_lsdb.h
index 71297da..a124adb 100644
--- a/ospf6d/ospf6_lsdb.h
+++ b/ospf6d/ospf6_lsdb.h
@@ -34,21 +34,6 @@
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 @@
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_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 */
diff --git a/ospf6d/ospf6_main.c b/ospf6d/ospf6_main.c
index 17d7654..e991971 100644
--- a/ospf6d/ospf6_main.c
+++ b/ospf6d/ospf6_main.c
@@ -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 @@
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 ();
diff --git a/ospf6d/ospf6_message.c b/ospf6d/ospf6_message.c
index 5edb70c..5fb5a21 100644
--- a/ospf6d/ospf6_message.c
+++ b/ospf6d/ospf6_message.c
@@ -517,20 +517,20 @@
{
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 @@
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 @@
{
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 @@
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 @@
{
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 @@
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 @@
}
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 @@
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 @@
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 @@
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 @@
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 @@
{
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 @@
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 @@
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 @@
/* 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 @@
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 @@
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 @@
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 @@
{
/* 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 @@
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 @@
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 @@
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 @@
{
/* 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 @@
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);
+ 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);
+ }
+
return 0;
}
@@ -2200,6 +2250,7 @@
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 @@
{
/* 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 @@
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)
{
diff --git a/ospf6d/ospf6_neighbor.c b/ospf6d/ospf6_neighbor.c
index 806767d..fb209fd 100644
--- a/ospf6d/ospf6_neighbor.c
+++ b/ospf6d/ospf6_neighbor.c
@@ -98,7 +98,6 @@
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_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_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 @@
}
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 @@
/* 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 @@
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 @@
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 @@
}
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 @@
*/
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 @@
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 @@
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 @@
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 @@
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 @@
}
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 @@
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 @@
}
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 @@
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 @@
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 @@
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);
diff --git a/ospf6d/ospf6_neighbor.h b/ospf6d/ospf6_neighbor.h
index 5f46c6f..8882189 100644
--- a/ospf6d/ospf6_neighbor.h
+++ b/ospf6d/ospf6_neighbor.h
@@ -86,6 +86,8 @@
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 @@
#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 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);
diff --git a/ospf6d/ospf6_network.c b/ospf6d/ospf6_network.c
index e5a1436..74cfbec 100644
--- a/ospf6d/ospf6_network.c
+++ b/ospf6d/ospf6_network.c
@@ -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 @@
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))
diff --git a/ospf6d/ospf6_proto.h b/ospf6d/ospf6_proto.h
index 6462500..af60eb9 100644
--- a/ospf6d/ospf6_proto.h
+++ b/ospf6d/ospf6_proto.h
@@ -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)
diff --git a/ospf6d/ospf6_route.c b/ospf6d/ospf6_route.c
index 398acfa..5f1869a 100644
--- a/ospf6d/ospf6_route.c
+++ b/ospf6d/ospf6_route.c
@@ -304,7 +304,7 @@
return route;
}
-#ifndef NDEBUG
+#ifdef DEBUG
static void
route_table_assert (struct ospf6_route_table *table)
{
@@ -350,7 +350,7 @@
#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,
diff --git a/ospf6d/ospf6_spf.c b/ospf6d/ospf6_spf.c
index da0ee13..3ef5485 100644
--- a/ospf6d/ospf6_spf.c
+++ b/ospf6d/ospf6_spf.c
@@ -377,6 +377,36 @@
}
}
+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 @@
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 @@
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 @@
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)
{
@@ -679,6 +874,19 @@
}
void
+ospf6_spf_config_write (struct vty *vty)
+{
+
+ if (ospf6->spf_delay != OSPF_SPF_DELAY_DEFAULT ||
+ ospf6->spf_holdtime != OSPF_SPF_HOLDTIME_DEFAULT ||
+ ospf6->spf_max_holdtime != OSPF_SPF_MAX_HOLDTIME_DEFAULT)
+ vty_out (vty, " timers throttle spf %d %d %d%s",
+ ospf6->spf_delay, ospf6->spf_holdtime,
+ ospf6->spf_max_holdtime, VTY_NEWLINE);
+
+}
+
+void
install_element_ospf6_debug_spf (void)
{
install_element (ENABLE_NODE, &debug_ospf6_spf_process_cmd);
@@ -698,6 +906,6 @@
void
ospf6_spf_init (void)
{
+ install_element (OSPF6_NODE, &ospf6_timers_throttle_spf_cmd);
+ install_element (OSPF6_NODE, &no_ospf6_timers_throttle_spf_cmd);
}
-
-
diff --git a/ospf6d/ospf6_spf.h b/ospf6d/ospf6_spf.h
index c7069c2..b3481dc 100644
--- a/ospf6d/ospf6_spf.h
+++ b/ospf6d/ospf6_spf.h
@@ -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 @@
#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 */
diff --git a/ospf6d/ospf6_top.c b/ospf6d/ospf6_top.c
index df856b4..7c0922a 100644
--- a/ospf6d/ospf6_top.c
+++ b/ospf6d/ospf6_top.c
@@ -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 @@
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 @@
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 @@
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 @@
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 @@
{
if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
on->state != OSPF6_NEIGHBOR_LOADING)
- continue;
+ continue;
+ ospf6_maxage_remove (o);
return 0;
}
}
@@ -231,11 +248,28 @@
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;
+ }
}
- OSPF6_LSDB_MAXAGE_REMOVER (o->lsdb);
+
+ if (ospf6_lsdb_maxage_remover (o->lsdb))
+ {
+ reschedule = 1;
+ }
+
+ if (reschedule)
+ {
+ ospf6_maxage_remove (o);
+ }
return 0;
}
@@ -244,7 +278,8 @@
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 @@
{
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 @@
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 @@
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 @@
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 @@
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 @@
/* 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 @@
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 @@
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 @@
/* 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 @@
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);
+ */
}
diff --git a/ospf6d/ospf6_top.h b/ospf6d/ospf6_top.h
index 4b2d2c3..866f92f 100644
--- a/ospf6d/ospf6_top.h
+++ b/ospf6d/ospf6_top.h
@@ -38,6 +38,7 @@
/* list of areas */
struct list *area_list;
+ struct ospf6_area *backbone;
/* AS scope link state database */
struct ospf6_lsdb *lsdb;
@@ -59,10 +60,30 @@
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;
diff --git a/ospf6d/ospf6_zebra.c b/ospf6d/ospf6_zebra.c
index f09e9d2..cffd767 100644
--- a/ospf6d/ospf6_zebra.c
+++ b/ospf6d/ospf6_zebra.c
@@ -117,7 +117,9 @@
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 @@
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 @@
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;
}
diff --git a/ospf6d/ospf6d.h b/ospf6d/ospf6d.h
index 2ac6300..0c86386 100644
--- a/ospf6d/ospf6d.h
+++ b/ospf6d/ospf6d.h
@@ -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 @@
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"
diff --git a/ospfd/ospf_interface.h b/ospfd/ospf_interface.h
index 9de6550..ed698c8 100644
--- a/ospfd/ospf_interface.h
+++ b/ospfd/ospf_interface.h
@@ -140,14 +140,6 @@
/* 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;
diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c
index 3e2b234..538bc09 100644
--- a/ospfd/ospfd.c
+++ b/ospfd/ospfd.c
@@ -200,7 +200,7 @@
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,
diff --git a/ospfd/ospfd.h b/ospfd/ospfd.h
index fb57bf5..4242aa0 100644
--- a/ospfd/ospfd.h
+++ b/ospfd/ospfd.h
@@ -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 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*/