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
),
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
), table
, route
, old
);
412 else if (IS_OSPF6_DEBUG_ROUTE (TABLE
))
413 zlog_debug ("%s: route add: needless update",
414 ospf6_route_table_name (table
));
416 ospf6_route_delete (route
);
417 SET_FLAG (old
->flag
, OSPF6_ROUTE_ADD
);
418 ospf6_route_table_assert (table
);
423 if (IS_OSPF6_DEBUG_ROUTE (MEMORY
))
424 zlog_debug ("%s %p: route add %p: update of %p",
425 ospf6_route_table_name (table
), table
, route
, old
);
426 else if (IS_OSPF6_DEBUG_ROUTE (TABLE
))
427 zlog_debug ("%s: route add: update",
428 ospf6_route_table_name (table
));
430 /* replace old one if exists */
431 if (node
->info
== old
)
434 SET_FLAG (route
->flag
, OSPF6_ROUTE_BEST
);
438 old
->prev
->next
= route
;
439 route
->prev
= old
->prev
;
441 old
->next
->prev
= route
;
442 route
->next
= old
->next
;
444 route
->installed
= old
->installed
;
445 route
->changed
= now
;
446 assert (route
->table
== NULL
);
447 route
->table
= table
;
449 ospf6_route_unlock (old
); /* will be deleted later */
450 ospf6_route_lock (route
);
452 SET_FLAG (route
->flag
, OSPF6_ROUTE_CHANGE
);
453 ospf6_route_table_assert (table
);
456 (*table
->hook_add
) (route
);
461 /* insert if previous or next node found */
464 if (IS_OSPF6_DEBUG_ROUTE (MEMORY
))
465 zlog_debug ("%s %p: route add %p: another path: prev %p, next %p",
466 ospf6_route_table_name (table
), table
, route
, prev
, next
);
467 else if (IS_OSPF6_DEBUG_ROUTE (TABLE
))
468 zlog_debug ("%s: route add: another path found",
469 ospf6_route_table_name (table
));
483 if (node
->info
== next
)
485 assert (next
->rnode
== node
);
487 UNSET_FLAG (next
->flag
, OSPF6_ROUTE_BEST
);
488 SET_FLAG (route
->flag
, OSPF6_ROUTE_BEST
);
489 if (IS_OSPF6_DEBUG_ROUTE (MEMORY
))
490 zlog_info ("%s %p: route add %p: replacing previous best: %p",
491 ospf6_route_table_name (table
), table
, route
, next
);
494 route
->installed
= now
;
495 route
->changed
= now
;
496 assert (route
->table
== NULL
);
497 route
->table
= table
;
499 ospf6_route_lock (route
);
501 ospf6_route_table_assert (table
);
503 SET_FLAG (route
->flag
, OSPF6_ROUTE_ADD
);
505 (*table
->hook_add
) (route
);
510 /* Else, this is the brand new route regarding to the prefix */
511 if (IS_OSPF6_DEBUG_ROUTE (MEMORY
))
512 zlog_debug ("%s %p: route add %p: brand new route",
513 ospf6_route_table_name (table
), table
, route
);
514 else if (IS_OSPF6_DEBUG_ROUTE (TABLE
))
515 zlog_debug ("%s: route add: brand new route",
516 ospf6_route_table_name (table
));
518 assert (node
->info
== NULL
);
520 SET_FLAG (route
->flag
, OSPF6_ROUTE_BEST
);
521 ospf6_route_lock (route
);
522 route
->installed
= now
;
523 route
->changed
= now
;
524 assert (route
->table
== NULL
);
525 route
->table
= table
;
527 /* lookup real existing next route */
529 route_lock_node (nextnode
);
531 nextnode
= route_next (nextnode
);
532 } while (nextnode
&& nextnode
->info
== NULL
);
535 if (nextnode
== NULL
)
539 route_unlock_node (nextnode
);
541 next
= nextnode
->info
;
546 /* lookup real existing prev route */
548 route_lock_node (prevnode
);
550 prevnode
= route_prev (prevnode
);
551 } while (prevnode
&& prevnode
->info
== NULL
);
554 if (prevnode
== NULL
)
558 route_unlock_node (prevnode
);
560 prev
= prevnode
->info
;
561 while (prev
->next
&& ospf6_route_is_same (prev
, prev
->next
))
568 ospf6_route_table_assert (table
);
570 SET_FLAG (route
->flag
, OSPF6_ROUTE_ADD
);
572 (*table
->hook_add
) (route
);
578 ospf6_route_remove (struct ospf6_route
*route
,
579 struct ospf6_route_table
*table
)
581 struct route_node
*node
;
582 struct ospf6_route
*current
;
585 if (route
->type
== OSPF6_DEST_TYPE_LINKSTATE
)
586 ospf6_linkstate_prefix2str (&route
->prefix
, buf
, sizeof (buf
));
588 prefix2str (&route
->prefix
, buf
, sizeof (buf
));
590 if (IS_OSPF6_DEBUG_ROUTE (MEMORY
))
591 zlog_debug ("%s %p: route remove %p: %s",
592 ospf6_route_table_name (table
), table
, route
, buf
);
593 else if (IS_OSPF6_DEBUG_ROUTE (TABLE
))
594 zlog_debug ("%s: route remove: %s", ospf6_route_table_name (table
), buf
);
596 node
= route_node_lookup (table
->table
, &route
->prefix
);
599 /* find the route to remove, making sure that the route pointer
600 is from the route table. */
601 current
= node
->info
;
602 while (current
&& ospf6_route_is_same (current
, route
))
604 if (current
== route
)
606 current
= current
->next
;
608 assert (current
== route
);
610 /* adjust doubly linked list */
612 route
->prev
->next
= route
->next
;
614 route
->next
->prev
= route
->prev
;
616 if (node
->info
== route
)
618 if (route
->next
&& ospf6_route_is_same (route
->next
, route
))
620 node
->info
= route
->next
;
621 SET_FLAG (route
->next
->flag
, OSPF6_ROUTE_BEST
);
624 node
->info
= NULL
; /* should unlock route_node here ? */
628 ospf6_route_table_assert (table
);
630 SET_FLAG (route
->flag
, OSPF6_ROUTE_WAS_REMOVED
);
632 if (table
->hook_remove
)
633 (*table
->hook_remove
) (route
);
635 ospf6_route_unlock (route
);
639 ospf6_route_head (struct ospf6_route_table
*table
)
641 struct route_node
*node
;
642 struct ospf6_route
*route
;
644 node
= route_top (table
->table
);
648 /* skip to the real existing entry */
649 while (node
&& node
->info
== NULL
)
650 node
= route_next (node
);
654 route_unlock_node (node
);
657 route
= (struct ospf6_route
*) node
->info
;
658 assert (route
->prev
== NULL
);
659 assert (route
->table
== table
);
660 ospf6_route_lock (route
);
662 if (IS_OSPF6_DEBUG_ROUTE (MEMORY
))
663 zlog_info ("%s %p: route head: %p<-[%p]->%p",
664 ospf6_route_table_name (table
), table
,
665 route
->prev
, route
, route
->next
);
671 ospf6_route_next (struct ospf6_route
*route
)
673 struct ospf6_route
*next
= route
->next
;
675 if (IS_OSPF6_DEBUG_ROUTE (MEMORY
))
676 zlog_info ("%s %p: route next: %p<-[%p]->%p",
677 ospf6_route_table_name (route
->table
), route
->table
,
678 route
->prev
, route
, route
->next
);
680 ospf6_route_unlock (route
);
682 ospf6_route_lock (next
);
688 ospf6_route_best_next (struct ospf6_route
*route
)
690 struct route_node
*rnode
;
691 struct ospf6_route
*next
;
693 rnode
= route
->rnode
;
694 route_lock_node (rnode
);
695 rnode
= route_next (rnode
);
696 while (rnode
&& rnode
->info
== NULL
)
697 rnode
= route_next (rnode
);
700 route_unlock_node (rnode
);
702 assert (rnode
->info
);
703 next
= (struct ospf6_route
*) rnode
->info
;
704 ospf6_route_unlock (route
);
705 ospf6_route_lock (next
);
709 /* Macro version of check_bit (). */
710 #define CHECK_BIT(X,P) ((((u_char *)(X))[(P) / 8]) >> (7 - ((P) % 8)) & 1)
713 ospf6_route_match_head (struct prefix
*prefix
,
714 struct ospf6_route_table
*table
)
716 struct route_node
*node
;
717 struct ospf6_route
*route
;
719 /* Walk down tree. */
720 node
= table
->table
->top
;
721 while (node
&& node
->p
.prefixlen
< prefix
->prefixlen
&&
722 prefix_match (&node
->p
, prefix
))
723 node
= node
->link
[CHECK_BIT(&prefix
->u
.prefix
, node
->p
.prefixlen
)];
726 route_lock_node (node
);
727 while (node
&& node
->info
== NULL
)
728 node
= route_next (node
);
731 route_unlock_node (node
);
733 if (! prefix_match (prefix
, &node
->p
))
737 ospf6_route_lock (route
);
742 ospf6_route_match_next (struct prefix
*prefix
,
743 struct ospf6_route
*route
)
745 struct ospf6_route
*next
;
747 next
= ospf6_route_next (route
);
748 if (next
&& ! prefix_match (prefix
, &next
->prefix
))
750 ospf6_route_unlock (next
);
758 ospf6_route_remove_all (struct ospf6_route_table
*table
)
760 struct ospf6_route
*route
;
761 for (route
= ospf6_route_head (table
); route
;
762 route
= ospf6_route_next (route
))
763 ospf6_route_remove (route
, table
);
766 struct ospf6_route_table
*
767 ospf6_route_table_create (int s
, int t
)
769 struct ospf6_route_table
*new;
770 new = XCALLOC (MTYPE_OSPF6_ROUTE
, sizeof (struct ospf6_route_table
));
771 new->table
= route_table_init ();
778 ospf6_route_table_delete (struct ospf6_route_table
*table
)
780 ospf6_route_remove_all (table
);
781 route_table_finish (table
->table
);
782 XFREE (MTYPE_OSPF6_ROUTE
, table
);
788 ospf6_route_show (struct vty
*vty
, struct ospf6_route
*route
)
791 char destination
[64], nexthop
[64];
792 char duration
[16], ifname
[IFNAMSIZ
];
793 struct timeval now
, res
;
795 quagga_gettime (QUAGGA_CLK_MONOTONIC
, &now
);
796 timersub (&now
, &route
->changed
, &res
);
797 timerstring (&res
, duration
, sizeof (duration
));
800 if (route
->type
== OSPF6_DEST_TYPE_LINKSTATE
)
801 ospf6_linkstate_prefix2str (&route
->prefix
, destination
,
802 sizeof (destination
));
803 else if (route
->type
== OSPF6_DEST_TYPE_ROUTER
)
804 inet_ntop (route
->prefix
.family
, &route
->prefix
.u
.prefix
,
805 destination
, sizeof (destination
));
807 prefix2str (&route
->prefix
, destination
, sizeof (destination
));
810 inet_ntop (AF_INET6
, &route
->nexthop
[0].address
, nexthop
,
812 if (! if_indextoname (route
->nexthop
[0].ifindex
, ifname
))
813 snprintf (ifname
, sizeof (ifname
), "%d", route
->nexthop
[0].ifindex
);
815 vty_out (vty
, "%c%1s %2s %-30s %-25s %6.*s %s%s",
816 (ospf6_route_is_best (route
) ? '*' : ' '),
817 OSPF6_DEST_TYPE_SUBSTR (route
->type
),
818 OSPF6_PATH_TYPE_SUBSTR (route
->path
.type
),
819 destination
, nexthop
, IFNAMSIZ
, ifname
, duration
, VNL
);
821 for (i
= 1; ospf6_nexthop_is_set (&route
->nexthop
[i
]) &&
822 i
< OSPF6_MULTI_PATH_LIMIT
; i
++)
825 inet_ntop (AF_INET6
, &route
->nexthop
[i
].address
, nexthop
,
827 if (! if_indextoname (route
->nexthop
[i
].ifindex
, ifname
))
828 snprintf (ifname
, sizeof (ifname
), "%d", route
->nexthop
[i
].ifindex
);
830 vty_out (vty
, "%c%1s %2s %-30s %-25s %6.*s %s%s",
831 ' ', "", "", "", nexthop
, IFNAMSIZ
, ifname
, "", VNL
);
836 ospf6_route_show_detail (struct vty
*vty
, struct ospf6_route
*route
)
838 char destination
[64], nexthop
[64], ifname
[IFNAMSIZ
];
839 char area_id
[16], id
[16], adv_router
[16], capa
[16], options
[16];
840 struct timeval now
, res
;
844 quagga_gettime (QUAGGA_CLK_MONOTONIC
, &now
);
847 if (route
->type
== OSPF6_DEST_TYPE_LINKSTATE
)
848 ospf6_linkstate_prefix2str (&route
->prefix
, destination
,
849 sizeof (destination
));
850 else if (route
->type
== OSPF6_DEST_TYPE_ROUTER
)
851 inet_ntop (route
->prefix
.family
, &route
->prefix
.u
.prefix
,
852 destination
, sizeof (destination
));
854 prefix2str (&route
->prefix
, destination
, sizeof (destination
));
855 vty_out (vty
, "Destination: %s%s", destination
, VNL
);
857 /* destination type */
858 vty_out (vty
, "Destination type: %s%s",
859 OSPF6_DEST_TYPE_NAME (route
->type
),
863 timersub (&now
, &route
->installed
, &res
);
864 timerstring (&res
, duration
, sizeof (duration
));
865 vty_out (vty
, "Installed Time: %s ago%s", duration
, VNL
);
867 timersub (&now
, &route
->changed
, &res
);
868 timerstring (&res
, duration
, sizeof (duration
));
869 vty_out (vty
, " Changed Time: %s ago%s", duration
, VNL
);
872 vty_out (vty
, "Lock: %d Flags: %s%s%s%s%s", route
->lock
,
873 (CHECK_FLAG (route
->flag
, OSPF6_ROUTE_BEST
) ? "B" : "-"),
874 (CHECK_FLAG (route
->flag
, OSPF6_ROUTE_ADD
) ? "A" : "-"),
875 (CHECK_FLAG (route
->flag
, OSPF6_ROUTE_REMOVE
) ? "R" : "-"),
876 (CHECK_FLAG (route
->flag
, OSPF6_ROUTE_CHANGE
) ? "C" : "-"),
878 vty_out (vty
, "Memory: prev: %p this: %p next: %p%s",
879 route
->prev
, route
, route
->next
, VNL
);
884 inet_ntop (AF_INET
, &route
->path
.area_id
, area_id
, sizeof (area_id
));
885 vty_out (vty
, "Associated Area: %s%s", area_id
, VNL
);
888 vty_out (vty
, "Path Type: %s%s",
889 OSPF6_PATH_TYPE_NAME (route
->path
.type
), VNL
);
892 inet_ntop (AF_INET
, &route
->path
.origin
.id
, id
, sizeof (id
));
893 inet_ntop (AF_INET
, &route
->path
.origin
.adv_router
, adv_router
,
894 sizeof (adv_router
));
895 vty_out (vty
, "LS Origin: %s Id: %s Adv: %s%s",
896 ospf6_lstype_name (route
->path
.origin
.type
),
897 id
, adv_router
, VNL
);
900 ospf6_options_printbuf (route
->path
.options
, options
, sizeof (options
));
901 vty_out (vty
, "Options: %s%s", options
, VNL
);
904 ospf6_capability_printbuf (route
->path
.router_bits
, capa
, sizeof (capa
));
905 vty_out (vty
, "Router Bits: %s%s", capa
, VNL
);
908 vty_out (vty
, "Prefix Options: xxx%s", VNL
);
911 vty_out (vty
, "Metric Type: %d%s", route
->path
.metric_type
,
913 vty_out (vty
, "Metric: %d (%d)%s",
914 route
->path
.cost
, route
->path
.cost_e2
, VNL
);
917 vty_out (vty
, "Nexthop:%s", VNL
);
918 for (i
= 0; ospf6_nexthop_is_set (&route
->nexthop
[i
]) &&
919 i
< OSPF6_MULTI_PATH_LIMIT
; i
++)
922 inet_ntop (AF_INET6
, &route
->nexthop
[i
].address
, nexthop
,
924 if (! if_indextoname (route
->nexthop
[i
].ifindex
, ifname
))
925 snprintf (ifname
, sizeof (ifname
), "%d", route
->nexthop
[i
].ifindex
);
926 vty_out (vty
, " %s %.*s%s", nexthop
, IFNAMSIZ
, ifname
, VNL
);
928 vty_out (vty
, "%s", VNL
);
932 ospf6_route_show_table_summary (struct vty
*vty
,
933 struct ospf6_route_table
*table
)
935 struct ospf6_route
*route
, *prev
= NULL
;
936 int i
, pathtype
[OSPF6_PATH_TYPE_MAX
];
937 unsigned int number
= 0;
938 int nhinval
= 0, ecmp
= 0;
939 int alternative
= 0, destination
= 0;
941 for (i
= 0; i
< OSPF6_PATH_TYPE_MAX
; i
++)
944 for (route
= ospf6_route_head (table
); route
;
945 route
= ospf6_route_next (route
))
947 if (prev
== NULL
|| ! ospf6_route_is_same (prev
, route
))
951 if (! ospf6_nexthop_is_set (&route
->nexthop
[0]))
953 else if (ospf6_nexthop_is_set (&route
->nexthop
[1]))
955 pathtype
[route
->path
.type
]++;
961 assert (number
== table
->count
);
963 vty_out (vty
, "Number of OSPFv3 routes: %d%s", number
, VNL
);
964 vty_out (vty
, "Number of Destination: %d%s", destination
, VNL
);
965 vty_out (vty
, "Number of Alternative routes: %d%s", alternative
, VNL
);
966 vty_out (vty
, "Number of Equal Cost Multi Path: %d%s", ecmp
, VNL
);
967 for (i
= OSPF6_PATH_TYPE_INTRA
; i
<= OSPF6_PATH_TYPE_EXTERNAL2
; i
++)
969 vty_out (vty
, "Number of %s routes: %d%s",
970 OSPF6_PATH_TYPE_NAME (i
), pathtype
[i
], VNL
);
975 ospf6_route_show_table_prefix (struct vty
*vty
,
976 struct prefix
*prefix
,
977 struct ospf6_route_table
*table
)
979 struct ospf6_route
*route
;
981 route
= ospf6_route_lookup (prefix
, table
);
985 ospf6_route_lock (route
);
986 while (route
&& ospf6_route_is_prefix (prefix
, route
))
988 /* Specifying a prefix will always display details */
989 ospf6_route_show_detail (vty
, route
);
990 route
= ospf6_route_next (route
);
993 ospf6_route_unlock (route
);
997 ospf6_route_show_table_address (struct vty
*vty
,
998 struct prefix
*prefix
,
999 struct ospf6_route_table
*table
)
1001 struct ospf6_route
*route
;
1003 route
= ospf6_route_lookup_bestmatch (prefix
, table
);
1007 prefix
= &route
->prefix
;
1008 ospf6_route_lock (route
);
1009 while (route
&& ospf6_route_is_prefix (prefix
, route
))
1011 /* Specifying a prefix will always display details */
1012 ospf6_route_show_detail (vty
, route
);
1013 route
= ospf6_route_next (route
);
1016 ospf6_route_unlock (route
);
1020 ospf6_route_show_table_match (struct vty
*vty
, int detail
,
1021 struct prefix
*prefix
,
1022 struct ospf6_route_table
*table
)
1024 struct ospf6_route
*route
;
1025 assert (prefix
->family
);
1027 route
= ospf6_route_match_head (prefix
, table
);
1031 ospf6_route_show_detail (vty
, route
);
1033 ospf6_route_show (vty
, route
);
1034 route
= ospf6_route_match_next (prefix
, route
);
1039 ospf6_route_show_table_type (struct vty
*vty
, int detail
, u_char type
,
1040 struct ospf6_route_table
*table
)
1042 struct ospf6_route
*route
;
1044 route
= ospf6_route_head (table
);
1047 if (route
->path
.type
== type
)
1050 ospf6_route_show_detail (vty
, route
);
1052 ospf6_route_show (vty
, route
);
1054 route
= ospf6_route_next (route
);
1059 ospf6_route_show_table (struct vty
*vty
, int detail
,
1060 struct ospf6_route_table
*table
)
1062 struct ospf6_route
*route
;
1064 route
= ospf6_route_head (table
);
1068 ospf6_route_show_detail (vty
, route
);
1070 ospf6_route_show (vty
, route
);
1071 route
= ospf6_route_next (route
);
1076 ospf6_route_table_show (struct vty
*vty
, int argc
, const char *argv
[],
1077 struct ospf6_route_table
*table
)
1085 struct prefix prefix
;
1088 memset (&prefix
, 0, sizeof (struct prefix
));
1090 for (i
= 0; i
< argc
; i
++)
1092 if (! strcmp (argv
[i
], "summary"))
1098 if (! strcmp (argv
[i
], "intra-area"))
1100 type
= OSPF6_PATH_TYPE_INTRA
;
1104 if (! strcmp (argv
[i
], "inter-area"))
1106 type
= OSPF6_PATH_TYPE_INTER
;
1110 if (! strcmp (argv
[i
], "external-1"))
1112 type
= OSPF6_PATH_TYPE_EXTERNAL1
;
1116 if (! strcmp (argv
[i
], "external-2"))
1118 type
= OSPF6_PATH_TYPE_EXTERNAL2
;
1122 if (! strcmp (argv
[i
], "detail"))
1128 if (! strcmp (argv
[i
], "match"))
1134 ret
= str2prefix (argv
[i
], &prefix
);
1135 if (ret
== 1 && prefix
.family
== AF_INET6
)
1138 if (strchr (argv
[i
], '/'))
1143 vty_out (vty
, "Malformed argument: %s%s", argv
[i
], VNL
);
1147 /* Give summary of this route table */
1150 ospf6_route_show_table_summary (vty
, table
);
1154 /* Give exact prefix-match route */
1155 if (isprefix
&& ! match
)
1157 /* If exact address, give best matching route */
1159 ospf6_route_show_table_address (vty
, &prefix
, table
);
1161 ospf6_route_show_table_prefix (vty
, &prefix
, table
);
1167 ospf6_route_show_table_match (vty
, detail
, &prefix
, table
);
1169 ospf6_route_show_table_type (vty
, detail
, type
, table
);
1171 ospf6_route_show_table (vty
, detail
, table
);
1177 ospf6_linkstate_show_header (struct vty
*vty
)
1179 vty_out (vty
, "%-7s %-15s %-15s %-8s %-14s %s%s",
1180 "Type", "Router-ID", "Net-ID", "Rtr-Bits", "Options", "Cost", VNL
);
1184 ospf6_linkstate_show (struct vty
*vty
, struct ospf6_route
*route
)
1186 u_int32_t router
, id
;
1187 char routername
[16], idname
[16], rbits
[16], options
[16];
1189 router
= ospf6_linkstate_prefix_adv_router (&route
->prefix
);
1190 inet_ntop (AF_INET
, &router
, routername
, sizeof (routername
));
1191 id
= ospf6_linkstate_prefix_id (&route
->prefix
);
1192 inet_ntop (AF_INET
, &id
, idname
, sizeof (idname
));
1194 ospf6_capability_printbuf (route
->path
.router_bits
, rbits
, sizeof (rbits
));
1195 ospf6_options_printbuf (route
->path
.options
, options
, sizeof (options
));
1198 vty_out (vty
, "%-7s %-15s %-15s %-8s %-14s %lu%s",
1199 "Network", routername
, idname
, rbits
, options
,
1200 (unsigned long) route
->path
.cost
, VNL
);
1202 vty_out (vty
, "%-7s %-15s %-15s %-8s %-14s %lu%s",
1203 "Router", routername
, idname
, rbits
, options
,
1204 (unsigned long) route
->path
.cost
, VNL
);
1209 ospf6_linkstate_show_table_exact (struct vty
*vty
,
1210 struct prefix
*prefix
,
1211 struct ospf6_route_table
*table
)
1213 struct ospf6_route
*route
;
1215 route
= ospf6_route_lookup (prefix
, table
);
1219 ospf6_route_lock (route
);
1220 while (route
&& ospf6_route_is_prefix (prefix
, route
))
1222 /* Specifying a prefix will always display details */
1223 ospf6_route_show_detail (vty
, route
);
1224 route
= ospf6_route_next (route
);
1227 ospf6_route_unlock (route
);
1231 ospf6_linkstate_show_table (struct vty
*vty
, int detail
,
1232 struct ospf6_route_table
*table
)
1234 struct ospf6_route
*route
;
1237 ospf6_linkstate_show_header (vty
);
1239 route
= ospf6_route_head (table
);
1243 ospf6_route_show_detail (vty
, route
);
1245 ospf6_linkstate_show (vty
, route
);
1246 route
= ospf6_route_next (route
);
1251 ospf6_linkstate_table_show (struct vty
*vty
, int argc
, const char *argv
[],
1252 struct ospf6_route_table
*table
)
1258 struct prefix router
, id
, prefix
;
1260 memset (&router
, 0, sizeof (struct prefix
));
1261 memset (&id
, 0, sizeof (struct prefix
));
1262 memset (&prefix
, 0, sizeof (struct prefix
));
1264 for (i
= 0; i
< argc
; i
++)
1266 if (! strcmp (argv
[i
], "detail"))
1274 ret
= str2prefix (argv
[i
], &router
);
1275 if (ret
== 1 && router
.family
== AF_INET
)
1280 vty_out (vty
, "Malformed argument: %s%s", argv
[i
], VNL
);
1286 ret
= str2prefix (argv
[i
], &id
);
1287 if (ret
== 1 && id
.family
== AF_INET
)
1292 vty_out (vty
, "Malformed argument: %s%s", argv
[i
], VNL
);
1296 vty_out (vty
, "Malformed argument: %s%s", argv
[i
], VNL
);
1301 ospf6_linkstate_prefix (router
.u
.prefix4
.s_addr
,
1302 id
.u
.prefix4
.s_addr
, &prefix
);
1305 ospf6_linkstate_show_table_exact (vty
, &prefix
, table
);
1307 ospf6_linkstate_show_table (vty
, detail
, table
);
1314 ospf6_brouter_show_header (struct vty
*vty
)
1316 vty_out (vty
, "%-15s %-8s %-14s %-10s %-15s%s",
1317 "Router-ID", "Rtr-Bits", "Options", "Path-Type", "Area", VNL
);
1321 ospf6_brouter_show (struct vty
*vty
, struct ospf6_route
*route
)
1323 u_int32_t adv_router
;
1324 char adv
[16], rbits
[16], options
[16], area
[16];
1326 adv_router
= ospf6_linkstate_prefix_adv_router (&route
->prefix
);
1327 inet_ntop (AF_INET
, &adv_router
, adv
, sizeof (adv
));
1328 ospf6_capability_printbuf (route
->path
.router_bits
, rbits
, sizeof (rbits
));
1329 ospf6_options_printbuf (route
->path
.options
, options
, sizeof (options
));
1330 inet_ntop (AF_INET
, &route
->path
.area_id
, area
, sizeof (area
));
1332 /* vty_out (vty, "%-15s %-8s %-14s %-10s %-15s%s",
1333 "Router-ID", "Rtr-Bits", "Options", "Path-Type", "Area", VNL); */
1334 vty_out (vty
, "%-15s %-8s %-14s %-10s %-15s%s",
1335 adv
, rbits
, options
, OSPF6_PATH_TYPE_NAME (route
->path
.type
),
1339 DEFUN (debug_ospf6_route
,
1340 debug_ospf6_route_cmd
,
1341 "debug ospf6 route (table|intra-area|inter-area)",
1344 "Debug route table calculation\n"
1346 "Debug intra-area route calculation\n"
1347 "Debug inter-area route calculation\n"
1350 unsigned char level
= 0;
1352 if (! strncmp (argv
[0], "table", 5))
1353 level
= OSPF6_DEBUG_ROUTE_TABLE
;
1354 else if (! strncmp (argv
[0], "intra", 5))
1355 level
= OSPF6_DEBUG_ROUTE_INTRA
;
1356 else if (! strncmp (argv
[0], "inter", 5))
1357 level
= OSPF6_DEBUG_ROUTE_INTER
;
1358 OSPF6_DEBUG_ROUTE_ON (level
);
1362 DEFUN (no_debug_ospf6_route
,
1363 no_debug_ospf6_route_cmd
,
1364 "no debug ospf6 route (table|intra-area|inter-area)",
1368 "Debug route table calculation\n"
1369 "Debug intra-area route calculation\n")
1371 unsigned char level
= 0;
1373 if (! strncmp (argv
[0], "table", 5))
1374 level
= OSPF6_DEBUG_ROUTE_TABLE
;
1375 else if (! strncmp (argv
[0], "intra", 5))
1376 level
= OSPF6_DEBUG_ROUTE_INTRA
;
1377 else if (! strncmp (argv
[0], "inter", 5))
1378 level
= OSPF6_DEBUG_ROUTE_INTER
;
1379 OSPF6_DEBUG_ROUTE_OFF (level
);
1384 config_write_ospf6_debug_route (struct vty
*vty
)
1386 if (IS_OSPF6_DEBUG_ROUTE (TABLE
))
1387 vty_out (vty
, "debug ospf6 route table%s", VNL
);
1388 if (IS_OSPF6_DEBUG_ROUTE (INTRA
))
1389 vty_out (vty
, "debug ospf6 route intra-area%s", VNL
);
1390 if (IS_OSPF6_DEBUG_ROUTE (INTER
))
1391 vty_out (vty
, "debug ospf6 route inter-area%s", VNL
);
1396 install_element_ospf6_debug_route (void)
1398 install_element (ENABLE_NODE
, &debug_ospf6_route_cmd
);
1399 install_element (ENABLE_NODE
, &no_debug_ospf6_route_cmd
);
1400 install_element (CONFIG_NODE
, &debug_ospf6_route_cmd
);
1401 install_element (CONFIG_NODE
, &no_debug_ospf6_route_cmd
);