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];
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 snprintf (buf
, size
, "%s(%lu)", adv_router_str
, (u_long
) ntohl (id
));
61 /* Global strings for logging */
62 char *ospf6_dest_type_str
[OSPF6_DEST_TYPE_MAX
] =
63 { "Unknown", "Router", "Network", "Discard", "Linkstate", };
65 char *ospf6_dest_type_substr
[OSPF6_DEST_TYPE_MAX
] =
66 { "?", "R", "N", "D", "L", };
68 char *ospf6_path_type_str
[OSPF6_PATH_TYPE_MAX
] =
69 { "Unknown", "Intra-Area", "Inter-Area", "External-1", "External-2", };
71 char *ospf6_path_type_substr
[OSPF6_PATH_TYPE_MAX
] =
72 { "??", "Ia", "Ie", "E1", "E2", };
78 struct ospf6_route
*route
;
79 route
= XCALLOC (MTYPE_OSPF6_ROUTE
, sizeof (struct ospf6_route
));
84 ospf6_route_delete (struct ospf6_route
*route
)
86 XFREE (MTYPE_OSPF6_ROUTE
, route
);
90 ospf6_route_copy (struct ospf6_route
*route
)
92 struct ospf6_route
*new;
94 new = ospf6_route_create ();
95 memcpy (new, route
, sizeof (struct ospf6_route
));
104 ospf6_route_lock (struct ospf6_route
*route
)
110 ospf6_route_unlock (struct ospf6_route
*route
)
112 assert (route
->lock
> 0);
114 if (route
->lock
== 0)
115 ospf6_route_delete (route
);
118 /* Route compare function. If ra is more preferred, it returns
119 less than 0. If rb is more preferred returns greater than 0.
120 Otherwise (neither one is preferred), returns 0 */
122 ospf6_route_cmp (struct ospf6_route
*ra
, struct ospf6_route
*rb
)
124 assert (ospf6_route_is_same (ra
, rb
));
125 assert (OSPF6_PATH_TYPE_NONE
< ra
->path
.type
&&
126 ra
->path
.type
< OSPF6_PATH_TYPE_MAX
);
127 assert (OSPF6_PATH_TYPE_NONE
< rb
->path
.type
&&
128 rb
->path
.type
< OSPF6_PATH_TYPE_MAX
);
130 if (ra
->type
!= rb
->type
)
131 return (ra
->type
- rb
->type
);
133 if (ra
->path
.area_id
!= rb
->path
.area_id
)
134 return (ntohl (ra
->path
.area_id
) - ntohl (rb
->path
.area_id
));
136 if (ra
->path
.type
!= rb
->path
.type
)
137 return (ra
->path
.type
- rb
->path
.type
);
139 if (ra
->path
.type
== OSPF6_PATH_TYPE_EXTERNAL2
)
141 if (ra
->path
.cost_e2
!= rb
->path
.cost_e2
)
142 return (ra
->path
.cost_e2
- rb
->path
.cost_e2
);
146 if (ra
->path
.cost
!= rb
->path
.cost
)
147 return (ra
->path
.cost
- rb
->path
.cost
);
154 ospf6_route_lookup (struct prefix
*prefix
,
155 struct ospf6_route_table
*table
)
157 struct route_node
*node
;
158 struct ospf6_route
*route
;
160 node
= route_node_lookup (table
->table
, prefix
);
164 route
= (struct ospf6_route
*) node
->info
;
169 ospf6_route_lookup_identical (struct ospf6_route
*route
,
170 struct ospf6_route_table
*table
)
172 struct ospf6_route
*target
;
174 for (target
= ospf6_route_lookup (&route
->prefix
, table
);
175 target
; target
= target
->next
)
177 if (ospf6_route_is_identical (target
, route
))
184 ospf6_route_lookup_bestmatch (struct prefix
*prefix
,
185 struct ospf6_route_table
*table
)
187 struct route_node
*node
;
188 struct ospf6_route
*route
;
190 node
= route_node_match (table
->table
, prefix
);
193 route_unlock_node (node
);
195 route
= (struct ospf6_route
*) node
->info
;
201 _route_count_assert (struct ospf6_route_table
*table
)
203 struct ospf6_route
*debug
;
205 for (debug
= ospf6_route_head (table
); debug
;
206 debug
= ospf6_route_next (debug
))
208 assert (num
== table
->count
);
210 #define ospf6_route_count_assert(t) (_route_count_assert (t))
212 #define ospf6_route_count_assert(t) ((void) 0)
216 ospf6_route_add (struct ospf6_route
*route
,
217 struct ospf6_route_table
*table
)
219 struct route_node
*node
, *nextnode
, *prevnode
;
220 struct ospf6_route
*current
= NULL
;
221 struct ospf6_route
*prev
= NULL
, *old
= NULL
, *next
= NULL
;
225 assert (route
->rnode
== NULL
);
226 assert (route
->lock
== 0);
227 assert (route
->next
== NULL
);
228 assert (route
->prev
== NULL
);
230 if (route
->type
== OSPF6_DEST_TYPE_LINKSTATE
)
231 ospf6_linkstate_prefix2str (&route
->prefix
, buf
, sizeof (buf
));
233 prefix2str (&route
->prefix
, buf
, sizeof (buf
));
235 if (IS_OSPF6_DEBUG_ROUTE (TABLE
))
236 zlog_info ("route add %s", buf
);
238 gettimeofday (&now
, NULL
);
240 node
= route_node_get (table
->table
, &route
->prefix
);
243 /* find place to insert */
244 for (current
= node
->info
; current
; current
= current
->next
)
246 if (! ospf6_route_is_same (current
, route
))
248 else if (current
->type
!= route
->type
)
250 else if (ospf6_route_is_same_origin (current
, route
))
252 else if (ospf6_route_cmp (current
, route
) > 0)
263 /* if route does not actually change, return unchanged */
264 if (ospf6_route_is_identical (old
, route
))
266 if (IS_OSPF6_DEBUG_ROUTE (TABLE
))
267 zlog_info (" identical route found, ignore");
269 ospf6_route_delete (route
);
270 SET_FLAG (old
->flag
, OSPF6_ROUTE_ADD
);
271 ospf6_route_count_assert (table
);
275 if (IS_OSPF6_DEBUG_ROUTE (TABLE
))
276 zlog_info (" old route found, replace");
278 /* replace old one if exists */
279 if (node
->info
== old
)
282 SET_FLAG (route
->flag
, OSPF6_ROUTE_BEST
);
286 old
->prev
->next
= route
;
287 route
->prev
= old
->prev
;
289 old
->next
->prev
= route
;
290 route
->next
= old
->next
;
292 route
->installed
= old
->installed
;
293 route
->changed
= now
;
295 ospf6_route_unlock (old
); /* will be deleted later */
296 ospf6_route_lock (route
);
298 SET_FLAG (route
->flag
, OSPF6_ROUTE_CHANGE
);
300 (*table
->hook_add
) (route
);
302 ospf6_route_count_assert (table
);
306 /* insert if previous or next node found */
309 if (IS_OSPF6_DEBUG_ROUTE (TABLE
))
310 zlog_info (" another path found, insert");
324 if (node
->info
== next
)
326 assert (next
->rnode
== node
);
328 UNSET_FLAG (next
->flag
, OSPF6_ROUTE_BEST
);
329 SET_FLAG (route
->flag
, OSPF6_ROUTE_BEST
);
332 route
->installed
= now
;
333 route
->changed
= now
;
335 ospf6_route_lock (route
);
338 SET_FLAG (route
->flag
, OSPF6_ROUTE_ADD
);
340 (*table
->hook_add
) (route
);
342 ospf6_route_count_assert (table
);
346 /* Else, this is the brand new route regarding to the prefix */
347 if (IS_OSPF6_DEBUG_ROUTE (TABLE
))
348 zlog_info (" brand new route, add");
350 assert (node
->info
== NULL
);
352 SET_FLAG (route
->flag
, OSPF6_ROUTE_BEST
);
353 ospf6_route_lock (route
);
354 route
->installed
= now
;
355 route
->changed
= now
;
357 /* lookup real existing next route */
359 route_lock_node (nextnode
);
361 nextnode
= route_next (nextnode
);
362 } while (nextnode
&& nextnode
->info
== NULL
);
365 if (nextnode
== NULL
)
369 route_unlock_node (nextnode
);
371 next
= nextnode
->info
;
376 /* lookup real existing prev route */
378 route_lock_node (prevnode
);
380 prevnode
= route_prev (prevnode
);
381 } while (prevnode
&& prevnode
->info
== NULL
);
384 if (prevnode
== NULL
)
388 route_unlock_node (prevnode
);
390 prev
= prevnode
->info
;
391 while (prev
->next
&& ospf6_route_is_same (prev
, prev
->next
))
399 SET_FLAG (route
->flag
, OSPF6_ROUTE_ADD
);
401 (*table
->hook_add
) (route
);
403 ospf6_route_count_assert (table
);
408 ospf6_route_remove (struct ospf6_route
*route
,
409 struct ospf6_route_table
*table
)
411 struct route_node
*node
;
412 struct ospf6_route
*current
;
415 if (route
->type
== OSPF6_DEST_TYPE_LINKSTATE
)
416 ospf6_linkstate_prefix2str (&route
->prefix
, buf
, sizeof (buf
));
418 prefix2str (&route
->prefix
, buf
, sizeof (buf
));
420 if (IS_OSPF6_DEBUG_ROUTE (TABLE
))
421 zlog_info ("route remove: %s", buf
);
423 node
= route_node_lookup (table
->table
, &route
->prefix
);
426 /* find the route to remove, making sure that the route pointer
427 is from the route table. */
428 current
= node
->info
;
429 while (current
&& ospf6_route_is_same (current
, route
))
431 if (current
== route
)
433 current
= current
->next
;
435 assert (current
== route
);
437 /* adjust doubly linked list */
439 route
->prev
->next
= route
->next
;
441 route
->next
->prev
= route
->prev
;
443 if (node
->info
== route
)
445 if (route
->next
&& ospf6_route_is_same (route
->next
, route
))
447 node
->info
= route
->next
;
448 SET_FLAG (route
->next
->flag
, OSPF6_ROUTE_BEST
);
451 node
->info
= NULL
; /* should unlock route_node here ? */
454 if (table
->hook_remove
)
455 (*table
->hook_remove
) (route
);
457 ospf6_route_unlock (route
);
460 ospf6_route_count_assert (table
);
464 ospf6_route_head (struct ospf6_route_table
*table
)
466 struct route_node
*node
;
467 struct ospf6_route
*route
;
469 node
= route_top (table
->table
);
473 /* skip to the real existing entry */
474 while (node
&& node
->info
== NULL
)
475 node
= route_next (node
);
479 route_unlock_node (node
);
482 route
= (struct ospf6_route
*) node
->info
;
483 assert (route
->prev
== NULL
);
484 ospf6_route_lock (route
);
489 ospf6_route_next (struct ospf6_route
*route
)
491 struct ospf6_route
*next
= route
->next
;
493 ospf6_route_unlock (route
);
495 ospf6_route_lock (next
);
501 ospf6_route_best_next (struct ospf6_route
*route
)
503 struct route_node
*rnode
;
504 struct ospf6_route
*next
;
506 rnode
= route
->rnode
;
507 route_lock_node (rnode
);
508 rnode
= route_next (rnode
);
509 while (rnode
&& rnode
->info
== NULL
)
510 rnode
= route_next (rnode
);
513 route_unlock_node (rnode
);
515 assert (rnode
->info
);
516 next
= (struct ospf6_route
*) rnode
->info
;
517 ospf6_route_unlock (route
);
518 ospf6_route_lock (next
);
522 /* Macro version of check_bit (). */
523 #define CHECK_BIT(X,P) ((((u_char *)(X))[(P) / 8]) >> (7 - ((P) % 8)) & 1)
526 ospf6_route_match_head (struct prefix
*prefix
,
527 struct ospf6_route_table
*table
)
529 struct route_node
*node
;
530 struct ospf6_route
*route
;
532 /* Walk down tree. */
533 node
= table
->table
->top
;
534 while (node
&& node
->p
.prefixlen
< prefix
->prefixlen
&&
535 prefix_match (&node
->p
, prefix
))
536 node
= node
->link
[CHECK_BIT(&prefix
->u
.prefix
, node
->p
.prefixlen
)];
539 route_lock_node (node
);
540 while (node
&& node
->info
== NULL
)
541 node
= route_next (node
);
544 route_unlock_node (node
);
546 if (! prefix_match (prefix
, &node
->p
))
550 ospf6_route_lock (route
);
555 ospf6_route_match_next (struct prefix
*prefix
,
556 struct ospf6_route
*route
)
558 struct ospf6_route
*next
;
560 next
= ospf6_route_next (route
);
561 if (next
&& ! prefix_match (prefix
, &next
->prefix
))
563 ospf6_route_unlock (next
);
571 ospf6_route_remove_all (struct ospf6_route_table
*table
)
573 struct ospf6_route
*route
;
574 for (route
= ospf6_route_head (table
); route
;
575 route
= ospf6_route_next (route
))
576 ospf6_route_remove (route
, table
);
579 struct ospf6_route_table
*
580 ospf6_route_table_create ()
582 struct ospf6_route_table
*new;
583 new = XCALLOC (MTYPE_OSPF6_ROUTE
, sizeof (struct ospf6_route_table
));
584 new->table
= route_table_init ();
589 ospf6_route_table_delete (struct ospf6_route_table
*table
)
591 ospf6_route_remove_all (table
);
592 route_table_finish (table
->table
);
593 XFREE (MTYPE_OSPF6_ROUTE
, table
);
600 ospf6_route_show (struct vty
*vty
, struct ospf6_route
*route
)
603 char destination
[64], nexthop
[64];
604 char duration
[16], ifname
[IFNAMSIZ
];
605 struct timeval now
, res
;
607 gettimeofday (&now
, (struct timezone
*) NULL
);
608 timersub (&now
, &route
->changed
, &res
);
609 timerstring (&res
, duration
, sizeof (duration
));
612 if (route
->type
== OSPF6_DEST_TYPE_LINKSTATE
)
613 ospf6_linkstate_prefix2str (&route
->prefix
, destination
,
614 sizeof (destination
));
615 else if (route
->type
== OSPF6_DEST_TYPE_ROUTER
)
616 inet_ntop (route
->prefix
.family
, &route
->prefix
.u
.prefix
,
617 destination
, sizeof (destination
));
619 prefix2str (&route
->prefix
, destination
, sizeof (destination
));
622 inet_ntop (AF_INET6
, &route
->nexthop
[0].address
, nexthop
,
624 if (! if_indextoname (route
->nexthop
[0].ifindex
, ifname
))
625 snprintf (ifname
, sizeof (ifname
), "%d", route
->nexthop
[0].ifindex
);
627 vty_out (vty
, "%c%1s %2s %-30s %-25s %6s %s%s",
628 (ospf6_route_is_best (route
) ? '*' : ' '),
629 OSPF6_DEST_TYPE_SUBSTR (route
->type
),
630 OSPF6_PATH_TYPE_SUBSTR (route
->path
.type
),
631 destination
, nexthop
, ifname
, duration
, VNL
);
633 for (i
= 1; ospf6_nexthop_is_set (&route
->nexthop
[i
]) &&
634 i
< OSPF6_MULTI_PATH_LIMIT
; i
++)
637 inet_ntop (AF_INET6
, &route
->nexthop
[i
].address
, nexthop
,
639 if (! if_indextoname (route
->nexthop
[i
].ifindex
, ifname
))
640 snprintf (ifname
, sizeof (ifname
), "%d", route
->nexthop
[i
].ifindex
);
642 vty_out (vty
, "%c%1s %2s %-30s %-25s %6s %s%s",
643 ' ', "", "", "", nexthop
, ifname
, "", VNL
);
648 ospf6_route_show_detail (struct vty
*vty
, struct ospf6_route
*route
)
650 char destination
[64], nexthop
[64], ifname
[IFNAMSIZ
];
651 char area_id
[16], id
[16], adv_router
[16], capa
[16], options
[16];
652 struct timeval now
, res
;
656 gettimeofday (&now
, (struct timezone
*) NULL
);
659 if (route
->type
== OSPF6_DEST_TYPE_LINKSTATE
)
660 ospf6_linkstate_prefix2str (&route
->prefix
, destination
,
661 sizeof (destination
));
662 else if (route
->type
== OSPF6_DEST_TYPE_ROUTER
)
663 inet_ntop (route
->prefix
.family
, &route
->prefix
.u
.prefix
,
664 destination
, sizeof (destination
));
666 prefix2str (&route
->prefix
, destination
, sizeof (destination
));
667 vty_out (vty
, "Destination: %s%s", destination
, VNL
);
669 /* destination type */
670 vty_out (vty
, "Destination type: %s%s",
671 OSPF6_DEST_TYPE_NAME (route
->type
),
675 timersub (&now
, &route
->installed
, &res
);
676 timerstring (&res
, duration
, sizeof (duration
));
677 vty_out (vty
, "Installed Time: %s ago%s", duration
, VNL
);
679 timersub (&now
, &route
->changed
, &res
);
680 timerstring (&res
, duration
, sizeof (duration
));
681 vty_out (vty
, " Changed Time: %s ago%s", duration
, VNL
);
684 vty_out (vty
, "Lock: %d Flags: %s%s%s%s%s", route
->lock
,
685 (CHECK_FLAG (route
->flag
, OSPF6_ROUTE_BEST
) ? "B" : "-"),
686 (CHECK_FLAG (route
->flag
, OSPF6_ROUTE_ADD
) ? "A" : "-"),
687 (CHECK_FLAG (route
->flag
, OSPF6_ROUTE_REMOVE
) ? "R" : "-"),
688 (CHECK_FLAG (route
->flag
, OSPF6_ROUTE_CHANGE
) ? "C" : "-"),
690 vty_out (vty
, "Memory: prev: %p this: %p next: %p%s",
691 route
->prev
, route
, route
->next
, VNL
);
696 inet_ntop (AF_INET
, &route
->path
.area_id
, area_id
, sizeof (area_id
));
697 vty_out (vty
, "Associated Area: %s%s", area_id
, VNL
);
700 vty_out (vty
, "Path Type: %s%s",
701 OSPF6_PATH_TYPE_NAME (route
->path
.type
), VNL
);
704 inet_ntop (AF_INET
, &route
->path
.origin
.id
, id
, sizeof (id
));
705 inet_ntop (AF_INET
, &route
->path
.origin
.adv_router
, adv_router
,
706 sizeof (adv_router
));
707 vty_out (vty
, "LS Origin: %s Id: %s Adv: %s%s",
708 OSPF6_LSTYPE_NAME (route
->path
.origin
.type
),
709 id
, adv_router
, VNL
);
712 ospf6_options_printbuf (route
->path
.options
, options
, sizeof (options
));
713 vty_out (vty
, "Options: %s%s", options
, VNL
);
716 ospf6_capability_printbuf (route
->path
.router_bits
, capa
, sizeof (capa
));
717 vty_out (vty
, "Router Bits: %s%s", capa
, VNL
);
720 vty_out (vty
, "Prefix Options: xxx%s", VNL
);
723 vty_out (vty
, "Metric Type: %d%s", route
->path
.metric_type
,
725 vty_out (vty
, "Metric: %d (%d)%s",
726 route
->path
.cost
, route
->path
.cost_e2
, VNL
);
729 vty_out (vty
, "Nexthop:%s", VNL
);
730 for (i
= 0; ospf6_nexthop_is_set (&route
->nexthop
[i
]) &&
731 i
< OSPF6_MULTI_PATH_LIMIT
; i
++)
734 inet_ntop (AF_INET6
, &route
->nexthop
[i
].address
, nexthop
,
736 if (! if_indextoname (route
->nexthop
[i
].ifindex
, ifname
))
737 snprintf (ifname
, sizeof (ifname
), "%d", route
->nexthop
[i
].ifindex
);
738 vty_out (vty
, " %s %s%s", nexthop
, ifname
, VNL
);
740 vty_out (vty
, "%s", VNL
);
744 ospf6_route_show_table_summary (struct vty
*vty
,
745 struct ospf6_route_table
*table
)
747 struct ospf6_route
*route
, *prev
= NULL
;
748 int i
, pathtype
[OSPF6_PATH_TYPE_MAX
];
750 int nhinval
= 0, ecmp
= 0;
751 int multipath
= 0, destination
= 0;
752 int desttype
= 0, desttype_mismatch
= 0;
754 for (i
= 0; i
< OSPF6_PATH_TYPE_MAX
; i
++)
757 for (route
= ospf6_route_head (table
); route
;
758 route
= ospf6_route_next (route
))
761 desttype
= route
->type
;
762 else if (desttype
!= route
->type
)
765 if (prev
== NULL
|| ! ospf6_route_is_same (prev
, route
))
770 if (! ospf6_nexthop_is_set (&route
->nexthop
[0]))
772 else if (ospf6_nexthop_is_set (&route
->nexthop
[1]))
775 if (prev
== NULL
|| ! ospf6_route_is_same (prev
, route
))
776 pathtype
[route
->path
.type
]++;
782 assert (number
== table
->count
);
783 vty_out (vty
, "Number of Destination: %d (%d routes)%s",
784 destination
, number
, VNL
);
786 vty_out (vty
, " Number of Multi-path: %d%s", multipath
, VNL
);
787 if (desttype_mismatch
)
788 vty_out (vty
, " Number of Different Dest-type: %d%s",
789 desttype_mismatch
, VNL
);
791 vty_out (vty
, " Number of Equal Cost Multi Path: %d%s",
794 vty_out (vty
, " Number of Invalid Nexthop: %d%s",
797 for (i
= 0; i
< OSPF6_PATH_TYPE_MAX
; i
++)
800 vty_out (vty
, " Number of %s routes: %d%s",
801 OSPF6_PATH_TYPE_NAME (i
), pathtype
[i
], VNL
);
806 ospf6_route_table_show (struct vty
*vty
, int argc
, char **argv
,
807 struct ospf6_route_table
*table
)
809 unsigned char flag
= 0;
815 struct prefix prefix
, *p
;
816 struct ospf6_route
*route
;
818 memset (&prefix
, 0, sizeof (struct prefix
));
820 for (i
= 0; i
< argc
; i
++)
823 if (! strcmp (argv
[i
], "summary"))
825 SET_FLAG (flag
, SUMMARY
);
830 if (! strcmp (argv
[i
], "detail"))
832 SET_FLAG (flag
, DETAIL
);
837 if (! strcmp (argv
[i
], "match"))
839 SET_FLAG (flag
, MATCH
);
845 vty_out (vty
, "Invalid argument: %s%s", argv
[i
], VNL
);
849 ret
= str2prefix (argv
[i
], &prefix
);
850 if (ret
!= 1 || prefix
.family
!= AF_INET6
)
852 vty_out (vty
, "Malformed argument: %s%s", argv
[i
], VNL
);
856 if (strchr (argv
[i
], '/'))
857 SET_FLAG (flag
, PREFIX
);
860 /* Give summary of this route table */
861 if (CHECK_FLAG (flag
, SUMMARY
))
863 ospf6_route_show_table_summary (vty
, table
);
867 /* Give exact prefix-match route */
868 if (prefix
.family
&& ! CHECK_FLAG (flag
, MATCH
))
870 /* If exact address, give best matching route */
871 if (! CHECK_FLAG (flag
, PREFIX
))
872 route
= ospf6_route_lookup_bestmatch (&prefix
, table
);
874 route
= ospf6_route_lookup (&prefix
, table
);
878 ospf6_route_lock (route
);
882 while (route
&& ospf6_route_is_prefix (p
, route
))
884 /* Seaching an entry will always display details */
886 ospf6_route_show_detail (vty
, route
);
888 route
= ospf6_route_next (route
);
894 if (prefix
.family
== 0)
895 route
= ospf6_route_head (table
);
897 route
= ospf6_route_match_head (&prefix
, table
);
901 if (CHECK_FLAG (flag
, DETAIL
))
902 ospf6_route_show_detail (vty
, route
);
904 ospf6_route_show (vty
, route
);
906 if (prefix
.family
== 0)
907 route
= ospf6_route_next (route
);
909 route
= ospf6_route_match_next (&prefix
, route
);
917 ospf6_lsentry_table_show (struct vty
*vty
, int argc
, char **argv
,
918 struct ospf6_route_table
*table
)
920 unsigned char flag
= 0;
924 struct prefix adv_router
, id
, prefix
;
925 struct ospf6_route
*route
;
927 memset (&adv_router
, 0, sizeof (struct prefix
));
928 memset (&id
, 0, sizeof (struct prefix
));
930 for (i
= 0; i
< argc
; i
++)
933 if (! strcmp (argv
[i
], "detail"))
935 SET_FLAG (flag
, DETAIL
);
940 if (! strcmp (argv
[i
], "match"))
942 SET_FLAG (flag
, MATCH
);
946 if (adv_router
.family
&& id
.family
)
948 vty_out (vty
, "Invalid argument: %s%s", argv
[i
], VNL
);
952 if (adv_router
.family
== 0)
954 ret
= str2prefix (argv
[i
], &adv_router
);
957 if (! strcmp (argv
[i
], "*"))
959 adv_router
.family
= AF_INET
;
960 adv_router
.prefixlen
= 0;
966 vty_out (vty
, "Invalid Router-ID: %s%s", argv
[i
], VNL
);
970 else if (id
.family
== 0)
975 ret
= str2prefix (argv
[i
], &id
);
978 val
= strtoul (argv
[i
], &endptr
, 0);
979 if (val
!= ULONG_MAX
&& *endptr
== '\0')
981 id
.u
.prefix4
.s_addr
= val
;
988 vty_out (vty
, "Invalid Link state ID: %s%s", argv
[i
],
995 /* Encode to linkstate prefix */
996 if (adv_router
.family
)
998 if (adv_router
.prefixlen
== 0 &&
999 id
.family
&& id
.prefixlen
!= IPV4_MAX_BITLEN
)
1001 vty_out (vty
, "Specifying Link State ID by prefix is not allowed%s"
1002 "when specifying Router-ID as wildcard%s",
1006 else if (adv_router
.prefixlen
!= 0 &&
1007 adv_router
.prefixlen
!= IPV4_MAX_BITLEN
&& id
.family
)
1009 vty_out (vty
, "Specifying Link State ID is not allowed%s"
1010 "when specifying Router-ID by prefix%s",
1015 if (adv_router
.prefixlen
== 0)
1016 ospf6_linkstate_prefix (0, id
.u
.prefix4
.s_addr
, &prefix
);
1017 else if (adv_router
.prefixlen
!= IPV4_MAX_BITLEN
)
1019 ospf6_linkstate_prefix (adv_router
.u
.prefix4
.s_addr
, 0, &prefix
);
1020 prefix
.prefixlen
= adv_router
.prefixlen
;
1021 SET_FLAG (flag
, MATCH
);
1025 ospf6_linkstate_prefix (adv_router
.u
.prefix4
.s_addr
,
1026 id
.u
.prefix4
.s_addr
, &prefix
);
1027 prefix
.prefixlen
= adv_router
.prefixlen
+ id
.prefixlen
;
1028 if (prefix
.prefixlen
!= 64)
1029 SET_FLAG (flag
, MATCH
);
1033 /* give exact match entry */
1034 if (adv_router
.family
&& adv_router
.prefixlen
== IPV4_MAX_BITLEN
&&
1035 id
.family
&& id
.prefixlen
== IPV4_MAX_BITLEN
)
1037 route
= ospf6_route_lookup (&prefix
, table
);
1039 ospf6_route_show_detail (vty
, route
);
1043 if (CHECK_FLAG (flag
, MATCH
))
1044 route
= ospf6_route_match_head (&prefix
, table
);
1046 route
= ospf6_route_head (table
);
1050 if (! adv_router
.family
||
1051 (CHECK_FLAG (flag
, MATCH
) &&
1052 prefix_match (&prefix
, &route
->prefix
)) ||
1053 (adv_router
.prefixlen
== 0 && id
.family
&&
1054 ospf6_linkstate_prefix_id (&prefix
) ==
1055 ospf6_linkstate_prefix_id (&route
->prefix
)))
1057 if (CHECK_FLAG (flag
, DETAIL
))
1058 ospf6_route_show_detail (vty
, route
);
1060 ospf6_route_show (vty
, route
);
1063 if (CHECK_FLAG (flag
, MATCH
))
1064 route
= ospf6_route_match_next (&prefix
, route
);
1066 route
= ospf6_route_next (route
);
1072 DEFUN (debug_ospf6_route
,
1073 debug_ospf6_route_cmd
,
1074 "debug ospf6 route (table|intra-area|inter-area)",
1077 "Debug route table calculation\n"
1079 "Debug intra-area route calculation\n"
1080 "Debug inter-area route calculation\n"
1083 unsigned char level
= 0;
1085 if (! strncmp (argv
[0], "table", 5))
1086 level
= OSPF6_DEBUG_ROUTE_TABLE
;
1087 else if (! strncmp (argv
[0], "intra", 5))
1088 level
= OSPF6_DEBUG_ROUTE_INTRA
;
1089 else if (! strncmp (argv
[0], "inter", 5))
1090 level
= OSPF6_DEBUG_ROUTE_INTER
;
1091 OSPF6_DEBUG_ROUTE_ON (level
);
1095 DEFUN (no_debug_ospf6_route
,
1096 no_debug_ospf6_route_cmd
,
1097 "no debug ospf6 route (table|intra-area|inter-area)",
1101 "Debug route table calculation\n"
1102 "Debug intra-area route calculation\n")
1104 unsigned char level
= 0;
1106 if (! strncmp (argv
[0], "table", 5))
1107 level
= OSPF6_DEBUG_ROUTE_TABLE
;
1108 else if (! strncmp (argv
[0], "intra", 5))
1109 level
= OSPF6_DEBUG_ROUTE_INTRA
;
1110 else if (! strncmp (argv
[0], "inter", 5))
1111 level
= OSPF6_DEBUG_ROUTE_INTER
;
1112 OSPF6_DEBUG_ROUTE_OFF (level
);
1117 config_write_ospf6_debug_route (struct vty
*vty
)
1119 if (IS_OSPF6_DEBUG_ROUTE (TABLE
))
1120 vty_out (vty
, "debug ospf6 route table%s", VNL
);
1121 if (IS_OSPF6_DEBUG_ROUTE (INTRA
))
1122 vty_out (vty
, "debug ospf6 route intra-area%s", VNL
);
1123 if (IS_OSPF6_DEBUG_ROUTE (INTER
))
1124 vty_out (vty
, "debug ospf6 route inter-area%s", VNL
);
1129 install_element_ospf6_debug_route ()
1131 install_element (ENABLE_NODE
, &debug_ospf6_route_cmd
);
1132 install_element (ENABLE_NODE
, &no_debug_ospf6_route_cmd
);
1133 install_element (CONFIG_NODE
, &debug_ospf6_route_cmd
);
1134 install_element (CONFIG_NODE
, &no_debug_ospf6_route_cmd
);