ospf6_route.c 38 KB

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