]> git.proxmox.com Git - mirror_frr.git/blobdiff - ospf6d/ospf6_intra.c
Merge pull request #2197 from qlyoung/docuser-debianpkg
[mirror_frr.git] / ospf6d / ospf6_intra.c
index 41271d8028a0d2540c9f1bc57f904eb2ada86990..26e6deadae89636490f744d00f41cebc79f054cc 100644 (file)
 #include "ospf6_spf.h"
 
 unsigned char conf_debug_ospf6_brouter = 0;
-u_int32_t conf_debug_ospf6_brouter_specific_router_id;
-u_int32_t conf_debug_ospf6_brouter_specific_area_id;
+uint32_t conf_debug_ospf6_brouter_specific_router_id;
+uint32_t conf_debug_ospf6_brouter_specific_area_id;
 
+#define MAX_LSA_PAYLOAD   (1024 + 256)
 /******************************/
 /* RFC2740 3.4.3.1 Router-LSA */
 /******************************/
 
-static char *
-ospf6_router_lsa_get_nbr_id (struct ospf6_lsa *lsa, char *buf, int buflen,
-                            int pos)
+static char *ospf6_router_lsa_get_nbr_id(struct ospf6_lsa *lsa, char *buf,
+                                        int buflen, int pos)
 {
-  struct ospf6_router_lsa *router_lsa;
-  struct ospf6_router_lsdesc *lsdesc;
-  char *start, *end;
-  char buf1[INET_ADDRSTRLEN], buf2[INET_ADDRSTRLEN];
-
-  if (lsa)
-    {
-      router_lsa = (struct ospf6_router_lsa *)
-       ((char *) lsa->header + sizeof (struct ospf6_lsa_header));
-      start = (char *) router_lsa + sizeof (struct ospf6_router_lsa);
-      end = (char *) lsa->header + ntohs (lsa->header->length);
-
-      lsdesc = (struct ospf6_router_lsdesc *)
-       (start + pos*(sizeof (struct ospf6_router_lsdesc)));
-      if ((char *)lsdesc < end)
-       {
-         if (buf && (buflen > INET_ADDRSTRLEN*2))
-           {
-             inet_ntop (AF_INET, &lsdesc->neighbor_interface_id,
-                        buf1, sizeof(buf1));
-             inet_ntop (AF_INET, &lsdesc->neighbor_router_id,
-                        buf2, sizeof(buf2));
-             sprintf (buf, "%s/%s", buf2, buf1);
-           }
+       struct ospf6_router_lsa *router_lsa;
+       struct ospf6_router_lsdesc *lsdesc;
+       char *start, *end;
+       char buf1[INET_ADDRSTRLEN], buf2[INET_ADDRSTRLEN];
+
+       if (lsa) {
+               router_lsa = (struct ospf6_router_lsa
+                                     *)((char *)lsa->header
+                                        + sizeof(struct ospf6_lsa_header));
+               start = (char *)router_lsa + sizeof(struct ospf6_router_lsa);
+               end = (char *)lsa->header + ntohs(lsa->header->length);
+
+               lsdesc = (struct ospf6_router_lsdesc
+                                 *)(start
+                                    + pos * (sizeof(struct
+                                                    ospf6_router_lsdesc)));
+               if ((char *)lsdesc < end) {
+                       if (buf && (buflen > INET_ADDRSTRLEN * 2)) {
+                               inet_ntop(AF_INET,
+                                         &lsdesc->neighbor_interface_id, buf1,
+                                         sizeof(buf1));
+                               inet_ntop(AF_INET, &lsdesc->neighbor_router_id,
+                                         buf2, sizeof(buf2));
+                               sprintf(buf, "%s/%s", buf2, buf1);
+                       }
+               } else
+                       return NULL;
        }
-      else
-       return NULL;
-    }
 
-  return buf;
+       return buf;
 }
 
-static int
-ospf6_router_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
+static int ospf6_router_lsa_show(struct vty *vty, struct ospf6_lsa *lsa)
 {
-  char *start, *end, *current;
-  char buf[32], name[32], bits[16], options[32];
-  struct ospf6_router_lsa *router_lsa;
-  struct ospf6_router_lsdesc *lsdesc;
-
-  router_lsa = (struct ospf6_router_lsa *)
-    ((char *) lsa->header + sizeof (struct ospf6_lsa_header));
-
-  ospf6_capability_printbuf (router_lsa->bits, bits, sizeof (bits));
-  ospf6_options_printbuf (router_lsa->options, options, sizeof (options));
-  vty_out (vty, "    Bits: %s Options: %s\n", bits, options);
-
-  start = (char *) router_lsa + sizeof (struct ospf6_router_lsa);
-  end = (char *) lsa->header + ntohs (lsa->header->length);
-  for (current = start; current + sizeof (struct ospf6_router_lsdesc) <= end;
-       current += sizeof (struct ospf6_router_lsdesc))
-    {
-      lsdesc = (struct ospf6_router_lsdesc *) current;
-
-      if (lsdesc->type == OSPF6_ROUTER_LSDESC_POINTTOPOINT)
-        snprintf (name, sizeof (name), "Point-To-Point");
-      else if (lsdesc->type == OSPF6_ROUTER_LSDESC_TRANSIT_NETWORK)
-        snprintf (name, sizeof (name), "Transit-Network");
-      else if (lsdesc->type == OSPF6_ROUTER_LSDESC_STUB_NETWORK)
-        snprintf (name, sizeof (name), "Stub-Network");
-      else if (lsdesc->type == OSPF6_ROUTER_LSDESC_VIRTUAL_LINK)
-        snprintf (name, sizeof (name), "Virtual-Link");
-      else
-        snprintf (name, sizeof (name), "Unknown (%#x)", lsdesc->type);
-
-      vty_out (vty, "    Type: %s Metric: %d\n",
-               name, ntohs (lsdesc->metric));
-      vty_out (vty, "    Interface ID: %s\n",
-               inet_ntop (AF_INET, &lsdesc->interface_id,
-                          buf, sizeof (buf)));
-      vty_out (vty, "    Neighbor Interface ID: %s\n",
-               inet_ntop (AF_INET, &lsdesc->neighbor_interface_id,
-                          buf, sizeof (buf)));
-      vty_out (vty, "    Neighbor Router ID: %s\n",
-               inet_ntop (AF_INET, &lsdesc->neighbor_router_id,
-                          buf, sizeof (buf)));
-    }
-  return 0;
+       char *start, *end, *current;
+       char buf[32], name[32], bits[16], options[32];
+       struct ospf6_router_lsa *router_lsa;
+       struct ospf6_router_lsdesc *lsdesc;
+
+       router_lsa =
+               (struct ospf6_router_lsa *)((char *)lsa->header
+                                           + sizeof(struct ospf6_lsa_header));
+
+       ospf6_capability_printbuf(router_lsa->bits, bits, sizeof(bits));
+       ospf6_options_printbuf(router_lsa->options, options, sizeof(options));
+       vty_out(vty, "    Bits: %s Options: %s\n", bits, options);
+
+       start = (char *)router_lsa + sizeof(struct ospf6_router_lsa);
+       end = (char *)lsa->header + ntohs(lsa->header->length);
+       for (current = start;
+            current + sizeof(struct ospf6_router_lsdesc) <= end;
+            current += sizeof(struct ospf6_router_lsdesc)) {
+               lsdesc = (struct ospf6_router_lsdesc *)current;
+
+               if (lsdesc->type == OSPF6_ROUTER_LSDESC_POINTTOPOINT)
+                       snprintf(name, sizeof(name), "Point-To-Point");
+               else if (lsdesc->type == OSPF6_ROUTER_LSDESC_TRANSIT_NETWORK)
+                       snprintf(name, sizeof(name), "Transit-Network");
+               else if (lsdesc->type == OSPF6_ROUTER_LSDESC_STUB_NETWORK)
+                       snprintf(name, sizeof(name), "Stub-Network");
+               else if (lsdesc->type == OSPF6_ROUTER_LSDESC_VIRTUAL_LINK)
+                       snprintf(name, sizeof(name), "Virtual-Link");
+               else
+                       snprintf(name, sizeof(name), "Unknown (%#x)",
+                                lsdesc->type);
+
+               vty_out(vty, "    Type: %s Metric: %d\n", name,
+                       ntohs(lsdesc->metric));
+               vty_out(vty, "    Interface ID: %s\n",
+                       inet_ntop(AF_INET, &lsdesc->interface_id, buf,
+                                 sizeof(buf)));
+               vty_out(vty, "    Neighbor Interface ID: %s\n",
+                       inet_ntop(AF_INET, &lsdesc->neighbor_interface_id, buf,
+                                 sizeof(buf)));
+               vty_out(vty, "    Neighbor Router ID: %s\n",
+                       inet_ntop(AF_INET, &lsdesc->neighbor_router_id, buf,
+                                 sizeof(buf)));
+       }
+       return 0;
 }
 
-static void
-ospf6_router_lsa_options_set (struct ospf6_area *oa,
-                             struct ospf6_router_lsa *router_lsa)
+static void ospf6_router_lsa_options_set(struct ospf6_area *oa,
+                                        struct ospf6_router_lsa *router_lsa)
 {
-  OSPF6_OPT_CLEAR_ALL (router_lsa->options);
-  memcpy (router_lsa->options, oa->options, 3);
-
-  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 (!IS_AREA_STUB (oa) && ospf6_asbr_is_asbr (oa->ospf6))
-    {
-      SET_FLAG (router_lsa->bits, OSPF6_ROUTER_BIT_E);
-    }
-  else
-    {
-      UNSET_FLAG (router_lsa->bits, OSPF6_ROUTER_BIT_E);
-    }
-
-  UNSET_FLAG (router_lsa->bits, OSPF6_ROUTER_BIT_V);
-  UNSET_FLAG (router_lsa->bits, OSPF6_ROUTER_BIT_W);
+       OSPF6_OPT_CLEAR_ALL(router_lsa->options);
+       memcpy(router_lsa->options, oa->options, 3);
+
+       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 (!IS_AREA_STUB(oa) && ospf6_asbr_is_asbr(oa->ospf6)) {
+               SET_FLAG(router_lsa->bits, OSPF6_ROUTER_BIT_E);
+       } else {
+               UNSET_FLAG(router_lsa->bits, OSPF6_ROUTER_BIT_E);
+       }
+
+       UNSET_FLAG(router_lsa->bits, OSPF6_ROUTER_BIT_V);
+       UNSET_FLAG(router_lsa->bits, OSPF6_ROUTER_BIT_W);
 }
 
-int
-ospf6_router_is_stub_router (struct ospf6_lsa *lsa)
+int ospf6_router_is_stub_router(struct ospf6_lsa *lsa)
 {
-  struct ospf6_router_lsa *rtr_lsa;
-
-  if (lsa != NULL && OSPF6_LSA_IS_TYPE (ROUTER, lsa))
-    {
-      rtr_lsa = (struct ospf6_router_lsa *)
-       ((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header));
-
-      if (!OSPF6_OPT_ISSET (rtr_lsa->options, OSPF6_OPT_R))
-       {
-         return (OSPF6_IS_STUB_ROUTER);
-       }
-      else if (!OSPF6_OPT_ISSET (rtr_lsa->options, OSPF6_OPT_V6))
-       {
-         return (OSPF6_IS_STUB_ROUTER_V6);
+       struct ospf6_router_lsa *rtr_lsa;
+
+       if (lsa != NULL && OSPF6_LSA_IS_TYPE(ROUTER, lsa)) {
+               rtr_lsa = (struct ospf6_router_lsa
+                                  *)((caddr_t)lsa->header
+                                     + sizeof(struct ospf6_lsa_header));
+
+               if (!OSPF6_OPT_ISSET(rtr_lsa->options, OSPF6_OPT_R)) {
+                       return (OSPF6_IS_STUB_ROUTER);
+               } else if (!OSPF6_OPT_ISSET(rtr_lsa->options, OSPF6_OPT_V6)) {
+                       return (OSPF6_IS_STUB_ROUTER_V6);
+               }
        }
-    }
 
-  return (OSPF6_NOT_STUB_ROUTER);
+       return (OSPF6_NOT_STUB_ROUTER);
 }
 
-int
-ospf6_router_lsa_originate (struct thread *thread)
+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;
-
-  u_int32_t link_state_id = 0;
-  struct listnode *node, *nnode;
-  struct listnode *j;
-  struct ospf6_interface *oi;
-  struct ospf6_neighbor *on, *drouter = NULL;
-  struct ospf6_router_lsa *router_lsa;
-  struct ospf6_router_lsdesc *lsdesc;
-  u_int16_t type;
-  u_int32_t router;
-  int count;
-
-  oa = (struct ospf6_area *) THREAD_ARG (thread);
-  oa->thread_router_lsa = NULL;
-
-  if (IS_OSPF6_DEBUG_ORIGINATE (ROUTER))
-    zlog_debug ("Originate Router-LSA for Area %s", oa->name);
-
-  memset (buffer, 0, sizeof (buffer));
-  lsa_header = (struct ospf6_lsa_header *) buffer;
-  router_lsa = (struct ospf6_router_lsa *)
-    ((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header));
-
-  ospf6_router_lsa_options_set (oa, router_lsa);
-
-  /* describe links for each interfaces */
-  lsdesc = (struct ospf6_router_lsdesc *)
-    ((caddr_t) router_lsa + sizeof (struct ospf6_router_lsa));
-
-  for (ALL_LIST_ELEMENTS (oa->if_list, node, nnode, oi))
-    {
-      /* Interfaces in state Down or Loopback are not described */
-      if (oi->state == OSPF6_INTERFACE_DOWN ||
-          oi->state == OSPF6_INTERFACE_LOOPBACK)
-        continue;
-
-      /* Nor are interfaces without any full adjacencies described */
-      count = 0;
-      for (ALL_LIST_ELEMENTS_RO (oi->neighbor_list, j, on))
-        if (on->state == OSPF6_NEIGHBOR_FULL)
-          count++;
-
-      if (count == 0)
-        continue;
-
-      /* Multiple Router-LSA instance according to size limit setting */
-      if ( (oa->router_lsa_size_limit != 0)
-          && ((size_t)((char *)lsdesc - buffer)
-              + sizeof (struct ospf6_router_lsdesc)
-               > oa->router_lsa_size_limit))
-        {
-          if ((caddr_t) lsdesc == (caddr_t) router_lsa +
-                                  sizeof (struct ospf6_router_lsa))
-            {
-              if (IS_OSPF6_DEBUG_ORIGINATE (ROUTER))
-                zlog_debug ("Size limit setting for Router-LSA too short");
-              return 0;
-            }
-
-          link_state_id ++;
-        }
-
-      /* Point-to-Point interfaces */
-      if (oi->type == OSPF_IFTYPE_POINTOPOINT)
-        {
-          for (ALL_LIST_ELEMENTS_RO (oi->neighbor_list, j, on))
-            {
-              if (on->state != OSPF6_NEIGHBOR_FULL)
-                continue;
-
-              lsdesc->type = OSPF6_ROUTER_LSDESC_POINTTOPOINT;
-              lsdesc->metric = htons (oi->cost);
-              lsdesc->interface_id = htonl (oi->interface->ifindex);
-              lsdesc->neighbor_interface_id = htonl (on->ifindex);
-              lsdesc->neighbor_router_id = on->router_id;
-
-              lsdesc++;
-            }
-        }
-
-      /* Broadcast and NBMA interfaces */
-      else if (oi->type == OSPF_IFTYPE_BROADCAST)
-        {
-          /* If this router is not DR,
-             and If this router not fully adjacent with DR,
-             this interface is not transit yet: ignore. */
-          if (oi->state != OSPF6_INTERFACE_DR)
-            {
-              drouter = ospf6_neighbor_lookup (oi->drouter, oi);
-              if (drouter == NULL || drouter->state != OSPF6_NEIGHBOR_FULL)
-                continue;
-            }
-
-          lsdesc->type = OSPF6_ROUTER_LSDESC_TRANSIT_NETWORK;
-          lsdesc->metric = htons (oi->cost);
-          lsdesc->interface_id = htonl (oi->interface->ifindex);
-          if (oi->state != OSPF6_INTERFACE_DR)
-            {
-              lsdesc->neighbor_interface_id = htonl (drouter->ifindex);
-              lsdesc->neighbor_router_id = drouter->router_id;
-            }
-          else
-            {
-              lsdesc->neighbor_interface_id = htonl (oi->interface->ifindex);
-              lsdesc->neighbor_router_id = oi->area->ospf6->router_id;
-            }
-
-          lsdesc++;
-        }
-      else
-       {
-         assert (0);           /* Unknown interface type */
+       struct ospf6_area *oa;
+
+       char buffer[OSPF6_MAX_LSASIZE];
+       struct ospf6_lsa_header *lsa_header;
+       struct ospf6_lsa *lsa;
+
+       uint32_t link_state_id = 0;
+       struct listnode *node, *nnode;
+       struct listnode *j;
+       struct ospf6_interface *oi;
+       struct ospf6_neighbor *on, *drouter = NULL;
+       struct ospf6_router_lsa *router_lsa;
+       struct ospf6_router_lsdesc *lsdesc;
+       uint16_t type;
+       uint32_t router;
+       int count;
+
+       oa = (struct ospf6_area *)THREAD_ARG(thread);
+       oa->thread_router_lsa = NULL;
+
+       if (IS_OSPF6_DEBUG_ORIGINATE(ROUTER))
+               zlog_debug("Originate Router-LSA for Area %s", oa->name);
+
+       memset(buffer, 0, sizeof(buffer));
+       lsa_header = (struct ospf6_lsa_header *)buffer;
+       router_lsa =
+               (struct ospf6_router_lsa *)((caddr_t)lsa_header
+                                           + sizeof(struct ospf6_lsa_header));
+
+       ospf6_router_lsa_options_set(oa, router_lsa);
+
+       /* describe links for each interfaces */
+       lsdesc = (struct ospf6_router_lsdesc
+                         *)((caddr_t)router_lsa
+                            + sizeof(struct ospf6_router_lsa));
+
+       for (ALL_LIST_ELEMENTS(oa->if_list, node, nnode, oi)) {
+               /* Interfaces in state Down or Loopback are not described */
+               if (oi->state == OSPF6_INTERFACE_DOWN
+                   || oi->state == OSPF6_INTERFACE_LOOPBACK)
+                       continue;
+
+               /* Nor are interfaces without any full adjacencies described */
+               count = 0;
+               for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, j, on))
+                       if (on->state == OSPF6_NEIGHBOR_FULL)
+                               count++;
+
+               if (count == 0)
+                       continue;
+
+               /* Multiple Router-LSA instance according to size limit setting
+                */
+               if ((oa->router_lsa_size_limit != 0)
+                   && ((size_t)((char *)lsdesc - buffer)
+                               + sizeof(struct ospf6_router_lsdesc)
+                       > oa->router_lsa_size_limit)) {
+                       if ((caddr_t)lsdesc
+                           == (caddr_t)router_lsa
+                                      + sizeof(struct ospf6_router_lsa)) {
+                               if (IS_OSPF6_DEBUG_ORIGINATE(ROUTER))
+                                       zlog_debug(
+                                               "Size limit setting for Router-LSA too short");
+                               return 0;
+                       }
+
+                       /* Fill LSA Header */
+                       lsa_header->age = 0;
+                       lsa_header->type = htons(OSPF6_LSTYPE_ROUTER);
+                       lsa_header->id = htonl(link_state_id);
+                       lsa_header->adv_router = oa->ospf6->router_id;
+                       lsa_header->seqnum = ospf6_new_ls_seqnum(
+                               lsa_header->type, lsa_header->id,
+                               lsa_header->adv_router, oa->lsdb);
+                       lsa_header->length =
+                               htons((caddr_t)lsdesc - (caddr_t)buffer);
+
+                       /* LSA checksum */
+                       ospf6_lsa_checksum(lsa_header);
+
+                       /* create LSA */
+                       lsa = ospf6_lsa_create(lsa_header);
+
+                       /* Originate */
+                       ospf6_lsa_originate_area(lsa, oa);
+
+                       /* Reset Buffer to fill next Router LSA */
+                       memset(buffer, 0, sizeof(buffer));
+                       lsa_header = (struct ospf6_lsa_header *)buffer;
+                       router_lsa =
+                               (struct ospf6_router_lsa
+                                        *)((caddr_t)lsa_header
+                                           + sizeof(struct ospf6_lsa_header));
+
+                       ospf6_router_lsa_options_set(oa, router_lsa);
+
+                       /* describe links for each interfaces */
+                       lsdesc = (struct ospf6_router_lsdesc
+                                         *)((caddr_t)router_lsa
+                                            + sizeof(struct ospf6_router_lsa));
+
+                       link_state_id++;
+               }
+
+               /* Point-to-Point interfaces */
+               if (oi->type == OSPF_IFTYPE_POINTOPOINT) {
+                       for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, j, on)) {
+                               if (on->state != OSPF6_NEIGHBOR_FULL)
+                                       continue;
+
+                               lsdesc->type = OSPF6_ROUTER_LSDESC_POINTTOPOINT;
+                               lsdesc->metric = htons(oi->cost);
+                               lsdesc->interface_id =
+                                       htonl(oi->interface->ifindex);
+                               lsdesc->neighbor_interface_id =
+                                       htonl(on->ifindex);
+                               lsdesc->neighbor_router_id = on->router_id;
+
+                               lsdesc++;
+                       }
+               }
+
+               /* Broadcast and NBMA interfaces */
+               else if (oi->type == OSPF_IFTYPE_BROADCAST) {
+                       /* If this router is not DR,
+                          and If this router not fully adjacent with DR,
+                          this interface is not transit yet: ignore. */
+                       if (oi->state != OSPF6_INTERFACE_DR) {
+                               drouter =
+                                       ospf6_neighbor_lookup(oi->drouter, oi);
+                               if (drouter == NULL
+                                   || drouter->state != OSPF6_NEIGHBOR_FULL)
+                                       continue;
+                       }
+
+                       lsdesc->type = OSPF6_ROUTER_LSDESC_TRANSIT_NETWORK;
+                       lsdesc->metric = htons(oi->cost);
+                       lsdesc->interface_id = htonl(oi->interface->ifindex);
+                       if (oi->state != OSPF6_INTERFACE_DR) {
+                               lsdesc->neighbor_interface_id =
+                                       htonl(drouter->ifindex);
+                               lsdesc->neighbor_router_id = drouter->router_id;
+                       } else {
+                               lsdesc->neighbor_interface_id =
+                                       htonl(oi->interface->ifindex);
+                               lsdesc->neighbor_router_id =
+                                       oi->area->ospf6->router_id;
+                       }
+
+                       lsdesc++;
+               } else {
+                       assert(0); /* Unknown interface type */
+               }
+
+               /* Virtual links */
+               /* xxx */
+               /* Point-to-Multipoint interfaces */
+               /* xxx */
+       }
+
+       /* Fill LSA Header */
+       lsa_header->age = 0;
+       lsa_header->type = htons(OSPF6_LSTYPE_ROUTER);
+       lsa_header->id = htonl(link_state_id);
+       lsa_header->adv_router = oa->ospf6->router_id;
+       lsa_header->seqnum =
+               ospf6_new_ls_seqnum(lsa_header->type, lsa_header->id,
+                                   lsa_header->adv_router, oa->lsdb);
+       lsa_header->length = htons((caddr_t)lsdesc - (caddr_t)buffer);
+
+       /* LSA checksum */
+       ospf6_lsa_checksum(lsa_header);
+
+       /* create LSA */
+       lsa = ospf6_lsa_create(lsa_header);
+
+       /* Originate */
+       ospf6_lsa_originate_area(lsa, oa);
+
+       link_state_id++;
+
+       /* Do premature-aging of rest, undesired Router-LSAs */
+       type = ntohs(OSPF6_LSTYPE_ROUTER);
+       router = oa->ospf6->router_id;
+       count = 0;
+       for (ALL_LSDB_TYPED_ADVRTR(oa->lsdb, type, router, lsa)) {
+               if (ntohl(lsa->header->id) < link_state_id)
+                       continue;
+               ospf6_lsa_purge(lsa);
+               count++;
        }
 
