]> git.proxmox.com Git - mirror_frr.git/blame - ospf6d/ospf6_route.c
redhat: Remove tab's with spaces in frr.spec.in to make it better readable
[mirror_frr.git] / ospf6d / ospf6_route.c
CommitLineData
718e3744 1/*
508e53e2 2 * Copyright (C) 2003 Yasuhiro Ohara
718e3744 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
508e53e2 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"
cf1ce250 30#include "linklist.h"
508e53e2 31
508e53e2 32#include "ospf6_proto.h"
33#include "ospf6_lsa.h"
049207c3 34#include "ospf6_lsdb.h"
508e53e2 35#include "ospf6_route.h"
cf1ce250
PJ
36#include "ospf6_top.h"
37#include "ospf6_area.h"
38#include "ospf6_interface.h"
049207c3 39#include "ospf6d.h"
c3c0ac83 40#include "ospf6_zebra.h"
718e3744 41
508e53e2 42unsigned char conf_debug_ospf6_route = 0;
718e3744 43
cf1ce250
PJ
44static char *
45ospf6_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
508e53e2 137void
138ospf6_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}
718e3744 147
508e53e2 148void
149ospf6_linkstate_prefix2str (struct prefix *prefix, char *buf, int size)
718e3744 150{
508e53e2 151 u_int32_t adv_router, id;
4846ef64 152 char adv_router_str[16], id_str[16];
508e53e2 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));
4846ef64 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);
508e53e2 161}
718e3744 162
508e53e2 163/* Global strings for logging */
0c083ee9 164const char *ospf6_dest_type_str[OSPF6_DEST_TYPE_MAX] =
4846ef64 165{ "Unknown", "Router", "Network", "Discard", "Linkstate", "AddressRange", };
718e3744 166
0c083ee9 167const char *ospf6_dest_type_substr[OSPF6_DEST_TYPE_MAX] =
4846ef64 168{ "?", "R", "N", "D", "L", "A", };
718e3744 169
0c083ee9 170const char *ospf6_path_type_str[OSPF6_PATH_TYPE_MAX] =
508e53e2 171{ "Unknown", "Intra-Area", "Inter-Area", "External-1", "External-2", };
718e3744 172
0c083ee9 173const char *ospf6_path_type_substr[OSPF6_PATH_TYPE_MAX] =
4846ef64 174{ "??", "IA", "IE", "E1", "E2", };
718e3744 175
718e3744 176
c3c0ac83
DS
177struct ospf6_nexthop *
178ospf6_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
186void
187ospf6_nexthop_delete (struct ospf6_nexthop *nh)
188{
189 if (nh)
190 XFREE (MTYPE_OSPF6_NEXTHOP, nh);
191}
192
193void
194ospf6_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
206void
207ospf6_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
219static struct ospf6_nexthop *
220ospf6_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
237void
238ospf6_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
257void
258ospf6_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
277int
278ospf6_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
302int
303ospf6_num_nexthops (struct list *nh_list)
304{
305 return (listcount(nh_list));
306}
307
308void
309ospf6_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
332void
333ospf6_route_zebra_copy_nexthops (struct ospf6_route *route,
b892f1dd 334 ifindex_t *ifindexes,
c3c0ac83
DS
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 {
322e5964 350 const char *ifname;
c3c0ac83 351 inet_ntop (AF_INET6, &nh->address, buf, sizeof (buf));
baaea325 352 ifname = ifindex2ifname (nh->ifindex, VRF_DEFAULT);
c3c0ac83
DS
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
370int
371ospf6_route_get_first_nh_index (struct ospf6_route *route)
372{
373 struct ospf6_nexthop *nh;
374
375 if (route)
376 {
ed2eb093 377 if ((nh = (struct ospf6_nexthop *)listhead (route->nh_list)))
c3c0ac83
DS
378 return (nh->ifindex);
379 }
380
381 return (-1);
382}
383
508e53e2 384struct ospf6_route *
6ac29a51 385ospf6_route_create (void)
718e3744 386{
508e53e2 387 struct ospf6_route *route;
388 route = XCALLOC (MTYPE_OSPF6_ROUTE, sizeof (struct ospf6_route));
c3c0ac83 389 route->nh_list = list_new();
508e53e2 390 return route;
391}
718e3744 392
508e53e2 393void
394ospf6_route_delete (struct ospf6_route *route)
395{
c3c0ac83
DS
396 if (route)
397 {
398 ospf6_free_nexthops (route->nh_list);
399 list_free (route->nh_list);
400 XFREE (MTYPE_OSPF6_ROUTE, route);
401 }
718e3744 402}
403
508e53e2 404struct ospf6_route *
405ospf6_route_copy (struct ospf6_route *route)
718e3744 406{
508e53e2 407 struct ospf6_route *new;
408
409 new = ospf6_route_create ();
c3c0ac83
DS
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);
508e53e2 419 new->rnode = NULL;
420 new->prev = NULL;
421 new->next = NULL;
cf1ce250 422 new->table = NULL;
508e53e2 423 new->lock = 0;
424 return new;
425}
718e3744 426
508e53e2 427void
428ospf6_route_lock (struct ospf6_route *route)
429{
430 route->lock++;
431}
718e3744 432
508e53e2 433void
434ospf6_route_unlock (struct ospf6_route *route)
435{
436 assert (route->lock > 0);
437 route->lock--;
438 if (route->lock == 0)
cf1ce250
PJ
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 }
508e53e2 446}
718e3744 447
508e53e2 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 */
c3c0ac83 451int
508e53e2 452ospf6_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);
718e3744 459
508e53e2 460 if (ra->type != rb->type)
461 return (ra->type - rb->type);
718e3744 462
508e53e2 463 if (ra->path.area_id != rb->path.area_id)
464 return (ntohl (ra->path.area_id) - ntohl (rb->path.area_id));
718e3744 465
508e53e2 466 if (ra->path.type != rb->path.type)
467 return (ra->path.type - rb->path.type);
718e3744 468
508e53e2 469 if (ra->path.type == OSPF6_PATH_TYPE_EXTERNAL2)
470 {
c3c0ac83
DS
471 if (ra->path.u.cost_e2 != rb->path.u.cost_e2)
472 return (ra->path.u.cost_e2 - rb->path.u.cost_e2);
718e3744 473 }
508e53e2 474 else
718e3744 475 {
508e53e2 476 if (ra->path.cost != rb->path.cost)
477 return (ra->path.cost - rb->path.cost);
718e3744 478 }
718e3744 479
508e53e2 480 return 0;
718e3744 481}
482
508e53e2 483struct ospf6_route *
484ospf6_route_lookup (struct prefix *prefix,
718e3744 485 struct ospf6_route_table *table)
486{
487 struct route_node *node;
508e53e2 488 struct ospf6_route *route;
718e3744 489
490 node = route_node_lookup (table->table, prefix);
508e53e2 491 if (node == NULL)
492 return NULL;
493
494 route = (struct ospf6_route *) node->info;
495 return route;
496}
718e3744 497
508e53e2 498struct ospf6_route *
499ospf6_route_lookup_identical (struct ospf6_route *route,
500 struct ospf6_route_table *table)
501{
502 struct ospf6_route *target;
718e3744 503
508e53e2 504 for (target = ospf6_route_lookup (&route->prefix, table);
505 target; target = target->next)
718e3744 506 {
508e53e2 507 if (ospf6_route_is_identical (target, route))
508 return target;
718e3744 509 }
508e53e2 510 return NULL;
718e3744 511}
512
508e53e2 513struct ospf6_route *
514ospf6_route_lookup_bestmatch (struct prefix *prefix,
515 struct ospf6_route_table *table)
718e3744 516{
517 struct route_node *node;
508e53e2 518 struct ospf6_route *route;
718e3744 519
508e53e2 520 node = route_node_match (table->table, prefix);
521 if (node == NULL)
522 return NULL;
523 route_unlock_node (node);
718e3744 524
508e53e2 525 route = (struct ospf6_route *) node->info;
526 return route;
718e3744 527}
528
e39d0538 529#ifdef DEBUG
508e53e2 530static void
cf1ce250 531route_table_assert (struct ospf6_route_table *table)
718e3744 532{
cf1ce250 533 struct ospf6_route *prev, *r, *next;
4690c7d7 534 char buf[PREFIX2STR_BUFFER];
cf1ce250
PJ
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))
508e53e2 554 num++;
cf1ce250
PJ
555
556 if (link_error == 0 && num == table->count)
ccb59b11 557 return;
558
cf1ce250
PJ
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))
ccb59b11 564 {
cf1ce250
PJ
565 prefix2str (&r->prefix, buf, sizeof (buf));
566 zlog_info ("%p<-[%p]->%p : %s", r->prev, r, r->next, buf);
ccb59b11 567 }
c6487d61 568 zlog_debug ("DUMP END");
ccb59b11 569
cf1ce250 570 assert (link_error == 0 && num == table->count);
718e3744 571}
cf1ce250 572#define ospf6_route_table_assert(t) (route_table_assert (t))
508e53e2 573#else
cf1ce250 574#define ospf6_route_table_assert(t) ((void) 0)
e39d0538 575#endif /*DEBUG*/
718e3744 576
508e53e2 577struct ospf6_route *
578ospf6_route_add (struct ospf6_route *route,
579 struct ospf6_route_table *table)
718e3744 580{
508e53e2 581 struct route_node *node, *nextnode, *prevnode;
582 struct ospf6_route *current = NULL;
583 struct ospf6_route *prev = NULL, *old = NULL, *next = NULL;
4690c7d7 584 char buf[PREFIX2STR_BUFFER];
508e53e2 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));
718e3744 596
cf1ce250
PJ
597 if (IS_OSPF6_DEBUG_ROUTE (MEMORY))
598 zlog_debug ("%s %p: route add %p: %s", ospf6_route_table_name (table),
6c4f4e6e 599 (void *)table, (void *)route, buf);
cf1ce250
PJ
600 else if (IS_OSPF6_DEBUG_ROUTE (TABLE))
601 zlog_debug ("%s: route add: %s", ospf6_route_table_name (table), buf);
718e3744 602
cf672a86 603 monotime(&now);
718e3744 604
508e53e2 605 node = route_node_get (table->table, &route->prefix);
606 route->rnode = node;
718e3744 607
508e53e2 608 /* find place to insert */
609 for (current = node->info; current; current = current->next)
718e3744 610 {
508e53e2 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;
718e3744 621
508e53e2 622 if (old || next)
623 break;
718e3744 624 }
508e53e2 625
626 if (old)
718e3744 627 {
508e53e2 628 /* if route does not actually change, return unchanged */
629 if (ospf6_route_is_identical (old, route))
630 {
cf1ce250
PJ
631 if (IS_OSPF6_DEBUG_ROUTE (MEMORY))
632 zlog_debug ("%s %p: route add %p: needless update of %p",
6c4f4e6e
DL
633 ospf6_route_table_name (table),
634 (void *)table, (void *)route, (void *)old);
cf1ce250
PJ
635 else if (IS_OSPF6_DEBUG_ROUTE (TABLE))
636 zlog_debug ("%s: route add: needless update",
637 ospf6_route_table_name (table));
718e3744 638
508e53e2 639 ospf6_route_delete (route);
640 SET_FLAG (old->flag, OSPF6_ROUTE_ADD);
cf1ce250 641 ospf6_route_table_assert (table);
9428f2dc 642
508e53e2 643 return old;
644 }
718e3744 645
cf1ce250
PJ
646 if (IS_OSPF6_DEBUG_ROUTE (MEMORY))
647 zlog_debug ("%s %p: route add %p: update of %p",
6c4f4e6e
DL
648 ospf6_route_table_name (table),
649 (void *)table, (void *)route, (void *)old);
cf1ce250
PJ
650 else if (IS_OSPF6_DEBUG_ROUTE (TABLE))
651 zlog_debug ("%s: route add: update",
652 ospf6_route_table_name (table));
718e3744 653
508e53e2 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 }
718e3744 660
508e53e2 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;
718e3744 667
508e53e2 668 route->installed = old->installed;
669 route->changed = now;
cf1ce250
PJ
670 assert (route->table == NULL);
671 route->table = table;
718e3744 672
508e53e2 673 ospf6_route_unlock (old); /* will be deleted later */
674 ospf6_route_lock (route);
718e3744 675
508e53e2 676 SET_FLAG (route->flag, OSPF6_ROUTE_CHANGE);
cf1ce250 677 ospf6_route_table_assert (table);
9428f2dc 678
508e53e2 679 if (table->hook_add)
680 (*table->hook_add) (route);
718e3744 681
508e53e2 682 return route;
683 }
718e3744 684
508e53e2 685 /* insert if previous or next node found */
686 if (prev || next)
687 {
cf1ce250
PJ
688 if (IS_OSPF6_DEBUG_ROUTE (MEMORY))
689 zlog_debug ("%s %p: route add %p: another path: prev %p, next %p",
6c4f4e6e
DL
690 ospf6_route_table_name (table),
691 (void *)table, (void *)route, (void *)prev, (void *)next);
cf1ce250
PJ
692 else if (IS_OSPF6_DEBUG_ROUTE (TABLE))
693 zlog_debug ("%s: route add: another path found",
694 ospf6_route_table_name (table));
508e53e2 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);
cf1ce250
PJ
714 if (IS_OSPF6_DEBUG_ROUTE (MEMORY))
715 zlog_info ("%s %p: route add %p: replacing previous best: %p",
6c4f4e6e
DL
716 ospf6_route_table_name (table),
717 (void *)table, (void *)route, (void *)next);
508e53e2 718 }
718e3744 719
508e53e2 720 route->installed = now;
721 route->changed = now;
cf1ce250
PJ
722 assert (route->table == NULL);
723 route->table = table;
718e3744 724
508e53e2 725 ospf6_route_lock (route);
726 table->count++;
cf1ce250 727 ospf6_route_table_assert (table);
508e53e2 728
729 SET_FLAG (route->flag, OSPF6_ROUTE_ADD);
730 if (table->hook_add)
731 (*table->hook_add) (route);
718e3744 732
508e53e2 733 return route;
718e3744 734 }
735
508e53e2 736 /* Else, this is the brand new route regarding to the prefix */
cf1ce250
PJ
737 if (IS_OSPF6_DEBUG_ROUTE (MEMORY))
738 zlog_debug ("%s %p: route add %p: brand new route",
6c4f4e6e 739 ospf6_route_table_name (table), (void *)table, (void *)route);
cf1ce250
PJ
740 else if (IS_OSPF6_DEBUG_ROUTE (TABLE))
741 zlog_debug ("%s: route add: brand new route",
742 ospf6_route_table_name (table));
508e53e2 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;
cf1ce250
PJ
750 assert (route->table == NULL);
751 route->table = table;
508e53e2 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
718e3744 764 {
508e53e2 765 route_unlock_node (nextnode);
766
767 next = nextnode->info;
768 route->next = next;
769 next->prev = route;
718e3744 770 }
718e3744 771
508e53e2 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);
718e3744 778
508e53e2 779 /* set prev link */
780 if (prevnode == NULL)
781 route->prev = NULL;
782 else
718e3744 783 {
508e53e2 784 route_unlock_node (prevnode);
718e3744 785
508e53e2 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;
718e3744 791 }
508e53e2 792
793 table->count++;
cf1ce250 794 ospf6_route_table_assert (table);
508e53e2 795
796 SET_FLAG (route->flag, OSPF6_ROUTE_ADD);
797 if (table->hook_add)
798 (*table->hook_add) (route);
799
508e53e2 800 return route;
718e3744 801}
802
803void
508e53e2 804ospf6_route_remove (struct ospf6_route *route,
805 struct ospf6_route_table *table)
718e3744 806{
508e53e2 807 struct route_node *node;
808 struct ospf6_route *current;
4690c7d7 809 char buf[PREFIX2STR_BUFFER];
718e3744 810
508e53e2 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));
718e3744 815
cf1ce250
PJ
816 if (IS_OSPF6_DEBUG_ROUTE (MEMORY))
817 zlog_debug ("%s %p: route remove %p: %s",
6c4f4e6e
DL
818 ospf6_route_table_name (table),
819 (void *)table, (void *)route, buf);
cf1ce250
PJ
820 else if (IS_OSPF6_DEBUG_ROUTE (TABLE))
821 zlog_debug ("%s: route remove: %s", ospf6_route_table_name (table), buf);
718e3744 822
508e53e2 823 node = route_node_lookup (table->table, &route->prefix);
824 assert (node);
718e3744 825
508e53e2 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))
718e3744 830 {
508e53e2 831 if (current == route)
832 break;
833 current = current->next;
718e3744 834 }
508e53e2 835 assert (current == route);
718e3744 836
508e53e2 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;
718e3744 842
508e53e2 843 if (node->info == route)
718e3744 844 {
0f23bb67 845 if (route->next && route->next->rnode == node)
718e3744 846 {
508e53e2 847 node->info = route->next;
848 SET_FLAG (route->next->flag, OSPF6_ROUTE_BEST);
718e3744 849 }
508e53e2 850 else
851 node->info = NULL; /* should unlock route_node here ? */
718e3744 852 }
853
9428f2dc 854 table->count--;
cf1ce250 855 ospf6_route_table_assert (table);
9428f2dc 856
857 SET_FLAG (route->flag, OSPF6_ROUTE_WAS_REMOVED);
858
508e53e2 859 if (table->hook_remove)
860 (*table->hook_remove) (route);
718e3744 861
508e53e2 862 ospf6_route_unlock (route);
508e53e2 863}
718e3744 864
508e53e2 865struct ospf6_route *
866ospf6_route_head (struct ospf6_route_table *table)
867{
868 struct route_node *node;
869 struct ospf6_route *route;
718e3744 870
508e53e2 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;
718e3744 880
508e53e2 881 route_unlock_node (node);
882 assert (node->info);
883
884 route = (struct ospf6_route *) node->info;
885 assert (route->prev == NULL);
cf1ce250 886 assert (route->table == table);
508e53e2 887 ospf6_route_lock (route);
cf1ce250
PJ
888
889 if (IS_OSPF6_DEBUG_ROUTE (MEMORY))
890 zlog_info ("%s %p: route head: %p<-[%p]->%p",
6c4f4e6e
DL
891 ospf6_route_table_name (table), (void *)table,
892 (void *)route->prev, (void *)route, (void *)route->next);
cf1ce250 893
508e53e2 894 return route;
718e3744 895}
896
508e53e2 897struct ospf6_route *
898ospf6_route_next (struct ospf6_route *route)
718e3744 899{
508e53e2 900 struct ospf6_route *next = route->next;
718e3744 901
cf1ce250
PJ
902 if (IS_OSPF6_DEBUG_ROUTE (MEMORY))
903 zlog_info ("%s %p: route next: %p<-[%p]->%p",
6c4f4e6e
DL
904 ospf6_route_table_name (route->table), (void *)route->table,
905 (void *)route->prev, (void *)route, (void *)route->next);
cf1ce250 906
508e53e2 907 ospf6_route_unlock (route);
908 if (next)
909 ospf6_route_lock (next);
718e3744 910
508e53e2 911 return next;
912}
718e3744 913
508e53e2 914struct ospf6_route *
915ospf6_route_best_next (struct ospf6_route *route)
916{
917 struct route_node *rnode;
918 struct ospf6_route *next;
919
e7a6d80d
TG
920 ospf6_route_unlock (route);
921
508e53e2 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;
508e53e2 933 ospf6_route_lock (next);
934 return next;
935}
718e3744 936
508e53e2 937struct ospf6_route *
938ospf6_route_match_head (struct prefix *prefix,
939 struct ospf6_route_table *table)
940{
941 struct route_node *node;
942 struct ospf6_route *route;
718e3744 943
508e53e2 944 /* Walk down tree. */
945 node = table->table->top;
946 while (node && node->p.prefixlen < prefix->prefixlen &&
947 prefix_match (&node->p, prefix))
1352ef32 948 node = node->link[prefix_bit(&prefix->u.prefix, node->p.prefixlen)];
718e3744 949
508e53e2 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);
718e3744 957
508e53e2 958 if (! prefix_match (prefix, &node->p))
959 return NULL;
718e3744 960
508e53e2 961 route = node->info;
962 ospf6_route_lock (route);
963 return route;
964}
718e3744 965
508e53e2 966struct ospf6_route *
967ospf6_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;
718e3744 980}
981
982void
983ospf6_route_remove_all (struct ospf6_route_table *table)
984{
508e53e2 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);
718e3744 989}
990
718e3744 991struct ospf6_route_table *
cf1ce250 992ospf6_route_table_create (int s, int t)
718e3744 993{
718e3744 994 struct ospf6_route_table *new;
718e3744 995 new = XCALLOC (MTYPE_OSPF6_ROUTE, sizeof (struct ospf6_route_table));
718e3744 996 new->table = route_table_init ();
cf1ce250
PJ
997 new->scope_type = s;
998 new->table_type = t;
718e3744 999 return new;
1000}
1001
1002void
1003ospf6_route_table_delete (struct ospf6_route_table *table)
1004{
718e3744 1005 ospf6_route_remove_all (table);
1006 route_table_finish (table->table);
718e3744 1007 XFREE (MTYPE_OSPF6_ROUTE, table);
1008}
1009
6b0655a2 1010
508e53e2 1011/* VTY commands */
718e3744 1012void
508e53e2 1013ospf6_route_show (struct vty *vty, struct ospf6_route *route)
718e3744 1014{
508e53e2 1015 int i;
4690c7d7 1016 char destination[PREFIX2STR_BUFFER], nexthop[64];
322e5964
FL
1017 char duration[16];
1018 const char *ifname;
508e53e2 1019 struct timeval now, res;
c3c0ac83
DS
1020 struct listnode *node;
1021 struct ospf6_nexthop *nh;
718e3744 1022
cf672a86 1023 monotime(&now);
508e53e2 1024 timersub (&now, &route->changed, &res);
1025 timerstring (&res, duration, sizeof (duration));
718e3744 1026
508e53e2 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
c3c0ac83
DS
1037 i = 0;
1038 for (ALL_LIST_ELEMENTS_RO (route->nh_list, node, nh))
718e3744 1039 {
508e53e2 1040 /* nexthop */
c3c0ac83 1041 inet_ntop (AF_INET6, &nh->address, nexthop,
508e53e2 1042 sizeof (nexthop));
baaea325 1043 ifname = ifindex2ifname (nh->ifindex, VRF_DEFAULT);
c3c0ac83
DS
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);
718e3744 1057 }
1058}
1059
718e3744 1060void
508e53e2 1061ospf6_route_show_detail (struct vty *vty, struct ospf6_route *route)
718e3744 1062{
322e5964
FL
1063 const char *ifname;
1064 char destination[PREFIX2STR_BUFFER], nexthop[64];
508e53e2 1065 char area_id[16], id[16], adv_router[16], capa[16], options[16];
718e3744 1066 struct timeval now, res;
1067 char duration[16];
c3c0ac83
DS
1068 struct listnode *node;
1069 struct ospf6_nexthop *nh;
718e3744 1070
cf672a86 1071 monotime(&now);
718e3744 1072
1073 /* destination */
508e53e2 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));
718e3744 1080 else
508e53e2 1081 prefix2str (&route->prefix, destination, sizeof (destination));
049207c3 1082 vty_out (vty, "Destination: %s%s", destination, VNL);
508e53e2 1083
1084 /* destination type */
1085 vty_out (vty, "Destination type: %s%s",
1086 OSPF6_DEST_TYPE_NAME (route->type),
049207c3 1087 VNL);
508e53e2 1088
1089 /* Time */
1090 timersub (&now, &route->installed, &res);
1091 timerstring (&res, duration, sizeof (duration));
049207c3 1092 vty_out (vty, "Installed Time: %s ago%s", duration, VNL);
508e53e2 1093
1094 timersub (&now, &route->changed, &res);
1095 timerstring (&res, duration, sizeof (duration));
049207c3 1096 vty_out (vty, " Changed Time: %s ago%s", duration, VNL);
508e53e2 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" : "-"),
049207c3 1104 VNL);
508e53e2 1105 vty_out (vty, "Memory: prev: %p this: %p next: %p%s",
6c4f4e6e 1106 (void *)route->prev, (void *)route, (void *)route->next, VNL);
508e53e2 1107
1108 /* Path section */
1109
1110 /* Area-ID */
1111 inet_ntop (AF_INET, &route->path.area_id, area_id, sizeof (area_id));
049207c3 1112 vty_out (vty, "Associated Area: %s%s", area_id, VNL);
508e53e2 1113
1114 /* Path type */
1115 vty_out (vty, "Path Type: %s%s",
049207c3 1116 OSPF6_PATH_TYPE_NAME (route->path.type), VNL);
508e53e2 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",
1e05838a 1123 ospf6_lstype_name (route->path.origin.type),
049207c3 1124 id, adv_router, VNL);
508e53e2 1125
1126 /* Options */
1127 ospf6_options_printbuf (route->path.options, options, sizeof (options));
049207c3 1128 vty_out (vty, "Options: %s%s", options, VNL);
508e53e2 1129
1130 /* Router Bits */
1131 ospf6_capability_printbuf (route->path.router_bits, capa, sizeof (capa));
049207c3 1132 vty_out (vty, "Router Bits: %s%s", capa, VNL);
508e53e2 1133
1134 /* Prefix Options */
049207c3 1135 vty_out (vty, "Prefix Options: xxx%s", VNL);
508e53e2 1136
1137 /* Metrics */
1138 vty_out (vty, "Metric Type: %d%s", route->path.metric_type,
049207c3 1139 VNL);
508e53e2 1140 vty_out (vty, "Metric: %d (%d)%s",
c3c0ac83 1141 route->path.cost, route->path.u.cost_e2, VNL);
508e53e2 1142
1143 /* Nexthops */
049207c3 1144 vty_out (vty, "Nexthop:%s", VNL);
c3c0ac83 1145 for (ALL_LIST_ELEMENTS_RO (route->nh_list, node, nh))
508e53e2 1146 {
1147 /* nexthop */
c3c0ac83 1148 inet_ntop (AF_INET6, &nh->address, nexthop, sizeof (nexthop));
baaea325 1149 ifname = ifindex2ifname (nh->ifindex, VRF_DEFAULT);
3b7b814c 1150 vty_out (vty, " %s %.*s%s", nexthop, IFNAMSIZ, ifname, VNL);
508e53e2 1151 }
049207c3 1152 vty_out (vty, "%s", VNL);
508e53e2 1153}
718e3744 1154
6ac29a51 1155static void
508e53e2 1156ospf6_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];
0c083ee9 1161 unsigned int number = 0;
c3c0ac83 1162 int nh_count =0 , nhinval = 0, ecmp = 0;
4846ef64 1163 int alternative = 0, destination = 0;
508e53e2 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))
718e3744 1170 {
508e53e2 1171 if (prev == NULL || ! ospf6_route_is_same (prev, route))
1172 destination++;
1173 else
4846ef64 1174 alternative++;
c3c0ac83
DS
1175 nh_count = ospf6_num_nexthops (route->nh_list);
1176 if (!nh_count)
508e53e2 1177 nhinval++;
c3c0ac83 1178 else if (nh_count > 1)
508e53e2 1179 ecmp++;
4846ef64 1180 pathtype[route->path.type]++;
508e53e2 1181 number++;
4846ef64 1182
508e53e2 1183 prev = route;
1184 }
718e3744 1185
508e53e2 1186 assert (number == table->count);
508e53e2 1187
4846ef64 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
6ac29a51 1199static void
4846ef64 1200ospf6_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
6ac29a51 1221static void
4846ef64 1222ospf6_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
6ac29a51 1244static void
4846ef64 1245ospf6_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
6ac29a51 1263static void
4846ef64 1264ospf6_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
6ac29a51 1283static void
4846ef64 1284ospf6_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)
508e53e2 1291 {
4846ef64 1292 if (detail)
1293 ospf6_route_show_detail (vty, route);
1294 else
1295 ospf6_route_show (vty, route);
1296 route = ospf6_route_next (route);
718e3744 1297 }
1298}
1299
508e53e2 1300int
1d68dbfe 1301ospf6_route_table_show (struct vty *vty, int argc_start, int argc, struct cmd_token **argv,
508e53e2 1302 struct ospf6_route_table *table)
718e3744 1303{
4846ef64 1304 int summary = 0;
1305 int match = 0;
1306 int detail = 0;
1307 int slash = 0;
1308 int isprefix = 0;
508e53e2 1309 int i, ret;
4846ef64 1310 struct prefix prefix;
1311 u_char type = 0;
718e3744 1312
508e53e2 1313 memset (&prefix, 0, sizeof (struct prefix));
718e3744 1314
1d68dbfe 1315 for (i = argc_start; i < argc; i++)
508e53e2 1316 {
cc9de1ba 1317 if (! strcmp (argv[i]->arg, "summary"))
508e53e2 1318 {
4846ef64 1319 summary++;
508e53e2 1320 continue;
1321 }
718e3744 1322
cc9de1ba 1323 if (! strcmp (argv[i]->arg, "intra-area"))
508e53e2 1324 {
4846ef64 1325 type = OSPF6_PATH_TYPE_INTRA;
508e53e2 1326 continue;
1327 }
1328
cc9de1ba 1329 if (! strcmp (argv[i]->arg, "inter-area"))
508e53e2 1330 {
4846ef64 1331 type = OSPF6_PATH_TYPE_INTER;
508e53e2 1332 continue;
1333 }
718e3744 1334
cc9de1ba 1335 if (! strcmp (argv[i]->arg, "external-1"))
508e53e2 1336 {
4846ef64 1337 type = OSPF6_PATH_TYPE_EXTERNAL1;
1338 continue;
1339 }
1340
cc9de1ba 1341 if (! strcmp (argv[i]->arg, "external-2"))
4846ef64 1342 {
1343 type = OSPF6_PATH_TYPE_EXTERNAL2;
1344 continue;
1345 }
1346
cc9de1ba 1347 if (! strcmp (argv[i]->arg, "detail"))
4846ef64 1348 {
1349 detail++;
1350 continue;
1351 }
1352
cc9de1ba 1353 if (! strcmp (argv[i]->arg, "match"))
4846ef64 1354 {
1355 match++;
1356 continue;
508e53e2 1357 }
718e3744 1358
cc9de1ba 1359 ret = str2prefix (argv[i]->arg, &prefix);
4846ef64 1360 if (ret == 1 && prefix.family == AF_INET6)
718e3744 1361 {
4846ef64 1362 isprefix++;
cc9de1ba 1363 if (strchr (argv[i]->arg, '/'))
4846ef64 1364 slash++;
1365 continue;
508e53e2 1366 }
718e3744 1367
cc9de1ba 1368 vty_out (vty, "Malformed argument: %s%s", argv[i]->arg, VNL);
4846ef64 1369 return CMD_SUCCESS;
508e53e2 1370 }
718e3744 1371
508e53e2 1372 /* Give summary of this route table */
4846ef64 1373 if (summary)
508e53e2 1374 {
1375 ospf6_route_show_table_summary (vty, table);
1376 return CMD_SUCCESS;
1377 }
718e3744 1378
508e53e2 1379 /* Give exact prefix-match route */
4846ef64 1380 if (isprefix && ! match)
508e53e2 1381 {
1382 /* If exact address, give best matching route */
4846ef64 1383 if (! slash)
1384 ospf6_route_show_table_address (vty, &prefix, table);
508e53e2 1385 else
4846ef64 1386 ospf6_route_show_table_prefix (vty, &prefix, table);
508e53e2 1387
4846ef64 1388 return CMD_SUCCESS;
1389 }
508e53e2 1390
4846ef64 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);
508e53e2 1397
4846ef64 1398 return CMD_SUCCESS;
1399}
508e53e2 1400
6ac29a51 1401static void
4846ef64 1402ospf6_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
6ac29a51 1408static void
4846ef64 1409ospf6_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));
508e53e2 1421
4846ef64 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);
508e53e2 1426 else
4846ef64 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
6ac29a51 1433static void
4846ef64 1434ospf6_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
6ac29a51 1455static void
4846ef64 1456ospf6_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);
508e53e2 1463
4846ef64 1464 route = ospf6_route_head (table);
508e53e2 1465 while (route)
1466 {
4846ef64 1467 if (detail)
508e53e2 1468 ospf6_route_show_detail (vty, route);
1469 else
4846ef64 1470 ospf6_linkstate_show (vty, route);
1471 route = ospf6_route_next (route);
508e53e2 1472 }
718e3744 1473}
1474
1475int
093d7a3a
DW
1476ospf6_linkstate_table_show (struct vty *vty, int idx_ipv4, int argc,
1477 struct cmd_token **argv,
4846ef64 1478 struct ospf6_route_table *table)
718e3744 1479{
4846ef64 1480 int detail = 0;
1481 int is_id = 0;
1482 int is_router = 0;
718e3744 1483 int i, ret;
4846ef64 1484 struct prefix router, id, prefix;
718e3744 1485
4846ef64 1486 memset (&router, 0, sizeof (struct prefix));
508e53e2 1487 memset (&id, 0, sizeof (struct prefix));
4846ef64 1488 memset (&prefix, 0, sizeof (struct prefix));
718e3744 1489
093d7a3a 1490 for (i = idx_ipv4; i < argc; i++)
718e3744 1491 {
cc9de1ba 1492 if (! strcmp (argv[i]->arg, "detail"))
718e3744 1493 {
4846ef64 1494 detail++;
508e53e2 1495 continue;
718e3744 1496 }
1497
4846ef64 1498 if (! is_router)
718e3744 1499 {
cc9de1ba 1500 ret = str2prefix (argv[i]->arg, &router);
4846ef64 1501 if (ret == 1 && router.family == AF_INET)
718e3744 1502 {
4846ef64 1503 is_router++;
1504 continue;
718e3744 1505 }
cc9de1ba 1506 vty_out (vty, "Malformed argument: %s%s", argv[i]->arg, VNL);
4846ef64 1507 return CMD_SUCCESS;
508e53e2 1508 }
508e53e2 1509
4846ef64 1510 if (! is_id)
1511 {
cc9de1ba 1512 ret = str2prefix (argv[i]->arg, &id);
4846ef64 1513 if (ret == 1 && id.family == AF_INET)
718e3744 1514 {
4846ef64 1515 is_id++;
1516 continue;
718e3744 1517 }
cc9de1ba 1518 vty_out (vty, "Malformed argument: %s%s", argv[i]->arg, VNL);
508e53e2 1519 return CMD_SUCCESS;
1520 }
1521
cc9de1ba 1522 vty_out (vty, "Malformed argument: %s%s", argv[i]->arg, VNL);
508e53e2 1523 return CMD_SUCCESS;
718e3744 1524 }
1525
4846ef64 1526 if (is_router)
1527 ospf6_linkstate_prefix (router.u.prefix4.s_addr,
1528 id.u.prefix4.s_addr, &prefix);
718e3744 1529
4846ef64 1530 if (prefix.family)
1531 ospf6_linkstate_show_table_exact (vty, &prefix, table);
1532 else
1533 ospf6_linkstate_show_table (vty, detail, table);
718e3744 1534
508e53e2 1535 return CMD_SUCCESS;
1536}
718e3744 1537
4846ef64 1538
6452df09 1539void
1540ospf6_brouter_show_header (struct vty *vty)
1541{
1542 vty_out (vty, "%-15s %-8s %-14s %-10s %-15s%s",
1543 "Router-ID", "Rtr-Bits", "Options", "Path-Type", "Area", VNL);
1544}
1545
1546void
1547ospf6_brouter_show (struct vty *vty, struct ospf6_route *route)
1548{
1549 u_int32_t adv_router;
1550 char adv[16], rbits[16], options[16], area[16];
1551
1552 adv_router = ospf6_linkstate_prefix_adv_router (&route->prefix);
1553 inet_ntop (AF_INET, &adv_router, adv, sizeof (adv));
1554 ospf6_capability_printbuf (route->path.router_bits, rbits, sizeof (rbits));
1555 ospf6_options_printbuf (route->path.options, options, sizeof (options));
1556 inet_ntop (AF_INET, &route->path.area_id, area, sizeof (area));
1557
1558 /* vty_out (vty, "%-15s %-8s %-14s %-10s %-15s%s",
1559 "Router-ID", "Rtr-Bits", "Options", "Path-Type", "Area", VNL); */
1560 vty_out (vty, "%-15s %-8s %-14s %-10s %-15s%s",
1561 adv, rbits, options, OSPF6_PATH_TYPE_NAME (route->path.type),
1562 area, VNL);
1563}
1564
508e53e2 1565DEFUN (debug_ospf6_route,
1566 debug_ospf6_route_cmd,
6147e2c6 1567 "debug ospf6 route <table|intra-area|inter-area|memory>",
508e53e2 1568 DEBUG_STR
1569 OSPF6_STR
16cedbb0 1570 "Debug routes\n"
508e53e2 1571 "Debug route table calculation\n"
508e53e2 1572 "Debug intra-area route calculation\n"
1573 "Debug inter-area route calculation\n"
8f228de7 1574 "Debug route memory use\n"
508e53e2 1575 )
1576{
51c26414 1577 int idx_type = 3;
508e53e2 1578 unsigned char level = 0;
1579
51c26414 1580 if (! strncmp (argv[idx_type]->arg, "table", 5))
508e53e2 1581 level = OSPF6_DEBUG_ROUTE_TABLE;
51c26414 1582 else if (! strncmp (argv[idx_type]->arg, "intra", 5))
508e53e2 1583 level = OSPF6_DEBUG_ROUTE_INTRA;
51c26414 1584 else if (! strncmp (argv[idx_type]->arg, "inter", 5))
508e53e2 1585 level = OSPF6_DEBUG_ROUTE_INTER;
51c26414 1586 else if (! strncmp (argv[idx_type]->arg, "memor", 5))
8f228de7 1587 level = OSPF6_DEBUG_ROUTE_MEMORY;
508e53e2 1588 OSPF6_DEBUG_ROUTE_ON (level);
1589 return CMD_SUCCESS;
1590}
1591
1592DEFUN (no_debug_ospf6_route,
1593 no_debug_ospf6_route_cmd,
6147e2c6 1594 "no debug ospf6 route <table|intra-area|inter-area|memory>",
508e53e2 1595 NO_STR
1596 DEBUG_STR
1597 OSPF6_STR
16cedbb0 1598 "Debug routes\n"
508e53e2 1599 "Debug route table calculation\n"
8f228de7 1600 "Debug intra-area route calculation\n"
16cedbb0 1601 "Debug inter-area route calculation\n"
8f228de7 1602 "Debug route memory use\n")
508e53e2 1603{
51c26414 1604 int idx_type = 4;
508e53e2 1605 unsigned char level = 0;
1606
51c26414 1607 if (! strncmp (argv[idx_type]->arg, "table", 5))
508e53e2 1608 level = OSPF6_DEBUG_ROUTE_TABLE;
51c26414 1609 else if (! strncmp (argv[idx_type]->arg, "intra", 5))
508e53e2 1610 level = OSPF6_DEBUG_ROUTE_INTRA;
51c26414 1611 else if (! strncmp (argv[idx_type]->arg, "inter", 5))
508e53e2 1612 level = OSPF6_DEBUG_ROUTE_INTER;
51c26414 1613 else if (! strncmp (argv[idx_type]->arg, "memor", 5))
8f228de7 1614 level = OSPF6_DEBUG_ROUTE_MEMORY;
508e53e2 1615 OSPF6_DEBUG_ROUTE_OFF (level);
718e3744 1616 return CMD_SUCCESS;
1617}
1618
508e53e2 1619int
1620config_write_ospf6_debug_route (struct vty *vty)
1621{
1622 if (IS_OSPF6_DEBUG_ROUTE (TABLE))
049207c3 1623 vty_out (vty, "debug ospf6 route table%s", VNL);
508e53e2 1624 if (IS_OSPF6_DEBUG_ROUTE (INTRA))
049207c3 1625 vty_out (vty, "debug ospf6 route intra-area%s", VNL);
508e53e2 1626 if (IS_OSPF6_DEBUG_ROUTE (INTER))
049207c3 1627 vty_out (vty, "debug ospf6 route inter-area%s", VNL);
508e53e2 1628 return 0;
1629}
1630
1631void
6ac29a51 1632install_element_ospf6_debug_route (void)
508e53e2 1633{
1634 install_element (ENABLE_NODE, &debug_ospf6_route_cmd);
1635 install_element (ENABLE_NODE, &no_debug_ospf6_route_cmd);
1636 install_element (CONFIG_NODE, &debug_ospf6_route_cmd);
1637 install_element (CONFIG_NODE, &no_debug_ospf6_route_cmd);
1638}
1639
1640
1641