#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%s", bits, options, VNL);
-
- 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%s",
- name, ntohs (lsdesc->metric), VNL);
- vty_out (vty, " Interface ID: %s%s",
- inet_ntop (AF_INET, &lsdesc->interface_id,
- buf, sizeof (buf)), VNL);
- vty_out (vty, " Neighbor Interface ID: %s%s",
- inet_ntop (AF_INET, &lsdesc->neighbor_interface_id,
- buf, sizeof (buf)), VNL);
- vty_out (vty, " Neighbor Router ID: %s%s",
- inet_ntop (AF_INET, &lsdesc->neighbor_router_id,
- buf, sizeof (buf)), VNL);
- }
- 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%s", options, VNL);
-
- 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%s", buf, VNL);
- }
- 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;
}
/* 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%s",
- link_lsa->priority, options, VNL);
- vty_out (vty, " LinkLocal Address: %s%s", buf, VNL);
- vty_out (vty, " Number of Prefix: %d%s", prefixnum, VNL);
-
- 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%s",
- p, mc, la, nu, VNL);
-
- 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%s",
- buf, prefix->prefix_length, VNL);
- }
-
- 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%s", prefixnum, VNL);
-
- 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%s",
- ospf6_lstype_name (intra_prefix_lsa->ref_type), id, adv_router,
- VNL);
-
- 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%s",
- p, mc, la, nu, VNL);
-
- 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%s",
- buf, prefix->prefix_length, VNL);
- }
-
- 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,
"Debug border router\n"
)
{
- OSPF6_DEBUG_BROUTER_ON ();
- return CMD_SUCCESS;
+ OSPF6_DEBUG_BROUTER_ON();
+ return CMD_SUCCESS;
}
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,
"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,
"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,
"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,
"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%s", VNL);
- 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%s", buf, VNL);
- }
- 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%s", buf, VNL);
- }
- 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);
}
-
-