-      /* Virtual links */
-        /* xxx */
-      /* Point-to-Multipoint interfaces */
-        /* xxx */
-    }
-
-  /* Fill LSA Header */
-  lsa_header->age = 0;
-  lsa_header->type = htons (OSPF6_LSTYPE_ROUTER);
-  lsa_header->id = htonl (link_state_id);
-  lsa_header->adv_router = oa->ospf6->router_id;
-  lsa_header->seqnum =
-    ospf6_new_ls_seqnum (lsa_header->type, lsa_header->id,
-                         lsa_header->adv_router, oa->lsdb);
-  lsa_header->length = htons ((caddr_t) lsdesc - (caddr_t) buffer);
-
-  /* LSA checksum */
-  ospf6_lsa_checksum (lsa_header);
-
-  /* create LSA */
-  lsa = ospf6_lsa_create (lsa_header);
-
-  /* Originate */
-  ospf6_lsa_originate_area (lsa, oa);
-
-  link_state_id ++;
-
-  /* Do premature-aging of rest, undesired Router-LSAs */
-  type = ntohs (OSPF6_LSTYPE_ROUTER);
-  router = oa->ospf6->router_id;
-  count = 0;
-  for (lsa = ospf6_lsdb_type_router_head (type, router, oa->lsdb); lsa;
-       lsa = ospf6_lsdb_type_router_next (type, router, lsa))
-    {
-      if (ntohl (lsa->header->id) < link_state_id)
-        continue;
-      ospf6_lsa_purge (lsa);
-      count++;
-    }
-
-  /*
-   * Waiting till the LSA is actually removed from the database to trigger
-   * SPF delays network convergence. Unlike IPv4, for an ABR, when all
-   * interfaces associated with an area are gone, triggering an SPF right away
-   * helps convergence with inter-area routes.
-   */
-  if (count && !link_state_id)
-    ospf6_spf_schedule (oa->ospf6, OSPF6_SPF_FLAGS_ROUTER_LSA_ORIGINATED);
-
-  return 0;
+       /*
+        * Waiting till the LSA is actually removed from the database to trigger
+        * SPF delays network convergence. Unlike IPv4, for an ABR, when all
+        * interfaces associated with an area are gone, triggering an SPF right
+        * away
+        * helps convergence with inter-area routes.
+        */
+       if (count && !link_state_id)
+               ospf6_spf_schedule(oa->ospf6,
+                                  OSPF6_SPF_FLAGS_ROUTER_LSA_ORIGINATED);
+
+       return 0;
 }
 
 /*******************************/
 /* RFC2740 3.4.3.2 Network-LSA */
 /*******************************/
 
-static char *
-ospf6_network_lsa_get_ar_id (struct ospf6_lsa *lsa, char *buf, int buflen,
-                            int pos)
+static char *ospf6_network_lsa_get_ar_id(struct ospf6_lsa *lsa, char *buf,
+                                        int buflen, int pos)
 {
-  char *start, *end, *current;
-  struct ospf6_network_lsa *network_lsa;
-  struct ospf6_network_lsdesc *lsdesc;
-
-  if (lsa)
-    {
-      network_lsa = (struct ospf6_network_lsa *)
-       ((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header));
-
-      start = (char *) network_lsa + sizeof (struct ospf6_network_lsa);
-      end = (char *) lsa->header + ntohs (lsa->header->length);
-      current = start + pos*(sizeof (struct ospf6_network_lsdesc));
-
-      if ((current + sizeof(struct ospf6_network_lsdesc)) <= end)
-       {
-         lsdesc = (struct ospf6_network_lsdesc *)current;
-         if (buf)
-           inet_ntop (AF_INET, &lsdesc->router_id, buf, buflen);
+       char *start, *end, *current;
+       struct ospf6_network_lsa *network_lsa;
+       struct ospf6_network_lsdesc *lsdesc;
+
+       if (lsa) {
+               network_lsa = (struct ospf6_network_lsa
+                                      *)((caddr_t)lsa->header
+                                         + sizeof(struct ospf6_lsa_header));
+
+               start = (char *)network_lsa + sizeof(struct ospf6_network_lsa);
+               end = (char *)lsa->header + ntohs(lsa->header->length);
+               current = start + pos * (sizeof(struct ospf6_network_lsdesc));
+
+               if ((current + sizeof(struct ospf6_network_lsdesc)) <= end) {
+                       lsdesc = (struct ospf6_network_lsdesc *)current;
+                       if (buf)
+                               inet_ntop(AF_INET, &lsdesc->router_id, buf,
+                                         buflen);
+               } else
+                       return NULL;
        }
-      else
-       return NULL;
-    }
 
-  return (buf);
+       return (buf);
 }
 
-static int
-ospf6_network_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
+static int ospf6_network_lsa_show(struct vty *vty, struct ospf6_lsa *lsa)
 {
-  char *start, *end, *current;
-  struct ospf6_network_lsa *network_lsa;
-  struct ospf6_network_lsdesc *lsdesc;
-  char buf[128], options[32];
-
-  network_lsa = (struct ospf6_network_lsa *)
-    ((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header));
-
-  ospf6_options_printbuf (network_lsa->options, options, sizeof (options));
-  vty_out (vty, "     Options: %s\n", options);
-
-  start = (char *) network_lsa + sizeof (struct ospf6_network_lsa);
-  end = (char *) lsa->header + ntohs (lsa->header->length);
-  for (current = start; current + sizeof (struct ospf6_network_lsdesc) <= end;
-       current += sizeof (struct ospf6_network_lsdesc))
-    {
-      lsdesc = (struct ospf6_network_lsdesc *) current;
-      inet_ntop (AF_INET, &lsdesc->router_id, buf, sizeof (buf));
-      vty_out (vty, "     Attached Router: %s\n", buf);
-    }
-  return 0;
+       char *start, *end, *current;
+       struct ospf6_network_lsa *network_lsa;
+       struct ospf6_network_lsdesc *lsdesc;
+       char buf[128], options[32];
+
+       network_lsa =
+               (struct ospf6_network_lsa *)((caddr_t)lsa->header
+                                            + sizeof(struct ospf6_lsa_header));
+
+       ospf6_options_printbuf(network_lsa->options, options, sizeof(options));
+       vty_out(vty, "     Options: %s\n", options);
+
+       start = (char *)network_lsa + sizeof(struct ospf6_network_lsa);
+       end = (char *)lsa->header + ntohs(lsa->header->length);
+       for (current = start;
+            current + sizeof(struct ospf6_network_lsdesc) <= end;
+            current += sizeof(struct ospf6_network_lsdesc)) {
+               lsdesc = (struct ospf6_network_lsdesc *)current;
+               inet_ntop(AF_INET, &lsdesc->router_id, buf, sizeof(buf));
+               vty_out(vty, "     Attached Router: %s\n", buf);
+       }
+       return 0;
 }
 
-int
-ospf6_network_lsa_originate (struct thread *thread)
+int ospf6_network_lsa_originate(struct thread *thread)
 {
-  struct ospf6_interface *oi;
-
-  char buffer [OSPF6_MAX_LSASIZE];
-  struct ospf6_lsa_header *lsa_header;
-
-  int count;
-  struct ospf6_lsa *old, *lsa;
-  struct ospf6_network_lsa *network_lsa;
-  struct ospf6_network_lsdesc *lsdesc;
-  struct ospf6_neighbor *on;
-  struct ospf6_link_lsa *link_lsa;
-  struct listnode *i;
-  u_int16_t type;
-
-  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),
-                           oi->area->ospf6->router_id, oi->area->lsdb);
-
-  /* Do not originate Network-LSA if not DR */
-  if (oi->state != OSPF6_INTERFACE_DR)
-    {
-      if (old)
-       {
-         ospf6_lsa_purge (old);
-           /*
-            * Waiting till the LSA is actually removed from the database to
-            * trigger SPF delays network convergence.
-            */
-         ospf6_spf_schedule (oi->area->ospf6,
-                             OSPF6_SPF_FLAGS_NETWORK_LSA_ORIGINATED);
+       struct ospf6_interface *oi;
+
+       char buffer[OSPF6_MAX_LSASIZE];
+       struct ospf6_lsa_header *lsa_header;
+
+       int count;
+       struct ospf6_lsa *old, *lsa;
+       struct ospf6_network_lsa *network_lsa;
+       struct ospf6_network_lsdesc *lsdesc;
+       struct ospf6_neighbor *on;
+       struct ospf6_link_lsa *link_lsa;
+       struct listnode *i;
+       uint16_t type;
+
+       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),
+                               oi->area->ospf6->router_id, oi->area->lsdb);
+
+       /* Do not originate Network-LSA if not DR */
+       if (oi->state != OSPF6_INTERFACE_DR) {
+               if (old) {
+                       ospf6_lsa_purge(old);
+                       /*
+                        * Waiting till the LSA is actually removed from the
+                        * database to
+                        * trigger SPF delays network convergence.
+                        */
+                       ospf6_spf_schedule(
+                               oi->area->ospf6,
+                               OSPF6_SPF_FLAGS_NETWORK_LSA_ORIGINATED);
+               }
+               return 0;
+       }
+
+       if (IS_OSPF6_DEBUG_ORIGINATE(NETWORK))
+               zlog_debug("Originate Network-LSA for Interface %s",
+                          oi->interface->name);
+
+       /* If none of neighbor is adjacent to us */
+       count = 0;
+
+       for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, i, on))
+               if (on->state == OSPF6_NEIGHBOR_FULL)
+                       count++;
+
+       if (count == 0) {
+               if (IS_OSPF6_DEBUG_ORIGINATE(NETWORK))
+                       zlog_debug("Interface stub, ignore");
+               if (old)
+                       ospf6_lsa_purge(old);
+               return 0;
+       }
+
+       /* prepare buffer */
+       memset(buffer, 0, sizeof(buffer));
+       lsa_header = (struct ospf6_lsa_header *)buffer;
+       network_lsa =
+               (struct ospf6_network_lsa *)((caddr_t)lsa_header
+                                            + sizeof(struct ospf6_lsa_header));
+
+       /* Collect the interface's Link-LSAs to describe
+          network's optional capabilities */
+       type = htons(OSPF6_LSTYPE_LINK);
+       for (ALL_LSDB_TYPED(oi->lsdb, type, lsa)) {
+               link_lsa = (struct ospf6_link_lsa
+                                   *)((caddr_t)lsa->header
+                                      + sizeof(struct ospf6_lsa_header));
+               network_lsa->options[0] |= link_lsa->options[0];
+               network_lsa->options[1] |= link_lsa->options[1];
+               network_lsa->options[2] |= link_lsa->options[2];
+       }
+
+       lsdesc = (struct ospf6_network_lsdesc
+                         *)((caddr_t)network_lsa
+                            + sizeof(struct ospf6_network_lsa));
+
+       /* set Link Description to the router itself */
+       lsdesc->router_id = oi->area->ospf6->router_id;
+       lsdesc++;
+
+       /* Walk through the neighbors */
+       for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, i, on)) {
+               if (on->state != OSPF6_NEIGHBOR_FULL)
+                       continue;
+
+               /* set this neighbor's Router-ID to LSA */
+               lsdesc->router_id = on->router_id;
+               lsdesc++;
        }
-      return 0;
-    }
-
-  if (IS_OSPF6_DEBUG_ORIGINATE (NETWORK))
-    zlog_debug ("Originate Network-LSA for Interface %s", oi->interface->name);
-
-  /* If none of neighbor is adjacent to us */
-  count = 0;
-
-  for (ALL_LIST_ELEMENTS_RO (oi->neighbor_list, i, on))
-    if (on->state == OSPF6_NEIGHBOR_FULL)
-      count++;
-
-  if (count == 0)
-    {
-      if (IS_OSPF6_DEBUG_ORIGINATE (NETWORK))
-        zlog_debug ("Interface stub, ignore");
-      if (old)
-        ospf6_lsa_purge (old);
-      return 0;
-    }
-
-  /* prepare buffer */
-  memset (buffer, 0, sizeof (buffer));
-  lsa_header = (struct ospf6_lsa_header *) buffer;
-  network_lsa = (struct ospf6_network_lsa *)
-    ((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header));
-
-  /* Collect the interface's Link-LSAs to describe
-     network's optional capabilities */
-  type = htons (OSPF6_LSTYPE_LINK);
-  for (lsa = ospf6_lsdb_type_head (type, oi->lsdb); lsa;
-       lsa = ospf6_lsdb_type_next (type, lsa))
-    {
-      link_lsa = (struct ospf6_link_lsa *)
-        ((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header));
-      network_lsa->options[0] |= link_lsa->options[0];
-      network_lsa->options[1] |= link_lsa->options[1];
-      network_lsa->options[2] |= link_lsa->options[2];
-    }
-
-  lsdesc = (struct ospf6_network_lsdesc *)
-    ((caddr_t) network_lsa + sizeof (struct ospf6_network_lsa));
-
-  /* set Link Description to the router itself */
-  lsdesc->router_id = oi->area->ospf6->router_id;
-  lsdesc++;
-
-  /* Walk through the neighbors */
-  for (ALL_LIST_ELEMENTS_RO (oi->neighbor_list, i, on))
-    {
-      if (on->state != OSPF6_NEIGHBOR_FULL)
-        continue;
-
-      /* set this neighbor's Router-ID to LSA */
-      lsdesc->router_id = on->router_id;
-      lsdesc++;
-    }
-
-  /* Fill LSA Header */
-  lsa_header->age = 0;
-  lsa_header->type = htons (OSPF6_LSTYPE_NETWORK);
-  lsa_header->id = htonl (oi->interface->ifindex);
-  lsa_header->adv_router = oi->area->ospf6->router_id;
-  lsa_header->seqnum =
-    ospf6_new_ls_seqnum (lsa_header->type, lsa_header->id,
-                         lsa_header->adv_router, oi->area->lsdb);
-  lsa_header->length = htons ((caddr_t) lsdesc - (caddr_t) buffer);
-
-  /* LSA checksum */
-  ospf6_lsa_checksum (lsa_header);
-
-  /* create LSA */
-  lsa = ospf6_lsa_create (lsa_header);
-
-  /* Originate */
-  ospf6_lsa_originate_area (lsa, oi->area);
-
-  return 0;
+
+       /* Fill LSA Header */
+       lsa_header->age = 0;
+       lsa_header->type = htons(OSPF6_LSTYPE_NETWORK);
+       lsa_header->id = htonl(oi->interface->ifindex);
+       lsa_header->adv_router = oi->area->ospf6->router_id;
+       lsa_header->seqnum =
+               ospf6_new_ls_seqnum(lsa_header->type, lsa_header->id,
+                                   lsa_header->adv_router, oi->area->lsdb);
+       lsa_header->length = htons((caddr_t)lsdesc - (caddr_t)buffer);
+
+       /* LSA checksum */
+       ospf6_lsa_checksum(lsa_header);
+
+       /* create LSA */
+       lsa = ospf6_lsa_create(lsa_header);
+
+       /* Originate */
+       ospf6_lsa_originate_area(lsa, oi->area);
+
+       return 0;
 }
 
 
