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.
31 #include "ospf6_proto.h"
32 #include "ospf6_lsa.h"
33 #include "ospf6_lsdb.h"
34 #include "ospf6_route.h"
37 unsigned char conf_debug_ospf6_route
= 0;
40 ospf6_linkstate_prefix (u_int32_t adv_router
, u_int32_t id
,
41 struct prefix
*prefix
)
43 memset (prefix
, 0, sizeof (struct prefix
));
44 prefix
->family
= AF_INET6
;
45 prefix
->prefixlen
= 64;
46 memcpy (&prefix
->u
.prefix6
.s6_addr
[0], &adv_router
, 4);
47 memcpy (&prefix
->u
.prefix6
.s6_addr
[4], &id
, 4);
51 ospf6_linkstate_prefix2str (struct prefix
*prefix
, char *buf
, int size
)
53 u_int32_t adv_router
, id
;
54 char adv_router_str
[16], id_str
[16];
55 memcpy (&adv_router
, &prefix
->u
.prefix6
.s6_addr
[0], 4);
56 memcpy (&id
, &prefix
->u
.prefix6
.s6_addr
[4], 4);
57 inet_ntop (AF_INET
, &adv_router
, adv_router_str
, sizeof (adv_router_str
));
58 inet_ntop (AF_INET
, &id
, id_str
, sizeof (id_str
));
60 snprintf (buf
, size
, "%s Net-ID: %s", adv_router_str
, id_str
);
62 snprintf (buf
, size
, "%s", adv_router_str
);
65 /* Global strings for logging */
66 char *ospf6_dest_type_str
[OSPF6_DEST_TYPE_MAX
] =
67 { "Unknown", "Router", "Network", "Discard", "Linkstate", "AddressRange", };
69 char *ospf6_dest_type_substr
[OSPF6_DEST_TYPE_MAX
] =
70 { "?", "R", "N", "D", "L", "A", };
72 char *ospf6_path_type_str
[OSPF6_PATH_TYPE_MAX
] =
73 { "Unknown", "Intra-Area", "Inter-Area", "External-1", "External-2", };
75 char *ospf6_path_type_substr
[OSPF6_PATH_TYPE_MAX
] =
76 { "??", "IA", "IE", "E1", "E2", };
82 struct ospf6_route
*route
;
83 route
= XCALLOC (MTYPE_OSPF6_ROUTE
, sizeof (struct ospf6_route
));
88 ospf6_route_delete (struct ospf6_route
*route
)
90 XFREE (MTYPE_OSPF6_ROUTE
, route
);
94 ospf6_route_copy (struct ospf6_route
*route
)
96 struct ospf6_route
*new;
98 new = ospf6_route_create ();
99 memcpy (new, route
, sizeof (struct ospf6_route
));
108 ospf6_route_lock (struct ospf6_route
*route
)
114 ospf6_route_unlock (struct ospf6_route
*route
)
116 assert (route
->lock
> 0);
118 if (route
->lock
== 0)
119 ospf6_route_delete (route
);
122 /* Route compare function. If ra is more preferred, it returns
123 less than 0. If rb is more preferred returns greater than 0.
124 Otherwise (neither one is preferred), returns 0 */
126 ospf6_route_cmp (struct ospf6_route
*ra
, struct ospf6_route
*rb
)
128 assert (ospf6_route_is_same (ra
, rb
));
129 assert (OSPF6_PATH_TYPE_NONE
< ra
->path
.type
&&
130 ra
->path
.type
< OSPF6_PATH_TYPE_MAX
);
131 assert (OSPF6_PATH_TYPE_NONE
< rb
->path
.type
&&
132 rb
->path
.type
< OSPF6_PATH_TYPE_MAX
);
134 if (ra
->type
!= rb
->type
)
135 return (ra
->type
- rb
->type
);
137 if (ra
->path
.area_id
!= rb
->path
.area_id
)
138 return (ntohl (ra
->path
.area_id
) - ntohl (rb
->path
.area_id
));
140 if (ra
->path
.type
!= rb
->path
.type
)
141 return (ra
->path
.type
- rb
->path
.type
);
143 if (ra
->path
.type
== OSPF6_PATH_TYPE_EXTERNAL2
)
145 if (ra
->path
.cost_e2
!= rb
->path
.cost_e2
)
146 return (ra
->path
.cost_e2
- rb
->path
.cost_e2
);
150 if (ra
->path
.cost
!= rb
->path
.cost
)
151 return (ra
->path
.cost
- rb
->path
.cost
);
158 ospf6_route_lookup (struct prefix
*prefix
,
159 struct ospf6_route_table
*table
)
161 struct route_node
*node
;
162 struct ospf6_route
*route
;
164 node
= route_node_lookup (table
->table
, prefix
);
168 route
= (struct ospf6_route
*) node
->info
;
173 ospf6_route_lookup_identical (struct ospf6_route
*route
,
174 struct ospf6_route_table
*table
)
176 struct ospf6_route
*target
;
178 for (target
= ospf6_route_lookup (&route
->prefix
, table
);
179 target
; target
= target
->next
)
181 if (ospf6_route_is_identical (target
, route
))
188 ospf6_route_lookup_bestmatch (struct prefix
*prefix
,
189 struct ospf6_route_table
*table
)
191 struct route_node
*node
;
192 struct ospf6_route
*route
;
194 node
= route_node_match (table
->table
, prefix
);
197 route_unlock_node (node
);
199 route
= (struct ospf6_route
*) node
->info
;
205 _route_count_assert (struct ospf6_route_table
*table
)
207 struct ospf6_route
*debug
;
210 for (debug
= ospf6_route_head (table
); debug
;
211 debug
= ospf6_route_next (debug
))
214 if (num
== table
->count
)
217 zlog_info ("PANIC !! table[%p]->count = %d, real = %d",
218 table
, table
->count
, num
);
219 for (debug
= ospf6_route_head (table
); debug
;
220 debug
= ospf6_route_next (debug
))
222 prefix2str (&debug
->prefix
, buf
, sizeof (buf
));
223 zlog_info ("%p %p %s", debug
->prev
, debug
->next
, buf
);
225 zlog_info ("DUMP END");
227 assert (num
== table
->count
);
229 #define ospf6_route_count_assert(t) (_route_count_assert (t))
231 #define ospf6_route_count_assert(t) ((void) 0)
235 ospf6_route_add (struct ospf6_route
*route
,
236 struct ospf6_route_table
*table
)
238 struct route_node
*node
, *nextnode
, *prevnode
;
239 struct ospf6_route
*current
= NULL
;
240 struct ospf6_route
*prev
= NULL
, *old
= NULL
, *next
= NULL
;
244 assert (route
->rnode
== NULL
);
245 assert (route
->lock
== 0);
246 assert (route
->next
== NULL
);
247 assert (route
->prev
== NULL
);
249 if (route
->type
== OSPF6_DEST_TYPE_LINKSTATE
)
250 ospf6_linkstate_prefix2str (&route
->prefix
, buf
, sizeof (buf
));
252 prefix2str (&route
->prefix
, buf
, sizeof (buf
));
254 if (IS_OSPF6_DEBUG_ROUTE (TABLE
))
255 zlog_info ("route add %s", buf
);
257 gettimeofday (&now
, NULL
);
259 node
= route_node_get (table
->table
, &route
->prefix
);
262 /* find place to insert */
263 for (current
= node
->info
; current
; current
= current
->next
)
265 if (! ospf6_route_is_same (current
, route
))
267 else if (current
->type
!= route
->type
)
269 else if (ospf6_route_is_same_origin (current
, route
))
271 else if (ospf6_route_cmp (current
, route
) > 0)
282 /* if route does not actually change, return unchanged */
283 if (ospf6_route_is_identical (old
, route
))
285 if (IS_OSPF6_DEBUG_ROUTE (TABLE
))
286 zlog_info (" identical route found, ignore");
288 ospf6_route_delete (route
);
289 SET_FLAG (old
->flag
, OSPF6_ROUTE_ADD
);
290 ospf6_route_count_assert (table
);
295 if (IS_OSPF6_DEBUG_ROUTE (TABLE
))
296 zlog_info (" old route found, replace");
298 /* replace old one if exists */
299 if (node
->info
== old
)
302 SET_FLAG (route
->flag
, OSPF6_ROUTE_BEST
);
306 old
->prev
->next
= route
;
307 route
->prev
= old
->prev
;
309 old
->next
->prev
= route
;
310 route
->next
= old
->next
;
312 route
->installed
= old
->installed
;
313 route
->changed
= now
;
315 ospf6_route_unlock (old
); /* will be deleted later */
316 ospf6_route_lock (route
);
318 SET_FLAG (route
->flag
, OSPF6_ROUTE_CHANGE
);
319 ospf6_route_count_assert (table
);
322 (*table
->hook_add
) (route
);
327 /* insert if previous or next node found */
330 if (IS_OSPF6_DEBUG_ROUTE (TABLE
))
331 zlog_info (" another path found, insert");
345 if (node
->info
== next
)
347 assert (next
->rnode
== node
);
349 UNSET_FLAG (next
->flag
, OSPF6_ROUTE_BEST
);
350 SET_FLAG (route
->flag
, OSPF6_ROUTE_BEST
);
353 route
->installed
= now
;
354 route
->changed
= now
;
356 ospf6_route_lock (route
);
358 ospf6_route_count_assert (table
);
360 SET_FLAG (route
->flag
, OSPF6_ROUTE_ADD
);
362 (*table
->hook_add
) (route
);
367 /* Else, this is the brand new route regarding to the prefix */
368 if (IS_OSPF6_DEBUG_ROUTE (TABLE
))
369 zlog_info (" brand new route, add");
371 assert (node
->info
== NULL
);
373 SET_FLAG (route
->flag
, OSPF6_ROUTE_BEST
);
374 ospf6_route_lock (route
);
375 route
->installed
= now
;
376 route
->changed
= now
;
378 /* lookup real existing next route */
380 route_lock_node (nextnode
);
382 nextnode
= route_next (nextnode
);
383 } while (nextnode
&& nextnode
->info
== NULL
);
386 if (nextnode
== NULL
)
390 route_unlock_node (nextnode
);
392 next
= nextnode
->info
;
397 /* lookup real existing prev route */
399 route_lock_node (prevnode
);
401 prevnode
= route_prev (prevnode
);
402 } while (prevnode
&& prevnode
->info
== NULL
);
405 if (prevnode
== NULL
)
409 route_unlock_node (prevnode
);
411 prev
= prevnode
->info
;
412 while (prev
->next
&& ospf6_route_is_same (prev
, prev
->next
))
419 ospf6_route_count_assert (table
);
421 SET_FLAG (route
->flag
, OSPF6_ROUTE_ADD
);
423 (*table
->hook_add
) (route
);
429 ospf6_route_remove (struct ospf6_route
*route
,
430 struct ospf6_route_table
*table
)
432 struct route_node
*node
;
433 struct ospf6_route
*current
;
436 if (route
->type
== OSPF6_DEST_TYPE_LINKSTATE
)
437 ospf6_linkstate_prefix2str (&route
->prefix
, buf
, sizeof (buf
));
439 prefix2str (&route
->prefix
, buf
, sizeof (buf
));
441 if (IS_OSPF6_DEBUG_ROUTE (TABLE
))
442 zlog_info ("route remove: %s", buf
);
444 node
= route_node_lookup (table
->table
, &route
->prefix
);
447 /* find the route to remove, making sure that the route pointer
448 is from the route table. */
449 current
= node
->info
;
450 while (current
&& ospf6_route_is_same (current
, route
))
452 if (current
== route
)
454 current
= current
->next
;
456 assert (current
== route
);
458 /* adjust doubly linked list */
460 route
->prev
->next
= route
->next
;
462 route
->next
->prev
= route
->prev
;
464 if (node
->info
== route
)
466 if (route
->next
&& ospf6_route_is_same (route
->next
, route
))
468 node
->info
= route
->next
;
469 SET_FLAG (route
->next
->flag
, OSPF6_ROUTE_BEST
);
472 node
->info
= NULL
; /* should unlock route_node here ? */
476 ospf6_route_count_assert (table
);
478 SET_FLAG (route
->flag
, OSPF6_ROUTE_WAS_REMOVED
);
480 if (table
->hook_remove
)
481 (*table
->hook_remove
) (route
);
483 ospf6_route_unlock (route
);
487 ospf6_route_head (struct ospf6_route_table
*table
)
489 struct route_node
*node
;
490 struct ospf6_route
*route
;
492 node
= route_top (table
->table
);
496 /* skip to the real existing entry */
497 while (node
&& node
->info
== NULL
)
498 node
= route_next (node
);
502 route_unlock_node (node
);
505 route
= (struct ospf6_route
*) node
->info
;
506 assert (route
->prev
== NULL
);
507 ospf6_route_lock (route
);
512 ospf6_route_next (struct ospf6_route
*route
)
514 struct ospf6_route
*next
= route
->next
;
516 ospf6_route_unlock (route
);
518 ospf6_route_lock (next
);
524 ospf6_route_best_next (struct ospf6_route
*route
)
526 struct route_node
*rnode
;
527 struct ospf6_route
*next
;
529 rnode
= route
->rnode
;
530 route_lock_node (rnode
);
531 rnode
= route_next (rnode
);
532 while (rnode
&& rnode
->info
== NULL
)
533 rnode
= route_next (rnode
);
536 route_unlock_node (rnode
);
538 assert (rnode
->info
);
539 next
= (struct ospf6_route
*) rnode
->info
;
540 ospf6_route_unlock (route
);
541 ospf6_route_lock (next
);
545 /* Macro version of check_bit (). */
546 #define CHECK_BIT(X,P) ((((u_char *)(X))[(P) / 8]) >> (7 - ((P) % 8)) & 1)
549 ospf6_route_match_head (struct prefix
*prefix
,
550 struct ospf6_route_table
*table
)
552 struct route_node
*node
;
553 struct ospf6_route
*route
;
555 /* Walk down tree. */
556 node
= table
->table
->top
;
557 while (node
&& node
->p
.prefixlen
< prefix
->prefixlen
&&
558 prefix_match (&node
->p
, prefix
))
559 node
= node
->link
[CHECK_BIT(&prefix
->u
.prefix
, node
->p
.prefixlen
)];
562 route_lock_node (node
);
563 while (node
&& node
->info
== NULL
)
564 node
= route_next (node
);
567 route_unlock_node (node
);
569 if (! prefix_match (prefix
, &node
->p
))
573 ospf6_route_lock (route
);
578 ospf6_route_match_next (struct prefix
*prefix
,
579 struct ospf6_route
*route
)
581 struct ospf6_route
*next
;
583 next
= ospf6_route_next (route
);
584 if (next
&& ! prefix_match (prefix
, &next
->prefix
))
586 ospf6_route_unlock (next
);
594 ospf6_route_remove_all (struct ospf6_route_table
*table
)
596 struct ospf6_route
*route
;
597 for (route
= ospf6_route_head (table
); route
;
598 route
= ospf6_route_next (route
))
599 ospf6_route_remove (route
, table
);
602 struct ospf6_route_table
*
603 ospf6_route_table_create ()
605 struct ospf6_route_table
*new;
606 new = XCALLOC (MTYPE_OSPF6_ROUTE
, sizeof (struct ospf6_route_table
));
607 new->table
= route_table_init ();
612 ospf6_route_table_delete (struct ospf6_route_table
*table
)
614 ospf6_route_remove_all (table
);
615 route_table_finish (table
->table
);
616 XFREE (MTYPE_OSPF6_ROUTE
, table
);
623 ospf6_route_show (struct vty
*vty
, struct ospf6_route
*route
)
626 char destination
[64], nexthop
[64];
627 char duration
[16], ifname
[IFNAMSIZ
];
628 struct timeval now
, res
;
630 gettimeofday (&now
, (struct timezone
*) NULL
);
631 timersub (&now
, &route
->changed
, &res
);
632 timerstring (&res
, duration
, sizeof (duration
));
635 if (route
->type
== OSPF6_DEST_TYPE_LINKSTATE
)
636 ospf6_linkstate_prefix2str (&route
->prefix
, destination
,
637 sizeof (destination
));
638 else if (route
->type
== OSPF6_DEST_TYPE_ROUTER
)
639 inet_ntop (route
->prefix
.family
, &route
->prefix
.u
.prefix
,
640 destination
, sizeof (destination
));
642 prefix2str (&route
->prefix
, destination
, sizeof (destination
));
645 inet_ntop (AF_INET6
, &route
->nexthop
[0].address
, nexthop
,
647 if (! if_indextoname (route
->nexthop
[0].ifindex
, ifname
))
648 snprintf (ifname
, sizeof (ifname
), "%d", route
->nexthop
[0].ifindex
);
650 vty_out (vty
, "%c%1s %2s %-30s %-25s %6s %s%s",
651 (ospf6_route_is_best (route
) ? '*' : ' '),
652 OSPF6_DEST_TYPE_SUBSTR (route
->type
),
653 OSPF6_PATH_TYPE_SUBSTR (route
->path
.type
),
654 destination
, nexthop
, ifname
, duration
, VNL
);
656 for (i
= 1; ospf6_nexthop_is_set (&route
->nexthop
[i
]) &&
657 i
< OSPF6_MULTI_PATH_LIMIT
; i
++)
660 inet_ntop (AF_INET6
, &route
->nexthop
[i
].address
, nexthop
,
662 if (! if_indextoname (route
->nexthop
[i
].ifindex
, ifname
))
663 snprintf (ifname
, sizeof (ifname
), "%d", route
->nexthop
[i
].ifindex
);
665 vty_out (vty
, "%c%1s %2s %-30s %-25s %6s %s%s",
666 ' ', "", "", "", nexthop
, ifname
, "", VNL
);
671 ospf6_route_show_detail (struct vty
*vty
, struct ospf6_route
*route
)
673 char destination
[64], nexthop
[64], ifname
[IFNAMSIZ
];
674 char area_id
[16], id
[16], adv_router
[16], capa
[16], options
[16];
675 struct timeval now
, res
;
679 gettimeofday (&now
, (struct timezone
*) NULL
);
682 if (route
->type
== OSPF6_DEST_TYPE_LINKSTATE
)
683 ospf6_linkstate_prefix2str (&route
->prefix
, destination
,
684 sizeof (destination
));
685 else if (route
->type
== OSPF6_DEST_TYPE_ROUTER
)
686 inet_ntop (route
->prefix
.family
, &route
->prefix
.u
.prefix
,
687 destination
, sizeof (destination
));
689 prefix2str (&route
->prefix
, destination
, sizeof (destination
));
690 vty_out (vty
, "Destination: %s%s", destination
, VNL
);
692 /* destination type */
693 vty_out (vty
, "Destination type: %s%s",
694 OSPF6_DEST_TYPE_NAME (route
->type
),
698 timersub (&now
, &route
->installed
, &res
);
699 timerstring (&res
, duration
, sizeof (duration
));
700 vty_out (vty
, "Installed Time: %s ago%s", duration
, VNL
);
702 timersub (&now
, &route
->changed
, &res
);
703 timerstring (&res
, duration
, sizeof (duration
));
704 vty_out (vty
, " Changed Time: %s ago%s", duration
, VNL
);
707 vty_out (vty
, "Lock: %d Flags: %s%s%s%s%s", route
->lock
,
708 (CHECK_FLAG (route
->flag
, OSPF6_ROUTE_BEST
) ? "B" : "-"),
709 (CHECK_FLAG (route
->flag
, OSPF6_ROUTE_ADD
) ? "A" : "-"),
710 (CHECK_FLAG (route
->flag
, OSPF6_ROUTE_REMOVE
) ? "R" : "-"),
711 (CHECK_FLAG (route
->flag
, OSPF6_ROUTE_CHANGE
) ? "C" : "-"),
713 vty_out (vty
, "Memory: prev: %p this: %p next: %p%s",
714 route
->prev
, route
, route
->next
, VNL
);
719 inet_ntop (AF_INET
, &route
->path
.area_id
, area_id
, sizeof (area_id
));
720 vty_out (vty
, "Associated Area: %s%s", area_id
, VNL
);
723 vty_out (vty
, "Path Type: %s%s",
724 OSPF6_PATH_TYPE_NAME (route
->path
.type
), VNL
);
727 inet_ntop (AF_INET
, &route
->path
.origin
.id
, id
, sizeof (id
));
728 inet_ntop (AF_INET
, &route
->path
.origin
.adv_router
, adv_router
,
729 sizeof (adv_router
));
730 vty_out (vty
, "LS Origin: %s Id: %s Adv: %s%s",
731 ospf6_lstype_name (route
->path
.origin
.type
),
732 id
, adv_router
, VNL
);
735 ospf6_options_printbuf (route
->path
.options
, options
, sizeof (options
));
736 vty_out (vty
, "Options: %s%s", options
, VNL
);
739 ospf6_capability_printbuf (route
->path
.router_bits
, capa
, sizeof (capa
));
740 vty_out (vty
, "Router Bits: %s%s", capa
, VNL
);
743 vty_out (vty
, "Prefix Options: xxx%s", VNL
);
746 vty_out (vty
, "Metric Type: %d%s", route
->path
.metric_type
,
748 vty_out (vty
, "Metric: %d (%d)%s",
749 route
->path
.cost
, route
->path
.cost_e2
, VNL
);
752 vty_out (vty
, "Nexthop:%s", VNL
);
753 for (i
= 0; ospf6_nexthop_is_set (&route
->nexthop
[i
]) &&
754 i
< OSPF6_MULTI_PATH_LIMIT
; i
++)
757 inet_ntop (AF_INET6
, &route
->nexthop
[i
].address
, nexthop
,
759 if (! if_indextoname (route
->nexthop
[i
].ifindex
, ifname
))
760 snprintf (ifname
, sizeof (ifname
), "%d", route
->nexthop
[i
].ifindex
);
761 vty_out (vty
, " %s %s%s", nexthop
, ifname
, VNL
);
763 vty_out (vty
, "%s", VNL
);
767 ospf6_route_show_table_summary (struct vty
*vty
,
768 struct ospf6_route_table
*table
)
770 struct ospf6_route
*route
, *prev
= NULL
;
771 int i
, pathtype
[OSPF6_PATH_TYPE_MAX
];
773 int nhinval
= 0, ecmp
= 0;
774 int alternative
= 0, destination
= 0;
776 for (i
= 0; i
< OSPF6_PATH_TYPE_MAX
; i
++)
779 for (route
= ospf6_route_head (table
); route
;
780 route
= ospf6_route_next (route
))
782 if (prev
== NULL
|| ! ospf6_route_is_same (prev
, route
))
786 if (! ospf6_nexthop_is_set (&route
->nexthop
[0]))
788 else if (ospf6_nexthop_is_set (&route
->nexthop
[1]))
790 pathtype
[route
->path
.type
]++;
796 assert (number
== table
->count
);
798 vty_out (vty
, "Number of OSPFv3 routes: %d%s", number
, VNL
);
799 vty_out (vty
, "Number of Destination: %d%s", destination
, VNL
);
800 vty_out (vty
, "Number of Alternative routes: %d%s", alternative
, VNL
);
801 vty_out (vty
, "Number of Equal Cost Multi Path: %d%s", ecmp
, VNL
);
802 for (i
= OSPF6_PATH_TYPE_INTRA
; i
<= OSPF6_PATH_TYPE_EXTERNAL2
; i
++)
804 vty_out (vty
, "Number of %s routes: %d%s",
805 OSPF6_PATH_TYPE_NAME (i
), pathtype
[i
], VNL
);
810 ospf6_route_show_table_prefix (struct vty
*vty
,
811 struct prefix
*prefix
,
812 struct ospf6_route_table
*table
)
814 struct ospf6_route
*route
;
816 route
= ospf6_route_lookup (prefix
, table
);
820 ospf6_route_lock (route
);
821 while (route
&& ospf6_route_is_prefix (prefix
, route
))
823 /* Specifying a prefix will always display details */
824 ospf6_route_show_detail (vty
, route
);
825 route
= ospf6_route_next (route
);
828 ospf6_route_unlock (route
);
832 ospf6_route_show_table_address (struct vty
*vty
,
833 struct prefix
*prefix
,
834 struct ospf6_route_table
*table
)
836 struct ospf6_route
*route
;
838 route
= ospf6_route_lookup_bestmatch (prefix
, table
);
842 prefix
= &route
->prefix
;
843 ospf6_route_lock (route
);
844 while (route
&& ospf6_route_is_prefix (prefix
, route
))
846 /* Specifying a prefix will always display details */
847 ospf6_route_show_detail (vty
, route
);
848 route
= ospf6_route_next (route
);
851 ospf6_route_unlock (route
);
855 ospf6_route_show_table_match (struct vty
*vty
, int detail
,
856 struct prefix
*prefix
,
857 struct ospf6_route_table
*table
)
859 struct ospf6_route
*route
;
860 assert (prefix
->family
);
862 route
= ospf6_route_match_head (prefix
, table
);
866 ospf6_route_show_detail (vty
, route
);
868 ospf6_route_show (vty
, route
);
869 route
= ospf6_route_match_next (prefix
, route
);
874 ospf6_route_show_table_type (struct vty
*vty
, int detail
, u_char type
,
875 struct ospf6_route_table
*table
)
877 struct ospf6_route
*route
;
879 route
= ospf6_route_head (table
);
882 if (route
->path
.type
== type
)
885 ospf6_route_show_detail (vty
, route
);
887 ospf6_route_show (vty
, route
);
889 route
= ospf6_route_next (route
);
894 ospf6_route_show_table (struct vty
*vty
, int detail
,
895 struct ospf6_route_table
*table
)
897 struct ospf6_route
*route
;
899 route
= ospf6_route_head (table
);
903 ospf6_route_show_detail (vty
, route
);
905 ospf6_route_show (vty
, route
);
906 route
= ospf6_route_next (route
);
911 ospf6_route_table_show (struct vty
*vty
, int argc
, char **argv
,
912 struct ospf6_route_table
*table
)
920 struct prefix prefix
;
923 memset (&prefix
, 0, sizeof (struct prefix
));
925 for (i
= 0; i
< argc
; i
++)
927 if (! strcmp (argv
[i
], "summary"))
933 if (! strcmp (argv
[i
], "intra-area"))
935 type
= OSPF6_PATH_TYPE_INTRA
;
939 if (! strcmp (argv
[i
], "inter-area"))
941 type
= OSPF6_PATH_TYPE_INTER
;
945 if (! strcmp (argv
[i
], "external-1"))
947 type
= OSPF6_PATH_TYPE_EXTERNAL1
;
951 if (! strcmp (argv
[i
], "external-2"))
953 type
= OSPF6_PATH_TYPE_EXTERNAL2
;
957 if (! strcmp (argv
[i
], "detail"))
963 if (! strcmp (argv
[i
], "match"))
969 ret
= str2prefix (argv
[i
], &prefix
);
970 if (ret
== 1 && prefix
.family
== AF_INET6
)
973 if (strchr (argv
[i
], '/'))
978 vty_out (vty
, "Malformed argument: %s%s", argv
[i
], VNL
);
982 /* Give summary of this route table */
985 ospf6_route_show_table_summary (vty
, table
);
989 /* Give exact prefix-match route */
990 if (isprefix
&& ! match
)
992 /* If exact address, give best matching route */
994 ospf6_route_show_table_address (vty
, &prefix
, table
);
996 ospf6_route_show_table_prefix (vty
, &prefix
, table
);
1002 ospf6_route_show_table_match (vty
, detail
, &prefix
, table
);
1004 ospf6_route_show_table_type (vty
, detail
, type
, table
);
1006 ospf6_route_show_table (vty
, detail
, table
);
1012 ospf6_linkstate_show_header (struct vty
*vty
)
1014 vty_out (vty
, "%-7s %-15s %-15s %-8s %-14s %s%s",
1015 "Type", "Router-ID", "Net-ID", "Rtr-Bits", "Options", "Cost", VNL
);
1019 ospf6_linkstate_show (struct vty
*vty
, struct ospf6_route
*route
)
1021 u_int32_t router
, id
;
1022 char routername
[16], idname
[16], rbits
[16], options
[16];
1024 router
= ospf6_linkstate_prefix_adv_router (&route
->prefix
);
1025 inet_ntop (AF_INET
, &router
, routername
, sizeof (routername
));
1026 id
= ospf6_linkstate_prefix_id (&route
->prefix
);
1027 inet_ntop (AF_INET
, &id
, idname
, sizeof (idname
));
1029 ospf6_capability_printbuf (route
->path
.router_bits
, rbits
, sizeof (rbits
));
1030 ospf6_options_printbuf (route
->path
.options
, options
, sizeof (options
));
1033 vty_out (vty
, "%-7s %-15s %-15s %-8s %-14s %lu%s",
1034 "Network", routername
, idname
, rbits
, options
,
1035 (unsigned long) route
->path
.cost
, VNL
);
1037 vty_out (vty
, "%-7s %-15s %-15s %-8s %-14s %lu%s",
1038 "Router", routername
, idname
, rbits
, options
,
1039 (unsigned long) route
->path
.cost
, VNL
);
1044 ospf6_linkstate_show_table_exact (struct vty
*vty
,
1045 struct prefix
*prefix
,
1046 struct ospf6_route_table
*table
)
1048 struct ospf6_route
*route
;
1050 route
= ospf6_route_lookup (prefix
, table
);
1054 ospf6_route_lock (route
);
1055 while (route
&& ospf6_route_is_prefix (prefix
, route
))
1057 /* Specifying a prefix will always display details */
1058 ospf6_route_show_detail (vty
, route
);
1059 route
= ospf6_route_next (route
);
1062 ospf6_route_unlock (route
);
1066 ospf6_linkstate_show_table (struct vty
*vty
, int detail
,
1067 struct ospf6_route_table
*table
)
1069 struct ospf6_route
*route
;
1072 ospf6_linkstate_show_header (vty
);
1074 route
= ospf6_route_head (table
);
1078 ospf6_route_show_detail (vty
, route
);
1080 ospf6_linkstate_show (vty
, route
);
1081 route
= ospf6_route_next (route
);
1086 ospf6_linkstate_table_show (struct vty
*vty
, int argc
, char **argv
,
1087 struct ospf6_route_table
*table
)
1093 struct prefix router
, id
, prefix
;
1095 memset (&router
, 0, sizeof (struct prefix
));
1096 memset (&id
, 0, sizeof (struct prefix
));
1097 memset (&prefix
, 0, sizeof (struct prefix
));
1099 for (i
= 0; i
< argc
; i
++)
1101 if (! strcmp (argv
[i
], "detail"))
1109 ret
= str2prefix (argv
[i
], &router
);
1110 if (ret
== 1 && router
.family
== AF_INET
)
1115 vty_out (vty
, "Malformed argument: %s%s", argv
[i
], VNL
);
1121 ret
= str2prefix (argv
[i
], &id
);
1122 if (ret
== 1 && id
.family
== AF_INET
)
1127 vty_out (vty
, "Malformed argument: %s%s", argv
[i
], VNL
);
1131 vty_out (vty
, "Malformed argument: %s%s", argv
[i
], VNL
);
1136 ospf6_linkstate_prefix (router
.u
.prefix4
.s_addr
,
1137 id
.u
.prefix4
.s_addr
, &prefix
);
1140 ospf6_linkstate_show_table_exact (vty
, &prefix
, table
);
1142 ospf6_linkstate_show_table (vty
, detail
, table
);
1149 ospf6_brouter_show_header (struct vty
*vty
)
1151 vty_out (vty
, "%-15s %-8s %-14s %-10s %-15s%s",
1152 "Router-ID", "Rtr-Bits", "Options", "Path-Type", "Area", VNL
);
1156 ospf6_brouter_show (struct vty
*vty
, struct ospf6_route
*route
)
1158 u_int32_t adv_router
;
1159 char adv
[16], rbits
[16], options
[16], area
[16];
1161 adv_router
= ospf6_linkstate_prefix_adv_router (&route
->prefix
);
1162 inet_ntop (AF_INET
, &adv_router
, adv
, sizeof (adv
));
1163 ospf6_capability_printbuf (route
->path
.router_bits
, rbits
, sizeof (rbits
));
1164 ospf6_options_printbuf (route
->path
.options
, options
, sizeof (options
));
1165 inet_ntop (AF_INET
, &route
->path
.area_id
, area
, sizeof (area
));
1167 /* vty_out (vty, "%-15s %-8s %-14s %-10s %-15s%s",
1168 "Router-ID", "Rtr-Bits", "Options", "Path-Type", "Area", VNL); */
1169 vty_out (vty
, "%-15s %-8s %-14s %-10s %-15s%s",
1170 adv
, rbits
, options
, OSPF6_PATH_TYPE_NAME (route
->path
.type
),
1174 DEFUN (debug_ospf6_route
,
1175 debug_ospf6_route_cmd
,
1176 "debug ospf6 route (table|intra-area|inter-area)",
1179 "Debug route table calculation\n"
1181 "Debug intra-area route calculation\n"
1182 "Debug inter-area route calculation\n"
1185 unsigned char level
= 0;
1187 if (! strncmp (argv
[0], "table", 5))
1188 level
= OSPF6_DEBUG_ROUTE_TABLE
;
1189 else if (! strncmp (argv
[0], "intra", 5))
1190 level
= OSPF6_DEBUG_ROUTE_INTRA
;
1191 else if (! strncmp (argv
[0], "inter", 5))
1192 level
= OSPF6_DEBUG_ROUTE_INTER
;
1193 OSPF6_DEBUG_ROUTE_ON (level
);
1197 DEFUN (no_debug_ospf6_route
,
1198 no_debug_ospf6_route_cmd
,
1199 "no debug ospf6 route (table|intra-area|inter-area)",
1203 "Debug route table calculation\n"
1204 "Debug intra-area route calculation\n")
1206 unsigned char level
= 0;
1208 if (! strncmp (argv
[0], "table", 5))
1209 level
= OSPF6_DEBUG_ROUTE_TABLE
;
1210 else if (! strncmp (argv
[0], "intra", 5))
1211 level
= OSPF6_DEBUG_ROUTE_INTRA
;
1212 else if (! strncmp (argv
[0], "inter", 5))
1213 level
= OSPF6_DEBUG_ROUTE_INTER
;
1214 OSPF6_DEBUG_ROUTE_OFF (level
);
1219 config_write_ospf6_debug_route (struct vty
*vty
)
1221 if (IS_OSPF6_DEBUG_ROUTE (TABLE
))
1222 vty_out (vty
, "debug ospf6 route table%s", VNL
);
1223 if (IS_OSPF6_DEBUG_ROUTE (INTRA
))
1224 vty_out (vty
, "debug ospf6 route intra-area%s", VNL
);
1225 if (IS_OSPF6_DEBUG_ROUTE (INTER
))
1226 vty_out (vty
, "debug ospf6 route inter-area%s", VNL
);
1231 install_element_ospf6_debug_route ()
1233 install_element (ENABLE_NODE
, &debug_ospf6_route_cmd
);
1234 install_element (ENABLE_NODE
, &no_debug_ospf6_route_cmd
);
1235 install_element (CONFIG_NODE
, &debug_ospf6_route_cmd
);
1236 install_element (CONFIG_NODE
, &no_debug_ospf6_route_cmd
);