Browse Source

SVN revisions 916-920 from Zebra. ABR support is almost done.

hasso 15 years ago
parent
commit
6452df092b

+ 22 - 0
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.

+ 299 - 81
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 @@ ospf6_abr_originate_prefix_to_area (struct ospf6_route *route,
   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;
+
+  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);
+        }
+    }
 
-  summary = ospf6_route_lookup (&route->prefix, area->summary_table);
+  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 @@ ospf6_abr_originate_prefix_to_area (struct ospf6_route *route,
   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);
+        ospf6_lsa_purge (old);
       return;
     }
 
-  /* do not generate if the route cost is greater or equal to LSInfinity */
-  if (route->path.cost >= LS_INFINITY)
+  /* 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;
     }
 
-  /* if this is an inter-area route */
-  if (route->path.type == OSPF6_PATH_TYPE_INTRA)
+  /* 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)
     {
-      /* 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);
+      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_purge (old);
+      return;
     }
 
-  /* 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))
+  /* 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_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 this is a route to ASBR */
+  if (route->type == OSPF6_DEST_TYPE_ROUTER)
     {
-      if (old)
-        ospf6_lsa_premature_aging (old);
-      return;
+      /* 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 */
     }
 
-  /* 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 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)
     {
-      if (old)
-        ospf6_lsa_premature_aging (old);
-      return;
+      /* 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);
-
-  /* prefixlen */
-  prefix_lsa->prefix.prefix_length = route->prefix.prefixlen;
-
-  /* PrefixOptions */
-  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);
+  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);
+
+      /* 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);
+
+      /* 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);
+      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 @@ ospf6_abr_originate_prefix_to_area (struct ospf6_route *route,
 
   /* 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_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_prefix (struct ospf6_route *route, struct ospf6 *o)
+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 @@ ospf6_abr_examin_summary (struct ospf6_lsa *lsa, struct ospf6_area *oa)
   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 @@ ospf6_abr_examin_summary (struct ospf6_lsa *lsa, struct ospf6_area *oa)
     }
 
   /* (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_abr_examin_summary (struct ospf6_lsa *lsa, struct ospf6_area *oa)
   ospf6_route_add (route, table);
 }
 
-int
-dummy (struct ospf6_lsa *lsa)
-{
-}
-
 
 /* Display functions */
 int
@@ -412,15 +620,25 @@ install_element_ospf6_debug_abr ()
   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);
 }
 
 

+ 5 - 3
ospf6d/ospf6_abr.h

