SVN revisions 916-920 from Zebra. ABR support is almost done.
diff --git a/ospf6d/ChangeLog b/ospf6d/ChangeLog
index e9fe119..52f4cef 100644
--- a/ospf6d/ChangeLog
+++ b/ospf6d/ChangeLog
@@ -1,3 +1,25 @@
+2004-08-15 Yasuhiro Ohara <yasu@sfc.wide.ad.jp>
+
+ * *.c: Area support almost done. (almost ! ;p)
+ * ospf6d.h: version 0.9.7i
+
+2004-08-15 Yasuhiro Ohara <yasu@sfc.wide.ad.jp>
+
+ * ospf6_message.c: Bug cause BadLSReq is fixed.
+ * ospf6_abr.c: Border Router check.
+ * ospf6d.h: version 0.9.7h
+
+2004-08-14 Yasuhiro Ohara <yasu@sfc.wide.ad.jp>
+
+ * ospf6_area.[ch], ospf6_abr.[ch]: area range,
+ border-routers, Inter-Area-Router-LSA origination
+ * ospf6d.h: version 0.9.7g
+
+2004-08-12 Yasuhiro Ohara <yasu@sfc.wide.ad.jp>
+
+ * *.[c,h]: LSA refreshing is changed and cleaned up.
+ * ospf6d.h: version 0.9.7f
+
2004-08-01 Yasuhiro Ohara <yasu@sfc.wide.ad.jp>
* ospf6_abr.[ch]: add files for abr function.
diff --git a/ospf6d/ospf6_abr.c b/ospf6d/ospf6_abr.c
index 04a55c4..397cef7 100644
--- a/ospf6d/ospf6_abr.c
+++ b/ospf6d/ospf6_abr.c
@@ -34,18 +34,42 @@
#include "ospf6_lsa.h"
#include "ospf6_route.h"
#include "ospf6_lsdb.h"
+#include "ospf6_message.h"
+
#include "ospf6_top.h"
#include "ospf6_area.h"
#include "ospf6_interface.h"
+#include "ospf6_neighbor.h"
+
#include "ospf6_abr.h"
+#include "ospf6_flood.h"
#include "ospf6d.h"
unsigned char conf_debug_ospf6_abr;
+int
+ospf6_is_router_abr (struct ospf6 *o)
+{
+ listnode node;
+ struct ospf6_area *oa;
+ int area_count = 0;
+
+ for (node = listhead (o->area_list); node; nextnode (node))
+ {
+ oa = OSPF6_AREA (getdata (node));
+ if (IS_AREA_ENABLED (oa))
+ area_count++;
+ }
+
+ if (area_count > 1)
+ return 1;
+ return 0;
+}
+
/* RFC 2328 12.4.3. Summary-LSAs */
void
-ospf6_abr_originate_prefix_to_area (struct ospf6_route *route,
- struct ospf6_area *area)
+ospf6_abr_originate_summary_to_area (struct ospf6_route *route,
+ struct ospf6_area *area)
{
struct ospf6_lsa *lsa, *old = NULL;
struct ospf6_interface *oi;
@@ -55,26 +79,63 @@
struct ospf6_lsa_header *lsa_header;
caddr_t p;
struct ospf6_inter_prefix_lsa *prefix_lsa;
+ struct ospf6_inter_router_lsa *router_lsa;
+ struct ospf6_route_table *summary_table = NULL;
+ u_int16_t type;
- summary = ospf6_route_lookup (&route->prefix, area->summary_table);
+ if (IS_OSPF6_DEBUG_ABR)
+ {
+ char buf[64];
+ if (route->type == OSPF6_DEST_TYPE_ROUTER)
+ {
+ inet_ntop (AF_INET,
+ &(ospf6_linkstate_prefix_adv_router (&route->prefix)),
+ buf, sizeof (buf));
+ zlog_info ("Originating summary in area %s for ASBR %s",
+ area->name, buf);
+ }
+ else
+ {
+ prefix2str (&route->prefix, buf, sizeof (buf));
+ zlog_info ("Originating summary in area %s for %s",
+ area->name, buf);
+ }
+ }
+
+ if (route->type == OSPF6_DEST_TYPE_ROUTER)
+ summary_table = area->summary_router;
+ else
+ summary_table = area->summary_prefix;
+ summary = ospf6_route_lookup (&route->prefix, summary_table);
if (summary)
- old = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_INTER_PREFIX),
+ old = ospf6_lsdb_lookup (summary->path.origin.type,
summary->path.origin.id,
area->ospf6->router_id, area->lsdb);
/* if this route has just removed, remove corresponding LSA */
if (CHECK_FLAG (route->flag, OSPF6_ROUTE_REMOVE))
{
+ if (IS_OSPF6_DEBUG_ABR)
+ zlog_info ("The route has just removed, purge previous LSA");
+ if (summary)
+ ospf6_route_remove (summary, summary_table);
if (old)
- ospf6_lsa_premature_aging (old);
+ ospf6_lsa_purge (old);
return;
}
- /* Only destination type network and address range are considered */
- if (route->type != OSPF6_DEST_TYPE_NETWORK)
+ /* Only destination type network, range or ASBR are considered */
+ if (route->type != OSPF6_DEST_TYPE_NETWORK &&
+ route->type != OSPF6_DEST_TYPE_RANGE &&
+ (route->type != OSPF6_DEST_TYPE_ROUTER ||
+ ! CHECK_FLAG (route->path.router_bits, OSPF6_ROUTER_BIT_E)))
{
+ if (IS_OSPF6_DEBUG_ABR)
+ zlog_info ("Route type is none of network, range nor ASBR, withdraw");
+ if (summary)
+ ospf6_route_remove (summary, summary_table);
if (old)
- ospf6_lsa_premature_aging (old);
+ ospf6_lsa_purge (old);
return;
}
@@ -82,95 +143,203 @@
if (route->path.type == OSPF6_PATH_TYPE_EXTERNAL1 ||
route->path.type == OSPF6_PATH_TYPE_EXTERNAL2)
{
+ if (IS_OSPF6_DEBUG_ABR)
+ zlog_info ("Path type is external, withdraw");
+ if (summary)
+ ospf6_route_remove (summary, summary_table);
if (old)
- ospf6_lsa_premature_aging (old);
- return;
- }
-
- /* do not generate if the route cost is greater or equal to LSInfinity */
- if (route->path.cost >= LS_INFINITY)
- {
- if (old)
- ospf6_lsa_premature_aging (old);
- return;
- }
-
- /* if this is an inter-area route */
- if (route->path.type == OSPF6_PATH_TYPE_INTRA)
- {
- /* search for configured address range for the route's area */
- route_area = ospf6_area_lookup (route->path.area_id, area->ospf6);
- assert (route_area);
- range = ospf6_route_lookup_bestmatch (&route->prefix,
- route_area->summary_table);
- }
-
- /* ranges are ignored when originate backbone routes to transit area.
- Otherwise, if ranges are configured, the route is suppressed. */
- if (range && (route->path.area_id != htonl (0) || ! area->transit_capability))
- {
- if (old)
- ospf6_lsa_premature_aging (old);
- if (range->path.cost < route->path.cost)
- range->path.cost = route->path.cost;
- SET_FLAG (range->flag, OSPF6_ROUTE_HAVE_LONGER);
+ ospf6_lsa_purge (old);
return;
}
/* do not generate if the path's area is the same as target area */
if (route->path.area_id == area->area_id)
{
+ if (IS_OSPF6_DEBUG_ABR)
+ zlog_info ("The route is in the area itself, ignore");
+ if (summary)
+ ospf6_route_remove (summary, summary_table);
if (old)
- ospf6_lsa_premature_aging (old);
+ ospf6_lsa_purge (old);
return;
}
/* do not generate if the nexthops belongs to the target area */
oi = ospf6_interface_lookup_by_ifindex (route->nexthop[0].ifindex);
- if (oi && oi->area && oi->area->area_id == area->area_id)
+ if (oi && oi->area && oi->area == area)
{
+ if (IS_OSPF6_DEBUG_ABR)
+ zlog_info ("The route's nexthop is in the same area, ignore");
+ if (summary)
+ ospf6_route_remove (summary, summary_table);
if (old)
- ospf6_lsa_premature_aging (old);
+ ospf6_lsa_purge (old);
return;
}
+ /* do not generate if the route cost is greater or equal to LSInfinity */
+ if (route->path.cost >= LS_INFINITY)
+ {
+ if (IS_OSPF6_DEBUG_ABR)
+ zlog_info ("The cost exceeds LSInfinity, withdraw");
+ if (summary)
+ ospf6_route_remove (summary, summary_table);
+ if (old)
+ ospf6_lsa_purge (old);
+ return;
+ }
+
+ /* if this is a route to ASBR */
+ if (route->type == OSPF6_DEST_TYPE_ROUTER)
+ {
+ /* Only the prefered best path is considered */
+ if (! CHECK_FLAG (route->flag, OSPF6_ROUTE_BEST))
+ {
+ if (IS_OSPF6_DEBUG_ABR)
+ zlog_info ("This is the secondary path to the ASBR, ignore");
+ if (summary)
+ ospf6_route_remove (summary, summary_table);
+ if (old)
+ ospf6_lsa_purge (old);
+ return;
+ }
+
+ /* Do not generate if the area is stub */
+ /* XXX */
+ }
+
+ /* if this is an intra-area route, this may be suppressed by aggregation */
+ if (route->type == OSPF6_DEST_TYPE_NETWORK &&
+ route->path.type == OSPF6_PATH_TYPE_INTRA)
+ {
+ /* search for configured address range for the route's area */
+ route_area = ospf6_area_lookup (route->path.area_id, area->ospf6);
+ assert (route_area);
+ range = ospf6_route_lookup_bestmatch (&route->prefix,
+ route_area->range_table);
+
+ /* 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 ||
+ ! IS_AREA_TRANSIT (area)))
+ {
+ if (IS_OSPF6_DEBUG_ABR)
+ {
+ char buf[64];
+ prefix2str (&range->prefix, buf, sizeof (buf));
+ zlog_info ("Suppressed by range %s of area %s",
+ buf, route_area->name);
+ }
+
+ if (summary)
+ ospf6_route_remove (summary, summary_table);
+ if (old)
+ ospf6_lsa_purge (old);
+ return;
+ }
+ }
+
+ /* If this is a configured address range */
+ if (route->type == OSPF6_DEST_TYPE_RANGE)
+ {
+ /* If DoNotAdvertise is set */
+ if (CHECK_FLAG (route->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE))
+ {
+ if (IS_OSPF6_DEBUG_ABR)
+ zlog_info ("This is the range with DoNotAdvertise set. ignore");
+ if (summary)
+ ospf6_route_remove (summary, summary_table);
+ if (old)
+ ospf6_lsa_purge (old);
+ return;
+ }
+
+ /* Whether the route have active longer prefix */
+ if (! CHECK_FLAG (route->flag, OSPF6_ROUTE_ACTIVE_SUMMARY))
+ {
+ if (IS_OSPF6_DEBUG_ABR)
+ zlog_info ("The range is not active. withdraw");
+ if (summary)
+ ospf6_route_remove (summary, summary_table);
+ if (old)
+ ospf6_lsa_purge (old);
+ return;
+ }
+ }
+
/* the route is going to be originated. store it in area's summary_table */
if (summary == NULL)
{
summary = ospf6_route_copy (route);
- summary->path.origin.type = htons (OSPF6_LSTYPE_INTER_PREFIX);
+ if (route->type == OSPF6_DEST_TYPE_NETWORK ||
+ route->type == OSPF6_DEST_TYPE_RANGE)
+ summary->path.origin.type = htons (OSPF6_LSTYPE_INTER_PREFIX);
+ else
+ summary->path.origin.type = htons (OSPF6_LSTYPE_INTER_ROUTER);
summary->path.origin.adv_router = area->ospf6->router_id;
summary->path.origin.id =
ospf6_new_ls_id (summary->path.origin.type,
summary->path.origin.adv_router, area->lsdb);
- ospf6_route_add (summary, area->summary_table);
+ ospf6_route_add (summary, summary_table);
}
+ else
+ {
+ summary->type = route->type;
+ gettimeofday (&summary->changed, NULL);
+ }
+
+ summary->path.router_bits = route->path.router_bits;
+ summary->path.options[0] = route->path.options[0];
+ summary->path.options[1] = route->path.options[1];
+ summary->path.options[2] = route->path.options[2];
+ summary->path.prefix_options = route->path.prefix_options;
+ summary->path.area_id = area->area_id;
+ summary->path.type = OSPF6_PATH_TYPE_INTER;
+ summary->path.cost = route->path.cost;
+ summary->nexthop[0] = route->nexthop[0];
/* prepare buffer */
memset (buffer, 0, sizeof (buffer));
lsa_header = (struct ospf6_lsa_header *) buffer;
- prefix_lsa = (struct ospf6_inter_prefix_lsa *)
- ((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header));
- p = (caddr_t) prefix_lsa + sizeof (struct ospf6_inter_prefix_lsa);
- /* Fill Inter-Area-Prefix-LSA */
- OSPF6_ABR_SUMMARY_METRIC_SET (prefix_lsa, route->path.cost);
+ if (route->type == OSPF6_DEST_TYPE_ROUTER)
+ {
+ router_lsa = (struct ospf6_inter_router_lsa *)
+ ((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header));
+ p = (caddr_t) router_lsa + sizeof (struct ospf6_inter_router_lsa);
- /* prefixlen */
- prefix_lsa->prefix.prefix_length = route->prefix.prefixlen;
+ /* Fill Inter-Area-Router-LSA */
+ router_lsa->options[0] = route->path.options[0];
+ router_lsa->options[1] = route->path.options[1];
+ router_lsa->options[2] = route->path.options[2];
+ OSPF6_ABR_SUMMARY_METRIC_SET (router_lsa, route->path.cost);
+ router_lsa->router_id =
+ ospf6_linkstate_prefix_adv_router (&route->prefix);
+ type = htons (OSPF6_LSTYPE_INTER_ROUTER);
+ }
+ else
+ {
+ prefix_lsa = (struct ospf6_inter_prefix_lsa *)
+ ((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header));
+ p = (caddr_t) prefix_lsa + sizeof (struct ospf6_inter_prefix_lsa);
- /* PrefixOptions */
- prefix_lsa->prefix.prefix_options = route->path.prefix_options;
+ /* Fill Inter-Area-Prefix-LSA */
+ OSPF6_ABR_SUMMARY_METRIC_SET (prefix_lsa, route->path.cost);
+ prefix_lsa->prefix.prefix_length = route->prefix.prefixlen;
+ prefix_lsa->prefix.prefix_options = route->path.prefix_options;
- /* set Prefix */
- memcpy (p, &route->prefix.u.prefix6,
- OSPF6_PREFIX_SPACE (route->prefix.prefixlen));
- ospf6_prefix_apply_mask (&prefix_lsa->prefix);
- p += OSPF6_PREFIX_SPACE (route->prefix.prefixlen);
+ /* set Prefix */
+ memcpy (p, &route->prefix.u.prefix6,
+ OSPF6_PREFIX_SPACE (route->prefix.prefixlen));
+ ospf6_prefix_apply_mask (&prefix_lsa->prefix);
+ p += OSPF6_PREFIX_SPACE (route->prefix.prefixlen);
+ type = htons (OSPF6_LSTYPE_INTER_PREFIX);
+ }
/* Fill LSA Header */
lsa_header->age = 0;
- lsa_header->type = htons (OSPF6_LSTYPE_INTER_PREFIX);
+ lsa_header->type = type;
lsa_header->id = summary->path.origin.id;
lsa_header->adv_router = area->ospf6->router_id;
lsa_header->seqnum =
@@ -183,23 +352,63 @@
/* create LSA */
lsa = ospf6_lsa_create (lsa_header);
- lsa->scope = area;
- SET_FLAG (lsa->flag, OSPF6_LSA_REFRESH); /* XXX */
+
+ if (IS_OSPF6_DEBUG_ABR)
+ zlog_info ("Originate as %s", lsa->name);
/* Originate */
- ospf6_lsa_originate (lsa);
+ ospf6_lsa_originate_area (lsa, area);
}
void
-ospf6_abr_originate_prefix (struct ospf6_route *route, struct ospf6 *o)
+ospf6_abr_range_update (struct ospf6_route *range)
+{
+ u_int32_t cost = 0;
+ struct ospf6_route *ro;
+
+ assert (range->type == OSPF6_DEST_TYPE_RANGE);
+
+ /* update range's cost and active flag */
+ for (ro = ospf6_route_match_head (&range->prefix, ospf6->route_table);
+ ro; ro = ospf6_route_match_next (&range->prefix, ro))
+ {
+ if (ro->path.area_id == range->path.area_id &&
+ ! CHECK_FLAG (ro->flag, OSPF6_ROUTE_REMOVE))
+ cost = MAX (cost, ro->path.cost);
+ }
+
+ if (range->path.cost != cost)
+ {
+ range->path.cost = cost;
+
+ if (range->path.cost)
+ SET_FLAG (range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY);
+ else
+ UNSET_FLAG (range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY);
+
+ ospf6_abr_originate_summary (range);
+ }
+}
+
+void
+ospf6_abr_originate_summary (struct ospf6_route *route)
{
listnode node;
struct ospf6_area *oa;
+ struct ospf6_route *range = NULL;
- for (node = listhead (o->area_list); node; nextnode (node))
+ if (route->type == OSPF6_DEST_TYPE_NETWORK)
+ {
+ oa = ospf6_area_lookup (route->path.area_id, ospf6);
+ range = ospf6_route_lookup_bestmatch (&route->prefix, oa->range_table);
+ if (range)
+ ospf6_abr_range_update (range);
+ }
+
+ for (node = listhead (ospf6->area_list); node; nextnode (node))
{
oa = (struct ospf6_area *) getdata (node);
- ospf6_abr_originate_prefix_to_area (route, oa);
+ ospf6_abr_originate_summary_to_area (route, oa);
}
}
@@ -211,7 +420,7 @@
struct ospf6_route_table *table = NULL;
struct ospf6_route *range, *route, *old = NULL;
struct ospf6_route *abr_entry;
- u_char type;
+ u_char type = 0;
char options[3] = {0, 0, 0};
u_int8_t prefix_options = 0;
u_int32_t cost = 0;
@@ -274,18 +483,22 @@
}
/* (3) if the prefix is equal to an active configured address range */
- range = ospf6_route_lookup (&prefix, oa->summary_table);
- if (range && CHECK_FLAG (range->flag, OSPF6_ROUTE_HAVE_LONGER))
+ if (lsa->header->type == htons (OSPF6_LSTYPE_INTER_PREFIX))
{
- if (old)
- ospf6_route_remove (old, oa->ospf6->route_table);
- return;
+ range = ospf6_route_lookup (&prefix, oa->range_table);
+ if (range)
+ {
+ if (old)
+ ospf6_route_remove (old, oa->ospf6->route_table);
+ return;
+ }
}
/* (4) if the routing table entry for the ABR does not exist */
ospf6_linkstate_prefix (lsa->header->adv_router, htonl (0), &abr_prefix);
abr_entry = ospf6_route_lookup (&abr_prefix, oa->ospf6->brouter_table);
- if (abr_entry == NULL)
+ if (abr_entry == NULL || abr_entry->path.area_id != oa->area_id ||
+ ! CHECK_FLAG (abr_entry->path.router_bits, OSPF6_ROUTER_BIT_B))
{
if (old)
ospf6_route_remove (old, oa->ospf6->route_table);
@@ -318,11 +531,6 @@
ospf6_route_add (route, table);
}
-int
-dummy (struct ospf6_lsa *lsa)
-{
-}
-
/* Display functions */
int
@@ -412,15 +620,25 @@
install_element (CONFIG_NODE, &no_debug_ospf6_abr_cmd);
}
+struct ospf6_lsa_handler inter_prefix_handler =
+{
+ OSPF6_LSTYPE_INTER_PREFIX,
+ "Inter-Prefix",
+ ospf6_inter_area_prefix_lsa_show
+};
+
+struct ospf6_lsa_handler inter_router_handler =
+{
+ OSPF6_LSTYPE_INTER_ROUTER,
+ "Inter-Router",
+ ospf6_inter_area_router_lsa_show
+};
+
void
ospf6_abr_init ()
{
- ospf6_lstype[3].name = "Inter-Area-Prefix-LSA";
- ospf6_lstype[3].reoriginate = dummy;
- ospf6_lstype[3].show = ospf6_inter_area_prefix_lsa_show;
- ospf6_lstype[4].name = "Inter-Area-Router-LSA";
- ospf6_lstype[4].reoriginate = dummy;
- ospf6_lstype[4].show = ospf6_inter_area_router_lsa_show;
+ ospf6_install_lsa_handler (&inter_prefix_handler);
+ ospf6_install_lsa_handler (&inter_router_handler);
}
diff --git a/ospf6d/ospf6_abr.h b/ospf6d/ospf6_abr.h
index 1c5c6a3..a12d985 100644
--- a/ospf6d/ospf6_abr.h
+++ b/ospf6d/ospf6_abr.h
@@ -52,9 +52,11 @@
{ (E)->metric &= htonl (0x00000000); \
(E)->metric |= htonl (0x00ffffff) & htonl (C); }
-void ospf6_abr_originate_prefix_to_area (struct ospf6_route *route,
- struct ospf6_area *area);
-void ospf6_abr_originate_prefix (struct ospf6_route *route, struct ospf6 *o);
+int ospf6_is_router_abr (struct ospf6 *o);
+
+void ospf6_abr_originate_summary_to_area (struct ospf6_route *route,
+ struct ospf6_area *area);
+void ospf6_abr_originate_summary (struct ospf6_route *route);
void ospf6_abr_examin_summary (struct ospf6_lsa *lsa, struct ospf6_area *oa);
int config_write_ospf6_debug_abr (struct vty *vty);
diff --git a/ospf6d/ospf6_area.c b/ospf6d/ospf6_area.c
index 04cbb0a..fc2103c 100644
--- a/ospf6d/ospf6_area.c
+++ b/ospf6d/ospf6_area.c
@@ -48,29 +48,18 @@
{
struct ospf6_area *oa = (struct ospf6_area *) va;
struct ospf6_area *ob = (struct ospf6_area *) vb;
- return (ntohl (oa->area_id) - ntohl (ob->area_id));
-}
-
-int
-ospf6_area_is_stub (struct ospf6_area *o6a)
-{
- if (OSPF6_OPT_ISSET (o6a->options, OSPF6_OPT_E))
- return 0;
- return 1;
+ return (ntohl (oa->area_id) < ntohl (ob->area_id) ? -1 : 1);
}
/* schedule routing table recalculation */
void
ospf6_area_lsdb_hook_add (struct ospf6_lsa *lsa)
{
- struct ospf6_area *oa;
-
- oa = (struct ospf6_area *) lsa->scope;
switch (ntohs (lsa->header->type))
{
case OSPF6_LSTYPE_ROUTER:
case OSPF6_LSTYPE_NETWORK:
- ospf6_spf_schedule (oa);
+ ospf6_spf_schedule (OSPF6_AREA (lsa->lsdb->data));
break;
case OSPF6_LSTYPE_INTRA_PREFIX:
@@ -83,7 +72,8 @@
default:
if (IS_OSPF6_DEBUG_LSA (RECV))
- zlog_info ("Unknown LSA in Area %s's lsdb", oa->name);
+ zlog_info ("Unknown LSA in Area %s's lsdb",
+ OSPF6_AREA (lsa->lsdb->data)->name);
break;
}
}
@@ -91,14 +81,11 @@
void
ospf6_area_lsdb_hook_remove (struct ospf6_lsa *lsa)
{
- struct ospf6_area *oa;
-
- oa = (struct ospf6_area *) lsa->scope;
switch (ntohs (lsa->header->type))
{
case OSPF6_LSTYPE_ROUTER:
case OSPF6_LSTYPE_NETWORK:
- ospf6_spf_schedule (oa);
+ ospf6_spf_schedule (OSPF6_AREA (lsa->lsdb->data));
break;
case OSPF6_LSTYPE_INTRA_PREFIX:
@@ -111,7 +98,8 @@
default:
if (IS_OSPF6_DEBUG_LSA (RECV))
- zlog_info ("Unknown LSA in Area %s's lsdb", oa->name);
+ zlog_info ("Unknown LSA in Area %s's lsdb",
+ OSPF6_AREA (lsa->lsdb->data)->name);
break;
}
}
@@ -146,17 +134,20 @@
oa->area_id = area_id;
oa->if_list = list_new ();
- oa->summary_table = ospf6_route_table_create ();
-
- oa->lsdb = ospf6_lsdb_create ();
+ oa->lsdb = ospf6_lsdb_create (oa);
oa->lsdb->hook_add = ospf6_area_lsdb_hook_add;
oa->lsdb->hook_remove = ospf6_area_lsdb_hook_remove;
+ oa->lsdb_self = ospf6_lsdb_create (oa);
oa->spf_table = ospf6_route_table_create ();
oa->route_table = ospf6_route_table_create ();
oa->route_table->hook_add = ospf6_area_route_hook_add;
oa->route_table->hook_remove = ospf6_area_route_hook_remove;
+ oa->range_table = ospf6_route_table_create ();
+ oa->summary_prefix = ospf6_route_table_create ();
+ oa->summary_router = ospf6_route_table_create ();
+
/* set default options */
OSPF6_OPT_SET (oa->options, OSPF6_OPT_V6);
OSPF6_OPT_SET (oa->options, OSPF6_OPT_E);
@@ -168,7 +159,7 @@
/* import athoer area's routes as inter-area routes */
for (route = ospf6_route_head (o->route_table); route;
route = ospf6_route_next (route))
- ospf6_abr_originate_prefix_to_area (route, oa);
+ ospf6_abr_originate_summary_to_area (route, oa);
return oa;
}
@@ -179,7 +170,9 @@
listnode n;
struct ospf6_interface *oi;
- ospf6_route_table_delete (oa->summary_table);
+ 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 (n = listhead (oa->if_list); n; nextnode (n))
@@ -190,6 +183,8 @@
list_delete (oa->if_list);
ospf6_lsdb_delete (oa->lsdb);
+ ospf6_lsdb_delete (oa->lsdb_self);
+
ospf6_route_table_delete (oa->spf_table);
ospf6_route_table_delete (oa->route_table);
@@ -224,13 +219,23 @@
return (struct ospf6_area *) NULL;
}
+struct ospf6_area *
+ospf6_area_get (u_int32_t area_id, struct ospf6 *o)
+{
+ struct ospf6_area *oa;
+ oa = ospf6_area_lookup (area_id, o);
+ if (oa == NULL)
+ oa = ospf6_area_create (area_id, o);
+ return oa;
+}
+
void
ospf6_area_enable (struct ospf6_area *oa)
{
listnode i;
struct ospf6_interface *oi;
- UNSET_FLAG (oa->flag, OSPF6_AREA_DISABLE);
+ SET_FLAG (oa->flag, OSPF6_AREA_ENABLE);
for (i = listhead (oa->if_list); i; nextnode (i))
{
@@ -245,7 +250,7 @@
listnode i;
struct ospf6_interface *oi;
- SET_FLAG (oa->flag, OSPF6_AREA_DISABLE);
+ UNSET_FLAG (oa->flag, OSPF6_AREA_ENABLE);
for (i = listhead (oa->if_list); i; nextnode (i))
{
@@ -291,6 +296,130 @@
} \
}
+#define OSPF6_CMD_AREA_GET(str, oa) \
+{ \
+ u_int32_t area_id = 0; \
+ if (inet_pton (AF_INET, str, &area_id) != 1) \
+ { \
+ vty_out (vty, "Malformed Area-ID: %s%s", str, VNL); \
+ return CMD_SUCCESS; \
+ } \
+ oa = ospf6_area_get (area_id, ospf6); \
+}
+
+DEFUN (area_range,
+ area_range_cmd,
+ "area A.B.C.D range X:X::X:X/M",
+ "OSPF area parameters\n"
+ OSPF6_AREA_ID_STR
+ "Configured address range\n"
+ "Specify IPv6 prefix\n"
+ )
+{
+ int ret;
+ struct ospf6_area *oa;
+ struct prefix prefix;
+ struct ospf6_route *range;
+
+ OSPF6_CMD_AREA_GET (argv[0], oa);
+ argc--;
+ argv++;
+
+ ret = str2prefix (argv[0], &prefix);
+ if (ret != 1 || prefix.family != AF_INET6)
+ {
+ vty_out (vty, "Malformed argument: %s%s", argv[0], VNL);
+ return CMD_SUCCESS;
+ }
+ argc--;
+ argv++;
+
+ range = ospf6_route_lookup (&prefix, oa->range_table);
+ if (range == NULL)
+ {
+ range = ospf6_route_create ();
+ range->type = OSPF6_DEST_TYPE_RANGE;
+ range->prefix = prefix;
+ }
+
+ if (argc)
+ {
+ if (! strcmp (argv[0], "not-advertise"))
+ SET_FLAG (range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE);
+ else if (! strcmp (argv[0], "advertise"))
+ UNSET_FLAG (range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE);
+ }
+
+ ospf6_route_add (range, oa->range_table);
+ return CMD_SUCCESS;
+}
+
+ALIAS (area_range,
+ area_range_advertise_cmd,
+ "area A.B.C.D range X:X::X:X/M (advertise|not-advertise)",
+ "OSPF area parameters\n"
+ OSPF6_AREA_ID_STR
+ "Configured address range\n"
+ "Specify IPv6 prefix\n"
+ );
+
+DEFUN (no_area_range,
+ no_area_range_cmd,
+ "no area A.B.C.D range X:X::X:X/M",
+ "OSPF area parameters\n"
+ OSPF6_AREA_ID_STR
+ "Configured address range\n"
+ "Specify IPv6 prefix\n"
+ )
+{
+ int ret;
+ struct ospf6_area *oa;
+ struct prefix prefix;
+ struct ospf6_route *range;
+
+ OSPF6_CMD_AREA_GET (argv[0], oa);
+ argc--;
+ argv++;
+
+ ret = str2prefix (argv[0], &prefix);
+ if (ret != 1 || prefix.family != AF_INET6)
+ {
+ vty_out (vty, "Malformed argument: %s%s", argv[0], VNL);
+ return CMD_SUCCESS;
+ }
+
+ range = ospf6_route_lookup (&prefix, oa->range_table);
+ if (range == NULL)
+ {
+ vty_out (vty, "Range %s does not exists.%s", argv[0], VNL);
+ return CMD_SUCCESS;
+ }
+
+ ospf6_route_remove (range, oa->range_table);
+ return CMD_SUCCESS;
+}
+
+void
+ospf6_area_config_write (struct vty *vty)
+{
+ listnode node;
+ struct ospf6_area *oa;
+ struct ospf6_route *range;
+ char buf[128];
+
+ for (node = listhead (ospf6->area_list); node; nextnode (node))
+ {
+ oa = OSPF6_AREA (getdata (node));
+
+ for (range = ospf6_route_head (oa->range_table); range;
+ range = ospf6_route_next (range))
+ {
+ prefix2str (&range->prefix, buf, sizeof (buf));
+ vty_out (vty, " area %s range %s%s", oa->name, buf, VNL);
+ }
+ }
+}
+
DEFUN (show_ipv6_ospf6_area_route_intra,
show_ipv6_ospf6_area_route_intra_cmd,
"show ipv6 ospf6 area A.B.C.D route intra-area",
@@ -876,5 +1005,10 @@
install_element (ENABLE_NODE, &show_ipv6_ospf6_area_route_intra_match_detail_cmd);
install_element (ENABLE_NODE, &show_ipv6_ospf6_simulate_spf_tree_root_cmd);
+
+ install_element (OSPF6_NODE, &area_range_cmd);
+ install_element (OSPF6_NODE, &area_range_advertise_cmd);
+ install_element (OSPF6_NODE, &no_area_range_cmd);
}
+
diff --git a/ospf6d/ospf6_area.h b/ospf6d/ospf6_area.h
index c15960c..734f030 100644
--- a/ospf6d/ospf6_area.h
+++ b/ospf6d/ospf6_area.h
@@ -41,16 +41,17 @@
/* OSPF Option */
u_char options[3];
- /* TransitCapability */
- int transit_capability;
-
/* Summary routes to be originated (includes Configured Address Ranges) */
- struct ospf6_route_table *summary_table;
+ struct ospf6_route_table *range_table;
+ struct ospf6_route_table *summary_prefix;
+ struct ospf6_route_table *summary_router;
/* OSPF interface list */
list if_list;
- struct ospf6_lsdb *lsdb;
+ struct ospf6_lsdb *lsdb;
+ struct ospf6_lsdb *lsdb_self;
+
struct ospf6_route_table *spf_table;
struct ospf6_route_table *route_table;
@@ -62,12 +63,21 @@
u_int32_t router_lsa_size_limit;
};
-#define OSPF6_AREA_DISABLE 0x01
-#define OSPF6_AREA_STUB 0x02
+#define OSPF6_AREA_ENABLE 0x01
+#define OSPF6_AREA_ACTIVE 0x02
+#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))
+#define IS_AREA_STUB(oa) (CHECK_FLAG ((oa)->flag, OSPF6_AREA_STUB))
/* prototypes */
int ospf6_area_cmp (void *va, void *vb);
-int ospf6_area_is_stub (struct ospf6_area *o6a);
+
struct ospf6_area *ospf6_area_create (u_int32_t, struct ospf6 *);
void ospf6_area_delete (struct ospf6_area *);
struct ospf6_area *ospf6_area_lookup (u_int32_t, struct ospf6 *);
@@ -76,6 +86,8 @@
void ospf6_area_disable (struct ospf6_area *);
void ospf6_area_show (struct vty *, struct ospf6_area *);
+
+void ospf6_area_config_write (struct vty *vty);
void ospf6_area_init ();
#endif /* OSPF_AREA_H */
diff --git a/ospf6d/ospf6_asbr.c b/ospf6d/ospf6_asbr.c
index 18f7cc2..a8a1ce1 100644
--- a/ospf6d/ospf6_asbr.c
+++ b/ospf6d/ospf6_asbr.c
@@ -37,10 +37,15 @@
#include "ospf6_lsdb.h"
#include "ospf6_route.h"
#include "ospf6_zebra.h"
+#include "ospf6_message.h"
+
#include "ospf6_top.h"
#include "ospf6_area.h"
+#include "ospf6_interface.h"
+#include "ospf6_neighbor.h"
#include "ospf6_asbr.h"
#include "ospf6_intra.h"
+#include "ospf6_flood.h"
#include "ospf6d.h"
unsigned char conf_debug_ospf6_asbr = 0;
@@ -61,20 +66,19 @@
/* AS External LSA origination */
void
-ospf6_as_external_lsa_originate_sub (struct ospf6_route *route, int force)
+ospf6_as_external_lsa_originate (struct ospf6_route *route)
{
char buffer[OSPF6_MAX_LSASIZE];
struct ospf6_lsa_header *lsa_header;
struct ospf6_lsa *old, *lsa;
- struct ospf6_external_info *info = route->route_option;
struct ospf6_as_external_lsa *as_external_lsa;
char buf[64];
caddr_t p;
/* find previous LSA */
old = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_AS_EXTERNAL),
- htonl (info->id), ospf6->router_id,
+ route->path.origin.id, ospf6->router_id,
ospf6->lsdb);
if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
@@ -99,7 +103,7 @@
UNSET_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_E);
/* forwarding address */
- if (! IN6_IS_ADDR_UNSPECIFIED (&info->forwarding))
+ if (! IN6_IS_ADDR_UNSPECIFIED (&route->nexthop[0].address))
SET_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_F);
else
UNSET_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_F);
@@ -128,7 +132,7 @@
/* Forwarding address */
if (CHECK_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_F))
{
- memcpy (p, &info->forwarding, sizeof (struct in6_addr));
+ memcpy (p, &route->nexthop[0].address, sizeof (struct in6_addr));
p += sizeof (struct in6_addr);
}
@@ -141,7 +145,7 @@
/* Fill LSA Header */
lsa_header->age = 0;
lsa_header->type = htons (OSPF6_LSTYPE_AS_EXTERNAL);
- lsa_header->id = htonl (info->id);
+ lsa_header->id = route->path.origin.id;
lsa_header->adv_router = ospf6->router_id;
lsa_header->seqnum =
ospf6_new_ls_seqnum (lsa_header->type, lsa_header->id,
@@ -153,37 +157,11 @@
/* create LSA */
lsa = ospf6_lsa_create (lsa_header);
- lsa->scope = ospf6;
- if (force)
- SET_FLAG (lsa->flag, OSPF6_LSA_REFRESH);
/* Originate */
- ospf6_lsa_originate (lsa);
+ ospf6_lsa_originate_process (lsa, ospf6);
}
-int
-ospf6_as_external_lsa_reoriginate (struct ospf6_lsa *lsa)
-{
- struct prefix prefix_id;
- struct route_node *node;
- struct ospf6_route *route;
-
- /* create/update binding in external_id_table */
- prefix_id.family = AF_INET;
- prefix_id.prefixlen = 32;
- prefix_id.u.prefix4.s_addr = lsa->header->id;
- node = route_node_get (ospf6->external_id_table, &prefix_id);
- route = node->info;
-
- if (route)
- ospf6_as_external_lsa_originate_sub (route, 1);
- else
- ospf6_lsa_premature_aging (lsa);
-
- return 0;
-}
-
-
void
ospf6_asbr_lsa_add (struct ospf6_lsa *lsa)
@@ -217,7 +195,7 @@
asbr_id.family = AF_INET;
asbr_id.prefixlen = 32;
asbr_id.u.prefix4.s_addr = lsa->header->adv_router;
- asbr_entry = ospf6_route_lookup (&asbr_id, ospf6->asbr_table);
+ asbr_entry = ospf6_route_lookup (&asbr_id, ospf6->brouter_table);
if (asbr_entry == NULL)
{
@@ -545,7 +523,7 @@
zlog_info ("Advertise as AS-External Id:%s", ibuf);
}
- ospf6_as_external_lsa_originate_sub (match, 0);
+ ospf6_as_external_lsa_originate (match);
return;
}
@@ -593,7 +571,7 @@
zlog_info ("Advertise as AS-External Id:%s", ibuf);
}
- ospf6_as_external_lsa_originate_sub (route, 0);
+ ospf6_as_external_lsa_originate (route);
/* Router-Bit (ASBR Flag) may have to be updated */
for (lnode = listhead (ospf6->area_list); lnode; nextnode (lnode))
@@ -649,7 +627,7 @@
lsa = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_AS_EXTERNAL),
htonl (info->id), ospf6->router_id, ospf6->lsdb);
if (lsa)
- ospf6_lsa_premature_aging (lsa);
+ ospf6_lsa_purge (lsa);
/* remove binding in external_id_table */
prefix_id.family = AF_INET;
@@ -1254,95 +1232,23 @@
return CMD_SUCCESS;
}
-DEFUN (show_ipv6_ospf6_asbr,
- show_ipv6_ospf6_asbr_cmd,
- "show ipv6 ospf6 asbr",
- SHOW_STR
- IP6_STR
- OSPF6_STR
- "Show AS Boundary Router table\n"
- )
+struct ospf6_lsa_handler as_external_handler =
{
- ospf6_lsentry_table_show (vty, argc, argv, ospf6->asbr_table);
- return CMD_SUCCESS;
-}
-
-ALIAS (show_ipv6_ospf6_asbr,
- show_ipv6_ospf6_asbr_1_cmd,
- "show ipv6 ospf6 asbr (A.B.C.D|A.B.C.D/M|detail)",
- SHOW_STR
- IP6_STR
- OSPF6_STR
- "Show AS Boundary Router table\n"
- "Specify Router-ID\n"
- "Display multiple entry by specifying match-prefix of Router-ID\n"
- "Display Detail\n"
- );
-
-ALIAS (show_ipv6_ospf6_asbr,
- show_ipv6_ospf6_asbr_2_cmd,
- "show ipv6 ospf6 asbr (A.B.C.D|A.B.C.D/M|*) (A.B.C.D|A.B.C.D/M|detail)",
- SHOW_STR
- IP6_STR
- OSPF6_STR
- "Show AS Boundary Router table\n"
- "Specify Router-ID\n"
- "Display multiple entry by specifying match-prefix of Router-ID\n"
- "Wildcard Router-ID\n"
- "Specify Link State ID\n"
- "Display multiple entry by specifying match-prefix of Link State ID\n"
- "Display Detail\n"
- );
-
-DEFUN (show_ipv6_ospf6_asbr_3,
- show_ipv6_ospf6_asbr_3_cmd,
- "show ipv6 ospf6 asbr (A.B.C.D|*) A.B.C.D/M detail",
- SHOW_STR
- IP6_STR
- OSPF6_STR
- "Show AS Boundary Router table\n"
- "Specify Router-ID\n"
- "Wildcard Router-ID\n"
- "Display multiple entry by specifying match-prefix of Link State ID\n"
- "Display Detail\n"
- )
-{
- char *sargv[CMD_ARGC_MAX];
- int i, sargc;
-
- /* copy argv to sargv and then append "detail" */
- for (i = 0; i < argc; i++)
- sargv[i] = argv[i];
- sargc = argc;
- sargv[sargc++] = "detail";
- sargv[sargc] = NULL;
-
- ospf6_lsentry_table_show (vty, sargc, sargv, ospf6->asbr_table);
- return CMD_SUCCESS;
-}
-
+ OSPF6_LSTYPE_AS_EXTERNAL,
+ "AS-External",
+ ospf6_as_external_lsa_show
+};
void
ospf6_asbr_init ()
{
ospf6_routemap_init ();
- ospf6_lstype[5].name = "AS-External";
- ospf6_lstype[5].reoriginate = ospf6_as_external_lsa_reoriginate;
- ospf6_lstype[5].show = ospf6_as_external_lsa_show;
+ ospf6_install_lsa_handler (&as_external_handler);
install_element (VIEW_NODE, &show_ipv6_ospf6_redistribute_cmd);
install_element (ENABLE_NODE, &show_ipv6_ospf6_redistribute_cmd);
- install_element (VIEW_NODE, &show_ipv6_ospf6_asbr_cmd);
- install_element (VIEW_NODE, &show_ipv6_ospf6_asbr_1_cmd);
- install_element (VIEW_NODE, &show_ipv6_ospf6_asbr_2_cmd);
- install_element (VIEW_NODE, &show_ipv6_ospf6_asbr_3_cmd);
- install_element (ENABLE_NODE, &show_ipv6_ospf6_asbr_cmd);
- install_element (ENABLE_NODE, &show_ipv6_ospf6_asbr_1_cmd);
- install_element (ENABLE_NODE, &show_ipv6_ospf6_asbr_2_cmd);
- install_element (ENABLE_NODE, &show_ipv6_ospf6_asbr_3_cmd);
-
install_element (OSPF6_NODE, &ospf6_redistribute_cmd);
install_element (OSPF6_NODE, &ospf6_redistribute_routemap_cmd);
install_element (OSPF6_NODE, &no_ospf6_redistribute_cmd);
diff --git a/ospf6d/ospf6_flood.c b/ospf6d/ospf6_flood.c
index 6e84a03..aeff15b 100644
--- a/ospf6d/ospf6_flood.c
+++ b/ospf6d/ospf6_flood.c
@@ -39,160 +39,169 @@
#include "ospf6_interface.h"
#include "ospf6_neighbor.h"
-
-void *
-ospf6_get_lsa_scope (u_int16_t type, struct ospf6_neighbor *from)
-{
- void *scope = NULL;
-
- if (from == NULL)
- return NULL;
-
- switch (OSPF6_LSA_SCOPE (type))
- {
- case OSPF6_LSA_SCOPE_AS:
- scope = (from)->ospf6_if->area->ospf6;
- break;
- case OSPF6_LSA_SCOPE_AREA:
- scope = (from)->ospf6_if->area;
- break;
- case OSPF6_LSA_SCOPE_LINKLOCAL:
- scope = (from)->ospf6_if;
- break;
- default:
- break;
- }
-
- return scope;
-}
+#include "ospf6_flood.h"
struct ospf6_lsdb *
-ospf6_get_scoped_lsdb (u_int16_t type, void *scope)
+ospf6_get_scoped_lsdb (struct ospf6_lsa *lsa)
{
struct ospf6_lsdb *lsdb = NULL;
-
- if (scope == NULL)
- return NULL;
-
- switch (OSPF6_LSA_SCOPE (type))
+ switch (OSPF6_LSA_SCOPE (lsa->header->type))
{
- case OSPF6_LSA_SCOPE_AS:
- lsdb = ((struct ospf6 *)(scope))->lsdb;
- break;
- case OSPF6_LSA_SCOPE_AREA:
- lsdb = ((struct ospf6_area *)(scope))->lsdb;
- break;
- case OSPF6_LSA_SCOPE_LINKLOCAL:
- lsdb = ((struct ospf6_interface *)(scope))->lsdb;
- break;
- default:
- break;
+ case OSPF6_SCOPE_LINKLOCAL:
+ lsdb = OSPF6_INTERFACE (lsa->lsdb->data)->lsdb;
+ break;
+ case OSPF6_SCOPE_AREA:
+ lsdb = OSPF6_AREA (lsa->lsdb->data)->lsdb;
+ break;
+ case OSPF6_SCOPE_AS:
+ lsdb = OSPF6_PROCESS (lsa->lsdb->data)->lsdb;
+ break;
+ default:
+ assert (0);
+ break;
}
-
return lsdb;
}
-void
-ospf6_decrement_onretrans (struct ospf6_lsa *lsa)
+struct ospf6_lsdb *
+ospf6_get_scoped_lsdb_self (struct ospf6_lsa *lsa)
{
- struct ospf6_lsdb *lsdb;
- struct ospf6_lsa *src;
-
- lsdb = ospf6_get_scoped_lsdb (lsa->header->type, lsa->scope);
- if (lsdb == NULL)
+ struct ospf6_lsdb *lsdb_self = NULL;
+ switch (OSPF6_LSA_SCOPE (lsa->header->type))
{
- zlog_warn ("Decrement onretrans: no such scope: %s", lsa->name);
- return;
+ case OSPF6_SCOPE_LINKLOCAL:
+ lsdb_self = OSPF6_INTERFACE (lsa->lsdb->data)->lsdb_self;
+ break;
+ case OSPF6_SCOPE_AREA:
+ lsdb_self = OSPF6_AREA (lsa->lsdb->data)->lsdb_self;
+ break;
+ case OSPF6_SCOPE_AS:
+ lsdb_self = OSPF6_PROCESS (lsa->lsdb->data)->lsdb_self;
+ break;
+ default:
+ assert (0);
+ break;
}
-
- src = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id,
- lsa->header->adv_router, lsdb);
- if (src && src != lsa)
- src->onretrans--;
-
- if (src->onretrans < 0)
- zlog_warn ("internal error: onretrans");
+ return lsdb_self;
}
void
-ospf6_flood_clear (struct ospf6_lsa *lsa)
+ospf6_lsa_originate (struct ospf6_lsa *lsa)
{
- struct ospf6_neighbor *on;
- struct ospf6_interface *oi, *ospf6_if = NULL;
- struct ospf6_area *oa, *area = NULL;
- struct ospf6 *ospf6 = NULL;
- u_int16_t scope_type;
- list scoped_interfaces;
- struct ospf6_lsa *rxmt;
- listnode i, j;
+ struct ospf6_lsa *old;
+ struct ospf6_lsdb *lsdb_self;
- scoped_interfaces = list_new ();
- scope_type = OSPF6_LSA_SCOPE (lsa->header->type);
+ /* find previous LSA */
+ old = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id,
+ lsa->header->adv_router, lsa->lsdb);
- if (scope_type == OSPF6_LSA_SCOPE_LINKLOCAL)
+ /* if the new LSA does not differ from previous,
+ suppress this update of the LSA */
+ if (old && ! OSPF6_LSA_IS_DIFFER (lsa, old))
{
- ospf6_if = (struct ospf6_interface *) lsa->scope;
- area = ospf6_if->area;
- ospf6 = area->ospf6;
- }
- else if (scope_type == OSPF6_LSA_SCOPE_AREA)
- {
- area = (struct ospf6_area *) lsa->scope;
- ospf6 = area->ospf6;
- }
- else if (scope_type == OSPF6_LSA_SCOPE_AS)
- {
- ospf6 = (struct ospf6 *) lsa->scope;
- }
- else
- {
- zlog_warn ("Can't decide LSA scope, quit ospf6_flood_clear ()");
+ if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
+ zlog_info ("Suppress updating LSA: %s", lsa->name);
+ ospf6_lsa_delete (lsa);
return;
}
- /* Collect eligible interfaces */
- for (i = listhead (ospf6->area_list); i; nextnode (i))
+ /* store it in the LSDB for self-originated LSAs */
+ lsdb_self = ospf6_get_scoped_lsdb_self (lsa);
+ ospf6_lsdb_add (ospf6_lsa_copy (lsa), lsdb_self);
+
+ lsa->refresh = thread_add_timer (master, ospf6_lsa_refresh, lsa,
+ LS_REFRESH_TIME);
+
+ if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
{
- oa = (struct ospf6_area *) getdata (i);
- if (scope_type != OSPF6_LSA_SCOPE_AS && oa != area)
- continue;
-
- for (j = listhead (oa->if_list); j; nextnode (j))
- {
- oi = (struct ospf6_interface *) getdata (j);
- if (scope_type != OSPF6_LSA_SCOPE_AS &&
- scope_type != OSPF6_LSA_SCOPE_AREA && oi != ospf6_if)
- continue;
-
- listnode_add (scoped_interfaces, oi);
- }
+ zlog_info ("LSA Originate:");
+ ospf6_lsa_header_print (lsa);
}
- for (i = listhead (scoped_interfaces); i; nextnode (i))
+ if (old)
+ ospf6_flood_clear (old);
+ ospf6_flood (NULL, lsa);
+ ospf6_install_lsa (lsa);
+}
+
+void
+ospf6_lsa_originate_process (struct ospf6_lsa *lsa,
+ struct ospf6 *process)
+{
+ lsa->lsdb = process->lsdb;
+ ospf6_lsa_originate (lsa);
+}
+
+void
+ospf6_lsa_originate_area (struct ospf6_lsa *lsa,
+ struct ospf6_area *oa)
+{
+ lsa->lsdb = oa->lsdb;
+ ospf6_lsa_originate (lsa);
+}
+
+void
+ospf6_lsa_originate_interface (struct ospf6_lsa *lsa,
+ struct ospf6_interface *oi)
+{
+ lsa->lsdb = oi->lsdb;
+ ospf6_lsa_originate (lsa);
+}
+
+void
+ospf6_lsa_purge (struct ospf6_lsa *lsa)
+{
+ struct ospf6_lsa *self;
+ struct ospf6_lsdb *lsdb_self;
+
+ /* remove it from the LSDB for self-originated LSAs */
+ lsdb_self = ospf6_get_scoped_lsdb_self (lsa);
+ self = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id,
+ lsa->header->adv_router, lsdb_self);
+ if (self)
{
- oi = (struct ospf6_interface *) getdata (i);
- for (j = listhead (oi->neighbor_list); j; nextnode (j))
- {
- on = (struct ospf6_neighbor *) getdata (j);
- rxmt = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id,
- lsa->header->adv_router, on->retrans_list);
- if (rxmt && ! ospf6_lsa_compare (rxmt, lsa))
- {
- if (IS_OSPF6_DEBUG_LSA (DATABASE))
- zlog_info ("Remove %s from retrans_list of %s",
- rxmt->name, on->name);
- ospf6_decrement_onretrans (rxmt);
- ospf6_lsdb_remove (rxmt, on->retrans_list);
- }
- }
+ THREAD_OFF (self->expire);
+ THREAD_OFF (self->refresh);
+ ospf6_lsdb_remove (self, lsdb_self);
}
- list_delete (scoped_interfaces);
+ ospf6_lsa_premature_aging (lsa);
+}
+
+
+void
+ospf6_increment_retrans_count (struct ospf6_lsa *lsa)
+{
+ /* The LSA must be the original one (see the description
+ in ospf6_decrement_retrans_count () below) */
+ lsa->retrans_count++;
+}
+
+void
+ospf6_decrement_retrans_count (struct ospf6_lsa *lsa)
+{
+ struct ospf6_lsdb *lsdb;
+ struct ospf6_lsa *orig;
+
+ /* The LSA must be on the retrans-list of a neighbor. It means
+ the "lsa" is a copied one, and we have to decrement the
+ retransmission count of the original one (instead of "lsa"'s).
+ In order to find the original LSA, first we have to find
+ appropriate LSDB that have the original LSA. */
+ lsdb = ospf6_get_scoped_lsdb (lsa);
+
+ /* Find the original LSA of which the retrans_count should be decremented */
+ orig = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id,
+ lsa->header->adv_router, lsdb);
+ if (orig)
+ orig->retrans_count--;
+
+ assert (orig->retrans_count >= 0);
}
/* RFC2328 section 13.2 Installing LSAs in the database */
void
-ospf6_install_lsa (struct ospf6_lsa *lsa, struct ospf6_lsdb *lsdb)
+ospf6_install_lsa (struct ospf6_lsa *lsa)
{
struct ospf6_lsa *old;
@@ -202,185 +211,299 @@
/* Remove the old instance from all neighbors' Link state
retransmission list (RFC2328 13.2 last paragraph) */
old = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id,
- lsa->header->adv_router, lsdb);
+ lsa->header->adv_router, lsa->lsdb);
if (old)
ospf6_flood_clear (old);
/* actually install */
gettimeofday (&lsa->installed, (struct timezone *) NULL);
- ospf6_lsdb_add (lsa, lsdb);
+ ospf6_lsdb_add (lsa, lsa->lsdb);
return;
}
+/* RFC2740 section 3.5.2. Sending Link State Update packets */
/* RFC2328 section 13.3 Next step in the flooding procedure */
void
-ospf6_flood_lsa (struct ospf6_lsa *lsa, struct ospf6_neighbor *from)
+ospf6_flood_interface (struct ospf6_neighbor *from,
+ struct ospf6_lsa *lsa, struct ospf6_interface *oi)
{
- struct ospf6 *scope_as = NULL;
- struct ospf6_area *oa, *scope_area = NULL;
- struct ospf6_interface *oi, *scope_linklocal = NULL;
+ listnode node;
struct ospf6_neighbor *on;
- list eligible_interfaces;
- listnode i, j;
- u_int16_t scope_type;
struct ospf6_lsa *req;
int retrans_added = 0;
- scope_type = OSPF6_LSA_SCOPE (lsa->header->type);
- switch (scope_type)
- {
- case OSPF6_LSA_SCOPE_AS:
- scope_as = (struct ospf6 *) lsa->scope;
- break;
- case OSPF6_LSA_SCOPE_AREA:
- scope_as = ((struct ospf6_area *) lsa->scope)->ospf6;
- scope_area = (struct ospf6_area *) lsa->scope;
- break;
- case OSPF6_LSA_SCOPE_LINKLOCAL:
- scope_as = ((struct ospf6_interface *) lsa->scope)->area->ospf6;
- scope_area = ((struct ospf6_interface *) lsa->scope)->area;
- scope_linklocal = (struct ospf6_interface *) lsa->scope;
- break;
- default:
- if (IS_OSPF6_DEBUG_LSA (SEND))
- zlog_info ("Can't decide LSA scope");
- return;
- }
-
if (IS_OSPF6_DEBUG_LSA (SEND))
- zlog_info ("Flood %s", lsa->name);
+ zlog_info ("Flooding on %s: %s", oi->interface->name, lsa->name);
- /* Collect eligible interfaces */
- eligible_interfaces = list_new ();
- for (i = listhead (scope_as->area_list); i; nextnode (i))
+ /* (1) For each neighbor */
+ for (node = listhead (oi->neighbor_list); node; nextnode (node))
{
- oa = (struct ospf6_area *) getdata (i);
- if (scope_type != OSPF6_LSA_SCOPE_AS &&
- oa != scope_area)
- continue;
+ on = (struct ospf6_neighbor *) getdata (node);
- for (j = listhead (oa->if_list); j; nextnode (j))
+ if (IS_OSPF6_DEBUG_LSA (SEND))
+ zlog_info ("To neighbor %s", on->name);
+
+ /* (a) if neighbor state < Exchange, examin next */
+ if (on->state < OSPF6_NEIGHBOR_EXCHANGE)
{
- oi = (struct ospf6_interface *) getdata (j);
- if (scope_type != OSPF6_LSA_SCOPE_AS &&
- scope_type != OSPF6_LSA_SCOPE_AREA &&
- oi != scope_linklocal)
- continue;
-
- listnode_add (eligible_interfaces, oi);
+ if (IS_OSPF6_DEBUG_LSA (SEND))
+ zlog_info ("Neighbor state less than ExChange, next neighbor");
+ continue;
}
- }
- /* For each eligible interface: */
- for (i = listhead (eligible_interfaces); i; nextnode (i))
- {
- oi = (struct ospf6_interface *) getdata (i);
-
- /* (1) For each neighbor */
- for (j = listhead (oi->neighbor_list); j; nextnode (j))
+ /* (b) if neighbor not yet Full, check request-list */
+ if (on->state != OSPF6_NEIGHBOR_FULL)
{
- on = (struct ospf6_neighbor *) getdata (j);
+ if (IS_OSPF6_DEBUG_LSA (SEND))
+ zlog_info ("Neighbor not yet Full");
- /* (a) if neighbor state < Exchange, examin next */
- if (on->state < OSPF6_NEIGHBOR_EXCHANGE)
- continue;
-
- /* (b) if neighbor not yet Full, check request-list */
- if (on->state != OSPF6_NEIGHBOR_FULL)
+ req = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id,
+ lsa->header->adv_router, on->request_list);
+ if (req == NULL)
{
- req = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id,
- lsa->header->adv_router,
- on->request_list);
- if (req)
+ if (IS_OSPF6_DEBUG_LSA (SEND))
+ zlog_info ("Not on request-list for this neighbor");
+ /* fall through */
+ }
+ else
+ {
+ /* If new LSA less recent, examin next neighbor */
+ if (ospf6_lsa_compare (lsa, req) > 0)
{
- /* If new LSA less recent, examin next neighbor */
- if (ospf6_lsa_compare (lsa, req) > 0)
- continue;
+ if (IS_OSPF6_DEBUG_LSA (SEND))
+ zlog_info ("Requesting is newer, next neighbor");
+ continue;
+ }
- /* If the same instance, delete from request-list and
- examin next neighbor */
- if (ospf6_lsa_compare (lsa, req) == 0)
- {
- if (IS_OSPF6_DEBUG_LSA (SEND) || IS_OSPF6_DEBUG_LSA (DATABASE))
- zlog_info ("Remove %s from request-list of %s: "
- "the same instance", req->name, on->name);
- ospf6_lsdb_remove (req, on->request_list);
- continue;
- }
+ /* If the same instance, delete from request-list and
+ examin next neighbor */
+ if (ospf6_lsa_compare (lsa, req) == 0)
+ {
+ if (IS_OSPF6_DEBUG_LSA (SEND))
+ zlog_info ("Requesting the same, remove it, next neighbor");
+ ospf6_lsdb_remove (req, on->request_list);
+ continue;
+ }
- /* If the new LSA is more recent, delete from
- request-list */
- if (ospf6_lsa_compare (lsa, req) < 0)
- {
- if (IS_OSPF6_DEBUG_LSA (SEND) || IS_OSPF6_DEBUG_LSA (DATABASE))
- zlog_info ("Remove %s from request-list of %s: "
- "newer instance", req->name, on->name);
- ospf6_lsdb_remove (req, on->request_list);
- /* fall through */
- }
+ /* If the new LSA is more recent, delete from request-list */
+ if (ospf6_lsa_compare (lsa, req) < 0)
+ {
+ if (IS_OSPF6_DEBUG_LSA (SEND))
+ zlog_info ("Received is newer, remove requesting");
+ ospf6_lsdb_remove (req, on->request_list);
+ /* fall through */
}
}
-
- /* (c) If the new LSA was received from this neighbor,
- examin next neighbor */
- if (from == on)
- continue;
-
- /* (d) add retrans-list, schedule retransmission */
- if (IS_OSPF6_DEBUG_LSA (SEND) || IS_OSPF6_DEBUG_LSA (DATABASE))
- zlog_info (" Add copy of %s to retrans-list of %s",
- lsa->name, on->name);
- lsa->onretrans++;
- ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->retrans_list);
- if (on->thread_send_lsupdate == NULL)
- on->thread_send_lsupdate =
- thread_add_event (master, ospf6_lsupdate_send_neighbor,
- on, on->ospf6_if->rxmt_interval);
- retrans_added++;
}
- /* (2) examin next interface if not added to retrans-list */
- if (retrans_added == 0)
- continue;
-
- /* (3) If the new LSA was received on this interface,
- and it was from DR or BDR, examin next interface */
- if (from && from->ospf6_if == oi &&
- (from->router_id == oi->drouter || from->router_id == oi->bdrouter))
- continue;
-
- /* (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)
- continue;
-
- /* (5) flood the LSA out the interface. */
- if (if_is_broadcast (oi->interface))
+ /* (c) If the new LSA was received from this neighbor,
+ examin next neighbor */
+ if (from == on)
{
- if (IS_OSPF6_DEBUG_LSA (SEND) || IS_OSPF6_DEBUG_LSA (DATABASE))
- zlog_info (" Add copy of %s to lsupdate_list of %s",
- lsa->name, oi->interface->name);
- ospf6_lsdb_add (ospf6_lsa_copy (lsa), oi->lsupdate_list);
- if (oi->thread_send_lsupdate == NULL)
- oi->thread_send_lsupdate =
- thread_add_event (master, ospf6_lsupdate_send_interface, oi, 0);
+ if (IS_OSPF6_DEBUG_LSA (SEND))
+ zlog_info ("Received is from the neighbor, next neighbor");
+ continue;
}
- else
- {
- for (j = listhead (oi->neighbor_list); j; nextnode (j))
- {
- on = (struct ospf6_neighbor *) getdata (j);
- THREAD_OFF (on->thread_send_lsupdate);
- on->thread_send_lsupdate =
- thread_add_event (master, ospf6_lsupdate_send_neighbor, on, 0);
- }
- }
+
+ /* (d) add retrans-list, schedule retransmission */
+ if (IS_OSPF6_DEBUG_LSA (SEND))
+ zlog_info ("Add retrans-list of this neighbor");
+ ospf6_increment_retrans_count (lsa);
+ ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->retrans_list);
+ if (on->thread_send_lsupdate == NULL)
+ on->thread_send_lsupdate =
+ thread_add_event (master, ospf6_lsupdate_send_neighbor,
+ on, on->ospf6_if->rxmt_interval);
+ retrans_added++;
}
- list_delete (eligible_interfaces);
+ /* (2) examin next interface if not added to retrans-list */
+ if (retrans_added == 0)
+ {
+ if (IS_OSPF6_DEBUG_LSA (SEND))
+ zlog_info ("No retransmission scheduled, next interface");
+ return;
+ }
+
+ /* (3) If the new LSA was received on this interface,
+ and it was from DR or BDR, examin next interface */
+ if (from && from->ospf6_if == oi &&
+ (from->router_id == oi->drouter || from->router_id == oi->bdrouter))
+ {
+ if (IS_OSPF6_DEBUG_LSA (SEND))
+ zlog_info ("Received is from the I/F's DR or BDR, next interface");
+ return;
+ }
+
+ /* (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 (IS_OSPF6_DEBUG_LSA (SEND))
+ zlog_info ("Received is from the I/F, itself BDR, next interface");
+ return;
+ }
+
+ /* (5) flood the LSA out the interface. */
+ if (IS_OSPF6_DEBUG_LSA (SEND))
+ zlog_info ("Schedule flooding for the interface");
+ if (if_is_broadcast (oi->interface))
+ {
+ ospf6_lsdb_add (ospf6_lsa_copy (lsa), oi->lsupdate_list);
+ if (oi->thread_send_lsupdate == NULL)
+ oi->thread_send_lsupdate =
+ thread_add_event (master, ospf6_lsupdate_send_interface, oi, 0);
+ }
+ else
+ {
+ /* reschedule retransmissions to all neighbors */
+ for (node = listhead (oi->neighbor_list); node; nextnode (node))
+ {
+ on = (struct ospf6_neighbor *) getdata (node);
+ THREAD_OFF (on->thread_send_lsupdate);
+ on->thread_send_lsupdate =
+ thread_add_event (master, ospf6_lsupdate_send_neighbor, on, 0);
+ }
+ }
}
+void
+ospf6_flood_area (struct ospf6_neighbor *from,
+ struct ospf6_lsa *lsa, struct ospf6_area *oa)
+{
+ listnode node;
+ struct ospf6_interface *oi;
+
+ for (node = listhead (oa->if_list); node; nextnode (node))
+ {
+ oi = OSPF6_INTERFACE (getdata (node));
+
+ if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_LINKLOCAL &&
+ oi != OSPF6_INTERFACE (lsa->lsdb->data))
+ continue;
+
+#if 0
+ if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_AS &&
+ ospf6_is_interface_virtual_link (oi))
+ continue;
+#endif/*0*/
+
+ ospf6_flood_interface (from, lsa, oi);
+ }
+}
+
+void
+ospf6_flood_process (struct ospf6_neighbor *from,
+ struct ospf6_lsa *lsa, struct ospf6 *process)
+{
+ listnode node;
+ struct ospf6_area *oa;
+
+ for (node = listhead (process->area_list); node; nextnode (node))
+ {
+ oa = OSPF6_AREA (getdata (node));
+
+ if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_AREA &&
+ oa != OSPF6_AREA (lsa->lsdb->data))
+ continue;
+ if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_LINKLOCAL &&
+ oa != OSPF6_INTERFACE (lsa->lsdb->data)->area)
+ continue;
+
+ if (ntohs (lsa->header->type) == OSPF6_LSTYPE_AS_EXTERNAL &&
+ IS_AREA_STUB (oa))
+ continue;
+
+ ospf6_flood_area (from, lsa, oa);
+ }
+}
+
+void
+ospf6_flood (struct ospf6_neighbor *from, struct ospf6_lsa *lsa)
+{
+ ospf6_flood_process (from, lsa, ospf6);
+}
+
+void
+ospf6_flood_clear_interface (struct ospf6_lsa *lsa, struct ospf6_interface *oi)
+{
+ listnode node;
+ struct ospf6_neighbor *on;
+ struct ospf6_lsa *rem;
+
+ for (node = listhead (oi->neighbor_list); node; nextnode (node))
+ {
+ on = OSPF6_NEIGHBOR (getdata (node));
+ rem = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id,
+ lsa->header->adv_router, on->retrans_list);
+ if (rem && ! ospf6_lsa_compare (rem, lsa))
+ {
+ if (IS_OSPF6_DEBUG_LSA (DATABASE))
+ zlog_info ("Remove %s from retrans_list of %s",
+ rem->name, on->name);
+ ospf6_decrement_retrans_count (rem);
+ ospf6_lsdb_remove (rem, on->retrans_list);
+ }
+ }
+}
+
+void
+ospf6_flood_clear_area (struct ospf6_lsa *lsa, struct ospf6_area *oa)
+{
+ listnode node;
+ struct ospf6_interface *oi;
+
+ for (node = listhead (oa->if_list); node; nextnode (node))
+ {
+ oi = OSPF6_INTERFACE (getdata (node));
+
+ if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_LINKLOCAL &&
+ oi != OSPF6_INTERFACE (lsa->lsdb->data))
+ continue;
+
+#if 0
+ if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_AS &&
+ ospf6_is_interface_virtual_link (oi))
+ continue;
+#endif/*0*/
+
+ ospf6_flood_clear_interface (lsa, oi);
+ }
+}
+
+void
+ospf6_flood_clear_process (struct ospf6_lsa *lsa, struct ospf6 *process)
+{
+ listnode node;
+ struct ospf6_area *oa;
+
+ for (node = listhead (process->area_list); node; nextnode (node))
+ {
+ oa = OSPF6_AREA (getdata (node));
+
+ if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_AREA &&
+ oa != OSPF6_AREA (lsa->lsdb->data))
+ continue;
+ if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_LINKLOCAL &&
+ oa != OSPF6_INTERFACE (lsa->lsdb->data)->area)
+ continue;
+
+ if (ntohs (lsa->header->type) == OSPF6_LSTYPE_AS_EXTERNAL &&
+ IS_AREA_STUB (oa))
+ continue;
+
+ ospf6_flood_clear_area (lsa, oa);
+ }
+}
+
+void
+ospf6_flood_clear (struct ospf6_lsa *lsa)
+{
+ ospf6_flood_clear_process (lsa, ospf6);
+}
+
+
/* RFC2328 13.5 (Table 19): Sending link state acknowledgements. */
static void
ospf6_acknowledge_lsa_bdrouter (struct ospf6_lsa *lsa, int ismore_recent,
@@ -396,7 +519,7 @@
if (CHECK_FLAG (lsa->flag, OSPF6_LSA_FLOODBACK))
{
if (IS_OSPF6_DEBUG_LSA (RECV))
- zlog_info (" BDR, FloodBack, No acknowledgement.");
+ zlog_info ("No acknowledgement (BDR & FloodBack)");
return;
}
@@ -406,16 +529,11 @@
otherwide do nothing. */
if (ismore_recent < 0)
{
- if (IS_OSPF6_DEBUG_LSA (RECV))
- zlog_info (" BDR, Not FloodBack, MoreRecent, ");
if (oi->drouter == from->router_id)
{
if (IS_OSPF6_DEBUG_LSA (RECV))
- zlog_info (" From DR, Delayed acknowledgement.");
+ zlog_info ("Delayed acknowledgement (BDR & MoreRecent & from DR)");
/* Delayed acknowledgement */
- if (IS_OSPF6_DEBUG_LSA (DATABASE))
- zlog_info (" Add copy of %s to lsack_list of %s",
- lsa->name, oi->interface->name);
ospf6_lsdb_add (ospf6_lsa_copy (lsa), oi->lsack_list);
if (oi->thread_send_lsack == NULL)
oi->thread_send_lsack =
@@ -424,7 +542,7 @@
else
{
if (IS_OSPF6_DEBUG_LSA (RECV))
- zlog_info (" Not From DR, No acknowledgement.");
+ zlog_info ("No acknowledgement (BDR & MoreRecent & ! from DR)");
}
return;
}
@@ -435,16 +553,11 @@
if (CHECK_FLAG (lsa->flag, OSPF6_LSA_DUPLICATE) &&
CHECK_FLAG (lsa->flag, OSPF6_LSA_IMPLIEDACK))
{
- if (IS_OSPF6_DEBUG_LSA (RECV))
- zlog_info (" BDR, Duplicate, ImpliedAck, ");
if (oi->drouter == from->router_id)
{
if (IS_OSPF6_DEBUG_LSA (RECV))
- zlog_info (" From DR, Delayed acknowledgement.");
+ zlog_info ("Delayed acknowledgement (BDR & Duplicate & ImpliedAck & from DR)");
/* Delayed acknowledgement */
- if (IS_OSPF6_DEBUG_LSA (DATABASE))
- zlog_info (" Add copy of %s to lsack_list of %s",
- lsa->name, oi->interface->name);
ospf6_lsdb_add (ospf6_lsa_copy (lsa), oi->lsack_list);
if (oi->thread_send_lsack == NULL)
oi->thread_send_lsack =
@@ -453,7 +566,7 @@
else
{
if (IS_OSPF6_DEBUG_LSA (RECV))
- zlog_info (" Not From DR, No acknowledgement.");
+ zlog_info ("No acknowledgement (BDR & Duplicate & ImpliedAck & ! from DR)");
}
return;
}
@@ -464,10 +577,7 @@
! CHECK_FLAG (lsa->flag, OSPF6_LSA_IMPLIEDACK))
{
if (IS_OSPF6_DEBUG_LSA (RECV))
- zlog_info (" BDR, Duplicate, Not ImpliedAck, Direct acknowledgement.");
- if (IS_OSPF6_DEBUG_LSA (DATABASE))
- zlog_info (" Add copy of %s to lsack_list of %s",
- lsa->name, from->name);
+ zlog_info ("Direct acknowledgement (BDR & Duplicate)");
ospf6_lsdb_add (ospf6_lsa_copy (lsa), from->lsack_list);
if (from->thread_send_lsack == NULL)
from->thread_send_lsack =
@@ -496,7 +606,7 @@
if (CHECK_FLAG (lsa->flag, OSPF6_LSA_FLOODBACK))
{
if (IS_OSPF6_DEBUG_LSA (RECV))
- zlog_info (" AllOther, FloodBack, No acknowledgement.");
+ zlog_info ("No acknowledgement (AllOther & FloodBack)");
return;
}
@@ -505,11 +615,8 @@
if (ismore_recent < 0)
{
if (IS_OSPF6_DEBUG_LSA (RECV))
- zlog_info (" AllOther, Not FloodBack, Delayed acknowledgement.");
+ zlog_info ("Delayed acknowledgement (AllOther & MoreRecent)");
/* Delayed acknowledgement */
- if (IS_OSPF6_DEBUG_LSA (DATABASE))
- zlog_info (" Add copy of %s to lsack_list of %s",
- lsa->name, oi->interface->name);
ospf6_lsdb_add (ospf6_lsa_copy (lsa), oi->lsack_list);
if (oi->thread_send_lsack == NULL)
oi->thread_send_lsack =
@@ -523,7 +630,7 @@
CHECK_FLAG (lsa->flag, OSPF6_LSA_IMPLIEDACK))
{
if (IS_OSPF6_DEBUG_LSA (RECV))
- zlog_info (" AllOther, Duplicate, ImpliedAck, No acknowledgement.");
+ zlog_info ("No acknowledgement (AllOther & Duplicate & ImpliedAck)");
return;
}
@@ -533,10 +640,7 @@
! CHECK_FLAG (lsa->flag, OSPF6_LSA_IMPLIEDACK))
{
if (IS_OSPF6_DEBUG_LSA (RECV))
- zlog_info (" AllOther, Duplicate, Not ImpliedAck, Direct acknowledgement.");
- if (IS_OSPF6_DEBUG_LSA (DATABASE))
- zlog_info (" Add copy of %s to lsack_list of %s",
- lsa->name, from->name);
+ zlog_info ("Direct acknowledgement (AllOther & Duplicate)");
ospf6_lsdb_add (ospf6_lsa_copy (lsa), from->lsack_list);
if (from->thread_send_lsack == NULL)
from->thread_send_lsack =
@@ -571,106 +675,55 @@
is in states Exchange or Loading
returns 1 if match this case, else returns 0 */
static int
-ospf6_is_maxage_lsa_drop (struct ospf6_lsa *lsa,
- struct ospf6_neighbor *from)
+ospf6_is_maxage_lsa_drop (struct ospf6_lsa *lsa, struct ospf6_neighbor *from)
{
- struct ospf6_lsdb *lsdb = NULL;
struct ospf6_neighbor *on;
- struct ospf6_interface *oi, *ospf6_if = NULL;
- struct ospf6_area *oa, *area = NULL;
- struct ospf6 *ospf6 = NULL;
- u_int16_t scope_type;
- list scoped_interfaces;
- listnode i, j;
+ struct ospf6_interface *oi;
+ struct ospf6_area *oa;
+ struct ospf6 *process = NULL;
+ listnode i, j, k;
int count = 0;
if (! OSPF6_LSA_IS_MAXAGE (lsa))
return 0;
- lsdb = ospf6_get_scoped_lsdb (lsa->header->type, lsa->scope);
- if (lsdb == NULL)
- {
- zlog_info ("Can't decide scoped LSDB");
- return 0;
- }
-
if (ospf6_lsdb_lookup (lsa->header->type, lsa->header->id,
- lsa->header->adv_router, lsdb))
+ lsa->header->adv_router, lsa->lsdb))
return 0;
- scoped_interfaces = list_new ();
- scope_type = OSPF6_LSA_SCOPE (lsa->header->type);
-
- if (scope_type == OSPF6_LSA_SCOPE_LINKLOCAL)
+ process = from->ospf6_if->area->ospf6;
+ for (i = listhead (process->area_list); i; nextnode (i))
{
- ospf6_if = (struct ospf6_interface *) lsa->scope;
- area = ospf6_if->area;
- ospf6 = area->ospf6;
- }
- else if (scope_type == OSPF6_LSA_SCOPE_AREA)
- {
- area = (struct ospf6_area *) lsa->scope;
- ospf6 = area->ospf6;
- }
- else if (scope_type == OSPF6_LSA_SCOPE_AS)
- {
- ospf6 = (struct ospf6 *) lsa->scope;
- }
- else
- {
- zlog_info ("Can't decide LSA scope");
- return 0;
- }
-
- /* Collect eligible interfaces */
- for (i = listhead (ospf6->area_list); i; nextnode (i))
- {
- oa = (struct ospf6_area *) getdata (i);
- if (scope_type != OSPF6_LSA_SCOPE_AS && oa != area)
- continue;
-
+ oa = OSPF6_AREA (getdata (i));
for (j = listhead (oa->if_list); j; nextnode (j))
{
- oi = (struct ospf6_interface *) getdata (j);
- if (scope_type != OSPF6_LSA_SCOPE_AS &&
- scope_type != OSPF6_LSA_SCOPE_AREA && oi != ospf6_if)
- continue;
-
- listnode_add (scoped_interfaces, oi);
+ oi = OSPF6_INTERFACE (getdata (j));
+ for (k = listhead (oi->neighbor_list); k; nextnode (k))
+ {
+ on = OSPF6_NEIGHBOR (getdata (k));
+ if (on->state == OSPF6_NEIGHBOR_EXCHANGE ||
+ on->state == OSPF6_NEIGHBOR_LOADING)
+ count++;
+ }
}
}
- for (i = listhead (scoped_interfaces); i; nextnode (i))
- {
- oi = (struct ospf6_interface *) getdata (i);
- for (j = listhead (oi->neighbor_list); j; nextnode (j))
- {
- on = (struct ospf6_neighbor *) getdata (j);
- if (on->state == OSPF6_NEIGHBOR_EXCHANGE ||
- on->state == OSPF6_NEIGHBOR_LOADING)
- count ++;
- }
- }
-
- list_delete (scoped_interfaces);
-
if (count == 0)
return 1;
-
return 0;
}
/* RFC2328 section 13 The Flooding Procedure */
void
-ospf6_receive_lsa (struct ospf6_lsa_header *lsa_header,
- struct ospf6_neighbor *from)
+ospf6_receive_lsa (struct ospf6_neighbor *from,
+ struct ospf6_lsa_header *lsa_header)
{
struct ospf6_lsa *new = NULL, *old = NULL, *rem = NULL;
int ismore_recent;
unsigned short cksum;
- struct ospf6_lsdb *lsdb = NULL;
ismore_recent = 1;
+ assert (from);
/* make lsa structure for received lsa */
new = ospf6_lsa_create (lsa_header);
@@ -681,30 +734,45 @@
ospf6_lsa_header_print (new);
}
- new->scope = ospf6_get_lsa_scope (new->header->type, from);
- if (new->scope == NULL)
- {
- zlog_warn ("Can't decide LSA scope, ignore");
- ospf6_lsa_delete (new);
- return;
- }
-
/* (1) LSA Checksum */
cksum = ntohs (new->header->checksum);
if (ntohs (ospf6_lsa_checksum (new->header)) != cksum)
{
if (IS_OSPF6_DEBUG_LSA (RECV))
- zlog_info ("Wrong LSA Checksum");
+ zlog_info ("Wrong LSA Checksum, discard");
ospf6_lsa_delete (new);
return;
}
- /* (3) Ebit Missmatch: AS-External-LSA */
- if (ntohs (new->header->type) == OSPF6_LSTYPE_AS_EXTERNAL &&
- ospf6_area_is_stub (from->ospf6_if->area))
+ /* (2) Examine the LSA's LS type.
+ RFC2470 3.5.1. Receiving Link State Update packets */
+ if (IS_AREA_STUB (from->ospf6_if->area) &&
+ OSPF6_LSA_SCOPE (new->header->type) == OSPF6_SCOPE_AS)
{
if (IS_OSPF6_DEBUG_LSA (RECV))
- zlog_info ("AS-External-LSA in stub area");
+ zlog_info ("AS-External-LSA (or AS-scope LSA) in stub area, discard");
+ ospf6_lsa_delete (new);
+ return;
+ }
+
+ /* (3) LSA which have reserved scope is discarded
+ RFC2470 3.5.1. Receiving Link State Update packets */
+ /* Flooding scope check. LSAs with unknown scope are discarded here.
+ Set appropriate LSDB for the LSA */
+ switch (OSPF6_LSA_SCOPE (new->header->type))
+ {
+ case OSPF6_SCOPE_LINKLOCAL:
+ new->lsdb = from->ospf6_if->lsdb;
+ break;
+ case OSPF6_SCOPE_AREA:
+ new->lsdb = from->ospf6_if->area->lsdb;
+ break;
+ case OSPF6_SCOPE_AS:
+ new->lsdb = from->ospf6_if->area->ospf6->lsdb;
+ break;
+ default:
+ if (IS_OSPF6_DEBUG_LSA (RECV))
+ zlog_info ("LSA has reserved scope, discard");
ospf6_lsa_delete (new);
return;
}
@@ -715,41 +783,30 @@
{
/* log */
if (IS_OSPF6_DEBUG_LSA (RECV))
- zlog_info ("Drop MaxAge LSA with Direct acknowledgement.");
+ zlog_info ("Drop MaxAge LSA with direct acknowledgement.");
/* a) Acknowledge back to neighbor (Direct acknowledgement, 13.5) */
- if (IS_OSPF6_DEBUG_LSA (DATABASE))
- zlog_info (" Add %s to lsack_list of %s",
- new->name, from->name);
- ospf6_lsdb_add (new, from->lsack_list);
+ ospf6_lsdb_add (ospf6_lsa_copy (new), from->lsack_list);
if (from->thread_send_lsack == NULL)
from->thread_send_lsack =
thread_add_event (master, ospf6_lsack_send_neighbor, from, 0);
/* b) Discard */
- /* "new" LSA will be discarded just after the LSAck sent */
+ ospf6_lsa_delete (new);
return;
}
/* (5) */
/* lookup the same database copy in lsdb */
- lsdb = ospf6_get_scoped_lsdb (new->header->type, new->scope);
- if (lsdb == NULL)
- {
- zlog_warn ("Can't decide scoped LSDB, ignore");
- ospf6_lsa_delete (new);
- return;
- }
-
old = ospf6_lsdb_lookup (new->header->type, new->header->id,
- new->header->adv_router, lsdb);
+ new->header->adv_router, new->lsdb);
if (old)
{
ismore_recent = ospf6_lsa_compare (new, old);
if (ntohl (new->header->seqnum) == ntohl (old->header->seqnum))
{
if (IS_OSPF6_DEBUG_LSA (RECV))
- zlog_info ("Duplicated LSA");
+ zlog_info ("Received is duplicated LSA");
SET_FLAG (new->flag, OSPF6_LSA_DUPLICATE);
}
}
@@ -769,35 +826,43 @@
if (res.tv_sec < MIN_LS_ARRIVAL)
{
if (IS_OSPF6_DEBUG_LSA (RECV) || IS_OSPF6_DEBUG_LSA (TIMER))
- zlog_info ("LSA can't be updated within MinLSArrival");
+ zlog_info ("LSA can't be updated within MinLSArrival, discard");
ospf6_lsa_delete (new);
return; /* examin next lsa */
}
}
+ if (IS_OSPF6_DEBUG_LSA (RECV))
+ zlog_info ("Flood, Install, Possibly acknowledge the received LSA");
+
/* (b) immediately flood and (c) remove from all retrans-list */
- ospf6_flood_lsa (new, from);
+ 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, lsdb);
+ ospf6_install_lsa (new);
/* (e) possibly acknowledge */
ospf6_acknowledge_lsa (new, ismore_recent, from);
- /* (f) */
- /* Self Originated LSA, section 13.4 */
- if (new->header->adv_router == from->ospf6_if->area->ospf6->router_id
- && (! old || ismore_recent < 0))
+ /* (f) Self Originated LSA, section 13.4 */
+ if (new->header->adv_router == from->ospf6_if->area->ospf6->router_id)
{
- /* We have to make a new instance of the LSA
+ /* Self-originated LSA (newer than ours) is received from
+ another router. We have to make a new instance of the LSA
or have to flush this LSA. */
if (IS_OSPF6_DEBUG_LSA (RECV))
- zlog_info ("New instance of the self-originated LSA");
-
- SET_FLAG (new->flag, OSPF6_LSA_REFRESH);
- ospf6_lsa_re_originate (new);
+ {
+ zlog_info ("Newer instance of the self-originated LSA");
+ zlog_info ("Schedule reorigination");
+ }
+ new->refresh = thread_add_event (master, ospf6_lsa_refresh, new, 0);
}
+
return;
}
@@ -809,7 +874,10 @@
assert (old);
if (IS_OSPF6_DEBUG_LSA (RECV))
- zlog_info ("LSA is not newer and on request-list of sending neighbor");
+ {
+ zlog_info ("Received is not newer, on the neighbor's request-list");
+ zlog_info ("BadLSReq, discard the received LSA");
+ }
/* BadLSReq */
thread_add_event (master, bad_lsreq, from, 0);
@@ -822,7 +890,7 @@
if (ismore_recent == 0)
{
if (IS_OSPF6_DEBUG_LSA (RECV))
- zlog_info ("The same instance as database copy");
+ zlog_info ("The same instance as database copy (neither recent)");
/* (a) if on retrans-list, Treat this LSA as an Ack: Implied Ack */
rem = ospf6_lsdb_lookup (new->header->type, new->header->id,
@@ -830,15 +898,18 @@
if (rem)
{
if (IS_OSPF6_DEBUG_LSA (RECV))
- zlog_info ("Treat as an Implied acknowledgement");
+ {
+ zlog_info ("It is on the neighbor's retrans-list.");
+ zlog_info ("Treat as an Implied acknowledgement");
+ }
SET_FLAG (new->flag, OSPF6_LSA_IMPLIEDACK);
- if (IS_OSPF6_DEBUG_LSA (DATABASE))
- zlog_info ("Remove %s from retrans_list of %s",
- rem->name, from->name);
- ospf6_decrement_onretrans (rem);
+ ospf6_decrement_retrans_count (rem);
ospf6_lsdb_remove (rem, from->retrans_list);
}
+ if (IS_OSPF6_DEBUG_LSA (RECV))
+ zlog_info ("Possibly acknowledge and then discard");
+
/* (b) possibly acknowledge */
ospf6_acknowledge_lsa (new, ismore_recent, from);
@@ -856,7 +927,10 @@
old->header->seqnum == htonl (MAX_SEQUENCE_NUMBER))
{
if (IS_OSPF6_DEBUG_LSA (RECV))
- zlog_info ("Database copy is in Seqnumber Wrapping");
+ {
+ zlog_info ("The LSA is in Seqnumber Wrapping");
+ zlog_info ("MaxAge & MaxSeqNum, discard");
+ }
ospf6_lsa_delete (new);
return;
}
@@ -864,13 +938,13 @@
/* Otherwise, Send database copy of this LSA to this neighbor */
{
if (IS_OSPF6_DEBUG_LSA (RECV))
- zlog_info ("Database is more recent, send back directly");
+ {
+ zlog_info ("Database copy is more recent.");
+ zlog_info ("Send back directly and then discard");
+ }
/* XXX, MinLSArrival check !? RFC 2328 13 (8) */
- if (IS_OSPF6_DEBUG_LSA (DATABASE))
- zlog_info (" Add copy of %s to lsupdate_list of %s",
- old->name, from->name);
ospf6_lsdb_add (ospf6_lsa_copy (old), from->lsupdate_list);
if (from->thread_send_lsupdate == NULL)
from->thread_send_lsupdate =
diff --git a/ospf6d/ospf6_flood.h b/ospf6d/ospf6_flood.h
index f639f63..e894e56 100644
--- a/ospf6d/ospf6_flood.h
+++ b/ospf6d/ospf6_flood.h
@@ -23,15 +23,31 @@
#define OSPF6_FLOOD_H
/* Function Prototypes */
-void *ospf6_get_lsa_scope (u_int16_t type, struct ospf6_neighbor *from);
-struct ospf6_lsdb *ospf6_get_scoped_lsdb (u_int16_t type, void *scope);
+struct ospf6_lsdb *ospf6_get_scoped_lsdb (struct ospf6_lsa *lsa);
+struct ospf6_lsdb *ospf6_get_scoped_lsdb_self (struct ospf6_lsa *lsa);
-void ospf6_decrement_onretrans (struct ospf6_lsa *lsa);
+/* origination & purging */
+void ospf6_lsa_originate (struct ospf6_lsa *lsa);
+void ospf6_lsa_originate_process (struct ospf6_lsa *lsa,
+ struct ospf6 *process);
+void ospf6_lsa_originate_area (struct ospf6_lsa *lsa,
+ struct ospf6_area *oa);
+void ospf6_lsa_originate_interface (struct ospf6_lsa *lsa,
+ struct ospf6_interface *oi);
+void ospf6_lsa_purge (struct ospf6_lsa *lsa);
+
+/* access method to retrans_count */
+void ospf6_increment_retrans_count (struct ospf6_lsa *lsa);
+void ospf6_decrement_retrans_count (struct ospf6_lsa *lsa);
+
+/* flooding & clear flooding */
void ospf6_flood_clear (struct ospf6_lsa *lsa);
-void ospf6_flood_lsa (struct ospf6_lsa *lsa, struct ospf6_neighbor *from);
-void ospf6_install_lsa (struct ospf6_lsa *lsa, struct ospf6_lsdb *lsdb);
-void ospf6_receive_lsa (struct ospf6_lsa_header *header,
- struct ospf6_neighbor *from);
+void ospf6_flood (struct ospf6_neighbor *from, struct ospf6_lsa *lsa);
+
+/* receive & install */
+void ospf6_receive_lsa (struct ospf6_neighbor *from,
+ struct ospf6_lsa_header *header);
+void ospf6_install_lsa (struct ospf6_lsa *lsa);
#endif /* OSPF6_FLOOD_H */
diff --git a/ospf6d/ospf6_interface.c b/ospf6d/ospf6_interface.c
index ccacc23..56ecacc 100644
--- a/ospf6d/ospf6_interface.c
+++ b/ospf6d/ospf6_interface.c
@@ -89,21 +89,18 @@
void
ospf6_interface_lsdb_hook (struct ospf6_lsa *lsa)
{
- struct ospf6_interface *oi;
-
- oi = (struct ospf6_interface *) lsa->scope;
switch (ntohs (lsa->header->type))
{
case OSPF6_LSTYPE_LINK:
- if (oi->state == OSPF6_INTERFACE_DR)
- OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT (oi);
- ospf6_spf_schedule (oi->area);
+ 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);
break;
default:
if (IS_OSPF6_DEBUG_LSA (RECV))
zlog_info ("Unknown LSA in Interface %s's lsdb",
- oi->interface->name);
+ OSPF6_INTERFACE (lsa->lsdb->data)->interface->name);
break;
}
}
@@ -151,11 +148,12 @@
oi->ifmtu = iobuflen;
}
- oi->lsupdate_list = ospf6_lsdb_create ();
- oi->lsack_list = ospf6_lsdb_create ();
- oi->lsdb = ospf6_lsdb_create ();
+ 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_self = ospf6_lsdb_create (oi);
oi->route_connected = ospf6_route_table_create ();
@@ -188,6 +186,8 @@
ospf6_lsdb_remove_all (oi->lsack_list);
ospf6_lsdb_delete (oi->lsdb);
+ ospf6_lsdb_delete (oi->lsdb_self);
+
ospf6_lsdb_delete (oi->lsupdate_list);
ospf6_lsdb_delete (oi->lsack_list);
@@ -428,7 +428,14 @@
ospf6_join_alldrouters (oi->interface->ifindex);
OSPF6_ROUTER_LSA_SCHEDULE (oi->area);
- if (prev_state == OSPF6_INTERFACE_DR || next_state == OSPF6_INTERFACE_DR)
+ if (next_state == OSPF6_INTERFACE_DOWN)
+ {
+ OSPF6_NETWORK_LSA_EXECUTE (oi);
+ OSPF6_INTRA_PREFIX_LSA_EXECUTE_TRANSIT (oi);
+ OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB (oi->area);
+ }
+ else if (prev_state == OSPF6_INTERFACE_DR ||
+ next_state == OSPF6_INTERFACE_DR)
{
OSPF6_NETWORK_LSA_SCHEDULE (oi);
OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT (oi);
diff --git a/ospf6d/ospf6_interface.h b/ospf6d/ospf6_interface.h
index 48b56fc..be3007d 100644
--- a/ospf6d/ospf6_interface.h
+++ b/ospf6d/ospf6_interface.h
@@ -84,6 +84,7 @@
/* Linklocal LSA Database: includes Link-LSA */
struct ospf6_lsdb *lsdb;
+ struct ospf6_lsdb *lsdb_self;
struct ospf6_lsdb *lsupdate_list;
struct ospf6_lsdb *lsack_list;
diff --git a/ospf6d/ospf6_intra.c b/ospf6d/ospf6_intra.c
index 72e2bde..74a8964 100644
--- a/ospf6d/ospf6_intra.c
+++ b/ospf6d/ospf6_intra.c
@@ -43,6 +43,8 @@
#include "ospf6_neighbor.h"
#include "ospf6_intra.h"
#include "ospf6_asbr.h"
+#include "ospf6_abr.h"
+#include "ospf6_flood.h"
#include "ospf6d.h"
/******************************/
@@ -97,9 +99,11 @@
return 0;
}
-void
-ospf6_router_lsa_originate_sub (struct ospf6_area *oa, int force)
+int
+ospf6_router_lsa_originate (struct thread *thread)
{
+ struct ospf6_area *oa;
+
char buffer [OSPF6_MAX_LSASIZE];
struct ospf6_lsa_header *lsa_header;
struct ospf6_lsa *lsa;
@@ -114,6 +118,9 @@
u_int32_t router;
int count;
+ oa = (struct ospf6_area *) THREAD_ARG (thread);
+ oa->thread_router_lsa = NULL;
+
if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
zlog_info ("Originate Router-LSA for Area %s", oa->name);
@@ -129,7 +136,10 @@
OSPF6_OPT_SET (router_lsa->options, OSPF6_OPT_R);
OSPF6_OPT_CLEAR (router_lsa->options, OSPF6_OPT_DC);
- UNSET_FLAG (router_lsa->bits, OSPF6_ROUTER_BIT_B);
+ if (ospf6_is_router_abr (ospf6))
+ SET_FLAG (router_lsa->bits, OSPF6_ROUTER_BIT_B);
+ else
+ UNSET_FLAG (router_lsa->bits, OSPF6_ROUTER_BIT_B);
if (ospf6_asbr_is_asbr (ospf6))
SET_FLAG (router_lsa->bits, OSPF6_ROUTER_BIT_E);
else
@@ -171,7 +181,7 @@
{
if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
zlog_info ("Size limit setting for Router-LSA too short");
- return;
+ return 0;
}
/* Fill LSA Header */
@@ -189,12 +199,9 @@
/* create LSA */
lsa = ospf6_lsa_create (lsa_header);
- lsa->scope = oa;
- if (force)
- SET_FLAG (lsa->flag, OSPF6_LSA_REFRESH);
/* Originate */
- ospf6_lsa_originate (lsa);
+ ospf6_lsa_originate_area (lsa, oa);
/* Reset setting for consecutive origination */
memset ((caddr_t) router_lsa + sizeof (struct ospf6_router_lsa),
@@ -277,15 +284,17 @@
/* create LSA */
lsa = ospf6_lsa_create (lsa_header);
- lsa->scope = oa;
- if (force)
- SET_FLAG (lsa->flag, OSPF6_LSA_REFRESH);
/* Originate */
- ospf6_lsa_originate (lsa);
+ ospf6_lsa_originate_area (lsa, oa);
link_state_id ++;
}
+ else
+ {
+ if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
+ zlog_info ("Nothing to describe in Router-LSA, suppress");
+ }
/* Do premature-aging of rest, undesired Router-LSAs */
type = ntohs (OSPF6_LSTYPE_ROUTER);
@@ -295,36 +304,12 @@
{
if (ntohl (lsa->header->id) < link_state_id)
continue;
- ospf6_lsa_premature_aging (lsa);
+ ospf6_lsa_purge (lsa);
}
-}
-
-int
-ospf6_router_lsa_originate (struct thread *thread)
-{
- struct ospf6_area *oa;
- int force = 0;
-
- oa = (struct ospf6_area *) THREAD_ARG (thread);
- oa->thread_router_lsa = NULL;
- ospf6_router_lsa_originate_sub (oa, force);
return 0;
}
-int
-ospf6_router_lsa_reoriginate (struct ospf6_lsa *lsa)
-{
- struct ospf6_area *oa;
- int force = 1;
-
- oa = (struct ospf6_area *) lsa->scope;
- ospf6_router_lsa_originate_sub (oa, force);
-
- return 0;
-}
-
-
/*******************************/
/* RFC2740 3.4.3.2 Network-LSA */
/*******************************/
@@ -355,9 +340,11 @@
return 0;
}
-void
-ospf6_network_lsa_originate_sub (struct ospf6_interface *oi, int force)
+int
+ospf6_network_lsa_originate (struct thread *thread)
{
+ struct ospf6_interface *oi;
+
char buffer [OSPF6_MAX_LSASIZE];
struct ospf6_lsa_header *lsa_header;
@@ -370,15 +357,13 @@
listnode i;
u_int16_t type;
- /* If self-originated Network-LSA for currently unenabled I/F
- (but was once enabled, so other routers send it to this router),
- we can't find oi->area for ospf6_lsdb_lookup (), and so can't
- do premature aging of the Network-LSA. Just let the LSA flow
- in network (other routers LSDB) for maximum duration of
- MaxAge. The contents of this router's Router-LSA will preclude
- the stale Network-LSA to be involved in routing calculation. */
- if (oi->area == NULL)
- return;
+ oi = (struct ospf6_interface *) THREAD_ARG (thread);
+ oi->thread_network_lsa = NULL;
+
+ /* The interface must be enabled until here. A Network-LSA of a
+ disabled interface (but was once enabled) should be flushed
+ by ospf6_lsa_refresh (), and does not come here. */
+ assert (oi->area);
old = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_NETWORK),
htonl (oi->interface->ifindex),
@@ -388,8 +373,8 @@
if (oi->state != OSPF6_INTERFACE_DR)
{
if (old)
- ospf6_lsa_premature_aging (old);
- return;
+ ospf6_lsa_purge (old);
+ return 0;
}
if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
@@ -408,8 +393,8 @@
if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
zlog_info ("Interface stub, ignore");
if (old)
- ospf6_lsa_premature_aging (old);
- return;
+ ospf6_lsa_purge (old);
+ return 0;
}
/* prepare buffer */
@@ -466,35 +451,9 @@
/* create LSA */
lsa = ospf6_lsa_create (lsa_header);
- lsa->scope = oi->area;
- if (force)
- SET_FLAG (lsa->flag, OSPF6_LSA_REFRESH);
/* Originate */
- ospf6_lsa_originate (lsa);
-}
-
-int
-ospf6_network_lsa_originate (struct thread *thread)
-{
- struct ospf6_interface *oi;
- int force = 0;
-
- oi = (struct ospf6_interface *) THREAD_ARG (thread);
- oi->thread_network_lsa = NULL;
- ospf6_network_lsa_originate_sub (oi, force);
-
- return 0;
-}
-
-int
-ospf6_network_lsa_reoriginate (struct ospf6_lsa *lsa)
-{
- struct ospf6_interface *oi;
- int force = 1;
-
- oi = ospf6_interface_lookup_by_ifindex (ntohl (lsa->header->id));
- ospf6_network_lsa_originate_sub (oi, force);
+ ospf6_lsa_originate_area (lsa, oi->area);
return 0;
}
@@ -558,9 +517,11 @@
return 0;
}
-void
-ospf6_link_lsa_originate_sub (struct ospf6_interface *oi, int force)
+int
+ospf6_link_lsa_originate (struct thread *thread)
{
+ struct ospf6_interface *oi;
+
char buffer[OSPF6_MAX_LSASIZE];
struct ospf6_lsa_header *lsa_header;
struct ospf6_lsa *old, *lsa;
@@ -569,8 +530,10 @@
struct ospf6_route *route;
struct ospf6_prefix *op;
- if (oi->area == NULL)
- return;
+ oi = (struct ospf6_interface *) THREAD_ARG (thread);
+ oi->thread_link_lsa = NULL;
+
+ assert (oi->area);
/* find previous LSA */
old = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_LINK),
@@ -580,8 +543,8 @@
if (CHECK_FLAG (oi->flag, OSPF6_INTERFACE_DISABLE))
{
if (old)
- ospf6_lsa_premature_aging (old);
- return;
+ ospf6_lsa_purge (old);
+ return 0;
}
if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
@@ -594,8 +557,8 @@
zlog_info ("No Linklocal address on %s, defer originating",
oi->interface->name);
if (old)
- ospf6_lsa_premature_aging (old);
- return;
+ ospf6_lsa_purge (old);
+ return 0;
}
/* prepare buffer */
@@ -641,35 +604,9 @@
/* create LSA */
lsa = ospf6_lsa_create (lsa_header);
- lsa->scope = oi;
- if (force)
- SET_FLAG (lsa->flag, OSPF6_LSA_REFRESH);
/* Originate */
- ospf6_lsa_originate (lsa);
-}
-
-int
-ospf6_link_lsa_originate (struct thread *thread)
-{
- struct ospf6_interface *oi;
- int force = 0;
-
- oi = (struct ospf6_interface *) THREAD_ARG (thread);
- oi->thread_link_lsa = NULL;
- ospf6_link_lsa_originate_sub (oi, force);
-
- return 0;
-}
-
-int
-ospf6_link_lsa_reoriginate (struct ospf6_lsa *lsa)
-{
- struct ospf6_interface *oi;
- int force = 1;
-
- oi = ospf6_interface_lookup_by_ifindex (ntohl (lsa->header->id));
- ospf6_link_lsa_originate_sub (oi, force);
+ ospf6_lsa_originate_interface (lsa, oi);
return 0;
}
@@ -736,10 +673,11 @@
return 0;
}
-void
-ospf6_intra_prefix_lsa_originate_stub_sub (struct ospf6_area *oa,
- int force)
+int
+ospf6_intra_prefix_lsa_originate_stub (struct thread *thread)
{
+ struct ospf6_area *oa;
+
char buffer[OSPF6_MAX_LSASIZE];
struct ospf6_lsa_header *lsa_header;
struct ospf6_lsa *old, *lsa;
@@ -755,15 +693,18 @@
char buf[BUFSIZ];
struct ospf6_route_table *route_advertise;
+ oa = (struct ospf6_area *) THREAD_ARG (thread);
+ oa->thread_intra_prefix_lsa = NULL;
+
/* find previous LSA */
old = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_INTRA_PREFIX),
htonl (0), oa->ospf6->router_id, oa->lsdb);
- if (CHECK_FLAG (oa->flag, OSPF6_AREA_DISABLE))
+ if (! IS_AREA_ENABLED (oa))
{
if (old)
- ospf6_lsa_premature_aging (old);
- return;
+ ospf6_lsa_purge (old);
+ return 0;
}
if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
@@ -830,9 +771,9 @@
if (route_advertise->count == 0)
{
if (old)
- ospf6_lsa_premature_aging (old);
+ ospf6_lsa_purge (old);
ospf6_route_table_delete (route_advertise);
- return;
+ return 0;
}
/* put prefixes to advertise */
@@ -857,7 +798,7 @@
{
if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
zlog_info ("Quit to Advertise Intra-Prefix: no route to advertise");
- return;
+ return 0;
}
intra_prefix_lsa->prefix_num = htons (prefix_num);
@@ -877,18 +818,19 @@
/* create LSA */
lsa = ospf6_lsa_create (lsa_header);
- lsa->scope = oa;
- if (force)
- SET_FLAG (lsa->flag, OSPF6_LSA_REFRESH);
/* Originate */
- ospf6_lsa_originate (lsa);
+ ospf6_lsa_originate_area (lsa, oa);
+
+ return 0;
}
-void
-ospf6_intra_prefix_lsa_originate_transit_sub (struct ospf6_interface *oi,
- int force)
+
+int
+ospf6_intra_prefix_lsa_originate_transit (struct thread *thread)
{
+ struct ospf6_interface *oi;
+
char buffer[OSPF6_MAX_LSASIZE];
struct ospf6_lsa_header *lsa_header;
struct ospf6_lsa *old, *lsa;
@@ -906,8 +848,10 @@
u_int16_t type;
char buf[BUFSIZ];
- if (oi->area == NULL)
- return;
+ oi = (struct ospf6_interface *) THREAD_ARG (thread);
+ oi->thread_intra_prefix_lsa = NULL;
+
+ assert (oi->area);
/* find previous LSA */
old = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_INTRA_PREFIX),
@@ -917,8 +861,8 @@
if (CHECK_FLAG (oi->flag, OSPF6_INTERFACE_DISABLE))
{
if (old)
- ospf6_lsa_premature_aging (old);
- return;
+ ospf6_lsa_purge (old);
+ return 0;
}
if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
@@ -941,8 +885,8 @@
if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
zlog_info (" Interface is not DR");
if (old)
- ospf6_lsa_premature_aging (old);
- return;
+ ospf6_lsa_purge (old);
+ return 0;
}
full_count = 0;
@@ -957,8 +901,8 @@
if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
zlog_info (" Interface is stub");
if (old)
- ospf6_lsa_premature_aging (old);
- return;
+ ospf6_lsa_purge (old);
+ return 0;
}
/* connected prefix to advertise */
@@ -1053,7 +997,7 @@
{
if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
zlog_info ("Quit to Advertise Intra-Prefix: no route to advertise");
- return;
+ return 0;
}
intra_prefix_lsa->prefix_num = htons (prefix_num);
@@ -1073,69 +1017,9 @@
/* create LSA */
lsa = ospf6_lsa_create (lsa_header);
- lsa->scope = oi->area;
- if (force)
- SET_FLAG (lsa->flag, OSPF6_LSA_REFRESH);
/* Originate */
- ospf6_lsa_originate (lsa);
-}
-
-int
-ospf6_intra_prefix_lsa_originate_stub (struct thread *thread)
-{
- struct ospf6_area *oa;
- int force = 0;
-
- oa = (struct ospf6_area *) THREAD_ARG (thread);
- oa->thread_intra_prefix_lsa = NULL;
- ospf6_intra_prefix_lsa_originate_stub_sub (oa, force);
-
- return 0;
-}
-
-int
-ospf6_intra_prefix_lsa_originate_transit (struct thread *thread)
-{
- struct ospf6_interface *oi;
- int force = 0;
-
- oi = (struct ospf6_interface *) THREAD_ARG (thread);
- oi->thread_intra_prefix_lsa = NULL;
- ospf6_intra_prefix_lsa_originate_transit_sub (oi, force);
-
- return 0;
-}
-
-int
-ospf6_intra_prefix_lsa_reoriginate (struct ospf6_lsa *lsa)
-{
- struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
- u_int16_t type;
- u_int32_t id;
- struct ospf6_area *oa;
- struct ospf6_interface *oi;
- int force = 1;
-
- intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *)
- ((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header));
- type = ntohs (intra_prefix_lsa->ref_type);
- id = ntohl (intra_prefix_lsa->ref_id);
-
- if (type == OSPF6_LSTYPE_ROUTER && id == 0)
- {
- oa = (struct ospf6_area *) lsa->scope;
- ospf6_intra_prefix_lsa_originate_stub_sub (oa, force);
- }
- else if (type == OSPF6_LSTYPE_NETWORK && id != 0)
- {
- if (intra_prefix_lsa->ref_id != lsa->header->id)
- ospf6_lsa_premature_aging (lsa);
- oi = ospf6_interface_lookup_by_ifindex (id);
- ospf6_intra_prefix_lsa_originate_transit_sub (oi, force);
- }
- else
- ospf6_lsa_premature_aging (lsa);
+ ospf6_lsa_originate_area (lsa, oi->area);
return 0;
}
@@ -1155,7 +1039,8 @@
if (IS_OSPF6_DEBUG_ROUTE (INTRA))
zlog_info ("%s found", lsa->name);
- oa = (struct ospf6_area *) lsa->scope;
+ oa = OSPF6_AREA (lsa->lsdb->data);
+
intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *)
OSPF6_LSA_HEADER_END (lsa->header);
if (intra_prefix_lsa->ref_type == htons (OSPF6_LSTYPE_ROUTER))
@@ -1244,7 +1129,8 @@
if (IS_OSPF6_DEBUG_ROUTE (INTRA))
zlog_info ("%s disappearing", lsa->name);
- oa = (struct ospf6_area *) lsa->scope;
+ oa = OSPF6_AREA (lsa->lsdb->data);
+
intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *)
OSPF6_LSA_HEADER_END (lsa->header);
@@ -1355,21 +1241,22 @@
}
void
-ospf6_intra_asbr_calculation (struct ospf6_area *oa)
+ospf6_intra_brouter_calculation (struct ospf6_area *oa)
{
struct ospf6_route *lsentry, *copy;
void (*hook_add) (struct ospf6_route *) = NULL;
void (*hook_remove) (struct ospf6_route *) = NULL;
- if (IS_OSPF6_DEBUG_ASBR)
- zlog_info ("Intra-area ASBR calculation for area %s", oa->name);
+ if (IS_OSPF6_DEBUG_ROUTE (INTRA))
+ zlog_info ("Border-router calculation for area %s", oa->name);
- hook_add = oa->ospf6->asbr_table->hook_add;
- hook_remove = oa->ospf6->asbr_table->hook_remove;
- oa->ospf6->asbr_table->hook_add = NULL;
- oa->ospf6->asbr_table->hook_remove = NULL;
+ hook_add = oa->ospf6->brouter_table->hook_add;
+ hook_remove = oa->ospf6->brouter_table->hook_remove;
+ oa->ospf6->brouter_table->hook_add = NULL;
+ oa->ospf6->brouter_table->hook_remove = NULL;
- for (lsentry = ospf6_route_head (oa->ospf6->asbr_table); lsentry;
+ /* withdraw the previous router entries for the area */
+ for (lsentry = ospf6_route_head (oa->ospf6->brouter_table); lsentry;
lsentry = ospf6_route_next (lsentry))
{
if (lsentry->path.area_id != oa->area_id)
@@ -1384,20 +1271,21 @@
continue;
if (ospf6_linkstate_prefix_id (&lsentry->prefix) != htonl (0))
continue;
- if (! CHECK_FLAG (lsentry->path.router_bits, OSPF6_ROUTER_BIT_E))
+ if (! CHECK_FLAG (lsentry->path.router_bits, OSPF6_ROUTER_BIT_E) &&
+ ! CHECK_FLAG (lsentry->path.router_bits, OSPF6_ROUTER_BIT_B))
continue;
copy = ospf6_route_copy (lsentry);
copy->type = OSPF6_DEST_TYPE_ROUTER;
copy->prefix.family = AF_INET;
copy->prefix.prefixlen = 32;
- ospf6_route_add (copy, oa->ospf6->asbr_table);
+ ospf6_route_add (copy, oa->ospf6->brouter_table);
}
- oa->ospf6->asbr_table->hook_add = hook_add;
- oa->ospf6->asbr_table->hook_remove = hook_remove;
+ oa->ospf6->brouter_table->hook_add = hook_add;
+ oa->ospf6->brouter_table->hook_remove = hook_remove;
- for (lsentry = ospf6_route_head (oa->ospf6->asbr_table); lsentry;
+ for (lsentry = ospf6_route_head (oa->ospf6->brouter_table); lsentry;
lsentry = ospf6_route_next (lsentry))
{
if (lsentry->path.area_id != oa->area_id)
@@ -1411,7 +1299,7 @@
}
if (CHECK_FLAG (lsentry->flag, OSPF6_ROUTE_REMOVE))
- ospf6_route_remove (lsentry, oa->ospf6->asbr_table);
+ ospf6_route_remove (lsentry, oa->ospf6->brouter_table);
else if (CHECK_FLAG (lsentry->flag, OSPF6_ROUTE_ADD) ||
CHECK_FLAG (lsentry->flag, OSPF6_ROUTE_CHANGE))
{
@@ -1422,27 +1310,45 @@
lsentry->flag = 0;
}
- if (IS_OSPF6_DEBUG_ASBR)
- zlog_info ("Intra-area ASBR calculation for area %s: Done", oa->name);
+ if (IS_OSPF6_DEBUG_ROUTE (INTRA))
+ zlog_info ("Border-router calculation for area %s: Done", oa->name);
}
+struct ospf6_lsa_handler router_handler =
+{
+ OSPF6_LSTYPE_ROUTER,
+ "Router",
+ ospf6_router_lsa_show
+};
+
+struct ospf6_lsa_handler network_handler =
+{
+ OSPF6_LSTYPE_NETWORK,
+ "Network",
+ ospf6_network_lsa_show
+};
+
+struct ospf6_lsa_handler link_handler =
+{
+ OSPF6_LSTYPE_LINK,
+ "Link",
+ ospf6_link_lsa_show
+};
+
+struct ospf6_lsa_handler intra_prefix_handler =
+{
+ OSPF6_LSTYPE_INTRA_PREFIX,
+ "Intra-Prefix",
+ ospf6_intra_prefix_lsa_show
+};
+
void
ospf6_intra_init ()
{
- ospf6_lstype[1].name = "Router";
- ospf6_lstype[2].name = "Network";
- ospf6_lstype[8].name = "Link";
- ospf6_lstype[9].name = "Intra-Prefix";
-
- ospf6_lstype[1].reoriginate = ospf6_router_lsa_reoriginate;
- ospf6_lstype[2].reoriginate = ospf6_network_lsa_reoriginate;
- ospf6_lstype[8].reoriginate = ospf6_link_lsa_reoriginate;
- ospf6_lstype[9].reoriginate = ospf6_intra_prefix_lsa_reoriginate;
-
- ospf6_lstype[1].show = ospf6_router_lsa_show;
- ospf6_lstype[2].show = ospf6_network_lsa_show;
- ospf6_lstype[8].show = ospf6_link_lsa_show;
- ospf6_lstype[9].show = ospf6_intra_prefix_lsa_show;
+ ospf6_install_lsa_handler (&router_handler);
+ ospf6_install_lsa_handler (&network_handler);
+ ospf6_install_lsa_handler (&link_handler);
+ ospf6_install_lsa_handler (&intra_prefix_handler);
}
diff --git a/ospf6d/ospf6_intra.h b/ospf6d/ospf6_intra.h
index 28780b4..db92f7e 100644
--- a/ospf6d/ospf6_intra.h
+++ b/ospf6d/ospf6_intra.h
@@ -128,6 +128,18 @@
oi, 0); \
} while (0)
+#define OSPF6_NETWORK_LSA_EXECUTE(oi) \
+ do { \
+ THREAD_OFF ((oi)->thread_network_lsa); \
+ thread_execute (master, ospf6_network_lsa_originate, oi, 0); \
+ } while (0)
+#define OSPF6_INTRA_PREFIX_LSA_EXECUTE_TRANSIT(oi) \
+ do { \
+ THREAD_OFF ((oi)->thread_intra_prefix_lsa); \
+ thread_execute (master, ospf6_intra_prefix_lsa_originate_transit, oi, 0); \
+ } while (0)
+
+
/* Function Prototypes */
char *ospf6_router_lsdesc_lookup (u_char type, u_int32_t interface_id,
u_int32_t neighbor_interface_id,
@@ -145,7 +157,7 @@
void ospf6_intra_prefix_lsa_remove (struct ospf6_lsa *lsa);
void ospf6_intra_route_calculation (struct ospf6_area *oa);
-void ospf6_intra_asbr_calculation (struct ospf6_area *oa);
+void ospf6_intra_brouter_calculation (struct ospf6_area *oa);
void ospf6_intra_init ();
diff --git a/ospf6d/ospf6_lsa.c b/ospf6d/ospf6_lsa.c
index 56ed318..c031a2d 100644
--- a/ospf6d/ospf6_lsa.c
+++ b/ospf6d/ospf6_lsa.c
@@ -43,7 +43,7 @@
unsigned char conf_debug_ospf6_lsa = 0;
-struct ospf6_lstype ospf6_lstype[OSPF6_LSTYPE_SIZE];
+struct ospf6_lsa_handler *ospf6_lsa_handler[OSPF6_LSTYPE_SIZE];
char *ospf6_lstype_str[OSPF6_LSTYPE_SIZE] =
{"Unknown", "Router", "Network", "Inter-Prefix", "Inter-Router",
@@ -53,10 +53,10 @@
ospf6_lstype_name (u_int16_t type)
{
static char buf[8];
- int index = ntohs (type) & OSPF6_LSTYPE_FCODE_MASK;
+ int index = OSPF6_LSTYPE_INDEX (type);
- if (index < OSPF6_LSTYPE_SIZE && ospf6_lstype_str[index])
- return ospf6_lstype_str[index];
+ if (ospf6_lsa_handler[index])
+ return ospf6_lsa_handler[index]->name;
snprintf (buf, sizeof (buf), "0x%04hx", ntohs (type));
return buf;
@@ -125,8 +125,7 @@
lsa->birth.tv_usec = now.tv_usec;
if (ntohs (lsa->header->age) != MAXAGE)
lsa->expire = thread_add_timer (master, ospf6_lsa_expire, lsa,
- MAXAGE + lsa->birth.tv_sec
- - now.tv_sec);
+ MAXAGE + lsa->birth.tv_sec - now.tv_sec);
else
lsa->expire = NULL;
return;
@@ -272,37 +271,6 @@
}
void
-ospf6_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
-{
- char adv_router[64], id[64];
- int index;
-
- assert (lsa && lsa->header);
-
- inet_ntop (AF_INET, &lsa->header->id, id, sizeof (id));
- inet_ntop (AF_INET, &lsa->header->adv_router,
- adv_router, sizeof (adv_router));
-
- 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);
- vty_out (vty, "Advertising Router: %s%s", adv_router, VNL);
- vty_out (vty, "LS Sequence Number: %#010lx%s",
- (u_long) ntohl (lsa->header->seqnum), VNL);
- vty_out (vty, "CheckSum: %#06hx Length: %hu%s",
- ntohs (lsa->header->checksum),
- ntohs (lsa->header->length), VNL);
-
- index = OSPF6_LSTYPE_INDEX (ntohs (lsa->header->type));
- if (ospf6_lstype[index].show)
- (*ospf6_lstype[index].show) (vty, lsa);
- else
- vty_out (vty, "%sUnknown LSA type ...%s", VNL, VNL);
-
- vty_out (vty, "%s", VNL);
-}
-
-void
ospf6_lsa_show_summary_header (struct vty *vty)
{
vty_out (vty, "%-12s %-15s %-15s %4s %8s %4s %4s %-8s%s",
@@ -360,6 +328,7 @@
}
vty_out (vty, "%s%s", VNL, VNL);
+ return;
}
void
@@ -386,10 +355,44 @@
vty_out (vty, " Prev: %p This: %p Next: %p%s",
lsa->prev, lsa, lsa->next, VNL);
vty_out (vty, "%s", VNL);
+ return;
+}
+
+void
+ospf6_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
+{
+ char adv_router[64], id[64];
+ int index;
+
+ assert (lsa && lsa->header);
+
+ inet_ntop (AF_INET, &lsa->header->id, id, sizeof (id));
+ inet_ntop (AF_INET, &lsa->header->adv_router,
+ adv_router, sizeof (adv_router));
+
+ 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);
+ vty_out (vty, "Advertising Router: %s%s", adv_router, VNL);
+ vty_out (vty, "LS Sequence Number: %#010lx%s",
+ (u_long) ntohl (lsa->header->seqnum), VNL);
+ vty_out (vty, "CheckSum: %#06hx Length: %hu%s",
+ ntohs (lsa->header->checksum),
+ ntohs (lsa->header->length), VNL);
+
+ index = OSPF6_LSTYPE_INDEX (lsa->header->type);
+ if (ospf6_lsa_handler[index]->show)
+ (*ospf6_lsa_handler[index]->show) (vty, lsa);
+ else
+ {
+ ospf6_lsa_show_dump (vty, lsa);
+ vty_out (vty, "%sUnknown LSA type ...%s", VNL, VNL);
+ }
+
+ vty_out (vty, "%s", VNL);
}
/* OSPFv3 LSA creation/deletion function */
-
struct ospf6_lsa *
ospf6_lsa_create (struct ospf6_lsa_header *header)
{
@@ -414,7 +417,6 @@
memset (lsa, 0, sizeof (struct ospf6_lsa));
lsa->header = (struct ospf6_lsa_header *) new_header;
- lsa->headeronly = 0; /* this is not header only */
/* dump string */
ospf6_lsa_printbuf (lsa, lsa->name, sizeof (lsa->name));
@@ -449,7 +451,7 @@
memset (lsa, 0, sizeof (struct ospf6_lsa));
lsa->header = (struct ospf6_lsa_header *) new_header;
- lsa->headeronly = 1; /* this is header only */
+ SET_FLAG (lsa->flag, OSPF6_LSA_HEADERONLY);
/* dump string */
ospf6_lsa_printbuf (lsa, lsa->name, sizeof (lsa->name));
@@ -475,8 +477,8 @@
if (IS_OSPF6_DEBUG_LSA (MEMORY))
zlog_info ("Delete LSA %s Memory: %s (%p/%p)",
- (lsa->headeronly ? "(Header-only) " : ""),
- lsa->name, lsa, lsa->header);
+ (CHECK_FLAG (lsa->flag, OSPF6_LSA_HEADERONLY) ?
+ "(Header-only) " : ""), lsa->name, lsa, lsa->header);
/* do free */
XFREE (MTYPE_OSPF6_LSA, lsa->header);
@@ -492,7 +494,7 @@
zlog_info ("Create LSA Copy from %s", lsa->name);
ospf6_lsa_age_current (lsa);
- if (lsa->headeronly)
+ if (CHECK_FLAG (lsa->flag, OSPF6_LSA_HEADERONLY))
copy = ospf6_lsa_create_headeronly (lsa->header);
else
copy = ospf6_lsa_create (lsa->header);
@@ -500,7 +502,7 @@
copy->installed = lsa->installed;
copy->originated = lsa->originated;
- copy->scope = lsa->scope;
+ copy->lsdb = lsa->lsdb;
return copy;
}
@@ -527,77 +529,12 @@
ospf6_lsa_delete (lsa);
}
-void
-ospf6_lsa_originate (struct ospf6_lsa *lsa)
-{
- struct ospf6_lsa *old;
- struct ospf6_lsdb *lsdb = NULL;
-
- /* find previous LSA */
- lsdb = ospf6_get_scoped_lsdb (lsa->header->type, lsa->scope);
- if (lsdb == NULL)
- {
- zlog_warn ("Can't decide scoped LSDB");
- ospf6_lsa_delete (lsa);
- return;
- }
-
- old = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id,
- lsa->header->adv_router, lsdb);
- if (old)
- {
- /* If this origination is neither different instance nor refresh,
- suppress this origination */
- if (! CHECK_FLAG (old->flag, OSPF6_LSA_REFRESH) &&
- ! OSPF6_LSA_IS_DIFFER (lsa, old))
- {
- if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
- zlog_info ("Suppress updating LSA: %s", lsa->name);
- ospf6_lsa_delete (lsa);
- return;
- }
- }
-
- lsa->refresh = thread_add_timer (master, ospf6_lsa_refresh, lsa,
- LS_REFRESH_TIME);
-
- if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
- {
- zlog_info ("LSA Originate:");
- ospf6_lsa_header_print (lsa);
- }
-
- if (old)
- ospf6_flood_clear (old);
- ospf6_flood_lsa (lsa, NULL);
- ospf6_install_lsa (lsa, lsdb);
-}
-
-void
-ospf6_lsa_re_originate (struct ospf6_lsa *lsa)
-{
- u_int16_t index;
-
- if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
- {
- zlog_info ("LSA Reoriginate:");
- ospf6_lsa_header_print (lsa);
- }
-
- index = OSPF6_LSTYPE_INDEX (ntohs (lsa->header->type));
- if (ospf6_lstype[index].reoriginate)
- (*ospf6_lstype[index].reoriginate) (lsa);
- else
- ospf6_lsa_premature_aging (lsa);
-}
-
/* ospf6 lsa expiry */
int
ospf6_lsa_expire (struct thread *thread)
{
struct ospf6_lsa *lsa;
- struct ospf6_lsdb *lsdb = NULL;
lsa = (struct ospf6_lsa *) THREAD_ARG (thread);
@@ -613,22 +550,16 @@
ospf6_lsa_header_print (lsa);
}
- if (lsa->headeronly)
+ if (CHECK_FLAG (lsa->flag, OSPF6_LSA_HEADERONLY))
return 0; /* dbexchange will do something ... */
/* reflood lsa */
- ospf6_flood_lsa (lsa, NULL);
+ ospf6_flood (NULL, lsa);
/* reinstall lsa */
- lsdb = ospf6_get_scoped_lsdb (lsa->header->type, lsa->scope);
- if (lsdb == NULL)
- {
- zlog_warn ("Can't decide scoped LSDB: %s", lsa->name);
- return 0;
- }
if (IS_OSPF6_DEBUG_LSA (DATABASE))
zlog_info ("Reinstall MaxAge %s", lsa->name);
- ospf6_lsdb_add (lsa, lsdb);
+ ospf6_lsdb_add (lsa, lsa->lsdb);
/* schedule maxage remover */
ospf6_maxage_remove (ospf6);
@@ -636,29 +567,52 @@
return 0;
}
-/* Below will become dummy thread.
- refresh function must be set individually per each LSAs */
int
ospf6_lsa_refresh (struct thread *thread)
{
- struct ospf6_lsa *lsa;
+ struct ospf6_lsa *old, *self, *new;
+ struct ospf6_lsdb *lsdb_self;
assert (thread);
- lsa = (struct ospf6_lsa *) THREAD_ARG (thread);
- assert (lsa && lsa->header);
+ old = (struct ospf6_lsa *) THREAD_ARG (thread);
+ assert (old && old->header);
- lsa->refresh = (struct thread *) NULL;
+ old->refresh = (struct thread *) NULL;
- /* this will be used later to decide really originate or not */
- SET_FLAG (lsa->flag, OSPF6_LSA_REFRESH);
+ lsdb_self = ospf6_get_scoped_lsdb_self (old);
+ self = ospf6_lsdb_lookup (old->header->type, old->header->id,
+ old->header->adv_router, lsdb_self);
+ if (self == NULL)
+ {
+ ospf6_lsa_premature_aging (old);
+ return 0;
+ }
+
+ /* Reset age, increment LS sequence number. */
+ self->header->age = htons (0);
+ self->header->seqnum =
+ ospf6_new_ls_seqnum (self->header->type, self->header->id,
+ self->header->adv_router, old->lsdb);
+ ospf6_lsa_checksum (self->header);
+
+ new = ospf6_lsa_create (self->header);
+ new->lsdb = old->lsdb;
+ new->refresh = thread_add_timer (master, ospf6_lsa_refresh, new,
+ LS_REFRESH_TIME);
+
+ /* store it in the LSDB for self-originated LSAs */
+ ospf6_lsdb_add (ospf6_lsa_copy (new), lsdb_self);
if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
{
zlog_info ("LSA Refresh:");
- ospf6_lsa_header_print (lsa);
+ ospf6_lsa_header_print (new);
}
- ospf6_lsa_re_originate (lsa);
+ ospf6_flood_clear (old);
+ ospf6_flood (NULL, new);
+ ospf6_install_lsa (new);
+
return 0;
}
@@ -708,14 +662,7 @@
}
int
-ospf6_unknown_reoriginate (struct ospf6_lsa *lsa)
-{
- ospf6_lsa_premature_aging (lsa);
- return 0;
-}
-
-int
-ospf6_unknown_show (struct vty *vty, struct ospf6_lsa *lsa)
+ospf6_unknown_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
{
u_char *start, *end, *current;
char byte[4];
@@ -740,13 +687,25 @@
}
void
+ospf6_install_lsa_handler (struct ospf6_lsa_handler *handler)
+{
+ /* might need to adjust dynamic array length ... */
+ int index = OSPF6_LSTYPE_INDEX (htons (handler->type));
+ ospf6_lsa_handler[index] = handler;
+}
+
+struct ospf6_lsa_handler unknown_handler =
+{
+ OSPF6_LSTYPE_UNKNOWN,
+ "Unknown",
+ ospf6_unknown_lsa_show
+};
+
+void
ospf6_lsa_init ()
{
- memset (ospf6_lstype, 0, sizeof (ospf6_lstype));
-
- ospf6_lstype[0].name = "Unknown";
- ospf6_lstype[0].reoriginate = ospf6_unknown_reoriginate;
- ospf6_lstype[0].show = ospf6_unknown_show;
+ memset (ospf6_lsa_handler, 0, sizeof (ospf6_lsa_handler));
+ ospf6_install_lsa_handler (&unknown_handler);
}
diff --git a/ospf6d/ospf6_lsa.h b/ospf6d/ospf6_lsa.h
index dd750e8..54921e1 100644
--- a/ospf6d/ospf6_lsa.h
+++ b/ospf6d/ospf6_lsa.h
@@ -62,11 +62,12 @@
#define OSPF6_LSTYPE_FCODE_MASK 0x1fff
/* LSA scope */
-#define OSPF6_LSA_SCOPE_LINKLOCAL 0x0000
-#define OSPF6_LSA_SCOPE_AREA 0x2000
-#define OSPF6_LSA_SCOPE_AS 0x4000
-#define OSPF6_LSA_SCOPE_RESERVED 0x6000
+#define OSPF6_SCOPE_LINKLOCAL 0x0000
+#define OSPF6_SCOPE_AREA 0x2000
+#define OSPF6_SCOPE_AS 0x4000
+#define OSPF6_SCOPE_RESERVED 0x6000
+/* XXX U-bit handling should be treated here */
#define OSPF6_LSA_SCOPE(type) \
(ntohs (type) & OSPF6_LSTYPE_SCOPE_MASK)
@@ -103,55 +104,46 @@
struct ospf6_lsa
{
- char name[64]; /* dump string */
+ char name[64]; /* dump string */
- struct ospf6_lsa *prev;
- struct ospf6_lsa *next;
+ struct ospf6_lsa *prev;
+ struct ospf6_lsa *next;
- unsigned char lock; /* reference counter */
- unsigned char flag; /* special meaning (e.g. floodback) */
+ unsigned char lock; /* reference counter */
+ unsigned char flag; /* special meaning (e.g. floodback) */
- struct timeval birth; /* tv_sec when LS age 0 */
- struct timeval installed; /* used by MinLSArrival check */
- struct timeval originated; /* used by MinLSInterval check */
+ struct timeval birth; /* tv_sec when LS age 0 */
+ struct timeval installed; /* used by MinLSArrival check */
+ struct timeval originated; /* used by MinLSInterval check */
- struct thread *expire;
- struct thread *refresh; /* For self-originated LSA */
+ struct thread *expire;
+ struct thread *refresh; /* For self-originated LSA */
- void *scope; /* pointer to scope data structure */
- int headeronly; /* indicate this is LS header only */
- int onretrans;
+ int retrans_count;
+
+struct ospf6_lsdb;
+ struct ospf6_lsdb *lsdb;
/* lsa instance */
struct ospf6_lsa_header *header;
};
-#define OSPF6_LSA_FLOODBACK 0x01
-#define OSPF6_LSA_DUPLICATE 0x02
-#define OSPF6_LSA_IMPLIEDACK 0x04
-#define OSPF6_LSA_REFRESH 0x08
+#define OSPF6_LSA_HEADERONLY 0x01
+#define OSPF6_LSA_FLOODBACK 0x02
+#define OSPF6_LSA_DUPLICATE 0x04
+#define OSPF6_LSA_IMPLIEDACK 0x08
-struct ospf6_lstype
+struct ospf6_lsa_handler
{
+ u_int16_t type; /* network byte order */
char *name;
- int (*reoriginate) (struct ospf6_lsa *);
int (*show) (struct vty *, struct ospf6_lsa *);
};
-extern struct ospf6_lstype ospf6_lstype[OSPF6_LSTYPE_SIZE];
#define OSPF6_LSTYPE_INDEX(type) \
- (((type) & OSPF6_LSTYPE_FCODE_MASK) < OSPF6_LSTYPE_SIZE ? \
- ((type) & OSPF6_LSTYPE_FCODE_MASK) : OSPF6_LSTYPE_UNKNOWN)
-
-#if 0
-extern char *ospf6_lstype_str[OSPF6_LSTYPE_SIZE];
-#define OSPF6_LSTYPE_NAME(type) \
((ntohs (type) & OSPF6_LSTYPE_FCODE_MASK) < OSPF6_LSTYPE_SIZE ? \
- ospf6_lstype_str[ntohs (type) & OSPF6_LSTYPE_FCODE_MASK] : \
- ospf6_lstype_str[OSPF6_LSTYPE_UNKNOWN])
-#else /*0*/
+ (ntohs (type) & OSPF6_LSTYPE_FCODE_MASK) : OSPF6_LSTYPE_UNKNOWN)
#define OSPF6_LSTYPE_NAME(type) (ospf6_lstype_name (type))
-#endif /*0*/
/* Macro for LSA Origination */
/* void (CONTINUE_IF_...) (struct prefix *addr); */
@@ -219,11 +211,11 @@
char *ospf6_lsa_printbuf (struct ospf6_lsa *lsa, char *buf, int size);
void ospf6_lsa_header_print_raw (struct ospf6_lsa_header *header);
void ospf6_lsa_header_print (struct ospf6_lsa *lsa);
-void ospf6_lsa_show (struct vty *vty, struct ospf6_lsa *lsa);
void ospf6_lsa_show_summary_header (struct vty *vty);
void ospf6_lsa_show_summary (struct vty *vty, struct ospf6_lsa *lsa);
void ospf6_lsa_show_dump (struct vty *vty, struct ospf6_lsa *lsa);
void ospf6_lsa_show_internal (struct vty *vty, struct ospf6_lsa *lsa);
+void ospf6_lsa_show (struct vty *vty, struct ospf6_lsa *lsa);
struct ospf6_lsa *ospf6_lsa_create (struct ospf6_lsa_header *header);
struct ospf6_lsa *ospf6_lsa_create_headeronly (struct ospf6_lsa_header *header);
@@ -233,8 +225,6 @@
void ospf6_lsa_lock (struct ospf6_lsa *);
void ospf6_lsa_unlock (struct ospf6_lsa *);
-void ospf6_lsa_originate (struct ospf6_lsa *);
-void ospf6_lsa_re_originate (struct ospf6_lsa *lsa);
int ospf6_lsa_expire (struct thread *);
int ospf6_lsa_refresh (struct thread *);
@@ -242,6 +232,7 @@
int ospf6_lsa_prohibited_duration (u_int16_t type, u_int32_t id,
u_int32_t adv_router, void *scope);
+void ospf6_install_lsa_handler (struct ospf6_lsa_handler *handler);
void ospf6_lsa_init ();
int config_write_ospf6_debug_lsa (struct vty *vty);
diff --git a/ospf6d/ospf6_lsdb.c b/ospf6d/ospf6_lsdb.c
index 5c132ca..9b37406 100644
--- a/ospf6d/ospf6_lsdb.c
+++ b/ospf6d/ospf6_lsdb.c
@@ -34,7 +34,7 @@
#include "ospf6d.h"
struct ospf6_lsdb *
-ospf6_lsdb_create ()
+ospf6_lsdb_create (void *data)
{
struct ospf6_lsdb *lsdb;
@@ -46,6 +46,7 @@
}
memset (lsdb, 0, sizeof (struct ospf6_lsdb));
+ lsdb->data = data;
lsdb->table = route_table_init ();
return lsdb;
}
@@ -228,6 +229,7 @@
ospf6_lsa_unlock (lsa);
route_unlock_node (node);
+
ospf6_lsdb_count_assert (lsdb);
}
@@ -475,7 +477,7 @@
if (ntohl (lsa->header->id) < id)
continue;
if (ntohl (lsa->header->id) > id)
- return ((u_int32_t) htonl (id));
+ break;
id++;
}
diff --git a/ospf6d/ospf6_lsdb.h b/ospf6d/ospf6_lsdb.h
index 71d996e..a10f001 100644
--- a/ospf6d/ospf6_lsdb.h
+++ b/ospf6d/ospf6_lsdb.h
@@ -27,6 +27,7 @@
struct ospf6_lsdb
{
+ void *data; /* data structure that holds this lsdb */
struct route_table *table;
u_int32_t count;
void (*hook_add) (struct ospf6_lsa *);
@@ -40,7 +41,7 @@
{ \
if (! OSPF6_LSA_IS_MAXAGE (lsa)) \
continue; \
- if (lsa->onretrans != 0) \
+ if (lsa->retrans_count != 0) \
continue; \
if (IS_OSPF6_DEBUG_LSA (TIMER)) \
zlog_info (" remove maxage %s", lsa->name); \
@@ -49,7 +50,7 @@
} while (0)
/* Function Prototypes */
-struct ospf6_lsdb *ospf6_lsdb_create ();
+struct ospf6_lsdb *ospf6_lsdb_create (void *data);
void ospf6_lsdb_delete (struct ospf6_lsdb *lsdb);
struct ospf6_lsa *ospf6_lsdb_lookup (u_int16_t type, u_int32_t id,
diff --git a/ospf6d/ospf6_message.c b/ospf6d/ospf6_message.c
index 91ecdf4..7e022da 100644
--- a/ospf6d/ospf6_message.c
+++ b/ospf6d/ospf6_message.c
@@ -245,7 +245,7 @@
/* Area-ID check */
if (oh->area_id != oi->area->area_id)
{
- if (oh->area_id == 0)
+ if (oh->area_id == BACKBONE_AREA_ID)
{
if (IS_OSPF6_DEBUG_MESSAGE (type, RECV))
zlog_info ("Message may be via Virtual Link: not supported");
@@ -519,21 +519,34 @@
struct ospf6_lsdb *lsdb = NULL;
his = ospf6_lsa_create_headeronly ((struct ospf6_lsa_header *) p);
- his->scope = ospf6_get_lsa_scope (his->header->type, on);
- lsdb = ospf6_get_scoped_lsdb (his->header->type, his->scope);
- if (lsdb == NULL)
+
+ if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
+ zlog_info ("%s", his->name);
+
+ switch (OSPF6_LSA_SCOPE (his->header->type))
{
- zlog_warn ("Can't decide scoped LSDB");
+ case OSPF6_SCOPE_LINKLOCAL:
+ lsdb = on->ospf6_if->lsdb;
+ break;
+ case OSPF6_SCOPE_AREA:
+ lsdb = on->ospf6_if->area->lsdb;
+ break;
+ case OSPF6_SCOPE_AS:
+ lsdb = on->ospf6_if->area->ospf6->lsdb;
+ break;
+ case OSPF6_SCOPE_RESERVED:
+ if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
+ zlog_info ("Ignoring LSA of reserved scope");
ospf6_lsa_delete (his);
- thread_add_event (master, seqnumber_mismatch, on, 0);
- return;
+ continue;
+ break;
}
if (ntohs (his->header->type) == OSPF6_LSTYPE_AS_EXTERNAL &&
- ospf6_area_is_stub (on->ospf6_if->area))
+ IS_AREA_STUB (on->ospf6_if->area))
{
if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
- zlog_info ("E-bit mismatch with LSA Headers");
+ zlog_info ("SeqNumMismatch (E-bit mismatch), discard");
ospf6_lsa_delete (his);
thread_add_event (master, seqnumber_mismatch, on, 0);
return;
@@ -541,14 +554,24 @@
mine = ospf6_lsdb_lookup (his->header->type, his->header->id,
his->header->adv_router, lsdb);
- if (mine == NULL || ospf6_lsa_compare (his, mine) < 0)
+ if (mine == NULL)
{
- if (IS_OSPF6_DEBUG_LSA (RECV) || IS_OSPF6_DEBUG_LSA (DATABASE))
- zlog_info ("Add %s's request-list: %s", on->name, his->name);
+ if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
+ zlog_info ("Add request (No database copy)", his->name);
+ ospf6_lsdb_add (his, on->request_list);
+ }
+ else if (ospf6_lsa_compare (his, mine) < 0)
+ {
+ if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
+ zlog_info ("Add request (Received MoreRecent)", his->name);
ospf6_lsdb_add (his, on->request_list);
}
else
- ospf6_lsa_delete (his);
+ {
+ if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
+ zlog_info ("Discard (Existing MoreRecent)", his->name);
+ ospf6_lsa_delete (his);
+ }
}
if (p != OSPF6_MESSAGE_END (oh))
@@ -721,18 +744,28 @@
struct ospf6_lsdb *lsdb = NULL;
his = ospf6_lsa_create_headeronly ((struct ospf6_lsa_header *) p);
- his->scope = ospf6_get_lsa_scope (his->header->type, on);
- lsdb = ospf6_get_scoped_lsdb (his->header->type, his->scope);
- if (lsdb == NULL)
+
+ switch (OSPF6_LSA_SCOPE (his->header->type))
{
- zlog_warn ("Can't decide scoped LSDB");
+ case OSPF6_SCOPE_LINKLOCAL:
+ lsdb = on->ospf6_if->lsdb;
+ break;
+ case OSPF6_SCOPE_AREA:
+ lsdb = on->ospf6_if->area->lsdb;
+ break;
+ case OSPF6_SCOPE_AS:
+ lsdb = on->ospf6_if->area->ospf6->lsdb;
+ break;
+ case OSPF6_SCOPE_RESERVED:
+ if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
+ zlog_info ("Ignoring LSA of reserved scope");
ospf6_lsa_delete (his);
- thread_add_event (master, seqnumber_mismatch, on, 0);
- return;
+ continue;
+ break;
}
- if (ntohs (his->header->type) == OSPF6_LSTYPE_AS_EXTERNAL &&
- ospf6_area_is_stub (on->ospf6_if->area))
+ if (OSPF6_LSA_SCOPE (his->header->type) == OSPF6_SCOPE_AS &&
+ IS_AREA_STUB (on->ospf6_if->area))
{
if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
zlog_info ("E-bit mismatch with LSA Headers");
@@ -745,8 +778,8 @@
his->header->adv_router, lsdb);
if (mine == NULL || ospf6_lsa_compare (his, mine) < 0)
{
- if (IS_OSPF6_DEBUG_LSA (RECV) || IS_OSPF6_DEBUG_LSA (DATABASE))
- zlog_info ("Add %s to request-list of %s", his->name, on->name);
+ if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
+ zlog_info ("Add request-list: %s", his->name);
ospf6_lsdb_add (his, on->request_list);
}
else
@@ -838,7 +871,6 @@
struct ospf6_neighbor *on;
char *p;
struct ospf6_lsreq_entry *e;
- void *scope = NULL;
struct ospf6_lsdb *lsdb = NULL;
struct ospf6_lsa *lsa;
@@ -875,8 +907,24 @@
p += sizeof (struct ospf6_lsreq_entry))
{
e = (struct ospf6_lsreq_entry *) p;
- scope = ospf6_get_lsa_scope (e->type, on);
- lsdb = ospf6_get_scoped_lsdb (e->type, scope);
+
+ switch (OSPF6_LSA_SCOPE (e->type))
+ {
+ case OSPF6_SCOPE_LINKLOCAL:
+ lsdb = on->ospf6_if->lsdb;
+ break;
+ case OSPF6_SCOPE_AREA:
+ lsdb = on->ospf6_if->area->lsdb;
+ break;
+ case OSPF6_SCOPE_AS:
+ lsdb = on->ospf6_if->area->ospf6->lsdb;
+ break;
+ default:
+ if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
+ zlog_info ("Ignoring LSA of reserved scope");
+ continue;
+ break;
+ }
/* Find database copy */
lsa = ospf6_lsdb_lookup (e->type, e->id, e->adv_router, lsdb);
@@ -895,9 +943,6 @@
return;
}
- if (IS_OSPF6_DEBUG_LSA (DATABASE))
- zlog_info ("Add copy of %s to lsupdate_list of %s",
- lsa->name, on->name);
ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->lsupdate_list);
}
@@ -969,7 +1014,7 @@
break;
}
- ospf6_receive_lsa ((struct ospf6_lsa_header *) p, on);
+ ospf6_receive_lsa (on, (struct ospf6_lsa_header *) p);
num--;
}
@@ -1041,11 +1086,27 @@
p += sizeof (struct ospf6_lsa_header))
{
his = ospf6_lsa_create_headeronly ((struct ospf6_lsa_header *) p);
- his->scope = ospf6_get_lsa_scope (his->header->type, on);
- lsdb = ospf6_get_scoped_lsdb (his->header->type, his->scope);
- if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV) ||
- IS_OSPF6_DEBUG_LSA (SEND))
+ switch (OSPF6_LSA_SCOPE (his->header->type))
+ {
+ case OSPF6_SCOPE_LINKLOCAL:
+ lsdb = on->ospf6_if->lsdb;
+ break;
+ case OSPF6_SCOPE_AREA:
+ lsdb = on->ospf6_if->area->lsdb;
+ break;
+ case OSPF6_SCOPE_AS:
+ lsdb = on->ospf6_if->area->ospf6->lsdb;
+ break;
+ case OSPF6_SCOPE_RESERVED:
+ if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
+ zlog_info ("Ignoring LSA of reserved scope");
+ ospf6_lsa_delete (his);
+ continue;
+ break;
+ }
+
+ if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
zlog_info ("%s acknowledged by %s", his->name, on->name);
/* Find database copy */
@@ -1080,18 +1141,14 @@
continue;
}
- if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV) ||
- IS_OSPF6_DEBUG_LSA (SEND))
+ if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
zlog_info ("Acknowledged, remove from %s's retrans-list",
on->name);
if (OSPF6_LSA_IS_MAXAGE (mine))
ospf6_maxage_remove (on->ospf6_if->area->ospf6);
- if (IS_OSPF6_DEBUG_LSA (DATABASE))
- zlog_info ("remove %s from retrans_list of %s",
- mine->name, on->name);
- ospf6_decrement_onretrans (mine);
+ ospf6_decrement_retrans_count (mine);
ospf6_lsdb_remove (mine, on->retrans_list);
ospf6_lsa_delete (his);
}
@@ -1473,8 +1530,6 @@
unsigned int size = 0;
on = (struct ospf6_neighbor *) THREAD_ARG (thread);
- if (IS_OSPF6_DEBUG_LSA (DATABASE))
- zlog_info ("Remove entire dbdesc_list of %s: sending newone", on->name);
ospf6_lsdb_remove_all (on->dbdesc_list);
/* move LSAs from summary_list to dbdesc_list (within neighbor structure)
@@ -1489,9 +1544,6 @@
break;
}
- if (IS_OSPF6_DEBUG_LSA (DATABASE))
- zlog_info ("Move %s from summary_list to dbdesc_list of %s",
- lsa->name, on->name);
ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->dbdesc_list);
ospf6_lsdb_remove (lsa, on->summary_list);
size += sizeof (struct ospf6_lsa_header);
@@ -1587,21 +1639,25 @@
on = (struct ospf6_neighbor *) THREAD_ARG (thread);
on->thread_send_lsupdate = (struct thread *) NULL;
+ if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
+ zlog_info ("LSUpdate to neighbor %s", on->name);
+
if (on->state < OSPF6_NEIGHBOR_EXCHANGE)
{
if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
- zlog_info ("Quit to send LSUpdate to neighbor %s state %s",
- on->name, ospf6_neighbor_state_str[on->state]);
+ zlog_info ("Quit to send (neighbor state %s)",
+ ospf6_neighbor_state_str[on->state]);
return 0;
}
/* if we have nothing to send, return */
if (on->lsupdate_list->count == 0 &&
on->retrans_list->count == 0)
- return 0;
-
- if (IS_OSPF6_DEBUG_LSA (SEND))
- zlog_info ("LSA Send to %s", on->name);
+ {
+ if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
+ zlog_info ("Quit to send (nothing to send)");
+ return 0;
+ }
memset (sendbuf, 0, iobuflen);
oh = (struct ospf6_header *) sendbuf;
@@ -1623,9 +1679,6 @@
break;
}
- if (IS_OSPF6_DEBUG_LSA (SEND))
- ospf6_lsa_header_print (lsa);
-
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);
@@ -1645,9 +1698,6 @@
break;
}
- if (IS_OSPF6_DEBUG_LSA (SEND))
- ospf6_lsa_header_print (lsa);
-
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);
diff --git a/ospf6d/ospf6_neighbor.c b/ospf6d/ospf6_neighbor.c
index a4823d2..e7818ab 100644
--- a/ospf6d/ospf6_neighbor.c
+++ b/ospf6d/ospf6_neighbor.c
@@ -51,7 +51,7 @@
{
struct ospf6_neighbor *ona = (struct ospf6_neighbor *) va;
struct ospf6_neighbor *onb = (struct ospf6_neighbor *) vb;
- return (ntohl (ona->router_id) - ntohl (onb->router_id));
+ return (ntohl (ona->router_id) < ntohl (onb->router_id) ? -1 : 1);
}
struct ospf6_neighbor *
@@ -94,14 +94,14 @@
gettimeofday (&on->last_changed, (struct timezone *) NULL);
on->router_id = router_id;
- on->summary_list = ospf6_lsdb_create ();
- on->request_list = ospf6_lsdb_create ();
- on->retrans_list = ospf6_lsdb_create ();
+ on->summary_list = ospf6_lsdb_create (on);
+ on->request_list = ospf6_lsdb_create (on);
+ on->retrans_list = ospf6_lsdb_create (on);
- on->dbdesc_list = ospf6_lsdb_create ();
- on->lsreq_list = ospf6_lsdb_create ();
- on->lsupdate_list = ospf6_lsdb_create ();
- on->lsack_list = ospf6_lsdb_create ();
+ 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);
listnode_add_sort (oi->neighbor_list, on);
return on;
@@ -117,7 +117,7 @@
for (lsa = ospf6_lsdb_head (on->retrans_list); lsa;
lsa = ospf6_lsdb_next (lsa))
{
- ospf6_decrement_onretrans (lsa);
+ ospf6_decrement_retrans_count (lsa);
ospf6_lsdb_remove (lsa, on->retrans_list);
}
@@ -286,7 +286,7 @@
for (lsa = ospf6_lsdb_head (on->retrans_list); lsa;
lsa = ospf6_lsdb_next (lsa))
{
- ospf6_decrement_onretrans (lsa);
+ ospf6_decrement_retrans_count (lsa);
ospf6_lsdb_remove (lsa, on->retrans_list);
}
@@ -300,7 +300,7 @@
"summary_list"), on->name);
if (OSPF6_LSA_IS_MAXAGE (lsa))
{
- lsa->onretrans++;
+ ospf6_increment_retrans_count (lsa);
ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->retrans_list);
}
else
@@ -317,7 +317,7 @@
"summary_list"), on->name);
if (OSPF6_LSA_IS_MAXAGE (lsa))
{
- lsa->onretrans++;
+ ospf6_increment_retrans_count (lsa);
ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->retrans_list);
}
else
@@ -334,7 +334,7 @@
"summary_list"), on->name);
if (OSPF6_LSA_IS_MAXAGE (lsa))
{
- lsa->onretrans++;
+ ospf6_increment_retrans_count (lsa);
ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->retrans_list);
}
else
@@ -431,7 +431,7 @@
for (lsa = ospf6_lsdb_head (on->retrans_list); lsa;
lsa = ospf6_lsdb_next (lsa))
{
- ospf6_decrement_onretrans (lsa);
+ ospf6_decrement_retrans_count (lsa);
ospf6_lsdb_remove (lsa, on->retrans_list);
}
}
@@ -464,7 +464,7 @@
for (lsa = ospf6_lsdb_head (on->retrans_list); lsa;
lsa = ospf6_lsdb_next (lsa))
{
- ospf6_decrement_onretrans (lsa);
+ ospf6_decrement_retrans_count (lsa);
ospf6_lsdb_remove (lsa, on->retrans_list);
}
@@ -500,7 +500,7 @@
for (lsa = ospf6_lsdb_head (on->retrans_list); lsa;
lsa = ospf6_lsdb_next (lsa))
{
- ospf6_decrement_onretrans (lsa);
+ ospf6_decrement_retrans_count (lsa);
ospf6_lsdb_remove (lsa, on->retrans_list);
}
@@ -534,7 +534,7 @@
for (lsa = ospf6_lsdb_head (on->retrans_list); lsa;
lsa = ospf6_lsdb_next (lsa))
{
- ospf6_decrement_onretrans (lsa);
+ ospf6_decrement_retrans_count (lsa);
ospf6_lsdb_remove (lsa, on->retrans_list);
}
diff --git a/ospf6d/ospf6_proto.c b/ospf6d/ospf6_proto.c
index 7ee7e0a..5b47cf8 100644
--- a/ospf6d/ospf6_proto.c
+++ b/ospf6d/ospf6_proto.c
@@ -36,12 +36,15 @@
offset = op->prefix_length % 8;
mask = 0xff << (8 - offset);
- if (index >= 16)
+ if (index > 16)
{
- zlog_warn ("Apply mask to ospf6_prefix failed");
+ zlog_warn ("Prefix length too long: %d", op->prefix_length);
return;
}
+ if (index == 16)
+ return;
+
pnt[index] &= mask;
index ++;
diff --git a/ospf6d/ospf6_route.c b/ospf6d/ospf6_route.c
index 9e64ea0..1202a3a 100644
--- a/ospf6d/ospf6_route.c
+++ b/ospf6d/ospf6_route.c
@@ -1069,6 +1069,32 @@
return CMD_SUCCESS;
}
+void
+ospf6_brouter_show_header (struct vty *vty)
+{
+ vty_out (vty, "%-15s %-8s %-14s %-10s %-15s%s",
+ "Router-ID", "Rtr-Bits", "Options", "Path-Type", "Area", VNL);
+}
+
+void
+ospf6_brouter_show (struct vty *vty, struct ospf6_route *route)
+{
+ u_int32_t adv_router;
+ char adv[16], rbits[16], options[16], area[16];
+
+ adv_router = ospf6_linkstate_prefix_adv_router (&route->prefix);
+ inet_ntop (AF_INET, &adv_router, adv, sizeof (adv));
+ ospf6_capability_printbuf (route->path.router_bits, rbits, sizeof (rbits));
+ ospf6_options_printbuf (route->path.options, options, sizeof (options));
+ inet_ntop (AF_INET, &route->path.area_id, area, sizeof (area));
+
+ /* vty_out (vty, "%-15s %-8s %-14s %-10s %-15s%s",
+ "Router-ID", "Rtr-Bits", "Options", "Path-Type", "Area", VNL); */
+ vty_out (vty, "%-15s %-8s %-14s %-10s %-15s%s",
+ adv, rbits, options, OSPF6_PATH_TYPE_NAME (route->path.type),
+ area, VNL);
+}
+
DEFUN (debug_ospf6_route,
debug_ospf6_route_cmd,
"debug ospf6 route (table|intra-area|inter-area)",
diff --git a/ospf6d/ospf6_route.h b/ospf6d/ospf6_route.h
index f58a801..333b2ce 100644
--- a/ospf6d/ospf6_route.h
+++ b/ospf6d/ospf6_route.h
@@ -90,6 +90,7 @@
/* Path-type */
u_char type;
+ u_char subtype; /* only used for redistribute i.e ZEBRA_ROUTE_XXX */
/* Cost */
u_int8_t metric_type;
@@ -97,12 +98,13 @@
u_int32_t cost_e2;
};
-#define OSPF6_PATH_TYPE_NONE 0
-#define OSPF6_PATH_TYPE_INTRA 1
-#define OSPF6_PATH_TYPE_INTER 2
-#define OSPF6_PATH_TYPE_EXTERNAL1 3
-#define OSPF6_PATH_TYPE_EXTERNAL2 4
-#define OSPF6_PATH_TYPE_MAX 5
+#define OSPF6_PATH_TYPE_NONE 0
+#define OSPF6_PATH_TYPE_INTRA 1
+#define OSPF6_PATH_TYPE_INTER 2
+#define OSPF6_PATH_TYPE_EXTERNAL1 3
+#define OSPF6_PATH_TYPE_EXTERNAL2 4
+#define OSPF6_PATH_TYPE_REDISTRIBUTE 5
+#define OSPF6_PATH_TYPE_MAX 6
#include "prefix.h"
#include "table.h"
@@ -147,13 +149,15 @@
#define OSPF6_DEST_TYPE_NETWORK 2
#define OSPF6_DEST_TYPE_DISCARD 3
#define OSPF6_DEST_TYPE_LINKSTATE 4
-#define OSPF6_DEST_TYPE_MAX 5
+#define OSPF6_DEST_TYPE_RANGE 5
+#define OSPF6_DEST_TYPE_MAX 6
-#define OSPF6_ROUTE_CHANGE 0x01
-#define OSPF6_ROUTE_ADD 0x02
-#define OSPF6_ROUTE_REMOVE 0x04
-#define OSPF6_ROUTE_BEST 0x08
-#define OSPF6_ROUTE_HAVE_LONGER 0x10
+#define OSPF6_ROUTE_CHANGE 0x01
+#define OSPF6_ROUTE_ADD 0x02
+#define OSPF6_ROUTE_REMOVE 0x04
+#define OSPF6_ROUTE_BEST 0x08
+#define OSPF6_ROUTE_ACTIVE_SUMMARY 0x08
+#define OSPF6_ROUTE_DO_NOT_ADVERTISE 0x10
struct ospf6_route_table
{
@@ -252,11 +256,18 @@
void ospf6_route_table_delete (struct ospf6_route_table *);
void ospf6_route_dump (struct ospf6_route_table *table);
+
+void ospf6_route_show (struct vty *vty, struct ospf6_route *route);
+void ospf6_route_show_detail (struct vty *vty, struct ospf6_route *route);
+
int ospf6_route_table_show (struct vty *, int, char **,
struct ospf6_route_table *);
int ospf6_lsentry_table_show (struct vty *, int, char **,
struct ospf6_route_table *);
+void ospf6_brouter_show_header (struct vty *vty);
+void ospf6_brouter_show (struct vty *vty, struct ospf6_route *route);
+
int config_write_ospf6_debug_route (struct vty *vty);
void install_element_ospf6_debug_route ();
void ospf6_route_init ();
diff --git a/ospf6d/ospf6_spf.c b/ospf6d/ospf6_spf.c
index 285d4bb..d3c0f81 100644
--- a/ospf6d/ospf6_spf.c
+++ b/ospf6d/ospf6_spf.c
@@ -342,8 +342,11 @@
/* There should be no case where candidate being installed (variable
"v") is closer than the one in the SPF tree (variable "route").
- In the case something's gone wrong with the behavior of
+ In the case something has gone wrong with the behavior of
Priority-Queue. */
+
+ /* the case where the route exists already is handled and returned
+ up to here. */
assert (route == NULL);
route = ospf6_route_create ();
@@ -387,6 +390,8 @@
}
}
+/* RFC2328 16.1. Calculating the shortest-path tree for an area */
+/* RFC2740 3.8.1. Calculating the shortest path tree for an area */
void
ospf6_spf_calculation (u_int32_t router_id,
struct ospf6_route_table *result_table,
@@ -415,7 +420,7 @@
root->area = oa;
root->cost = 0;
root->hops = 0;
- root->nexthop[0].ifindex = 0; /* should have been loopbak I/F ... */
+ root->nexthop[0].ifindex = 0; /* loopbak I/F is better ... */
inet_pton (AF_INET6, "::1", &root->nexthop[0].address);
/* Actually insert root to the candidate-list as the only candidate */
@@ -427,7 +432,7 @@
/* get closest candidate from priority queue */
v = pqueue_dequeue (candidate_list);
- /* install may result in merging and rejecting of the vertex */
+ /* installing may result in merging or rejecting of the vertex */
if (ospf6_spf_install (v, result_table) < 0)
continue;
@@ -507,7 +512,7 @@
}
ospf6_intra_route_calculation (oa);
- ospf6_intra_asbr_calculation (oa);
+ ospf6_intra_brouter_calculation (oa);
return 0;
}
diff --git a/ospf6d/ospf6_top.c b/ospf6d/ospf6_top.c
index 4a33d47..865a116 100644
--- a/ospf6d/ospf6_top.c
+++ b/ospf6d/ospf6_top.c
@@ -42,8 +42,10 @@
#include "ospf6_interface.h"
#include "ospf6_neighbor.h"
+#include "ospf6_flood.h"
#include "ospf6_asbr.h"
#include "ospf6_abr.h"
+#include "ospf6_intra.h"
#include "ospf6d.h"
/* global ospf6d variable */
@@ -84,17 +86,31 @@
void
ospf6_top_route_hook_add (struct ospf6_route *route)
{
- ospf6_abr_originate_prefix (route, ospf6);
+ ospf6_abr_originate_summary (route);
ospf6_zebra_route_update_add (route);
}
void
ospf6_top_route_hook_remove (struct ospf6_route *route)
{
- ospf6_abr_originate_prefix (route, ospf6);
+ ospf6_abr_originate_summary (route);
ospf6_zebra_route_update_remove (route);
}
+void
+ospf6_top_brouter_hook_add (struct ospf6_route *route)
+{
+ ospf6_abr_originate_summary (route);
+ ospf6_asbr_lsentry_add (route);
+}
+
+void
+ospf6_top_brouter_hook_remove (struct ospf6_route *route)
+{
+ ospf6_abr_originate_summary (route);
+ ospf6_asbr_lsentry_remove (route);
+}
+
struct ospf6 *
ospf6_create ()
{
@@ -107,7 +123,8 @@
gettimeofday (&o->starttime, (struct timezone *) NULL);
o->area_list = list_new ();
o->area_list->cmp = ospf6_area_cmp;
- o->lsdb = ospf6_lsdb_create ();
+ o->lsdb = ospf6_lsdb_create (o);
+ o->lsdb_self = ospf6_lsdb_create (o);
o->lsdb->hook_add = ospf6_top_lsdb_hook_add;
o->lsdb->hook_remove = ospf6_top_lsdb_hook_remove;
@@ -115,11 +132,9 @@
o->route_table->hook_add = ospf6_top_route_hook_add;
o->route_table->hook_remove = ospf6_top_route_hook_remove;
- o->asbr_table = ospf6_route_table_create ();
- o->asbr_table->hook_add = ospf6_asbr_lsentry_add;
- o->asbr_table->hook_remove = ospf6_asbr_lsentry_remove;
-
o->brouter_table = ospf6_route_table_create ();
+ o->brouter_table->hook_add = ospf6_top_brouter_hook_add;
+ o->brouter_table->hook_remove = ospf6_top_brouter_hook_remove;
o->external_table = ospf6_route_table_create ();
o->external_id_table = route_table_init ();
@@ -140,9 +155,9 @@
}
ospf6_lsdb_delete (o->lsdb);
+ ospf6_lsdb_delete (o->lsdb_self);
ospf6_route_table_delete (o->route_table);
- ospf6_route_table_delete (o->asbr_table);
ospf6_route_table_delete (o->brouter_table);
ospf6_route_table_delete (o->external_table);
@@ -185,7 +200,7 @@
ospf6_lsdb_remove_all (o->lsdb);
ospf6_route_remove_all (o->route_table);
- ospf6_route_remove_all (o->asbr_table);
+ ospf6_route_remove_all (o->brouter_table);
}
}
@@ -320,10 +335,12 @@
)
{
struct ospf6 *o;
- struct ospf6_area *oa;
+ struct ospf6_area *oa, *area;
struct ospf6_interface *oi;
struct interface *ifp;
u_int32_t area_id;
+ listnode node;
+ struct ospf6_route *ro;
o = (struct ospf6 *) vty->index;
@@ -355,8 +372,31 @@
listnode_add (oa->if_list, oi); /* sort ?? */
oi->area = oa;
+ SET_FLAG (oa->flag, OSPF6_AREA_ENABLE);
+
/* start up */
thread_add_event (master, interface_up, oi, 0);
+
+ /* ABR stuff, redistribute inter-area LSAs and
+ re-originate Router-LSA (B-bit may have been changed) */
+ for (node = listhead (o->area_list); node; nextnode (node))
+ {
+ area = OSPF6_AREA (getdata (node));
+ OSPF6_ROUTER_LSA_SCHEDULE (area);
+
+ for (ro = ospf6_route_head (area->range_table); ro;
+ ro = ospf6_route_next (ro))
+ ospf6_abr_originate_summary_to_area (ro, oa);
+ }
+
+ for (ro = ospf6_route_head (o->brouter_table); ro;
+ ro = ospf6_route_next (ro))
+ ospf6_abr_originate_summary_to_area (ro, oa);
+
+ for (ro = ospf6_route_head (o->route_table); ro;
+ ro = ospf6_route_next (ro))
+ ospf6_abr_originate_summary_to_area (ro, oa);
+
return CMD_SUCCESS;
}
@@ -372,8 +412,12 @@
{
struct ospf6 *o;
struct ospf6_interface *oi;
+ struct ospf6_area *oa, *area;
struct interface *ifp;
u_int32_t area_id;
+ listnode node;
+ struct ospf6_route *ro;
+ struct ospf6_lsa *old;
o = (struct ospf6 *) vty->index;
@@ -407,9 +451,45 @@
thread_execute (master, interface_down, oi, 0);
+ oa = oi->area;
listnode_delete (oi->area->if_list, oi);
oi->area = (struct ospf6_area *) NULL;
+ /* Withdraw inter-area routes from this area, if necessary */
+ if (oa->if_list->count == 0)
+ {
+ UNSET_FLAG (oa->flag, OSPF6_AREA_ENABLE);
+
+ for (ro = ospf6_route_head (oa->summary_prefix); ro;
+ ro = ospf6_route_next (ro))
+ {
+ old = ospf6_lsdb_lookup (ro->path.origin.type,
+ ro->path.origin.id,
+ oa->ospf6->router_id, oa->lsdb);
+ if (old)
+ ospf6_lsa_purge (old);
+ ospf6_route_remove (ro, oa->summary_prefix);
+ }
+ for (ro = ospf6_route_head (oa->summary_router); ro;
+ ro = ospf6_route_next (ro))
+ {
+ old = ospf6_lsdb_lookup (ro->path.origin.type,
+ ro->path.origin.id,
+ oa->ospf6->router_id, oa->lsdb);
+ if (old)
+ ospf6_lsa_purge (old);
+ ospf6_route_remove (ro, oa->summary_router);
+ }
+ }
+
+ /* Schedule Refreshment of Router-LSA for each area
+ (ABR status may change) */
+ for (node = listhead (o->area_list); node; nextnode (node))
+ {
+ area = OSPF6_AREA (getdata (node));
+ OSPF6_ROUTER_LSA_SCHEDULE (area);
+ }
+
return CMD_SUCCESS;
}
@@ -562,6 +642,7 @@
vty_out (vty, " router-id %s%s", router_id, VNL);
ospf6_redistribute_config_write (vty);
+ ospf6_area_config_write (vty);
for (j = listhead (ospf6->area_list); j; nextnode (j))
{
diff --git a/ospf6d/ospf6_top.h b/ospf6d/ospf6_top.h
index f48b7f6..d831d94 100644
--- a/ospf6d/ospf6_top.h
+++ b/ospf6d/ospf6_top.h
@@ -38,9 +38,9 @@
/* AS scope link state database */
struct ospf6_lsdb *lsdb;
+ struct ospf6_lsdb *lsdb_self;
struct ospf6_route_table *route_table;
- struct ospf6_route_table *asbr_table;
struct ospf6_route_table *brouter_table;
struct ospf6_route_table *external_table;
diff --git a/ospf6d/ospf6d.c b/ospf6d/ospf6d.c
index 4eba8a4..6cc0764 100644
--- a/ospf6d/ospf6d.c
+++ b/ospf6d/ospf6d.c
@@ -140,7 +140,8 @@
return prev;
}
-
+
+/* show database functions */
DEFUN (show_version_ospf6,
show_version_ospf6_cmd,
"show version ospf6",
@@ -186,7 +187,7 @@
static int
parse_show_level (int argc, char **argv)
{
- int level;
+ int level = 0;
if (argc)
{
if (! strncmp (argv[0], "de", 2))
@@ -204,7 +205,7 @@
static u_int16_t
parse_type_spec (int argc, char **argv)
{
- u_int16_t type;
+ u_int16_t type = 0;
assert (argc);
if (! strcmp (argv[0], "router"))
type = htons (OSPF6_LSTYPE_ROUTER);
@@ -316,7 +317,7 @@
switch (OSPF6_LSA_SCOPE (type))
{
- case OSPF6_LSA_SCOPE_AREA:
+ case OSPF6_SCOPE_AREA:
for (i = listhead (o->area_list); i; nextnode (i))
{
oa = (struct ospf6_area *) getdata (i);
@@ -325,7 +326,7 @@
}
break;
- case OSPF6_LSA_SCOPE_LINKLOCAL:
+ case OSPF6_SCOPE_LINKLOCAL:
for (i = listhead (o->area_list); i; nextnode (i))
{
oa = (struct ospf6_area *) getdata (i);
@@ -339,7 +340,7 @@
}
break;
- case OSPF6_LSA_SCOPE_AS:
+ case OSPF6_SCOPE_AS:
vty_out (vty, AS_LSDB_TITLE_FORMAT, VNL, VNL, VNL);
ospf6_lsdb_show (vty, level, &type, NULL, NULL, o->lsdb);
break;
@@ -623,7 +624,7 @@
switch (OSPF6_LSA_SCOPE (type))
{
- case OSPF6_LSA_SCOPE_AREA:
+ case OSPF6_SCOPE_AREA:
for (i = listhead (o->area_list); i; nextnode (i))
{
oa = (struct ospf6_area *) getdata (i);
@@ -632,7 +633,7 @@
}
break;
- case OSPF6_LSA_SCOPE_LINKLOCAL:
+ case OSPF6_SCOPE_LINKLOCAL:
for (i = listhead (o->area_list); i; nextnode (i))
{
oa = (struct ospf6_area *) getdata (i);
@@ -646,7 +647,7 @@
}
break;
- case OSPF6_LSA_SCOPE_AS:
+ case OSPF6_SCOPE_AS:
vty_out (vty, AS_LSDB_TITLE_FORMAT, VNL, VNL, VNL);
ospf6_lsdb_show (vty, level, &type, &id, NULL, o->lsdb);
break;
@@ -782,7 +783,7 @@
switch (OSPF6_LSA_SCOPE (type))
{
- case OSPF6_LSA_SCOPE_AREA:
+ case OSPF6_SCOPE_AREA:
for (i = listhead (o->area_list); i; nextnode (i))
{
oa = (struct ospf6_area *) getdata (i);
@@ -791,7 +792,7 @@
}
break;
- case OSPF6_LSA_SCOPE_LINKLOCAL:
+ case OSPF6_SCOPE_LINKLOCAL:
for (i = listhead (o->area_list); i; nextnode (i))
{
oa = (struct ospf6_area *) getdata (i);
@@ -805,7 +806,7 @@
}
break;
- case OSPF6_LSA_SCOPE_AS:
+ case OSPF6_SCOPE_AS:
vty_out (vty, AS_LSDB_TITLE_FORMAT, VNL, VNL, VNL);
ospf6_lsdb_show (vty, level, &type, NULL, &adv_router, o->lsdb);
break;
@@ -918,7 +919,7 @@
if ((inet_pton (AF_INET, argv[0], &id)) != 1)
{
vty_out (vty, "Link state ID is not parsable: %s%s",
- argv[1], VNL);
+ argv[0], VNL);
return CMD_SUCCESS;
}
@@ -1014,7 +1015,7 @@
if ((inet_pton (AF_INET, argv[0], &id)) != 1)
{
vty_out (vty, "Link state ID is not parsable: %s%s",
- argv[1], VNL);
+ argv[0], VNL);
return CMD_SUCCESS;
}
@@ -1125,7 +1126,7 @@
switch (OSPF6_LSA_SCOPE (type))
{
- case OSPF6_LSA_SCOPE_AREA:
+ case OSPF6_SCOPE_AREA:
for (i = listhead (o->area_list); i; nextnode (i))
{
oa = (struct ospf6_area *) getdata (i);
@@ -1134,7 +1135,7 @@
}
break;
- case OSPF6_LSA_SCOPE_LINKLOCAL:
+ case OSPF6_SCOPE_LINKLOCAL:
for (i = listhead (o->area_list); i; nextnode (i))
{
oa = (struct ospf6_area *) getdata (i);
@@ -1148,7 +1149,7 @@
}
break;
- case OSPF6_LSA_SCOPE_AS:
+ case OSPF6_SCOPE_AS:
vty_out (vty, AS_LSDB_TITLE_FORMAT, VNL, VNL, VNL);
ospf6_lsdb_show (vty, level, &type, &id, &adv_router, o->lsdb);
break;
@@ -1250,7 +1251,7 @@
switch (OSPF6_LSA_SCOPE (type))
{
- case OSPF6_LSA_SCOPE_AREA:
+ case OSPF6_SCOPE_AREA:
for (i = listhead (o->area_list); i; nextnode (i))
{
oa = (struct ospf6_area *) getdata (i);
@@ -1259,7 +1260,7 @@
}
break;
- case OSPF6_LSA_SCOPE_LINKLOCAL:
+ case OSPF6_SCOPE_LINKLOCAL:
for (i = listhead (o->area_list); i; nextnode (i))
{
oa = (struct ospf6_area *) getdata (i);
@@ -1273,7 +1274,7 @@
}
break;
- case OSPF6_LSA_SCOPE_AS:
+ case OSPF6_SCOPE_AS:
vty_out (vty, AS_LSDB_TITLE_FORMAT, VNL, VNL, VNL);
ospf6_lsdb_show (vty, level, &type, &id, &adv_router, o->lsdb);
break;
@@ -1416,7 +1417,7 @@
switch (OSPF6_LSA_SCOPE (type))
{
- case OSPF6_LSA_SCOPE_AREA:
+ case OSPF6_SCOPE_AREA:
for (i = listhead (o->area_list); i; nextnode (i))
{
oa = (struct ospf6_area *) getdata (i);
@@ -1425,7 +1426,7 @@
}
break;
- case OSPF6_LSA_SCOPE_LINKLOCAL:
+ case OSPF6_SCOPE_LINKLOCAL:
for (i = listhead (o->area_list); i; nextnode (i))
{
oa = (struct ospf6_area *) getdata (i);
@@ -1439,7 +1440,7 @@
}
break;
- case OSPF6_LSA_SCOPE_AS:
+ case OSPF6_SCOPE_AS:
vty_out (vty, AS_LSDB_TITLE_FORMAT, VNL, VNL, VNL);
ospf6_lsdb_show (vty, level, &type, NULL, &adv_router, o->lsdb);
break;
@@ -1517,7 +1518,7 @@
argc--;
argv++;
- if ((inet_pton (AF_INET, argv[1], &id)) != 1)
+ if ((inet_pton (AF_INET, argv[0], &id)) != 1)
{
vty_out (vty, "Link State ID is not parsable: %s%s",
argv[0], VNL);
@@ -1532,7 +1533,7 @@
switch (OSPF6_LSA_SCOPE (type))
{
- case OSPF6_LSA_SCOPE_AREA:
+ case OSPF6_SCOPE_AREA:
for (i = listhead (o->area_list); i; nextnode (i))
{
oa = (struct ospf6_area *) getdata (i);
@@ -1541,7 +1542,7 @@
}
break;
- case OSPF6_LSA_SCOPE_LINKLOCAL:
+ case OSPF6_SCOPE_LINKLOCAL:
for (i = listhead (o->area_list); i; nextnode (i))
{
oa = (struct ospf6_area *) getdata (i);
@@ -1555,7 +1556,7 @@
}
break;
- case OSPF6_LSA_SCOPE_AS:
+ case OSPF6_SCOPE_AS:
vty_out (vty, AS_LSDB_TITLE_FORMAT, VNL, VNL, VNL);
ospf6_lsdb_show (vty, level, &type, &id, &adv_router, o->lsdb);
break;
@@ -1633,7 +1634,7 @@
argc--;
argv++;
- if ((inet_pton (AF_INET, argv[1], &id)) != 1)
+ if ((inet_pton (AF_INET, argv[0], &id)) != 1)
{
vty_out (vty, "Link State ID is not parsable: %s%s",
argv[0], VNL);
@@ -1648,7 +1649,7 @@
switch (OSPF6_LSA_SCOPE (type))
{
- case OSPF6_LSA_SCOPE_AREA:
+ case OSPF6_SCOPE_AREA:
for (i = listhead (o->area_list); i; nextnode (i))
{
oa = (struct ospf6_area *) getdata (i);
@@ -1657,7 +1658,7 @@
}
break;
- case OSPF6_LSA_SCOPE_LINKLOCAL:
+ case OSPF6_SCOPE_LINKLOCAL:
for (i = listhead (o->area_list); i; nextnode (i))
{
oa = (struct ospf6_area *) getdata (i);
@@ -1671,7 +1672,7 @@
}
break;
- case OSPF6_LSA_SCOPE_AS:
+ case OSPF6_SCOPE_AS:
vty_out (vty, AS_LSDB_TITLE_FORMAT, VNL, VNL, VNL);
ospf6_lsdb_show (vty, level, &type, &id, &adv_router, o->lsdb);
break;
@@ -1712,6 +1713,68 @@
"Display LSA's internal information\n"
);
+
+DEFUN (show_ipv6_ospf6_border_routers,
+ show_ipv6_ospf6_border_routers_cmd,
+ "show ipv6 ospf6 border-routers",
+ SHOW_STR
+ IP6_STR
+ OSPF6_STR
+ "Display routing table for ABR and ASBR\n"
+ )
+{
+ u_int32_t adv_router;
+ void (*showfunc) (struct vty *, struct ospf6_route *);
+ struct ospf6_route *ro;
+ struct prefix prefix;
+
+ OSPF6_CMD_CHECK_RUNNING ();
+
+ if (argc && ! strcmp ("detail", argv[0]))
+ {
+ showfunc = ospf6_route_show_detail;
+ argc--;
+ argv++;
+ }
+ else
+ showfunc = ospf6_brouter_show;
+
+ if (argc)
+ {
+ if ((inet_pton (AF_INET, argv[0], &adv_router)) != 1)
+ {
+ vty_out (vty, "Router ID is not parsable: %s%s", argv[0], VNL);
+ return CMD_SUCCESS;
+ }
+
+ ospf6_linkstate_prefix (adv_router, 0, &prefix);
+ ro = ospf6_route_lookup (&prefix, ospf6->brouter_table);
+ ospf6_route_show_detail (vty, ro);
+ return CMD_SUCCESS;
+ }
+
+ if (showfunc == ospf6_brouter_show)
+ ospf6_brouter_show_header (vty);
+
+ for (ro = ospf6_route_head (ospf6->brouter_table); ro;
+ ro = ospf6_route_next (ro))
+ (*showfunc) (vty, ro);
+
+ return CMD_SUCCESS;
+}
+
+ALIAS (show_ipv6_ospf6_border_routers,
+ show_ipv6_ospf6_border_routers_detail_cmd,
+ "show ipv6 ospf6 border-routers (A.B.C.D|detail)",
+ SHOW_STR
+ IP6_STR
+ OSPF6_STR
+ "Display routing table for ABR and ASBR\n"
+ "Specify Router-ID\n"
+ "Display Detail\n"
+ );
+
+
/* Install ospf related commands. */
void
ospf6_init ()
@@ -1726,10 +1789,16 @@
install_element_ospf6_debug_spf ();
install_element_ospf6_debug_route ();
install_element_ospf6_debug_asbr ();
+ install_element_ospf6_debug_abr ();
install_element (VIEW_NODE, &show_version_ospf6_cmd);
install_element (ENABLE_NODE, &show_version_ospf6_cmd);
+ install_element (VIEW_NODE, &show_ipv6_ospf6_border_routers_cmd);
+ install_element (VIEW_NODE, &show_ipv6_ospf6_border_routers_detail_cmd);
+ install_element (ENABLE_NODE, &show_ipv6_ospf6_border_routers_cmd);
+ install_element (ENABLE_NODE, &show_ipv6_ospf6_border_routers_detail_cmd);
+
#define INSTALL(n,c) \
install_element (n ## _NODE, &show_ipv6_ospf6_ ## c);
diff --git a/ospf6d/ospf6d.h b/ospf6d/ospf6d.h
index c738df6..3274242 100644
--- a/ospf6d/ospf6d.h
+++ b/ospf6d/ospf6d.h
@@ -22,7 +22,7 @@
#ifndef OSPF6D_H
#define OSPF6D_H
-#define OSPF6_DAEMON_VERSION "0.9.7e"
+#define OSPF6_DAEMON_VERSION "0.9.7i"
/* global variables */
extern int errno;
@@ -50,6 +50,12 @@
#endif /* IPV6_DROP_MEMBERSHIP */
#endif /* ! IPV6_LEAVE_GROUP */
+/* cast macro */
+#define OSPF6_PROCESS(x) ((struct ospf6 *) (x))
+#define OSPF6_AREA(x) ((struct ospf6_area *) (x))
+#define OSPF6_INTERFACE(x) ((struct ospf6_interface *) (x))
+#define OSPF6_NEIGHBOR(x) ((struct ospf6_neighbor *) (x))
+
/* operation on timeval structure */
#ifndef timerclear
#define timerclear(a) (a)->tv_sec = (tvp)->tv_usec = 0