isis_redist.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825
  1. /*
  2. * IS-IS Rout(e)ing protocol - isis_redist.c
  3. *
  4. * Copyright (C) 2013-2015 Christian Franke <chris@opensourcerouting.org>
  5. *
  6. * This program 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 Free
  8. * Software Foundation; either version 2 of the License, or (at your option)
  9. * any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,but WITHOUT
  12. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  14. * more details.
  15. * You should have received a copy of the GNU General Public License along
  16. * with this program; if not, write to the Free Software Foundation, Inc.,
  17. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  18. */
  19. #include <zebra.h>
  20. #include "command.h"
  21. #include "if.h"
  22. #include "linklist.h"
  23. #include "memory.h"
  24. #include "memtypes.h"
  25. #include "prefix.h"
  26. #include "routemap.h"
  27. #include "stream.h"
  28. #include "table.h"
  29. #include "vty.h"
  30. #include "isisd/dict.h"
  31. #include "isisd/isis_constants.h"
  32. #include "isisd/isis_common.h"
  33. #include "isisd/isis_flags.h"
  34. #include "isisd/isis_misc.h"
  35. #include "isisd/isis_circuit.h"
  36. #include "isisd/isis_tlv.h"
  37. #include "isisd/isisd.h"
  38. #include "isisd/isis_lsp.h"
  39. #include "isisd/isis_route.h"
  40. #include "isisd/isis_zebra.h"
  41. static int
  42. redist_protocol(int family)
  43. {
  44. if (family == AF_INET)
  45. return 0;
  46. if (family == AF_INET6)
  47. return 1;
  48. assert(!"Unsupported address family!");
  49. return 0;
  50. }
  51. static int
  52. is_default(struct prefix *p)
  53. {
  54. if (p->family == AF_INET)
  55. if (p->u.prefix4.s_addr == 0 && p->prefixlen == 0)
  56. return 1;
  57. if (p->family == AF_INET6)
  58. if (IN6_IS_ADDR_UNSPECIFIED(&p->u.prefix6) && p->prefixlen == 0)
  59. return 1;
  60. return 0;
  61. }
  62. static struct route_table*
  63. get_ext_info(struct isis *i, int family)
  64. {
  65. int protocol = redist_protocol(family);
  66. return i->ext_info[protocol];
  67. }
  68. static struct isis_redist*
  69. get_redist_settings(struct isis_area *area, int family, int type, int level)
  70. {
  71. int protocol = redist_protocol(family);
  72. return &area->redist_settings[protocol][type][level-1];
  73. }
  74. struct route_table*
  75. get_ext_reach(struct isis_area *area, int family, int level)
  76. {
  77. int protocol = redist_protocol(family);
  78. return area->ext_reach[protocol][level-1];
  79. }
  80. static struct route_node *
  81. isis_redist_route_node_create(route_table_delegate_t *delegate,
  82. struct route_table *table)
  83. {
  84. struct route_node *node;
  85. node = XCALLOC(MTYPE_ROUTE_NODE, sizeof(*node));
  86. return node;
  87. }
  88. static void
  89. isis_redist_route_node_destroy(route_table_delegate_t *delegate,
  90. struct route_table *table,
  91. struct route_node *node)
  92. {
  93. if (node->info)
  94. XFREE(MTYPE_ISIS, node->info);
  95. XFREE (MTYPE_ROUTE_NODE, node);
  96. }
  97. static route_table_delegate_t isis_redist_rt_delegate = {
  98. .create_node = isis_redist_route_node_create,
  99. .destroy_node = isis_redist_route_node_destroy
  100. };
  101. /* Install external reachability information into a
  102. * specific area for a specific level.
  103. * Schedule an lsp regenerate if necessary */
  104. static void
  105. isis_redist_install(struct isis_area *area, int level,
  106. struct prefix *p, struct isis_ext_info *info)
  107. {
  108. int family = p->family;
  109. struct route_table *er_table = get_ext_reach(area, family, level);
  110. struct route_node *er_node;
  111. if (!er_table)
  112. {
  113. zlog_warn("%s: External reachability table of area %s"
  114. " is not initialized.", __func__, area->area_tag);
  115. return;
  116. }
  117. er_node = route_node_get(er_table, p);
  118. if (er_node->info)
  119. {
  120. route_unlock_node(er_node);
  121. /* Don't update/reschedule lsp generation if nothing changed. */
  122. if (!memcmp(er_node->info, info, sizeof(*info)))
  123. return;
  124. }
  125. else
  126. {
  127. er_node->info = XMALLOC(MTYPE_ISIS, sizeof(*info));
  128. }
  129. memcpy(er_node->info, info, sizeof(*info));
  130. lsp_regenerate_schedule(area, level, 0);
  131. }
  132. /* Remove external reachability information from a
  133. * specific area for a specific level.
  134. * Schedule an lsp regenerate if necessary. */
  135. static void
  136. isis_redist_uninstall(struct isis_area *area, int level, struct prefix *p)
  137. {
  138. int family = p->family;
  139. struct route_table *er_table = get_ext_reach(area, family, level);
  140. struct route_node *er_node;
  141. if (!er_table)
  142. {
  143. zlog_warn("%s: External reachability table of area %s"
  144. " is not initialized.", __func__, area->area_tag);
  145. return;
  146. }
  147. er_node = route_node_lookup(er_table, p);
  148. if (!er_node)
  149. return;
  150. else
  151. route_unlock_node(er_node);
  152. if (!er_node->info)
  153. return;
  154. XFREE(MTYPE_ISIS, er_node->info);
  155. route_unlock_node(er_node);
  156. lsp_regenerate_schedule(area, level, 0);
  157. }
  158. /* Update external reachability info of area for a given level
  159. * and prefix, using the given redistribution settings. */
  160. static void
  161. isis_redist_update_ext_reach(struct isis_area *area, int level,
  162. struct isis_redist *redist, struct prefix *p,
  163. struct isis_ext_info *info)
  164. {
  165. struct isis_ext_info area_info;
  166. route_map_result_t map_ret;
  167. memcpy(&area_info, info, sizeof(area_info));
  168. if (redist->metric != 0xffffffff)
  169. area_info.metric = redist->metric;
  170. if (redist->map_name)
  171. {
  172. map_ret = route_map_apply(redist->map, p, RMAP_ISIS, &area_info);
  173. if (map_ret == RMAP_DENYMATCH)
  174. area_info.distance = 255;
  175. }
  176. /* Allow synthesized default routes only on always orignate */
  177. if (area_info.origin == DEFAULT_ROUTE
  178. && redist->redist != DEFAULT_ORIGINATE_ALWAYS)
  179. area_info.distance = 255;
  180. if (area_info.distance < 255)
  181. isis_redist_install(area, level, p, &area_info);
  182. else
  183. isis_redist_uninstall(area, level, p);
  184. }
  185. static void
  186. isis_redist_ensure_default(struct isis *isis, int family)
  187. {
  188. struct prefix p;
  189. struct route_table *ei_table = get_ext_info(isis, family);
  190. struct route_node *ei_node;
  191. struct isis_ext_info *info;
  192. if (family == AF_INET)
  193. {
  194. p.family = AF_INET;
  195. p.prefixlen = 0;
  196. memset(&p.u.prefix4, 0, sizeof(p.u.prefix4));
  197. }
  198. else if (family == AF_INET6)
  199. {
  200. p.family = AF_INET6;
  201. p.prefixlen = 0;
  202. memset(&p.u.prefix6, 0, sizeof(p.u.prefix6));
  203. }
  204. else
  205. assert(!"Unknown family!");
  206. ei_node = route_node_get(ei_table, &p);
  207. if (ei_node->info)
  208. {
  209. route_unlock_node(ei_node);
  210. return;
  211. }
  212. ei_node->info = XCALLOC(MTYPE_ISIS, sizeof(struct isis_ext_info));
  213. info = ei_node->info;
  214. info->origin = DEFAULT_ROUTE;
  215. info->distance = 254;
  216. info->metric = MAX_WIDE_PATH_METRIC;
  217. }
  218. /* Handle notification about route being added */
  219. void
  220. isis_redist_add(int type, struct prefix *p, u_char distance, uint32_t metric)
  221. {
  222. int family = p->family;
  223. struct route_table *ei_table = get_ext_info(isis, family);
  224. struct route_node *ei_node;
  225. struct isis_ext_info *info;
  226. struct listnode *node;
  227. struct isis_area *area;
  228. int level;
  229. struct isis_redist *redist;
  230. char debug_buf[BUFSIZ];
  231. prefix2str(p, debug_buf, sizeof(debug_buf));
  232. zlog_debug("%s: New route %s from %s.", __func__, debug_buf,
  233. zebra_route_string(type));
  234. if (!ei_table)
  235. {
  236. zlog_warn("%s: External information table not initialized.",
  237. __func__);
  238. return;
  239. }
  240. ei_node = route_node_get(ei_table, p);
  241. if (ei_node->info)
  242. route_unlock_node(ei_node);
  243. else
  244. ei_node->info = XCALLOC(MTYPE_ISIS, sizeof(struct isis_ext_info));
  245. info = ei_node->info;
  246. info->origin = type;
  247. info->distance = distance;
  248. info->metric = metric;
  249. if (is_default(p))
  250. type = DEFAULT_ROUTE;
  251. for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area))
  252. for (level = 1; level <= ISIS_LEVELS; level++)
  253. {
  254. redist = get_redist_settings(area, family, type, level);
  255. if (!redist->redist)
  256. continue;
  257. isis_redist_update_ext_reach(area, level, redist, p, info);
  258. }
  259. }
  260. void
  261. isis_redist_delete(int type, struct prefix *p)
  262. {
  263. int family = p->family;
  264. struct route_table *ei_table = get_ext_info(isis, family);
  265. struct route_node *ei_node;
  266. struct listnode *node;
  267. struct isis_area *area;
  268. int level;
  269. struct isis_redist *redist;
  270. char debug_buf[BUFSIZ];
  271. prefix2str(p, debug_buf, sizeof(debug_buf));
  272. zlog_debug("%s: Removing route %s from %s.", __func__, debug_buf,
  273. zebra_route_string(type));
  274. if (is_default(p))
  275. {
  276. /* Don't remove default route but add synthetic route for use
  277. * by "default-information originate always". Areas without the
  278. * "always" setting will ignore routes with origin DEFAULT_ROUTE. */
  279. isis_redist_add(DEFAULT_ROUTE, p, 254, MAX_WIDE_PATH_METRIC);
  280. return;
  281. }
  282. if (!ei_table)
  283. {
  284. zlog_warn("%s: External information table not initialized.",
  285. __func__);
  286. return;
  287. }
  288. ei_node = route_node_lookup(ei_table, p);
  289. if (!ei_node || !ei_node->info)
  290. {
  291. char buf[BUFSIZ];
  292. prefix2str(p, buf, sizeof(buf));
  293. zlog_warn("%s: Got a delete for %s route %s, but that route"
  294. " was never added.", __func__, zebra_route_string(type),
  295. buf);
  296. if (ei_node)
  297. route_unlock_node(ei_node);
  298. return;
  299. }
  300. route_unlock_node(ei_node);
  301. for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area))
  302. for (level = 1; level < ISIS_LEVELS; level++)
  303. {
  304. redist = get_redist_settings(area, family, type, level);
  305. if (!redist->redist)
  306. continue;
  307. isis_redist_uninstall(area, level, p);
  308. }
  309. XFREE(MTYPE_ISIS, ei_node->info);
  310. route_unlock_node(ei_node);
  311. }
  312. static void
  313. isis_redist_routemap_set(struct isis_redist *redist, const char *routemap)
  314. {
  315. if (redist->map_name) {
  316. XFREE(MTYPE_ISIS, redist->map_name);
  317. redist->map = NULL;
  318. }
  319. if (routemap && strlen(routemap)) {
  320. redist->map_name = XSTRDUP(MTYPE_ISIS, routemap);
  321. redist->map = route_map_lookup_by_name(routemap);
  322. }
  323. }
  324. static void
  325. isis_redist_update_zebra_subscriptions(struct isis *isis)
  326. {
  327. struct listnode *node;
  328. struct isis_area *area;
  329. int type;
  330. int level;
  331. int protocol;
  332. char do_subscribe[ZEBRA_ROUTE_MAX + 1];
  333. memset(do_subscribe, 0, sizeof(do_subscribe));
  334. for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area))
  335. for (protocol = 0; protocol < REDIST_PROTOCOL_COUNT; protocol++)
  336. for (type = 0; type < ZEBRA_ROUTE_MAX + 1; type++)
  337. for (level = 0; level < ISIS_LEVELS; level++)
  338. if (area->redist_settings[protocol][type][level].redist)
  339. do_subscribe[type] = 1;
  340. for (type = 0; type < ZEBRA_ROUTE_MAX + 1; type++)
  341. {
  342. /* This field is actually controlling transmission of the IS-IS
  343. * routes to Zebra and has nothing to do with redistribution,
  344. * so skip it. */
  345. if (type == ZEBRA_ROUTE_ISIS)
  346. continue;
  347. if (do_subscribe[type])
  348. isis_zebra_redistribute_set(type);
  349. else
  350. isis_zebra_redistribute_unset(type);
  351. }
  352. }
  353. static void
  354. isis_redist_set(struct isis_area *area, int level,
  355. int family, int type, uint32_t metric,
  356. const char *routemap, int originate_type)
  357. {
  358. int protocol = redist_protocol(family);
  359. struct isis_redist *redist = get_redist_settings(area, family, type, level);
  360. int i;
  361. struct route_table *ei_table;
  362. struct route_node *rn;
  363. struct isis_ext_info *info;
  364. redist->redist = (type == DEFAULT_ROUTE) ? originate_type : 1;
  365. redist->metric = metric;
  366. isis_redist_routemap_set(redist, routemap);
  367. if (!area->ext_reach[protocol][level-1])
  368. {
  369. area->ext_reach[protocol][level-1] =
  370. route_table_init_with_delegate(&isis_redist_rt_delegate);
  371. }
  372. for (i = 0; i < REDIST_PROTOCOL_COUNT; i++)
  373. if (!area->isis->ext_info[i])
  374. {
  375. area->isis->ext_info[i] =
  376. route_table_init_with_delegate(&isis_redist_rt_delegate);
  377. }
  378. isis_redist_update_zebra_subscriptions(area->isis);
  379. if (type == DEFAULT_ROUTE && originate_type == DEFAULT_ORIGINATE_ALWAYS)
  380. isis_redist_ensure_default(area->isis, family);
  381. ei_table = get_ext_info(area->isis, family);
  382. for (rn = route_top(ei_table); rn; rn = route_next(rn))
  383. {
  384. if (!rn->info)
  385. continue;
  386. info = rn->info;
  387. if (type == DEFAULT_ROUTE)
  388. {
  389. if (!is_default(&rn->p))
  390. continue;
  391. }
  392. else
  393. {
  394. if (info->origin != type)
  395. continue;
  396. }
  397. isis_redist_update_ext_reach(area, level, redist, &rn->p, info);
  398. }
  399. }
  400. static void
  401. isis_redist_unset(struct isis_area *area, int level,
  402. int family, int type)
  403. {
  404. struct isis_redist *redist = get_redist_settings(area, family, type, level);
  405. struct route_table *er_table = get_ext_reach(area, family, level);
  406. struct route_node *rn;
  407. struct isis_ext_info *info;
  408. if (!redist->redist)
  409. return;
  410. redist->redist = 0;
  411. if (!er_table)
  412. {
  413. zlog_warn("%s: External reachability table uninitialized.", __func__);
  414. return;
  415. }
  416. for (rn = route_top(er_table); rn; rn = route_next(rn))
  417. {
  418. if (!rn->info)
  419. continue;
  420. info = rn->info;
  421. if (type == DEFAULT_ROUTE)
  422. {
  423. if (!is_default(&rn->p))
  424. continue;
  425. }
  426. else
  427. {
  428. if (info->origin != type)
  429. continue;
  430. }
  431. XFREE(MTYPE_ISIS, rn->info);
  432. route_unlock_node(rn);
  433. }
  434. lsp_regenerate_schedule(area, level, 0);
  435. isis_redist_update_zebra_subscriptions(area->isis);
  436. }
  437. void
  438. isis_redist_area_finish(struct isis_area *area)
  439. {
  440. int protocol;
  441. int level;
  442. int type;
  443. for (protocol = 0; protocol < REDIST_PROTOCOL_COUNT; protocol++)
  444. for (level = 0; level < ISIS_LEVELS; level++)
  445. {
  446. for (type = 0; type < ZEBRA_ROUTE_MAX + 1; type++)
  447. {
  448. struct isis_redist *redist;
  449. redist = &area->redist_settings[protocol][type][level];
  450. redist->redist = 0;
  451. if (redist->map_name)
  452. XFREE(MTYPE_ISIS, redist->map_name);
  453. }
  454. route_table_finish(area->ext_reach[protocol][level]);
  455. }
  456. isis_redist_update_zebra_subscriptions(area->isis);
  457. }
  458. DEFUN(isis_redistribute,
  459. isis_redistribute_cmd,
  460. "redistribute (ipv4|ipv6) " QUAGGA_REDIST_STR_ISISD
  461. " (level-1|level-2) {metric <0-16777215>|route-map WORD}",
  462. REDIST_STR
  463. "Redistribute IPv4 routes\n"
  464. "Redistribute IPv6 routes\n"
  465. QUAGGA_REDIST_HELP_STR_ISISD
  466. "Redistribute into level-1\n"
  467. "Redistribute into level-2\n"
  468. "Metric for redistributed routes\n"
  469. "ISIS default metric\n"
  470. "Route map reference\n"
  471. "Pointer to route-map entries\n")
  472. {
  473. struct isis_area *area = vty->index;
  474. int family;
  475. int afi;
  476. int type;
  477. int level;
  478. unsigned long metric;
  479. const char *routemap;
  480. if (argc < 5)
  481. return CMD_WARNING;
  482. family = str2family(argv[0]);
  483. if (family < 0)
  484. return CMD_WARNING;
  485. afi = family2afi(family);
  486. if (!afi)
  487. return CMD_WARNING;
  488. type = proto_redistnum(afi, argv[1]);
  489. if (type < 0 || type == ZEBRA_ROUTE_ISIS)
  490. return CMD_WARNING;
  491. if (!strcmp("level-1", argv[2]))
  492. level = 1;
  493. else if (!strcmp("level-2", argv[2]))
  494. level = 2;
  495. else
  496. return CMD_WARNING;
  497. if ((area->is_type & level) != level)
  498. {
  499. vty_out(vty, "Node is not a level-%d IS%s", level, VTY_NEWLINE);
  500. return CMD_WARNING;
  501. }
  502. if (argv[3])
  503. {
  504. char *endp;
  505. metric = strtoul(argv[3], &endp, 10);
  506. if (argv[3][0] == '\0' || *endp != '\0')
  507. return CMD_WARNING;
  508. }
  509. else
  510. {
  511. metric = 0xffffffff;
  512. }
  513. routemap = argv[4];
  514. isis_redist_set(area, level, family, type, metric, routemap, 0);
  515. return 0;
  516. }
  517. DEFUN(no_isis_redistribute,
  518. no_isis_redistribute_cmd,
  519. "no redistribute (ipv4|ipv6) " QUAGGA_REDIST_STR_ISISD
  520. " (level-1|level-2)",
  521. NO_STR
  522. REDIST_STR
  523. "Redistribute IPv4 routes\n"
  524. "Redistribute IPv6 routes\n"
  525. QUAGGA_REDIST_HELP_STR_ISISD
  526. "Redistribute into level-1\n"
  527. "Redistribute into level-2\n")
  528. {
  529. struct isis_area *area = vty->index;
  530. int type;
  531. int level;
  532. int family;
  533. int afi;
  534. if (argc < 3)
  535. return CMD_WARNING;
  536. family = str2family(argv[0]);
  537. if (family < 0)
  538. return CMD_WARNING;
  539. afi = family2afi(family);
  540. if (!afi)
  541. return CMD_WARNING;
  542. type = proto_redistnum(afi, argv[1]);
  543. if (type < 0 || type == ZEBRA_ROUTE_ISIS)
  544. return CMD_WARNING;
  545. if (!strcmp("level-1", argv[2]))
  546. level = 1;
  547. else if (!strcmp("level-2", argv[2]))
  548. level = 2;
  549. else
  550. return CMD_WARNING;
  551. isis_redist_unset(area, level, family, type);
  552. return 0;
  553. }
  554. DEFUN(isis_default_originate,
  555. isis_default_originate_cmd,
  556. "default-information originate (ipv4|ipv6) (level-1|level-2) "
  557. "{always|metric <0-16777215>|route-map WORD}",
  558. "Control distribution of default information\n"
  559. "Distribute a default route\n"
  560. "Distribute default route for IPv4\n"
  561. "Distribute default route for IPv6\n"
  562. "Distribute default route into level-1\n"
  563. "Distribute default route into level-2\n"
  564. "Always advertise default route\n"
  565. "Metric for default route\n"
  566. "ISIS default metric\n"
  567. "Route map reference\n"
  568. "Pointer to route-map entries\n")
  569. {
  570. struct isis_area *area = vty->index;
  571. int family;
  572. int originate_type;
  573. int level;
  574. unsigned long metric;
  575. const char *routemap;
  576. if (argc < 5)
  577. return CMD_WARNING;
  578. family = str2family(argv[0]);
  579. if (family < 0)
  580. return CMD_WARNING;
  581. if (!strcmp("level-1", argv[1]))
  582. level = 1;
  583. else if (!strcmp("level-2", argv[1]))
  584. level = 2;
  585. else
  586. return CMD_WARNING;
  587. if ((area->is_type & level) != level)
  588. {
  589. vty_out(vty, "Node is not a level-%d IS%s", level, VTY_NEWLINE);
  590. return CMD_WARNING;
  591. }
  592. if (argv[2] && *argv[2] != '\0')
  593. originate_type = DEFAULT_ORIGINATE_ALWAYS;
  594. else
  595. originate_type = DEFAULT_ORIGINATE;
  596. if (family == AF_INET6 && originate_type != DEFAULT_ORIGINATE_ALWAYS)
  597. {
  598. vty_out(vty, "Zebra doesn't implement default-originate for IPv6 yet%s", VTY_NEWLINE);
  599. vty_out(vty, "so use with care or use default-originate always.%s", VTY_NEWLINE);
  600. }
  601. if (argv[3])
  602. {
  603. char *endp;
  604. metric = strtoul(argv[3], &endp, 10);
  605. if (argv[3][0] == '\0' || *endp != '\0')
  606. return CMD_WARNING;
  607. }
  608. else
  609. {
  610. metric = 0xffffffff;
  611. }
  612. routemap = argv[4];
  613. isis_redist_set(area, level, family, DEFAULT_ROUTE, metric, routemap, originate_type);
  614. return 0;
  615. }
  616. DEFUN(no_isis_default_originate,
  617. no_isis_default_originate_cmd,
  618. "no default-information originate (ipv4|ipv6) (level-1|level-2)",
  619. NO_STR
  620. "Control distribution of default information\n"
  621. "Distribute a default route\n"
  622. "Distribute default route for IPv4\n"
  623. "Distribute default route for IPv6\n"
  624. "Distribute default route into level-1\n"
  625. "Distribute default route into level-2\n")
  626. {
  627. struct isis_area *area = vty->index;
  628. int family;
  629. int level;
  630. if (argc < 2)
  631. return CMD_WARNING;
  632. family = str2family(argv[0]);
  633. if (family < 0)
  634. return CMD_WARNING;
  635. if (!strcmp("level-1", argv[1]))
  636. level = 1;
  637. else if (!strcmp("level-2", argv[1]))
  638. level = 2;
  639. else
  640. return CMD_WARNING;
  641. isis_redist_unset(area, level, family, DEFAULT_ROUTE);
  642. return 0;
  643. }
  644. int
  645. isis_redist_config_write(struct vty *vty, struct isis_area *area,
  646. int family)
  647. {
  648. int type;
  649. int level;
  650. int write = 0;
  651. struct isis_redist *redist;
  652. const char *family_str;
  653. if (family == AF_INET)
  654. family_str = "ipv4";
  655. else if (family == AF_INET6)
  656. family_str = "ipv6";
  657. else
  658. return 0;
  659. for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
  660. {
  661. if (type == ZEBRA_ROUTE_ISIS)
  662. continue;
  663. for (level = 1; level <= ISIS_LEVELS; level++)
  664. {
  665. redist = get_redist_settings(area, family, type, level);
  666. if (!redist->redist)
  667. continue;
  668. vty_out(vty, " redistribute %s %s level-%d",
  669. family_str, zebra_route_string(type), level);
  670. if (redist->metric != 0xffffffff)
  671. vty_out(vty, " metric %u", redist->metric);
  672. if (redist->map_name)
  673. vty_out(vty, " route-map %s", redist->map_name);
  674. vty_out(vty, "%s", VTY_NEWLINE);
  675. write++;
  676. }
  677. }
  678. for (level = 1; level <= ISIS_LEVELS; level++)
  679. {
  680. redist = get_redist_settings(area, family, DEFAULT_ROUTE, level);
  681. if (!redist->redist)
  682. continue;
  683. vty_out(vty, " default-information originate %s level-%d",
  684. family_str, level);
  685. if (redist->redist == DEFAULT_ORIGINATE_ALWAYS)
  686. vty_out(vty, " always");
  687. if (redist->metric != 0xffffffff)
  688. vty_out(vty, " metric %u", redist->metric);
  689. if (redist->map_name)
  690. vty_out(vty, " route-map %s", redist->map_name);
  691. vty_out(vty, "%s", VTY_NEWLINE);
  692. write++;
  693. }
  694. return write;
  695. }
  696. void
  697. isis_redist_init(void)
  698. {
  699. install_element(ISIS_NODE, &isis_redistribute_cmd);
  700. install_element(ISIS_NODE, &no_isis_redistribute_cmd);
  701. install_element(ISIS_NODE, &isis_default_originate_cmd);
  702. install_element(ISIS_NODE, &no_isis_default_originate_cmd);
  703. }