ospf6_route.c 30 KB

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