@@ -52,9 +52,11 @@ struct ospf6_inter_router_lsa
   { (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);

+ 160 - 26
ospf6d/ospf6_area.c

@@ -48,29 +48,18 @@ ospf6_area_cmp (void *va, void *vb)
 {
   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 @@ ospf6_area_lsdb_hook_add (struct ospf6_lsa *lsa)
 
     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 @@ ospf6_area_lsdb_hook_add (struct ospf6_lsa *lsa)
 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 @@ ospf6_area_lsdb_hook_remove (struct ospf6_lsa *lsa)
 
     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 @@ ospf6_area_create (u_int32_t area_id, struct ospf6 *o)
   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 @@ ospf6_area_create (u_int32_t area_id, struct ospf6 *o)
   /* 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 @@ ospf6_area_delete (struct ospf6_area *oa)
   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 @@ ospf6_area_delete (struct ospf6_area *oa)
   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 @@ ospf6_area_lookup (u_int32_t area_id, struct ospf6 *ospf6)
   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 @@ ospf6_area_disable (struct ospf6_area *oa)
   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 @@ ospf6_area_show (struct vty *vty, struct ospf6_area *oa)
     }                                                      \
 }
 
+#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 @@ ospf6_area_init ()
   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);
 }
 
+

+ 20 - 8
ospf6d/ospf6_area.h

@@ -41,16 +41,17 @@ struct ospf6_area
   /* 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 @@ struct ospf6_area
   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_enable (struct ospf6_area *);
 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 */

+ 21 - 115
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 @@ char *zroute_abname[] =
 
 /* 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 @@ ospf6_as_external_lsa_originate_sub (struct ospf6_route *route, int force)
     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 @@ ospf6_as_external_lsa_originate_sub (struct ospf6_route *route, int force)
   /* 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 @@ ospf6_as_external_lsa_originate_sub (struct ospf6_route *route, int force)
   /* 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 @@ ospf6_as_external_lsa_originate_sub (struct ospf6_route *route, int force)
 
   /* 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 @@ ospf6_asbr_lsa_add (struct ospf6_lsa *lsa)
   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 @@ ospf6_asbr_redistribute_add (int type, int ifindex, struct prefix *prefix,
           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 @@ ospf6_asbr_redistribute_add (int type, int ifindex, struct prefix *prefix,
       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 @@ ospf6_asbr_redistribute_remove (int type, int ifindex, struct prefix *prefix)
   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 @@ DEFUN (show_ipv6_ospf6_redistribute,
   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"
-      )
-{
-  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"
-      )
+struct ospf6_lsa_handler as_external_handler =
 {
-  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);

File diff suppressed because it is too large
+ 480 - 406
ospf6d/ospf6_flood.c


+ 23 - 7
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 */
 

+ 18 - 11
ospf6d/ospf6_interface.c

@@ -89,21 +89,18 @@ ospf6_interface_lookup_by_name (char *ifname)
 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 @@ ospf6_interface_create (struct interface *ifp)
       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_interface_delete (struct ospf6_interface *oi)
   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_interface_state_change (u_char next_state, struct ospf6_interface *oi)
     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);

+ 1 - 0
ospf6d/ospf6_interface.h

@@ -84,6 +84,7 @@ struct ospf6_interface
 
   /* 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;

+ 138 - 232
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 @@ ospf6_router_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
   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 @@ ospf6_router_lsa_originate_sub (struct ospf6_area *oa, int force)
   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_router_lsa_originate_sub (struct ospf6_area *oa, int force)
   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 @@ ospf6_router_lsa_originate_sub (struct ospf6_area *oa, int force)
             {
               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 @@ ospf6_router_lsa_originate_sub (struct ospf6_area *oa, int force)
 
           /* 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 @@ ospf6_router_lsa_originate_sub (struct ospf6_area *oa, int force)
 
       /* 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 @@ ospf6_router_lsa_originate_sub (struct ospf6_area *oa, int force)
     {
       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 @@ ospf6_network_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
   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 @@ ospf6_network_lsa_originate_sub (struct ospf6_interface *oi, int force)
   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 @@ ospf6_network_lsa_originate_sub (struct ospf6_interface *oi, int force)
   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 @@ ospf6_network_lsa_originate_sub (struct ospf6_interface *oi, int force)
       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 @@ ospf6_network_lsa_originate_sub (struct ospf6_interface *oi, int force)
 
   /* 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 @@ ospf6_link_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
   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 @@ ospf6_link_lsa_originate_sub (struct ospf6_interface *oi, int force)
   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 @@ ospf6_link_lsa_originate_sub (struct ospf6_interface *oi, int force)
   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 @@ ospf6_link_lsa_originate_sub (struct ospf6_interface *oi, int force)
         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 @@ ospf6_link_lsa_originate_sub (struct ospf6_interface *oi, int force)
 
   /* 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 @@ ospf6_intra_prefix_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
   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 @@ ospf6_intra_prefix_lsa_originate_stub_sub (struct ospf6_area *oa,
   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 @@ ospf6_intra_prefix_lsa_originate_stub_sub (struct ospf6_area *oa,
   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 @@ ospf6_intra_prefix_lsa_originate_stub_sub (struct ospf6_area *oa,
     {
       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 @@ ospf6_intra_prefix_lsa_originate_stub_sub (struct ospf6_area *oa,
 
   /* 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 @@ ospf6_intra_prefix_lsa_originate_transit_sub (struct ospf6_interface *oi,
   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 @@ ospf6_intra_prefix_lsa_originate_transit_sub (struct ospf6_interface *oi,
   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 @@ ospf6_intra_prefix_lsa_originate_transit_sub (struct ospf6_interface *oi,
       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 @@ ospf6_intra_prefix_lsa_originate_transit_sub (struct ospf6_interface *oi,
       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 @@ ospf6_intra_prefix_lsa_originate_transit_sub (struct ospf6_interface *oi,
     {
       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 @@ ospf6_intra_prefix_lsa_originate_transit_sub (struct ospf6_interface *oi,
 
   /* 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 @@ ospf6_intra_prefix_lsa_add (struct ospf6_lsa *lsa)
   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 @@ ospf6_intra_prefix_lsa_remove (struct ospf6_lsa *lsa)
   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 @@ ospf6_intra_route_calculation (struct ospf6_area *oa)
 }
 
 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 @@ ospf6_intra_asbr_calculation (struct ospf6_area *oa)
         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 @@ ospf6_intra_asbr_calculation (struct ospf6_area *oa)
         }
 
       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 @@ ospf6_intra_asbr_calculation (struct ospf6_area *oa)
       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);
 }
 
 

+ 13 - 1
ospf6d/ospf6_intra.h

@@ -128,6 +128,18 @@ struct ospf6_intra_prefix_lsa
                           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_add (struct ospf6_lsa *lsa);
 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 ();
 

+ 100 - 141
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 @@ char *
 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 @@ ospf6_lsa_age_set (struct ospf6_lsa *lsa)
   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 @@ ospf6_lsa_header_print (struct ospf6_lsa *lsa)
 }
 
 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 @@ ospf6_lsa_show_dump (struct vty *vty, struct ospf6_lsa *lsa)
     }
 
   vty_out (vty, "%s%s", VNL, VNL);
+  return;
 }
 
 void
@@ -386,10 +355,44 @@ ospf6_lsa_show_internal (struct vty *vty, struct ospf6_lsa *lsa)
   vty_out (vty, "    Prev: %p This: %p Next: %p%s",
            lsa->prev, lsa, lsa->next, VNL);
   vty_out (vty, "%s", VNL);
+  return;
 }
 
-/* OSPFv3 LSA creation/deletion function */
+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 @@ ospf6_lsa_create (struct ospf6_lsa_header *header)
   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 @@ ospf6_lsa_create_headeronly (struct ospf6_lsa_header *header)
   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 @@ ospf6_lsa_delete (struct ospf6_lsa *lsa)
 
   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 @@ ospf6_lsa_copy (struct ospf6_lsa *lsa)
     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 @@ ospf6_lsa_copy (struct ospf6_lsa *lsa)
 
   copy->installed = lsa->installed;
   copy->originated = lsa->originated;
-  copy->scope = lsa->scope;
+  copy->lsdb = lsa->lsdb;
 
   return copy;
 }
