]> git.proxmox.com Git - mirror_frr.git/blob - ospf6d/ospf6_route.c
Merge remote-tracking branch 'origin/cmaster' into cmaster-next
[mirror_frr.git] / ospf6d / ospf6_route.c
1 /*
2 * Copyright (C) 2003 Yasuhiro Ohara
3 *
4 * This file is part of GNU Zebra.
5 *
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
9 * later version.
10 *
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.
15 *
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.
20 */
21
22 #include <zebra.h>
23
24 #include "log.h"
25 #include "memory.h"
26 #include "prefix.h"
27 #include "table.h"
28 #include "vty.h"
29 #include "command.h"
30 #include "linklist.h"
31
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"
39 #include "ospf6d.h"
40 #include "ospf6_zebra.h"
41
42 unsigned char conf_debug_ospf6_route = 0;
43
44 static char *
45 ospf6_route_table_name (struct ospf6_route_table *table)
46 {
47 static char name[32];
48 switch (table->scope_type)
49 {
50 case OSPF6_SCOPE_TYPE_GLOBAL:
51 {
52 switch (table->table_type)
53 {
54 case OSPF6_TABLE_TYPE_ROUTES:
55 snprintf (name, sizeof (name), "global route table");
56 break;
57 case OSPF6_TABLE_TYPE_BORDER_ROUTERS:
58 snprintf (name, sizeof (name), "global brouter table");
59 break;
60 case OSPF6_TABLE_TYPE_EXTERNAL_ROUTES:
61 snprintf (name, sizeof (name), "global external table");
62 break;
63 default:
64 snprintf (name, sizeof (name), "global unknown table");
65 break;
66 }
67 }
68 break;
69
70 case OSPF6_SCOPE_TYPE_AREA:
71 {
72 struct ospf6_area *oa = (struct ospf6_area *) table->scope;
73 switch (table->table_type)
74 {
75 case OSPF6_TABLE_TYPE_SPF_RESULTS:
76 snprintf (name, sizeof (name),
77 "area %s spf table", oa->name);
78 break;
79 case OSPF6_TABLE_TYPE_ROUTES:
80 snprintf (name, sizeof (name),
81 "area %s route table", oa->name);
82 break;
83 case OSPF6_TABLE_TYPE_PREFIX_RANGES:
84 snprintf (name, sizeof (name),
85 "area %s range table", oa->name);
86 break;
87 case OSPF6_TABLE_TYPE_SUMMARY_PREFIXES:
88 snprintf (name, sizeof (name),
89 "area %s summary prefix table", oa->name);
90 break;
91 case OSPF6_TABLE_TYPE_SUMMARY_ROUTERS:
92 snprintf (name, sizeof (name),
93 "area %s summary router table", oa->name);
94 break;
95 default:
96 snprintf (name, sizeof (name),
97 "area %s unknown table", oa->name);
98 break;
99 }
100 }
101 break;
102
103 case OSPF6_SCOPE_TYPE_INTERFACE:
104 {
105 struct ospf6_interface *oi = (struct ospf6_interface *) table->scope;
106 switch (table->table_type)
107 {
108 case OSPF6_TABLE_TYPE_CONNECTED_ROUTES:
109 snprintf (name, sizeof (name), "interface %s connected table",
110 oi->interface->name);
111 break;
112 default:
113 snprintf (name, sizeof (name), "interface %s unknown table",
114 oi->interface->name);
115 break;
116 }
117 }
118 break;
119
120 default:
121 {
122 switch (table->table_type)
123 {
124 case OSPF6_TABLE_TYPE_SPF_RESULTS:
125 snprintf (name, sizeof (name), "temporary spf table");
126 break;
127 default:
128 snprintf (name, sizeof (name), "temporary unknown table");
129 break;
130 }
131 }
132 break;
133 }
134 return name;
135 }
136
137 void
138 ospf6_linkstate_prefix (u_int32_t adv_router, u_int32_t id,
139 struct prefix *prefix)
140 {
141 memset (prefix, 0, sizeof (struct prefix));
142 prefix->family = AF_INET6;
143 prefix->prefixlen = 64;
144 memcpy (&prefix->u.prefix6.s6_addr[0], &adv_router, 4);
145 memcpy (&prefix->u.prefix6.s6_addr[4], &id, 4);
146 }
147
148 void
149 ospf6_linkstate_prefix2str (struct prefix *prefix, char *buf, int size)
150 {
151 u_int32_t adv_router, id;
152 char adv_router_str[16], id_str[16];
153 memcpy (&adv_router, &prefix->u.prefix6.s6_addr[0], 4);
154 memcpy (&id, &prefix->u.prefix6.s6_addr[4], 4);
155 inet_ntop (AF_INET, &adv_router, adv_router_str, sizeof (adv_router_str));
156 inet_ntop (AF_INET, &id, id_str, sizeof (id_str));
157 if (ntohl (id))
158 snprintf (buf, size, "%s Net-ID: %s", adv_router_str, id_str);
159 else
160 snprintf (buf, size, "%s", adv_router_str);
161 }
162
163 /* Global strings for logging */
164 const char *ospf6_dest_type_str[OSPF6_DEST_TYPE_MAX] =
165 { "Unknown", "Router", "Network", "Discard", "Linkstate", "AddressRange", };
166
167 const char *ospf6_dest_type_substr[OSPF6_DEST_TYPE_MAX] =
168 { "?", "R", "N", "D", "L", "A", };
169
170 const char *ospf6_path_type_str[OSPF6_PATH_TYPE_MAX] =
171 { "Unknown", "Intra-Area", "Inter-Area", "External-1", "External-2", };
172
173 const char *ospf6_path_type_substr[OSPF6_PATH_TYPE_MAX] =
174 { "??", "IA", "IE", "E1", "E2", };
175
176
177 struct ospf6_nexthop *
178 ospf6_nexthop_create (void)
179 {
180 struct ospf6_nexthop *nh;
181
182 nh = XCALLOC (MTYPE_OSPF6_NEXTHOP, sizeof (struct ospf6_nexthop));
183 return nh;
184 }
185
186 void
187 ospf6_nexthop_delete (struct ospf6_nexthop *nh)
188 {
189 if (nh)
190 XFREE (MTYPE_OSPF6_NEXTHOP, nh);
191 }
192
193 void
194 ospf6_free_nexthops (struct list *nh_list)
195 {
196 struct ospf6_nexthop *nh;
197 struct listnode *node, *nnode;
198
199 if (nh_list)
200 {
201 for (ALL_LIST_ELEMENTS (nh_list, node, nnode, nh))
202 ospf6_nexthop_delete (nh);
203 }
204 }
205
206 void
207 ospf6_clear_nexthops (struct list *nh_list)
208 {
209 struct listnode *node;
210 struct ospf6_nexthop *nh;
211
212 if (nh_list)
213 {
214 for (ALL_LIST_ELEMENTS_RO (nh_list, node, nh))
215 ospf6_nexthop_clear (nh);
216 }
217 }
218
219 static struct ospf6_nexthop *
220 ospf6_route_find_nexthop (struct list *nh_list, struct ospf6_nexthop *nh_match)
221 {
222 struct listnode *node;
223 struct ospf6_nexthop *nh;
224
225 if (nh_list && nh_match)
226 {
227 for (ALL_LIST_ELEMENTS_RO (nh_list, node, nh))
228 {
229 if (ospf6_nexthop_is_same (nh, nh_match))
230 return (nh);
231 }
232 }
233
234 return (NULL);
235 }
236
237 void
238 ospf6_copy_nexthops (struct list *dst, struct list *src)
239 {
240 struct ospf6_nexthop *nh_new, *nh;
241 struct listnode *node;
242
243 if (dst && src)
244 {
245 for (ALL_LIST_ELEMENTS_RO (src, node, nh))
246 {
247 if (ospf6_nexthop_is_set (nh))
248 {
249 nh_new = ospf6_nexthop_create ();
250 ospf6_nexthop_copy (nh_new, nh);
251 listnode_add (dst, nh_new);
252 }
253 }
254 }
255 }
256
257 void
258 ospf6_merge_nexthops (struct list *dst, struct list *src)
259 {
260 struct listnode *node;
261 struct ospf6_nexthop *nh, *nh_new;
262
263 if (src && dst)
264 {
265 for (ALL_LIST_ELEMENTS_RO (src, node, nh))
266 {
267 if (!ospf6_route_find_nexthop (dst, nh))
268 {
269 nh_new = ospf6_nexthop_create ();
270 ospf6_nexthop_copy (nh_new, nh);
271 listnode_add (dst, nh_new);
272 }
273 }
274 }
275 }
276
277 int
278 ospf6_route_cmp_nexthops (struct ospf6_route *a, struct ospf6_route *b)
279 {
280 struct listnode *anode, *bnode;
281 struct ospf6_nexthop *anh, *bnh;
282
283 if (a && b)
284 {
285 if (listcount(a->nh_list) == listcount(b->nh_list))
286 {
287 for (ALL_LIST_ELEMENTS_RO (a->nh_list, anode, anh))
288 {
289 for (ALL_LIST_ELEMENTS_RO (b->nh_list, bnode, bnh))
290 if (!ospf6_nexthop_is_same (anh, bnh))
291 return (1);
292 }
293 return (0);
294 }
295 else
296 return (1);
297 }
298 /* One of the routes doesn't exist ? */
299 return (1);
300 }
301
302 int
303 ospf6_num_nexthops (struct list *nh_list)
304 {
305 return (listcount(nh_list));
306 }
307
308 void
309 ospf6_add_nexthop (struct list *nh_list, int ifindex,
310 struct in6_addr *addr)
311 {
312 struct ospf6_nexthop *nh;
313 struct ospf6_nexthop nh_match;
314
315 if (nh_list)
316 {
317 nh_match.ifindex = ifindex;
318 if (addr != NULL)
319 memcpy (&nh_match.address, addr, sizeof (struct in6_addr));
320 else
321 memset (&nh_match.address, 0, sizeof (struct in6_addr));
322
323 if (!ospf6_route_find_nexthop (nh_list, &nh_match))
324 {
325 nh = ospf6_nexthop_create();
326 ospf6_nexthop_copy (nh, &nh_match);
327 listnode_add (nh_list, nh);
328 }
329 }
330 }
331
332 void
333 ospf6_route_zebra_copy_nexthops (struct ospf6_route *route,
334 unsigned int *ifindexes,
335 struct in6_addr **nexthop_addr,
336 int entries)
337 {
338 struct ospf6_nexthop *nh;
339 struct listnode *node;
340 char buf[64];
341 int i;
342
343 if (route)
344 {
345 i = 0;
346 for (ALL_LIST_ELEMENTS_RO (route->nh_list, node, nh))
347 {
348 if (IS_OSPF6_DEBUG_ZEBRA (SEND))
349 {
350 const char *ifname;
351 inet_ntop (AF_INET6, &nh->address, buf, sizeof (buf));
352 ifname = ifindex2ifname (nh->ifindex);
353 zlog_debug (" nexthop: %s%%%.*s(%d)", buf, IFNAMSIZ, ifname,
354 nh->ifindex);
355 }
356 if (i < entries)
357 {
358 nexthop_addr[i] = &nh->address;
359 ifindexes[i] = nh->ifindex;
360 i++;
361 }
362 else
363 {
364 return;
365 }
366 }
367 }
368 }
369
370 int
371 ospf6_route_get_first_nh_index (struct ospf6_route *route)
372 {
373 struct ospf6_nexthop *nh;
374
375 if (route)
376 {
377 if ((nh = (struct ospf6_nexthop *)listhead (route->nh_list)))
378 return (nh->ifindex);
379 }
380
381 return (-1);
382 }
383
384 struct ospf6_route *
385 ospf6_route_create (void)
386 {
387 struct ospf6_route *route;
388 route = XCALLOC (MTYPE_OSPF6_ROUTE, sizeof (struct ospf6_route));
389 route->nh_list = list_new();
390 return route;
391 }
392
393 void
394 ospf6_route_delete (struct ospf6_route *route)
395 {
396 if (route)
397 {
398 ospf6_free_nexthops (route->nh_list);
399 list_free (route->nh_list);
400 XFREE (MTYPE_OSPF6_ROUTE, route);
401 }
402 }
403
404 struct ospf6_route *
405 ospf6_route_copy (struct ospf6_route *route)
406 {
407 struct ospf6_route *new;
408
409 new = ospf6_route_create ();
410 new->type = route->type;
411 memcpy (&new->prefix, &route->prefix, sizeof (struct prefix));
412 new->installed = route->installed;
413 new->changed = route->changed;
414 new->flag = route->flag;
415 new->route_option = route->route_option;
416 new->linkstate_id = route->linkstate_id;
417 new->path = route->path;
418 ospf6_copy_nexthops (new->nh_list, route->nh_list);
419 new->rnode = NULL;
420 new->prev = NULL;
421 new->next = NULL;
422 new->table = NULL;
423 new->lock = 0;
424 return new;
425 }
426
427 void
428 ospf6_route_lock (struct ospf6_route *route)
429 {
430 route->lock++;
431 }
432
433 void
434 ospf6_route_unlock (struct ospf6_route *route)
435 {
436 assert (route->lock > 0);
437 route->lock--;
438 if (route->lock == 0)
439 {
440 /* Can't detach from the table until here
441 because ospf6_route_next () will use
442 the 'route->table' pointer for logging */
443 route->table = NULL;
444 ospf6_route_delete (route);
445 }
446 }
447
448 /* Route compare function. If ra is more preferred, it returns
449 less than 0. If rb is more preferred returns greater than 0.
450 Otherwise (neither one is preferred), returns 0 */
451 int
452 ospf6_route_cmp (struct ospf6_route *ra, struct ospf6_route *rb)
453 {
454 assert (ospf6_route_is_same (ra, rb));
455 assert (OSPF6_PATH_TYPE_NONE < ra->path.type &&
456 ra->path.type < OSPF6_PATH_TYPE_MAX);
457 assert (OSPF6_PATH_TYPE_NONE < rb->path.type &&
458 rb->path.type < OSPF6_PATH_TYPE_MAX);
459
460 if (ra->type != rb->type)
461 return (ra->type - rb->type);
462
463 if (ra->path.area_id != rb->path.area_id)
464 return (ntohl (ra->path.area_id) - ntohl (rb->path.area_id));
465
466 if (ra->path.type != rb->path.type)
467 return (ra->path.type - rb->path.type);
468
469 if (ra->path.type == OSPF6_PATH_TYPE_EXTERNAL2)
470 {
471 if (ra->path.u.cost_e2 != rb->path.u.cost_e2)
472 return (ra->path.u.cost_e2 - rb->path.u.cost_e2);
473 }
474 else
475 {
476 if (ra->path.cost != rb->path.cost)
477 return (ra->path.cost - rb->path.cost);
478 }
479
480 return 0;
481 }
482
483 struct ospf6_route *
484 ospf6_route_lookup (struct prefix *prefix,
485 struct ospf6_route_table *table)
486 {
487 struct route_node *node;
488 struct ospf6_route *route;
489
490 node = route_node_lookup (table->table, prefix);
491 if (node == NULL)
492 return NULL;
493
494 route = (struct ospf6_route *) node->info;
495 return route;
496 }
497
498 struct ospf6_route *
499 ospf6_route_lookup_identical (struct ospf6_route *route,
500 struct ospf6_route_table *table)
501 {
502 struct ospf6_route *target;
503
504 for (target = ospf6_route_lookup (&route->prefix, table);
505 target; target = target->next)
506 {
507 if (ospf6_route_is_identical (target, route))
508 return target;
509 }
510 return NULL;
511 }
512
513 struct ospf6_route *
514 ospf6_route_lookup_bestmatch (struct prefix *prefix,
515 struct ospf6_route_table *table)
516 {
517 struct route_node *node;
518 struct ospf6_route *route;
519
520 node = route_node_match (table->table, prefix);
521 if (node == NULL)
522 return NULL;
523 route_unlock_node (node);
524
525 route = (struct ospf6_route *) node->info;
526 return route;
527 }
528
529 #ifdef DEBUG
530 static void
531 route_table_assert (struct ospf6_route_table *table)
532 {
533 struct ospf6_route *prev, *r, *next;
534 char buf[PREFIX2STR_BUFFER];
535 unsigned int link_error = 0, num = 0;
536
537 r = ospf6_route_head (table);
538 prev = NULL;
539 while (r)
540 {
541 if (r->prev != prev)
542 link_error++;
543
544 next = ospf6_route_next (r);
545
546 if (r->next != next)
547 link_error++;
548
549 prev = r;
550 r = next;
551 }
552
553 for (r = ospf6_route_head (table); r; r = ospf6_route_next (r))
554 num++;
555
556 if (link_error == 0 && num == table->count)
557 return;
558
559 zlog_err ("PANIC !!");
560 zlog_err ("Something has gone wrong with ospf6_route_table[%p]", table);
561 zlog_debug ("table count = %d, real number = %d", table->count, num);
562 zlog_debug ("DUMP START");
563 for (r = ospf6_route_head (table); r; r = ospf6_route_next (r))
564 {
565 prefix2str (&r->prefix, buf, sizeof (buf));
566 zlog_info ("%p<-[%p]->%p : %s", r->prev, r, r->next, buf);
567 }
568 zlog_debug ("DUMP END");
569
570 assert (link_error == 0 && num == table->count);
571 }
572 #define ospf6_route_table_assert(t) (route_table_assert (t))
573 #else
574 #define ospf6_route_table_assert(t) ((void) 0)
575 #endif /*DEBUG*/
576
577 struct ospf6_route *
578 ospf6_route_add (struct ospf6_route *route,
579 struct ospf6_route_table *table)
580 {
581 struct route_node *node, *nextnode, *prevnode;
582 struct ospf6_route *current = NULL;
583 struct ospf6_route *prev = NULL, *old = NULL, *next = NULL;
584 char buf[PREFIX2STR_BUFFER];
585 struct timeval now;
586
587 assert (route->rnode == NULL);
588 assert (route->lock == 0);
589 assert (route->next == NULL);
590 assert (route->prev == NULL);
591
592 if (route->type == OSPF6_DEST_TYPE_LINKSTATE)
593 ospf6_linkstate_prefix2str (&route->prefix, buf, sizeof (buf));
594 else
595 prefix2str (&route->prefix, buf, sizeof (buf));
596
597 if (IS_OSPF6_DEBUG_ROUTE (MEMORY))
598 zlog_debug ("%s %p: route add %p: %s", ospf6_route_table_name (table),
599 (void *)table, (void *)route, buf);
600 else if (IS_OSPF6_DEBUG_ROUTE (TABLE))
601 zlog_debug ("%s: route add: %s", ospf6_route_table_name (table), buf);
602
603 quagga_gettime (QUAGGA_CLK_MONOTONIC, &now);
604
605 node = route_node_get (table->table, &route->prefix);
606 route->rnode = node;
607
608 /* find place to insert */
609 for (current = node->info; current; current = current->next)
610 {
611 if (! ospf6_route_is_same (current, route))
612 next = current;
613 else if (current->type != route->type)
614 prev = current;
615 else if (ospf6_route_is_same_origin (current, route))
616 old = current;
617 else if (ospf6_route_cmp (current, route) > 0)
618 next = current;
619 else
620 prev = current;
621
622 if (old || next)
623 break;
624 }
625
626 if (old)
627 {
628 /* if route does not actually change, return unchanged */
629 if (ospf6_route_is_identical (old, route))
630 {
631 if (IS_OSPF6_DEBUG_ROUTE (MEMORY))
632 zlog_debug ("%s %p: route add %p: needless update of %p",
633 ospf6_route_table_name (table),
634 (void *)table, (void *)route, (void *)old);
635 else if (IS_OSPF6_DEBUG_ROUTE (TABLE))
636 zlog_debug ("%s: route add: needless update",
637 ospf6_route_table_name (table));
638
639 ospf6_route_delete (route);
640 SET_FLAG (old->flag, OSPF6_ROUTE_ADD);
641 ospf6_route_table_assert (table);
642
643 return old;
644 }
645
646 if (IS_OSPF6_DEBUG_ROUTE (MEMORY))
647 zlog_debug ("%s %p: route add %p: update of %p",
648 ospf6_route_table_name (table),
649 (void *)table, (void *)route, (void *)old);
650 else if (IS_OSPF6_DEBUG_ROUTE (TABLE))
651 zlog_debug ("%s: route add: update",
652 ospf6_route_table_name (table));
653
654 /* replace old one if exists */
655 if (node->info == old)
656 {
657 node->info = route;
658 SET_FLAG (route->flag, OSPF6_ROUTE_BEST);
659 }
660
661 if (old->prev)
662 old->prev->next = route;
663 route->prev = old->prev;
664 if (old->next)
665 old->next->prev = route;
666 route->next = old->next;
667
668 route->installed = old->installed;
669 route->changed = now;
670 assert (route->table == NULL);
671 route->table = table;
672
673 ospf6_route_unlock (old); /* will be deleted later */
674 ospf6_route_lock (route);
675
676 SET_FLAG (route->flag, OSPF6_ROUTE_CHANGE);
677 ospf6_route_table_assert (table);
678
679 if (table->hook_add)
680 (*table->hook_add) (route);
681
682 return route;
683 }
684
685 /* insert if previous or next node found */
686 if (prev || next)
687 {
688 if (IS_OSPF6_DEBUG_ROUTE (MEMORY))
689 zlog_debug ("%s %p: route add %p: another path: prev %p, next %p",
690 ospf6_route_table_name (table),
691 (void *)table, (void *)route, (void *)prev, (void *)next);
692 else if (IS_OSPF6_DEBUG_ROUTE (TABLE))
693 zlog_debug ("%s: route add: another path found",
694 ospf6_route_table_name (table));
695
696 if (prev == NULL)
697 prev = next->prev;
698 if (next == NULL)
699 next = prev->next;
700
701 if (prev)
702 prev->next = route;
703 route->prev = prev;
704 if (next)
705 next->prev = route;
706 route->next = next;
707
708 if (node->info == next)
709 {
710 assert (next->rnode == node);
711 node->info = route;
712 UNSET_FLAG (next->flag, OSPF6_ROUTE_BEST);
713 SET_FLAG (route->flag, OSPF6_ROUTE_BEST);
714 if (IS_OSPF6_DEBUG_ROUTE (MEMORY))
715 zlog_info ("%s %p: route add %p: replacing previous best: %p",
716 ospf6_route_table_name (table),
717 (void *)table, (void *)route, (void *)next);
718 }
719
720 route->installed = now;
721 route->changed = now;
722 assert (route->table == NULL);
723 route->table = table;
724
725 ospf6_route_lock (route);
726 table->count++;
727 ospf6_route_table_assert (table);
728
729 SET_FLAG (route->flag, OSPF6_ROUTE_ADD);
730 if (table->hook_add)
731 (*table->hook_add) (route);
732
733 return route;
734 }
735
736 /* Else, this is the brand new route regarding to the prefix */
737 if (IS_OSPF6_DEBUG_ROUTE (MEMORY))
738 zlog_debug ("%s %p: route add %p: brand new route",
739 ospf6_route_table_name (table), (void *)table, (void *)route);
740 else if (IS_OSPF6_DEBUG_ROUTE (TABLE))
741 zlog_debug ("%s: route add: brand new route",
742 ospf6_route_table_name (table));
743
744 assert (node->info == NULL);
745 node->info = route;
746 SET_FLAG (route->flag, OSPF6_ROUTE_BEST);
747 ospf6_route_lock (route);
748 route->installed = now;
749 route->changed = now;
750 assert (route->table == NULL);
751 route->table = table;
752
753 /* lookup real existing next route */
754 nextnode = node;
755 route_lock_node (nextnode);
756 do {
757 nextnode = route_next (nextnode);
758 } while (nextnode && nextnode->info == NULL);
759
760 /* set next link */
761 if (nextnode == NULL)
762 route->next = NULL;
763 else
764 {
765 route_unlock_node (nextnode);
766
767 next = nextnode->info;
768 route->next = next;
769 next->prev = route;
770 }
771
772 /* lookup real existing prev route */
773 prevnode = node;
774 route_lock_node (prevnode);
775 do {
776 prevnode = route_prev (prevnode);
777 } while (prevnode && prevnode->info == NULL);
778
779 /* set prev link */
780 if (prevnode == NULL)
781 route->prev = NULL;
782 else
783 {
784 route_unlock_node (prevnode);
785
786 prev = prevnode->info;
787 while (prev->next && ospf6_route_is_same (prev, prev->next))
788 prev = prev->next;
789 route->prev = prev;
790 prev->next = route;
791 }
792
793 table->count++;
794 ospf6_route_table_assert (table);
795
796 SET_FLAG (route->flag, OSPF6_ROUTE_ADD);
797 if (table->hook_add)
798 (*table->hook_add) (route);
799
800 return route;
801 }
802
803 void
804 ospf6_route_remove (struct ospf6_route *route,
805 struct ospf6_route_table *table)
806 {
807 struct route_node *node;
808 struct ospf6_route *current;
809 char buf[PREFIX2STR_BUFFER];
810
811 if (route->type == OSPF6_DEST_TYPE_LINKSTATE)
812 ospf6_linkstate_prefix2str (&route->prefix, buf, sizeof (buf));
813 else
814 prefix2str (&route->prefix, buf, sizeof (buf));
815
816 if (IS_OSPF6_DEBUG_ROUTE (MEMORY))
817 zlog_debug ("%s %p: route remove %p: %s",
818 ospf6_route_table_name (table),
819 (void *)table, (void *)route, buf);
820 else if (IS_OSPF6_DEBUG_ROUTE (TABLE))
821 zlog_debug ("%s: route remove: %s", ospf6_route_table_name (table), buf);
822
823 node = route_node_lookup (table->table, &route->prefix);
824 assert (node);
825
826 /* find the route to remove, making sure that the route pointer
827 is from the route table. */
828 current = node->info;
829 while (current && ospf6_route_is_same (current, route))
830 {
831 if (current == route)
832 break;
833 current = current->next;
834 }
835 assert (current == route);
836
837 /* adjust doubly linked list */
838 if (route->prev)
839 route->prev->next = route->next;
840 if (route->next)
841 route->next->prev = route->prev;
842
843 if (node->info == route)
844 {
845 if (route->next && route->next->rnode == node)
846 {
847 node->info = route->next;
848 SET_FLAG (route->next->flag, OSPF6_ROUTE_BEST);
849 }
850 else
851 node->info = NULL; /* should unlock route_node here ? */
852 }
853
854 table->count--;
855 ospf6_route_table_assert (table);
856
857 SET_FLAG (route->flag, OSPF6_ROUTE_WAS_REMOVED);
858
859 if (table->hook_remove)
860 (*table->hook_remove) (route);
861
862 ospf6_route_unlock (route);
863 }
864
865 struct ospf6_route *
866 ospf6_route_head (struct ospf6_route_table *table)
867 {
868 struct route_node *node;
869 struct ospf6_route *route;
870
871 node = route_top (table->table);
872 if (node == NULL)
873 return NULL;
874
875 /* skip to the real existing entry */
876 while (node && node->info == NULL)
877 node = route_next (node);
878 if (node == NULL)
879 return NULL;
880
881 route_unlock_node (node);
882 assert (node->info);
883
884 route = (struct ospf6_route *) node->info;
885 assert (route->prev == NULL);
886 assert (route->table == table);
887 ospf6_route_lock (route);
888
889 if (IS_OSPF6_DEBUG_ROUTE (MEMORY))
890 zlog_info ("%s %p: route head: %p<-[%p]->%p",
891 ospf6_route_table_name (table), (void *)table,
892 (void *)route->prev, (void *)route, (void *)route->next);
893
894 return route;
895 }
896
897 struct ospf6_route *
898 ospf6_route_next (struct ospf6_route *route)
899 {
900 struct ospf6_route *next = route->next;
901
902 if (IS_OSPF6_DEBUG_ROUTE (MEMORY))
903 zlog_info ("%s %p: route next: %p<-[%p]->%p",
904 ospf6_route_table_name (route->table), (void *)route->table,
905 (void *)route->prev, (void *)route, (void *)route->next);
906
907 ospf6_route_unlock (route);
908 if (next)
909 ospf6_route_lock (next);
910
911 return next;
912 }
913
914 struct ospf6_route *
915 ospf6_route_best_next (struct ospf6_route *route)
916 {
917 struct route_node *rnode;
918 struct ospf6_route *next;
919
920 ospf6_route_unlock (route);
921
922 rnode = route->rnode;
923 route_lock_node (rnode);
924 rnode = route_next (rnode);
925 while (rnode && rnode->info == NULL)
926 rnode = route_next (rnode);
927 if (rnode == NULL)
928 return NULL;
929 route_unlock_node (rnode);
930
931 assert (rnode->info);
932 next = (struct ospf6_route *) rnode->info;
933 ospf6_route_lock (next);
934 return next;
935 }
936
937 struct ospf6_route *
938 ospf6_route_match_head (struct prefix *prefix,
939 struct ospf6_route_table *table)
940 {
941 struct route_node *node;
942 struct ospf6_route *route;
943
944 /* Walk down tree. */
945 node = table->table->top;
946 while (node && node->p.prefixlen < prefix->prefixlen &&
947 prefix_match (&node->p, prefix))
948 node = node->link[prefix_bit(&prefix->u.prefix, node->p.prefixlen)];
949
950 if (node)
951 route_lock_node (node);
952 while (node && node->info == NULL)
953 node = route_next (node);
954 if (node == NULL)
955 return NULL;
956 route_unlock_node (node);
957
958 if (! prefix_match (prefix, &node->p))
959 return NULL;
960
961 route = node->info;
962 ospf6_route_lock (route);
963 return route;
964 }
965
966 struct ospf6_route *
967 ospf6_route_match_next (struct prefix *prefix,
968 struct ospf6_route *route)
969 {
970 struct ospf6_route *next;
971
972 next = ospf6_route_next (route);
973 if (next && ! prefix_match (prefix, &next->prefix))
974 {
975 ospf6_route_unlock (next);
976 next = NULL;
977 }
978
979 return next;
980 }
981
982 void
983 ospf6_route_remove_all (struct ospf6_route_table *table)
984 {
985 struct ospf6_route *route;
986 for (route = ospf6_route_head (table); route;
987 route = ospf6_route_next (route))
988 ospf6_route_remove (route, table);
989 }
990
991 struct ospf6_route_table *
992 ospf6_route_table_create (int s, int t)
993 {
994 struct ospf6_route_table *new;
995 new = XCALLOC (MTYPE_OSPF6_ROUTE, sizeof (struct ospf6_route_table));
996 new->table = route_table_init ();
997 new->scope_type = s;
998 new->table_type = t;
999 return new;
1000 }
1001
1002 void
1003 ospf6_route_table_delete (struct ospf6_route_table *table)
1004 {
1005 ospf6_route_remove_all (table);
1006 route_table_finish (table->table);
1007 XFREE (MTYPE_OSPF6_ROUTE, table);
1008 }
1009
1010
1011 /* VTY commands */
1012 void
1013 ospf6_route_show (struct vty *vty, struct ospf6_route *route)
1014 {
1015 int i;
1016 char destination[PREFIX2STR_BUFFER], nexthop[64];
1017 char duration[16];
1018 const char *ifname;
1019 struct timeval now, res;
1020 struct listnode *node;
1021 struct ospf6_nexthop *nh;
1022
1023 quagga_gettime (QUAGGA_CLK_MONOTONIC, &now);
1024 timersub (&now, &route->changed, &res);
1025 timerstring (&res, duration, sizeof (duration));
1026
1027 /* destination */
1028 if (route->type == OSPF6_DEST_TYPE_LINKSTATE)
1029 ospf6_linkstate_prefix2str (&route->prefix, destination,
1030 sizeof (destination));
1031 else if (route->type == OSPF6_DEST_TYPE_ROUTER)
1032 inet_ntop (route->prefix.family, &route->prefix.u.prefix,
1033 destination, sizeof (destination));
1034 else
1035 prefix2str (&route->prefix, destination, sizeof (destination));
1036
1037 i = 0;
1038 for (ALL_LIST_ELEMENTS_RO (route->nh_list, node, nh))
1039 {
1040 /* nexthop */
1041 inet_ntop (AF_INET6, &nh->address, nexthop,
1042 sizeof (nexthop));
1043 ifname = ifindex2ifname (nh->ifindex);
1044
1045 if (!i)
1046 {
1047 vty_out (vty, "%c%1s %2s %-30s %-25s %6.*s %s%s",
1048 (ospf6_route_is_best (route) ? '*' : ' '),
1049 OSPF6_DEST_TYPE_SUBSTR (route->type),
1050 OSPF6_PATH_TYPE_SUBSTR (route->path.type),
1051 destination, nexthop, IFNAMSIZ, ifname, duration, VNL);
1052 i++;
1053 }
1054 else
1055 vty_out (vty, "%c%1s %2s %-30s %-25s %6.*s %s%s",
1056 ' ', "", "", "", nexthop, IFNAMSIZ, ifname, "", VNL);
1057 }
1058 }
1059
1060 void
1061 ospf6_route_show_detail (struct vty *vty, struct ospf6_route *route)
1062 {
1063 const char *ifname;
1064 char destination[PREFIX2STR_BUFFER], nexthop[64];
1065 char area_id[16], id[16], adv_router[16], capa[16], options[16];
1066 struct timeval now, res;
1067 char duration[16];
1068 struct listnode *node;
1069 struct ospf6_nexthop *nh;
1070
1071 quagga_gettime (QUAGGA_CLK_MONOTONIC, &now);
1072
1073 /* destination */
1074 if (route->type == OSPF6_DEST_TYPE_LINKSTATE)
1075 ospf6_linkstate_prefix2str (&route->prefix, destination,
1076 sizeof (destination));
1077 else if (route->type == OSPF6_DEST_TYPE_ROUTER)
1078 inet_ntop (route->prefix.family, &route->prefix.u.prefix,
1079 destination, sizeof (destination));
1080 else
1081 prefix2str (&route->prefix, destination, sizeof (destination));
1082 vty_out (vty, "Destination: %s%s", destination, VNL);
1083
1084 /* destination type */
1085 vty_out (vty, "Destination type: %s%s",
1086 OSPF6_DEST_TYPE_NAME (route->type),
1087 VNL);
1088
1089 /* Time */
1090 timersub (&now, &route->installed, &res);
1091 timerstring (&res, duration, sizeof (duration));
1092 vty_out (vty, "Installed Time: %s ago%s", duration, VNL);
1093
1094 timersub (&now, &route->changed, &res);
1095 timerstring (&res, duration, sizeof (duration));
1096 vty_out (vty, " Changed Time: %s ago%s", duration, VNL);
1097
1098 /* Debugging info */
1099 vty_out (vty, "Lock: %d Flags: %s%s%s%s%s", route->lock,
1100 (CHECK_FLAG (route->flag, OSPF6_ROUTE_BEST) ? "B" : "-"),
1101 (CHECK_FLAG (route->flag, OSPF6_ROUTE_ADD) ? "A" : "-"),
1102 (CHECK_FLAG (route->flag, OSPF6_ROUTE_REMOVE) ? "R" : "-"),
1103 (CHECK_FLAG (route->flag, OSPF6_ROUTE_CHANGE) ? "C" : "-"),
1104 VNL);
1105 vty_out (vty, "Memory: prev: %p this: %p next: %p%s",
1106 (void *)route->prev, (void *)route, (void *)route->next, VNL);
1107
1108 /* Path section */
1109
1110 /* Area-ID */
1111 inet_ntop (AF_INET, &route->path.area_id, area_id, sizeof (area_id));
1112 vty_out (vty, "Associated Area: %s%s", area_id, VNL);
1113
1114 /* Path type */
1115 vty_out (vty, "Path Type: %s%s",
1116 OSPF6_PATH_TYPE_NAME (route->path.type), VNL);
1117
1118 /* LS Origin */
1119 inet_ntop (AF_INET, &route->path.origin.id, id, sizeof (id));
1120 inet_ntop (AF_INET, &route->path.origin.adv_router, adv_router,
1121 sizeof (adv_router));
1122 vty_out (vty, "LS Origin: %s Id: %s Adv: %s%s",
1123 ospf6_lstype_name (route->path.origin.type),
1124 id, adv_router, VNL);
1125
1126 /* Options */
1127 ospf6_options_printbuf (route->path.options, options, sizeof (options));
1128 vty_out (vty, "Options: %s%s", options, VNL);
1129
1130 /* Router Bits */
1131 ospf6_capability_printbuf (route->path.router_bits, capa, sizeof (capa));
1132 vty_out (vty, "Router Bits: %s%s", capa, VNL);
1133
1134 /* Prefix Options */
1135 vty_out (vty, "Prefix Options: xxx%s", VNL);
1136
1137 /* Metrics */
1138 vty_out (vty, "Metric Type: %d%s", route->path.metric_type,
1139 VNL);
1140 vty_out (vty, "Metric: %d (%d)%s",
1141 route->path.cost, route->path.u.cost_e2, VNL);
1142
1143 /* Nexthops */
1144 vty_out (vty, "Nexthop:%s", VNL);
1145 for (ALL_LIST_ELEMENTS_RO (route->nh_list, node, nh))
1146 {
1147 /* nexthop */
1148 inet_ntop (AF_INET6, &nh->address, nexthop, sizeof (nexthop));
1149 ifname = ifindex2ifname (nh->ifindex);
1150 vty_out (vty, " %s %.*s%s", nexthop, IFNAMSIZ, ifname, VNL);
1151 }
1152 vty_out (vty, "%s", VNL);
1153 }
1154
1155 static void
1156 ospf6_route_show_table_summary (struct vty *vty,
1157 struct ospf6_route_table *table)
1158 {
1159 struct ospf6_route *route, *prev = NULL;
1160 int i, pathtype[OSPF6_PATH_TYPE_MAX];
1161 unsigned int number = 0;
1162 int nh_count =0 , nhinval = 0, ecmp = 0;
1163 int alternative = 0, destination = 0;
1164
1165 for (i = 0; i < OSPF6_PATH_TYPE_MAX; i++)
1166 pathtype[i] = 0;
1167
1168 for (route = ospf6_route_head (table); route;
1169 route = ospf6_route_next (route))
1170 {
1171 if (prev == NULL || ! ospf6_route_is_same (prev, route))
1172 destination++;
1173 else
1174 alternative++;
1175 nh_count = ospf6_num_nexthops (route->nh_list);
1176 if (!nh_count)
1177 nhinval++;
1178 else if (nh_count > 1)
1179 ecmp++;
1180 pathtype[route->path.type]++;
1181 number++;
1182
1183 prev = route;
1184 }
1185
1186 assert (number == table->count);
1187
1188 vty_out (vty, "Number of OSPFv3 routes: %d%s", number, VNL);
1189 vty_out (vty, "Number of Destination: %d%s", destination, VNL);
1190 vty_out (vty, "Number of Alternative routes: %d%s", alternative, VNL);
1191 vty_out (vty, "Number of Equal Cost Multi Path: %d%s", ecmp, VNL);
1192 for (i = OSPF6_PATH_TYPE_INTRA; i <= OSPF6_PATH_TYPE_EXTERNAL2; i++)
1193 {
1194 vty_out (vty, "Number of %s routes: %d%s",
1195 OSPF6_PATH_TYPE_NAME (i), pathtype[i], VNL);
1196 }
1197 }
1198
1199 static void
1200 ospf6_route_show_table_prefix (struct vty *vty,
1201 struct prefix *prefix,
1202 struct ospf6_route_table *table)
1203 {
1204 struct ospf6_route *route;
1205
1206 route = ospf6_route_lookup (prefix, table);
1207 if (route == NULL)
1208 return;
1209
1210 ospf6_route_lock (route);
1211 while (route && ospf6_route_is_prefix (prefix, route))
1212 {
1213 /* Specifying a prefix will always display details */
1214 ospf6_route_show_detail (vty, route);
1215 route = ospf6_route_next (route);
1216 }
1217 if (route)
1218 ospf6_route_unlock (route);
1219 }
1220
1221 static void
1222 ospf6_route_show_table_address (struct vty *vty,
1223 struct prefix *prefix,
1224 struct ospf6_route_table *table)
1225 {
1226 struct ospf6_route *route;
1227
1228 route = ospf6_route_lookup_bestmatch (prefix, table);
1229 if (route == NULL)
1230 return;
1231
1232 prefix = &route->prefix;
1233 ospf6_route_lock (route);
1234 while (route && ospf6_route_is_prefix (prefix, route))
1235 {
1236 /* Specifying a prefix will always display details */
1237 ospf6_route_show_detail (vty, route);
1238 route = ospf6_route_next (route);
1239 }
1240 if (route)
1241 ospf6_route_unlock (route);
1242 }
1243
1244 static void
1245 ospf6_route_show_table_match (struct vty *vty, int detail,
1246 struct prefix *prefix,
1247 struct ospf6_route_table *table)
1248 {
1249 struct ospf6_route *route;
1250 assert (prefix->family);
1251
1252 route = ospf6_route_match_head (prefix, table);
1253 while (route)
1254 {
1255 if (detail)
1256 ospf6_route_show_detail (vty, route);
1257 else
1258 ospf6_route_show (vty, route);
1259 route = ospf6_route_match_next (prefix, route);
1260 }
1261 }
1262
1263 static void
1264 ospf6_route_show_table_type (struct vty *vty, int detail, u_char type,
1265 struct ospf6_route_table *table)
1266 {
1267 struct ospf6_route *route;
1268
1269 route = ospf6_route_head (table);
1270 while (route)
1271 {
1272 if (route->path.type == type)
1273 {
1274 if (detail)
1275 ospf6_route_show_detail (vty, route);
1276 else
1277 ospf6_route_show (vty, route);
1278 }
1279 route = ospf6_route_next (route);
1280 }
1281 }
1282
1283 static void
1284 ospf6_route_show_table (struct vty *vty, int detail,
1285 struct ospf6_route_table *table)
1286 {
1287 struct ospf6_route *route;
1288
1289 route = ospf6_route_head (table);
1290 while (route)
1291 {
1292 if (detail)
1293 ospf6_route_show_detail (vty, route);
1294 else
1295 ospf6_route_show (vty, route);
1296 route = ospf6_route_next (route);
1297 }
1298 }
1299
1300 int
1301 ospf6_route_table_show (struct vty *vty, int argc, const char *argv[],
1302 struct ospf6_route_table *table)
1303 {
1304 int summary = 0;
1305 int match = 0;
1306 int detail = 0;
1307 int slash = 0;
1308 int isprefix = 0;
1309 int i, ret;
1310 struct prefix prefix;
1311 u_char type = 0;
1312
1313 memset (&prefix, 0, sizeof (struct prefix));
1314
1315 for (i = 0; i < argc; i++)
1316 {
1317 if (! strcmp (argv[i], "summary"))
1318 {
1319 summary++;
1320 continue;
1321 }
1322
1323 if (! strcmp (argv[i], "intra-area"))
1324 {
1325 type = OSPF6_PATH_TYPE_INTRA;
1326 continue;
1327 }
1328
1329 if (! strcmp (argv[i], "inter-area"))
1330 {
1331 type = OSPF6_PATH_TYPE_INTER;
1332 continue;
1333 }
1334
1335 if (! strcmp (argv[i], "external-1"))
1336 {
1337 type = OSPF6_PATH_TYPE_EXTERNAL1;
1338 continue;
1339 }
1340
1341 if (! strcmp (argv[i], "external-2"))
1342 {
1343 type = OSPF6_PATH_TYPE_EXTERNAL2;
1344 continue;
1345 }
1346
1347 if (! strcmp (argv[i], "detail"))
1348 {
1349 detail++;
1350 continue;
1351 }
1352
1353 if (! strcmp (argv[i], "match"))
1354 {
1355 match++;
1356 continue;
1357 }
1358
1359 ret = str2prefix (argv[i], &prefix);
1360 if (ret == 1 && prefix.family == AF_INET6)
1361 {
1362 isprefix++;
1363 if (strchr (argv[i], '/'))
1364 slash++;
1365 continue;
1366 }
1367
1368 vty_out (vty, "Malformed argument: %s%s", argv[i], VNL);
1369 return CMD_SUCCESS;
1370 }
1371
1372 /* Give summary of this route table */
1373 if (summary)
1374 {
1375 ospf6_route_show_table_summary (vty, table);
1376 return CMD_SUCCESS;
1377 }
1378
1379 /* Give exact prefix-match route */
1380 if (isprefix && ! match)
1381 {
1382 /* If exact address, give best matching route */
1383 if (! slash)
1384 ospf6_route_show_table_address (vty, &prefix, table);
1385 else
1386 ospf6_route_show_table_prefix (vty, &prefix, table);
1387
1388 return CMD_SUCCESS;
1389 }
1390
1391 if (match)
1392 ospf6_route_show_table_match (vty, detail, &prefix, table);
1393 else if (type)
1394 ospf6_route_show_table_type (vty, detail, type, table);
1395 else
1396 ospf6_route_show_table (vty, detail, table);
1397
1398 return CMD_SUCCESS;
1399 }
1400
1401 static void
1402 ospf6_linkstate_show_header (struct vty *vty)
1403 {
1404 vty_out (vty, "%-7s %-15s %-15s %-8s %-14s %s%s",
1405 "Type", "Router-ID", "Net-ID", "Rtr-Bits", "Options", "Cost", VNL);
1406 }
1407
1408 static void
1409 ospf6_linkstate_show (struct vty *vty, struct ospf6_route *route)
1410 {
1411 u_int32_t router, id;
1412 char routername[16], idname[16], rbits[16], options[16];
1413
1414 router = ospf6_linkstate_prefix_adv_router (&route->prefix);
1415 inet_ntop (AF_INET, &router, routername, sizeof (routername));
1416 id = ospf6_linkstate_prefix_id (&route->prefix);
1417 inet_ntop (AF_INET, &id, idname, sizeof (idname));
1418
1419 ospf6_capability_printbuf (route->path.router_bits, rbits, sizeof (rbits));
1420 ospf6_options_printbuf (route->path.options, options, sizeof (options));
1421
1422 if (ntohl (id))
1423 vty_out (vty, "%-7s %-15s %-15s %-8s %-14s %lu%s",
1424 "Network", routername, idname, rbits, options,
1425 (unsigned long) route->path.cost, VNL);
1426 else
1427 vty_out (vty, "%-7s %-15s %-15s %-8s %-14s %lu%s",
1428 "Router", routername, idname, rbits, options,
1429 (unsigned long) route->path.cost, VNL);
1430 }
1431
1432
1433 static void
1434 ospf6_linkstate_show_table_exact (struct vty *vty,
1435 struct prefix *prefix,
1436 struct ospf6_route_table *table)
1437 {
1438 struct ospf6_route *route;
1439
1440 route = ospf6_route_lookup (prefix, table);
1441 if (route == NULL)
1442 return;
1443
1444 ospf6_route_lock (route);
1445 while (route && ospf6_route_is_prefix (prefix, route))
1446 {
1447 /* Specifying a prefix will always display details */
1448 ospf6_route_show_detail (vty, route);
1449 route = ospf6_route_next (route);
1450 }
1451 if (route)
1452 ospf6_route_unlock (route);
1453 }
1454
1455 static void
1456 ospf6_linkstate_show_table (struct vty *vty, int detail,
1457 struct ospf6_route_table *table)
1458 {
1459 struct ospf6_route *route;
1460
1461 if (! detail)
1462 ospf6_linkstate_show_header (vty);
1463
1464 route = ospf6_route_head (table);
1465 while (route)
1466 {
1467 if (detail)
1468 ospf6_route_show_detail (vty, route);
1469 else
1470 ospf6_linkstate_show (vty, route);
1471 route = ospf6_route_next (route);
1472 }
1473 }
1474
1475 int
1476 ospf6_linkstate_table_show (struct vty *vty, int argc, const char *argv[],
1477 struct ospf6_route_table *table)
1478 {
1479 int detail = 0;
1480 int is_id = 0;
1481 int is_router = 0;
1482 int i, ret;
1483 struct prefix router, id, prefix;
1484
1485 memset (&router, 0, sizeof (struct prefix));
1486 memset (&id, 0, sizeof (struct prefix));
1487 memset (&prefix, 0, sizeof (struct prefix));
1488
1489 for (i = 0; i < argc; i++)
1490 {
1491 if (! strcmp (argv[i], "detail"))
1492 {
1493 detail++;
1494 continue;
1495 }
1496
1497 if (! is_router)
1498 {
1499 ret = str2prefix (argv[i], &router);
1500 if (ret == 1 && router.family == AF_INET)
1501 {
1502 is_router++;
1503 continue;
1504 }
1505 vty_out (vty, "Malformed argument: %s%s", argv[i], VNL);
1506 return CMD_SUCCESS;
1507 }
1508
1509 if (! is_id)
1510 {
1511 ret = str2prefix (argv[i], &id);
1512 if (ret == 1 && id.family == AF_INET)
1513 {
1514 is_id++;
1515 continue;
1516 }
1517 vty_out (vty, "Malformed argument: %s%s", argv[i], VNL);
1518 return CMD_SUCCESS;
1519 }
1520
1521 vty_out (vty, "Malformed argument: %s%s", argv[i], VNL);
1522 return CMD_SUCCESS;
1523 }
1524
1525 if (is_router)
1526 ospf6_linkstate_prefix (router.u.prefix4.s_addr,
1527 id.u.prefix4.s_addr, &prefix);
1528
1529 if (prefix.family)
1530 ospf6_linkstate_show_table_exact (vty, &prefix, table);
1531 else
1532 ospf6_linkstate_show_table (vty, detail, table);
1533
1534 return CMD_SUCCESS;
1535 }
1536
1537
1538 void
1539 ospf6_brouter_show_header (struct vty *vty)
1540 {
1541 vty_out (vty, "%-15s %-8s %-14s %-10s %-15s%s",
1542 "Router-ID", "Rtr-Bits", "Options", "Path-Type", "Area", VNL);
1543 }
1544
1545 void
1546 ospf6_brouter_show (struct vty *vty, struct ospf6_route *route)
1547 {
1548 u_int32_t adv_router;
1549 char adv[16], rbits[16], options[16], area[16];
1550
1551 adv_router = ospf6_linkstate_prefix_adv_router (&route->prefix);
1552 inet_ntop (AF_INET, &adv_router, adv, sizeof (adv));
1553 ospf6_capability_printbuf (route->path.router_bits, rbits, sizeof (rbits));
1554 ospf6_options_printbuf (route->path.options, options, sizeof (options));
1555 inet_ntop (AF_INET, &route->path.area_id, area, sizeof (area));
1556
1557 /* vty_out (vty, "%-15s %-8s %-14s %-10s %-15s%s",
1558 "Router-ID", "Rtr-Bits", "Options", "Path-Type", "Area", VNL); */
1559 vty_out (vty, "%-15s %-8s %-14s %-10s %-15s%s",
1560 adv, rbits, options, OSPF6_PATH_TYPE_NAME (route->path.type),
1561 area, VNL);
1562 }
1563
1564 DEFUN (debug_ospf6_route,
1565 debug_ospf6_route_cmd,
1566 "debug ospf6 route (table|intra-area|inter-area|memory)",
1567 DEBUG_STR
1568 OSPF6_STR
1569 "Debug route table calculation\n"
1570 "Debug detail\n"
1571 "Debug intra-area route calculation\n"
1572 "Debug inter-area route calculation\n"
1573 "Debug route memory use\n"
1574 )
1575 {
1576 unsigned char level = 0;
1577
1578 if (! strncmp (argv[0], "table", 5))
1579 level = OSPF6_DEBUG_ROUTE_TABLE;
1580 else if (! strncmp (argv[0], "intra", 5))
1581 level = OSPF6_DEBUG_ROUTE_INTRA;
1582 else if (! strncmp (argv[0], "inter", 5))
1583 level = OSPF6_DEBUG_ROUTE_INTER;
1584 else if (! strncmp (argv[0], "memor", 5))
1585 level = OSPF6_DEBUG_ROUTE_MEMORY;
1586 OSPF6_DEBUG_ROUTE_ON (level);
1587 return CMD_SUCCESS;
1588 }
1589
1590 DEFUN (no_debug_ospf6_route,
1591 no_debug_ospf6_route_cmd,
1592 "no debug ospf6 route (table|intra-area|inter-area|memory)",
1593 NO_STR
1594 DEBUG_STR
1595 OSPF6_STR
1596 "Debug route table calculation\n"
1597 "Debug intra-area route calculation\n"
1598 "Debug route memory use\n")
1599 {
1600 unsigned char level = 0;
1601
1602 if (! strncmp (argv[0], "table", 5))
1603 level = OSPF6_DEBUG_ROUTE_TABLE;
1604 else if (! strncmp (argv[0], "intra", 5))
1605 level = OSPF6_DEBUG_ROUTE_INTRA;
1606 else if (! strncmp (argv[0], "inter", 5))
1607 level = OSPF6_DEBUG_ROUTE_INTER;
1608 else if (! strncmp (argv[0], "memor", 5))
1609 level = OSPF6_DEBUG_ROUTE_MEMORY;
1610 OSPF6_DEBUG_ROUTE_OFF (level);
1611 return CMD_SUCCESS;
1612 }
1613
1614 int
1615 config_write_ospf6_debug_route (struct vty *vty)
1616 {
1617 if (IS_OSPF6_DEBUG_ROUTE (TABLE))
1618 vty_out (vty, "debug ospf6 route table%s", VNL);
1619 if (IS_OSPF6_DEBUG_ROUTE (INTRA))
1620 vty_out (vty, "debug ospf6 route intra-area%s", VNL);
1621 if (IS_OSPF6_DEBUG_ROUTE (INTER))
1622 vty_out (vty, "debug ospf6 route inter-area%s", VNL);
1623 return 0;
1624 }
1625
1626 void
1627 install_element_ospf6_debug_route (void)
1628 {
1629 install_element (ENABLE_NODE, &debug_ospf6_route_cmd);
1630 install_element (ENABLE_NODE, &no_debug_ospf6_route_cmd);
1631 install_element (CONFIG_NODE, &debug_ospf6_route_cmd);
1632 install_element (CONFIG_NODE, &no_debug_ospf6_route_cmd);
1633 }
1634
1635
1636