ospf6_route.c 32 KB

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