@@ -550,1154 +574,1697 @@ ospf6_network_lsa_originate (struct thread *thread)
 /* RFC2740 3.4.3.6 Link-LSA */
 /****************************/
 
-static char *
-ospf6_link_lsa_get_prefix_str (struct ospf6_lsa *lsa, char *buf, int buflen,
-                              int pos)
+static char *ospf6_link_lsa_get_prefix_str(struct ospf6_lsa *lsa, char *buf,
+                                          int buflen, int pos)
 {
-  char *start, *end, *current;
-  struct ospf6_link_lsa *link_lsa;
-  struct in6_addr in6;
-  struct ospf6_prefix *prefix;
-  int cnt = 0, prefixnum;
-
-  if (lsa)
-    {
-      link_lsa = (struct ospf6_link_lsa *)
-       ((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header));
-
-      if (pos == 0) {
-       inet_ntop (AF_INET6, &link_lsa->linklocal_addr, buf, buflen);
-       return (buf);
-      }
-
-      prefixnum = ntohl (link_lsa->prefix_num);
-      if (pos > prefixnum)
+       char *start, *end, *current;
+       struct ospf6_link_lsa *link_lsa;
+       struct in6_addr in6;
+       struct ospf6_prefix *prefix;
+       int cnt = 0, prefixnum;
+
+       if (lsa) {
+               link_lsa = (struct ospf6_link_lsa
+                                   *)((caddr_t)lsa->header
+                                      + sizeof(struct ospf6_lsa_header));
+
+               if (pos == 0) {
+                       inet_ntop(AF_INET6, &link_lsa->linklocal_addr, buf,
+                                 buflen);
+                       return (buf);
+               }
+
+               prefixnum = ntohl(link_lsa->prefix_num);
+               if (pos > prefixnum)
+                       return (NULL);
+
+               start = (char *)link_lsa + sizeof(struct ospf6_link_lsa);
+               end = (char *)lsa->header + ntohs(lsa->header->length);
+               current = start;
+
+               do {
+                       prefix = (struct ospf6_prefix *)current;
+                       if (prefix->prefix_length == 0
+                           || current + OSPF6_PREFIX_SIZE(prefix) > end) {
+                               return (NULL);
+                       }
+
+                       if (cnt < pos) {
+                               current =
+                                       start + pos * OSPF6_PREFIX_SIZE(prefix);
+                               cnt++;
+                       } else {
+                               memset(&in6, 0, sizeof(in6));
+                               memcpy(&in6, OSPF6_PREFIX_BODY(prefix),
+                                      OSPF6_PREFIX_SPACE(
+                                              prefix->prefix_length));
+                               inet_ntop(AF_INET6, &in6, buf, buflen);
+                               return (buf);
+                       }
+               } while (current <= end);
+       }
        return (NULL);
-
-      start = (char *) link_lsa + sizeof (struct ospf6_link_lsa);
-      end = (char *) lsa->header + ntohs (lsa->header->length);
-      current = start;
-
-      do
-       {
-         prefix = (struct ospf6_prefix *) current;
-         if (prefix->prefix_length == 0 ||
-             current + OSPF6_PREFIX_SIZE (prefix) > end)
-           {
-             return (NULL);
-           }
-
-         if (cnt < pos)
-           {
-             current = start + pos*OSPF6_PREFIX_SIZE(prefix);
-             cnt++;
-           }
-         else
-           {
-             memset (&in6, 0, sizeof (in6));
-             memcpy (&in6, OSPF6_PREFIX_BODY (prefix),
-                     OSPF6_PREFIX_SPACE (prefix->prefix_length));
-             inet_ntop (AF_INET6, &in6, buf, buflen);
-             return (buf);
-           }
-       } while (current <= end);
-    }
-  return (NULL);
 }
 
-static int
-ospf6_link_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
+static int ospf6_link_lsa_show(struct vty *vty, struct ospf6_lsa *lsa)
 {
-  char *start, *end, *current;
-  struct ospf6_link_lsa *link_lsa;
-  int prefixnum;
-  char buf[128], options[32];
-  struct ospf6_prefix *prefix;
-  const char *p, *mc, *la, *nu;
-  struct in6_addr in6;
-
-  link_lsa = (struct ospf6_link_lsa *)
-    ((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header));
-
-  ospf6_options_printbuf (link_lsa->options, options, sizeof (options));
-  inet_ntop (AF_INET6, &link_lsa->linklocal_addr, buf, sizeof (buf));
-  prefixnum = ntohl (link_lsa->prefix_num);
-
-  vty_out (vty, "     Priority: %d Options: %s\n",
-           link_lsa->priority, options);
-  vty_out (vty, "     LinkLocal Address: %s\n", buf);
-  vty_out (vty, "     Number of Prefix: %d\n", prefixnum);
-
-  start = (char *) link_lsa + sizeof (struct ospf6_link_lsa);
-  end = (char *) lsa->header + ntohs (lsa->header->length); 
-  for (current = start; current < end; current += OSPF6_PREFIX_SIZE (prefix))
-    {
-      prefix = (struct ospf6_prefix *) current;
-      if (prefix->prefix_length == 0 ||
-          current + OSPF6_PREFIX_SIZE (prefix) > end)
-        break;
-
-      p = (CHECK_FLAG (prefix->prefix_options, OSPF6_PREFIX_OPTION_P) ?
-           "P" : "--");
-      mc = (CHECK_FLAG (prefix->prefix_options, OSPF6_PREFIX_OPTION_MC) ?
-           "MC" : "--");
-      la = (CHECK_FLAG (prefix->prefix_options, OSPF6_PREFIX_OPTION_LA) ?
-           "LA" : "--");
-      nu = (CHECK_FLAG (prefix->prefix_options, OSPF6_PREFIX_OPTION_NU) ?
-           "NU" : "--");
-      vty_out (vty, "     Prefix Options: %s|%s|%s|%s\n",
-               p, mc, la, nu);
-
-      memset (&in6, 0, sizeof (in6));
-      memcpy (&in6, OSPF6_PREFIX_BODY (prefix),
-              OSPF6_PREFIX_SPACE (prefix->prefix_length));
-      inet_ntop (AF_INET6, &in6, buf, sizeof (buf));
-      vty_out (vty, "     Prefix: %s/%d\n",
-               buf, prefix->prefix_length);
-    }
-
-  return 0;
+       char *start, *end, *current;
+       struct ospf6_link_lsa *link_lsa;
+       int prefixnum;
+       char buf[128], options[32];
+       struct ospf6_prefix *prefix;
+       const char *p, *mc, *la, *nu;
+       struct in6_addr in6;
+
+       link_lsa = (struct ospf6_link_lsa *)((caddr_t)lsa->header
+                                            + sizeof(struct ospf6_lsa_header));
+
+       ospf6_options_printbuf(link_lsa->options, options, sizeof(options));
+       inet_ntop(AF_INET6, &link_lsa->linklocal_addr, buf, sizeof(buf));
+       prefixnum = ntohl(link_lsa->prefix_num);
+
+       vty_out(vty, "     Priority: %d Options: %s\n", link_lsa->priority,
+               options);
+       vty_out(vty, "     LinkLocal Address: %s\n", buf);
+       vty_out(vty, "     Number of Prefix: %d\n", prefixnum);
+
+       start = (char *)link_lsa + sizeof(struct ospf6_link_lsa);
+       end = (char *)lsa->header + ntohs(lsa->header->length);
+       for (current = start; current < end;
+            current += OSPF6_PREFIX_SIZE(prefix)) {
+               prefix = (struct ospf6_prefix *)current;
+               if (prefix->prefix_length == 0
+                   || current + OSPF6_PREFIX_SIZE(prefix) > end)
+                       break;
+
+               p = (CHECK_FLAG(prefix->prefix_options, OSPF6_PREFIX_OPTION_P)
+                            ? "P"
+                            : "--");
+               mc = (CHECK_FLAG(prefix->prefix_options, OSPF6_PREFIX_OPTION_MC)
+                             ? "MC"
+                             : "--");
+               la = (CHECK_FLAG(prefix->prefix_options, OSPF6_PREFIX_OPTION_LA)
+                             ? "LA"
+                             : "--");
+               nu = (CHECK_FLAG(prefix->prefix_options, OSPF6_PREFIX_OPTION_NU)
+                             ? "NU"
+                             : "--");
+               vty_out(vty, "     Prefix Options: %s|%s|%s|%s\n", p, mc, la,
+                       nu);
+
+               memset(&in6, 0, sizeof(in6));
+               memcpy(&in6, OSPF6_PREFIX_BODY(prefix),
+                      OSPF6_PREFIX_SPACE(prefix->prefix_length));
+               inet_ntop(AF_INET6, &in6, buf, sizeof(buf));
+               vty_out(vty, "     Prefix: %s/%d\n", buf,
+                       prefix->prefix_length);
+       }
+
+       return 0;
 }
 
-int
-ospf6_link_lsa_originate (struct thread *thread)
+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;
-
-  struct ospf6_link_lsa *link_lsa;
-  struct ospf6_route *route;
-  struct ospf6_prefix *op;
-
-  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),
-                           htonl (oi->interface->ifindex),
-                           oi->area->ospf6->router_id, oi->lsdb);
-
-  if (CHECK_FLAG (oi->flag, OSPF6_INTERFACE_DISABLE))
-    {
-      if (old)
-        ospf6_lsa_purge (old);
-      return 0;
-    }
-
-  if (IS_OSPF6_DEBUG_ORIGINATE (LINK))
-    zlog_debug ("Originate Link-LSA for Interface %s", oi->interface->name);
-
-  /* can't make Link-LSA if linklocal address not set */
-  if (oi->linklocal_addr == NULL)
-    {
-      if (IS_OSPF6_DEBUG_ORIGINATE (LINK))
-        zlog_debug ("No Linklocal address on %s, defer originating",
-                   oi->interface->name);
-      if (old)
-        ospf6_lsa_purge (old);
-      return 0;
-    }
-
-  /* prepare buffer */
-  memset (buffer, 0, sizeof (buffer));
-  lsa_header = (struct ospf6_lsa_header *) buffer;
-  link_lsa = (struct ospf6_link_lsa *)
-    ((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header));
-
-  /* Fill Link-LSA */
-  link_lsa->priority = oi->priority;
-  memcpy (link_lsa->options, oi->area->options, 3);
-  memcpy (&link_lsa->linklocal_addr, oi->linklocal_addr,
-          sizeof (struct in6_addr));
-  link_lsa->prefix_num = htonl (oi->route_connected->count);
-
-  op = (struct ospf6_prefix *)
-    ((caddr_t) link_lsa + sizeof (struct ospf6_link_lsa));
-
-  /* connected prefix to advertise */
-  for (route = ospf6_route_head (oi->route_connected); route;
-       route = ospf6_route_next (route))
-    {
-      op->prefix_length = route->prefix.prefixlen;
-      op->prefix_options = route->path.prefix_options;
-      op->prefix_metric = htons (0);
-      memcpy (OSPF6_PREFIX_BODY (op), &route->prefix.u.prefix6,
-              OSPF6_PREFIX_SPACE (op->prefix_length));
-      op = OSPF6_PREFIX_NEXT (op);
-    }
-
-  /* Fill LSA Header */
-  lsa_header->age = 0;
-  lsa_header->type = htons (OSPF6_LSTYPE_LINK);
-  lsa_header->id = htonl (oi->interface->ifindex);
-  lsa_header->adv_router = oi->area->ospf6->router_id;
-  lsa_header->seqnum =
-    ospf6_new_ls_seqnum (lsa_header->type, lsa_header->id,
-                         lsa_header->adv_router, oi->lsdb);
-  lsa_header->length = htons ((caddr_t) op - (caddr_t) buffer);
-
-  /* LSA checksum */
-  ospf6_lsa_checksum (lsa_header);
-
-  /* create LSA */
-  lsa = ospf6_lsa_create (lsa_header);
-
-  /* Originate */
-  ospf6_lsa_originate_interface (lsa, oi);
-
-  return 0;
+       struct ospf6_interface *oi;
+
+       char buffer[OSPF6_MAX_LSASIZE];
+       struct ospf6_lsa_header *lsa_header;
+       struct ospf6_lsa *old, *lsa;
+
+       struct ospf6_link_lsa *link_lsa;
+       struct ospf6_route *route;
+       struct ospf6_prefix *op;
+
+       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),
+                               htonl(oi->interface->ifindex),
+                               oi->area->ospf6->router_id, oi->lsdb);
+
+       if (CHECK_FLAG(oi->flag, OSPF6_INTERFACE_DISABLE)) {
+               if (old)
+                       ospf6_lsa_purge(old);
+               return 0;
+       }
+
+       if (IS_OSPF6_DEBUG_ORIGINATE(LINK))
+               zlog_debug("Originate Link-LSA for Interface %s",
+                          oi->interface->name);
+
+       /* can't make Link-LSA if linklocal address not set */
+       if (oi->linklocal_addr == NULL) {
+               if (IS_OSPF6_DEBUG_ORIGINATE(LINK))
+                       zlog_debug(
+                               "No Linklocal address on %s, defer originating",
+                               oi->interface->name);
+               if (old)
+                       ospf6_lsa_purge(old);
+               return 0;
+       }
+
+       /* prepare buffer */
+       memset(buffer, 0, sizeof(buffer));
+       lsa_header = (struct ospf6_lsa_header *)buffer;
+       link_lsa = (struct ospf6_link_lsa *)((caddr_t)lsa_header
+                                            + sizeof(struct ospf6_lsa_header));
+
+       /* Fill Link-LSA */
+       link_lsa->priority = oi->priority;
+       memcpy(link_lsa->options, oi->area->options, 3);
+       memcpy(&link_lsa->linklocal_addr, oi->linklocal_addr,
+              sizeof(struct in6_addr));
+       link_lsa->prefix_num = htonl(oi->route_connected->count);
+
+       op = (struct ospf6_prefix *)((caddr_t)link_lsa
+                                    + sizeof(struct ospf6_link_lsa));
+
+       /* connected prefix to advertise */
+       for (route = ospf6_route_head(oi->route_connected); route;
+            route = ospf6_route_next(route)) {
+               op->prefix_length = route->prefix.prefixlen;
+               op->prefix_options = route->path.prefix_options;
+               op->prefix_metric = htons(0);
+               memcpy(OSPF6_PREFIX_BODY(op), &route->prefix.u.prefix6,
+                      OSPF6_PREFIX_SPACE(op->prefix_length));
+               op = OSPF6_PREFIX_NEXT(op);
+       }
+
+       /* Fill LSA Header */
+       lsa_header->age = 0;
+       lsa_header->type = htons(OSPF6_LSTYPE_LINK);
+       lsa_header->id = htonl(oi->interface->ifindex);
+       lsa_header->adv_router = oi->area->ospf6->router_id;
+       lsa_header->seqnum =
+               ospf6_new_ls_seqnum(lsa_header->type, lsa_header->id,
+                                   lsa_header->adv_router, oi->lsdb);
+       lsa_header->length = htons((caddr_t)op - (caddr_t)buffer);
+
+       /* LSA checksum */
+       ospf6_lsa_checksum(lsa_header);
+
+       /* create LSA */
+       lsa = ospf6_lsa_create(lsa_header);
+
+       /* Originate */
+       ospf6_lsa_originate_interface(lsa, oi);
+
+       return 0;
 }
 
 
 /*****************************************/
 /* RFC2740 3.4.3.7 Intra-Area-Prefix-LSA */
 /*****************************************/
-static char *
-ospf6_intra_prefix_lsa_get_prefix_str (struct ospf6_lsa *lsa, char *buf,
-                                      int buflen, int pos)
+static char *ospf6_intra_prefix_lsa_get_prefix_str(struct ospf6_lsa *lsa,
+                                                  char *buf, int buflen,
+                                                  int pos)
 {
-  char *start, *end, *current;
-  struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
-  struct in6_addr in6;
-  int prefixnum, cnt = 0;
-  struct ospf6_prefix *prefix;
-
-  if (lsa)
-    {
-      intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *)
-       ((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header));
-
-      prefixnum = ntohs (intra_prefix_lsa->prefix_num);
-      if (pos > prefixnum)
-       return (NULL);
-
-      start = (char *) intra_prefix_lsa + sizeof (struct ospf6_intra_prefix_lsa);
-      end = (char *) lsa->header + ntohs (lsa->header->length);
-      current = start;
-
-      do
-       {
-         prefix = (struct ospf6_prefix *) current;
-         if (prefix->prefix_length == 0 ||
-             current + OSPF6_PREFIX_SIZE (prefix) > end)
-           {
-             return NULL;
-           }
-
-         if (cnt < pos)
-           {
-             current = start + pos*OSPF6_PREFIX_SIZE(prefix);
-             cnt++;
-           }
-         else
-           {
-             memset (&in6, 0, sizeof (in6));
-             memcpy (&in6, OSPF6_PREFIX_BODY (prefix),
-                     OSPF6_PREFIX_SPACE (prefix->prefix_length));
-             inet_ntop (AF_INET6, &in6, buf, buflen);
-             sprintf(&buf[strlen(buf)], "/%d", prefix->prefix_length);
-             return (buf);
-           }
-       } while (current <= end);
-    }
-  return (buf);
+       char *start, *end, *current;
+       struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
+       struct in6_addr in6;
+       int prefixnum, cnt = 0;
+       struct ospf6_prefix *prefix;
+
+       if (lsa) {
+               intra_prefix_lsa =
+                       (struct ospf6_intra_prefix_lsa
+                                *)((caddr_t)lsa->header
+                                   + sizeof(struct ospf6_lsa_header));
+
+               prefixnum = ntohs(intra_prefix_lsa->prefix_num);
+               if (pos > prefixnum)
+                       return (NULL);
+
+               start = (char *)intra_prefix_lsa
+                       + sizeof(struct ospf6_intra_prefix_lsa);
+               end = (char *)lsa->header + ntohs(lsa->header->length);
+               current = start;
+
+               do {
+                       prefix = (struct ospf6_prefix *)current;
+                       if (prefix->prefix_length == 0
+                           || current + OSPF6_PREFIX_SIZE(prefix) > end) {
+                               return NULL;
+                       }
+
+                       if (cnt < pos) {
+                               current =
+                                       start + pos * OSPF6_PREFIX_SIZE(prefix);
+                               cnt++;
+                       } else {
+                               memset(&in6, 0, sizeof(in6));
+                               memcpy(&in6, OSPF6_PREFIX_BODY(prefix),
+                                      OSPF6_PREFIX_SPACE(
+                                              prefix->prefix_length));
+                               inet_ntop(AF_INET6, &in6, buf, buflen);
+                               sprintf(&buf[strlen(buf)], "/%d",
+                                       prefix->prefix_length);
+                               return (buf);
+                       }
+               } while (current <= end);
+       }
+       return (buf);
 }
 
