ospf6_abr.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655
  1. /*
  2. * Copyright (C) 2001 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 "ospf6d.h"
  22. #include "ospf6_dump.h"
  23. #include "ospf6_abr.h"
  24. static int abr_index;
  25. #define IS_OSPF6_DUMP_ABR (ospf6_dump_is_on (abr_index))
  26. #define ADD 0
  27. #define CHANGE 1
  28. #define REMOVE 2
  29. /* Inter-Area-Prefix-LSA Calculation */
  30. static struct ospf6_route_req *
  31. ospf6_abr_entry_lookup (struct ospf6_route_req *abr_entry,
  32. u_int32_t router_id, struct ospf6_area *area)
  33. {
  34. struct prefix_ls abr_id;
  35. char router_string[32];
  36. inet_ntop (AF_INET, &router_id, router_string, sizeof (router_string));
  37. //zlog_info ("ABR: Finding router %s in area %s", router_string, area->str);
  38. memset (&abr_id, 0, sizeof (abr_id));
  39. abr_id.family = AF_UNSPEC;
  40. abr_id.prefixlen = 64; /* xxx */
  41. abr_id.id.s_addr = htonl (0);
  42. abr_id.adv_router.s_addr = router_id;
  43. ospf6_route_lookup (abr_entry, (struct prefix *) &abr_id,
  44. area->table_topology);
  45. if (ospf6_route_end (abr_entry))
  46. {
  47. if (IS_OSPF6_DUMP_ABR)
  48. zlog_info ("ABR: Router %s not found in area %s",
  49. router_string, area->str);
  50. return NULL;
  51. }
  52. if (abr_entry->path.area_id != area->area_id)
  53. {
  54. if (IS_OSPF6_DUMP_ABR)
  55. zlog_info ("ABR: ABR area id mismatch");
  56. return NULL;
  57. }
  58. if (! CHECK_FLAG (abr_entry->path.router_bits, OSPF6_ROUTER_LSA_BIT_B))
  59. {
  60. if (IS_OSPF6_DUMP_ABR)
  61. zlog_info ("ABR: ABR entry's B bit off");
  62. return NULL;
  63. }
  64. return abr_entry;
  65. }
  66. static int
  67. ospf6_abr_prefix_lsa_to_route (struct ospf6_lsa *lsa,
  68. struct ospf6_route_req *request)
  69. {
  70. struct ospf6_inter_area_prefix_lsa *iep;
  71. struct ospf6_route_req abr_entry;
  72. if (lsa->header->type != htons (OSPF6_LSA_TYPE_INTER_PREFIX))
  73. {
  74. if (IS_OSPF6_DUMP_ABR)
  75. zlog_info ("ABR: LSA type mismatch");
  76. return -1;
  77. }
  78. if (IS_LSA_MAXAGE (lsa))
  79. {
  80. if (IS_OSPF6_DUMP_ABR)
  81. zlog_info ("ABR: LSA MaxAge");
  82. return -1;
  83. }
  84. if (! ospf6_abr_entry_lookup (&abr_entry, lsa->header->adv_router,
  85. (struct ospf6_area *) lsa->scope))
  86. {
  87. if (IS_OSPF6_DUMP_ABR)
  88. zlog_info ("ABR: ABR check failed");
  89. return -1;
  90. }
  91. iep = OSPF6_LSA_HEADER_END (lsa->header);
  92. memset (request, 0, sizeof (struct ospf6_route_req));
  93. request->route.type = OSPF6_DEST_TYPE_NETWORK;
  94. request->route.prefix.family = AF_INET6;
  95. request->route.prefix.prefixlen = iep->prefix.prefix_length;
  96. ospf6_prefix_in6_addr (&iep->prefix, &request->route.prefix.u.prefix6);
  97. request->path.cost = abr_entry.path.cost +
  98. (ntohl (iep->metric) & ntohl (0x000fffff));
  99. request->path.type = OSPF6_PATH_TYPE_INTER;
  100. request->path.origin.type = lsa->header->type;
  101. request->path.origin.id = lsa->header->id;
  102. request->path.origin.adv_router = lsa->header->adv_router;
  103. memcpy (&request->nexthop.address, &abr_entry.nexthop.address,
  104. sizeof (request->nexthop.address));
  105. request->nexthop.ifindex = abr_entry.nexthop.ifindex;
  106. return 0;
  107. }
  108. void
  109. ospf6_abr_prefix_lsa_add (struct ospf6_lsa *lsa)
  110. {
  111. struct ospf6_route_req request;
  112. int ret;
  113. if (IS_OSPF6_DUMP_ABR)
  114. zlog_info ("ABR: Calculate %s", lsa->str);
  115. ret = ospf6_abr_prefix_lsa_to_route (lsa, &request);
  116. if (ret < 0)
  117. return;
  118. if (IS_OSPF6_DUMP_ABR)
  119. zlog_info ("ABR: Inter Area Route add for %s", lsa->str);
  120. ospf6_route_add (&request, ospf6->route_table);
  121. }
  122. void
  123. ospf6_abr_prefix_lsa_remove (struct ospf6_lsa *lsa)
  124. {
  125. struct ospf6_inter_area_prefix_lsa *iep;
  126. struct prefix_ipv6 prefix6;
  127. struct ospf6_route_req request;
  128. iep = OSPF6_LSA_HEADER_END (lsa->header);
  129. prefix6.family = AF_INET6;
  130. prefix6.prefixlen = iep->prefix.prefix_length;
  131. ospf6_prefix_in6_addr (&iep->prefix, &prefix6.prefix);
  132. if (IS_OSPF6_DUMP_ABR)
  133. zlog_info ("ABR: Inter Area Route remove for %s", lsa->str);
  134. for (ospf6_route_lookup (&request, (struct prefix *) &prefix6,
  135. ospf6->route_table);
  136. ! ospf6_route_end (&request);
  137. ospf6_route_next (&request))
  138. {
  139. if (memcmp (&prefix6, &request.route.prefix, sizeof (prefix6)))
  140. break;
  141. if (request.path.origin.type != htons (OSPF6_LSA_TYPE_INTER_PREFIX) ||
  142. request.path.origin.adv_router != lsa->header->adv_router ||
  143. request.path.origin.id != lsa->header->id)
  144. continue;
  145. ospf6_route_remove (&request, ospf6->route_table);
  146. }
  147. }
  148. static int
  149. ospf6_abr_router_lsa_to_route (struct ospf6_lsa *lsa,
  150. struct ospf6_route_req *request)
  151. {
  152. struct ospf6_inter_area_router_lsa *ier;
  153. struct ospf6_route_req abr_entry;
  154. if (lsa->header->type != htons (OSPF6_LSA_TYPE_INTER_ROUTER))
  155. {
  156. if (IS_OSPF6_DUMP_ABR)
  157. zlog_info ("ABR: LSA type mismatch");
  158. return -1;
  159. }
  160. if (IS_LSA_MAXAGE (lsa))
  161. {
  162. if (IS_OSPF6_DUMP_ABR)
  163. zlog_info ("ABR: LSA MaxAge");
  164. return -1;
  165. }
  166. if (! ospf6_abr_entry_lookup (&abr_entry, lsa->header->adv_router,
  167. (struct ospf6_area *) lsa->scope))
  168. {
  169. if (IS_OSPF6_DUMP_ABR)
  170. zlog_info ("ABR: Advertising router check failed");
  171. return -1;
  172. }
  173. ier = OSPF6_LSA_HEADER_END (lsa->header);
  174. memset (request, 0, sizeof (struct ospf6_route_req));
  175. request->route.type = OSPF6_DEST_TYPE_ROUTER;
  176. request->route.prefix.family = AF_UNSPEC;
  177. request->route.prefix.prefixlen = 64; /* XXX */
  178. ((struct prefix_ls *) &request->route.prefix)->adv_router.s_addr
  179. = ier->router_id;
  180. request->path.cost = abr_entry.path.cost +
  181. (ntohl (ier->metric & htonl (0x000fffff)));
  182. request->path.type = OSPF6_PATH_TYPE_INTER;
  183. request->path.origin.type = lsa->header->type;
  184. request->path.origin.id = lsa->header->id;
  185. request->path.origin.adv_router = lsa->header->adv_router;
  186. SET_FLAG (request->path.router_bits, OSPF6_ROUTER_LSA_BIT_E);
  187. request->path.capability[0] = ier->options[0];
  188. request->path.capability[1] = ier->options[1];
  189. request->path.capability[2] = ier->options[2];
  190. memcpy (&request->nexthop.address, &abr_entry.nexthop.address,
  191. sizeof (request->nexthop.address));
  192. request->nexthop.ifindex = abr_entry.nexthop.ifindex;
  193. return 0;
  194. }
  195. void
  196. ospf6_abr_router_lsa_add (struct ospf6_lsa *lsa)
  197. {
  198. struct ospf6_route_req request;
  199. int ret;
  200. if (IS_OSPF6_DUMP_ABR)
  201. zlog_info ("ABR: Calculate %s", lsa->str);
  202. ret = ospf6_abr_router_lsa_to_route (lsa, &request);
  203. if (ret < 0)
  204. return;
  205. if (IS_OSPF6_DUMP_ABR)
  206. zlog_info ("ABR: Inter Area Router add for %s", lsa->str);
  207. ospf6_route_add (&request, ospf6->topology_table);
  208. }
  209. void
  210. ospf6_abr_router_lsa_remove (struct ospf6_lsa *lsa)
  211. {
  212. struct ospf6_inter_area_router_lsa *ier;
  213. struct prefix_ls prefix_ls;
  214. struct ospf6_route_req request;
  215. ier = OSPF6_LSA_HEADER_END (lsa->header);
  216. memset (&prefix_ls, 0, sizeof (prefix_ls));
  217. prefix_ls.family = AF_INET6;
  218. prefix_ls.prefixlen = 64; /* XXX */
  219. prefix_ls.adv_router.s_addr = ier->router_id;
  220. if (IS_OSPF6_DUMP_ABR)
  221. zlog_info ("ABR: Inter Area Route remove for %s", lsa->str);
  222. for (ospf6_route_lookup (&request, (struct prefix *) &prefix_ls,
  223. ospf6->route_table);
  224. ! ospf6_route_end (&request);
  225. ospf6_route_next (&request))
  226. {
  227. if (memcmp (&prefix_ls, &request.route.prefix, sizeof (prefix_ls)))
  228. break;
  229. if (request.path.origin.type != htons (OSPF6_LSA_TYPE_INTER_ROUTER) ||
  230. request.path.origin.adv_router != lsa->header->adv_router ||
  231. request.path.origin.id != lsa->header->id)
  232. continue;
  233. ospf6_route_remove (&request, ospf6->route_table);
  234. }
  235. }
  236. void
  237. ospf6_abr_abr_entry_add (struct ospf6_route_req *abr_entry)
  238. {
  239. struct ospf6_lsdb_node node;
  240. struct prefix_ls *abr_id;
  241. struct ospf6_route_req request;
  242. struct ospf6_area *area;
  243. if (IS_OSPF6_DUMP_ABR)
  244. zlog_info ("ABR: New Area Border Router found");
  245. area = ospf6_area_lookup (abr_entry->path.area_id, ospf6);
  246. if (! area)
  247. {
  248. if (IS_OSPF6_DUMP_ABR)
  249. zlog_info ("ABR: Can't find associated area");
  250. return;
  251. }
  252. abr_id = (struct prefix_ls *) &abr_entry->route.prefix;
  253. if (! ospf6_abr_entry_lookup (&request, abr_id->adv_router.s_addr, area))
  254. {
  255. if (IS_OSPF6_DUMP_ABR)
  256. zlog_info ("ABR: back check failed");
  257. return;
  258. }
  259. /* for each inter-prefix LSA this ABR originated */
  260. for (ospf6_lsdb_type_router (&node, htons (OSPF6_LSA_TYPE_INTER_PREFIX),
  261. abr_id->adv_router.s_addr, area->lsdb);
  262. ! ospf6_lsdb_is_end (&node);
  263. ospf6_lsdb_next (&node))
  264. ospf6_abr_prefix_lsa_add (node.lsa);
  265. /* for each inter-router LSA this ABR originated */
  266. for (ospf6_lsdb_type_router (&node, htons (OSPF6_LSA_TYPE_INTER_ROUTER),
  267. abr_id->adv_router.s_addr, area->lsdb);
  268. ! ospf6_lsdb_is_end (&node);
  269. ospf6_lsdb_next (&node))
  270. ospf6_abr_router_lsa_add (node.lsa);
  271. }
  272. void
  273. ospf6_abr_abr_entry_remove (struct ospf6_route_req *abr_entry)
  274. {
  275. struct ospf6_lsdb_node node;
  276. struct prefix_ls *abr_id;
  277. struct ospf6_area *area;
  278. if (IS_OSPF6_DUMP_ABR)
  279. zlog_info ("ABR: Area Border Router removed");
  280. abr_id = (struct prefix_ls *) &abr_entry->route.prefix;
  281. area = ospf6_area_lookup (abr_entry->path.area_id, ospf6);
  282. if (! area)
  283. {
  284. if (IS_OSPF6_DUMP_ABR)
  285. zlog_info ("ABR: Can't find associated area");
  286. return;
  287. }
  288. /* for each inter-prefix LSA this ABR originated */
  289. for (ospf6_lsdb_type_router (&node, htons (OSPF6_LSA_TYPE_INTER_PREFIX),
  290. abr_id->adv_router.s_addr, area->lsdb);
  291. ! ospf6_lsdb_is_end (&node);
  292. ospf6_lsdb_next (&node))
  293. ospf6_abr_prefix_lsa_remove (node.lsa);
  294. /* for each inter-router LSA this ABR originated */
  295. for (ospf6_lsdb_type_router (&node, htons (OSPF6_LSA_TYPE_INTER_ROUTER),
  296. abr_id->adv_router.s_addr, area->lsdb);
  297. ! ospf6_lsdb_is_end (&node);
  298. ospf6_lsdb_next (&node))
  299. ospf6_abr_router_lsa_remove (node.lsa);
  300. }
  301. /* Inter-Area-Prefix-LSA Origination */
  302. static void
  303. ospf6_abr_prefix_lsa_update_add (struct ospf6_route_req *request,
  304. struct ospf6_area *area)
  305. {
  306. char buffer [MAXLSASIZE];
  307. u_int16_t size;
  308. struct ospf6_inter_area_prefix_lsa *iep;
  309. char *p;
  310. if (IS_OSPF6_DUMP_ABR)
  311. zlog_info ("Update Inter-Prefix for %s: ID: %lu",
  312. area->str, (u_long) ntohl (request->route_id));
  313. /* prepare buffer */
  314. memset (buffer, 0, sizeof (buffer));
  315. size = sizeof (struct ospf6_inter_area_prefix_lsa);
  316. iep = (struct ospf6_inter_area_prefix_lsa *) buffer;
  317. p = (char *) (iep + 1);
  318. /* prefixlen */
  319. iep->prefix.prefix_length = request->route.prefix.prefixlen;
  320. /* PrefixOptions */
  321. iep->prefix.prefix_options = request->path.prefix_options;
  322. /* set Prefix */
  323. memcpy (p, &request->route.prefix.u.prefix6,
  324. OSPF6_PREFIX_SPACE (request->route.prefix.prefixlen));
  325. ospf6_prefix_apply_mask (&iep->prefix);
  326. size += OSPF6_PREFIX_SPACE (request->route.prefix.prefixlen);
  327. ospf6_lsa_originate (htons (OSPF6_LSA_TYPE_INTER_PREFIX),
  328. htonl (request->route_id), ospf6->router_id,
  329. (char *) iep, size, area);
  330. }
  331. static void
  332. ospf6_abr_prefix_lsa_update_remove (struct ospf6_route_req *request,
  333. struct ospf6_area *area)
  334. {
  335. struct ospf6_lsa *lsa;
  336. lsa = ospf6_lsdb_lookup_lsdb (htons (OSPF6_LSA_TYPE_INTER_PREFIX),
  337. htonl (request->route_id),
  338. ospf6->router_id, area->lsdb);
  339. if (lsa)
  340. ospf6_lsa_premature_aging (lsa);
  341. }
  342. static void
  343. ospf6_abr_prefix_lsa_update (int type, struct ospf6_route_req *request)
  344. {
  345. struct ospf6_route_req route, target;
  346. listnode node;
  347. struct ospf6_area *area;
  348. struct ospf6_interface *o6i;
  349. if (request->route.type != OSPF6_DEST_TYPE_NETWORK)
  350. return;
  351. /* assert this is best path; if not, return */
  352. ospf6_route_lookup (&route, &request->route.prefix, request->table);
  353. if (memcmp (&route.path, &request->path, sizeof (route.path)))
  354. return;
  355. if (target.path.cost >= LS_INFINITY ||
  356. target.path.cost_e2 >= LS_INFINITY)
  357. {
  358. if (IS_OSPF6_DUMP_ABR)
  359. zlog_info ("ABR: Exceeds LS Infinity, ignore");
  360. return;
  361. }
  362. ospf6_route_lookup (&target, &request->route.prefix, request->table);
  363. if (type == REMOVE)
  364. {
  365. ospf6_route_next (&route);
  366. if (! memcmp (&route.route, &request->route, sizeof (route.route)))
  367. {
  368. type = ADD;
  369. ospf6_route_next (&target);
  370. }
  371. }
  372. for (node = listhead (ospf6->area_list); node; nextnode (node))
  373. {
  374. area = getdata (node);
  375. if (target.path.area_id == area->area_id)
  376. continue;
  377. o6i = ospf6_interface_lookup_by_index (target.nexthop.ifindex);
  378. if (o6i && o6i->area && o6i->area->area_id == area->area_id)
  379. {
  380. zlog_info ("ABR: Logical equivalent of split horizon, skip for %s",
  381. area->str);
  382. continue;
  383. }
  384. if (area->area_id == ntohs (0) && /* Backbone */
  385. target.path.type != OSPF6_PATH_TYPE_INTRA)
  386. continue;
  387. /* XXX, stub area check */
  388. /* XXX, aggregate */
  389. /* if either the area of the route or the area trying to
  390. advertise is backbone, do not aggregate */
  391. if (type == ADD)
  392. ospf6_abr_prefix_lsa_update_add (&target, area);
  393. else
  394. ospf6_abr_prefix_lsa_update_remove (&target, area);
  395. }
  396. }
  397. void
  398. ospf6_abr_route_add (struct ospf6_route_req *request)
  399. {
  400. ospf6_abr_prefix_lsa_update (ADD, request);
  401. }
  402. void
  403. ospf6_abr_route_remove (struct ospf6_route_req *request)
  404. {
  405. ospf6_abr_prefix_lsa_update (REMOVE, request);
  406. }
  407. int
  408. ospf6_abr_prefix_lsa_refresh (void *data)
  409. {
  410. struct ospf6_lsa *lsa = data;
  411. struct ospf6_inter_area_prefix_lsa *ier;
  412. struct prefix_ipv6 prefix6;
  413. struct ospf6_route_req route;
  414. ier = OSPF6_LSA_HEADER_END (lsa->header);
  415. memset (&prefix6, 0, sizeof (prefix6));
  416. prefix6.family = AF_INET6;
  417. prefix6.prefixlen = ier->prefix.prefix_length;
  418. ospf6_prefix_in6_addr (&ier->prefix, &prefix6.prefix);
  419. ospf6_route_lookup (&route, (struct prefix *) &prefix6,
  420. ospf6->route_table);
  421. assert (! ospf6_route_end (&route));
  422. ospf6_abr_prefix_lsa_update (ADD, &route);
  423. return 0;
  424. }
  425. int
  426. ospf6_abr_prefix_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
  427. {
  428. struct ospf6_inter_area_prefix_lsa *ier;
  429. char prefix[128];
  430. assert (lsa->header);
  431. ier = OSPF6_LSA_HEADER_END (lsa->header);
  432. ospf6_prefix_string (&ier->prefix, prefix, sizeof (prefix));
  433. vty_out (vty, " Metric: %d%s",
  434. ntohl (ier->metric & htonl (0x000fffff)), VTY_NEWLINE);
  435. vty_out (vty, " Prefix: %s%s", prefix, VTY_NEWLINE);
  436. return 0;
  437. }
  438. int
  439. ospf6_abr_prefix_lsa_hook_add (void *data)
  440. {
  441. struct ospf6_lsa *lsa = data;
  442. ospf6_abr_prefix_lsa_add (lsa);
  443. return 0;
  444. }
  445. int
  446. ospf6_abr_prefix_lsa_hook_remove (void *data)
  447. {
  448. struct ospf6_lsa *lsa = data;
  449. ospf6_abr_prefix_lsa_remove (lsa);
  450. return 0;
  451. }
  452. void
  453. ospf6_abr_database_hook_inter_prefix (struct ospf6_lsa *old,
  454. struct ospf6_lsa *new)
  455. {
  456. if (old)
  457. ospf6_abr_prefix_lsa_hook_remove (old);
  458. if (new && ! IS_LSA_MAXAGE (new))
  459. ospf6_abr_prefix_lsa_hook_add (new);
  460. }
  461. void
  462. ospf6_abr_register_inter_prefix ()
  463. {
  464. struct ospf6_lsa_slot slot;
  465. memset (&slot, 0, sizeof (slot));
  466. slot.type = htons (OSPF6_LSA_TYPE_INTER_PREFIX);
  467. slot.name = "Inter-Prefix";
  468. slot.func_show = ospf6_abr_prefix_lsa_show;
  469. slot.func_refresh = ospf6_abr_prefix_lsa_refresh;
  470. ospf6_lsa_slot_register (&slot);
  471. ospf6_lsdb_hook[OSPF6_LSA_TYPE_INTER_PREFIX & OSPF6_LSTYPE_CODE_MASK].hook =
  472. ospf6_abr_database_hook_inter_prefix;
  473. }
  474. int
  475. ospf6_abr_router_lsa_hook_add (void *data)
  476. {
  477. struct ospf6_lsa *lsa = data;
  478. ospf6_abr_router_lsa_add (lsa);
  479. return 0;
  480. }
  481. int
  482. ospf6_abr_router_lsa_hook_remove (void *data)
  483. {
  484. struct ospf6_lsa *lsa = data;
  485. ospf6_abr_router_lsa_remove (lsa);
  486. return 0;
  487. }
  488. int
  489. ospf6_abr_router_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
  490. {
  491. return 0;
  492. }
  493. int
  494. ospf6_abr_router_lsa_refresh (void *data)
  495. {
  496. return 0;
  497. }
  498. void
  499. ospf6_abr_database_hook_inter_router (struct ospf6_lsa *old,
  500. struct ospf6_lsa *new)
  501. {
  502. if (old)
  503. ospf6_abr_router_lsa_hook_remove (old);
  504. if (new && ! IS_LSA_MAXAGE (new))
  505. ospf6_abr_router_lsa_hook_add (new);
  506. }
  507. void
  508. ospf6_abr_register_inter_router ()
  509. {
  510. struct ospf6_lsa_slot slot;
  511. memset (&slot, 0, sizeof (slot));
  512. slot.type = htons (OSPF6_LSA_TYPE_INTER_ROUTER);
  513. slot.name = "Inter-Router";
  514. slot.func_show = ospf6_abr_router_lsa_show;
  515. slot.func_refresh = ospf6_abr_router_lsa_refresh;
  516. ospf6_lsa_slot_register (&slot);
  517. ospf6_lsdb_hook[OSPF6_LSA_TYPE_INTER_ROUTER & OSPF6_LSTYPE_CODE_MASK].hook =
  518. ospf6_abr_database_hook_inter_router;
  519. }
  520. void
  521. ospf6_abr_inter_route_calculation (struct ospf6_area *area)
  522. {
  523. struct ospf6_lsdb_node node;
  524. /* for each inter-prefix LSA */
  525. for (ospf6_lsdb_type (&node, htons (OSPF6_LSA_TYPE_INTER_PREFIX),
  526. area->lsdb);
  527. ! ospf6_lsdb_is_end (&node);
  528. ospf6_lsdb_next (&node))
  529. ospf6_abr_prefix_lsa_add (node.lsa);
  530. }
  531. void
  532. ospf6_abr_init ()
  533. {
  534. abr_index = ospf6_dump_install ("abr", "Area Border Router Function\n");
  535. ospf6_abr_register_inter_prefix ();
  536. ospf6_abr_register_inter_router ();
  537. }