@@ -527,77 +529,12 @@ ospf6_lsa_unlock (struct ospf6_lsa *lsa)
   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_expire (struct thread *thread)
       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 @@ ospf6_lsa_expire (struct thread *thread)
   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;
+
+  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);
 
-  /* this will be used later to decide really originate or not */
-  SET_FLAG (lsa->flag, OSPF6_LSA_REFRESH);
+  /* 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 @@ ospf6_lsa_checksum (struct ospf6_lsa_header *lsa_header)
 }
 
 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 @@ ospf6_unknown_show (struct vty *vty, struct ospf6_lsa *lsa)
 }
 
 void
-ospf6_lsa_init ()
+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 =
 {
-  memset (ospf6_lstype, 0, sizeof (ospf6_lstype));
+  OSPF6_LSTYPE_UNKNOWN,
+  "Unknown",
+  ospf6_unknown_lsa_show
+};
 
-  ospf6_lstype[0].name = "Unknown";
-  ospf6_lstype[0].reoriginate = ospf6_unknown_reoriginate;
-  ospf6_lstype[0].show = ospf6_unknown_show;
+void
+ospf6_lsa_init ()
+{
+  memset (ospf6_lsa_handler, 0, sizeof (ospf6_lsa_handler));
+  ospf6_install_lsa_handler (&unknown_handler);
 }
 
 

+ 28 - 37
ospf6d/ospf6_lsa.h

@@ -62,11 +62,12 @@ extern unsigned char conf_debug_ospf6_lsa;
 #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_header
 
 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 @@ int ospf6_lsa_compare (struct ospf6_lsa *, struct ospf6_lsa *);
 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 @@ struct ospf6_lsa *ospf6_lsa_copy (struct ospf6_lsa *);
 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 @@ unsigned short ospf6_lsa_checksum (struct ospf6_lsa_header *);
 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);

+ 4 - 2
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 @@ ospf6_lsdb_create ()
     }
   memset (lsdb, 0, sizeof (struct ospf6_lsdb));
 
+  lsdb->data = data;
   lsdb->table = route_table_init ();
   return lsdb;
 }
@@ -228,6 +229,7 @@ ospf6_lsdb_remove (struct ospf6_lsa *lsa, struct ospf6_lsdb *lsdb)
 
   ospf6_lsa_unlock (lsa);
   route_unlock_node (node);
+
   ospf6_lsdb_count_assert (lsdb);
 }
 
@@ -475,7 +477,7 @@ ospf6_new_ls_id (u_int16_t type, u_int32_t adv_router,
       if (ntohl (lsa->header->id) < id)
         continue;
       if (ntohl (lsa->header->id) > id)
-        return ((u_int32_t) htonl (id));
+        break;
       id++;
     }
 

+ 3 - 2
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 @@ struct ospf6_lsdb
       {                                                                  \
         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 @@ struct ospf6_lsdb
   } 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,

+ 107 - 57
ospf6d/ospf6_message.c

@@ -245,7 +245,7 @@ ospf6_header_examin (struct in6_addr *src, struct in6_addr *dst,
   /* 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 @@ ospf6_dbdesc_recv_master (struct ospf6_header *oh,
       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 @@ ospf6_dbdesc_recv_master (struct ospf6_header *oh,
 
       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_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_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 (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 @@ ospf6_dbdesc_recv_slave (struct ospf6_header *oh,
       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 @@ ospf6_dbdesc_recv_slave (struct ospf6_header *oh,
                                 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 @@ ospf6_lsreq_recv (struct in6_addr *src, struct in6_addr *dst,
   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 @@ ospf6_lsreq_recv (struct in6_addr *src, struct in6_addr *dst,
        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 @@ ospf6_lsreq_recv (struct in6_addr *src, struct in6_addr *dst,
           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 @@ ospf6_lsupdate_recv (struct in6_addr *src, struct in6_addr *dst,
           break;
         }
 
-      ospf6_receive_lsa ((struct ospf6_lsa_header *) p, on);
+      ospf6_receive_lsa (on, (struct ospf6_lsa_header *) p);
       num--;
     }
 
@@ -1041,11 +1086,27 @@ ospf6_lsack_recv (struct in6_addr *src, struct in6_addr *dst,
        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");