-static int
-ospf6_intra_prefix_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
+static int ospf6_intra_prefix_lsa_show(struct vty *vty, struct ospf6_lsa *lsa)
 {
-  char *start, *end, *current;
-  struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
-  int prefixnum;
-  char buf[128];
-  struct ospf6_prefix *prefix;
-  char id[16], adv_router[16];
-  const char *p, *mc, *la, *nu;
-  struct in6_addr in6;
-
-  intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *)
-    ((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header));
-
-  prefixnum = ntohs (intra_prefix_lsa->prefix_num);
-
-  vty_out (vty, "     Number of Prefix: %d\n", prefixnum);
-
-  inet_ntop (AF_INET, &intra_prefix_lsa->ref_id, id, sizeof (id));
-  inet_ntop (AF_INET, &intra_prefix_lsa->ref_adv_router,
-             adv_router, sizeof (adv_router));
-  vty_out (vty, "     Reference: %s Id: %s Adv: %s\n",
-           ospf6_lstype_name (intra_prefix_lsa->ref_type), id, adv_router);
-
-  start = (char *) intra_prefix_lsa + sizeof (struct ospf6_intra_prefix_lsa);
-  end = (char *) lsa->header + ntohs (lsa->header->length); 
-  for (current = start; current < end; current += OSPF6_PREFIX_SIZE (prefix))
-    {
-      prefix = (struct ospf6_prefix *) current;
-      if (prefix->prefix_length == 0 ||
-          current + OSPF6_PREFIX_SIZE (prefix) > end)
-        break;
-
-      p = (CHECK_FLAG (prefix->prefix_options, OSPF6_PREFIX_OPTION_P) ?
-           "P" : "--");
-      mc = (CHECK_FLAG (prefix->prefix_options, OSPF6_PREFIX_OPTION_MC) ?
-           "MC" : "--");
-      la = (CHECK_FLAG (prefix->prefix_options, OSPF6_PREFIX_OPTION_LA) ?
-           "LA" : "--");
-      nu = (CHECK_FLAG (prefix->prefix_options, OSPF6_PREFIX_OPTION_NU) ?
-           "NU" : "--");
-      vty_out (vty, "     Prefix Options: %s|%s|%s|%s\n",
-               p, mc, la, nu);
-
-      memset (&in6, 0, sizeof (in6));
-      memcpy (&in6, OSPF6_PREFIX_BODY (prefix),
-              OSPF6_PREFIX_SPACE (prefix->prefix_length));
-      inet_ntop (AF_INET6, &in6, buf, sizeof (buf));
-      vty_out (vty, "     Prefix: %s/%d\n",
-               buf, prefix->prefix_length);
-    }
-
-  return 0;
+       char *start, *end, *current;
+       struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
+       int prefixnum;
+       char buf[128];
+       struct ospf6_prefix *prefix;
+       char id[16], adv_router[16];
+       const char *p, *mc, *la, *nu;
+       struct in6_addr in6;
+
+       intra_prefix_lsa = (struct ospf6_intra_prefix_lsa
+                                   *)((caddr_t)lsa->header
+                                      + sizeof(struct ospf6_lsa_header));
+
+       prefixnum = ntohs(intra_prefix_lsa->prefix_num);
+
+       vty_out(vty, "     Number of Prefix: %d\n", prefixnum);
+
+       inet_ntop(AF_INET, &intra_prefix_lsa->ref_id, id, sizeof(id));
+       inet_ntop(AF_INET, &intra_prefix_lsa->ref_adv_router, adv_router,
+                 sizeof(adv_router));
+       vty_out(vty, "     Reference: %s Id: %s Adv: %s\n",
+               ospf6_lstype_name(intra_prefix_lsa->ref_type), id, adv_router);
+
+       start = (char *)intra_prefix_lsa
+               + sizeof(struct ospf6_intra_prefix_lsa);
+       end = (char *)lsa->header + ntohs(lsa->header->length);
+       for (current = start; current < end;
+            current += OSPF6_PREFIX_SIZE(prefix)) {
+               prefix = (struct ospf6_prefix *)current;
+               if (prefix->prefix_length == 0
+                   || current + OSPF6_PREFIX_SIZE(prefix) > end)
+                       break;
+
+               p = (CHECK_FLAG(prefix->prefix_options, OSPF6_PREFIX_OPTION_P)
+                            ? "P"
+                            : "--");
+               mc = (CHECK_FLAG(prefix->prefix_options, OSPF6_PREFIX_OPTION_MC)
+                             ? "MC"
+                             : "--");
+               la = (CHECK_FLAG(prefix->prefix_options, OSPF6_PREFIX_OPTION_LA)
+                             ? "LA"
+                             : "--");
+               nu = (CHECK_FLAG(prefix->prefix_options, OSPF6_PREFIX_OPTION_NU)
+                             ? "NU"
+                             : "--");
+               vty_out(vty, "     Prefix Options: %s|%s|%s|%s\n", p, mc, la,
+                       nu);
+
+               memset(&in6, 0, sizeof(in6));
+               memcpy(&in6, OSPF6_PREFIX_BODY(prefix),
+                      OSPF6_PREFIX_SPACE(prefix->prefix_length));
+               inet_ntop(AF_INET6, &in6, buf, sizeof(buf));
+               vty_out(vty, "     Prefix: %s/%d\n", buf,
+                       prefix->prefix_length);
+       }
+
+       return 0;
 }
 
-int
-ospf6_intra_prefix_lsa_originate_stub (struct thread *thread)
+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;
-
-  struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
-  struct ospf6_interface *oi;
-  struct ospf6_neighbor *on;
-  struct ospf6_route *route;
-  struct ospf6_prefix *op;
-  struct listnode *i, *j;
-  int full_count = 0;
-  unsigned short prefix_num = 0;
-  char buf[PREFIX2STR_BUFFER];
-  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 (! IS_AREA_ENABLED (oa))
-    {
-      if (old)
-        ospf6_lsa_purge (old);
-      return 0;
-    }
-
-  if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
-    zlog_debug ("Originate Intra-Area-Prefix-LSA for area %s's stub prefix",
-               oa->name);
-
-  /* prepare buffer */
-  memset (buffer, 0, sizeof (buffer));
-  lsa_header = (struct ospf6_lsa_header *) buffer;
-  intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *)
-    ((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header));
-
-  /* Fill Intra-Area-Prefix-LSA */
-  intra_prefix_lsa->ref_type = htons (OSPF6_LSTYPE_ROUTER);
-  intra_prefix_lsa->ref_id = htonl (0);
-  intra_prefix_lsa->ref_adv_router = oa->ospf6->router_id;
-
-  route_advertise = ospf6_route_table_create (0, 0);
-
-  for (ALL_LIST_ELEMENTS_RO (oa->if_list, i, oi))
-    {
-      if (oi->state == OSPF6_INTERFACE_DOWN)
-        {
-          if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
-            zlog_debug ("  Interface %s is down, ignore", oi->interface->name);
-          continue;
-        }
-
-      full_count = 0;
-
-      for (ALL_LIST_ELEMENTS_RO (oi->neighbor_list, j, on))
-        if (on->state == OSPF6_NEIGHBOR_FULL)
-          full_count++;
-
-      if (oi->state != OSPF6_INTERFACE_LOOPBACK &&
-          oi->state != OSPF6_INTERFACE_POINTTOPOINT &&
-          full_count != 0)
-        {
-          if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
-            zlog_debug ("  Interface %s is not stub, ignore",
-                       oi->interface->name);
-          continue;
-        }
-
-      if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
-        zlog_debug ("  Interface %s:", oi->interface->name);
-
-      /* connected prefix to advertise */
-      for (route = ospf6_route_head (oi->route_connected); route;
-           route = ospf6_route_best_next (route))
-        {
-          if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
-            {
-              prefix2str (&route->prefix, buf, sizeof (buf));
-              zlog_debug ("    include %s", buf);
-            }
-          ospf6_route_add (ospf6_route_copy (route), route_advertise);
-        }
-    }
-
-  if (route_advertise->count == 0)
-    {
-      if (old)
-        ospf6_lsa_purge (old);
-      ospf6_route_table_delete (route_advertise);
-      return 0;
-    }
-
-  /* put prefixes to advertise */
-  prefix_num = 0;
-  op = (struct ospf6_prefix *)
-    ((caddr_t) intra_prefix_lsa + sizeof (struct ospf6_intra_prefix_lsa));
-  for (route = ospf6_route_head (route_advertise); route;
-       route = ospf6_route_best_next (route))
-    {
-      op->prefix_length = route->prefix.prefixlen;
-      op->prefix_options = route->path.prefix_options;
-      op->prefix_metric = htons (route->path.cost);
-      memcpy (OSPF6_PREFIX_BODY (op), &route->prefix.u.prefix6,
-              OSPF6_PREFIX_SPACE (op->prefix_length));
-      op = OSPF6_PREFIX_NEXT (op);
-      prefix_num++;
-    }
-
-  ospf6_route_table_delete (route_advertise);
-
-  if (prefix_num == 0)
-    {
-      if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
-        zlog_debug ("Quit to Advertise Intra-Prefix: no route to advertise");
-      return 0;
-    }
-
-  intra_prefix_lsa->prefix_num = htons (prefix_num);
-
-  /* Fill LSA Header */
-  lsa_header->age = 0;
-  lsa_header->type = htons (OSPF6_LSTYPE_INTRA_PREFIX);
-  lsa_header->id = htonl (0);
-  lsa_header->adv_router = oa->ospf6->router_id;
-  lsa_header->seqnum =
-    ospf6_new_ls_seqnum (lsa_header->type, lsa_header->id,
-                         lsa_header->adv_router, oa->lsdb);
-  lsa_header->length = htons ((caddr_t) op - (caddr_t) lsa_header);
-
-  /* LSA checksum */
-  ospf6_lsa_checksum (lsa_header);
-
-  /* create LSA */
-  lsa = ospf6_lsa_create (lsa_header);
-
-  /* Originate */
-  ospf6_lsa_originate_area (lsa, oa);
-
-  return 0;
+       struct ospf6_area *oa;
+
+       char buffer[OSPF6_MAX_LSASIZE];
+       struct ospf6_lsa_header *lsa_header;
+       struct ospf6_lsa *old, *lsa, *old_next = NULL;
+
+       struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
+       struct ospf6_interface *oi;
+       struct ospf6_neighbor *on;
+       struct ospf6_route *route;
+       struct ospf6_prefix *op;
+       struct listnode *i, *j;
+       int full_count = 0;
+       unsigned short prefix_num = 0;
+       char buf[PREFIX2STR_BUFFER];
+       struct ospf6_route_table *route_advertise;
+       int ls_id = 0;
+
+       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 (!IS_AREA_ENABLED(oa)) {
+               if (old) {
+                       ospf6_lsa_purge(old);
+                       /* find previous LSA */
+                       old_next = ospf6_lsdb_lookup(
+                               htons(OSPF6_LSTYPE_INTRA_PREFIX),
+                               htonl(++ls_id), oa->ospf6->router_id, oa->lsdb);
+
+                       while (old_next) {
+                               ospf6_lsa_purge(old_next);
+                               old_next = ospf6_lsdb_lookup(
+                                       htons(OSPF6_LSTYPE_INTRA_PREFIX),
+                                       htonl(++ls_id), oa->ospf6->router_id,
+                                       oa->lsdb);
+                       }
+               }
+               return 0;
+       }
+
+       if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX))
+               zlog_debug(
+                       "Originate Intra-Area-Prefix-LSA for area %s's stub prefix",
+                       oa->name);
+
+       /* prepare buffer */
+       memset(buffer, 0, sizeof(buffer));
+       lsa_header = (struct ospf6_lsa_header *)buffer;
+       intra_prefix_lsa = (struct ospf6_intra_prefix_lsa
+                                   *)((caddr_t)lsa_header
+                                      + sizeof(struct ospf6_lsa_header));
+
+       /* Fill Intra-Area-Prefix-LSA */
+       intra_prefix_lsa->ref_type = htons(OSPF6_LSTYPE_ROUTER);
+       intra_prefix_lsa->ref_id = htonl(0);
+       intra_prefix_lsa->ref_adv_router = oa->ospf6->router_id;
+
+       route_advertise = ospf6_route_table_create(0, 0);
+
+       for (ALL_LIST_ELEMENTS_RO(oa->if_list, i, oi)) {
+               if (oi->state == OSPF6_INTERFACE_DOWN) {
+                       if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX))
+                               zlog_debug("  Interface %s is down, ignore",
+                                          oi->interface->name);
+                       continue;
+               }
+
+               full_count = 0;
+
+               for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, j, on))
+                       if (on->state == OSPF6_NEIGHBOR_FULL)
+                               full_count++;
+
+               if (oi->state != OSPF6_INTERFACE_LOOPBACK
+                   && oi->state != OSPF6_INTERFACE_POINTTOPOINT
+                   && full_count != 0) {
+                       if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX))
+                               zlog_debug("  Interface %s is not stub, ignore",
+                                          oi->interface->name);
+                       continue;
+               }
+
+               if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX))
+                       zlog_debug("  Interface %s:", oi->interface->name);
+
+               /* connected prefix to advertise */
+               for (route = ospf6_route_head(oi->route_connected); route;
+                    route = ospf6_route_best_next(route)) {
+                       if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX)) {
+                               prefix2str(&route->prefix, buf, sizeof(buf));
+                               zlog_debug("    include %s", buf);
+                       }
+                       ospf6_route_add(ospf6_route_copy(route),
+                                       route_advertise);
+               }
+       }
+
+       if (route_advertise->count == 0) {
+               if (old) {
+                       ls_id = 0;
+                       ospf6_lsa_purge(old);
+                       /* find previous LSA */
+                       old_next = ospf6_lsdb_lookup(
+                               htons(OSPF6_LSTYPE_INTRA_PREFIX),
+                               htonl(++ls_id), oa->ospf6->router_id, oa->lsdb);
+
+                       while (old_next) {
+                               ospf6_lsa_purge(old_next);
+                               old_next = ospf6_lsdb_lookup(
+                                       htons(OSPF6_LSTYPE_INTRA_PREFIX),
+                                       htonl(++ls_id), oa->ospf6->router_id,
+                                       oa->lsdb);
+                       }
+               }
+               ospf6_route_table_delete(route_advertise);
+               return 0;
+       }
+
+       /* Neighbor change to FULL, if INTRA-AREA-PREFIX LSA
+        * has not change, Flush old LSA and Re-Originate INP,
+        * as ospf6_flood() checks if LSA is same as DB,
+        * it won't be updated to neighbor's DB.
+        */
+       if (oa->intra_prefix_originate) {
+               if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX))
+                       zlog_debug("%s: Re-originate intra prefix LSA, Current full nbrs %u",
+                                  __PRETTY_FUNCTION__, oa->full_nbrs);
+               if (old)
+                       ospf6_lsa_purge_multi_ls_id(oa, old);
+               oa->intra_prefix_originate = 0;
+       }
+
+       /* put prefixes to advertise */
+       prefix_num = 0;
+       op = (struct ospf6_prefix *)((caddr_t)intra_prefix_lsa
+                                    + sizeof(struct ospf6_intra_prefix_lsa));
+       for (route = ospf6_route_head(route_advertise); route;
+            route = ospf6_route_best_next(route)) {
+               if (((caddr_t)op - (caddr_t)lsa_header) > MAX_LSA_PAYLOAD) {
+
+                       intra_prefix_lsa->prefix_num = htons(prefix_num);
+
+                       /* Fill LSA Header */
+                       lsa_header->age = 0;
+                       lsa_header->type = htons(OSPF6_LSTYPE_INTRA_PREFIX);
+                       lsa_header->id = htonl(ls_id++);
+                       lsa_header->adv_router = oa->ospf6->router_id;
+                       lsa_header->seqnum = ospf6_new_ls_seqnum(
+                               lsa_header->type, lsa_header->id,
+                               lsa_header->adv_router, oa->lsdb);
+                       lsa_header->length =
+                               htons((caddr_t)op - (caddr_t)lsa_header);
+
+                       /* LSA checksum */
+                       ospf6_lsa_checksum(lsa_header);
+
+                       /* Create LSA */
+                       lsa = ospf6_lsa_create(lsa_header);
+
+                       /* Originate */
+                       ospf6_lsa_originate_area(lsa, oa);
+
+                       /* Prepare next buffer */
+                       memset(buffer, 0, sizeof(buffer));
+                       lsa_header = (struct ospf6_lsa_header *)buffer;
+                       intra_prefix_lsa =
+                               (struct ospf6_intra_prefix_lsa
+                                        *)((caddr_t)lsa_header
+                                           + sizeof(struct ospf6_lsa_header));
+
+                       /* Fill Intra-Area-Prefix-LSA */
+                       intra_prefix_lsa->ref_type = htons(OSPF6_LSTYPE_ROUTER);
+                       intra_prefix_lsa->ref_id = htonl(0);
+                       intra_prefix_lsa->ref_adv_router = oa->ospf6->router_id;
+
+                       /* Put next set of prefixes to advertise */
+                       prefix_num = 0;
+                       op = (struct ospf6_prefix
+                                     *)((caddr_t)intra_prefix_lsa
+                                        + sizeof(struct
+                                                 ospf6_intra_prefix_lsa));
+               }
+
+               op->prefix_length = route->prefix.prefixlen;
+               op->prefix_options = route->path.prefix_options;
+               op->prefix_metric = htons(route->path.cost);
+               memcpy(OSPF6_PREFIX_BODY(op), &route->prefix.u.prefix6,
+                      OSPF6_PREFIX_SPACE(op->prefix_length));
+               prefix_num++;
+
+               op = OSPF6_PREFIX_NEXT(op);
+       }
+
+       ospf6_route_table_delete(route_advertise);
+
+       if (prefix_num == 0) {
+               if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX))
+                       zlog_debug(
+                               "Quit to Advertise Intra-Prefix: no route to advertise");
+               return 0;
+       }
+
+       intra_prefix_lsa->prefix_num = htons(prefix_num);
+
+       /* Fill LSA Header */
+       lsa_header->age = 0;
+       lsa_header->type = htons(OSPF6_LSTYPE_INTRA_PREFIX);
+       lsa_header->id = htonl(ls_id++);
+       lsa_header->adv_router = oa->ospf6->router_id;
+       lsa_header->seqnum =
+               ospf6_new_ls_seqnum(lsa_header->type, lsa_header->id,
+                                   lsa_header->adv_router, oa->lsdb);
+       lsa_header->length = htons((caddr_t)op - (caddr_t)lsa_header);
+
+       /* LSA checksum */
+       ospf6_lsa_checksum(lsa_header);
+
+       /* create LSA */
+       lsa = ospf6_lsa_create(lsa_header);
+
+       /* Originate */
+       ospf6_lsa_originate_area(lsa, oa);
+
+       return 0;
 }
 
 
