ospf6_route.c 30 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138
  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. #include <zebra.h>
  22. #include "log.h"
  23. #include "memory.h"
  24. #include "prefix.h"
  25. #include "table.h"
  26. #include "vty.h"
  27. #include "command.h"
  28. #include "ospf6_proto.h"
  29. #include "ospf6_lsa.h"
  30. #include "ospf6_lsdb.h"
  31. #include "ospf6_route.h"
  32. #include "ospf6d.h"
  33. unsigned char conf_debug_ospf6_route = 0;
  34. void
  35. ospf6_linkstate_prefix (u_int32_t adv_router, u_int32_t id,
  36. struct prefix *prefix)
  37. {
  38. memset (prefix, 0, sizeof (struct prefix));
  39. prefix->family = AF_INET6;
  40. prefix->prefixlen = 64;
  41. memcpy (&prefix->u.prefix6.s6_addr[0], &adv_router, 4);
  42. memcpy (&prefix->u.prefix6.s6_addr[4], &id, 4);
  43. }
  44. void
  45. ospf6_linkstate_prefix2str (struct prefix *prefix, char *buf, int size)
  46. {
  47. u_int32_t adv_router, id;
  48. char adv_router_str[16];
  49. memcpy (&adv_router, &prefix->u.prefix6.s6_addr[0], 4);
  50. memcpy (&id, &prefix->u.prefix6.s6_addr[4], 4);
  51. inet_ntop (AF_INET, &adv_router, adv_router_str, sizeof (adv_router_str));
  52. snprintf (buf, size, "%s(%lu)", adv_router_str, (u_long) ntohl (id));
  53. }
  54. /* Global strings for logging */
  55. char *ospf6_dest_type_str[OSPF6_DEST_TYPE_MAX] =
  56. { "Unknown", "Router", "Network", "Discard", "Linkstate", };
  57. char *ospf6_dest_type_substr[OSPF6_DEST_TYPE_MAX] =
  58. { "?", "R", "N", "D", "L", };
  59. char *ospf6_path_type_str[OSPF6_PATH_TYPE_MAX] =
  60. { "Unknown", "Intra-Area", "Inter-Area", "External-1", "External-2", };
  61. char *ospf6_path_type_substr[OSPF6_PATH_TYPE_MAX] =
  62. { "??", "Ia", "Ie", "E1", "E2", };
  63. struct ospf6_route *
  64. ospf6_route_create ()
  65. {
  66. struct ospf6_route *route;
  67. route = XCALLOC (MTYPE_OSPF6_ROUTE, sizeof (struct ospf6_route));
  68. return route;
  69. }
  70. void
  71. ospf6_route_delete (struct ospf6_route *route)
  72. {
  73. XFREE (MTYPE_OSPF6_ROUTE, route);
  74. }
  75. struct ospf6_route *
  76. ospf6_route_copy (struct ospf6_route *route)
  77. {
  78. struct ospf6_route *new;
  79. new = ospf6_route_create ();
  80. memcpy (new, route, sizeof (struct ospf6_route));
  81. new->rnode = NULL;
  82. new->prev = NULL;
  83. new->next = NULL;
  84. new->lock = 0;
  85. return new;
  86. }
  87. void
  88. ospf6_route_lock (struct ospf6_route *route)
  89. {
  90. route->lock++;
  91. }
  92. void
  93. ospf6_route_unlock (struct ospf6_route *route)
  94. {
  95. assert (route->lock > 0);
  96. route->lock--;
  97. if (route->lock == 0)
  98. ospf6_route_delete (route);
  99. }
  100. /* Route compare function. If ra is more preferred, it returns
  101. less than 0. If rb is more preferred returns greater than 0.
  102. Otherwise (neither one is preferred), returns 0 */
  103. static int
  104. ospf6_route_cmp (struct ospf6_route *ra, struct ospf6_route *rb)
  105. {
  106. assert (ospf6_route_is_same (ra, rb));
  107. assert (OSPF6_PATH_TYPE_NONE < ra->path.type &&
  108. ra->path.type < OSPF6_PATH_TYPE_MAX);
  109. assert (OSPF6_PATH_TYPE_NONE < rb->path.type &&
  110. rb->path.type < OSPF6_PATH_TYPE_MAX);
  111. if (ra->type != rb->type)
  112. return (ra->type - rb->type);
  113. if (ra->path.area_id != rb->path.area_id)
  114. return (ntohl (ra->path.area_id) - ntohl (rb->path.area_id));
  115. if (ra->path.type != rb->path.type)
  116. return (ra->path.type - rb->path.type);
  117. if (ra->path.type == OSPF6_PATH_TYPE_EXTERNAL2)
  118. {
  119. if (ra->path.cost_e2 != rb->path.cost_e2)
  120. return (ra->path.cost_e2 - rb->path.cost_e2);
  121. }
  122. else
  123. {
  124. if (ra->path.cost != rb->path.cost)
  125. return (ra->path.cost - rb->path.cost);
  126. }
  127. return 0;
  128. }
  129. struct ospf6_route *
  130. ospf6_route_lookup (struct prefix *prefix,
  131. struct ospf6_route_table *table)
  132. {
  133. struct route_node *node;
  134. struct ospf6_route *route;
  135. node = route_node_lookup (table->table, prefix);
  136. if (node == NULL)
  137. return NULL;
  138. route = (struct ospf6_route *) node->info;
  139. return route;
  140. }
  141. struct ospf6_route *
  142. ospf6_route_lookup_identical (struct ospf6_route *route,
  143. struct ospf6_route_table *table)
  144. {
  145. struct ospf6_route *target;
  146. for (target = ospf6_route_lookup (&route->prefix, table);
  147. target; target = target->next)
  148. {
  149. if (ospf6_route_is_identical (target, route))
  150. return target;
  151. }
  152. return NULL;
  153. }
  154. struct ospf6_route *
  155. ospf6_route_lookup_bestmatch (struct prefix *prefix,
  156. struct ospf6_route_table *table)
  157. {
  158. struct route_node *node;
  159. struct ospf6_route *route;
  160. node = route_node_match (table->table, prefix);
  161. if (node == NULL)
  162. return NULL;
  163. route_unlock_node (node);
  164. route = (struct ospf6_route *) node->info;
  165. return route;
  166. }
  167. #ifndef NDEBUG
  168. static void
  169. _route_count_assert (struct ospf6_route_table *table)
  170. {
  171. struct ospf6_route *debug;
  172. int num = 0;
  173. for (debug = ospf6_route_head (table); debug;
  174. debug = ospf6_route_next (debug))
  175. num++;
  176. assert (num == table->count);
  177. }
  178. #define ospf6_route_count_assert(t) (_route_count_assert (t))
  179. #else
  180. #define ospf6_route_count_assert(t) ((void) 0)
  181. #endif /*NDEBUG*/
  182. struct ospf6_route *
  183. ospf6_route_add (struct ospf6_route *route,
  184. struct ospf6_route_table *table)
  185. {
  186. struct route_node *node, *nextnode, *prevnode;
  187. struct ospf6_route *current = NULL;
  188. struct ospf6_route *prev = NULL, *old = NULL, *next = NULL;
  189. char buf[64];
  190. struct timeval now;
  191. assert (route->rnode == NULL);
  192. assert (route->lock == 0);
  193. assert (route->next == NULL);
  194. assert (route->prev == NULL);
  195. if (route->type == OSPF6_DEST_TYPE_LINKSTATE)
  196. ospf6_linkstate_prefix2str (&route->prefix, buf, sizeof (buf));
  197. else
  198. prefix2str (&route->prefix, buf, sizeof (buf));
  199. if (IS_OSPF6_DEBUG_ROUTE (TABLE))
  200. zlog_info ("route add %s", buf);
  201. gettimeofday (&now, NULL);
  202. node = route_node_get (table->table, &route->prefix);
  203. route->rnode = node;
  204. /* find place to insert */
  205. for (current = node->info; current; current = current->next)
  206. {
  207. if (! ospf6_route_is_same (current, route))
  208. next = current;
  209. else if (current->type != route->type)
  210. prev = current;
  211. else if (ospf6_route_is_same_origin (current, route))
  212. old = current;
  213. else if (ospf6_route_cmp (current, route) > 0)
  214. next = current;
  215. else
  216. prev = current;
  217. if (old || next)
  218. break;
  219. }
  220. if (old)
  221. {
  222. /* if route does not actually change, return unchanged */
  223. if (ospf6_route_is_identical (old, route))
  224. {
  225. if (IS_OSPF6_DEBUG_ROUTE (TABLE))
  226. zlog_info (" identical route found, ignore");
  227. ospf6_route_delete (route);
  228. SET_FLAG (old->flag, OSPF6_ROUTE_ADD);
  229. ospf6_route_count_assert (table);
  230. return old;
  231. }
  232. if (IS_OSPF6_DEBUG_ROUTE (TABLE))
  233. zlog_info (" old route found, replace");
  234. /* replace old one if exists */
  235. if (node->info == old)
  236. {
  237. node->info = route;
  238. SET_FLAG (route->flag, OSPF6_ROUTE_BEST);
  239. }
  240. if (old->prev)
  241. old->prev->next = route;
  242. route->prev = old->prev;
  243. if (old->next)
  244. old->next->prev = route;
  245. route->next = old->next;
  246. route->installed = old->installed;
  247. route->changed = now;
  248. ospf6_route_unlock (old); /* will be deleted later */
  249. ospf6_route_lock (route);
  250. SET_FLAG (route->flag, OSPF6_ROUTE_CHANGE);
  251. if (table->hook_add)
  252. (*table->hook_add) (route);
  253. ospf6_route_count_assert (table);
  254. return route;
  255. }
  256. /* insert if previous or next node found */
  257. if (prev || next)
  258. {
  259. if (IS_OSPF6_DEBUG_ROUTE (TABLE))
  260. zlog_info (" another path found, insert");
  261. if (prev == NULL)
  262. prev = next->prev;
  263. if (next == NULL)
  264. next = prev->next;
  265. if (prev)
  266. prev->next = route;
  267. route->prev = prev;
  268. if (next)
  269. next->prev = route;
  270. route->next = next;
  271. if (node->info == next)
  272. {
  273. assert (next->rnode == node);
  274. node->info = route;
  275. UNSET_FLAG (next->flag, OSPF6_ROUTE_BEST);
  276. SET_FLAG (route->flag, OSPF6_ROUTE_BEST);
  277. }
  278. route->installed = now;
  279. route->changed = now;
  280. ospf6_route_lock (route);
  281. table->count++;
  282. SET_FLAG (route->flag, OSPF6_ROUTE_ADD);
  283. if (table->hook_add)
  284. (*table->hook_add) (route);
  285. ospf6_route_count_assert (table);
  286. return route;
  287. }
  288. /* Else, this is the brand new route regarding to the prefix */
  289. if (IS_OSPF6_DEBUG_ROUTE (TABLE))
  290. zlog_info (" brand new route, add");
  291. assert (node->info == NULL);
  292. node->info = route;
  293. SET_FLAG (route->flag, OSPF6_ROUTE_BEST);
  294. ospf6_route_lock (route);
  295. route->installed = now;
  296. route->changed = now;
  297. /* lookup real existing next route */
  298. nextnode = node;
  299. route_lock_node (nextnode);
  300. do {
  301. nextnode = route_next (nextnode);
  302. } while (nextnode && nextnode->info == NULL);
  303. /* set next link */
  304. if (nextnode == NULL)
  305. route->next = NULL;
  306. else
  307. {
  308. route_unlock_node (nextnode);
  309. next = nextnode->info;
  310. route->next = next;
  311. next->prev = route;
  312. }
  313. /* lookup real existing prev route */
  314. prevnode = node;
  315. route_lock_node (prevnode);
  316. do {
  317. prevnode = route_prev (prevnode);
  318. } while (prevnode && prevnode->info == NULL);
  319. /* set prev link */
  320. if (prevnode == NULL)
  321. route->prev = NULL;
  322. else
  323. {
  324. route_unlock_node (prevnode);
  325. prev = prevnode->info;
  326. while (prev->next && ospf6_route_is_same (prev, prev->next))
  327. prev = prev->next;
  328. route->prev = prev;
  329. prev->next = route;
  330. }
  331. table->count++;
  332. SET_FLAG (route->flag, OSPF6_ROUTE_ADD);
  333. if (table->hook_add)
  334. (*table->hook_add) (route);
  335. ospf6_route_count_assert (table);
  336. return route;
  337. }
  338. void
  339. ospf6_route_remove (struct ospf6_route *route,
  340. struct ospf6_route_table *table)
  341. {
  342. struct route_node *node;
  343. struct ospf6_route *current;
  344. char buf[64];
  345. if (route->type == OSPF6_DEST_TYPE_LINKSTATE)
  346. ospf6_linkstate_prefix2str (&route->prefix, buf, sizeof (buf));
  347. else
  348. prefix2str (&route->prefix, buf, sizeof (buf));
  349. if (IS_OSPF6_DEBUG_ROUTE (TABLE))
  350. zlog_info ("route remove: %s", buf);
  351. node = route_node_lookup (table->table, &route->prefix);
  352. assert (node);
  353. /* find the route to remove, making sure that the route pointer
  354. is from the route table. */
  355. current = node->info;
  356. while (current && ospf6_route_is_same (current, route))
  357. {
  358. if (current == route)
  359. break;
  360. current = current->next;
  361. }
  362. assert (current == route);
  363. /* adjust doubly linked list */
  364. if (route->prev)
  365. route->prev->next = route->next;
  366. if (route->next)
  367. route->next->prev = route->prev;
  368. if (node->info == route)
  369. {
  370. if (route->next && ospf6_route_is_same (route->next, route))
  371. {
  372. node->info = route->next;
  373. SET_FLAG (route->next->flag, OSPF6_ROUTE_BEST);
  374. }
  375. else
  376. node->info = NULL; /* should unlock route_node here ? */
  377. }
  378. if (table->hook_remove)
  379. (*table->hook_remove) (route);
  380. ospf6_route_unlock (route);
  381. table->count--;
  382. ospf6_route_count_assert (table);
  383. }
  384. struct ospf6_route *
  385. ospf6_route_head (struct ospf6_route_table *table)
  386. {
  387. struct route_node *node;
  388. struct ospf6_route *route;
  389. node = route_top (table->table);
  390. if (node == NULL)
  391. return NULL;
  392. /* skip to the real existing entry */
  393. while (node && node->info == NULL)
  394. node = route_next (node);
  395. if (node == NULL)
  396. return NULL;
  397. route_unlock_node (node);
  398. assert (node->info);
  399. route = (struct ospf6_route *) node->info;
  400. assert (route->prev == NULL);
  401. ospf6_route_lock (route);
  402. return route;
  403. }
  404. struct ospf6_route *
  405. ospf6_route_next (struct ospf6_route *route)
  406. {
  407. struct ospf6_route *next = route->next;
  408. ospf6_route_unlock (route);
  409. if (next)
  410. ospf6_route_lock (next);
  411. return next;
  412. }
  413. struct ospf6_route *
  414. ospf6_route_best_next (struct ospf6_route *route)
  415. {
  416. struct route_node *rnode;
  417. struct ospf6_route *next;
  418. rnode = route->rnode;
  419. route_lock_node (rnode);
  420. rnode = route_next (rnode);
  421. while (rnode && rnode->info == NULL)
  422. rnode = route_next (rnode);
  423. if (rnode == NULL)
  424. return NULL;
  425. route_unlock_node (rnode);
  426. assert (rnode->info);
  427. next = (struct ospf6_route *) rnode->info;
  428. ospf6_route_unlock (route);
  429. ospf6_route_lock (next);
  430. return next;
  431. }
  432. /* Macro version of check_bit (). */
  433. #define CHECK_BIT(X,P) ((((u_char *)(X))[(P) / 8]) >> (7 - ((P) % 8)) & 1)
  434. struct ospf6_route *
  435. ospf6_route_match_head (struct prefix *prefix,
  436. struct ospf6_route_table *table)
  437. {
  438. struct route_node *node;
  439. struct ospf6_route *route;
  440. /* Walk down tree. */
  441. node = table->table->top;
  442. while (node && node->p.prefixlen < prefix->prefixlen &&
  443. prefix_match (&node->p, prefix))
  444. node = node->link[CHECK_BIT(&prefix->u.prefix, node->p.prefixlen)];
  445. if (node)
  446. route_lock_node (node);
  447. while (node && node->info == NULL)
  448. node = route_next (node);
  449. if (node == NULL)
  450. return NULL;
  451. route_unlock_node (node);
  452. if (! prefix_match (prefix, &node->p))
  453. return NULL;
  454. route = node->info;
  455. ospf6_route_lock (route);
  456. return route;
  457. }
  458. struct ospf6_route *
  459. ospf6_route_match_next (struct prefix *prefix,
  460. struct ospf6_route *route)
  461. {
  462. struct ospf6_route *next;
  463. next = ospf6_route_next (route);
  464. if (next && ! prefix_match (prefix, &next->prefix))
  465. {
  466. ospf6_route_unlock (next);
  467. next = NULL;
  468. }
  469. return next;
  470. }
  471. void
  472. ospf6_route_remove_all (struct ospf6_route_table *table)
  473. {
  474. struct ospf6_route *route;
  475. for (route = ospf6_route_head (table); route;
  476. route = ospf6_route_next (route))
  477. ospf6_route_remove (route, table);
  478. }
  479. struct ospf6_route_table *
  480. ospf6_route_table_create ()
  481. {
  482. struct ospf6_route_table *new;
  483. new = XCALLOC (MTYPE_OSPF6_ROUTE, sizeof (struct ospf6_route_table));
  484. new->table = route_table_init ();
  485. return new;
  486. }
  487. void
  488. ospf6_route_table_delete (struct ospf6_route_table *table)
  489. {
  490. ospf6_route_remove_all (table);
  491. route_table_finish (table->table);
  492. XFREE (MTYPE_OSPF6_ROUTE, table);
  493. }
  494. /* VTY commands */
  495. void
  496. ospf6_route_show (struct vty *vty, struct ospf6_route *route)
  497. {
  498. int i;
  499. char destination[64], nexthop[64];
  500. char duration[16], ifname[IFNAMSIZ];
  501. struct timeval now, res;
  502. gettimeofday (&now, (struct timezone *) NULL);
  503. timersub (&now, &route->changed, &res);
  504. timerstring (&res, duration, sizeof (duration));
  505. /* destination */
  506. if (route->type == OSPF6_DEST_TYPE_LINKSTATE)
  507. ospf6_linkstate_prefix2str (&route->prefix, destination,
  508. sizeof (destination));
  509. else if (route->type == OSPF6_DEST_TYPE_ROUTER)
  510. inet_ntop (route->prefix.family, &route->prefix.u.prefix,
  511. destination, sizeof (destination));
  512. else
  513. prefix2str (&route->prefix, destination, sizeof (destination));
  514. /* nexthop */
  515. inet_ntop (AF_INET6, &route->nexthop[0].address, nexthop,
  516. sizeof (nexthop));
  517. if (! if_indextoname (route->nexthop[0].ifindex, ifname))
  518. snprintf (ifname, sizeof (ifname), "%d", route->nexthop[0].ifindex);
  519. vty_out (vty, "%c%1s %2s %-30s %-25s %6s %s%s",
  520. (ospf6_route_is_best (route) ? '*' : ' '),
  521. OSPF6_DEST_TYPE_SUBSTR (route->type),
  522. OSPF6_PATH_TYPE_SUBSTR (route->path.type),
  523. destination, nexthop, ifname, duration, VNL);
  524. for (i = 1; ospf6_nexthop_is_set (&route->nexthop[i]) &&
  525. i < OSPF6_MULTI_PATH_LIMIT; i++)
  526. {
  527. /* nexthop */
  528. inet_ntop (AF_INET6, &route->nexthop[i].address, nexthop,
  529. sizeof (nexthop));
  530. if (! if_indextoname (route->nexthop[i].ifindex, ifname))
  531. snprintf (ifname, sizeof (ifname), "%d", route->nexthop[i].ifindex);
  532. vty_out (vty, "%c%1s %2s %-30s %-25s %6s %s%s",
  533. ' ', "", "", "", nexthop, ifname, "", VNL);
  534. }
  535. }
  536. void
  537. ospf6_route_show_detail (struct vty *vty, struct ospf6_route *route)
  538. {
  539. char destination[64], nexthop[64], ifname[IFNAMSIZ];
  540. char area_id[16], id[16], adv_router[16], capa[16], options[16];
  541. struct timeval now, res;
  542. char duration[16];
  543. int i;
  544. gettimeofday (&now, (struct timezone *) NULL);
  545. /* destination */
  546. if (route->type == OSPF6_DEST_TYPE_LINKSTATE)
  547. ospf6_linkstate_prefix2str (&route->prefix, destination,
  548. sizeof (destination));
  549. else if (route->type == OSPF6_DEST_TYPE_ROUTER)
  550. inet_ntop (route->prefix.family, &route->prefix.u.prefix,
  551. destination, sizeof (destination));
  552. else
  553. prefix2str (&route->prefix, destination, sizeof (destination));
  554. vty_out (vty, "Destination: %s%s", destination, VNL);
  555. /* destination type */
  556. vty_out (vty, "Destination type: %s%s",
  557. OSPF6_DEST_TYPE_NAME (route->type),
  558. VNL);
  559. /* Time */
  560. timersub (&now, &route->installed, &res);
  561. timerstring (&res, duration, sizeof (duration));
  562. vty_out (vty, "Installed Time: %s ago%s", duration, VNL);
  563. timersub (&now, &route->changed, &res);
  564. timerstring (&res, duration, sizeof (duration));
  565. vty_out (vty, " Changed Time: %s ago%s", duration, VNL);
  566. /* Debugging info */
  567. vty_out (vty, "Lock: %d Flags: %s%s%s%s%s", route->lock,
  568. (CHECK_FLAG (route->flag, OSPF6_ROUTE_BEST) ? "B" : "-"),
  569. (CHECK_FLAG (route->flag, OSPF6_ROUTE_ADD) ? "A" : "-"),
  570. (CHECK_FLAG (route->flag, OSPF6_ROUTE_REMOVE) ? "R" : "-"),
  571. (CHECK_FLAG (route->flag, OSPF6_ROUTE_CHANGE) ? "C" : "-"),
  572. VNL);
  573. vty_out (vty, "Memory: prev: %p this: %p next: %p%s",
  574. route->prev, route, route->next, VNL);
  575. /* Path section */
  576. /* Area-ID */
  577. inet_ntop (AF_INET, &route->path.area_id, area_id, sizeof (area_id));
  578. vty_out (vty, "Associated Area: %s%s", area_id, VNL);
  579. /* Path type */
  580. vty_out (vty, "Path Type: %s%s",
  581. OSPF6_PATH_TYPE_NAME (route->path.type), VNL);
  582. /* LS Origin */
  583. inet_ntop (AF_INET, &route->path.origin.id, id, sizeof (id));
  584. inet_ntop (AF_INET, &route->path.origin.adv_router, adv_router,
  585. sizeof (adv_router));
  586. vty_out (vty, "LS Origin: %s Id: %s Adv: %s%s",
  587. OSPF6_LSTYPE_NAME (route->path.origin.type),
  588. id, adv_router, VNL);
  589. /* Options */
  590. ospf6_options_printbuf (route->path.options, options, sizeof (options));
  591. vty_out (vty, "Options: %s%s", options, VNL);
  592. /* Router Bits */
  593. ospf6_capability_printbuf (route->path.router_bits, capa, sizeof (capa));
  594. vty_out (vty, "Router Bits: %s%s", capa, VNL);
  595. /* Prefix Options */
  596. vty_out (vty, "Prefix Options: xxx%s", VNL);
  597. /* Metrics */
  598. vty_out (vty, "Metric Type: %d%s", route->path.metric_type,
  599. VNL);
  600. vty_out (vty, "Metric: %d (%d)%s",
  601. route->path.cost, route->path.cost_e2, VNL);
  602. /* Nexthops */
  603. vty_out (vty, "Nexthop:%s", VNL);
  604. for (i = 0; ospf6_nexthop_is_set (&route->nexthop[i]) &&
  605. i < OSPF6_MULTI_PATH_LIMIT; i++)
  606. {
  607. /* nexthop */
  608. inet_ntop (AF_INET6, &route->nexthop[i].address, nexthop,
  609. sizeof (nexthop));
  610. if (! if_indextoname (route->nexthop[i].ifindex, ifname))
  611. snprintf (ifname, sizeof (ifname), "%d", route->nexthop[i].ifindex);
  612. vty_out (vty, " %s %s%s", nexthop, ifname, VNL);
  613. }
  614. vty_out (vty, "%s", VNL);
  615. }
  616. void
  617. ospf6_route_show_table_summary (struct vty *vty,
  618. struct ospf6_route_table *table)
  619. {
  620. struct ospf6_route *route, *prev = NULL;
  621. int i, pathtype[OSPF6_PATH_TYPE_MAX];
  622. int number = 0;
  623. int nhinval = 0, ecmp = 0;
  624. int multipath = 0, destination = 0;
  625. int desttype = 0, desttype_mismatch = 0;
  626. for (i = 0; i < OSPF6_PATH_TYPE_MAX; i++)
  627. pathtype[i] = 0;
  628. for (route = ospf6_route_head (table); route;
  629. route = ospf6_route_next (route))
  630. {
  631. if (desttype == 0)
  632. desttype = route->type;
  633. else if (desttype != route->type)
  634. desttype_mismatch++;
  635. if (prev == NULL || ! ospf6_route_is_same (prev, route))
  636. destination++;
  637. else
  638. multipath++;
  639. if (! ospf6_nexthop_is_set (&route->nexthop[0]))
  640. nhinval++;
  641. else if (ospf6_nexthop_is_set (&route->nexthop[1]))
  642. ecmp++;
  643. if (prev == NULL || ! ospf6_route_is_same (prev, route))
  644. pathtype[route->path.type]++;
  645. number++;
  646. prev = route;
  647. }
  648. assert (number == table->count);
  649. vty_out (vty, "Number of Destination: %d (%d routes)%s",
  650. destination, number, VNL);
  651. if (multipath)
  652. vty_out (vty, " Number of Multi-path: %d%s", multipath, VNL);
  653. if (desttype_mismatch)
  654. vty_out (vty, " Number of Different Dest-type: %d%s",
  655. desttype_mismatch, VNL);
  656. if (ecmp)
  657. vty_out (vty, " Number of Equal Cost Multi Path: %d%s",
  658. ecmp, VNL);
  659. if (ecmp)
  660. vty_out (vty, " Number of Invalid Nexthop: %d%s",
  661. nhinval, VNL);
  662. for (i = 0; i < OSPF6_PATH_TYPE_MAX; i++)
  663. {
  664. if (pathtype[i])
  665. vty_out (vty, " Number of %s routes: %d%s",
  666. OSPF6_PATH_TYPE_NAME (i), pathtype[i], VNL);
  667. }
  668. }
  669. int
  670. ospf6_route_table_show (struct vty *vty, int argc, char **argv,
  671. struct ospf6_route_table *table)
  672. {
  673. unsigned char flag = 0;
  674. #define MATCH 0x01
  675. #define DETAIL 0x02
  676. #define PREFIX 0x04
  677. #define SUMMARY 0x08
  678. int i, ret;
  679. struct prefix prefix, *p;
  680. struct ospf6_route *route;
  681. memset (&prefix, 0, sizeof (struct prefix));
  682. for (i = 0; i < argc; i++)
  683. {
  684. /* set "detail" */
  685. if (! strcmp (argv[i], "summary"))
  686. {
  687. SET_FLAG (flag, SUMMARY);
  688. continue;
  689. }
  690. /* set "detail" */
  691. if (! strcmp (argv[i], "detail"))
  692. {
  693. SET_FLAG (flag, DETAIL);
  694. continue;
  695. }
  696. /* set "match" */
  697. if (! strcmp (argv[i], "match"))
  698. {
  699. SET_FLAG (flag, MATCH);
  700. continue;
  701. }
  702. if (prefix.family)
  703. {
  704. vty_out (vty, "Invalid argument: %s%s", argv[i], VNL);
  705. return CMD_SUCCESS;
  706. }
  707. ret = str2prefix (argv[i], &prefix);
  708. if (ret != 1 || prefix.family != AF_INET6)
  709. {
  710. vty_out (vty, "Malformed argument: %s%s", argv[i], VNL);
  711. return CMD_SUCCESS;
  712. }
  713. if (strchr (argv[i], '/'))
  714. SET_FLAG (flag, PREFIX);
  715. }
  716. /* Give summary of this route table */
  717. if (CHECK_FLAG (flag, SUMMARY))
  718. {
  719. ospf6_route_show_table_summary (vty, table);
  720. return CMD_SUCCESS;
  721. }
  722. /* Give exact prefix-match route */
  723. if (prefix.family && ! CHECK_FLAG (flag, MATCH))
  724. {
  725. /* If exact address, give best matching route */
  726. if (! CHECK_FLAG (flag, PREFIX))
  727. route = ospf6_route_lookup_bestmatch (&prefix, table);
  728. else
  729. route = ospf6_route_lookup (&prefix, table);
  730. if (route)
  731. {
  732. ospf6_route_lock (route);
  733. p = &route->prefix;
  734. }
  735. while (route && ospf6_route_is_prefix (p, route))
  736. {
  737. /* Seaching an entry will always display details */
  738. if (route)
  739. ospf6_route_show_detail (vty, route);
  740. route = ospf6_route_next (route);
  741. }
  742. return CMD_SUCCESS;
  743. }
  744. if (prefix.family == 0)
  745. route = ospf6_route_head (table);
  746. else
  747. route = ospf6_route_match_head (&prefix, table);
  748. while (route)
  749. {
  750. if (CHECK_FLAG (flag, DETAIL))
  751. ospf6_route_show_detail (vty, route);
  752. else
  753. ospf6_route_show (vty, route);
  754. if (prefix.family == 0)
  755. route = ospf6_route_next (route);
  756. else
  757. route = ospf6_route_match_next (&prefix, route);
  758. }
  759. return CMD_SUCCESS;
  760. }
  761. int
  762. ospf6_lsentry_table_show (struct vty *vty, int argc, char **argv,
  763. struct ospf6_route_table *table)
  764. {
  765. unsigned char flag = 0;
  766. #define MATCH 0x01
  767. #define DETAIL 0x02
  768. int i, ret;
  769. struct prefix adv_router, id, prefix;
  770. struct ospf6_route *route;
  771. memset (&adv_router, 0, sizeof (struct prefix));
  772. memset (&id, 0, sizeof (struct prefix));
  773. for (i = 0; i < argc; i++)
  774. {
  775. /* set "detail" */
  776. if (! strcmp (argv[i], "detail"))
  777. {
  778. SET_FLAG (flag, DETAIL);
  779. continue;
  780. }
  781. /* set "match" */
  782. if (! strcmp (argv[i], "match"))
  783. {
  784. SET_FLAG (flag, MATCH);
  785. continue;
  786. }
  787. if (adv_router.family && id.family)
  788. {
  789. vty_out (vty, "Invalid argument: %s%s", argv[i], VNL);
  790. return CMD_SUCCESS;
  791. }
  792. if (adv_router.family == 0)
  793. {
  794. ret = str2prefix (argv[i], &adv_router);
  795. if (ret != 1)
  796. {
  797. if (! strcmp (argv[i], "*"))
  798. {
  799. adv_router.family = AF_INET;
  800. adv_router.prefixlen = 0;
  801. ret = 1;
  802. }
  803. }
  804. if (ret != 1)
  805. {
  806. vty_out (vty, "Invalid Router-ID: %s%s", argv[i], VNL);
  807. return CMD_SUCCESS;
  808. }
  809. }
  810. else if (id.family == 0)
  811. {
  812. unsigned long val;
  813. char *endptr;
  814. ret = str2prefix (argv[i], &id);
  815. if (ret != 1)
  816. {
  817. val = strtoul (argv[i], &endptr, 0);
  818. if (val != ULONG_MAX && *endptr == '\0')
  819. {
  820. id.u.prefix4.s_addr = val;
  821. ret = 1;
  822. }
  823. }
  824. if (ret != 1)
  825. {
  826. vty_out (vty, "Invalid Link state ID: %s%s", argv[i],
  827. VNL);
  828. return CMD_WARNING;
  829. }
  830. }
  831. }
  832. /* Encode to linkstate prefix */
  833. if (adv_router.family)
  834. {
  835. if (adv_router.prefixlen == 0 &&
  836. id.family && id.prefixlen != IPV4_MAX_BITLEN)
  837. {
  838. vty_out (vty, "Specifying Link State ID by prefix is not allowed%s"
  839. "when specifying Router-ID as wildcard%s",
  840. VNL, VNL);
  841. return CMD_SUCCESS;
  842. }
  843. else if (adv_router.prefixlen != 0 &&
  844. adv_router.prefixlen != IPV4_MAX_BITLEN && id.family)
  845. {
  846. vty_out (vty, "Specifying Link State ID is not allowed%s"
  847. "when specifying Router-ID by prefix%s",
  848. VNL, VNL);
  849. return CMD_SUCCESS;
  850. }
  851. if (adv_router.prefixlen == 0)
  852. ospf6_linkstate_prefix (0, id.u.prefix4.s_addr, &prefix);
  853. else if (adv_router.prefixlen != IPV4_MAX_BITLEN)
  854. {
  855. ospf6_linkstate_prefix (adv_router.u.prefix4.s_addr, 0, &prefix);
  856. prefix.prefixlen = adv_router.prefixlen;
  857. SET_FLAG (flag, MATCH);
  858. }
  859. else
  860. {
  861. ospf6_linkstate_prefix (adv_router.u.prefix4.s_addr,
  862. id.u.prefix4.s_addr, &prefix);
  863. prefix.prefixlen = adv_router.prefixlen + id.prefixlen;
  864. if (prefix.prefixlen != 64)
  865. SET_FLAG (flag, MATCH);
  866. }
  867. }
  868. /* give exact match entry */
  869. if (adv_router.family && adv_router.prefixlen == IPV4_MAX_BITLEN &&
  870. id.family && id.prefixlen == IPV4_MAX_BITLEN)
  871. {
  872. route = ospf6_route_lookup (&prefix, table);
  873. if (route)
  874. ospf6_route_show_detail (vty, route);
  875. return CMD_SUCCESS;
  876. }
  877. if (CHECK_FLAG (flag, MATCH))
  878. route = ospf6_route_match_head (&prefix, table);
  879. else
  880. route = ospf6_route_head (table);
  881. while (route)
  882. {
  883. if (! adv_router.family ||
  884. (CHECK_FLAG (flag, MATCH) &&
  885. prefix_match (&prefix, &route->prefix)) ||
  886. (adv_router.prefixlen == 0 && id.family &&
  887. ospf6_linkstate_prefix_id (&prefix) ==
  888. ospf6_linkstate_prefix_id (&route->prefix)))
  889. {
  890. if (CHECK_FLAG (flag, DETAIL))
  891. ospf6_route_show_detail (vty, route);
  892. else
  893. ospf6_route_show (vty, route);
  894. }
  895. if (CHECK_FLAG (flag, MATCH))
  896. route = ospf6_route_match_next (&prefix, route);
  897. else
  898. route = ospf6_route_next (route);
  899. }
  900. return CMD_SUCCESS;
  901. }
  902. DEFUN (debug_ospf6_route,
  903. debug_ospf6_route_cmd,
  904. "debug ospf6 route (table|intra-area|inter-area)",
  905. DEBUG_STR
  906. OSPF6_STR
  907. "Debug route table calculation\n"
  908. "Debug detail\n"
  909. "Debug intra-area route calculation\n"
  910. "Debug inter-area route calculation\n"
  911. )
  912. {
  913. unsigned char level = 0;
  914. if (! strncmp (argv[0], "table", 5))
  915. level = OSPF6_DEBUG_ROUTE_TABLE;
  916. else if (! strncmp (argv[0], "intra", 5))
  917. level = OSPF6_DEBUG_ROUTE_INTRA;
  918. else if (! strncmp (argv[0], "inter", 5))
  919. level = OSPF6_DEBUG_ROUTE_INTER;
  920. OSPF6_DEBUG_ROUTE_ON (level);
  921. return CMD_SUCCESS;
  922. }
  923. DEFUN (no_debug_ospf6_route,
  924. no_debug_ospf6_route_cmd,
  925. "no debug ospf6 route (table|intra-area|inter-area)",
  926. NO_STR
  927. DEBUG_STR
  928. OSPF6_STR
  929. "Debug route table calculation\n"
  930. "Debug intra-area route calculation\n")
  931. {
  932. unsigned char level = 0;
  933. if (! strncmp (argv[0], "table", 5))
  934. level = OSPF6_DEBUG_ROUTE_TABLE;
  935. else if (! strncmp (argv[0], "intra", 5))
  936. level = OSPF6_DEBUG_ROUTE_INTRA;
  937. else if (! strncmp (argv[0], "inter", 5))
  938. level = OSPF6_DEBUG_ROUTE_INTER;
  939. OSPF6_DEBUG_ROUTE_OFF (level);
  940. return CMD_SUCCESS;
  941. }
  942. int
  943. config_write_ospf6_debug_route (struct vty *vty)
  944. {
  945. if (IS_OSPF6_DEBUG_ROUTE (TABLE))
  946. vty_out (vty, "debug ospf6 route table%s", VNL);
  947. if (IS_OSPF6_DEBUG_ROUTE (INTRA))
  948. vty_out (vty, "debug ospf6 route intra-area%s", VNL);
  949. if (IS_OSPF6_DEBUG_ROUTE (INTER))
  950. vty_out (vty, "debug ospf6 route inter-area%s", VNL);
  951. return 0;
  952. }
  953. void
  954. install_element_ospf6_debug_route ()
  955. {
  956. install_element (ENABLE_NODE, &debug_ospf6_route_cmd);
  957. install_element (ENABLE_NODE, &no_debug_ospf6_route_cmd);
  958. install_element (CONFIG_NODE, &debug_ospf6_route_cmd);
  959. install_element (CONFIG_NODE, &no_debug_ospf6_route_cmd);
  960. }