Annotation of embedaddon/quagga/ospf6d/ospf6_route.c, revision 1.1
1.1 ! misho 1: /*
! 2: * Copyright (C) 2003 Yasuhiro Ohara
! 3: *
! 4: * This file is part of GNU Zebra.
! 5: *
! 6: * GNU Zebra is free software; you can redistribute it and/or modify it
! 7: * under the terms of the GNU General Public License as published by the
! 8: * Free Software Foundation; either version 2, or (at your option) any
! 9: * later version.
! 10: *
! 11: * GNU Zebra is distributed in the hope that it will be useful, but
! 12: * WITHOUT ANY WARRANTY; without even the implied warranty of
! 13: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
! 14: * General Public License for more details.
! 15: *
! 16: * You should have received a copy of the GNU General Public License
! 17: * along with GNU Zebra; see the file COPYING. If not, write to the
! 18: * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
! 19: * Boston, MA 02111-1307, USA.
! 20: */
! 21:
! 22: #include <zebra.h>
! 23:
! 24: #include "log.h"
! 25: #include "memory.h"
! 26: #include "prefix.h"
! 27: #include "table.h"
! 28: #include "vty.h"
! 29: #include "command.h"
! 30: #include "linklist.h"
! 31:
! 32: #include "ospf6_proto.h"
! 33: #include "ospf6_lsa.h"
! 34: #include "ospf6_lsdb.h"
! 35: #include "ospf6_route.h"
! 36: #include "ospf6_top.h"
! 37: #include "ospf6_area.h"
! 38: #include "ospf6_interface.h"
! 39: #include "ospf6d.h"
! 40:
! 41: unsigned char conf_debug_ospf6_route = 0;
! 42:
! 43: static char *
! 44: ospf6_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:
! 136: void
! 137: ospf6_linkstate_prefix (u_int32_t adv_router, u_int32_t id,
! 138: struct prefix *prefix)
! 139: {
! 140: 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);
! 145: }
! 146:
! 147: void
! 148: ospf6_linkstate_prefix2str (struct prefix *prefix, char *buf, int size)
! 149: {
! 150: u_int32_t adv_router, id;
! 151: char adv_router_str[16], id_str[16];
! 152: 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));
! 155: 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);
! 160: }
! 161:
! 162: /* Global strings for logging */
! 163: const char *ospf6_dest_type_str[OSPF6_DEST_TYPE_MAX] =
! 164: { "Unknown", "Router", "Network", "Discard", "Linkstate", "AddressRange", };
! 165:
! 166: const char *ospf6_dest_type_substr[OSPF6_DEST_TYPE_MAX] =
! 167: { "?", "R", "N", "D", "L", "A", };
! 168:
! 169: const char *ospf6_path_type_str[OSPF6_PATH_TYPE_MAX] =
! 170: { "Unknown", "Intra-Area", "Inter-Area", "External-1", "External-2", };
! 171:
! 172: const char *ospf6_path_type_substr[OSPF6_PATH_TYPE_MAX] =
! 173: { "??", "IA", "IE", "E1", "E2", };
! 174:
! 175:
! 176: struct ospf6_route *
! 177: ospf6_route_create (void)
! 178: {
! 179: struct ospf6_route *route;
! 180: route = XCALLOC (MTYPE_OSPF6_ROUTE, sizeof (struct ospf6_route));
! 181: return route;
! 182: }
! 183:
! 184: void
! 185: ospf6_route_delete (struct ospf6_route *route)
! 186: {
! 187: XFREE (MTYPE_OSPF6_ROUTE, route);
! 188: }
! 189:
! 190: struct ospf6_route *
! 191: ospf6_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;
! 200: new->table = NULL;
! 201: new->lock = 0;
! 202: return new;
! 203: }
! 204:
! 205: void
! 206: ospf6_route_lock (struct ospf6_route *route)
! 207: {
! 208: route->lock++;
! 209: }
! 210:
! 211: void
! 212: ospf6_route_unlock (struct ospf6_route *route)
! 213: {
! 214: assert (route->lock > 0);
! 215: route->lock--;
! 216: if (route->lock == 0)
! 217: {
! 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: }
! 224: }
! 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 */
! 229: static int
! 230: ospf6_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:
! 261: struct ospf6_route *
! 262: ospf6_route_lookup (struct prefix *prefix,
! 263: struct ospf6_route_table *table)
! 264: {
! 265: struct route_node *node;
! 266: struct ospf6_route *route;
! 267:
! 268: node = route_node_lookup (table->table, prefix);
! 269: if (node == NULL)
! 270: return NULL;
! 271:
! 272: route = (struct ospf6_route *) node->info;
! 273: return route;
! 274: }
! 275:
! 276: struct ospf6_route *
! 277: ospf6_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:
! 291: struct ospf6_route *
! 292: ospf6_route_lookup_bestmatch (struct prefix *prefix,
! 293: struct ospf6_route_table *table)
! 294: {
! 295: struct route_node *node;
! 296: struct ospf6_route *route;
! 297:
! 298: node = route_node_match (table->table, prefix);
! 299: if (node == NULL)
! 300: return NULL;
! 301: route_unlock_node (node);
! 302:
! 303: route = (struct ospf6_route *) node->info;
! 304: return route;
! 305: }
! 306:
! 307: #ifndef NDEBUG
! 308: static void
! 309: route_table_assert (struct ospf6_route_table *table)
! 310: {
! 311: struct ospf6_route *prev, *r, *next;
! 312: char buf[64];
! 313: 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))
! 332: num++;
! 333:
! 334: if (link_error == 0 && num == table->count)
! 335: return;
! 336:
! 337: 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))
! 342: {
! 343: prefix2str (&r->prefix, buf, sizeof (buf));
! 344: zlog_info ("%p<-[%p]->%p : %s", r->prev, r, r->next, buf);
! 345: }
! 346: zlog_debug ("DUMP END");
! 347:
! 348: assert (link_error == 0 && num == table->count);
! 349: }
! 350: #define ospf6_route_table_assert(t) (route_table_assert (t))
! 351: #else
! 352: #define ospf6_route_table_assert(t) ((void) 0)
! 353: #endif /*NDEBUG*/
! 354:
! 355: struct ospf6_route *
! 356: ospf6_route_add (struct ospf6_route *route,
! 357: struct ospf6_route_table *table)
! 358: {
! 359: 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;
! 364:
! 365: assert (route->rnode == NULL);
! 366: assert (route->lock == 0);
! 367: assert (route->next == NULL);
! 368: assert (route->prev == NULL);
! 369:
! 370: 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));
! 374:
! 375: if (IS_OSPF6_DEBUG_ROUTE (MEMORY))
! 376: zlog_debug ("%s %p: route add %p: %s", ospf6_route_table_name (table),
! 377: table, route, buf);
! 378: else if (IS_OSPF6_DEBUG_ROUTE (TABLE))
! 379: zlog_debug ("%s: route add: %s", ospf6_route_table_name (table), buf);
! 380:
! 381: quagga_gettime (QUAGGA_CLK_MONOTONIC, &now);
! 382:
! 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)
! 388: {
! 389: 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;
! 402: }
! 403:
! 404: if (old)
! 405: {
! 406: /* if route does not actually change, return unchanged */
! 407: if (ospf6_route_is_identical (old, route))
! 408: {
! 409: if (IS_OSPF6_DEBUG_ROUTE (MEMORY))
! 410: zlog_debug ("%s %p: route add %p: needless update of %p",
! 411: ospf6_route_table_name (table), table, route, old);
! 412: else if (IS_OSPF6_DEBUG_ROUTE (TABLE))
! 413: zlog_debug ("%s: route add: needless update",
! 414: ospf6_route_table_name (table));
! 415:
! 416: ospf6_route_delete (route);
! 417: SET_FLAG (old->flag, OSPF6_ROUTE_ADD);
! 418: ospf6_route_table_assert (table);
! 419:
! 420: return old;
! 421: }
! 422:
! 423: if (IS_OSPF6_DEBUG_ROUTE (MEMORY))
! 424: zlog_debug ("%s %p: route add %p: update of %p",
! 425: ospf6_route_table_name (table), table, route, old);
! 426: else if (IS_OSPF6_DEBUG_ROUTE (TABLE))
! 427: zlog_debug ("%s: route add: update",
! 428: ospf6_route_table_name (table));
! 429:
! 430: /* replace old one if exists */
! 431: if (node->info == old)
! 432: {
! 433: node->info = route;
! 434: SET_FLAG (route->flag, OSPF6_ROUTE_BEST);
! 435: }
! 436:
! 437: if (old->prev)
! 438: old->prev->next = route;
! 439: route->prev = old->prev;
! 440: if (old->next)
! 441: old->next->prev = route;
! 442: route->next = old->next;
! 443:
! 444: route->installed = old->installed;
! 445: route->changed = now;
! 446: assert (route->table == NULL);
! 447: route->table = table;
! 448:
! 449: ospf6_route_unlock (old); /* will be deleted later */
! 450: ospf6_route_lock (route);
! 451:
! 452: SET_FLAG (route->flag, OSPF6_ROUTE_CHANGE);
! 453: ospf6_route_table_assert (table);
! 454:
! 455: if (table->hook_add)
! 456: (*table->hook_add) (route);
! 457:
! 458: return route;
! 459: }
! 460:
! 461: /* insert if previous or next node found */
! 462: if (prev || next)
! 463: {
! 464: if (IS_OSPF6_DEBUG_ROUTE (MEMORY))
! 465: zlog_debug ("%s %p: route add %p: another path: prev %p, next %p",
! 466: ospf6_route_table_name (table), table, route, prev, next);
! 467: else if (IS_OSPF6_DEBUG_ROUTE (TABLE))
! 468: zlog_debug ("%s: route add: another path found",
! 469: ospf6_route_table_name (table));
! 470:
! 471: if (prev == NULL)
! 472: prev = next->prev;
! 473: if (next == NULL)
! 474: next = prev->next;
! 475:
! 476: if (prev)
! 477: prev->next = route;
! 478: route->prev = prev;
! 479: if (next)
! 480: next->prev = route;
! 481: route->next = next;
! 482:
! 483: if (node->info == next)
! 484: {
! 485: assert (next->rnode == node);
! 486: node->info = route;
! 487: UNSET_FLAG (next->flag, OSPF6_ROUTE_BEST);
! 488: SET_FLAG (route->flag, OSPF6_ROUTE_BEST);
! 489: if (IS_OSPF6_DEBUG_ROUTE (MEMORY))
! 490: zlog_info ("%s %p: route add %p: replacing previous best: %p",
! 491: ospf6_route_table_name (table), table, route, next);
! 492: }
! 493:
! 494: route->installed = now;
! 495: route->changed = now;
! 496: assert (route->table == NULL);
! 497: route->table = table;
! 498:
! 499: ospf6_route_lock (route);
! 500: table->count++;
! 501: ospf6_route_table_assert (table);
! 502:
! 503: SET_FLAG (route->flag, OSPF6_ROUTE_ADD);
! 504: if (table->hook_add)
! 505: (*table->hook_add) (route);
! 506:
! 507: return route;
! 508: }
! 509:
! 510: /* Else, this is the brand new route regarding to the prefix */
! 511: if (IS_OSPF6_DEBUG_ROUTE (MEMORY))
! 512: zlog_debug ("%s %p: route add %p: brand new route",
! 513: ospf6_route_table_name (table), table, route);
! 514: else if (IS_OSPF6_DEBUG_ROUTE (TABLE))
! 515: zlog_debug ("%s: route add: brand new route",
! 516: ospf6_route_table_name (table));
! 517:
! 518: assert (node->info == NULL);
! 519: node->info = route;
! 520: SET_FLAG (route->flag, OSPF6_ROUTE_BEST);
! 521: ospf6_route_lock (route);
! 522: route->installed = now;
! 523: route->changed = now;
! 524: assert (route->table == NULL);
! 525: route->table = table;
! 526:
! 527: /* lookup real existing next route */
! 528: nextnode = node;
! 529: route_lock_node (nextnode);
! 530: do {
! 531: nextnode = route_next (nextnode);
! 532: } while (nextnode && nextnode->info == NULL);
! 533:
! 534: /* set next link */
! 535: if (nextnode == NULL)
! 536: route->next = NULL;
! 537: else
! 538: {
! 539: route_unlock_node (nextnode);
! 540:
! 541: next = nextnode->info;
! 542: route->next = next;
! 543: next->prev = route;
! 544: }
! 545:
! 546: /* lookup real existing prev route */
! 547: prevnode = node;
! 548: route_lock_node (prevnode);
! 549: do {
! 550: prevnode = route_prev (prevnode);
! 551: } while (prevnode && prevnode->info == NULL);
! 552:
! 553: /* set prev link */
! 554: if (prevnode == NULL)
! 555: route->prev = NULL;
! 556: else
! 557: {
! 558: route_unlock_node (prevnode);
! 559:
! 560: prev = prevnode->info;
! 561: while (prev->next && ospf6_route_is_same (prev, prev->next))
! 562: prev = prev->next;
! 563: route->prev = prev;
! 564: prev->next = route;
! 565: }
! 566:
! 567: table->count++;
! 568: ospf6_route_table_assert (table);
! 569:
! 570: SET_FLAG (route->flag, OSPF6_ROUTE_ADD);
! 571: if (table->hook_add)
! 572: (*table->hook_add) (route);
! 573:
! 574: return route;
! 575: }
! 576:
! 577: void
! 578: ospf6_route_remove (struct ospf6_route *route,
! 579: struct ospf6_route_table *table)
! 580: {
! 581: struct route_node *node;
! 582: struct ospf6_route *current;
! 583: char buf[64];
! 584:
! 585: if (route->type == OSPF6_DEST_TYPE_LINKSTATE)
! 586: ospf6_linkstate_prefix2str (&route->prefix, buf, sizeof (buf));
! 587: else
! 588: prefix2str (&route->prefix, buf, sizeof (buf));
! 589:
! 590: if (IS_OSPF6_DEBUG_ROUTE (MEMORY))
! 591: zlog_debug ("%s %p: route remove %p: %s",
! 592: ospf6_route_table_name (table), table, route, buf);
! 593: else if (IS_OSPF6_DEBUG_ROUTE (TABLE))
! 594: zlog_debug ("%s: route remove: %s", ospf6_route_table_name (table), buf);
! 595:
! 596: node = route_node_lookup (table->table, &route->prefix);
! 597: assert (node);
! 598:
! 599: /* find the route to remove, making sure that the route pointer
! 600: is from the route table. */
! 601: current = node->info;
! 602: while (current && ospf6_route_is_same (current, route))
! 603: {
! 604: if (current == route)
! 605: break;
! 606: current = current->next;
! 607: }
! 608: assert (current == route);
! 609:
! 610: /* adjust doubly linked list */
! 611: if (route->prev)
! 612: route->prev->next = route->next;
! 613: if (route->next)
! 614: route->next->prev = route->prev;
! 615:
! 616: if (node->info == route)
! 617: {
! 618: if (route->next && ospf6_route_is_same (route->next, route))
! 619: {
! 620: node->info = route->next;
! 621: SET_FLAG (route->next->flag, OSPF6_ROUTE_BEST);
! 622: }
! 623: else
! 624: node->info = NULL; /* should unlock route_node here ? */
! 625: }
! 626:
! 627: table->count--;
! 628: ospf6_route_table_assert (table);
! 629:
! 630: SET_FLAG (route->flag, OSPF6_ROUTE_WAS_REMOVED);
! 631:
! 632: if (table->hook_remove)
! 633: (*table->hook_remove) (route);
! 634:
! 635: ospf6_route_unlock (route);
! 636: }
! 637:
! 638: struct ospf6_route *
! 639: ospf6_route_head (struct ospf6_route_table *table)
! 640: {
! 641: struct route_node *node;
! 642: struct ospf6_route *route;
! 643:
! 644: node = route_top (table->table);
! 645: if (node == NULL)
! 646: return NULL;
! 647:
! 648: /* skip to the real existing entry */
! 649: while (node && node->info == NULL)
! 650: node = route_next (node);
! 651: if (node == NULL)
! 652: return NULL;
! 653:
! 654: route_unlock_node (node);
! 655: assert (node->info);
! 656:
! 657: route = (struct ospf6_route *) node->info;
! 658: assert (route->prev == NULL);
! 659: assert (route->table == table);
! 660: ospf6_route_lock (route);
! 661:
! 662: if (IS_OSPF6_DEBUG_ROUTE (MEMORY))
! 663: zlog_info ("%s %p: route head: %p<-[%p]->%p",
! 664: ospf6_route_table_name (table), table,
! 665: route->prev, route, route->next);
! 666:
! 667: return route;
! 668: }
! 669:
! 670: struct ospf6_route *
! 671: ospf6_route_next (struct ospf6_route *route)
! 672: {
! 673: struct ospf6_route *next = route->next;
! 674:
! 675: if (IS_OSPF6_DEBUG_ROUTE (MEMORY))
! 676: zlog_info ("%s %p: route next: %p<-[%p]->%p",
! 677: ospf6_route_table_name (route->table), route->table,
! 678: route->prev, route, route->next);
! 679:
! 680: ospf6_route_unlock (route);
! 681: if (next)
! 682: ospf6_route_lock (next);
! 683:
! 684: return next;
! 685: }
! 686:
! 687: struct ospf6_route *
! 688: ospf6_route_best_next (struct ospf6_route *route)
! 689: {
! 690: struct route_node *rnode;
! 691: struct ospf6_route *next;
! 692:
! 693: ospf6_route_unlock (route);
! 694:
! 695: rnode = route->rnode;
! 696: route_lock_node (rnode);
! 697: rnode = route_next (rnode);
! 698: while (rnode && rnode->info == NULL)
! 699: rnode = route_next (rnode);
! 700: if (rnode == NULL)
! 701: return NULL;
! 702: route_unlock_node (rnode);
! 703:
! 704: assert (rnode->info);
! 705: next = (struct ospf6_route *) rnode->info;
! 706: ospf6_route_lock (next);
! 707: return next;
! 708: }
! 709:
! 710: struct ospf6_route *
! 711: ospf6_route_match_head (struct prefix *prefix,
! 712: struct ospf6_route_table *table)
! 713: {
! 714: struct route_node *node;
! 715: struct ospf6_route *route;
! 716:
! 717: /* Walk down tree. */
! 718: node = table->table->top;
! 719: while (node && node->p.prefixlen < prefix->prefixlen &&
! 720: prefix_match (&node->p, prefix))
! 721: node = node->link[prefix_bit(&prefix->u.prefix, node->p.prefixlen)];
! 722:
! 723: if (node)
! 724: route_lock_node (node);
! 725: while (node && node->info == NULL)
! 726: node = route_next (node);
! 727: if (node == NULL)
! 728: return NULL;
! 729: route_unlock_node (node);
! 730:
! 731: if (! prefix_match (prefix, &node->p))
! 732: return NULL;
! 733:
! 734: route = node->info;
! 735: ospf6_route_lock (route);
! 736: return route;
! 737: }
! 738:
! 739: struct ospf6_route *
! 740: ospf6_route_match_next (struct prefix *prefix,
! 741: struct ospf6_route *route)
! 742: {
! 743: struct ospf6_route *next;
! 744:
! 745: next = ospf6_route_next (route);
! 746: if (next && ! prefix_match (prefix, &next->prefix))
! 747: {
! 748: ospf6_route_unlock (next);
! 749: next = NULL;
! 750: }
! 751:
! 752: return next;
! 753: }
! 754:
! 755: void
! 756: ospf6_route_remove_all (struct ospf6_route_table *table)
! 757: {
! 758: struct ospf6_route *route;
! 759: for (route = ospf6_route_head (table); route;
! 760: route = ospf6_route_next (route))
! 761: ospf6_route_remove (route, table);
! 762: }
! 763:
! 764: struct ospf6_route_table *
! 765: ospf6_route_table_create (int s, int t)
! 766: {
! 767: struct ospf6_route_table *new;
! 768: new = XCALLOC (MTYPE_OSPF6_ROUTE, sizeof (struct ospf6_route_table));
! 769: new->table = route_table_init ();
! 770: new->scope_type = s;
! 771: new->table_type = t;
! 772: return new;
! 773: }
! 774:
! 775: void
! 776: ospf6_route_table_delete (struct ospf6_route_table *table)
! 777: {
! 778: ospf6_route_remove_all (table);
! 779: route_table_finish (table->table);
! 780: XFREE (MTYPE_OSPF6_ROUTE, table);
! 781: }
! 782:
! 783:
! 784: /* VTY commands */
! 785: void
! 786: ospf6_route_show (struct vty *vty, struct ospf6_route *route)
! 787: {
! 788: int i;
! 789: char destination[64], nexthop[64];
! 790: char duration[16], ifname[IFNAMSIZ];
! 791: struct timeval now, res;
! 792:
! 793: quagga_gettime (QUAGGA_CLK_MONOTONIC, &now);
! 794: timersub (&now, &route->changed, &res);
! 795: timerstring (&res, duration, sizeof (duration));
! 796:
! 797: /* destination */
! 798: if (route->type == OSPF6_DEST_TYPE_LINKSTATE)
! 799: ospf6_linkstate_prefix2str (&route->prefix, destination,
! 800: sizeof (destination));
! 801: else if (route->type == OSPF6_DEST_TYPE_ROUTER)
! 802: inet_ntop (route->prefix.family, &route->prefix.u.prefix,
! 803: destination, sizeof (destination));
! 804: else
! 805: prefix2str (&route->prefix, destination, sizeof (destination));
! 806:
! 807: /* nexthop */
! 808: inet_ntop (AF_INET6, &route->nexthop[0].address, nexthop,
! 809: sizeof (nexthop));
! 810: if (! if_indextoname (route->nexthop[0].ifindex, ifname))
! 811: snprintf (ifname, sizeof (ifname), "%d", route->nexthop[0].ifindex);
! 812:
! 813: vty_out (vty, "%c%1s %2s %-30s %-25s %6.*s %s%s",
! 814: (ospf6_route_is_best (route) ? '*' : ' '),
! 815: OSPF6_DEST_TYPE_SUBSTR (route->type),
! 816: OSPF6_PATH_TYPE_SUBSTR (route->path.type),
! 817: destination, nexthop, IFNAMSIZ, ifname, duration, VNL);
! 818:
! 819: for (i = 1; ospf6_nexthop_is_set (&route->nexthop[i]) &&
! 820: i < OSPF6_MULTI_PATH_LIMIT; i++)
! 821: {
! 822: /* nexthop */
! 823: inet_ntop (AF_INET6, &route->nexthop[i].address, nexthop,
! 824: sizeof (nexthop));
! 825: if (! if_indextoname (route->nexthop[i].ifindex, ifname))
! 826: snprintf (ifname, sizeof (ifname), "%d", route->nexthop[i].ifindex);
! 827:
! 828: vty_out (vty, "%c%1s %2s %-30s %-25s %6.*s %s%s",
! 829: ' ', "", "", "", nexthop, IFNAMSIZ, ifname, "", VNL);
! 830: }
! 831: }
! 832:
! 833: void
! 834: ospf6_route_show_detail (struct vty *vty, struct ospf6_route *route)
! 835: {
! 836: char destination[64], nexthop[64], ifname[IFNAMSIZ];
! 837: char area_id[16], id[16], adv_router[16], capa[16], options[16];
! 838: struct timeval now, res;
! 839: char duration[16];
! 840: int i;
! 841:
! 842: quagga_gettime (QUAGGA_CLK_MONOTONIC, &now);
! 843:
! 844: /* destination */
! 845: if (route->type == OSPF6_DEST_TYPE_LINKSTATE)
! 846: ospf6_linkstate_prefix2str (&route->prefix, destination,
! 847: sizeof (destination));
! 848: else if (route->type == OSPF6_DEST_TYPE_ROUTER)
! 849: inet_ntop (route->prefix.family, &route->prefix.u.prefix,
! 850: destination, sizeof (destination));
! 851: else
! 852: prefix2str (&route->prefix, destination, sizeof (destination));
! 853: vty_out (vty, "Destination: %s%s", destination, VNL);
! 854:
! 855: /* destination type */
! 856: vty_out (vty, "Destination type: %s%s",
! 857: OSPF6_DEST_TYPE_NAME (route->type),
! 858: VNL);
! 859:
! 860: /* Time */
! 861: timersub (&now, &route->installed, &res);
! 862: timerstring (&res, duration, sizeof (duration));
! 863: vty_out (vty, "Installed Time: %s ago%s", duration, VNL);
! 864:
! 865: timersub (&now, &route->changed, &res);
! 866: timerstring (&res, duration, sizeof (duration));
! 867: vty_out (vty, " Changed Time: %s ago%s", duration, VNL);
! 868:
! 869: /* Debugging info */
! 870: vty_out (vty, "Lock: %d Flags: %s%s%s%s%s", route->lock,
! 871: (CHECK_FLAG (route->flag, OSPF6_ROUTE_BEST) ? "B" : "-"),
! 872: (CHECK_FLAG (route->flag, OSPF6_ROUTE_ADD) ? "A" : "-"),
! 873: (CHECK_FLAG (route->flag, OSPF6_ROUTE_REMOVE) ? "R" : "-"),
! 874: (CHECK_FLAG (route->flag, OSPF6_ROUTE_CHANGE) ? "C" : "-"),
! 875: VNL);
! 876: vty_out (vty, "Memory: prev: %p this: %p next: %p%s",
! 877: route->prev, route, route->next, VNL);
! 878:
! 879: /* Path section */
! 880:
! 881: /* Area-ID */
! 882: inet_ntop (AF_INET, &route->path.area_id, area_id, sizeof (area_id));
! 883: vty_out (vty, "Associated Area: %s%s", area_id, VNL);
! 884:
! 885: /* Path type */
! 886: vty_out (vty, "Path Type: %s%s",
! 887: OSPF6_PATH_TYPE_NAME (route->path.type), VNL);
! 888:
! 889: /* LS Origin */
! 890: inet_ntop (AF_INET, &route->path.origin.id, id, sizeof (id));
! 891: inet_ntop (AF_INET, &route->path.origin.adv_router, adv_router,
! 892: sizeof (adv_router));
! 893: vty_out (vty, "LS Origin: %s Id: %s Adv: %s%s",
! 894: ospf6_lstype_name (route->path.origin.type),
! 895: id, adv_router, VNL);
! 896:
! 897: /* Options */
! 898: ospf6_options_printbuf (route->path.options, options, sizeof (options));
! 899: vty_out (vty, "Options: %s%s", options, VNL);
! 900:
! 901: /* Router Bits */
! 902: ospf6_capability_printbuf (route->path.router_bits, capa, sizeof (capa));
! 903: vty_out (vty, "Router Bits: %s%s", capa, VNL);
! 904:
! 905: /* Prefix Options */
! 906: vty_out (vty, "Prefix Options: xxx%s", VNL);
! 907:
! 908: /* Metrics */
! 909: vty_out (vty, "Metric Type: %d%s", route->path.metric_type,
! 910: VNL);
! 911: vty_out (vty, "Metric: %d (%d)%s",
! 912: route->path.cost, route->path.cost_e2, VNL);
! 913:
! 914: /* Nexthops */
! 915: vty_out (vty, "Nexthop:%s", VNL);
! 916: for (i = 0; ospf6_nexthop_is_set (&route->nexthop[i]) &&
! 917: i < OSPF6_MULTI_PATH_LIMIT; i++)
! 918: {
! 919: /* nexthop */
! 920: inet_ntop (AF_INET6, &route->nexthop[i].address, nexthop,
! 921: sizeof (nexthop));
! 922: if (! if_indextoname (route->nexthop[i].ifindex, ifname))
! 923: snprintf (ifname, sizeof (ifname), "%d", route->nexthop[i].ifindex);
! 924: vty_out (vty, " %s %.*s%s", nexthop, IFNAMSIZ, ifname, VNL);
! 925: }
! 926: vty_out (vty, "%s", VNL);
! 927: }
! 928:
! 929: static void
! 930: ospf6_route_show_table_summary (struct vty *vty,
! 931: struct ospf6_route_table *table)
! 932: {
! 933: struct ospf6_route *route, *prev = NULL;
! 934: int i, pathtype[OSPF6_PATH_TYPE_MAX];
! 935: unsigned int number = 0;
! 936: int nhinval = 0, ecmp = 0;
! 937: int alternative = 0, destination = 0;
! 938:
! 939: for (i = 0; i < OSPF6_PATH_TYPE_MAX; i++)
! 940: pathtype[i] = 0;
! 941:
! 942: for (route = ospf6_route_head (table); route;
! 943: route = ospf6_route_next (route))
! 944: {
! 945: if (prev == NULL || ! ospf6_route_is_same (prev, route))
! 946: destination++;
! 947: else
! 948: alternative++;
! 949: if (! ospf6_nexthop_is_set (&route->nexthop[0]))
! 950: nhinval++;
! 951: else if (ospf6_nexthop_is_set (&route->nexthop[1]))
! 952: ecmp++;
! 953: pathtype[route->path.type]++;
! 954: number++;
! 955:
! 956: prev = route;
! 957: }
! 958:
! 959: assert (number == table->count);
! 960:
! 961: vty_out (vty, "Number of OSPFv3 routes: %d%s", number, VNL);
! 962: vty_out (vty, "Number of Destination: %d%s", destination, VNL);
! 963: vty_out (vty, "Number of Alternative routes: %d%s", alternative, VNL);
! 964: vty_out (vty, "Number of Equal Cost Multi Path: %d%s", ecmp, VNL);
! 965: for (i = OSPF6_PATH_TYPE_INTRA; i <= OSPF6_PATH_TYPE_EXTERNAL2; i++)
! 966: {
! 967: vty_out (vty, "Number of %s routes: %d%s",
! 968: OSPF6_PATH_TYPE_NAME (i), pathtype[i], VNL);
! 969: }
! 970: }
! 971:
! 972: static void
! 973: ospf6_route_show_table_prefix (struct vty *vty,
! 974: struct prefix *prefix,
! 975: struct ospf6_route_table *table)
! 976: {
! 977: struct ospf6_route *route;
! 978:
! 979: route = ospf6_route_lookup (prefix, table);
! 980: if (route == NULL)
! 981: return;
! 982:
! 983: ospf6_route_lock (route);
! 984: while (route && ospf6_route_is_prefix (prefix, route))
! 985: {
! 986: /* Specifying a prefix will always display details */
! 987: ospf6_route_show_detail (vty, route);
! 988: route = ospf6_route_next (route);
! 989: }
! 990: if (route)
! 991: ospf6_route_unlock (route);
! 992: }
! 993:
! 994: static void
! 995: ospf6_route_show_table_address (struct vty *vty,
! 996: struct prefix *prefix,
! 997: struct ospf6_route_table *table)
! 998: {
! 999: struct ospf6_route *route;
! 1000:
! 1001: route = ospf6_route_lookup_bestmatch (prefix, table);
! 1002: if (route == NULL)
! 1003: return;
! 1004:
! 1005: prefix = &route->prefix;
! 1006: ospf6_route_lock (route);
! 1007: while (route && ospf6_route_is_prefix (prefix, route))
! 1008: {
! 1009: /* Specifying a prefix will always display details */
! 1010: ospf6_route_show_detail (vty, route);
! 1011: route = ospf6_route_next (route);
! 1012: }
! 1013: if (route)
! 1014: ospf6_route_unlock (route);
! 1015: }
! 1016:
! 1017: static void
! 1018: ospf6_route_show_table_match (struct vty *vty, int detail,
! 1019: struct prefix *prefix,
! 1020: struct ospf6_route_table *table)
! 1021: {
! 1022: struct ospf6_route *route;
! 1023: assert (prefix->family);
! 1024:
! 1025: route = ospf6_route_match_head (prefix, table);
! 1026: while (route)
! 1027: {
! 1028: if (detail)
! 1029: ospf6_route_show_detail (vty, route);
! 1030: else
! 1031: ospf6_route_show (vty, route);
! 1032: route = ospf6_route_match_next (prefix, route);
! 1033: }
! 1034: }
! 1035:
! 1036: static void
! 1037: ospf6_route_show_table_type (struct vty *vty, int detail, u_char type,
! 1038: struct ospf6_route_table *table)
! 1039: {
! 1040: struct ospf6_route *route;
! 1041:
! 1042: route = ospf6_route_head (table);
! 1043: while (route)
! 1044: {
! 1045: if (route->path.type == type)
! 1046: {
! 1047: if (detail)
! 1048: ospf6_route_show_detail (vty, route);
! 1049: else
! 1050: ospf6_route_show (vty, route);
! 1051: }
! 1052: route = ospf6_route_next (route);
! 1053: }
! 1054: }
! 1055:
! 1056: static void
! 1057: ospf6_route_show_table (struct vty *vty, int detail,
! 1058: struct ospf6_route_table *table)
! 1059: {
! 1060: struct ospf6_route *route;
! 1061:
! 1062: route = ospf6_route_head (table);
! 1063: while (route)
! 1064: {
! 1065: if (detail)
! 1066: ospf6_route_show_detail (vty, route);
! 1067: else
! 1068: ospf6_route_show (vty, route);
! 1069: route = ospf6_route_next (route);
! 1070: }
! 1071: }
! 1072:
! 1073: int
! 1074: ospf6_route_table_show (struct vty *vty, int argc, const char *argv[],
! 1075: struct ospf6_route_table *table)
! 1076: {
! 1077: int summary = 0;
! 1078: int match = 0;
! 1079: int detail = 0;
! 1080: int slash = 0;
! 1081: int isprefix = 0;
! 1082: int i, ret;
! 1083: struct prefix prefix;
! 1084: u_char type = 0;
! 1085:
! 1086: memset (&prefix, 0, sizeof (struct prefix));
! 1087:
! 1088: for (i = 0; i < argc; i++)
! 1089: {
! 1090: if (! strcmp (argv[i], "summary"))
! 1091: {
! 1092: summary++;
! 1093: continue;
! 1094: }
! 1095:
! 1096: if (! strcmp (argv[i], "intra-area"))
! 1097: {
! 1098: type = OSPF6_PATH_TYPE_INTRA;
! 1099: continue;
! 1100: }
! 1101:
! 1102: if (! strcmp (argv[i], "inter-area"))
! 1103: {
! 1104: type = OSPF6_PATH_TYPE_INTER;
! 1105: continue;
! 1106: }
! 1107:
! 1108: if (! strcmp (argv[i], "external-1"))
! 1109: {
! 1110: type = OSPF6_PATH_TYPE_EXTERNAL1;
! 1111: continue;
! 1112: }
! 1113:
! 1114: if (! strcmp (argv[i], "external-2"))
! 1115: {
! 1116: type = OSPF6_PATH_TYPE_EXTERNAL2;
! 1117: continue;
! 1118: }
! 1119:
! 1120: if (! strcmp (argv[i], "detail"))
! 1121: {
! 1122: detail++;
! 1123: continue;
! 1124: }
! 1125:
! 1126: if (! strcmp (argv[i], "match"))
! 1127: {
! 1128: match++;
! 1129: continue;
! 1130: }
! 1131:
! 1132: ret = str2prefix (argv[i], &prefix);
! 1133: if (ret == 1 && prefix.family == AF_INET6)
! 1134: {
! 1135: isprefix++;
! 1136: if (strchr (argv[i], '/'))
! 1137: slash++;
! 1138: continue;
! 1139: }
! 1140:
! 1141: vty_out (vty, "Malformed argument: %s%s", argv[i], VNL);
! 1142: return CMD_SUCCESS;
! 1143: }
! 1144:
! 1145: /* Give summary of this route table */
! 1146: if (summary)
! 1147: {
! 1148: ospf6_route_show_table_summary (vty, table);
! 1149: return CMD_SUCCESS;
! 1150: }
! 1151:
! 1152: /* Give exact prefix-match route */
! 1153: if (isprefix && ! match)
! 1154: {
! 1155: /* If exact address, give best matching route */
! 1156: if (! slash)
! 1157: ospf6_route_show_table_address (vty, &prefix, table);
! 1158: else
! 1159: ospf6_route_show_table_prefix (vty, &prefix, table);
! 1160:
! 1161: return CMD_SUCCESS;
! 1162: }
! 1163:
! 1164: if (match)
! 1165: ospf6_route_show_table_match (vty, detail, &prefix, table);
! 1166: else if (type)
! 1167: ospf6_route_show_table_type (vty, detail, type, table);
! 1168: else
! 1169: ospf6_route_show_table (vty, detail, table);
! 1170:
! 1171: return CMD_SUCCESS;
! 1172: }
! 1173:
! 1174: static void
! 1175: ospf6_linkstate_show_header (struct vty *vty)
! 1176: {
! 1177: vty_out (vty, "%-7s %-15s %-15s %-8s %-14s %s%s",
! 1178: "Type", "Router-ID", "Net-ID", "Rtr-Bits", "Options", "Cost", VNL);
! 1179: }
! 1180:
! 1181: static void
! 1182: ospf6_linkstate_show (struct vty *vty, struct ospf6_route *route)
! 1183: {
! 1184: u_int32_t router, id;
! 1185: char routername[16], idname[16], rbits[16], options[16];
! 1186:
! 1187: router = ospf6_linkstate_prefix_adv_router (&route->prefix);
! 1188: inet_ntop (AF_INET, &router, routername, sizeof (routername));
! 1189: id = ospf6_linkstate_prefix_id (&route->prefix);
! 1190: inet_ntop (AF_INET, &id, idname, sizeof (idname));
! 1191:
! 1192: ospf6_capability_printbuf (route->path.router_bits, rbits, sizeof (rbits));
! 1193: ospf6_options_printbuf (route->path.options, options, sizeof (options));
! 1194:
! 1195: if (ntohl (id))
! 1196: vty_out (vty, "%-7s %-15s %-15s %-8s %-14s %lu%s",
! 1197: "Network", routername, idname, rbits, options,
! 1198: (unsigned long) route->path.cost, VNL);
! 1199: else
! 1200: vty_out (vty, "%-7s %-15s %-15s %-8s %-14s %lu%s",
! 1201: "Router", routername, idname, rbits, options,
! 1202: (unsigned long) route->path.cost, VNL);
! 1203: }
! 1204:
! 1205:
! 1206: static void
! 1207: ospf6_linkstate_show_table_exact (struct vty *vty,
! 1208: struct prefix *prefix,
! 1209: struct ospf6_route_table *table)
! 1210: {
! 1211: struct ospf6_route *route;
! 1212:
! 1213: route = ospf6_route_lookup (prefix, table);
! 1214: if (route == NULL)
! 1215: return;
! 1216:
! 1217: ospf6_route_lock (route);
! 1218: while (route && ospf6_route_is_prefix (prefix, route))
! 1219: {
! 1220: /* Specifying a prefix will always display details */
! 1221: ospf6_route_show_detail (vty, route);
! 1222: route = ospf6_route_next (route);
! 1223: }
! 1224: if (route)
! 1225: ospf6_route_unlock (route);
! 1226: }
! 1227:
! 1228: static void
! 1229: ospf6_linkstate_show_table (struct vty *vty, int detail,
! 1230: struct ospf6_route_table *table)
! 1231: {
! 1232: struct ospf6_route *route;
! 1233:
! 1234: if (! detail)
! 1235: ospf6_linkstate_show_header (vty);
! 1236:
! 1237: route = ospf6_route_head (table);
! 1238: while (route)
! 1239: {
! 1240: if (detail)
! 1241: ospf6_route_show_detail (vty, route);
! 1242: else
! 1243: ospf6_linkstate_show (vty, route);
! 1244: route = ospf6_route_next (route);
! 1245: }
! 1246: }
! 1247:
! 1248: int
! 1249: ospf6_linkstate_table_show (struct vty *vty, int argc, const char *argv[],
! 1250: struct ospf6_route_table *table)
! 1251: {
! 1252: int detail = 0;
! 1253: int is_id = 0;
! 1254: int is_router = 0;
! 1255: int i, ret;
! 1256: struct prefix router, id, prefix;
! 1257:
! 1258: memset (&router, 0, sizeof (struct prefix));
! 1259: memset (&id, 0, sizeof (struct prefix));
! 1260: memset (&prefix, 0, sizeof (struct prefix));
! 1261:
! 1262: for (i = 0; i < argc; i++)
! 1263: {
! 1264: if (! strcmp (argv[i], "detail"))
! 1265: {
! 1266: detail++;
! 1267: continue;
! 1268: }
! 1269:
! 1270: if (! is_router)
! 1271: {
! 1272: ret = str2prefix (argv[i], &router);
! 1273: if (ret == 1 && router.family == AF_INET)
! 1274: {
! 1275: is_router++;
! 1276: continue;
! 1277: }
! 1278: vty_out (vty, "Malformed argument: %s%s", argv[i], VNL);
! 1279: return CMD_SUCCESS;
! 1280: }
! 1281:
! 1282: if (! is_id)
! 1283: {
! 1284: ret = str2prefix (argv[i], &id);
! 1285: if (ret == 1 && id.family == AF_INET)
! 1286: {
! 1287: is_id++;
! 1288: continue;
! 1289: }
! 1290: vty_out (vty, "Malformed argument: %s%s", argv[i], VNL);
! 1291: return CMD_SUCCESS;
! 1292: }
! 1293:
! 1294: vty_out (vty, "Malformed argument: %s%s", argv[i], VNL);
! 1295: return CMD_SUCCESS;
! 1296: }
! 1297:
! 1298: if (is_router)
! 1299: ospf6_linkstate_prefix (router.u.prefix4.s_addr,
! 1300: id.u.prefix4.s_addr, &prefix);
! 1301:
! 1302: if (prefix.family)
! 1303: ospf6_linkstate_show_table_exact (vty, &prefix, table);
! 1304: else
! 1305: ospf6_linkstate_show_table (vty, detail, table);
! 1306:
! 1307: return CMD_SUCCESS;
! 1308: }
! 1309:
! 1310:
! 1311: void
! 1312: ospf6_brouter_show_header (struct vty *vty)
! 1313: {
! 1314: vty_out (vty, "%-15s %-8s %-14s %-10s %-15s%s",
! 1315: "Router-ID", "Rtr-Bits", "Options", "Path-Type", "Area", VNL);
! 1316: }
! 1317:
! 1318: void
! 1319: ospf6_brouter_show (struct vty *vty, struct ospf6_route *route)
! 1320: {
! 1321: u_int32_t adv_router;
! 1322: char adv[16], rbits[16], options[16], area[16];
! 1323:
! 1324: adv_router = ospf6_linkstate_prefix_adv_router (&route->prefix);
! 1325: inet_ntop (AF_INET, &adv_router, adv, sizeof (adv));
! 1326: ospf6_capability_printbuf (route->path.router_bits, rbits, sizeof (rbits));
! 1327: ospf6_options_printbuf (route->path.options, options, sizeof (options));
! 1328: inet_ntop (AF_INET, &route->path.area_id, area, sizeof (area));
! 1329:
! 1330: /* vty_out (vty, "%-15s %-8s %-14s %-10s %-15s%s",
! 1331: "Router-ID", "Rtr-Bits", "Options", "Path-Type", "Area", VNL); */
! 1332: vty_out (vty, "%-15s %-8s %-14s %-10s %-15s%s",
! 1333: adv, rbits, options, OSPF6_PATH_TYPE_NAME (route->path.type),
! 1334: area, VNL);
! 1335: }
! 1336:
! 1337: DEFUN (debug_ospf6_route,
! 1338: debug_ospf6_route_cmd,
! 1339: "debug ospf6 route (table|intra-area|inter-area|memory)",
! 1340: DEBUG_STR
! 1341: OSPF6_STR
! 1342: "Debug route table calculation\n"
! 1343: "Debug detail\n"
! 1344: "Debug intra-area route calculation\n"
! 1345: "Debug inter-area route calculation\n"
! 1346: "Debug route memory use\n"
! 1347: )
! 1348: {
! 1349: unsigned char level = 0;
! 1350:
! 1351: if (! strncmp (argv[0], "table", 5))
! 1352: level = OSPF6_DEBUG_ROUTE_TABLE;
! 1353: else if (! strncmp (argv[0], "intra", 5))
! 1354: level = OSPF6_DEBUG_ROUTE_INTRA;
! 1355: else if (! strncmp (argv[0], "inter", 5))
! 1356: level = OSPF6_DEBUG_ROUTE_INTER;
! 1357: else if (! strncmp (argv[0], "memor", 5))
! 1358: level = OSPF6_DEBUG_ROUTE_MEMORY;
! 1359: OSPF6_DEBUG_ROUTE_ON (level);
! 1360: return CMD_SUCCESS;
! 1361: }
! 1362:
! 1363: DEFUN (no_debug_ospf6_route,
! 1364: no_debug_ospf6_route_cmd,
! 1365: "no debug ospf6 route (table|intra-area|inter-area|memory)",
! 1366: NO_STR
! 1367: DEBUG_STR
! 1368: OSPF6_STR
! 1369: "Debug route table calculation\n"
! 1370: "Debug intra-area route calculation\n"
! 1371: "Debug route memory use\n")
! 1372: {
! 1373: unsigned char level = 0;
! 1374:
! 1375: if (! strncmp (argv[0], "table", 5))
! 1376: level = OSPF6_DEBUG_ROUTE_TABLE;
! 1377: else if (! strncmp (argv[0], "intra", 5))
! 1378: level = OSPF6_DEBUG_ROUTE_INTRA;
! 1379: else if (! strncmp (argv[0], "inter", 5))
! 1380: level = OSPF6_DEBUG_ROUTE_INTER;
! 1381: else if (! strncmp (argv[0], "memor", 5))
! 1382: level = OSPF6_DEBUG_ROUTE_MEMORY;
! 1383: OSPF6_DEBUG_ROUTE_OFF (level);
! 1384: return CMD_SUCCESS;
! 1385: }
! 1386:
! 1387: int
! 1388: config_write_ospf6_debug_route (struct vty *vty)
! 1389: {
! 1390: if (IS_OSPF6_DEBUG_ROUTE (TABLE))
! 1391: vty_out (vty, "debug ospf6 route table%s", VNL);
! 1392: if (IS_OSPF6_DEBUG_ROUTE (INTRA))
! 1393: vty_out (vty, "debug ospf6 route intra-area%s", VNL);
! 1394: if (IS_OSPF6_DEBUG_ROUTE (INTER))
! 1395: vty_out (vty, "debug ospf6 route inter-area%s", VNL);
! 1396: return 0;
! 1397: }
! 1398:
! 1399: void
! 1400: install_element_ospf6_debug_route (void)
! 1401: {
! 1402: install_element (ENABLE_NODE, &debug_ospf6_route_cmd);
! 1403: install_element (ENABLE_NODE, &no_debug_ospf6_route_cmd);
! 1404: install_element (CONFIG_NODE, &debug_ospf6_route_cmd);
! 1405: install_element (CONFIG_NODE, &no_debug_ospf6_route_cmd);
! 1406: }
! 1407:
! 1408:
! 1409:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>