-int
-ospf6_intra_prefix_lsa_originate_transit (struct thread *thread)
+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;
-
-  struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
-  struct ospf6_neighbor *on;
-  struct ospf6_route *route;
-  struct ospf6_prefix *op;
-  struct listnode *i;
-  int full_count = 0;
-  unsigned short prefix_num = 0;
-  struct ospf6_route_table *route_advertise;
-  struct ospf6_link_lsa *link_lsa;
-  char *start, *end, *current;
-  u_int16_t type;
-  char buf[PREFIX2STR_BUFFER];
-
-  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),
-                           htonl (oi->interface->ifindex),
-                           oi->area->ospf6->router_id, oi->area->lsdb);
-
-  if (CHECK_FLAG (oi->flag, OSPF6_INTERFACE_DISABLE))
-    {
-      if (old)
-        ospf6_lsa_purge (old);
-      return 0;
-    }
-
-  if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
-    zlog_debug ("Originate Intra-Area-Prefix-LSA for interface %s's prefix",
-               oi->interface->name);
-
-  /* prepare buffer */
-  memset (buffer, 0, sizeof (buffer));
-  lsa_header = (struct ospf6_lsa_header *) buffer;
-  intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *)
-    ((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header));
-
-  /* Fill Intra-Area-Prefix-LSA */
-  intra_prefix_lsa->ref_type = htons (OSPF6_LSTYPE_NETWORK);
-  intra_prefix_lsa->ref_id = htonl (oi->interface->ifindex);
-  intra_prefix_lsa->ref_adv_router = oi->area->ospf6->router_id;
-
-  if (oi->state != OSPF6_INTERFACE_DR)
-    {
-      if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
-        zlog_debug ("  Interface is not DR");
-      if (old)
-        ospf6_lsa_purge (old);
-      return 0;
-    }
-
-  full_count = 0;
-  for (ALL_LIST_ELEMENTS_RO (oi->neighbor_list, i, on))
-    if (on->state == OSPF6_NEIGHBOR_FULL)
-      full_count++;
-
-  if (full_count == 0)
-    {
-      if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
-        zlog_debug ("  Interface is stub");
-      if (old)
-        ospf6_lsa_purge (old);
-      return 0;
-    }
-
-  /* connected prefix to advertise */
-  route_advertise = ospf6_route_table_create (0, 0);
-
-  type = ntohs (OSPF6_LSTYPE_LINK);
-  for (lsa = ospf6_lsdb_type_head (type, oi->lsdb); lsa;
-       lsa = ospf6_lsdb_type_next (type, lsa))
-    {
-      if (OSPF6_LSA_IS_MAXAGE (lsa))
-        continue;
-
-      if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
-        zlog_debug ("  include prefix from %s", lsa->name);
-
-      if (lsa->header->adv_router != oi->area->ospf6->router_id)
-        {
-          on = ospf6_neighbor_lookup (lsa->header->adv_router, oi);
-          if (on == NULL || on->state != OSPF6_NEIGHBOR_FULL)
-            {
-              if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
-                zlog_debug ("    Neighbor not found or not Full, ignore");
-              continue;
-            }
-        }
-
-      link_lsa = (struct ospf6_link_lsa *)
-        ((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header));
-
-      prefix_num = (unsigned short) ntohl (link_lsa->prefix_num);
-      start = (char *) link_lsa + sizeof (struct ospf6_link_lsa);
-      end = (char *) lsa->header + ntohs (lsa->header->length); 
-      for (current = start; current < end && prefix_num;
-           current += OSPF6_PREFIX_SIZE (op))
-        {
-          op = (struct ospf6_prefix *) current;
-          if (op->prefix_length == 0 ||
-              current + OSPF6_PREFIX_SIZE (op) > end)
-            break;
-
-          route = ospf6_route_create ();
-
-          route->type = OSPF6_DEST_TYPE_NETWORK;
-          route->prefix.family = AF_INET6;
-          route->prefix.prefixlen = op->prefix_length;
-          memset (&route->prefix.u.prefix6, 0, sizeof (struct in6_addr));
-          memcpy (&route->prefix.u.prefix6, OSPF6_PREFIX_BODY (op),
-                  OSPF6_PREFIX_SPACE (op->prefix_length));
-
-          route->path.origin.type = lsa->header->type;
-          route->path.origin.id = lsa->header->id;
-          route->path.origin.adv_router = lsa->header->adv_router;
-          route->path.options[0] = link_lsa->options[0];
-          route->path.options[1] = link_lsa->options[1];
-          route->path.options[2] = link_lsa->options[2];
-          route->path.prefix_options = op->prefix_options;
-          route->path.area_id = oi->area->area_id;
-          route->path.type = OSPF6_PATH_TYPE_INTRA;
-
-          if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
-            {
-              prefix2str (&route->prefix, buf, sizeof (buf));
-              zlog_debug ("    include %s", buf);
-            }
-
-          ospf6_route_add (route, route_advertise);
-          prefix_num--;
-        }
-      if (current != end && IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
-        zlog_debug ("Trailing garbage in %s", lsa->name);
-    }
-
-  op = (struct ospf6_prefix *)
-    ((caddr_t) intra_prefix_lsa + sizeof (struct ospf6_intra_prefix_lsa));
-
-  prefix_num = 0;
-  for (route = ospf6_route_head (route_advertise); route;
-       route = ospf6_route_best_next (route))
-    {
-      op->prefix_length = route->prefix.prefixlen;
-      op->prefix_options = route->path.prefix_options;
-      op->prefix_metric = htons (0);
-      memcpy (OSPF6_PREFIX_BODY (op), &route->prefix.u.prefix6,
-              OSPF6_PREFIX_SPACE (op->prefix_length));
-      op = OSPF6_PREFIX_NEXT (op);
-      prefix_num++;
-    }
-
-  ospf6_route_table_delete (route_advertise);
-
-  if (prefix_num == 0)
-    {
-      if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
-        zlog_debug ("Quit to Advertise Intra-Prefix: no route to advertise");
-      return 0;
-    }
-
-  intra_prefix_lsa->prefix_num = htons (prefix_num);
-
-  /* Fill LSA Header */
-  lsa_header->age = 0;
-  lsa_header->type = htons (OSPF6_LSTYPE_INTRA_PREFIX);
-  lsa_header->id = htonl (oi->interface->ifindex);
-  lsa_header->adv_router = oi->area->ospf6->router_id;
-  lsa_header->seqnum =
-    ospf6_new_ls_seqnum (lsa_header->type, lsa_header->id,
-                         lsa_header->adv_router, oi->area->lsdb);
-  lsa_header->length = htons ((caddr_t) op - (caddr_t) lsa_header);
-
-  /* LSA checksum */
-  ospf6_lsa_checksum (lsa_header);
-
-  /* create LSA */
-  lsa = ospf6_lsa_create (lsa_header);
-
-  /* Originate */
-  ospf6_lsa_originate_area (lsa, oi->area);
-
-  return 0;
+       struct ospf6_interface *oi;
+
+       char buffer[OSPF6_MAX_LSASIZE];
+       struct ospf6_lsa_header *lsa_header;
+       struct ospf6_lsa *old, *lsa;
+
+       struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
+       struct ospf6_neighbor *on;
+       struct ospf6_route *route;
+       struct ospf6_prefix *op;
+       struct listnode *i;
+       int full_count = 0;
+       unsigned short prefix_num = 0;
+       struct ospf6_route_table *route_advertise;
+       struct ospf6_link_lsa *link_lsa;
+       char *start, *end, *current;
+       uint16_t type;
+       char buf[PREFIX2STR_BUFFER];
+
+       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),
+                               htonl(oi->interface->ifindex),
+                               oi->area->ospf6->router_id, oi->area->lsdb);
+
+       if (CHECK_FLAG(oi->flag, OSPF6_INTERFACE_DISABLE)) {
+               if (old)
+                       ospf6_lsa_purge(old);
+               return 0;
+       }
+
+       if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX))
+               zlog_debug(
+                       "Originate Intra-Area-Prefix-LSA for interface %s's prefix",
+                       oi->interface->name);
+
+       /* prepare buffer */
+       memset(buffer, 0, sizeof(buffer));
+       lsa_header = (struct ospf6_lsa_header *)buffer;
+       intra_prefix_lsa = (struct ospf6_intra_prefix_lsa
+                                   *)((caddr_t)lsa_header
+                                      + sizeof(struct ospf6_lsa_header));
+
+       /* Fill Intra-Area-Prefix-LSA */
+       intra_prefix_lsa->ref_type = htons(OSPF6_LSTYPE_NETWORK);
+       intra_prefix_lsa->ref_id = htonl(oi->interface->ifindex);
+       intra_prefix_lsa->ref_adv_router = oi->area->ospf6->router_id;
+
+       if (oi->state != OSPF6_INTERFACE_DR) {
+               if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX))
+                       zlog_debug("  Interface is not DR");
+               if (old)
+                       ospf6_lsa_purge(old);
+               return 0;
+       }
+
+       full_count = 0;
+       for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, i, on))
+               if (on->state == OSPF6_NEIGHBOR_FULL)
+                       full_count++;
+
+       if (full_count == 0) {
+               if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX))
+                       zlog_debug("  Interface is stub");
+               if (old)
+                       ospf6_lsa_purge(old);
+               return 0;
+       }
+
+       /* connected prefix to advertise */
+       route_advertise = ospf6_route_table_create(0, 0);
+
+       type = ntohs(OSPF6_LSTYPE_LINK);
+       for (ALL_LSDB_TYPED(oi->lsdb, type, lsa)) {
+               if (OSPF6_LSA_IS_MAXAGE(lsa))
+                       continue;
+
+               if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX))
+                       zlog_debug("  include prefix from %s", lsa->name);
+
+               if (lsa->header->adv_router != oi->area->ospf6->router_id) {
+                       on = ospf6_neighbor_lookup(lsa->header->adv_router, oi);
+                       if (on == NULL || on->state != OSPF6_NEIGHBOR_FULL) {
+                               if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX))
+                                       zlog_debug(
+                                               "    Neighbor not found or not Full, ignore");
+                               continue;
+                       }
+               }
+
+               link_lsa = (struct ospf6_link_lsa
+                                   *)((caddr_t)lsa->header
+                                      + sizeof(struct ospf6_lsa_header));
+
+               prefix_num = (unsigned short)ntohl(link_lsa->prefix_num);
+               start = (char *)link_lsa + sizeof(struct ospf6_link_lsa);
+               end = (char *)lsa->header + ntohs(lsa->header->length);
+               for (current = start; current < end && prefix_num;
+                    current += OSPF6_PREFIX_SIZE(op)) {
+                       op = (struct ospf6_prefix *)current;
+                       if (op->prefix_length == 0
+                           || current + OSPF6_PREFIX_SIZE(op) > end)
+                               break;
+
+                       route = ospf6_route_create();
+
+                       route->type = OSPF6_DEST_TYPE_NETWORK;
+                       route->prefix.family = AF_INET6;
+                       route->prefix.prefixlen = op->prefix_length;
+                       memset(&route->prefix.u.prefix6, 0,
+                              sizeof(struct in6_addr));
+                       memcpy(&route->prefix.u.prefix6, OSPF6_PREFIX_BODY(op),
+                              OSPF6_PREFIX_SPACE(op->prefix_length));
+
+                       route->path.origin.type = lsa->header->type;
+                       route->path.origin.id = lsa->header->id;
+                       route->path.origin.adv_router = lsa->header->adv_router;
+                       route->path.options[0] = link_lsa->options[0];
+                       route->path.options[1] = link_lsa->options[1];
+                       route->path.options[2] = link_lsa->options[2];
+                       route->path.prefix_options = op->prefix_options;
+                       route->path.area_id = oi->area->area_id;
+                       route->path.type = OSPF6_PATH_TYPE_INTRA;
+
+                       if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX)) {
+                               prefix2str(&route->prefix, buf, sizeof(buf));
+                               zlog_debug("    include %s", buf);
+                       }
+
+                       ospf6_route_add(route, route_advertise);
+                       prefix_num--;
+               }
+               if (current != end && IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX))
+                       zlog_debug("Trailing garbage in %s", lsa->name);
+       }
+
+       op = (struct ospf6_prefix *)((caddr_t)intra_prefix_lsa
+                                    + sizeof(struct ospf6_intra_prefix_lsa));
+
+       prefix_num = 0;
+       for (route = ospf6_route_head(route_advertise); route;
+            route = ospf6_route_best_next(route)) {
+               op->prefix_length = route->prefix.prefixlen;
+               op->prefix_options = route->path.prefix_options;
+               op->prefix_metric = htons(0);
+               memcpy(OSPF6_PREFIX_BODY(op), &route->prefix.u.prefix6,
+                      OSPF6_PREFIX_SPACE(op->prefix_length));
+               op = OSPF6_PREFIX_NEXT(op);
+               prefix_num++;
+       }
+
+       ospf6_route_table_delete(route_advertise);
+
+       if (prefix_num == 0) {
+               if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX))
+                       zlog_debug(
+                               "Quit to Advertise Intra-Prefix: no route to advertise");
+               return 0;
+       }
+
+       intra_prefix_lsa->prefix_num = htons(prefix_num);
+
+       /* Fill LSA Header */
+       lsa_header->age = 0;
+       lsa_header->type = htons(OSPF6_LSTYPE_INTRA_PREFIX);
+       lsa_header->id = htonl(oi->interface->ifindex);
+       lsa_header->adv_router = oi->area->ospf6->router_id;
+       lsa_header->seqnum =
+               ospf6_new_ls_seqnum(lsa_header->type, lsa_header->id,
+                                   lsa_header->adv_router, oi->area->lsdb);
+       lsa_header->length = htons((caddr_t)op - (caddr_t)lsa_header);
+
+       /* LSA checksum */
+       ospf6_lsa_checksum(lsa_header);
+
+       /* create LSA */
+       lsa = ospf6_lsa_create(lsa_header);
+
+       /* Originate */
+       ospf6_lsa_originate_area(lsa, oi->area);
+
+       return 0;
 }
 
