2 * Copyright (C) 2003 Yasuhiro Ohara
4 * This file is part of GNU Zebra.
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with GNU Zebra; see the file COPYING. If not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
32 #include "ospf6_proto.h"
33 #include "ospf6_lsa.h"
34 #include "ospf6_lsdb.h"
35 #include "ospf6_route.h"
36 #include "ospf6_top.h"
37 #include "ospf6_area.h"
38 #include "ospf6_interface.h"
41 unsigned char conf_debug_ospf6_route = 0;
44 ospf6_route_table_name (struct ospf6_route_table *table)
47 switch (table->scope_type)
49 case OSPF6_SCOPE_TYPE_GLOBAL:
51 switch (table->table_type)
53 case OSPF6_TABLE_TYPE_ROUTES:
54 snprintf (name, sizeof (name), "global route table");
56 case OSPF6_TABLE_TYPE_BORDER_ROUTERS:
57 snprintf (name, sizeof (name), "global brouter table");
59 case OSPF6_TABLE_TYPE_EXTERNAL_ROUTES:
60 snprintf (name, sizeof (name), "global external table");
63 snprintf (name, sizeof (name), "global unknown table");
69 case OSPF6_SCOPE_TYPE_AREA:
71 struct ospf6_area *oa = (struct ospf6_area *) table->scope;
72 switch (table->table_type)
74 case OSPF6_TABLE_TYPE_SPF_RESULTS:
75 snprintf (name, sizeof (name),
76 "area %s spf table", oa->name);
78 case OSPF6_TABLE_TYPE_ROUTES:
79 snprintf (name, sizeof (name),
80 "area %s route table", oa->name);
82 case OSPF6_TABLE_TYPE_PREFIX_RANGES:
83 snprintf (name, sizeof (name),
84 "area %s range table", oa->name);
86 case OSPF6_TABLE_TYPE_SUMMARY_PREFIXES:
87 snprintf (name, sizeof (name),
88 "area %s summary prefix table", oa->name);
90 case OSPF6_TABLE_TYPE_SUMMARY_ROUTERS:
91 snprintf (name, sizeof (name),
92 "area %s summary router table", oa->name);
95 snprintf (name, sizeof (name),
96 "area %s unknown table", oa->name);
102 case OSPF6_SCOPE_TYPE_INTERFACE:
104 struct ospf6_interface *oi = (struct ospf6_interface *) table->scope;
105 switch (table->table_type)
107 case OSPF6_TABLE_TYPE_CONNECTED_ROUTES:
108 snprintf (name, sizeof (name), "interface %s connected table",
109 oi->interface->name);
112 snprintf (name, sizeof (name), "interface %s unknown table",
113 oi->interface->name);
121 switch (table->table_type)
123 case OSPF6_TABLE_TYPE_SPF_RESULTS:
124 snprintf (name, sizeof (name), "temporary spf table");
127 snprintf (name, sizeof (name), "temporary unknown table");
137 ospf6_linkstate_prefix (u_int32_t adv_router, u_int32_t id,
138 struct prefix *prefix)
140 memset (prefix, 0, sizeof (struct prefix));
141 prefix->family = AF_INET6;
142 prefix->prefixlen = 64;
143 memcpy (&prefix->u.prefix6.s6_addr[0], &adv_router, 4);
144 memcpy (&prefix->u.prefix6.s6_addr[4], &id, 4);
148 ospf6_linkstate_prefix2str (struct prefix *prefix, char *buf, int size)
150 u_int32_t adv_router, id;
151 char adv_router_str[16], id_str[16];
152 memcpy (&adv_router, &prefix->u.prefix6.s6_addr[0], 4);
153 memcpy (&id, &prefix->u.prefix6.s6_addr[4], 4);
154 inet_ntop (AF_INET, &adv_router, adv_router_str, sizeof (adv_router_str));
155 inet_ntop (AF_INET, &id, id_str, sizeof (id_str));
157 snprintf (buf, size, "%s Net-ID: %s", adv_router_str, id_str);
159 snprintf (buf, size, "%s", adv_router_str);
162 /* Global strings for logging */
163 const char *ospf6_dest_type_str[OSPF6_DEST_TYPE_MAX] =
164 { "Unknown", "Router", "Network", "Discard", "Linkstate", "AddressRange", };
166 const char *ospf6_dest_type_substr[OSPF6_DEST_TYPE_MAX] =
167 { "?", "R", "N", "D", "L", "A", };
169 const char *ospf6_path_type_str[OSPF6_PATH_TYPE_MAX] =
170 { "Unknown", "Intra-Area", "Inter-Area", "External-1", "External-2", };
172 const char *ospf6_path_type_substr[OSPF6_PATH_TYPE_MAX] =
173 { "??", "IA", "IE", "E1", "E2", };
177 ospf6_route_create (void)
179 struct ospf6_route *route;
180 route = XCALLOC (MTYPE_OSPF6_ROUTE, sizeof (struct ospf6_route));
185 ospf6_route_delete (struct ospf6_route *route)
187 XFREE (MTYPE_OSPF6_ROUTE, route);
191 ospf6_route_copy (struct ospf6_route *route)
193 struct ospf6_route *new;
195 new = ospf6_route_create ();
196 memcpy (new, route, sizeof (struct ospf6_route));
206 ospf6_route_lock (struct ospf6_route *route)
212 ospf6_route_unlock (struct ospf6_route *route)
214 assert (route->lock > 0);
216 if (route->lock == 0)
218 /* Can't detach from the table until here
219 because ospf6_route_next () will use
220 the 'route->table' pointer for logging */
222 ospf6_route_delete (route);
226 /* Route compare function. If ra is more preferred, it returns
227 less than 0. If rb is more preferred returns greater than 0.
228 Otherwise (neither one is preferred), returns 0 */
230 ospf6_route_cmp (struct ospf6_route *ra, struct ospf6_route *rb)
232 assert (ospf6_route_is_same (ra, rb));
233 assert (OSPF6_PATH_TYPE_NONE < ra->path.type &&
234 ra->path.type < OSPF6_PATH_TYPE_MAX);
235 assert (OSPF6_PATH_TYPE_NONE < rb->path.type &&
236 rb->path.type < OSPF6_PATH_TYPE_MAX);
238 if (ra->type != rb->type)
239 return (ra->type - rb->type);
241 if (ra->path.area_id != rb->path.area_id)
242 return (ntohl (ra->path.area_id) - ntohl (rb->path.area_id));
244 if (ra->path.type != rb->path.type)
245 return (ra->path.type - rb->path.type);
247 if (ra->path.type == OSPF6_PATH_TYPE_EXTERNAL2)
249 if (ra->path.cost_e2 != rb->path.cost_e2)
250 return (ra->path.cost_e2 - rb->path.cost_e2);
254 if (ra->path.cost != rb->path.cost)
255 return (ra->path.cost - rb->path.cost);
262 ospf6_route_lookup (struct prefix *prefix,
263 struct ospf6_route_table *table)
265 struct route_node *node;
266 struct ospf6_route *route;
268 node = route_node_lookup (table->table, prefix);
272 route = (struct ospf6_route *) node->info;
277 ospf6_route_lookup_identical (struct ospf6_route *route,
278 struct ospf6_route_table *table)
280 struct ospf6_route *target;
282 for (target = ospf6_route_lookup (&route->prefix, table);
283 target; target = target->next)
285 if (ospf6_route_is_identical (target, route))
292 ospf6_route_lookup_bestmatch (struct prefix *prefix,
293 struct ospf6_route_table *table)
295 struct route_node *node;
296 struct ospf6_route *route;
298 node = route_node_match (table->table, prefix);
301 route_unlock_node (node);
303 route = (struct ospf6_route *) node->info;
309 route_table_assert (struct ospf6_route_table *table)
311 struct ospf6_route *prev, *r, *next;
313 unsigned int link_error = 0, num = 0;
315 r = ospf6_route_head (table);
322 next = ospf6_route_next (r);
331 for (r = ospf6_route_head (table); r; r = ospf6_route_next (r))
334 if (link_error == 0 && num == table->count)
337 zlog_err ("PANIC !!");
338 zlog_err ("Something has gone wrong with ospf6_route_table[%p]", table);
339 zlog_debug ("table count = %d, real number = %d", table->count, num);
340 zlog_debug ("DUMP START");
341 for (r = ospf6_route_head (table); r; r = ospf6_route_next (r))
343 prefix2str (&r->prefix, buf, sizeof (buf));
344 zlog_info ("%p<-[%p]->%p : %s", r->prev, r, r->next, buf);
346 zlog_debug ("DUMP END");
348 assert (link_error == 0 && num == table->count);
350 #define ospf6_route_table_assert(t) (route_table_assert (t))
352 #define ospf6_route_table_assert(t) ((void) 0)
356 ospf6_route_add (struct ospf6_route *route,
357 struct ospf6_route_table *table)
359 struct route_node *node, *nextnode, *prevnode;
360 struct ospf6_route *current = NULL;
361 struct ospf6_route *prev = NULL, *old = NULL, *next = NULL;
365 assert (route->rnode == NULL);
366 assert (route->lock == 0);
367 assert (route->next == NULL);
368 assert (route->prev == NULL);
370 if (route->type == OSPF6_DEST_TYPE_LINKSTATE)
371 ospf6_linkstate_prefix2str (&route->prefix, buf, sizeof (buf));
373 prefix2str (&route->prefix, buf, sizeof (buf));
375 if (IS_OSPF6_DEBUG_ROUTE (MEMORY))
376 zlog_debug ("%s %p: route add %p: %s", ospf6_route_table_name (table),
377 (void *)table, (void *)route, buf);
378 else if (IS_OSPF6_DEBUG_ROUTE (TABLE))
379 zlog_debug ("%s: route add: %s", ospf6_route_table_name (table), buf);
381 quagga_gettime (QUAGGA_CLK_MONOTONIC, &now);
383 node = route_node_get (table->table, &route->prefix);
386 /* find place to insert */
387 for (current = node->info; current; current = current->next)
389 if (! ospf6_route_is_same (current, route))
391 else if (current->type != route->type)
393 else if (ospf6_route_is_same_origin (current, route))
395 else if (ospf6_route_cmp (current, route) > 0)
406 /* if route does not actually change, return unchanged */
407 if (ospf6_route_is_identical (old, route))
409 if (IS_OSPF6_DEBUG_ROUTE (MEMORY))
410 zlog_debug ("%s %p: route add %p: needless update of %p",
411 ospf6_route_table_name (table),
412 (void *)table, (void *)route, (void *)old);
413 else if (IS_OSPF6_DEBUG_ROUTE (TABLE))
414 zlog_debug ("%s: route add: needless update",
415 ospf6_route_table_name (table));
417 ospf6_route_delete (route);
418 SET_FLAG (old->flag, OSPF6_ROUTE_ADD);
419 ospf6_route_table_assert (table);
424 if (IS_OSPF6_DEBUG_ROUTE (MEMORY))
425 zlog_debug ("%s %p: route add %p: update of %p",
426 ospf6_route_table_name (table),
427 (void *)table, (void *)route, (void *)old);
428 else if (IS_OSPF6_DEBUG_ROUTE (TABLE))
429 zlog_debug ("%s: route add: update",
430 ospf6_route_table_name (table));
432 /* replace old one if exists */
433 if (node->info == old)
436 SET_FLAG (route->flag, OSPF6_ROUTE_BEST);
440 old->prev->next = route;
441 route->prev = old->prev;
443 old->next->prev = route;
444 route->next = old->next;
446 route->installed = old->installed;
447 route->changed = now;
448 assert (route->table == NULL);
449 route->table = table;
451 ospf6_route_unlock (old); /* will be deleted later */
452 ospf6_route_lock (route);
454 SET_FLAG (route->flag, OSPF6_ROUTE_CHANGE);
455 ospf6_route_table_assert (table);
458 (*table->hook_add) (route);
463 /* insert if previous or next node found */
466 if (IS_OSPF6_DEBUG_ROUTE (MEMORY))
467 zlog_debug ("%s %p: route add %p: another path: prev %p, next %p",
468 ospf6_route_table_name (table),
469 (void *)table, (void *)route, (void *)prev, (void *)next);
470 else if (IS_OSPF6_DEBUG_ROUTE (TABLE))
471 zlog_debug ("%s: route add: another path found",
472 ospf6_route_table_name (table));
486 if (node->info == next)
488 assert (next->rnode == node);
490 UNSET_FLAG (next->flag, OSPF6_ROUTE_BEST);
491 SET_FLAG (route->flag, OSPF6_ROUTE_BEST);
492 if (IS_OSPF6_DEBUG_ROUTE (MEMORY))
493 zlog_info ("%s %p: route add %p: replacing previous best: %p",
494 ospf6_route_table_name (table),
495 (void *)table, (void *)route, (void *)next);
498 route->installed = now;
499 route->changed = now;
500 assert (route->table == NULL);
501 route->table = table;
503 ospf6_route_lock (route);
505 ospf6_route_table_assert (table);
507 SET_FLAG (route->flag, OSPF6_ROUTE_ADD);
509 (*table->hook_add) (route);
514 /* Else, this is the brand new route regarding to the prefix */
515 if (IS_OSPF6_DEBUG_ROUTE (MEMORY))
516 zlog_debug ("%s %p: route add %p: brand new route",
517 ospf6_route_table_name (table), (void *)table, (void *)route);
518 else if (IS_OSPF6_DEBUG_ROUTE (TABLE))
519 zlog_debug ("%s: route add: brand new route",
520 ospf6_route_table_name (table));
522 assert (node->info == NULL);
524 SET_FLAG (route->flag, OSPF6_ROUTE_BEST);
525 ospf6_route_lock (route);
526 route->installed = now;
527 route->changed = now;
528 assert (route->table == NULL);
529 route->table = table;
531 /* lookup real existing next route */
533 route_lock_node (nextnode);
535 nextnode = route_next (nextnode);
536 } while (nextnode && nextnode->info == NULL);
539 if (nextnode == NULL)
543 route_unlock_node (nextnode);
545 next = nextnode->info;
550 /* lookup real existing prev route */
552 route_lock_node (prevnode);
554 prevnode = route_prev (prevnode);
555 } while (prevnode && prevnode->info == NULL);
558 if (prevnode == NULL)
562 route_unlock_node (prevnode);
564 prev = prevnode->info;
565 while (prev->next && ospf6_route_is_same (prev, prev->next))
572 ospf6_route_table_assert (table);
574 SET_FLAG (route->flag, OSPF6_ROUTE_ADD);
576 (*table->hook_add) (route);
582 ospf6_route_remove (struct ospf6_route *route,
583 struct ospf6_route_table *table)
585 struct route_node *node;
586 struct ospf6_route *current;
589 if (route->type == OSPF6_DEST_TYPE_LINKSTATE)
590 ospf6_linkstate_prefix2str (&route->prefix, buf, sizeof (buf));
592 prefix2str (&route->prefix, buf, sizeof (buf));
594 if (IS_OSPF6_DEBUG_ROUTE (MEMORY))
595 zlog_debug ("%s %p: route remove %p: %s",
596 ospf6_route_table_name (table),
597 (void *)table, (void *)route, buf);
598 else if (IS_OSPF6_DEBUG_ROUTE (TABLE))
599 zlog_debug ("%s: route remove: %s", ospf6_route_table_name (table), buf);
601 node = route_node_lookup (table->table, &route->prefix);
604 /* find the route to remove, making sure that the route pointer
605 is from the route table. */
606 current = node->info;
607 while (current && ospf6_route_is_same (current, route))
609 if (current == route)
611 current = current->next;
613 assert (current == route);
615 /* adjust doubly linked list */
617 route->prev->next = route->next;
619 route->next->prev = route->prev;
621 if (node->info == route)
623 if (route->next && route->next->rnode == node)
625 node->info = route->next;
626 SET_FLAG (route->next->flag, OSPF6_ROUTE_BEST);
629 node->info = NULL; /* should unlock route_node here ? */
633 ospf6_route_table_assert (table);
635 SET_FLAG (route->flag, OSPF6_ROUTE_WAS_REMOVED);
637 if (table->hook_remove)
638 (*table->hook_remove) (route);
640 ospf6_route_unlock (route);
644 ospf6_route_head (struct ospf6_route_table *table)
646 struct route_node *node;
647 struct ospf6_route *route;
649 node = route_top (table->table);
653 /* skip to the real existing entry */
654 while (node && node->info == NULL)
655 node = route_next (node);
659 route_unlock_node (node);
662 route = (struct ospf6_route *) node->info;
663 assert (route->prev == NULL);
664 assert (route->table == table);
665 ospf6_route_lock (route);
667 if (IS_OSPF6_DEBUG_ROUTE (MEMORY))
668 zlog_info ("%s %p: route head: %p<-[%p]->%p",
669 ospf6_route_table_name (table), (void *)table,
670 (void *)route->prev, (void *)route, (void *)route->next);
676 ospf6_route_next (struct ospf6_route *route)
678 struct ospf6_route *next = route->next;
680 if (IS_OSPF6_DEBUG_ROUTE (MEMORY))
681 zlog_info ("%s %p: route next: %p<-[%p]->%p",
682 ospf6_route_table_name (route->table), (void *)route->table,
683 (void *)route->prev, (void *)route, (void *)route->next);
685 ospf6_route_unlock (route);
687 ospf6_route_lock (next);
693 ospf6_route_best_next (struct ospf6_route *route)
695 struct route_node *rnode;
696 struct ospf6_route *next;
698 ospf6_route_unlock (route);
700 rnode = route->rnode;
701 route_lock_node (rnode);
702 rnode = route_next (rnode);
703 while (rnode && rnode->info == NULL)
704 rnode = route_next (rnode);
707 route_unlock_node (rnode);
709 assert (rnode->info);
710 next = (struct ospf6_route *) rnode->info;
711 ospf6_route_lock (next);
716 ospf6_route_match_head (struct prefix *prefix,
717 struct ospf6_route_table *table)
719 struct route_node *node;
720 struct ospf6_route *route;
722 /* Walk down tree. */
723 node = table->table->top;
724 while (node && node->p.prefixlen < prefix->prefixlen &&
725 prefix_match (&node->p, prefix))
726 node = node->link[prefix_bit(&prefix->u.prefix, node->p.prefixlen)];
729 route_lock_node (node);
730 while (node && node->info == NULL)
731 node = route_next (node);
734 route_unlock_node (node);
736 if (! prefix_match (prefix, &node->p))
740 ospf6_route_lock (route);
745 ospf6_route_match_next (struct prefix *prefix,
746 struct ospf6_route *route)
748 struct ospf6_route *next;
750 next = ospf6_route_next (route);
751 if (next && ! prefix_match (prefix, &next->prefix))
753 ospf6_route_unlock (next);
761 ospf6_route_remove_all (struct ospf6_route_table *table)
763 struct ospf6_route *route;
764 for (route = ospf6_route_head (table); route;
765 route = ospf6_route_next (route))
766 ospf6_route_remove (route, table);
769 struct ospf6_route_table *
770 ospf6_route_table_create (int s, int t)
772 struct ospf6_route_table *new;
773 new = XCALLOC (MTYPE_OSPF6_ROUTE, sizeof (struct ospf6_route_table));
774 new->table = route_table_init ();
781 ospf6_route_table_delete (struct ospf6_route_table *table)
783 ospf6_route_remove_all (table);
784 route_table_finish (table->table);
785 XFREE (MTYPE_OSPF6_ROUTE, table);
791 ospf6_route_show (struct vty *vty, struct ospf6_route *route)
794 char destination[64], nexthop[64];
797 struct timeval now, res;
799 quagga_gettime (QUAGGA_CLK_MONOTONIC, &now);
800 timersub (&now, &route->changed, &res);
801 timerstring (&res, duration, sizeof (duration));
804 if (route->type == OSPF6_DEST_TYPE_LINKSTATE)
805 ospf6_linkstate_prefix2str (&route->prefix, destination,
806 sizeof (destination));
807 else if (route->type == OSPF6_DEST_TYPE_ROUTER)
808 inet_ntop (route->prefix.family, &route->prefix.u.prefix,
809 destination, sizeof (destination));
811 prefix2str (&route->prefix, destination, sizeof (destination));
814 inet_ntop (AF_INET6, &route->nexthop[0].address, nexthop,
816 ifname = ifindex2ifname (route->nexthop[0].ifindex);
818 vty_out (vty, "%c%1s %2s %-30s %-25s %6.*s %s%s",
819 (ospf6_route_is_best (route) ? '*' : ' '),
820 OSPF6_DEST_TYPE_SUBSTR (route->type),
821 OSPF6_PATH_TYPE_SUBSTR (route->path.type),
822 destination, nexthop, IFNAMSIZ, ifname, duration, VNL);
824 for (i = 1; i < OSPF6_MULTI_PATH_LIMIT &&
825 ospf6_nexthop_is_set (&route->nexthop[i]); i++)
828 inet_ntop (AF_INET6, &route->nexthop[i].address, nexthop,
830 ifname = ifindex2ifname (route->nexthop[i].ifindex);
832 vty_out (vty, "%c%1s %2s %-30s %-25s %6.*s %s%s",
833 ' ', "", "", "", nexthop, IFNAMSIZ, ifname, "", VNL);
838 ospf6_route_show_detail (struct vty *vty, struct ospf6_route *route)
841 char destination[64], nexthop[64];
842 char area_id[16], id[16], adv_router[16], capa[16], options[16];
843 struct timeval now, res;
847 quagga_gettime (QUAGGA_CLK_MONOTONIC, &now);
850 if (route->type == OSPF6_DEST_TYPE_LINKSTATE)
851 ospf6_linkstate_prefix2str (&route->prefix, destination,
852 sizeof (destination));
853 else if (route->type == OSPF6_DEST_TYPE_ROUTER)
854 inet_ntop (route->prefix.family, &route->prefix.u.prefix,
855 destination, sizeof (destination));
857 prefix2str (&route->prefix, destination, sizeof (destination));
858 vty_out (vty, "Destination: %s%s", destination, VNL);
860 /* destination type */
861 vty_out (vty, "Destination type: %s%s",
862 OSPF6_DEST_TYPE_NAME (route->type),
866 timersub (&now, &route->installed, &res);
867 timerstring (&res, duration, sizeof (duration));
868 vty_out (vty, "Installed Time: %s ago%s", duration, VNL);
870 timersub (&now, &route->changed, &res);
871 timerstring (&res, duration, sizeof (duration));
872 vty_out (vty, " Changed Time: %s ago%s", duration, VNL);
875 vty_out (vty, "Lock: %d Flags: %s%s%s%s%s", route->lock,
876 (CHECK_FLAG (route->flag, OSPF6_ROUTE_BEST) ? "B" : "-"),
877 (CHECK_FLAG (route->flag, OSPF6_ROUTE_ADD) ? "A" : "-"),
878 (CHECK_FLAG (route->flag, OSPF6_ROUTE_REMOVE) ? "R" : "-"),
879 (CHECK_FLAG (route->flag, OSPF6_ROUTE_CHANGE) ? "C" : "-"),
881 vty_out (vty, "Memory: prev: %p this: %p next: %p%s",
882 (void *)route->prev, (void *)route, (void *)route->next, VNL);
887 inet_ntop (AF_INET, &route->path.area_id, area_id, sizeof (area_id));
888 vty_out (vty, "Associated Area: %s%s", area_id, VNL);
891 vty_out (vty, "Path Type: %s%s",
892 OSPF6_PATH_TYPE_NAME (route->path.type), VNL);
895 inet_ntop (AF_INET, &route->path.origin.id, id, sizeof (id));
896 inet_ntop (AF_INET, &route->path.origin.adv_router, adv_router,
897 sizeof (adv_router));
898 vty_out (vty, "LS Origin: %s Id: %s Adv: %s%s",
899 ospf6_lstype_name (route->path.origin.type),
900 id, adv_router, VNL);
903 ospf6_options_printbuf (route->path.options, options, sizeof (options));
904 vty_out (vty, "Options: %s%s", options, VNL);
907 ospf6_capability_printbuf (route->path.router_bits, capa, sizeof (capa));
908 vty_out (vty, "Router Bits: %s%s", capa, VNL);
911 vty_out (vty, "Prefix Options: xxx%s", VNL);
914 vty_out (vty, "Metric Type: %d%s", route->path.metric_type,
916 vty_out (vty, "Metric: %d (%d)%s",
917 route->path.cost, route->path.cost_e2, VNL);
920 vty_out (vty, "Nexthop:%s", VNL);
921 for (i = 0; i < OSPF6_MULTI_PATH_LIMIT &&
922 ospf6_nexthop_is_set (&route->nexthop[i]); i++)
925 inet_ntop (AF_INET6, &route->nexthop[i].address, nexthop,
927 ifname = ifindex2ifname (route->nexthop[i].ifindex);
928 vty_out (vty, " %s %.*s%s", nexthop, IFNAMSIZ, ifname, VNL);
930 vty_out (vty, "%s", VNL);
934 ospf6_route_show_table_summary (struct vty *vty,
935 struct ospf6_route_table *table)
937 struct ospf6_route *route, *prev = NULL;
938 int i, pathtype[OSPF6_PATH_TYPE_MAX];
939 unsigned int number = 0;
940 int nhinval = 0, ecmp = 0;
941 int alternative = 0, destination = 0;
943 for (i = 0; i < OSPF6_PATH_TYPE_MAX; i++)
946 for (route = ospf6_route_head (table); route;
947 route = ospf6_route_next (route))
949 if (prev == NULL || ! ospf6_route_is_same (prev, route))
953 if (! ospf6_nexthop_is_set (&route->nexthop[0]))
955 else if (ospf6_nexthop_is_set (&route->nexthop[1]))
957 pathtype[route->path.type]++;
963 assert (number == table->count);
965 vty_out (vty, "Number of OSPFv3 routes: %d%s", number, VNL);
966 vty_out (vty, "Number of Destination: %d%s", destination, VNL);
967 vty_out (vty, "Number of Alternative routes: %d%s", alternative, VNL);
968 vty_out (vty, "Number of Equal Cost Multi Path: %d%s", ecmp, VNL);
969 for (i = OSPF6_PATH_TYPE_INTRA; i <= OSPF6_PATH_TYPE_EXTERNAL2; i++)
971 vty_out (vty, "Number of %s routes: %d%s",
972 OSPF6_PATH_TYPE_NAME (i), pathtype[i], VNL);
977 ospf6_route_show_table_prefix (struct vty *vty,
978 struct prefix *prefix,
979 struct ospf6_route_table *table)
981 struct ospf6_route *route;
983 route = ospf6_route_lookup (prefix, table);
987 ospf6_route_lock (route);
988 while (route && ospf6_route_is_prefix (prefix, route))
990 /* Specifying a prefix will always display details */
991 ospf6_route_show_detail (vty, route);
992 route = ospf6_route_next (route);
995 ospf6_route_unlock (route);
999 ospf6_route_show_table_address (struct vty *vty,
1000 struct prefix *prefix,
1001 struct ospf6_route_table *table)
1003 struct ospf6_route *route;
1005 route = ospf6_route_lookup_bestmatch (prefix, table);
1009 prefix = &route->prefix;
1010 ospf6_route_lock (route);
1011 while (route && ospf6_route_is_prefix (prefix, route))
1013 /* Specifying a prefix will always display details */
1014 ospf6_route_show_detail (vty, route);
1015 route = ospf6_route_next (route);
1018 ospf6_route_unlock (route);
1022 ospf6_route_show_table_match (struct vty *vty, int detail,
1023 struct prefix *prefix,
1024 struct ospf6_route_table *table)
1026 struct ospf6_route *route;
1027 assert (prefix->family);
1029 route = ospf6_route_match_head (prefix, table);
1033 ospf6_route_show_detail (vty, route);
1035 ospf6_route_show (vty, route);
1036 route = ospf6_route_match_next (prefix, route);
1041 ospf6_route_show_table_type (struct vty *vty, int detail, u_char type,
1042 struct ospf6_route_table *table)
1044 struct ospf6_route *route;
1046 route = ospf6_route_head (table);
1049 if (route->path.type == type)
1052 ospf6_route_show_detail (vty, route);
1054 ospf6_route_show (vty, route);
1056 route = ospf6_route_next (route);
1061 ospf6_route_show_table (struct vty *vty, int detail,
1062 struct ospf6_route_table *table)
1064 struct ospf6_route *route;
1066 route = ospf6_route_head (table);
1070 ospf6_route_show_detail (vty, route);
1072 ospf6_route_show (vty, route);
1073 route = ospf6_route_next (route);
1078 ospf6_route_table_show (struct vty *vty, int argc, const char *argv[],
1079 struct ospf6_route_table *table)
1087 struct prefix prefix;
1090 memset (&prefix, 0, sizeof (struct prefix));
1092 for (i = 0; i < argc; i++)
1094 if (! strcmp (argv[i], "summary"))
1100 if (! strcmp (argv[i], "intra-area"))
1102 type = OSPF6_PATH_TYPE_INTRA;
1106 if (! strcmp (argv[i], "inter-area"))
1108 type = OSPF6_PATH_TYPE_INTER;
1112 if (! strcmp (argv[i], "external-1"))
1114 type = OSPF6_PATH_TYPE_EXTERNAL1;
1118 if (! strcmp (argv[i], "external-2"))
1120 type = OSPF6_PATH_TYPE_EXTERNAL2;
1124 if (! strcmp (argv[i], "detail"))
1130 if (! strcmp (argv[i], "match"))
1136 ret = str2prefix (argv[i], &prefix);
1137 if (ret == 1 && prefix.family == AF_INET6)
1140 if (strchr (argv[i], '/'))
1145 vty_out (vty, "Malformed argument: %s%s", argv[i], VNL);
1149 /* Give summary of this route table */
1152 ospf6_route_show_table_summary (vty, table);
1156 /* Give exact prefix-match route */
1157 if (isprefix && ! match)
1159 /* If exact address, give best matching route */
1161 ospf6_route_show_table_address (vty, &prefix, table);
1163 ospf6_route_show_table_prefix (vty, &prefix, table);
1169 ospf6_route_show_table_match (vty, detail, &prefix, table);
1171 ospf6_route_show_table_type (vty, detail, type, table);
1173 ospf6_route_show_table (vty, detail, table);
1179 ospf6_linkstate_show_header (struct vty *vty)
1181 vty_out (vty, "%-7s %-15s %-15s %-8s %-14s %s%s",
1182 "Type", "Router-ID", "Net-ID", "Rtr-Bits", "Options", "Cost", VNL);
1186 ospf6_linkstate_show (struct vty *vty, struct ospf6_route *route)
1188 u_int32_t router, id;
1189 char routername[16], idname[16], rbits[16], options[16];
1191 router = ospf6_linkstate_prefix_adv_router (&route->prefix);
1192 inet_ntop (AF_INET, &router, routername, sizeof (routername));
1193 id = ospf6_linkstate_prefix_id (&route->prefix);
1194 inet_ntop (AF_INET, &id, idname, sizeof (idname));
1196 ospf6_capability_printbuf (route->path.router_bits, rbits, sizeof (rbits));
1197 ospf6_options_printbuf (route->path.options, options, sizeof (options));
1200 vty_out (vty, "%-7s %-15s %-15s %-8s %-14s %lu%s",
1201 "Network", routername, idname, rbits, options,
1202 (unsigned long) route->path.cost, VNL);
1204 vty_out (vty, "%-7s %-15s %-15s %-8s %-14s %lu%s",
1205 "Router", routername, idname, rbits, options,
1206 (unsigned long) route->path.cost, VNL);
1211 ospf6_linkstate_show_table_exact (struct vty *vty,
1212 struct prefix *prefix,
1213 struct ospf6_route_table *table)
1215 struct ospf6_route *route;
1217 route = ospf6_route_lookup (prefix, table);
1221 ospf6_route_lock (route);
1222 while (route && ospf6_route_is_prefix (prefix, route))
1224 /* Specifying a prefix will always display details */
1225 ospf6_route_show_detail (vty, route);
1226 route = ospf6_route_next (route);
1229 ospf6_route_unlock (route);
1233 ospf6_linkstate_show_table (struct vty *vty, int detail,
1234 struct ospf6_route_table *table)
1236 struct ospf6_route *route;
1239 ospf6_linkstate_show_header (vty);
1241 route = ospf6_route_head (table);
1245 ospf6_route_show_detail (vty, route);
1247 ospf6_linkstate_show (vty, route);
1248 route = ospf6_route_next (route);
1253 ospf6_linkstate_table_show (struct vty *vty, int argc, const char *argv[],
1254 struct ospf6_route_table *table)
1260 struct prefix router, id, prefix;
1262 memset (&router, 0, sizeof (struct prefix));
1263 memset (&id, 0, sizeof (struct prefix));
1264 memset (&prefix, 0, sizeof (struct prefix));
1266 for (i = 0; i < argc; i++)
1268 if (! strcmp (argv[i], "detail"))
1276 ret = str2prefix (argv[i], &router);
1277 if (ret == 1 && router.family == AF_INET)
1282 vty_out (vty, "Malformed argument: %s%s", argv[i], VNL);
1288 ret = str2prefix (argv[i], &id);
1289 if (ret == 1 && id.family == AF_INET)
1294 vty_out (vty, "Malformed argument: %s%s", argv[i], VNL);
1298 vty_out (vty, "Malformed argument: %s%s", argv[i], VNL);
1303 ospf6_linkstate_prefix (router.u.prefix4.s_addr,
1304 id.u.prefix4.s_addr, &prefix);
1307 ospf6_linkstate_show_table_exact (vty, &prefix, table);
1309 ospf6_linkstate_show_table (vty, detail, table);
1316 ospf6_brouter_show_header (struct vty *vty)
1318 vty_out (vty, "%-15s %-8s %-14s %-10s %-15s%s",
1319 "Router-ID", "Rtr-Bits", "Options", "Path-Type", "Area", VNL);
1323 ospf6_brouter_show (struct vty *vty, struct ospf6_route *route)
1325 u_int32_t adv_router;
1326 char adv[16], rbits[16], options[16], area[16];
1328 adv_router = ospf6_linkstate_prefix_adv_router (&route->prefix);
1329 inet_ntop (AF_INET, &adv_router, adv, sizeof (adv));
1330 ospf6_capability_printbuf (route->path.router_bits, rbits, sizeof (rbits));
1331 ospf6_options_printbuf (route->path.options, options, sizeof (options));
1332 inet_ntop (AF_INET, &route->path.area_id, area, sizeof (area));
1334 /* vty_out (vty, "%-15s %-8s %-14s %-10s %-15s%s",
1335 "Router-ID", "Rtr-Bits", "Options", "Path-Type", "Area", VNL); */
1336 vty_out (vty, "%-15s %-8s %-14s %-10s %-15s%s",
1337 adv, rbits, options, OSPF6_PATH_TYPE_NAME (route->path.type),
1341 DEFUN (debug_ospf6_route,
1342 debug_ospf6_route_cmd,
1343 "debug ospf6 route (table|intra-area|inter-area|memory)",
1346 "Debug route table calculation\n"
1348 "Debug intra-area route calculation\n"
1349 "Debug inter-area route calculation\n"
1350 "Debug route memory use\n"
1353 unsigned char level = 0;
1355 if (! strncmp (argv[0], "table", 5))
1356 level = OSPF6_DEBUG_ROUTE_TABLE;
1357 else if (! strncmp (argv[0], "intra", 5))
1358 level = OSPF6_DEBUG_ROUTE_INTRA;
1359 else if (! strncmp (argv[0], "inter", 5))
1360 level = OSPF6_DEBUG_ROUTE_INTER;
1361 else if (! strncmp (argv[0], "memor", 5))
1362 level = OSPF6_DEBUG_ROUTE_MEMORY;
1363 OSPF6_DEBUG_ROUTE_ON (level);
1367 DEFUN (no_debug_ospf6_route,
1368 no_debug_ospf6_route_cmd,
1369 "no debug ospf6 route (table|intra-area|inter-area|memory)",
1373 "Debug route table calculation\n"
1374 "Debug intra-area route calculation\n"
1375 "Debug route memory use\n")
1377 unsigned char level = 0;
1379 if (! strncmp (argv[0], "table", 5))
1380 level = OSPF6_DEBUG_ROUTE_TABLE;
1381 else if (! strncmp (argv[0], "intra", 5))
1382 level = OSPF6_DEBUG_ROUTE_INTRA;
1383 else if (! strncmp (argv[0], "inter", 5))
1384 level = OSPF6_DEBUG_ROUTE_INTER;
1385 else if (! strncmp (argv[0], "memor", 5))
1386 level = OSPF6_DEBUG_ROUTE_MEMORY;
1387 OSPF6_DEBUG_ROUTE_OFF (level);
1392 config_write_ospf6_debug_route (struct vty *vty)
1394 if (IS_OSPF6_DEBUG_ROUTE (TABLE))
1395 vty_out (vty, "debug ospf6 route table%s", VNL);
1396 if (IS_OSPF6_DEBUG_ROUTE (INTRA))
1397 vty_out (vty, "debug ospf6 route intra-area%s", VNL);
1398 if (IS_OSPF6_DEBUG_ROUTE (INTER))
1399 vty_out (vty, "debug ospf6 route inter-area%s", VNL);
1404 install_element_ospf6_debug_route (void)
1406 install_element (ENABLE_NODE, &debug_ospf6_route_cmd);
1407 install_element (ENABLE_NODE, &no_debug_ospf6_route_cmd);
1408 install_element (CONFIG_NODE, &debug_ospf6_route_cmd);
1409 install_element (CONFIG_NODE, &no_debug_ospf6_route_cmd);