blob: 30927737a64928ad787ba80a60e3333994fcb924 [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/*
hasso508e53e2004-05-18 18:57:06 +00002 * Copyright (C) 2003 Yasuhiro Ohara
paul718e3742002-12-13 20:15:29 +00003 *
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
hasso508e53e2004-05-18 18:57:06 +000022#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"
Paul Jakmacf1ce252006-05-15 10:46:07 +000030#include "linklist.h"
hasso508e53e2004-05-18 18:57:06 +000031
hasso508e53e2004-05-18 18:57:06 +000032#include "ospf6_proto.h"
33#include "ospf6_lsa.h"
hasso049207c2004-08-04 20:02:13 +000034#include "ospf6_lsdb.h"
hasso508e53e2004-05-18 18:57:06 +000035#include "ospf6_route.h"
Paul Jakmacf1ce252006-05-15 10:46:07 +000036#include "ospf6_top.h"
37#include "ospf6_area.h"
38#include "ospf6_interface.h"
hasso049207c2004-08-04 20:02:13 +000039#include "ospf6d.h"
paul718e3742002-12-13 20:15:29 +000040
hasso508e53e2004-05-18 18:57:06 +000041unsigned char conf_debug_ospf6_route = 0;
42
Paul Jakmacf1ce252006-05-15 10:46:07 +000043static char *
44ospf6_route_table_name (struct ospf6_route_table *table)
45{
46 static char name[32];
47 switch (table->scope_type)
48 {
49 case OSPF6_SCOPE_TYPE_GLOBAL:
50 {
51 switch (table->table_type)
52 {
53 case OSPF6_TABLE_TYPE_ROUTES:
54 snprintf (name, sizeof (name), "global route table");
55 break;
56 case OSPF6_TABLE_TYPE_BORDER_ROUTERS:
57 snprintf (name, sizeof (name), "global brouter table");
58 break;
59 case OSPF6_TABLE_TYPE_EXTERNAL_ROUTES:
60 snprintf (name, sizeof (name), "global external table");
61 break;
62 default:
63 snprintf (name, sizeof (name), "global unknown table");
64 break;
65 }
66 }
67 break;
68
69 case OSPF6_SCOPE_TYPE_AREA:
70 {
71 struct ospf6_area *oa = (struct ospf6_area *) table->scope;
72 switch (table->table_type)
73 {
74 case OSPF6_TABLE_TYPE_SPF_RESULTS:
75 snprintf (name, sizeof (name),
76 "area %s spf table", oa->name);
77 break;
78 case OSPF6_TABLE_TYPE_ROUTES:
79 snprintf (name, sizeof (name),
80 "area %s route table", oa->name);
81 break;
82 case OSPF6_TABLE_TYPE_PREFIX_RANGES:
83 snprintf (name, sizeof (name),
84 "area %s range table", oa->name);
85 break;
86 case OSPF6_TABLE_TYPE_SUMMARY_PREFIXES:
87 snprintf (name, sizeof (name),
88 "area %s summary prefix table", oa->name);
89 break;
90 case OSPF6_TABLE_TYPE_SUMMARY_ROUTERS:
91 snprintf (name, sizeof (name),
92 "area %s summary router table", oa->name);
93 break;
94 default:
95 snprintf (name, sizeof (name),
96 "area %s unknown table", oa->name);
97 break;
98 }
99 }
100 break;
101
102 case OSPF6_SCOPE_TYPE_INTERFACE:
103 {
104 struct ospf6_interface *oi = (struct ospf6_interface *) table->scope;
105 switch (table->table_type)
106 {
107 case OSPF6_TABLE_TYPE_CONNECTED_ROUTES:
108 snprintf (name, sizeof (name), "interface %s connected table",
109 oi->interface->name);
110 break;
111 default:
112 snprintf (name, sizeof (name), "interface %s unknown table",
113 oi->interface->name);
114 break;
115 }
116 }
117 break;
118
119 default:
120 {
121 switch (table->table_type)
122 {
123 case OSPF6_TABLE_TYPE_SPF_RESULTS:
124 snprintf (name, sizeof (name), "temporary spf table");
125 break;
126 default:
127 snprintf (name, sizeof (name), "temporary unknown table");
128 break;
129 }
130 }
131 break;
132 }
133 return name;
134}
135
hasso508e53e2004-05-18 18:57:06 +0000136void
137ospf6_linkstate_prefix (u_int32_t adv_router, u_int32_t id,
138 struct prefix *prefix)
paul718e3742002-12-13 20:15:29 +0000139{
hasso508e53e2004-05-18 18:57:06 +0000140 memset (prefix, 0, sizeof (struct prefix));
141 prefix->family = AF_INET6;
142 prefix->prefixlen = 64;
143 memcpy (&prefix->u.prefix6.s6_addr[0], &adv_router, 4);
144 memcpy (&prefix->u.prefix6.s6_addr[4], &id, 4);
paul718e3742002-12-13 20:15:29 +0000145}
146
hasso508e53e2004-05-18 18:57:06 +0000147void
148ospf6_linkstate_prefix2str (struct prefix *prefix, char *buf, int size)
paul718e3742002-12-13 20:15:29 +0000149{
hasso508e53e2004-05-18 18:57:06 +0000150 u_int32_t adv_router, id;
hasso4846ef62004-09-03 06:04:00 +0000151 char adv_router_str[16], id_str[16];
hasso508e53e2004-05-18 18:57:06 +0000152 memcpy (&adv_router, &prefix->u.prefix6.s6_addr[0], 4);
153 memcpy (&id, &prefix->u.prefix6.s6_addr[4], 4);
154 inet_ntop (AF_INET, &adv_router, adv_router_str, sizeof (adv_router_str));
hasso4846ef62004-09-03 06:04:00 +0000155 inet_ntop (AF_INET, &id, id_str, sizeof (id_str));
156 if (ntohl (id))
157 snprintf (buf, size, "%s Net-ID: %s", adv_router_str, id_str);
158 else
159 snprintf (buf, size, "%s", adv_router_str);
paul718e3742002-12-13 20:15:29 +0000160}
161
hasso508e53e2004-05-18 18:57:06 +0000162/* Global strings for logging */
paul0c083ee2004-10-10 12:54:58 +0000163const char *ospf6_dest_type_str[OSPF6_DEST_TYPE_MAX] =
hasso4846ef62004-09-03 06:04:00 +0000164{ "Unknown", "Router", "Network", "Discard", "Linkstate", "AddressRange", };
hasso508e53e2004-05-18 18:57:06 +0000165
paul0c083ee2004-10-10 12:54:58 +0000166const char *ospf6_dest_type_substr[OSPF6_DEST_TYPE_MAX] =
hasso4846ef62004-09-03 06:04:00 +0000167{ "?", "R", "N", "D", "L", "A", };
hasso508e53e2004-05-18 18:57:06 +0000168
paul0c083ee2004-10-10 12:54:58 +0000169const char *ospf6_path_type_str[OSPF6_PATH_TYPE_MAX] =
hasso508e53e2004-05-18 18:57:06 +0000170{ "Unknown", "Intra-Area", "Inter-Area", "External-1", "External-2", };
171
paul0c083ee2004-10-10 12:54:58 +0000172const char *ospf6_path_type_substr[OSPF6_PATH_TYPE_MAX] =
hasso4846ef62004-09-03 06:04:00 +0000173{ "??", "IA", "IE", "E1", "E2", };
hasso508e53e2004-05-18 18:57:06 +0000174
175
176struct ospf6_route *
Paul Jakma6ac29a52008-08-15 13:45:30 +0100177ospf6_route_create (void)
paul718e3742002-12-13 20:15:29 +0000178{
hasso508e53e2004-05-18 18:57:06 +0000179 struct ospf6_route *route;
180 route = XCALLOC (MTYPE_OSPF6_ROUTE, sizeof (struct ospf6_route));
181 return route;
paul718e3742002-12-13 20:15:29 +0000182}
183
hasso508e53e2004-05-18 18:57:06 +0000184void
185ospf6_route_delete (struct ospf6_route *route)
paul718e3742002-12-13 20:15:29 +0000186{
hasso508e53e2004-05-18 18:57:06 +0000187 XFREE (MTYPE_OSPF6_ROUTE, route);
paul718e3742002-12-13 20:15:29 +0000188}
189
hasso508e53e2004-05-18 18:57:06 +0000190struct ospf6_route *
191ospf6_route_copy (struct ospf6_route *route)
192{
193 struct ospf6_route *new;
194
195 new = ospf6_route_create ();
196 memcpy (new, route, sizeof (struct ospf6_route));
197 new->rnode = NULL;
198 new->prev = NULL;
199 new->next = NULL;
Paul Jakmacf1ce252006-05-15 10:46:07 +0000200 new->table = NULL;
hasso508e53e2004-05-18 18:57:06 +0000201 new->lock = 0;
202 return new;
203}
204
205void
206ospf6_route_lock (struct ospf6_route *route)
207{
208 route->lock++;
209}
210
211void
212ospf6_route_unlock (struct ospf6_route *route)
213{
214 assert (route->lock > 0);
215 route->lock--;
216 if (route->lock == 0)
Paul Jakmacf1ce252006-05-15 10:46:07 +0000217 {
218 /* Can't detach from the table until here
219 because ospf6_route_next () will use
220 the 'route->table' pointer for logging */
221 route->table = NULL;
222 ospf6_route_delete (route);
223 }
hasso508e53e2004-05-18 18:57:06 +0000224}
225
226/* Route compare function. If ra is more preferred, it returns
227 less than 0. If rb is more preferred returns greater than 0.
228 Otherwise (neither one is preferred), returns 0 */
229static int
230ospf6_route_cmp (struct ospf6_route *ra, struct ospf6_route *rb)
231{
232 assert (ospf6_route_is_same (ra, rb));
233 assert (OSPF6_PATH_TYPE_NONE < ra->path.type &&
234 ra->path.type < OSPF6_PATH_TYPE_MAX);
235 assert (OSPF6_PATH_TYPE_NONE < rb->path.type &&
236 rb->path.type < OSPF6_PATH_TYPE_MAX);
237
238 if (ra->type != rb->type)
239 return (ra->type - rb->type);
240
241 if (ra->path.area_id != rb->path.area_id)
242 return (ntohl (ra->path.area_id) - ntohl (rb->path.area_id));
243
244 if (ra->path.type != rb->path.type)
245 return (ra->path.type - rb->path.type);
246
247 if (ra->path.type == OSPF6_PATH_TYPE_EXTERNAL2)
248 {
249 if (ra->path.cost_e2 != rb->path.cost_e2)
250 return (ra->path.cost_e2 - rb->path.cost_e2);
251 }
252 else
253 {
254 if (ra->path.cost != rb->path.cost)
255 return (ra->path.cost - rb->path.cost);
256 }
257
258 return 0;
259}
260
261struct ospf6_route *
262ospf6_route_lookup (struct prefix *prefix,
paul718e3742002-12-13 20:15:29 +0000263 struct ospf6_route_table *table)
264{
265 struct route_node *node;
hasso508e53e2004-05-18 18:57:06 +0000266 struct ospf6_route *route;
paul718e3742002-12-13 20:15:29 +0000267
268 node = route_node_lookup (table->table, prefix);
hasso508e53e2004-05-18 18:57:06 +0000269 if (node == NULL)
270 return NULL;
paul718e3742002-12-13 20:15:29 +0000271
hasso508e53e2004-05-18 18:57:06 +0000272 route = (struct ospf6_route *) node->info;
273 return route;
paul718e3742002-12-13 20:15:29 +0000274}
275
hasso508e53e2004-05-18 18:57:06 +0000276struct ospf6_route *
277ospf6_route_lookup_identical (struct ospf6_route *route,
278 struct ospf6_route_table *table)
279{
280 struct ospf6_route *target;
281
282 for (target = ospf6_route_lookup (&route->prefix, table);
283 target; target = target->next)
284 {
285 if (ospf6_route_is_identical (target, route))
286 return target;
287 }
288 return NULL;
289}
290
291struct ospf6_route *
292ospf6_route_lookup_bestmatch (struct prefix *prefix,
293 struct ospf6_route_table *table)
paul718e3742002-12-13 20:15:29 +0000294{
295 struct route_node *node;
hasso508e53e2004-05-18 18:57:06 +0000296 struct ospf6_route *route;
paul718e3742002-12-13 20:15:29 +0000297
hasso508e53e2004-05-18 18:57:06 +0000298 node = route_node_match (table->table, prefix);
299 if (node == NULL)
300 return NULL;
301 route_unlock_node (node);
paul718e3742002-12-13 20:15:29 +0000302
hasso508e53e2004-05-18 18:57:06 +0000303 route = (struct ospf6_route *) node->info;
304 return route;
paul718e3742002-12-13 20:15:29 +0000305}
306
Dinesh Dutte39d0532013-08-24 07:55:36 +0000307#ifdef DEBUG
hasso508e53e2004-05-18 18:57:06 +0000308static void
Paul Jakmacf1ce252006-05-15 10:46:07 +0000309route_table_assert (struct ospf6_route_table *table)
paul718e3742002-12-13 20:15:29 +0000310{
Paul Jakmacf1ce252006-05-15 10:46:07 +0000311 struct ospf6_route *prev, *r, *next;
hassoccb59b12004-08-25 09:10:37 +0000312 char buf[64];
Paul Jakmacf1ce252006-05-15 10:46:07 +0000313 unsigned int link_error = 0, num = 0;
314
315 r = ospf6_route_head (table);
316 prev = NULL;
317 while (r)
318 {
319 if (r->prev != prev)
320 link_error++;
321
322 next = ospf6_route_next (r);
323
324 if (r->next != next)
325 link_error++;
326
327 prev = r;
328 r = next;
329 }
330
331 for (r = ospf6_route_head (table); r; r = ospf6_route_next (r))
hasso508e53e2004-05-18 18:57:06 +0000332 num++;
Paul Jakmacf1ce252006-05-15 10:46:07 +0000333
334 if (link_error == 0 && num == table->count)
hassoccb59b12004-08-25 09:10:37 +0000335 return;
336
Paul Jakmacf1ce252006-05-15 10:46:07 +0000337 zlog_err ("PANIC !!");
338 zlog_err ("Something has gone wrong with ospf6_route_table[%p]", table);
339 zlog_debug ("table count = %d, real number = %d", table->count, num);
340 zlog_debug ("DUMP START");
341 for (r = ospf6_route_head (table); r; r = ospf6_route_next (r))
hassoccb59b12004-08-25 09:10:37 +0000342 {
Paul Jakmacf1ce252006-05-15 10:46:07 +0000343 prefix2str (&r->prefix, buf, sizeof (buf));
344 zlog_info ("%p<-[%p]->%p : %s", r->prev, r, r->next, buf);
hassoccb59b12004-08-25 09:10:37 +0000345 }
hassoc6487d62004-12-24 06:00:11 +0000346 zlog_debug ("DUMP END");
hassoccb59b12004-08-25 09:10:37 +0000347
Paul Jakmacf1ce252006-05-15 10:46:07 +0000348 assert (link_error == 0 && num == table->count);
paul718e3742002-12-13 20:15:29 +0000349}
Paul Jakmacf1ce252006-05-15 10:46:07 +0000350#define ospf6_route_table_assert(t) (route_table_assert (t))
hasso508e53e2004-05-18 18:57:06 +0000351#else
Paul Jakmacf1ce252006-05-15 10:46:07 +0000352#define ospf6_route_table_assert(t) ((void) 0)
Dinesh Dutte39d0532013-08-24 07:55:36 +0000353#endif /*DEBUG*/
paul718e3742002-12-13 20:15:29 +0000354
hasso508e53e2004-05-18 18:57:06 +0000355struct ospf6_route *
356ospf6_route_add (struct ospf6_route *route,
paul718e3742002-12-13 20:15:29 +0000357 struct ospf6_route_table *table)
358{
hasso508e53e2004-05-18 18:57:06 +0000359 struct route_node *node, *nextnode, *prevnode;
360 struct ospf6_route *current = NULL;
361 struct ospf6_route *prev = NULL, *old = NULL, *next = NULL;
362 char buf[64];
363 struct timeval now;
paul718e3742002-12-13 20:15:29 +0000364
hasso508e53e2004-05-18 18:57:06 +0000365 assert (route->rnode == NULL);
366 assert (route->lock == 0);
367 assert (route->next == NULL);
368 assert (route->prev == NULL);
paul718e3742002-12-13 20:15:29 +0000369
hasso508e53e2004-05-18 18:57:06 +0000370 if (route->type == OSPF6_DEST_TYPE_LINKSTATE)
371 ospf6_linkstate_prefix2str (&route->prefix, buf, sizeof (buf));
372 else
373 prefix2str (&route->prefix, buf, sizeof (buf));
paul718e3742002-12-13 20:15:29 +0000374
Paul Jakmacf1ce252006-05-15 10:46:07 +0000375 if (IS_OSPF6_DEBUG_ROUTE (MEMORY))
376 zlog_debug ("%s %p: route add %p: %s", ospf6_route_table_name (table),
David Lampartereed3c482015-03-03 08:51:53 +0100377 (void *)table, (void *)route, buf);
Paul Jakmacf1ce252006-05-15 10:46:07 +0000378 else if (IS_OSPF6_DEBUG_ROUTE (TABLE))
379 zlog_debug ("%s: route add: %s", ospf6_route_table_name (table), buf);
paul718e3742002-12-13 20:15:29 +0000380
Takashi Sogabe86f72dc2009-06-22 13:07:02 +0900381 quagga_gettime (QUAGGA_CLK_MONOTONIC, &now);
hasso508e53e2004-05-18 18:57:06 +0000382
383 node = route_node_get (table->table, &route->prefix);
384 route->rnode = node;
385
386 /* find place to insert */
387 for (current = node->info; current; current = current->next)
paul718e3742002-12-13 20:15:29 +0000388 {
hasso508e53e2004-05-18 18:57:06 +0000389 if (! ospf6_route_is_same (current, route))
390 next = current;
391 else if (current->type != route->type)
392 prev = current;
393 else if (ospf6_route_is_same_origin (current, route))
394 old = current;
395 else if (ospf6_route_cmp (current, route) > 0)
396 next = current;
397 else
398 prev = current;
399
400 if (old || next)
401 break;
paul718e3742002-12-13 20:15:29 +0000402 }
hasso508e53e2004-05-18 18:57:06 +0000403
404 if (old)
405 {
406 /* if route does not actually change, return unchanged */
407 if (ospf6_route_is_identical (old, route))
408 {
Paul Jakmacf1ce252006-05-15 10:46:07 +0000409 if (IS_OSPF6_DEBUG_ROUTE (MEMORY))
410 zlog_debug ("%s %p: route add %p: needless update of %p",
David Lampartereed3c482015-03-03 08:51:53 +0100411 ospf6_route_table_name (table),
412 (void *)table, (void *)route, (void *)old);
Paul Jakmacf1ce252006-05-15 10:46:07 +0000413 else if (IS_OSPF6_DEBUG_ROUTE (TABLE))
414 zlog_debug ("%s: route add: needless update",
415 ospf6_route_table_name (table));
hasso508e53e2004-05-18 18:57:06 +0000416
417 ospf6_route_delete (route);
418 SET_FLAG (old->flag, OSPF6_ROUTE_ADD);
Paul Jakmacf1ce252006-05-15 10:46:07 +0000419 ospf6_route_table_assert (table);
hasso9428f2d2004-09-13 14:01:12 +0000420
hasso508e53e2004-05-18 18:57:06 +0000421 return old;
422 }
423
Paul Jakmacf1ce252006-05-15 10:46:07 +0000424 if (IS_OSPF6_DEBUG_ROUTE (MEMORY))
425 zlog_debug ("%s %p: route add %p: update of %p",
David Lampartereed3c482015-03-03 08:51:53 +0100426 ospf6_route_table_name (table),
427 (void *)table, (void *)route, (void *)old);
Paul Jakmacf1ce252006-05-15 10:46:07 +0000428 else if (IS_OSPF6_DEBUG_ROUTE (TABLE))
429 zlog_debug ("%s: route add: update",
430 ospf6_route_table_name (table));
hasso508e53e2004-05-18 18:57:06 +0000431
432 /* replace old one if exists */
433 if (node->info == old)
434 {
435 node->info = route;
436 SET_FLAG (route->flag, OSPF6_ROUTE_BEST);
437 }
438
439 if (old->prev)
440 old->prev->next = route;
441 route->prev = old->prev;
442 if (old->next)
443 old->next->prev = route;
444 route->next = old->next;
445
446 route->installed = old->installed;
447 route->changed = now;
Paul Jakmacf1ce252006-05-15 10:46:07 +0000448 assert (route->table == NULL);
449 route->table = table;
hasso508e53e2004-05-18 18:57:06 +0000450
451 ospf6_route_unlock (old); /* will be deleted later */
452 ospf6_route_lock (route);
453
454 SET_FLAG (route->flag, OSPF6_ROUTE_CHANGE);
Paul Jakmacf1ce252006-05-15 10:46:07 +0000455 ospf6_route_table_assert (table);
hasso9428f2d2004-09-13 14:01:12 +0000456
hasso508e53e2004-05-18 18:57:06 +0000457 if (table->hook_add)
458 (*table->hook_add) (route);
459
hasso508e53e2004-05-18 18:57:06 +0000460 return route;
461 }
462
463 /* insert if previous or next node found */
464 if (prev || next)
465 {
Paul Jakmacf1ce252006-05-15 10:46:07 +0000466 if (IS_OSPF6_DEBUG_ROUTE (MEMORY))
467 zlog_debug ("%s %p: route add %p: another path: prev %p, next %p",
David Lampartereed3c482015-03-03 08:51:53 +0100468 ospf6_route_table_name (table),
469 (void *)table, (void *)route, (void *)prev, (void *)next);
Paul Jakmacf1ce252006-05-15 10:46:07 +0000470 else if (IS_OSPF6_DEBUG_ROUTE (TABLE))
471 zlog_debug ("%s: route add: another path found",
472 ospf6_route_table_name (table));
hasso508e53e2004-05-18 18:57:06 +0000473
474 if (prev == NULL)
475 prev = next->prev;
476 if (next == NULL)
477 next = prev->next;
478
479 if (prev)
480 prev->next = route;
481 route->prev = prev;
482 if (next)
483 next->prev = route;
484 route->next = next;
485
486 if (node->info == next)
487 {
488 assert (next->rnode == node);
489 node->info = route;
490 UNSET_FLAG (next->flag, OSPF6_ROUTE_BEST);
491 SET_FLAG (route->flag, OSPF6_ROUTE_BEST);
Paul Jakmacf1ce252006-05-15 10:46:07 +0000492 if (IS_OSPF6_DEBUG_ROUTE (MEMORY))
493 zlog_info ("%s %p: route add %p: replacing previous best: %p",
David Lampartereed3c482015-03-03 08:51:53 +0100494 ospf6_route_table_name (table),
495 (void *)table, (void *)route, (void *)next);
hasso508e53e2004-05-18 18:57:06 +0000496 }
497
498 route->installed = now;
499 route->changed = now;
Paul Jakmacf1ce252006-05-15 10:46:07 +0000500 assert (route->table == NULL);
501 route->table = table;
hasso508e53e2004-05-18 18:57:06 +0000502
503 ospf6_route_lock (route);
504 table->count++;
Paul Jakmacf1ce252006-05-15 10:46:07 +0000505 ospf6_route_table_assert (table);
hasso508e53e2004-05-18 18:57:06 +0000506
507 SET_FLAG (route->flag, OSPF6_ROUTE_ADD);
508 if (table->hook_add)
509 (*table->hook_add) (route);
510
hasso508e53e2004-05-18 18:57:06 +0000511 return route;
512 }
513
514 /* Else, this is the brand new route regarding to the prefix */
Paul Jakmacf1ce252006-05-15 10:46:07 +0000515 if (IS_OSPF6_DEBUG_ROUTE (MEMORY))
516 zlog_debug ("%s %p: route add %p: brand new route",
David Lampartereed3c482015-03-03 08:51:53 +0100517 ospf6_route_table_name (table), (void *)table, (void *)route);
Paul Jakmacf1ce252006-05-15 10:46:07 +0000518 else if (IS_OSPF6_DEBUG_ROUTE (TABLE))
519 zlog_debug ("%s: route add: brand new route",
520 ospf6_route_table_name (table));
hasso508e53e2004-05-18 18:57:06 +0000521
522 assert (node->info == NULL);
523 node->info = route;
524 SET_FLAG (route->flag, OSPF6_ROUTE_BEST);
525 ospf6_route_lock (route);
526 route->installed = now;
527 route->changed = now;
Paul Jakmacf1ce252006-05-15 10:46:07 +0000528 assert (route->table == NULL);
529 route->table = table;
hasso508e53e2004-05-18 18:57:06 +0000530
531 /* lookup real existing next route */
532 nextnode = node;
533 route_lock_node (nextnode);
534 do {
535 nextnode = route_next (nextnode);
536 } while (nextnode && nextnode->info == NULL);
537
538 /* set next link */
539 if (nextnode == NULL)
540 route->next = NULL;
paul718e3742002-12-13 20:15:29 +0000541 else
542 {
hasso508e53e2004-05-18 18:57:06 +0000543 route_unlock_node (nextnode);
544
545 next = nextnode->info;
546 route->next = next;
547 next->prev = route;
paul718e3742002-12-13 20:15:29 +0000548 }
549
hasso508e53e2004-05-18 18:57:06 +0000550 /* lookup real existing prev route */
551 prevnode = node;
552 route_lock_node (prevnode);
553 do {
554 prevnode = route_prev (prevnode);
555 } while (prevnode && prevnode->info == NULL);
paul718e3742002-12-13 20:15:29 +0000556
hasso508e53e2004-05-18 18:57:06 +0000557 /* set prev link */
558 if (prevnode == NULL)
559 route->prev = NULL;
paul718e3742002-12-13 20:15:29 +0000560 else
561 {
hasso508e53e2004-05-18 18:57:06 +0000562 route_unlock_node (prevnode);
563
564 prev = prevnode->info;
565 while (prev->next && ospf6_route_is_same (prev, prev->next))
566 prev = prev->next;
567 route->prev = prev;
568 prev->next = route;
paul718e3742002-12-13 20:15:29 +0000569 }
570
hasso508e53e2004-05-18 18:57:06 +0000571 table->count++;
Paul Jakmacf1ce252006-05-15 10:46:07 +0000572 ospf6_route_table_assert (table);
paul718e3742002-12-13 20:15:29 +0000573
hasso508e53e2004-05-18 18:57:06 +0000574 SET_FLAG (route->flag, OSPF6_ROUTE_ADD);
575 if (table->hook_add)
576 (*table->hook_add) (route);
paul718e3742002-12-13 20:15:29 +0000577
hasso508e53e2004-05-18 18:57:06 +0000578 return route;
paul718e3742002-12-13 20:15:29 +0000579}
580
581void
hasso508e53e2004-05-18 18:57:06 +0000582ospf6_route_remove (struct ospf6_route *route,
paul718e3742002-12-13 20:15:29 +0000583 struct ospf6_route_table *table)
584{
hasso508e53e2004-05-18 18:57:06 +0000585 struct route_node *node;
586 struct ospf6_route *current;
587 char buf[64];
paul718e3742002-12-13 20:15:29 +0000588
hasso508e53e2004-05-18 18:57:06 +0000589 if (route->type == OSPF6_DEST_TYPE_LINKSTATE)
590 ospf6_linkstate_prefix2str (&route->prefix, buf, sizeof (buf));
591 else
592 prefix2str (&route->prefix, buf, sizeof (buf));
paul718e3742002-12-13 20:15:29 +0000593
Paul Jakmacf1ce252006-05-15 10:46:07 +0000594 if (IS_OSPF6_DEBUG_ROUTE (MEMORY))
595 zlog_debug ("%s %p: route remove %p: %s",
David Lampartereed3c482015-03-03 08:51:53 +0100596 ospf6_route_table_name (table),
597 (void *)table, (void *)route, buf);
Paul Jakmacf1ce252006-05-15 10:46:07 +0000598 else if (IS_OSPF6_DEBUG_ROUTE (TABLE))
599 zlog_debug ("%s: route remove: %s", ospf6_route_table_name (table), buf);
hasso508e53e2004-05-18 18:57:06 +0000600
601 node = route_node_lookup (table->table, &route->prefix);
602 assert (node);
603
604 /* find the route to remove, making sure that the route pointer
605 is from the route table. */
606 current = node->info;
607 while (current && ospf6_route_is_same (current, route))
paul718e3742002-12-13 20:15:29 +0000608 {
hasso508e53e2004-05-18 18:57:06 +0000609 if (current == route)
610 break;
611 current = current->next;
612 }
613 assert (current == route);
614
615 /* adjust doubly linked list */
616 if (route->prev)
617 route->prev->next = route->next;
618 if (route->next)
619 route->next->prev = route->prev;
620
621 if (node->info == route)
622 {
623 if (route->next && ospf6_route_is_same (route->next, route))
paul718e3742002-12-13 20:15:29 +0000624 {
hasso508e53e2004-05-18 18:57:06 +0000625 node->info = route->next;
626 SET_FLAG (route->next->flag, OSPF6_ROUTE_BEST);
paul718e3742002-12-13 20:15:29 +0000627 }
hasso508e53e2004-05-18 18:57:06 +0000628 else
629 node->info = NULL; /* should unlock route_node here ? */
paul718e3742002-12-13 20:15:29 +0000630 }
631
hasso9428f2d2004-09-13 14:01:12 +0000632 table->count--;
Paul Jakmacf1ce252006-05-15 10:46:07 +0000633 ospf6_route_table_assert (table);
hasso9428f2d2004-09-13 14:01:12 +0000634
635 SET_FLAG (route->flag, OSPF6_ROUTE_WAS_REMOVED);
636
paul718e3742002-12-13 20:15:29 +0000637 if (table->hook_remove)
hasso508e53e2004-05-18 18:57:06 +0000638 (*table->hook_remove) (route);
paul718e3742002-12-13 20:15:29 +0000639
hasso508e53e2004-05-18 18:57:06 +0000640 ospf6_route_unlock (route);
hasso508e53e2004-05-18 18:57:06 +0000641}
paul718e3742002-12-13 20:15:29 +0000642
hasso508e53e2004-05-18 18:57:06 +0000643struct ospf6_route *
644ospf6_route_head (struct ospf6_route_table *table)
645{
646 struct route_node *node;
647 struct ospf6_route *route;
paul718e3742002-12-13 20:15:29 +0000648
hasso508e53e2004-05-18 18:57:06 +0000649 node = route_top (table->table);
650 if (node == NULL)
651 return NULL;
652
653 /* skip to the real existing entry */
654 while (node && node->info == NULL)
655 node = route_next (node);
656 if (node == NULL)
657 return NULL;
658
659 route_unlock_node (node);
660 assert (node->info);
661
662 route = (struct ospf6_route *) node->info;
663 assert (route->prev == NULL);
Paul Jakmacf1ce252006-05-15 10:46:07 +0000664 assert (route->table == table);
hasso508e53e2004-05-18 18:57:06 +0000665 ospf6_route_lock (route);
Paul Jakmacf1ce252006-05-15 10:46:07 +0000666
667 if (IS_OSPF6_DEBUG_ROUTE (MEMORY))
668 zlog_info ("%s %p: route head: %p<-[%p]->%p",
David Lampartereed3c482015-03-03 08:51:53 +0100669 ospf6_route_table_name (table), (void *)table,
670 (void *)route->prev, (void *)route, (void *)route->next);
Paul Jakmacf1ce252006-05-15 10:46:07 +0000671
hasso508e53e2004-05-18 18:57:06 +0000672 return route;
673}
674
675struct ospf6_route *
676ospf6_route_next (struct ospf6_route *route)
677{
678 struct ospf6_route *next = route->next;
679
Paul Jakmacf1ce252006-05-15 10:46:07 +0000680 if (IS_OSPF6_DEBUG_ROUTE (MEMORY))
681 zlog_info ("%s %p: route next: %p<-[%p]->%p",
David Lampartereed3c482015-03-03 08:51:53 +0100682 ospf6_route_table_name (route->table), (void *)route->table,
683 (void *)route->prev, (void *)route, (void *)route->next);
Paul Jakmacf1ce252006-05-15 10:46:07 +0000684
hasso508e53e2004-05-18 18:57:06 +0000685 ospf6_route_unlock (route);
686 if (next)
687 ospf6_route_lock (next);
688
689 return next;
690}
691
692struct ospf6_route *
693ospf6_route_best_next (struct ospf6_route *route)
694{
695 struct route_node *rnode;
696 struct ospf6_route *next;
697
Tom Goffe7a6d802010-11-10 13:03:02 -0800698 ospf6_route_unlock (route);
699
hasso508e53e2004-05-18 18:57:06 +0000700 rnode = route->rnode;
701 route_lock_node (rnode);
702 rnode = route_next (rnode);
703 while (rnode && rnode->info == NULL)
704 rnode = route_next (rnode);
705 if (rnode == NULL)
706 return NULL;
707 route_unlock_node (rnode);
708
709 assert (rnode->info);
710 next = (struct ospf6_route *) rnode->info;
hasso508e53e2004-05-18 18:57:06 +0000711 ospf6_route_lock (next);
712 return next;
713}
714
hasso508e53e2004-05-18 18:57:06 +0000715struct ospf6_route *
716ospf6_route_match_head (struct prefix *prefix,
717 struct ospf6_route_table *table)
718{
719 struct route_node *node;
720 struct ospf6_route *route;
721
722 /* Walk down tree. */
723 node = table->table->top;
724 while (node && node->p.prefixlen < prefix->prefixlen &&
725 prefix_match (&node->p, prefix))
Stephen Hemminger1352ef32009-12-09 14:43:17 +0300726 node = node->link[prefix_bit(&prefix->u.prefix, node->p.prefixlen)];
hasso508e53e2004-05-18 18:57:06 +0000727
728 if (node)
729 route_lock_node (node);
730 while (node && node->info == NULL)
731 node = route_next (node);
732 if (node == NULL)
733 return NULL;
734 route_unlock_node (node);
735
736 if (! prefix_match (prefix, &node->p))
737 return NULL;
738
739 route = node->info;
740 ospf6_route_lock (route);
741 return route;
742}
743
744struct ospf6_route *
745ospf6_route_match_next (struct prefix *prefix,
746 struct ospf6_route *route)
747{
748 struct ospf6_route *next;
749
750 next = ospf6_route_next (route);
751 if (next && ! prefix_match (prefix, &next->prefix))
752 {
753 ospf6_route_unlock (next);
754 next = NULL;
755 }
756
757 return next;
paul718e3742002-12-13 20:15:29 +0000758}
759
760void
761ospf6_route_remove_all (struct ospf6_route_table *table)
762{
hasso508e53e2004-05-18 18:57:06 +0000763 struct ospf6_route *route;
764 for (route = ospf6_route_head (table); route;
765 route = ospf6_route_next (route))
766 ospf6_route_remove (route, table);
paul718e3742002-12-13 20:15:29 +0000767}
768
paul718e3742002-12-13 20:15:29 +0000769struct ospf6_route_table *
Paul Jakmacf1ce252006-05-15 10:46:07 +0000770ospf6_route_table_create (int s, int t)
paul718e3742002-12-13 20:15:29 +0000771{
paul718e3742002-12-13 20:15:29 +0000772 struct ospf6_route_table *new;
paul718e3742002-12-13 20:15:29 +0000773 new = XCALLOC (MTYPE_OSPF6_ROUTE, sizeof (struct ospf6_route_table));
paul718e3742002-12-13 20:15:29 +0000774 new->table = route_table_init ();
Paul Jakmacf1ce252006-05-15 10:46:07 +0000775 new->scope_type = s;
776 new->table_type = t;
paul718e3742002-12-13 20:15:29 +0000777 return new;
778}
779
780void
781ospf6_route_table_delete (struct ospf6_route_table *table)
782{
paul718e3742002-12-13 20:15:29 +0000783 ospf6_route_remove_all (table);
784 route_table_finish (table->table);
paul718e3742002-12-13 20:15:29 +0000785 XFREE (MTYPE_OSPF6_ROUTE, table);
786}
787
David Lamparter6b0655a2014-06-04 06:53:35 +0200788
paul718e3742002-12-13 20:15:29 +0000789/* VTY commands */
hasso508e53e2004-05-18 18:57:06 +0000790void
791ospf6_route_show (struct vty *vty, struct ospf6_route *route)
792{
793 int i;
794 char destination[64], nexthop[64];
795 char duration[16], ifname[IFNAMSIZ];
796 struct timeval now, res;
797
Takashi Sogabe86f72dc2009-06-22 13:07:02 +0900798 quagga_gettime (QUAGGA_CLK_MONOTONIC, &now);
hasso508e53e2004-05-18 18:57:06 +0000799 timersub (&now, &route->changed, &res);
800 timerstring (&res, duration, sizeof (duration));
801
802 /* destination */
803 if (route->type == OSPF6_DEST_TYPE_LINKSTATE)
804 ospf6_linkstate_prefix2str (&route->prefix, destination,
805 sizeof (destination));
806 else if (route->type == OSPF6_DEST_TYPE_ROUTER)
807 inet_ntop (route->prefix.family, &route->prefix.u.prefix,
808 destination, sizeof (destination));
809 else
810 prefix2str (&route->prefix, destination, sizeof (destination));
811
812 /* nexthop */
813 inet_ntop (AF_INET6, &route->nexthop[0].address, nexthop,
814 sizeof (nexthop));
815 if (! if_indextoname (route->nexthop[0].ifindex, ifname))
816 snprintf (ifname, sizeof (ifname), "%d", route->nexthop[0].ifindex);
817
ajs3b7b8142005-04-02 16:37:07 +0000818 vty_out (vty, "%c%1s %2s %-30s %-25s %6.*s %s%s",
hasso508e53e2004-05-18 18:57:06 +0000819 (ospf6_route_is_best (route) ? '*' : ' '),
820 OSPF6_DEST_TYPE_SUBSTR (route->type),
821 OSPF6_PATH_TYPE_SUBSTR (route->path.type),
ajs3b7b8142005-04-02 16:37:07 +0000822 destination, nexthop, IFNAMSIZ, ifname, duration, VNL);
hasso508e53e2004-05-18 18:57:06 +0000823
824 for (i = 1; ospf6_nexthop_is_set (&route->nexthop[i]) &&
825 i < OSPF6_MULTI_PATH_LIMIT; i++)
826 {
827 /* nexthop */
828 inet_ntop (AF_INET6, &route->nexthop[i].address, nexthop,
829 sizeof (nexthop));
830 if (! if_indextoname (route->nexthop[i].ifindex, ifname))
831 snprintf (ifname, sizeof (ifname), "%d", route->nexthop[i].ifindex);
832
ajs3b7b8142005-04-02 16:37:07 +0000833 vty_out (vty, "%c%1s %2s %-30s %-25s %6.*s %s%s",
834 ' ', "", "", "", nexthop, IFNAMSIZ, ifname, "", VNL);
hasso508e53e2004-05-18 18:57:06 +0000835 }
836}
paul718e3742002-12-13 20:15:29 +0000837
838void
hasso508e53e2004-05-18 18:57:06 +0000839ospf6_route_show_detail (struct vty *vty, struct ospf6_route *route)
paul718e3742002-12-13 20:15:29 +0000840{
hasso508e53e2004-05-18 18:57:06 +0000841 char destination[64], nexthop[64], ifname[IFNAMSIZ];
842 char area_id[16], id[16], adv_router[16], capa[16], options[16];
paul718e3742002-12-13 20:15:29 +0000843 struct timeval now, res;
844 char duration[16];
hasso508e53e2004-05-18 18:57:06 +0000845 int i;
paul718e3742002-12-13 20:15:29 +0000846
Takashi Sogabe86f72dc2009-06-22 13:07:02 +0900847 quagga_gettime (QUAGGA_CLK_MONOTONIC, &now);
paul718e3742002-12-13 20:15:29 +0000848
849 /* destination */
hasso508e53e2004-05-18 18:57:06 +0000850 if (route->type == OSPF6_DEST_TYPE_LINKSTATE)
851 ospf6_linkstate_prefix2str (&route->prefix, destination,
852 sizeof (destination));
853 else if (route->type == OSPF6_DEST_TYPE_ROUTER)
854 inet_ntop (route->prefix.family, &route->prefix.u.prefix,
855 destination, sizeof (destination));
paul718e3742002-12-13 20:15:29 +0000856 else
hasso508e53e2004-05-18 18:57:06 +0000857 prefix2str (&route->prefix, destination, sizeof (destination));
hasso049207c2004-08-04 20:02:13 +0000858 vty_out (vty, "Destination: %s%s", destination, VNL);
paul718e3742002-12-13 20:15:29 +0000859
hasso508e53e2004-05-18 18:57:06 +0000860 /* destination type */
861 vty_out (vty, "Destination type: %s%s",
862 OSPF6_DEST_TYPE_NAME (route->type),
hasso049207c2004-08-04 20:02:13 +0000863 VNL);
hasso508e53e2004-05-18 18:57:06 +0000864
865 /* Time */
866 timersub (&now, &route->installed, &res);
867 timerstring (&res, duration, sizeof (duration));
hasso049207c2004-08-04 20:02:13 +0000868 vty_out (vty, "Installed Time: %s ago%s", duration, VNL);
hasso508e53e2004-05-18 18:57:06 +0000869
870 timersub (&now, &route->changed, &res);
871 timerstring (&res, duration, sizeof (duration));
hasso049207c2004-08-04 20:02:13 +0000872 vty_out (vty, " Changed Time: %s ago%s", duration, VNL);
hasso508e53e2004-05-18 18:57:06 +0000873
874 /* Debugging info */
875 vty_out (vty, "Lock: %d Flags: %s%s%s%s%s", route->lock,
876 (CHECK_FLAG (route->flag, OSPF6_ROUTE_BEST) ? "B" : "-"),
877 (CHECK_FLAG (route->flag, OSPF6_ROUTE_ADD) ? "A" : "-"),
878 (CHECK_FLAG (route->flag, OSPF6_ROUTE_REMOVE) ? "R" : "-"),
879 (CHECK_FLAG (route->flag, OSPF6_ROUTE_CHANGE) ? "C" : "-"),
hasso049207c2004-08-04 20:02:13 +0000880 VNL);
hasso508e53e2004-05-18 18:57:06 +0000881 vty_out (vty, "Memory: prev: %p this: %p next: %p%s",
David Lampartereed3c482015-03-03 08:51:53 +0100882 (void *)route->prev, (void *)route, (void *)route->next, VNL);
hasso508e53e2004-05-18 18:57:06 +0000883
884 /* Path section */
885
886 /* Area-ID */
887 inet_ntop (AF_INET, &route->path.area_id, area_id, sizeof (area_id));
hasso049207c2004-08-04 20:02:13 +0000888 vty_out (vty, "Associated Area: %s%s", area_id, VNL);
hasso508e53e2004-05-18 18:57:06 +0000889
890 /* Path type */
891 vty_out (vty, "Path Type: %s%s",
hasso049207c2004-08-04 20:02:13 +0000892 OSPF6_PATH_TYPE_NAME (route->path.type), VNL);
hasso508e53e2004-05-18 18:57:06 +0000893
894 /* LS Origin */
895 inet_ntop (AF_INET, &route->path.origin.id, id, sizeof (id));
896 inet_ntop (AF_INET, &route->path.origin.adv_router, adv_router,
897 sizeof (adv_router));
898 vty_out (vty, "LS Origin: %s Id: %s Adv: %s%s",
hasso1e058382004-09-01 21:36:14 +0000899 ospf6_lstype_name (route->path.origin.type),
hasso049207c2004-08-04 20:02:13 +0000900 id, adv_router, VNL);
hasso508e53e2004-05-18 18:57:06 +0000901
902 /* Options */
903 ospf6_options_printbuf (route->path.options, options, sizeof (options));
hasso049207c2004-08-04 20:02:13 +0000904 vty_out (vty, "Options: %s%s", options, VNL);
hasso508e53e2004-05-18 18:57:06 +0000905
906 /* Router Bits */
907 ospf6_capability_printbuf (route->path.router_bits, capa, sizeof (capa));
hasso049207c2004-08-04 20:02:13 +0000908 vty_out (vty, "Router Bits: %s%s", capa, VNL);
hasso508e53e2004-05-18 18:57:06 +0000909
910 /* Prefix Options */
hasso049207c2004-08-04 20:02:13 +0000911 vty_out (vty, "Prefix Options: xxx%s", VNL);
hasso508e53e2004-05-18 18:57:06 +0000912
913 /* Metrics */
914 vty_out (vty, "Metric Type: %d%s", route->path.metric_type,
hasso049207c2004-08-04 20:02:13 +0000915 VNL);
hasso508e53e2004-05-18 18:57:06 +0000916 vty_out (vty, "Metric: %d (%d)%s",
hasso049207c2004-08-04 20:02:13 +0000917 route->path.cost, route->path.cost_e2, VNL);
hasso508e53e2004-05-18 18:57:06 +0000918
919 /* Nexthops */
hasso049207c2004-08-04 20:02:13 +0000920 vty_out (vty, "Nexthop:%s", VNL);
hasso508e53e2004-05-18 18:57:06 +0000921 for (i = 0; ospf6_nexthop_is_set (&route->nexthop[i]) &&
922 i < OSPF6_MULTI_PATH_LIMIT; i++)
paul718e3742002-12-13 20:15:29 +0000923 {
hasso508e53e2004-05-18 18:57:06 +0000924 /* nexthop */
925 inet_ntop (AF_INET6, &route->nexthop[i].address, nexthop,
926 sizeof (nexthop));
927 if (! if_indextoname (route->nexthop[i].ifindex, ifname))
928 snprintf (ifname, sizeof (ifname), "%d", route->nexthop[i].ifindex);
ajs3b7b8142005-04-02 16:37:07 +0000929 vty_out (vty, " %s %.*s%s", nexthop, IFNAMSIZ, ifname, VNL);
paul718e3742002-12-13 20:15:29 +0000930 }
hasso049207c2004-08-04 20:02:13 +0000931 vty_out (vty, "%s", VNL);
paul718e3742002-12-13 20:15:29 +0000932}
933
Paul Jakma6ac29a52008-08-15 13:45:30 +0100934static void
hasso508e53e2004-05-18 18:57:06 +0000935ospf6_route_show_table_summary (struct vty *vty,
936 struct ospf6_route_table *table)
paul718e3742002-12-13 20:15:29 +0000937{
hasso508e53e2004-05-18 18:57:06 +0000938 struct ospf6_route *route, *prev = NULL;
939 int i, pathtype[OSPF6_PATH_TYPE_MAX];
paul0c083ee2004-10-10 12:54:58 +0000940 unsigned int number = 0;
hasso508e53e2004-05-18 18:57:06 +0000941 int nhinval = 0, ecmp = 0;
hasso4846ef62004-09-03 06:04:00 +0000942 int alternative = 0, destination = 0;
paul718e3742002-12-13 20:15:29 +0000943
hasso508e53e2004-05-18 18:57:06 +0000944 for (i = 0; i < OSPF6_PATH_TYPE_MAX; i++)
945 pathtype[i] = 0;
paul718e3742002-12-13 20:15:29 +0000946
hasso508e53e2004-05-18 18:57:06 +0000947 for (route = ospf6_route_head (table); route;
948 route = ospf6_route_next (route))
paul718e3742002-12-13 20:15:29 +0000949 {
hasso508e53e2004-05-18 18:57:06 +0000950 if (prev == NULL || ! ospf6_route_is_same (prev, route))
951 destination++;
952 else
hasso4846ef62004-09-03 06:04:00 +0000953 alternative++;
hasso508e53e2004-05-18 18:57:06 +0000954 if (! ospf6_nexthop_is_set (&route->nexthop[0]))
955 nhinval++;
956 else if (ospf6_nexthop_is_set (&route->nexthop[1]))
957 ecmp++;
hasso4846ef62004-09-03 06:04:00 +0000958 pathtype[route->path.type]++;
hasso508e53e2004-05-18 18:57:06 +0000959 number++;
hasso4846ef62004-09-03 06:04:00 +0000960
hasso508e53e2004-05-18 18:57:06 +0000961 prev = route;
paul718e3742002-12-13 20:15:29 +0000962 }
hasso508e53e2004-05-18 18:57:06 +0000963
964 assert (number == table->count);
hasso508e53e2004-05-18 18:57:06 +0000965
hasso4846ef62004-09-03 06:04:00 +0000966 vty_out (vty, "Number of OSPFv3 routes: %d%s", number, VNL);
967 vty_out (vty, "Number of Destination: %d%s", destination, VNL);
968 vty_out (vty, "Number of Alternative routes: %d%s", alternative, VNL);
969 vty_out (vty, "Number of Equal Cost Multi Path: %d%s", ecmp, VNL);
970 for (i = OSPF6_PATH_TYPE_INTRA; i <= OSPF6_PATH_TYPE_EXTERNAL2; i++)
hasso508e53e2004-05-18 18:57:06 +0000971 {
hasso4846ef62004-09-03 06:04:00 +0000972 vty_out (vty, "Number of %s routes: %d%s",
973 OSPF6_PATH_TYPE_NAME (i), pathtype[i], VNL);
974 }
975}
976
Paul Jakma6ac29a52008-08-15 13:45:30 +0100977static void
hasso4846ef62004-09-03 06:04:00 +0000978ospf6_route_show_table_prefix (struct vty *vty,
979 struct prefix *prefix,
980 struct ospf6_route_table *table)
981{
982 struct ospf6_route *route;
983
984 route = ospf6_route_lookup (prefix, table);
985 if (route == NULL)
986 return;
987
988 ospf6_route_lock (route);
989 while (route && ospf6_route_is_prefix (prefix, route))
990 {
991 /* Specifying a prefix will always display details */
992 ospf6_route_show_detail (vty, route);
993 route = ospf6_route_next (route);
994 }
995 if (route)
996 ospf6_route_unlock (route);
997}
998
Paul Jakma6ac29a52008-08-15 13:45:30 +0100999static void
hasso4846ef62004-09-03 06:04:00 +00001000ospf6_route_show_table_address (struct vty *vty,
1001 struct prefix *prefix,
1002 struct ospf6_route_table *table)
1003{
1004 struct ospf6_route *route;
1005
1006 route = ospf6_route_lookup_bestmatch (prefix, table);
1007 if (route == NULL)
1008 return;
1009
1010 prefix = &route->prefix;
1011 ospf6_route_lock (route);
1012 while (route && ospf6_route_is_prefix (prefix, route))
1013 {
1014 /* Specifying a prefix will always display details */
1015 ospf6_route_show_detail (vty, route);
1016 route = ospf6_route_next (route);
1017 }
1018 if (route)
1019 ospf6_route_unlock (route);
1020}
1021
Paul Jakma6ac29a52008-08-15 13:45:30 +01001022static void
hasso4846ef62004-09-03 06:04:00 +00001023ospf6_route_show_table_match (struct vty *vty, int detail,
1024 struct prefix *prefix,
1025 struct ospf6_route_table *table)
1026{
1027 struct ospf6_route *route;
1028 assert (prefix->family);
1029
1030 route = ospf6_route_match_head (prefix, table);
1031 while (route)
1032 {
1033 if (detail)
1034 ospf6_route_show_detail (vty, route);
1035 else
1036 ospf6_route_show (vty, route);
1037 route = ospf6_route_match_next (prefix, route);
1038 }
1039}
1040
Paul Jakma6ac29a52008-08-15 13:45:30 +01001041static void
hasso4846ef62004-09-03 06:04:00 +00001042ospf6_route_show_table_type (struct vty *vty, int detail, u_char type,
1043 struct ospf6_route_table *table)
1044{
1045 struct ospf6_route *route;
1046
1047 route = ospf6_route_head (table);
1048 while (route)
1049 {
1050 if (route->path.type == type)
1051 {
1052 if (detail)
1053 ospf6_route_show_detail (vty, route);
1054 else
1055 ospf6_route_show (vty, route);
1056 }
1057 route = ospf6_route_next (route);
1058 }
1059}
1060
Paul Jakma6ac29a52008-08-15 13:45:30 +01001061static void
hasso4846ef62004-09-03 06:04:00 +00001062ospf6_route_show_table (struct vty *vty, int detail,
1063 struct ospf6_route_table *table)
1064{
1065 struct ospf6_route *route;
1066
1067 route = ospf6_route_head (table);
1068 while (route)
1069 {
1070 if (detail)
1071 ospf6_route_show_detail (vty, route);
1072 else
1073 ospf6_route_show (vty, route);
1074 route = ospf6_route_next (route);
hasso508e53e2004-05-18 18:57:06 +00001075 }
paul718e3742002-12-13 20:15:29 +00001076}
1077
1078int
paul0c083ee2004-10-10 12:54:58 +00001079ospf6_route_table_show (struct vty *vty, int argc, const char *argv[],
paul718e3742002-12-13 20:15:29 +00001080 struct ospf6_route_table *table)
1081{
hasso4846ef62004-09-03 06:04:00 +00001082 int summary = 0;
1083 int match = 0;
1084 int detail = 0;
1085 int slash = 0;
1086 int isprefix = 0;
paul718e3742002-12-13 20:15:29 +00001087 int i, ret;
hasso4846ef62004-09-03 06:04:00 +00001088 struct prefix prefix;
1089 u_char type = 0;
paul718e3742002-12-13 20:15:29 +00001090
1091 memset (&prefix, 0, sizeof (struct prefix));
1092
1093 for (i = 0; i < argc; i++)
1094 {
hasso508e53e2004-05-18 18:57:06 +00001095 if (! strcmp (argv[i], "summary"))
1096 {
hasso4846ef62004-09-03 06:04:00 +00001097 summary++;
hasso508e53e2004-05-18 18:57:06 +00001098 continue;
1099 }
1100
hasso4846ef62004-09-03 06:04:00 +00001101 if (! strcmp (argv[i], "intra-area"))
1102 {
1103 type = OSPF6_PATH_TYPE_INTRA;
1104 continue;
1105 }
1106
1107 if (! strcmp (argv[i], "inter-area"))
1108 {
1109 type = OSPF6_PATH_TYPE_INTER;
1110 continue;
1111 }
1112
1113 if (! strcmp (argv[i], "external-1"))
1114 {
1115 type = OSPF6_PATH_TYPE_EXTERNAL1;
1116 continue;
1117 }
1118
1119 if (! strcmp (argv[i], "external-2"))
1120 {
1121 type = OSPF6_PATH_TYPE_EXTERNAL2;
1122 continue;
1123 }
1124
paul718e3742002-12-13 20:15:29 +00001125 if (! strcmp (argv[i], "detail"))
1126 {
hasso4846ef62004-09-03 06:04:00 +00001127 detail++;
hasso508e53e2004-05-18 18:57:06 +00001128 continue;
paul718e3742002-12-13 20:15:29 +00001129 }
1130
hasso508e53e2004-05-18 18:57:06 +00001131 if (! strcmp (argv[i], "match"))
paul718e3742002-12-13 20:15:29 +00001132 {
hasso4846ef62004-09-03 06:04:00 +00001133 match++;
hasso508e53e2004-05-18 18:57:06 +00001134 continue;
paul718e3742002-12-13 20:15:29 +00001135 }
1136
hasso508e53e2004-05-18 18:57:06 +00001137 ret = str2prefix (argv[i], &prefix);
hasso4846ef62004-09-03 06:04:00 +00001138 if (ret == 1 && prefix.family == AF_INET6)
hasso508e53e2004-05-18 18:57:06 +00001139 {
hasso4846ef62004-09-03 06:04:00 +00001140 isprefix++;
1141 if (strchr (argv[i], '/'))
1142 slash++;
1143 continue;
hasso508e53e2004-05-18 18:57:06 +00001144 }
1145
hasso4846ef62004-09-03 06:04:00 +00001146 vty_out (vty, "Malformed argument: %s%s", argv[i], VNL);
1147 return CMD_SUCCESS;
paul718e3742002-12-13 20:15:29 +00001148 }
1149
hasso508e53e2004-05-18 18:57:06 +00001150 /* Give summary of this route table */
hasso4846ef62004-09-03 06:04:00 +00001151 if (summary)
paul718e3742002-12-13 20:15:29 +00001152 {
hasso508e53e2004-05-18 18:57:06 +00001153 ospf6_route_show_table_summary (vty, table);
paul718e3742002-12-13 20:15:29 +00001154 return CMD_SUCCESS;
1155 }
1156
hasso508e53e2004-05-18 18:57:06 +00001157 /* Give exact prefix-match route */
hasso4846ef62004-09-03 06:04:00 +00001158 if (isprefix && ! match)
paul718e3742002-12-13 20:15:29 +00001159 {
hasso508e53e2004-05-18 18:57:06 +00001160 /* If exact address, give best matching route */
hasso4846ef62004-09-03 06:04:00 +00001161 if (! slash)
1162 ospf6_route_show_table_address (vty, &prefix, table);
hasso508e53e2004-05-18 18:57:06 +00001163 else
hasso4846ef62004-09-03 06:04:00 +00001164 ospf6_route_show_table_prefix (vty, &prefix, table);
hasso508e53e2004-05-18 18:57:06 +00001165
1166 return CMD_SUCCESS;
paul718e3742002-12-13 20:15:29 +00001167 }
1168
hasso4846ef62004-09-03 06:04:00 +00001169 if (match)
1170 ospf6_route_show_table_match (vty, detail, &prefix, table);
1171 else if (type)
1172 ospf6_route_show_table_type (vty, detail, type, table);
hasso508e53e2004-05-18 18:57:06 +00001173 else
hasso4846ef62004-09-03 06:04:00 +00001174 ospf6_route_show_table (vty, detail, table);
paul718e3742002-12-13 20:15:29 +00001175
paul718e3742002-12-13 20:15:29 +00001176 return CMD_SUCCESS;
1177}
1178
Paul Jakma6ac29a52008-08-15 13:45:30 +01001179static void
hasso4846ef62004-09-03 06:04:00 +00001180ospf6_linkstate_show_header (struct vty *vty)
hasso508e53e2004-05-18 18:57:06 +00001181{
hasso4846ef62004-09-03 06:04:00 +00001182 vty_out (vty, "%-7s %-15s %-15s %-8s %-14s %s%s",
1183 "Type", "Router-ID", "Net-ID", "Rtr-Bits", "Options", "Cost", VNL);
1184}
1185
Paul Jakma6ac29a52008-08-15 13:45:30 +01001186static void
hasso4846ef62004-09-03 06:04:00 +00001187ospf6_linkstate_show (struct vty *vty, struct ospf6_route *route)
1188{
1189 u_int32_t router, id;
1190 char routername[16], idname[16], rbits[16], options[16];
1191
1192 router = ospf6_linkstate_prefix_adv_router (&route->prefix);
1193 inet_ntop (AF_INET, &router, routername, sizeof (routername));
1194 id = ospf6_linkstate_prefix_id (&route->prefix);
1195 inet_ntop (AF_INET, &id, idname, sizeof (idname));
1196
1197 ospf6_capability_printbuf (route->path.router_bits, rbits, sizeof (rbits));
1198 ospf6_options_printbuf (route->path.options, options, sizeof (options));
1199
1200 if (ntohl (id))
1201 vty_out (vty, "%-7s %-15s %-15s %-8s %-14s %lu%s",
1202 "Network", routername, idname, rbits, options,
1203 (unsigned long) route->path.cost, VNL);
1204 else
1205 vty_out (vty, "%-7s %-15s %-15s %-8s %-14s %lu%s",
1206 "Router", routername, idname, rbits, options,
1207 (unsigned long) route->path.cost, VNL);
1208}
1209
1210
Paul Jakma6ac29a52008-08-15 13:45:30 +01001211static void
hasso4846ef62004-09-03 06:04:00 +00001212ospf6_linkstate_show_table_exact (struct vty *vty,
1213 struct prefix *prefix,
1214 struct ospf6_route_table *table)
1215{
hasso508e53e2004-05-18 18:57:06 +00001216 struct ospf6_route *route;
1217
hasso4846ef62004-09-03 06:04:00 +00001218 route = ospf6_route_lookup (prefix, table);
1219 if (route == NULL)
1220 return;
1221
1222 ospf6_route_lock (route);
1223 while (route && ospf6_route_is_prefix (prefix, route))
1224 {
1225 /* Specifying a prefix will always display details */
1226 ospf6_route_show_detail (vty, route);
1227 route = ospf6_route_next (route);
1228 }
1229 if (route)
1230 ospf6_route_unlock (route);
1231}
1232
Paul Jakma6ac29a52008-08-15 13:45:30 +01001233static void
hasso4846ef62004-09-03 06:04:00 +00001234ospf6_linkstate_show_table (struct vty *vty, int detail,
1235 struct ospf6_route_table *table)
1236{
1237 struct ospf6_route *route;
1238
1239 if (! detail)
1240 ospf6_linkstate_show_header (vty);
1241
1242 route = ospf6_route_head (table);
1243 while (route)
1244 {
1245 if (detail)
1246 ospf6_route_show_detail (vty, route);
1247 else
1248 ospf6_linkstate_show (vty, route);
1249 route = ospf6_route_next (route);
1250 }
1251}
1252
1253int
paul0c083ee2004-10-10 12:54:58 +00001254ospf6_linkstate_table_show (struct vty *vty, int argc, const char *argv[],
hasso4846ef62004-09-03 06:04:00 +00001255 struct ospf6_route_table *table)
1256{
1257 int detail = 0;
1258 int is_id = 0;
1259 int is_router = 0;
1260 int i, ret;
1261 struct prefix router, id, prefix;
1262
1263 memset (&router, 0, sizeof (struct prefix));
hasso508e53e2004-05-18 18:57:06 +00001264 memset (&id, 0, sizeof (struct prefix));
hasso4846ef62004-09-03 06:04:00 +00001265 memset (&prefix, 0, sizeof (struct prefix));
hasso508e53e2004-05-18 18:57:06 +00001266
1267 for (i = 0; i < argc; i++)
1268 {
hasso508e53e2004-05-18 18:57:06 +00001269 if (! strcmp (argv[i], "detail"))
1270 {
hasso4846ef62004-09-03 06:04:00 +00001271 detail++;
hasso508e53e2004-05-18 18:57:06 +00001272 continue;
1273 }
1274
hasso4846ef62004-09-03 06:04:00 +00001275 if (! is_router)
hasso508e53e2004-05-18 18:57:06 +00001276 {
hasso4846ef62004-09-03 06:04:00 +00001277 ret = str2prefix (argv[i], &router);
1278 if (ret == 1 && router.family == AF_INET)
1279 {
1280 is_router++;
1281 continue;
1282 }
1283 vty_out (vty, "Malformed argument: %s%s", argv[i], VNL);
hasso508e53e2004-05-18 18:57:06 +00001284 return CMD_SUCCESS;
1285 }
1286
hasso4846ef62004-09-03 06:04:00 +00001287 if (! is_id)
hasso508e53e2004-05-18 18:57:06 +00001288 {
hasso508e53e2004-05-18 18:57:06 +00001289 ret = str2prefix (argv[i], &id);
hasso4846ef62004-09-03 06:04:00 +00001290 if (ret == 1 && id.family == AF_INET)
hasso508e53e2004-05-18 18:57:06 +00001291 {
hasso4846ef62004-09-03 06:04:00 +00001292 is_id++;
1293 continue;
hasso508e53e2004-05-18 18:57:06 +00001294 }
hasso4846ef62004-09-03 06:04:00 +00001295 vty_out (vty, "Malformed argument: %s%s", argv[i], VNL);
hasso508e53e2004-05-18 18:57:06 +00001296 return CMD_SUCCESS;
1297 }
1298
hasso4846ef62004-09-03 06:04:00 +00001299 vty_out (vty, "Malformed argument: %s%s", argv[i], VNL);
hasso508e53e2004-05-18 18:57:06 +00001300 return CMD_SUCCESS;
1301 }
1302
hasso4846ef62004-09-03 06:04:00 +00001303 if (is_router)
1304 ospf6_linkstate_prefix (router.u.prefix4.s_addr,
1305 id.u.prefix4.s_addr, &prefix);
1306
1307 if (prefix.family)
1308 ospf6_linkstate_show_table_exact (vty, &prefix, table);
hasso508e53e2004-05-18 18:57:06 +00001309 else
hasso4846ef62004-09-03 06:04:00 +00001310 ospf6_linkstate_show_table (vty, detail, table);
hasso508e53e2004-05-18 18:57:06 +00001311
1312 return CMD_SUCCESS;
1313}
1314
hasso4846ef62004-09-03 06:04:00 +00001315
hasso6452df02004-08-15 05:52:07 +00001316void
1317ospf6_brouter_show_header (struct vty *vty)
1318{
1319 vty_out (vty, "%-15s %-8s %-14s %-10s %-15s%s",
1320 "Router-ID", "Rtr-Bits", "Options", "Path-Type", "Area", VNL);
1321}
1322
1323void
1324ospf6_brouter_show (struct vty *vty, struct ospf6_route *route)
1325{
1326 u_int32_t adv_router;
1327 char adv[16], rbits[16], options[16], area[16];
1328
1329 adv_router = ospf6_linkstate_prefix_adv_router (&route->prefix);
1330 inet_ntop (AF_INET, &adv_router, adv, sizeof (adv));
1331 ospf6_capability_printbuf (route->path.router_bits, rbits, sizeof (rbits));
1332 ospf6_options_printbuf (route->path.options, options, sizeof (options));
1333 inet_ntop (AF_INET, &route->path.area_id, area, sizeof (area));
1334
1335 /* vty_out (vty, "%-15s %-8s %-14s %-10s %-15s%s",
1336 "Router-ID", "Rtr-Bits", "Options", "Path-Type", "Area", VNL); */
1337 vty_out (vty, "%-15s %-8s %-14s %-10s %-15s%s",
1338 adv, rbits, options, OSPF6_PATH_TYPE_NAME (route->path.type),
1339 area, VNL);
1340}
1341
hasso508e53e2004-05-18 18:57:06 +00001342DEFUN (debug_ospf6_route,
1343 debug_ospf6_route_cmd,
Tom Goff8f228de2010-11-10 13:02:11 -08001344 "debug ospf6 route (table|intra-area|inter-area|memory)",
hasso508e53e2004-05-18 18:57:06 +00001345 DEBUG_STR
1346 OSPF6_STR
1347 "Debug route table calculation\n"
1348 "Debug detail\n"
1349 "Debug intra-area route calculation\n"
1350 "Debug inter-area route calculation\n"
Tom Goff8f228de2010-11-10 13:02:11 -08001351 "Debug route memory use\n"
hasso508e53e2004-05-18 18:57:06 +00001352 )
1353{
1354 unsigned char level = 0;
1355
1356 if (! strncmp (argv[0], "table", 5))
1357 level = OSPF6_DEBUG_ROUTE_TABLE;
1358 else if (! strncmp (argv[0], "intra", 5))
1359 level = OSPF6_DEBUG_ROUTE_INTRA;
1360 else if (! strncmp (argv[0], "inter", 5))
1361 level = OSPF6_DEBUG_ROUTE_INTER;
Tom Goff8f228de2010-11-10 13:02:11 -08001362 else if (! strncmp (argv[0], "memor", 5))
1363 level = OSPF6_DEBUG_ROUTE_MEMORY;
hasso508e53e2004-05-18 18:57:06 +00001364 OSPF6_DEBUG_ROUTE_ON (level);
1365 return CMD_SUCCESS;
1366}
1367
1368DEFUN (no_debug_ospf6_route,
1369 no_debug_ospf6_route_cmd,
Tom Goff8f228de2010-11-10 13:02:11 -08001370 "no debug ospf6 route (table|intra-area|inter-area|memory)",
hasso508e53e2004-05-18 18:57:06 +00001371 NO_STR
1372 DEBUG_STR
1373 OSPF6_STR
1374 "Debug route table calculation\n"
Tom Goff8f228de2010-11-10 13:02:11 -08001375 "Debug intra-area route calculation\n"
1376 "Debug route memory use\n")
hasso508e53e2004-05-18 18:57:06 +00001377{
1378 unsigned char level = 0;
1379
1380 if (! strncmp (argv[0], "table", 5))
1381 level = OSPF6_DEBUG_ROUTE_TABLE;
1382 else if (! strncmp (argv[0], "intra", 5))
1383 level = OSPF6_DEBUG_ROUTE_INTRA;
1384 else if (! strncmp (argv[0], "inter", 5))
1385 level = OSPF6_DEBUG_ROUTE_INTER;
Tom Goff8f228de2010-11-10 13:02:11 -08001386 else if (! strncmp (argv[0], "memor", 5))
1387 level = OSPF6_DEBUG_ROUTE_MEMORY;
hasso508e53e2004-05-18 18:57:06 +00001388 OSPF6_DEBUG_ROUTE_OFF (level);
1389 return CMD_SUCCESS;
1390}
1391
1392int
1393config_write_ospf6_debug_route (struct vty *vty)
1394{
1395 if (IS_OSPF6_DEBUG_ROUTE (TABLE))
hasso049207c2004-08-04 20:02:13 +00001396 vty_out (vty, "debug ospf6 route table%s", VNL);
hasso508e53e2004-05-18 18:57:06 +00001397 if (IS_OSPF6_DEBUG_ROUTE (INTRA))
hasso049207c2004-08-04 20:02:13 +00001398 vty_out (vty, "debug ospf6 route intra-area%s", VNL);
hasso508e53e2004-05-18 18:57:06 +00001399 if (IS_OSPF6_DEBUG_ROUTE (INTER))
hasso049207c2004-08-04 20:02:13 +00001400 vty_out (vty, "debug ospf6 route inter-area%s", VNL);
hasso508e53e2004-05-18 18:57:06 +00001401 return 0;
1402}
1403
1404void
Paul Jakma6ac29a52008-08-15 13:45:30 +01001405install_element_ospf6_debug_route (void)
hasso508e53e2004-05-18 18:57:06 +00001406{
1407 install_element (ENABLE_NODE, &debug_ospf6_route_cmd);
1408 install_element (ENABLE_NODE, &no_debug_ospf6_route_cmd);
1409 install_element (CONFIG_NODE, &debug_ospf6_route_cmd);
1410 install_element (CONFIG_NODE, &no_debug_ospf6_route_cmd);
1411}
1412
1413
1414