-void
-ospf6_intra_prefix_lsa_add (struct ospf6_lsa *lsa)
+static void ospf6_intra_prefix_update_route_origin(struct ospf6_route *oa_route)
 {
-  struct ospf6_area *oa;
-  struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
-  struct prefix ls_prefix;
-  struct ospf6_route *route, *ls_entry;
-  int prefix_num;
-  struct ospf6_prefix *op;
-  char *start, *current, *end;
-  char buf[PREFIX2STR_BUFFER];
-  struct interface *ifp;
-  int direct_connect = 0;
-
-  if (OSPF6_LSA_IS_MAXAGE (lsa))
-    return;
-
-  if (IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
-    zlog_debug ("%s found", lsa->name);
-
-  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))
-    ospf6_linkstate_prefix (intra_prefix_lsa->ref_adv_router,
-                            htonl (0), &ls_prefix);
-  else if (intra_prefix_lsa->ref_type == htons (OSPF6_LSTYPE_NETWORK))
-    ospf6_linkstate_prefix (intra_prefix_lsa->ref_adv_router,
-                            intra_prefix_lsa->ref_id, &ls_prefix);
-  else
-    {
-      if (IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
-        zlog_debug ("Unknown reference LS-type: %#hx",
-                   ntohs (intra_prefix_lsa->ref_type));
-      return;
-    }
-
-  ls_entry = ospf6_route_lookup (&ls_prefix, oa->spf_table);
-  if (ls_entry == NULL)
-    {
-      if (IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
-        {
-          ospf6_linkstate_prefix2str (&ls_prefix, buf, sizeof (buf));
-          zlog_debug ("LS entry does not exist: %s", buf);
-        }
-      return;
-    }
-
-  if (intra_prefix_lsa->ref_adv_router == oa->ospf6->router_id)
-    {
-      /* the intra-prefix are directly connected */
-      direct_connect = 1;
-    }
-
-  prefix_num = ntohs (intra_prefix_lsa->prefix_num);
-  start = (caddr_t) intra_prefix_lsa +
-          sizeof (struct ospf6_intra_prefix_lsa);
-  end = OSPF6_LSA_END (lsa->header);
-  for (current = start; current < end; current += OSPF6_PREFIX_SIZE (op))
-    {
-      op = (struct ospf6_prefix *) current;
-      if (prefix_num == 0)
-        break;
-      if (end < current + OSPF6_PREFIX_SIZE (op))
-        break;
-
-      /* Appendix A.4.1.1 */
-      if (CHECK_FLAG(op->prefix_options, OSPF6_PREFIX_OPTION_NU))
-       {
-         if (IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
-           {
-             ospf6_linkstate_prefix2str ((struct prefix *)OSPF6_PREFIX_BODY(op),
-                                         buf, sizeof (buf));
-             zlog_debug ("%s: Skipping Prefix %s has NU option set",
-                         __func__, buf);
-           }
-         continue;
+       struct ospf6_path *h_path;
+       struct ospf6_route *g_route, *nroute;
+
+       /* Update Global ospf6 route path */
+       g_route = ospf6_route_lookup(&oa_route->prefix,
+                                    ospf6->route_table);
+
+       for (ospf6_route_lock(g_route); g_route &&
+            ospf6_route_is_prefix(&oa_route->prefix, g_route);
+            g_route = nroute) {
+               nroute = ospf6_route_next(g_route);
+               if (g_route->type != oa_route->type)
+                       continue;
+               if (g_route->path.area_id != oa_route->path.area_id)
+                       continue;
+               if (g_route->path.type != OSPF6_PATH_TYPE_INTRA)
+                       continue;
+               if (g_route->path.cost != oa_route->path.cost)
+                       continue;
+
+               if (ospf6_route_is_same_origin(g_route, oa_route)) {
+                       h_path = (struct ospf6_path *)listgetdata(
+                               listhead(g_route->paths));
+                       g_route->path.origin.type = h_path->origin.type;
+                       g_route->path.origin.id = h_path->origin.id;
+                       g_route->path.origin.adv_router =
+                               h_path->origin.adv_router;
+                       break;
+               }
        }
 
-      route = ospf6_route_create ();
-
-      memset (&route->prefix, 0, sizeof (struct prefix));
-      route->prefix.family = AF_INET6;
-      route->prefix.prefixlen = op->prefix_length;
-      ospf6_prefix_in6_addr (&route->prefix.u.prefix6, op);
-
-      route->type = OSPF6_DEST_TYPE_NETWORK;
-      route->path.origin.type = lsa->header->type;
-      route->path.origin.id = lsa->header->id;
-      route->path.origin.adv_router = lsa->header->adv_router;
-      route->path.prefix_options = op->prefix_options;
-      route->path.area_id = oa->area_id;
-      route->path.type = OSPF6_PATH_TYPE_INTRA;
-      route->path.metric_type = 1;
-      route->path.cost = ls_entry->path.cost +
-                         ntohs (op->prefix_metric);
-
-      if (direct_connect)
-        {
-          ifp = if_lookup_prefix(&route->prefix, VRF_DEFAULT);
-          if (ifp)
-           ospf6_route_add_nexthop (route, ifp->ifindex, NULL);
-        }
-      else
-        {
-         ospf6_route_copy_nexthops (route, ls_entry);
-        }
-
-      if (IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
-        {
-          prefix2str (&route->prefix, buf, sizeof (buf));
-          zlog_debug ("  add %s", buf);
-        }
-
-      ospf6_route_add (route, oa->route_table);
-      prefix_num--;
-    }
-
-  if (current != end && IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
-    zlog_debug ("Trailing garbage ignored");
+       h_path = (struct ospf6_path *)listgetdata(
+                               listhead(oa_route->paths));
+       oa_route->path.origin.type = h_path->origin.type;
+       oa_route->path.origin.id = h_path->origin.id;
+       oa_route->path.origin.adv_router = h_path->origin.adv_router;
 }
 
-void
-ospf6_intra_prefix_lsa_remove (struct ospf6_lsa *lsa)
+void ospf6_intra_prefix_route_ecmp_path(struct ospf6_area *oa,
+                                       struct ospf6_route *old,
+                                       struct ospf6_route *route)
 {
-  struct ospf6_area *oa;
-  struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
-  struct prefix prefix;
-  struct ospf6_route *route, *nroute;
-  int prefix_num;
-  struct ospf6_prefix *op;
-  char *start, *current, *end;
-  char buf[PREFIX2STR_BUFFER];
-
-  if (IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
-    zlog_debug ("%s disappearing", lsa->name);
-
-  oa = OSPF6_AREA (lsa->lsdb->data);
-
-  intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *)
-    OSPF6_LSA_HEADER_END (lsa->header);
-
-  prefix_num = ntohs (intra_prefix_lsa->prefix_num);
-  start = (caddr_t) intra_prefix_lsa +
-          sizeof (struct ospf6_intra_prefix_lsa);
-  end = OSPF6_LSA_END (lsa->header);
-  for (current = start; current < end; current += OSPF6_PREFIX_SIZE (op))
-    {
-      op = (struct ospf6_prefix *) current;
-      if (prefix_num == 0)
-        break;
-      if (end < current + OSPF6_PREFIX_SIZE (op))
-        break;
-      prefix_num--;
-
-      memset (&prefix, 0, sizeof (struct prefix));
-      prefix.family = AF_INET6;
-      prefix.prefixlen = op->prefix_length;
-      ospf6_prefix_in6_addr (&prefix.u.prefix6, op);
-
-      route = ospf6_route_lookup (&prefix, oa->route_table);
-      if (route == NULL)
-        continue;
-
-      for (ospf6_route_lock (route);
-           route && ospf6_route_is_prefix (&prefix, route);
-           route = nroute)
-        {
-          nroute = ospf6_route_next (route);
-          if (route->type != OSPF6_DEST_TYPE_NETWORK)
-            continue;
-          if (route->path.area_id != oa->area_id)
-            continue;
-          if (route->path.type != OSPF6_PATH_TYPE_INTRA)
-            continue;
-          if (route->path.origin.type != lsa->header->type ||
-              route->path.origin.id != lsa->header->id ||
-              route->path.origin.adv_router != lsa->header->adv_router)
-            continue;
-
-          if (IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
-            {
-              prefix2str (&route->prefix, buf, sizeof (buf));
-              zlog_debug ("remove %s", buf);
-            }
-          ospf6_route_remove (route, oa->route_table);
-        }
-      if (route)
-       ospf6_route_unlock (route);
-    }
-
-  if (current != end && IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
-    zlog_debug ("Trailing garbage ignored");
+       struct ospf6_route *old_route, *ls_entry;
+       struct ospf6_path *ecmp_path, *o_path = NULL;
+       struct listnode *anode, *anext;
+       struct listnode *nnode, *rnode, *rnext;
+       struct ospf6_nexthop *nh, *rnh;
+       char buf[PREFIX2STR_BUFFER];
+       bool route_found = false;
+       struct interface *ifp;
+       struct ospf6_lsa *lsa;
+       struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
+
+       /* check for old entry match with new route origin,
+        * delete old entry.
+        */
+       for (old_route = old; old_route; old_route = old_route->next) {
+               bool route_updated = false;
+
+               if (!ospf6_route_is_same(old_route, route) ||
+                       (old_route->path.type != route->path.type))
+                       continue;
+
+               /* Current and New route has same origin,
+                * delete old entry.
+                */
+               for (ALL_LIST_ELEMENTS(old_route->paths, anode, anext,
+                                                 o_path)) {
+                       /* Check old route path and route has same
+                        * origin.
+                        */
+                       if (o_path->area_id != route->path.area_id ||
+                           (memcmp(&(o_path)->origin, &(route)->path.origin,
+                                  sizeof(struct ospf6_ls_origin)) != 0))
+                               continue;
+
+                       /* Cost is not same then delete current path */
+                       if (o_path->cost == route->path.cost)
+                               continue;
+
+                       if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX)) {
+                               prefix2str(&old_route->prefix, buf,
+                                          sizeof(buf));
+                               zlog_debug("%s: route %s cost old %u new %u is not same, replace route",
+                                          __PRETTY_FUNCTION__, buf,
+                                          o_path->cost, route->path.cost);
+                       }
+
+                       /* Remove selected current path's nh from
+                        * effective nh list.
+                        */
+                       for (ALL_LIST_ELEMENTS_RO(o_path->nh_list, nnode, nh)) {
+                               for (ALL_LIST_ELEMENTS(old_route->nh_list,
+                                                       rnode, rnext, rnh)) {
+                                       if (!ospf6_nexthop_is_same(rnh, nh))
+                                               continue;
+                                       listnode_delete(old_route->nh_list,
+                                                               rnh);
+                                       ospf6_nexthop_delete(rnh);
+                                       route_updated = true;
+                               }
+                       }
+
+                       listnode_delete(old_route->paths, o_path);
+                       ospf6_path_free(o_path);
+
+                       /* Current route's path (adv_router info) is similar
+                        * to route being added.
+                        * Replace current route's path with paths list head.
+                        * Update FIB with effective NHs.
+                        */
+                       if (listcount(old_route->paths)) {
+                               if (route_updated) {
+                                       for (ALL_LIST_ELEMENTS(old_route->paths,
+                                                       anode, anext, o_path)) {
+                                               ospf6_merge_nexthops(
+                                                       old_route->nh_list,
+                                                       o_path->nh_list);
+                                       }
+                                       /* Update ospf6 route table and
+                                        * RIB/FIB with effective
+                                        * nh_list
+                                        */
+                                       if (oa->route_table->hook_add)
+                                               (*oa->route_table->hook_add)
+                                                       (old_route);
+
+                                       if (old_route->path.origin.id ==
+                                       route->path.origin.id &&
+                                       old_route->path.origin.adv_router ==
+                                               route->path.origin.adv_router) {
+                                               ospf6_intra_prefix_update_route_origin(
+                                                               old_route);
+                                       }
+                                       break;
+                               }
+                       } else {
+                               if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX)) {
+                                       prefix2str(&old_route->prefix, buf,
+                                                  sizeof(buf));
+                                       zlog_debug("%s: route %s old cost %u new cost %u, delete old entry.",
+                                                  __PRETTY_FUNCTION__, buf,
+                                                  old_route->path.cost,
+                                                  route->path.cost);
+                               }
+                               if (oa->route_table->hook_remove)
+                                       ospf6_route_remove(old_route,
+                                                  oa->route_table);
+                               else
+                                       SET_FLAG(old_route->flag,
+                                                OSPF6_ROUTE_REMOVE);
+                               break;
+                       }
+               }
+               if (route_updated)
+                       break;
+       }
+
+       for (old_route = old; old_route; old_route = old_route->next) {
+
+               if (!ospf6_route_is_same(old_route, route) ||
+                       (old_route->path.type != route->path.type))
+                       continue;
+
+               /* Old Route and New Route have Equal Cost, Merge NHs */
+               if (old_route->path.cost == route->path.cost) {
+                       route_found = true;
+
+                       /* check if this path exists already in
+                        * route->paths list, if so, replace nh_list.
+                        */
+                       for (ALL_LIST_ELEMENTS_RO(old_route->paths, anode,
+                                                 o_path)) {
+                               if (o_path->area_id == route->path.area_id &&
+                                   (memcmp(&(o_path)->origin,
+                                       &(route)->path.origin,
+                                       sizeof(struct ospf6_ls_origin)) == 0))
+                                       break;
+                       }
+                       /* If path is not found in old_route paths's list,
+                        * add a new path to route paths list and merge
+                        * nexthops in route->path->nh_list.
+                        * Otherwise replace existing path's nh_list.
+                        */
+                       if (o_path == NULL) {
+                               ecmp_path = ospf6_path_dup(&route->path);
+
+                               /* Add a nh_list to new ecmp path */
+                               ospf6_copy_nexthops(ecmp_path->nh_list,
+                                                   route->nh_list);
+                               /* Add the new path to route's path list */
+                               listnode_add_sort(old_route->paths, ecmp_path);
+
+                               if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX)) {
+                                       prefix2str(&route->prefix, buf,
+                                                  sizeof(buf));
+                                       zlog_debug(
+                                               "%s: route %s %p another path added with nh %u, effective paths %u nh %u",
+                                               __PRETTY_FUNCTION__, buf,
+                                               (void *)old_route,
+                                               listcount(ecmp_path->nh_list),
+                                               old_route->paths ?
+                                               listcount(old_route->paths) : 0,
+                                               listcount(old_route->nh_list));
+
+                               }
+                       } else {
+                               list_delete_all_node(o_path->nh_list);
+                               ospf6_copy_nexthops(o_path->nh_list,
+                                           route->nh_list);
+
+                       }
+
+                       list_delete_all_node(old_route->nh_list);
+
+                       for (ALL_LIST_ELEMENTS_RO(old_route->paths, anode,
+                                                 o_path)) {
+                               ls_entry = ospf6_route_lookup(
+                                                       &o_path->ls_prefix,
+                                                       oa->spf_table);
+                               if (ls_entry == NULL) {
+                                       if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX))
+                                               zlog_debug("%s: ls_prfix %s ls_entry not found.",
+                                                          __PRETTY_FUNCTION__,
+                                                          buf);
+                                       continue;
+                               }
+                               lsa = ospf6_lsdb_lookup(o_path->origin.type,
+                                               o_path->origin.id,
+                                               o_path->origin.adv_router,
+                                               oa->lsdb);
+                               if (lsa == NULL) {
+                                       if (IS_OSPF6_DEBUG_EXAMIN(
+                                                               INTRA_PREFIX)) {
+                                               struct prefix adv_prefix;
+
+                                               ospf6_linkstate_prefix(
+                                               o_path->origin.adv_router,
+                                               o_path->origin.id, &adv_prefix);
+                                               prefix2str(&adv_prefix, buf,
+                                                          sizeof(buf));
+                                               zlog_debug("%s: adv_router %s lsa not found",
+                                                          __PRETTY_FUNCTION__,
+                                                          buf);
+                                       }
+                                       continue;
+                               }
+                               intra_prefix_lsa =
+                                       (struct ospf6_intra_prefix_lsa *)
+                                       OSPF6_LSA_HEADER_END(lsa->header);
+
+                               if (intra_prefix_lsa->ref_adv_router
+                                    == oa->ospf6->router_id) {
+                                       ifp = if_lookup_prefix(
+                                                       &old_route->prefix,
+                                                       VRF_DEFAULT);
+                                       if (ifp)
+                                               ospf6_route_add_nexthop(
+                                                               old_route,
+                                                               ifp->ifindex,
+                                                               NULL);
+                               } else {
+                                       ospf6_route_merge_nexthops(old_route,
+                                                                  ls_entry);
+                               }
+                       }
+
+                       if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX)) {
+                               prefix2str(&route->prefix, buf, sizeof(buf));
+                               zlog_debug("%s: route %s %p with final effective paths %u nh%u",
+                                          __PRETTY_FUNCTION__, buf,
+                                          (void *)old_route,
+                                          old_route->paths ?
+                                          listcount(old_route->paths) : 0,
+                                          listcount(old_route->nh_list));
+                       }
+
+                       /* used in intra_route_calculation() to add to
+                        * global ospf6 route table.
+                        */
+                       UNSET_FLAG(old_route->flag, OSPF6_ROUTE_REMOVE);
+                       SET_FLAG(old_route->flag, OSPF6_ROUTE_ADD);
+                       /* Update ospf6 route table and RIB/FIB */
+                       if (oa->route_table->hook_add)
+                               (*oa->route_table->hook_add)(old_route);
+                       /* Delete the new route its info added to existing
+                        * route.
+                        */
+                       ospf6_route_delete(route);
+
+                       break;
+               }
+       }
+
+       if (!route_found) {
+               /* Add new route to existing node in ospf6 route table. */
+               ospf6_route_add(route, oa->route_table);
+       }
 }
 
-void
-ospf6_intra_route_calculation (struct ospf6_area *oa)
+void ospf6_intra_prefix_lsa_add(struct ospf6_lsa *lsa)
 {
-  struct ospf6_route *route, *nroute;
-  u_int16_t type;
-  struct ospf6_lsa *lsa;
-  void (*hook_add) (struct ospf6_route *) = NULL;
-  void (*hook_remove) (struct ospf6_route *) = NULL;
-
-  if (IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
-    zlog_debug ("Re-examin intra-routes for area %s", oa->name);
-
-  hook_add = oa->route_table->hook_add;
-  hook_remove = oa->route_table->hook_remove;
-  oa->route_table->hook_add = NULL;
-  oa->route_table->hook_remove = NULL;
-
-  for (route = ospf6_route_head (oa->route_table); route;
-       route = ospf6_route_next (route))
-    route->flag = OSPF6_ROUTE_REMOVE;
-
-  type = htons (OSPF6_LSTYPE_INTRA_PREFIX);
-  for (lsa = ospf6_lsdb_type_head (type, oa->lsdb); lsa;
-       lsa = ospf6_lsdb_type_next (type, lsa))
-    ospf6_intra_prefix_lsa_add (lsa);
-
-  oa->route_table->hook_add = hook_add;
-  oa->route_table->hook_remove = hook_remove;
-
-  for (route = ospf6_route_head (oa->route_table); route;
-       route = nroute)
-    {
-      nroute = ospf6_route_next (route);
-      if (CHECK_FLAG (route->flag, OSPF6_ROUTE_REMOVE) &&
-          CHECK_FLAG (route->flag, OSPF6_ROUTE_ADD))
-        {
-          UNSET_FLAG (route->flag, OSPF6_ROUTE_REMOVE);
-          UNSET_FLAG (route->flag, OSPF6_ROUTE_ADD);
-        }
-
-      if (CHECK_FLAG (route->flag, OSPF6_ROUTE_REMOVE))
-        ospf6_route_remove (route, oa->route_table);
-      else if (CHECK_FLAG (route->flag, OSPF6_ROUTE_ADD) ||
-               CHECK_FLAG (route->flag, OSPF6_ROUTE_CHANGE))
-        {
-          if (hook_add)
-            (*hook_add) (route);
-          route->flag = 0;
-        }
-      else
-       {
-         /* Redo the summaries as things might have changed */
-         ospf6_abr_originate_summary (route);
-         route->flag = 0;
+       struct ospf6_area *oa;
+       struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
+       struct prefix ls_prefix;
+       struct ospf6_route *route, *ls_entry, *old;
+       int prefix_num;
+       struct ospf6_prefix *op;
+       char *start, *current, *end;
+       char buf[PREFIX2STR_BUFFER];
+       struct interface *ifp;
+       int direct_connect = 0;
+       struct ospf6_path *path;
+
+       if (OSPF6_LSA_IS_MAXAGE(lsa))
+               return;
+
+       if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX))
+               zlog_debug("%s: LSA %s found", __PRETTY_FUNCTION__, lsa->name);
+
+       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))
+               ospf6_linkstate_prefix(intra_prefix_lsa->ref_adv_router,
+                                      intra_prefix_lsa->ref_id, &ls_prefix);
+       else if (intra_prefix_lsa->ref_type == htons(OSPF6_LSTYPE_NETWORK))
+               ospf6_linkstate_prefix(intra_prefix_lsa->ref_adv_router,
+                                      intra_prefix_lsa->ref_id, &ls_prefix);
+       else {
+               if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX))
+                       zlog_debug("Unknown reference LS-type: %#hx",
+                                  ntohs(intra_prefix_lsa->ref_type));
+               return;
        }
-    }
 
-  if (IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
-    zlog_debug ("Re-examin intra-routes for area %s: Done", oa->name);
+       ls_entry = ospf6_route_lookup(&ls_prefix, oa->spf_table);
+       if (ls_entry == NULL) {
+               if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX)) {
+                       ospf6_linkstate_prefix2str(&ls_prefix, buf,
+                                                  sizeof(buf));
+                       zlog_debug("LS entry does not exist: %s", buf);
+               }
+               return;
+       }
+
+       if (intra_prefix_lsa->ref_adv_router == oa->ospf6->router_id) {
+               /* the intra-prefix are directly connected */
+               direct_connect = 1;
+       }
+
+       prefix_num = ntohs(intra_prefix_lsa->prefix_num);
+       start = (caddr_t)intra_prefix_lsa
+               + sizeof(struct ospf6_intra_prefix_lsa);
+       end = OSPF6_LSA_END(lsa->header);
+       for (current = start; current < end; current += OSPF6_PREFIX_SIZE(op)) {
+               op = (struct ospf6_prefix *)current;
+               if (prefix_num == 0)
+                       break;
+               if (end < current + OSPF6_PREFIX_SIZE(op))
+                       break;
+
+               /* Appendix A.4.1.1 */
+               if (CHECK_FLAG(op->prefix_options, OSPF6_PREFIX_OPTION_NU)) {
+                       if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX)) {
+                               ospf6_linkstate_prefix2str(
+                                       (struct prefix *)OSPF6_PREFIX_BODY(op),
+                                       buf, sizeof(buf));
+                               zlog_debug(
+                                       "%s: Skipping Prefix %s has NU option set",
+                                       __func__, buf);
+                       }
+                       continue;
+               }
+
+               route = ospf6_route_create();
+
+               memset(&route->prefix, 0, sizeof(struct prefix));
+               route->prefix.family = AF_INET6;
+               route->prefix.prefixlen = op->prefix_length;
+               ospf6_prefix_in6_addr(&route->prefix.u.prefix6, op);
+
+               route->type = OSPF6_DEST_TYPE_NETWORK;
+               route->path.origin.type = lsa->header->type;
+               route->path.origin.id = lsa->header->id;
+               route->path.origin.adv_router = lsa->header->adv_router;
+               route->path.prefix_options = op->prefix_options;
+               route->path.area_id = oa->area_id;
+               route->path.type = OSPF6_PATH_TYPE_INTRA;
+               route->path.metric_type = 1;
+               route->path.cost =
+                       ls_entry->path.cost + ntohs(op->prefix_metric);
+               memcpy(&route->path.ls_prefix, &ls_prefix,
+                      sizeof(struct prefix));
+               if (direct_connect) {
+                       ifp = if_lookup_prefix(&route->prefix, VRF_DEFAULT);
+                       if (ifp)
+                               ospf6_route_add_nexthop(route, ifp->ifindex,
+                                                       NULL);
+               } else {
+                       ospf6_route_copy_nexthops(route, ls_entry);
+               }
+
+               path = ospf6_path_dup(&route->path);
+               ospf6_copy_nexthops(path->nh_list, route->path.nh_list);
+               listnode_add_sort(route->paths, path);
+
+               old = ospf6_route_lookup(&route->prefix, oa->route_table);
+               if (old && (ospf6_route_cmp(route, old) == 0)) {
+                       if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX)) {
+                               prefix2str(&route->prefix, buf, sizeof(buf));
+                               zlog_debug("%s Update route: %s old cost %u new cost %u paths %u nh %u",
+                                          __PRETTY_FUNCTION__, buf,
+                                          old->path.cost, route->path.cost,
+                                          listcount(route->paths),
+                                          listcount(route->nh_list));
+                       }
+                       ospf6_intra_prefix_route_ecmp_path(oa, old, route);
+               } else {
+                       if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX)) {
+                               prefix2str(&route->prefix, buf, sizeof(buf));
+                               zlog_debug("%s route %s add with cost %u paths %u nh %u",
+                                          __PRETTY_FUNCTION__, buf,
+                                          route->path.cost,
+                                          listcount(route->paths),
+                                          listcount(route->nh_list));
+                       }
+                       ospf6_route_add(route, oa->route_table);
+               }
+               prefix_num--;
+       }
+
+       if (current != end && IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX))
+               zlog_debug("Trailing garbage ignored");
 }
 
-static void
-ospf6_brouter_debug_print (struct ospf6_route *brouter)
+static void ospf6_intra_prefix_lsa_remove_update_route(struct ospf6_lsa *lsa,
+                                                 struct ospf6_area *oa,
+                                                 struct ospf6_route *route)
 {
-  u_int32_t brouter_id;
-  char brouter_name[16];
-  char area_name[16];
-  char destination[64];
-  char installed[16], changed[16];
-  struct timeval now, res;
-  char id[16], adv_router[16];
-  char capa[16], options[16];
-
-  brouter_id = ADV_ROUTER_IN_PREFIX (&brouter->prefix);
-  inet_ntop (AF_INET, &brouter_id, brouter_name, sizeof (brouter_name));
-  inet_ntop (AF_INET, &brouter->path.area_id, area_name, sizeof (area_name));
-  ospf6_linkstate_prefix2str (&brouter->prefix, destination,
-                              sizeof (destination));
-
-  monotime(&now);
-  timersub (&now, &brouter->installed, &res);
-  timerstring (&res, installed, sizeof (installed));
-
-  monotime(&now);
-  timersub (&now, &brouter->changed, &res);
-  timerstring (&res, changed, sizeof (changed));
-
-  inet_ntop (AF_INET, &brouter->path.origin.id, id, sizeof (id));
-  inet_ntop (AF_INET, &brouter->path.origin.adv_router, adv_router,
-             sizeof (adv_router));
-
-  ospf6_options_printbuf (brouter->path.options, options, sizeof (options));
-  ospf6_capability_printbuf (brouter->path.router_bits, capa, sizeof (capa));
-
-  zlog_info ("Brouter: %s via area %s", brouter_name, area_name);
-  zlog_info ("  memory: prev: %p this: %p next: %p parent rnode: %p",
-             (void *)brouter->prev, (void *)brouter, (void *)brouter->next,
-             (void *)brouter->rnode);
-  zlog_info ("  type: %d prefix: %s installed: %s changed: %s",
-             brouter->type, destination, installed, changed);
-  zlog_info ("  lock: %d flags: %s%s%s%s", brouter->lock,
-           (CHECK_FLAG (brouter->flag, OSPF6_ROUTE_BEST)   ? "B" : "-"),
-           (CHECK_FLAG (brouter->flag, OSPF6_ROUTE_ADD)    ? "A" : "-"),
-           (CHECK_FLAG (brouter->flag, OSPF6_ROUTE_REMOVE) ? "R" : "-"),
-           (CHECK_FLAG (brouter->flag, OSPF6_ROUTE_CHANGE) ? "C" : "-"));
-  zlog_info ("  path type: %s ls-origin %s id: %s adv-router %s",
-             OSPF6_PATH_TYPE_NAME (brouter->path.type),
-             ospf6_lstype_name (brouter->path.origin.type),
-             id, adv_router);
-  zlog_info ("  options: %s router-bits: %s metric-type: %d metric: %d/%d",
-             options, capa, brouter->path.metric_type,
-             brouter->path.cost, brouter->path.u.cost_e2);
+       struct listnode *anode, *anext;
+       struct listnode *nnode, *rnode, *rnext;
+       struct ospf6_nexthop *nh, *rnh;
+       struct ospf6_path *o_path;
+       bool nh_updated = false;
+       char buf[PREFIX2STR_BUFFER];
+
+       /* Iterate all paths of route to find maching
+        * with LSA remove info.
+        * If route->path is same, replace
+        * from paths list.
+        */
+       for (ALL_LIST_ELEMENTS(route->paths, anode, anext, o_path)) {
+               if ((o_path->origin.type != lsa->header->type) ||
+                   (o_path->origin.adv_router != lsa->header->adv_router) ||
+                   (o_path->origin.id != lsa->header->id))
+                       continue;
+
+               if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX)) {
+                       prefix2str(&route->prefix, buf, sizeof(buf));
+                       zlog_debug(
+                               "%s: route %s path found with cost %u nh %u to remove.",
+                               __PRETTY_FUNCTION__, buf, o_path->cost,
+                               listcount(o_path->nh_list));
+               }
+
+               /* Remove found path's nh_list from
+                * the route's nh_list.
+                */
+               for (ALL_LIST_ELEMENTS_RO(o_path->nh_list, nnode, nh)) {
+                       for (ALL_LIST_ELEMENTS(route->nh_list, rnode,
+                                              rnext, rnh)) {
+                               if (!ospf6_nexthop_is_same(rnh, nh))
+                                       continue;
+                               listnode_delete(route->nh_list, rnh);
+                               ospf6_nexthop_delete(rnh);
+                       }
+               }
+               /* Delete the path from route's
+                * path list
+                */
+               listnode_delete(route->paths, o_path);
+               ospf6_path_free(o_path);
+               nh_updated = true;
+               break;
+       }
+
+       if (nh_updated) {
+               /* Iterate all paths and merge nexthop,
+                * unlesss any of the nexthop similar to
+                * ones deleted as part of path deletion.
+                */
+               for (ALL_LIST_ELEMENTS(route->paths, anode, anext, o_path))
+                       ospf6_merge_nexthops(route->nh_list, o_path->nh_list);
+
+
+               if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX)) {
+                       prefix2str(&route->prefix, buf, sizeof(buf));
+                       zlog_debug("%s: route %s update paths %u nh %u",
+                                  __PRETTY_FUNCTION__, buf,
+                                  route->paths ? listcount(route->paths) : 0,
+                                  route->nh_list ? listcount(route->nh_list)
+                                  : 0);
+               }
+
+               /* Update Global Route table and
+                * RIB/FIB with effective
+                * nh_list
+                */
+               if (oa->route_table->hook_add)
+                       (*oa->route_table->hook_add)(route);
+
+               /* route's primary path is similar
+                * to LSA, replace route's primary
+                * path with route's paths list
+                * head.
+                */
+               if ((route->path.origin.id == lsa->header->id) &&
+                   (route->path.origin.adv_router ==
+                               lsa->header->adv_router)) {
+                       ospf6_intra_prefix_update_route_origin(route);
+               }
+       }
+
 }
 
-void
-ospf6_intra_brouter_calculation (struct ospf6_area *oa)
+void ospf6_intra_prefix_lsa_remove(struct ospf6_lsa *lsa)
 {
-  struct ospf6_route *brouter, *nbrouter, *copy;
-  void (*hook_add) (struct ospf6_route *) = NULL;
-  void (*hook_remove) (struct ospf6_route *) = NULL;
-  u_int32_t brouter_id;
-  char brouter_name[16];
-  
-  if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID (oa->area_id))
-    zlog_info ("border-router calculation for area %s", oa->name);
-  
-  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;
-
-  /* withdraw the previous router entries for the area */
-  for (brouter = ospf6_route_head (oa->ospf6->brouter_table); brouter;
-       brouter = ospf6_route_next (brouter))
-    {
-      brouter_id = ADV_ROUTER_IN_PREFIX (&brouter->prefix);
-      inet_ntop (AF_INET, &brouter_id, brouter_name, sizeof (brouter_name));
-      if (brouter->path.area_id != oa->area_id)
-        continue;
-      SET_FLAG (brouter->flag, OSPF6_ROUTE_REMOVE);
-
-      if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID (brouter_id) ||
-          IS_OSPF6_DEBUG_ROUTE (MEMORY))
-        {
-          zlog_info ("%p: mark as removing: area %s brouter %s",
-                     (void *)brouter, oa->name, brouter_name);
-          ospf6_brouter_debug_print (brouter);
-        }
-    }
-
-  for (brouter = ospf6_route_head (oa->spf_table); brouter;
-       brouter = ospf6_route_next (brouter))
-    {
-      brouter_id = ADV_ROUTER_IN_PREFIX (&brouter->prefix);
-      inet_ntop (AF_INET, &brouter_id, brouter_name, sizeof (brouter_name));
-
-      if (brouter->type != OSPF6_DEST_TYPE_LINKSTATE)
-        continue;
-      if (ospf6_linkstate_prefix_id (&brouter->prefix) != htonl (0))
-        continue;
-      if (! CHECK_FLAG (brouter->path.router_bits, OSPF6_ROUTER_BIT_E) &&
-          ! CHECK_FLAG (brouter->path.router_bits, OSPF6_ROUTER_BIT_B))
-        continue;
-
-      if (! OSPF6_OPT_ISSET (brouter->path.options, OSPF6_OPT_V6) ||
-         ! OSPF6_OPT_ISSET (brouter->path.options, OSPF6_OPT_R))
-       continue;
-
-      copy = ospf6_route_copy (brouter);
-      copy->type = OSPF6_DEST_TYPE_ROUTER;
-      copy->path.area_id = oa->area_id;
-      ospf6_route_add (copy, oa->ospf6->brouter_table);
-
-      if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID (brouter_id) ||
-          IS_OSPF6_DEBUG_ROUTE (MEMORY))
-        {
-          zlog_info ("%p: transfer: area %s brouter %s",
-                     (void *)brouter, oa->name, brouter_name);
-          ospf6_brouter_debug_print (brouter);
-        }
-    }
-
-  oa->ospf6->brouter_table->hook_add = hook_add;
-  oa->ospf6->brouter_table->hook_remove = hook_remove;
-
-  for (brouter = ospf6_route_head (oa->ospf6->brouter_table); brouter;
-       brouter = nbrouter)
-    {
-      nbrouter = ospf6_route_next (brouter);
-      brouter_id = ADV_ROUTER_IN_PREFIX (&brouter->prefix);
-      inet_ntop (AF_INET, &brouter_id, brouter_name, sizeof (brouter_name));
-      
-      if (brouter->path.area_id != oa->area_id)
-        continue;
-
-      if (CHECK_FLAG (brouter->flag, OSPF6_ROUTE_WAS_REMOVED))
-        continue;
-
-      if (CHECK_FLAG (brouter->flag, OSPF6_ROUTE_REMOVE) &&
-          CHECK_FLAG (brouter->flag, OSPF6_ROUTE_ADD))
-        {
-          UNSET_FLAG (brouter->flag, OSPF6_ROUTE_REMOVE);
-          UNSET_FLAG (brouter->flag, OSPF6_ROUTE_ADD);
-        }
-
-      if (CHECK_FLAG (brouter->flag, OSPF6_ROUTE_REMOVE))
-        {
-          if (IS_OSPF6_DEBUG_BROUTER ||
-              IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID (brouter_id) ||
-              IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID (oa->area_id))
-            zlog_info ("brouter %s disappears via area %s",
-                       brouter_name, oa->name);
-          ospf6_route_remove (brouter, oa->ospf6->brouter_table);
-          brouter = NULL;
-        }
-      else if (CHECK_FLAG (brouter->flag, OSPF6_ROUTE_ADD) ||
-               CHECK_FLAG (brouter->flag, OSPF6_ROUTE_CHANGE))
-        {
-          if (IS_OSPF6_DEBUG_BROUTER ||
-              IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID (brouter_id) ||
-              IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID (oa->area_id))
-            zlog_info ("brouter %s appears via area %s",
-                       brouter_name, oa->name);
-
-          /* newly added */
-          if (hook_add)
-            (*hook_add) (brouter);
-        }
-      else
-        {
-          if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID (brouter_id) ||
-              IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID (oa->area_id))
-            zlog_info ("brouter %s still exists via area %s",
-                       brouter_name, oa->name);
-          /* But re-originate summaries */
-         ospf6_abr_originate_summary (brouter);
-        }
-
-      if (brouter)
-        {
-          UNSET_FLAG (brouter->flag, OSPF6_ROUTE_ADD);
-          UNSET_FLAG (brouter->flag, OSPF6_ROUTE_CHANGE);
-        }
-    }
-
-  if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID (oa->area_id))
-    zlog_info ("border-router calculation for area %s: done", oa->name);
+       struct ospf6_area *oa;
+       struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
+       struct prefix prefix;
+       struct ospf6_route *route, *nroute;
+       int prefix_num;
+       struct ospf6_prefix *op;
+       char *start, *current, *end;
+       char buf[PREFIX2STR_BUFFER];
+
+       if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX))
+               zlog_debug("%s: %s disappearing", __PRETTY_FUNCTION__,
+                          lsa->name);
+
+       oa = OSPF6_AREA(lsa->lsdb->data);
+
+       intra_prefix_lsa =
+               (struct ospf6_intra_prefix_lsa *)OSPF6_LSA_HEADER_END(
+                       lsa->header);
+
+       prefix_num = ntohs(intra_prefix_lsa->prefix_num);
+       start = (caddr_t)intra_prefix_lsa
+               + sizeof(struct ospf6_intra_prefix_lsa);
+       end = OSPF6_LSA_END(lsa->header);
+       for (current = start; current < end; current += OSPF6_PREFIX_SIZE(op)) {
+               op = (struct ospf6_prefix *)current;
+               if (prefix_num == 0)
+                       break;
+               if (end < current + OSPF6_PREFIX_SIZE(op))
+                       break;
+               prefix_num--;
+
+               memset(&prefix, 0, sizeof(struct prefix));
+               prefix.family = AF_INET6;
+               prefix.prefixlen = op->prefix_length;
+               ospf6_prefix_in6_addr(&prefix.u.prefix6, op);
+
+               route = ospf6_route_lookup(&prefix, oa->route_table);
+               if (route == NULL)
+                       continue;
+
+               for (ospf6_route_lock(route);
+                    route && ospf6_route_is_prefix(&prefix, route);
+                    route = nroute) {
+                       nroute = ospf6_route_next(route);
+                       if (route->type != OSPF6_DEST_TYPE_NETWORK)
+                               continue;
+                       if (route->path.area_id != oa->area_id)
+                               continue;
+                       if (route->path.type != OSPF6_PATH_TYPE_INTRA)
+                               continue;
+                       /* Route has multiple ECMP paths, remove matching
+                        * path. Update current route's effective nh list
+                        * after removal of one of the path.
+                        */
+                       if (listcount(route->paths) > 1) {
+                               ospf6_intra_prefix_lsa_remove_update_route(
+                                                       lsa, oa, route);
+                       } else {
+
+                               if (route->path.origin.type != lsa->header->type
+                                   || route->path.origin.id != lsa->header->id
+                                   || route->path.origin.adv_router
+                                   != lsa->header->adv_router)
+                                       continue;
+
+                               if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX)) {
+                                       prefix2str(&route->prefix, buf,
+                                                  sizeof(buf));
+                                       zlog_debug("%s: route remove %s with path type %u cost %u paths %u nh %u",
+                                                  __PRETTY_FUNCTION__, buf,
+                                                  route->path.type,
+                                                  route->path.cost,
+                                                  listcount(route->paths),
+                                                  listcount(route->nh_list));
+                               }
+                               ospf6_route_remove(route, oa->route_table);
+                       }
+               }
+               if (route)
+                       ospf6_route_unlock(route);
+       }
+
+       if (current != end && IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX))
+               zlog_debug("Trailing garbage ignored");
 }
 
-struct ospf6_lsa_handler router_handler =
+void ospf6_intra_route_calculation(struct ospf6_area *oa)
 {
-  OSPF6_LSTYPE_ROUTER,
-  "Router",
-  "Rtr",
-  ospf6_router_lsa_show,
-  ospf6_router_lsa_get_nbr_id
-};
-
-struct ospf6_lsa_handler network_handler =
-{
-  OSPF6_LSTYPE_NETWORK,
-  "Network",
-  "Net",
-  ospf6_network_lsa_show,
-  ospf6_network_lsa_get_ar_id
-};
-
-struct ospf6_lsa_handler link_handler =
+       struct ospf6_route *route, *nroute;
+       uint16_t type;
+       struct ospf6_lsa *lsa;
+       void (*hook_add)(struct ospf6_route *) = NULL;
+       void (*hook_remove)(struct ospf6_route *) = NULL;
+
+       if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX))
+               zlog_debug("Re-examin intra-routes for area %s", oa->name);
+
+       hook_add = oa->route_table->hook_add;
+       hook_remove = oa->route_table->hook_remove;
+       oa->route_table->hook_add = NULL;
+       oa->route_table->hook_remove = NULL;
+
+       for (route = ospf6_route_head(oa->route_table); route;
+            route = ospf6_route_next(route))
+               route->flag = OSPF6_ROUTE_REMOVE;
+
+       type = htons(OSPF6_LSTYPE_INTRA_PREFIX);
+       for (ALL_LSDB_TYPED(oa->lsdb, type, lsa))
+               ospf6_intra_prefix_lsa_add(lsa);
+
+       oa->route_table->hook_add = hook_add;
+       oa->route_table->hook_remove = hook_remove;
+
+       for (route = ospf6_route_head(oa->route_table); route; route = nroute) {
+               nroute = ospf6_route_next(route);
+               if (CHECK_FLAG(route->flag, OSPF6_ROUTE_REMOVE)
+                   && CHECK_FLAG(route->flag, OSPF6_ROUTE_ADD)) {
+                       UNSET_FLAG(route->flag, OSPF6_ROUTE_REMOVE);
+                       UNSET_FLAG(route->flag, OSPF6_ROUTE_ADD);
+               }
+
+               if (CHECK_FLAG(route->flag, OSPF6_ROUTE_REMOVE))
+                       ospf6_route_remove(route, oa->route_table);
+               else if (CHECK_FLAG(route->flag, OSPF6_ROUTE_ADD)
+                        || CHECK_FLAG(route->flag, OSPF6_ROUTE_CHANGE)) {
+                       if (hook_add)
+                               (*hook_add)(route);
+                       route->flag = 0;
+               } else {
+                       /* Redo the summaries as things might have changed */
+                       ospf6_abr_originate_summary(route);
+                       route->flag = 0;
+               }
+       }
+
+       if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX))
+               zlog_debug("Re-examin intra-routes for area %s: Done",
+                          oa->name);
+}
+
+static void ospf6_brouter_debug_print(struct ospf6_route *brouter)
 {
-  OSPF6_LSTYPE_LINK,
-  "Link",
-  "Lnk",
-  ospf6_link_lsa_show,
-  ospf6_link_lsa_get_prefix_str
-};
-
-struct ospf6_lsa_handler intra_prefix_handler =
+       uint32_t brouter_id;
+       char brouter_name[16];
+       char area_name[16];
+       char destination[64];
+       char installed[64], changed[64];
+       struct timeval now, res;
+       char id[16], adv_router[16];
+       char capa[16], options[16];
+
+       brouter_id = ADV_ROUTER_IN_PREFIX(&brouter->prefix);
+       inet_ntop(AF_INET, &brouter_id, brouter_name, sizeof(brouter_name));
+       inet_ntop(AF_INET, &brouter->path.area_id, area_name,
+                 sizeof(area_name));
+       ospf6_linkstate_prefix2str(&brouter->prefix, destination,
+                                  sizeof(destination));
+
+       monotime(&now);
+       timersub(&now, &brouter->installed, &res);
+       timerstring(&res, installed, sizeof(installed));
+
+       monotime(&now);
+       timersub(&now, &brouter->changed, &res);
+       timerstring(&res, changed, sizeof(changed));
+
+       inet_ntop(AF_INET, &brouter->path.origin.id, id, sizeof(id));
+       inet_ntop(AF_INET, &brouter->path.origin.adv_router, adv_router,
+                 sizeof(adv_router));
+
+       ospf6_options_printbuf(brouter->path.options, options, sizeof(options));
+       ospf6_capability_printbuf(brouter->path.router_bits, capa,
+                                 sizeof(capa));
+
+       zlog_info("Brouter: %s via area %s", brouter_name, area_name);
+       zlog_info("  memory: prev: %p this: %p next: %p parent rnode: %p",
+                 (void *)brouter->prev, (void *)brouter, (void *)brouter->next,
+                 (void *)brouter->rnode);
+       zlog_info("  type: %d prefix: %s installed: %s changed: %s",
+                 brouter->type, destination, installed, changed);
+       zlog_info("  lock: %d flags: %s%s%s%s", brouter->lock,
+                 (CHECK_FLAG(brouter->flag, OSPF6_ROUTE_BEST) ? "B" : "-"),
+                 (CHECK_FLAG(brouter->flag, OSPF6_ROUTE_ADD) ? "A" : "-"),
+                 (CHECK_FLAG(brouter->flag, OSPF6_ROUTE_REMOVE) ? "R" : "-"),
+                 (CHECK_FLAG(brouter->flag, OSPF6_ROUTE_CHANGE) ? "C" : "-"));
+       zlog_info("  path type: %s ls-origin %s id: %s adv-router %s",
+                 OSPF6_PATH_TYPE_NAME(brouter->path.type),
+                 ospf6_lstype_name(brouter->path.origin.type), id, adv_router);
+       zlog_info("  options: %s router-bits: %s metric-type: %d metric: %d/%d",
+                 options, capa, brouter->path.metric_type, brouter->path.cost,
+                 brouter->path.u.cost_e2);
+}
+
+void ospf6_intra_brouter_calculation(struct ospf6_area *oa)
 {
-  OSPF6_LSTYPE_INTRA_PREFIX,
-  "Intra-Prefix",
-  "INP",
-  ospf6_intra_prefix_lsa_show,
-  ospf6_intra_prefix_lsa_get_prefix_str
-};
-
-void
-ospf6_intra_init (void)
+       struct ospf6_route *brouter, *nbrouter, *copy;
+       void (*hook_add)(struct ospf6_route *) = NULL;
+       void (*hook_remove)(struct ospf6_route *) = NULL;
+       uint32_t brouter_id;
+       char brouter_name[16];
+
+       if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID(oa->area_id) ||
+           IS_OSPF6_DEBUG_ROUTE(MEMORY))
+               zlog_info("%s: border-router calculation for area %s",
+                         __PRETTY_FUNCTION__, oa->name);
+
+       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;
+
+       /* withdraw the previous router entries for the area */
+       for (brouter = ospf6_route_head(oa->ospf6->brouter_table); brouter;
+            brouter = ospf6_route_next(brouter)) {
+               brouter_id = ADV_ROUTER_IN_PREFIX(&brouter->prefix);
+               inet_ntop(AF_INET, &brouter_id, brouter_name,
+                         sizeof(brouter_name));
+
+               if (brouter->path.area_id != oa->area_id)
+                       continue;
+
+               SET_FLAG(brouter->flag, OSPF6_ROUTE_REMOVE);
+
+               if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID(brouter_id)
+                   || IS_OSPF6_DEBUG_ROUTE(MEMORY)) {
+                       zlog_info("%p: mark as removing: area %s brouter %s",
+                                 (void *)brouter, oa->name, brouter_name);
+                       ospf6_brouter_debug_print(brouter);
+               }
+       }
+
+       for (brouter = ospf6_route_head(oa->spf_table); brouter;
+            brouter = ospf6_route_next(brouter)) {
+               brouter_id = ADV_ROUTER_IN_PREFIX(&brouter->prefix);
+               inet_ntop(AF_INET, &brouter_id, brouter_name,
+                         sizeof(brouter_name));
+
+               if (brouter->type != OSPF6_DEST_TYPE_LINKSTATE)
+                       continue;
+
+               if (ospf6_linkstate_prefix_id(&brouter->prefix) != htonl(0))
+                       continue;
+
+               if (!CHECK_FLAG(brouter->path.router_bits, OSPF6_ROUTER_BIT_E)
+                   && !CHECK_FLAG(brouter->path.router_bits,
+                                  OSPF6_ROUTER_BIT_B))
+                       continue;
+
+               if (!OSPF6_OPT_ISSET(brouter->path.options, OSPF6_OPT_V6)
+                   || !OSPF6_OPT_ISSET(brouter->path.options, OSPF6_OPT_R))
+                       continue;
+
+               copy = ospf6_route_copy(brouter);
+               copy->type = OSPF6_DEST_TYPE_ROUTER;
+               copy->path.area_id = oa->area_id;
+               ospf6_route_add(copy, oa->ospf6->brouter_table);
+
+               if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID(brouter_id)
+                   || IS_OSPF6_DEBUG_ROUTE(MEMORY)) {
+                       zlog_info("%p: transfer: area %s brouter %s",
+                                 (void *)brouter, oa->name, brouter_name);
+                       ospf6_brouter_debug_print(brouter);
+               }
+       }
+
+       oa->ospf6->brouter_table->hook_add = hook_add;
+       oa->ospf6->brouter_table->hook_remove = hook_remove;
+
+       for (brouter = ospf6_route_head(oa->ospf6->brouter_table); brouter;
+            brouter = nbrouter) {
+
+               /*
+                * brouter may have been "deleted" in the last loop iteration.
+                * If this is the case there is still 1 final refcount lock
+                * taken by ospf6_route_next, that will be released by the same
+                * call and result in deletion. To avoid heap UAF we must then
+                * skip processing the deleted route.
+                */
+               if (brouter->lock == 1) {
+                       if (IS_OSPF6_DEBUG_ROUTE(MEMORY))
+                               ospf6_brouter_debug_print(brouter);
+                       nbrouter = ospf6_route_next(brouter);
+                       continue;
+               } else {
+                       nbrouter = ospf6_route_next(brouter);
+               }
+
+               brouter_id = ADV_ROUTER_IN_PREFIX(&brouter->prefix);
+               inet_ntop(AF_INET, &brouter_id, brouter_name,
+                         sizeof(brouter_name));
+
+               if (brouter->path.area_id != oa->area_id)
+                       continue;
+
+               if (CHECK_FLAG(brouter->flag, OSPF6_ROUTE_WAS_REMOVED))
+                       continue;
+
+               /* After iterating spf_table for all routers including
+                * intra brouter, clear mark for remove flag for
+                * inter border router if its adv router present in
+                * SPF table.
+                */
+               if (brouter->path.type == OSPF6_PATH_TYPE_INTER) {
+                       struct prefix adv_prefix;
+
+                       ospf6_linkstate_prefix(brouter->path.origin.adv_router,
+                                              htonl(0), &adv_prefix);
+
+                       if (ospf6_route_lookup(&adv_prefix, oa->spf_table)) {
+                               if (IS_OSPF6_DEBUG_BROUTER) {
+                                       zlog_debug("%s: keep inter brouter %s as adv router 0x%x found in spf",
+                                                  __PRETTY_FUNCTION__,
+                                                  brouter_name,
+                                       brouter->path.origin.adv_router);
+                                       ospf6_brouter_debug_print(brouter);
+                               }
+                               UNSET_FLAG(brouter->flag, OSPF6_ROUTE_REMOVE);
+                       }
+               }
+
+               if (CHECK_FLAG(brouter->flag, OSPF6_ROUTE_REMOVE)
+                   && CHECK_FLAG(brouter->flag, OSPF6_ROUTE_ADD)) {
+                       UNSET_FLAG(brouter->flag, OSPF6_ROUTE_REMOVE);
+                       UNSET_FLAG(brouter->flag, OSPF6_ROUTE_ADD);
+               }
+
+               if (CHECK_FLAG(brouter->flag, OSPF6_ROUTE_REMOVE)) {
+                       if (IS_OSPF6_DEBUG_BROUTER
+                           || IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID(
+                                      brouter_id)
+                           || IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID(
+                                      oa->area_id))
+                               zlog_info("%s: brouter %s disappears via area %s",
+                                         __PRETTY_FUNCTION__, brouter_name,
+                                         oa->name);
+                       /* This is used to protect nbrouter from removed from
+                        * the table. For an example, ospf6_abr_examin_summary,
+                        * removes brouters which are marked for remove.
+                        */
+                       oa->intra_brouter_calc = 1;
+                       ospf6_route_remove(brouter, oa->ospf6->brouter_table);
+                       brouter = NULL;
+               } else if (CHECK_FLAG(brouter->flag, OSPF6_ROUTE_ADD)
+                          || CHECK_FLAG(brouter->flag, OSPF6_ROUTE_CHANGE)) {
+                       if (IS_OSPF6_DEBUG_BROUTER
+                           || IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID(
+                                      brouter_id)
+                           || IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID(
+                                      oa->area_id))
+                               zlog_info("%s: brouter %s appears via area %s",
+                                         __PRETTY_FUNCTION__, brouter_name,
+                                         oa->name);
+
+                       /* newly added */
+                       if (hook_add)
+                               (*hook_add)(brouter);
+               } else {
+                       if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID(
+                                   brouter_id)
+                           || IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID(
+                                      oa->area_id))
+                               zlog_info("brouter %s still exists via area %s",
+                                         brouter_name, oa->name);
+                       /* But re-originate summaries */
+                       ospf6_abr_originate_summary(brouter);
+               }
+
+               if (brouter) {
+                       UNSET_FLAG(brouter->flag, OSPF6_ROUTE_ADD);
+                       UNSET_FLAG(brouter->flag, OSPF6_ROUTE_CHANGE);
+               }
+               /* Reset for nbrouter */
+               oa->intra_brouter_calc = 0;
+       }
+
+       if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID(oa->area_id) ||
+           IS_OSPF6_DEBUG_ROUTE(MEMORY))
+               zlog_info("%s: border-router calculation for area %s: done",
+                         __PRETTY_FUNCTION__, oa->name);
+}
+
+struct ospf6_lsa_handler router_handler = {.lh_type = OSPF6_LSTYPE_ROUTER,
+                                          .lh_name = "Router",
+                                          .lh_short_name = "Rtr",
+                                          .lh_show = ospf6_router_lsa_show,
+                                          .lh_get_prefix_str =
+                                                  ospf6_router_lsa_get_nbr_id,
+                                          .lh_debug = 0};
+
+struct ospf6_lsa_handler network_handler = {.lh_type = OSPF6_LSTYPE_NETWORK,
+                                           .lh_name = "Network",
+                                           .lh_short_name = "Net",
+                                           .lh_show = ospf6_network_lsa_show,
+                                           .lh_get_prefix_str =
+                                                   ospf6_network_lsa_get_ar_id,
+                                           .lh_debug = 0};
+
+struct ospf6_lsa_handler link_handler = {.lh_type = OSPF6_LSTYPE_LINK,
+                                        .lh_name = "Link",
+                                        .lh_short_name = "Lnk",
+                                        .lh_show = ospf6_link_lsa_show,
+                                        .lh_get_prefix_str =
+                                                ospf6_link_lsa_get_prefix_str,
+                                        .lh_debug = 0};
+
+struct ospf6_lsa_handler intra_prefix_handler = {
+       .lh_type = OSPF6_LSTYPE_INTRA_PREFIX,
+       .lh_name = "Intra-Prefix",
+       .lh_short_name = "INP",
+       .lh_show = ospf6_intra_prefix_lsa_show,
+       .lh_get_prefix_str = ospf6_intra_prefix_lsa_get_prefix_str,
+       .lh_debug = 0};
+
+void ospf6_intra_init(void)
 {
-  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);
+       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);
 }
 
 DEFUN (debug_ospf6_brouter,
@@ -1708,8 +2275,8 @@ DEFUN (debug_ospf6_brouter,
        "Debug border router\n"
       )
 {
-  OSPF6_DEBUG_BROUTER_ON ();
-  return CMD_SUCCESS;
+       OSPF6_DEBUG_BROUTER_ON();
+       return CMD_SUCCESS;
 }
 
 DEFUN (no_debug_ospf6_brouter,
@@ -1721,8 +2288,8 @@ DEFUN (no_debug_ospf6_brouter,
        "Debug border router\n"
       )
 {
-  OSPF6_DEBUG_BROUTER_OFF ();
-  return CMD_SUCCESS;
+       OSPF6_DEBUG_BROUTER_OFF();
+       return CMD_SUCCESS;
 }
 
 DEFUN (debug_ospf6_brouter_router,
@@ -1735,11 +2302,11 @@ DEFUN (debug_ospf6_brouter_router,
        "Specify border-router's router-id\n"
       )
 {
-  int idx_ipv4 = 4;
-  u_int32_t router_id;
-  inet_pton (AF_INET, argv[idx_ipv4]->arg, &router_id);
-  OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ON (router_id);
-  return CMD_SUCCESS;
+       int idx_ipv4 = 4;
+       uint32_t router_id;
+       inet_pton(AF_INET, argv[idx_ipv4]->arg, &router_id);
+       OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ON(router_id);
+       return CMD_SUCCESS;
 }
 
 DEFUN (no_debug_ospf6_brouter_router,
@@ -1752,8 +2319,8 @@ DEFUN (no_debug_ospf6_brouter_router,
        "Debug specific border router\n"
       )
 {
-  OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_OFF ();
-  return CMD_SUCCESS;
+       OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_OFF();
+       return CMD_SUCCESS;
 }
 
 DEFUN (debug_ospf6_brouter_area,
@@ -1766,11 +2333,11 @@ DEFUN (debug_ospf6_brouter_area,
        "Specify Area-ID\n"
       )
 {
-  int idx_ipv4 = 4;
-  u_int32_t area_id;
-  inet_pton (AF_INET, argv[idx_ipv4]->arg, &area_id);
-  OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ON (area_id);
-  return CMD_SUCCESS;
+       int idx_ipv4 = 4;
+       uint32_t area_id;
+       inet_pton(AF_INET, argv[idx_ipv4]->arg, &area_id);
+       OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ON(area_id);
+       return CMD_SUCCESS;
 }
 
 DEFUN (no_debug_ospf6_brouter_area,
@@ -1783,46 +2350,40 @@ DEFUN (no_debug_ospf6_brouter_area,
        "Debug border routers in specific Area\n"
       )
 {
-  OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_OFF ();
-  return CMD_SUCCESS;
+       OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_OFF();
+       return CMD_SUCCESS;
 }
 
-int
-config_write_ospf6_debug_brouter (struct vty *vty)
+int config_write_ospf6_debug_brouter(struct vty *vty)
 {
-  char buf[16];
-  if (IS_OSPF6_DEBUG_BROUTER)
-    vty_out (vty, "debug ospf6 border-routers\n");
-  if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER)
-    {
-      inet_ntop (AF_INET, &conf_debug_ospf6_brouter_specific_router_id,
-                 buf, sizeof (buf));
-      vty_out (vty, "debug ospf6 border-routers router-id %s\n", buf);
-    }
-  if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA)
-    {
-      inet_ntop (AF_INET, &conf_debug_ospf6_brouter_specific_area_id,
-                 buf, sizeof (buf));
-      vty_out (vty, "debug ospf6 border-routers area-id %s\n", buf);
-    }
-  return 0;
+       char buf[16];
+       if (IS_OSPF6_DEBUG_BROUTER)
+               vty_out(vty, "debug ospf6 border-routers\n");
+       if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER) {
+               inet_ntop(AF_INET, &conf_debug_ospf6_brouter_specific_router_id,
+                         buf, sizeof(buf));
+               vty_out(vty, "debug ospf6 border-routers router-id %s\n", buf);
+       }
+       if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA) {
+               inet_ntop(AF_INET, &conf_debug_ospf6_brouter_specific_area_id,
+                         buf, sizeof(buf));
+               vty_out(vty, "debug ospf6 border-routers area-id %s\n", buf);
+       }
+       return 0;
 }
 
-void
-install_element_ospf6_debug_brouter (void)
+void install_element_ospf6_debug_brouter(void)
 {
-  install_element (ENABLE_NODE, &debug_ospf6_brouter_cmd);
-  install_element (ENABLE_NODE, &debug_ospf6_brouter_router_cmd);
-  install_element (ENABLE_NODE, &debug_ospf6_brouter_area_cmd);
-  install_element (ENABLE_NODE, &no_debug_ospf6_brouter_cmd);
-  install_element (ENABLE_NODE, &no_debug_ospf6_brouter_router_cmd);
-  install_element (ENABLE_NODE, &no_debug_ospf6_brouter_area_cmd);
-  install_element (CONFIG_NODE, &debug_ospf6_brouter_cmd);
-  install_element (CONFIG_NODE, &debug_ospf6_brouter_router_cmd);
-  install_element (CONFIG_NODE, &debug_ospf6_brouter_area_cmd);
-  install_element (CONFIG_NODE, &no_debug_ospf6_brouter_cmd);
-  install_element (CONFIG_NODE, &no_debug_ospf6_brouter_router_cmd);
-  install_element (CONFIG_NODE, &no_debug_ospf6_brouter_area_cmd);
+       install_element(ENABLE_NODE, &debug_ospf6_brouter_cmd);
+       install_element(ENABLE_NODE, &debug_ospf6_brouter_router_cmd);
+       install_element(ENABLE_NODE, &debug_ospf6_brouter_area_cmd);
+       install_element(ENABLE_NODE, &no_debug_ospf6_brouter_cmd);
+       install_element(ENABLE_NODE, &no_debug_ospf6_brouter_router_cmd);
+       install_element(ENABLE_NODE, &no_debug_ospf6_brouter_area_cmd);
+       install_element(CONFIG_NODE, &debug_ospf6_brouter_cmd);
+       install_element(CONFIG_NODE, &debug_ospf6_brouter_router_cmd);
+       install_element(CONFIG_NODE, &debug_ospf6_brouter_area_cmd);
+       install_element(CONFIG_NODE, &no_debug_ospf6_brouter_cmd);
+       install_element(CONFIG_NODE, &no_debug_ospf6_brouter_router_cmd);
+       install_element(CONFIG_NODE, &no_debug_ospf6_brouter_area_cmd);
 }
-
-