zebra_rnh.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630
  1. /* Zebra next hop tracking code
  2. * Copyright (C) 2013 Cumulus Networks, Inc.
  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 Free
  18. * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
  19. * 02111-1307, USA.
  20. */
  21. #include <zebra.h>
  22. #include "prefix.h"
  23. #include "table.h"
  24. #include "memory.h"
  25. #include "str.h"
  26. #include "command.h"
  27. #include "if.h"
  28. #include "log.h"
  29. #include "sockunion.h"
  30. #include "linklist.h"
  31. #include "thread.h"
  32. #include "workqueue.h"
  33. #include "prefix.h"
  34. #include "routemap.h"
  35. #include "stream.h"
  36. #include "nexthop.h"
  37. #include "zebra/rib.h"
  38. #include "zebra/rt.h"
  39. #include "zebra/zserv.h"
  40. #include "zebra/redistribute.h"
  41. #include "zebra/debug.h"
  42. #include "zebra/zebra_rnh.h"
  43. #define lookup_rnh_table(v, f) \
  44. ({ \
  45. struct zebra_vrf *zvrf; \
  46. struct route_table *t = NULL; \
  47. zvrf = zebra_vrf_lookup(v); \
  48. if (zvrf) \
  49. t = zvrf->rnh_table[family2afi(f)]; \
  50. t; \
  51. })
  52. static void free_state(struct rib *rib);
  53. static void copy_state(struct rnh *rnh, struct rib *rib);
  54. static int compare_state(struct rib *r1, struct rib *r2);
  55. static int send_client(struct rnh *rnh, struct zserv *client, vrf_id_t vrf_id);
  56. static void print_rnh(struct route_node *rn, struct vty *vty);
  57. char *
  58. rnh_str (struct rnh *rnh, char *buf, int size)
  59. {
  60. prefix2str(&(rnh->node->p), buf, size);
  61. return buf;
  62. }
  63. struct rnh *
  64. zebra_add_rnh (struct prefix *p, vrf_id_t vrfid)
  65. {
  66. struct route_table *table;
  67. struct route_node *rn;
  68. struct rnh *rnh = NULL;
  69. if (IS_ZEBRA_DEBUG_NHT)
  70. {
  71. char buf[INET6_ADDRSTRLEN];
  72. prefix2str(p, buf, INET6_ADDRSTRLEN);
  73. zlog_debug("add rnh %s in vrf %d", buf, vrfid);
  74. }
  75. table = lookup_rnh_table(vrfid, PREFIX_FAMILY(p));
  76. if (!table)
  77. {
  78. zlog_debug("add_rnh: rnh table not found\n");
  79. return NULL;
  80. }
  81. /* Make it sure prefixlen is applied to the prefix. */
  82. apply_mask (p);
  83. /* Lookup (or add) route node.*/
  84. rn = route_node_get (table, p);
  85. if (!rn->info)
  86. {
  87. rnh = XCALLOC(MTYPE_RNH, sizeof(struct rnh));
  88. rnh->client_list = list_new();
  89. route_lock_node (rn);
  90. rn->info = rnh;
  91. rnh->node = rn;
  92. }
  93. route_unlock_node (rn);
  94. return (rn->info);
  95. }
  96. struct rnh *
  97. zebra_lookup_rnh (struct prefix *p, vrf_id_t vrfid)
  98. {
  99. struct route_table *table;
  100. struct route_node *rn;
  101. table = lookup_rnh_table(vrfid, PREFIX_FAMILY(p));
  102. if (!table)
  103. return NULL;
  104. /* Make it sure prefixlen is applied to the prefix. */
  105. apply_mask (p);
  106. /* Lookup route node.*/
  107. rn = route_node_lookup (table, p);
  108. if (!rn)
  109. return NULL;
  110. route_unlock_node (rn);
  111. return (rn->info);
  112. }
  113. void
  114. zebra_delete_rnh (struct rnh *rnh)
  115. {
  116. struct route_node *rn;
  117. if (!rnh || !(rn = rnh->node))
  118. return;
  119. if (IS_ZEBRA_DEBUG_NHT)
  120. {
  121. char buf[INET6_ADDRSTRLEN];
  122. zlog_debug("delete rnh %s", rnh_str(rnh, buf, INET6_ADDRSTRLEN));
  123. }
  124. list_free(rnh->client_list);
  125. free_state(rnh->state);
  126. XFREE(MTYPE_RNH, rn->info);
  127. rn->info = NULL;
  128. route_unlock_node (rn);
  129. return;
  130. }
  131. void
  132. zebra_add_rnh_client (struct rnh *rnh, struct zserv *client, vrf_id_t vrf_id)
  133. {
  134. if (IS_ZEBRA_DEBUG_NHT)
  135. {
  136. char buf[INET6_ADDRSTRLEN];
  137. zlog_debug("client %s registers rnh %s",
  138. zebra_route_string(client->proto),
  139. rnh_str(rnh, buf, INET6_ADDRSTRLEN));
  140. }
  141. if (!listnode_lookup(rnh->client_list, client))
  142. {
  143. listnode_add(rnh->client_list, client);
  144. send_client(rnh, client, vrf_id);
  145. }
  146. }
  147. void
  148. zebra_remove_rnh_client (struct rnh *rnh, struct zserv *client)
  149. {
  150. if (IS_ZEBRA_DEBUG_NHT)
  151. {
  152. char buf[INET6_ADDRSTRLEN];
  153. zlog_debug("client %s unregisters rnh %s",
  154. zebra_route_string(client->proto),
  155. rnh_str(rnh, buf, INET6_ADDRSTRLEN));
  156. }
  157. listnode_delete(rnh->client_list, client);
  158. if (list_isempty(rnh->client_list))
  159. zebra_delete_rnh(rnh);
  160. }
  161. int
  162. zebra_evaluate_rnh_table (vrf_id_t vrfid, int family)
  163. {
  164. struct route_table *ptable;
  165. struct route_table *ntable;
  166. struct route_node *prn;
  167. struct route_node *nrn;
  168. struct rnh *rnh;
  169. struct zserv *client;
  170. struct listnode *node;
  171. struct rib *rib;
  172. ntable = lookup_rnh_table(vrfid, family);
  173. if (!ntable)
  174. {
  175. zlog_debug("evaluate_rnh_table: rnh table not found\n");
  176. return -1;
  177. }
  178. ptable = zebra_vrf_table(family2afi(family), SAFI_UNICAST, vrfid);
  179. if (!ptable)
  180. {
  181. zlog_debug("evaluate_rnh_table: prefix table not found\n");
  182. return -1;
  183. }
  184. for (nrn = route_top (ntable); nrn; nrn = route_next (nrn))
  185. {
  186. if (!nrn->info)
  187. continue;
  188. rnh = nrn->info;
  189. prn = route_node_match(ptable, &nrn->p);
  190. if (!prn)
  191. rib = NULL;
  192. else
  193. {
  194. RNODE_FOREACH_RIB(prn, rib)
  195. {
  196. if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
  197. continue;
  198. if (! CHECK_FLAG (rib->status, RIB_ENTRY_SELECTED_FIB))
  199. continue;
  200. if (CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED))
  201. {
  202. if (rib->type == ZEBRA_ROUTE_CONNECT)
  203. break;
  204. if (rib->type == ZEBRA_ROUTE_NHRP)
  205. {
  206. struct nexthop *nexthop;
  207. for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
  208. if (nexthop->type == NEXTHOP_TYPE_IFINDEX ||
  209. nexthop->type == NEXTHOP_TYPE_IFNAME)
  210. break;
  211. if (nexthop)
  212. break;
  213. }
  214. }
  215. else
  216. break;
  217. }
  218. }
  219. if (compare_state(rib, rnh->state))
  220. {
  221. if (IS_ZEBRA_DEBUG_NHT)
  222. {
  223. char bufn[INET6_ADDRSTRLEN];
  224. char bufp[INET6_ADDRSTRLEN];
  225. prefix2str(&nrn->p, bufn, INET6_ADDRSTRLEN);
  226. if (prn)
  227. prefix2str(&prn->p, bufp, INET6_ADDRSTRLEN);
  228. else
  229. strcpy(bufp, "null");
  230. zlog_debug("rnh %s resolved through route %s - sending "
  231. "nexthop %s event to clients", bufn, bufp,
  232. rib ? "reachable" : "unreachable");
  233. }
  234. copy_state(rnh, rib);
  235. for (ALL_LIST_ELEMENTS_RO(rnh->client_list, node, client))
  236. send_client(rnh, client, vrfid);
  237. }
  238. }
  239. return 1;
  240. }
  241. int
  242. zebra_dispatch_rnh_table (vrf_id_t vrfid, int family, struct zserv *client)
  243. {
  244. struct route_table *ntable;
  245. struct route_node *nrn;
  246. struct rnh *rnh;
  247. ntable = lookup_rnh_table(vrfid, family);
  248. if (!ntable)
  249. {
  250. zlog_debug("dispatch_rnh_table: rnh table not found\n");
  251. return -1;
  252. }
  253. for (nrn = route_top (ntable); nrn; nrn = route_next (nrn))
  254. {
  255. if (!nrn->info)
  256. continue;
  257. rnh = nrn->info;
  258. if (IS_ZEBRA_DEBUG_NHT)
  259. {
  260. char bufn[INET6_ADDRSTRLEN];
  261. prefix2str(&nrn->p, bufn, INET6_ADDRSTRLEN);
  262. zlog_debug("rnh %s - sending nexthop %s event to client %s", bufn,
  263. rnh->state ? "reachable" : "unreachable",
  264. zebra_route_string(client->proto));
  265. }
  266. send_client(rnh, client, vrfid);
  267. }
  268. return 1;
  269. }
  270. void
  271. zebra_print_rnh_table (vrf_id_t vrfid, int af, struct vty *vty)
  272. {
  273. struct route_table *table;
  274. struct route_node *rn;
  275. table = lookup_rnh_table(vrfid, af);
  276. if (!table)
  277. {
  278. zlog_debug("print_rnhs: rnh table not found\n");
  279. return;
  280. }
  281. for (rn = route_top(table); rn; rn = route_next(rn))
  282. if (rn->info)
  283. print_rnh(rn, vty);
  284. }
  285. int
  286. zebra_cleanup_rnh_client (vrf_id_t vrfid, int family, struct zserv *client)
  287. {
  288. struct route_table *ntable;
  289. struct route_node *nrn;
  290. struct rnh *rnh;
  291. ntable = lookup_rnh_table(vrfid, family);
  292. if (!ntable)
  293. {
  294. zlog_debug("cleanup_rnh_client: rnh table not found\n");
  295. return -1;
  296. }
  297. for (nrn = route_top (ntable); nrn; nrn = route_next (nrn))
  298. {
  299. if (!nrn->info)
  300. continue;
  301. rnh = nrn->info;
  302. if (IS_ZEBRA_DEBUG_NHT)
  303. {
  304. char bufn[INET6_ADDRSTRLEN];
  305. prefix2str(&nrn->p, bufn, INET6_ADDRSTRLEN);
  306. zlog_debug("rnh %s - cleaning state for client %s", bufn,
  307. zebra_route_string(client->proto));
  308. }
  309. zebra_remove_rnh_client(rnh, client);
  310. }
  311. return 1;
  312. }
  313. /**
  314. * free_state - free up the rib structure associated with the rnh.
  315. */
  316. static void
  317. free_state (struct rib *rib)
  318. {
  319. struct nexthop *nexthop, *next;
  320. if (!rib)
  321. return;
  322. /* free RIB and nexthops */
  323. for (nexthop = rib->nexthop; nexthop; nexthop = next)
  324. {
  325. next = nexthop->next;
  326. nexthop_free (nexthop);
  327. }
  328. XFREE (MTYPE_RIB, rib);
  329. }
  330. /**
  331. * copy_nexthop - copy a nexthop to the rib structure.
  332. */
  333. static void
  334. rib_copy_nexthop (struct rib *state, struct nexthop *nh)
  335. {
  336. struct nexthop *nexthop;
  337. nexthop = nexthop_new();
  338. nexthop->flags = nh->flags;
  339. nexthop->type = nh->type;
  340. nexthop->ifindex = nh->ifindex;
  341. if (nh->ifname)
  342. nexthop->ifname = XSTRDUP(0, nh->ifname);
  343. memcpy(&(nexthop->gate), &(nh->gate), sizeof(union g_addr));
  344. memcpy(&(nexthop->src), &(nh->src), sizeof(union g_addr));
  345. rib_nexthop_add(state, nexthop);
  346. }
  347. static void
  348. copy_state (struct rnh *rnh, struct rib *rib)
  349. {
  350. struct rib *state;
  351. struct nexthop *nh;
  352. if (rnh->state)
  353. {
  354. free_state(rnh->state);
  355. rnh->state = NULL;
  356. }
  357. if (!rib)
  358. return;
  359. state = XCALLOC (MTYPE_RIB, sizeof (struct rib));
  360. state->type = rib->type;
  361. state->metric = rib->metric;
  362. for (nh = rib->nexthop; nh; nh = nh->next)
  363. rib_copy_nexthop(state, nh);
  364. rnh->state = state;
  365. }
  366. static int
  367. compare_state (struct rib *r1, struct rib *r2)
  368. {
  369. struct nexthop *nh1;
  370. struct nexthop *nh2;
  371. u_char found_nh = 0;
  372. if (!r1 && !r2)
  373. return 0;
  374. if ((!r1 && r2) || (r1 && !r2))
  375. return 1;
  376. if (r1->metric != r2->metric)
  377. return 1;
  378. if (r1->nexthop_num != r2->nexthop_num)
  379. return 1;
  380. /* We need to verify that the nexthops for r1 match the nexthops for r2.
  381. * Since it is possible for a rib entry to have the same nexthop multiple
  382. * times (Example: [a,a]) we need to keep track of which r2 nexthops we have
  383. * already used as a match against a r1 nexthop. We track this
  384. * via NEXTHOP_FLAG_MATCHED. Clear this flag for all r2 nexthops when you
  385. * are finished.
  386. *
  387. * TRUE: r1 [a,b], r2 [a,b]
  388. * TRUE: r1 [a,b], r2 [b,a]
  389. * FALSE: r1 [a,b], r2 [a,c]
  390. * FALSE: r1 [a,a], r2 [a,b]
  391. */
  392. for (nh1 = r1->nexthop; nh1; nh1 = nh1->next)
  393. {
  394. found_nh = 0;
  395. for (nh2 = r2->nexthop; nh2; nh2 = nh2->next)
  396. {
  397. if (CHECK_FLAG (nh2->flags, NEXTHOP_FLAG_MATCHED))
  398. continue;
  399. if (nexthop_same_no_recurse(nh1, nh2))
  400. {
  401. SET_FLAG (nh2->flags, NEXTHOP_FLAG_MATCHED);
  402. found_nh = 1;
  403. break;
  404. }
  405. }
  406. if (!found_nh)
  407. {
  408. for (nh2 = r2->nexthop; nh2; nh2 = nh2->next)
  409. if (CHECK_FLAG (nh2->flags, NEXTHOP_FLAG_MATCHED))
  410. UNSET_FLAG (nh2->flags, NEXTHOP_FLAG_MATCHED);
  411. return 1;
  412. }
  413. }
  414. for (nh2 = r2->nexthop; nh2; nh2 = nh2->next)
  415. if (CHECK_FLAG (nh2->flags, NEXTHOP_FLAG_MATCHED))
  416. UNSET_FLAG (nh2->flags, NEXTHOP_FLAG_MATCHED);
  417. return 0;
  418. }
  419. static int
  420. send_client (struct rnh *rnh, struct zserv *client, vrf_id_t vrf_id)
  421. {
  422. struct stream *s;
  423. struct rib *rib;
  424. unsigned long nump;
  425. u_char num;
  426. struct nexthop *nexthop;
  427. struct route_node *rn;
  428. rn = rnh->node;
  429. rib = rnh->state;
  430. /* Get output stream. */
  431. s = client->obuf;
  432. stream_reset (s);
  433. zserv_create_header (s, ZEBRA_NEXTHOP_UPDATE, vrf_id);
  434. stream_putw(s, rn->p.family);
  435. stream_put_prefix (s, &rn->p);
  436. if (rib)
  437. {
  438. stream_putl (s, rib->metric);
  439. num = 0;
  440. nump = stream_get_endp(s);
  441. stream_putc (s, 0);
  442. for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
  443. if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB) &&
  444. ! CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE) &&
  445. CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
  446. {
  447. stream_putc (s, nexthop->type);
  448. switch (nexthop->type)
  449. {
  450. case ZEBRA_NEXTHOP_IPV4:
  451. stream_put_in_addr (s, &nexthop->gate.ipv4);
  452. break;
  453. case ZEBRA_NEXTHOP_IFINDEX:
  454. case ZEBRA_NEXTHOP_IFNAME:
  455. stream_putl (s, nexthop->ifindex);
  456. break;
  457. case ZEBRA_NEXTHOP_IPV4_IFINDEX:
  458. case ZEBRA_NEXTHOP_IPV4_IFNAME:
  459. stream_put_in_addr (s, &nexthop->gate.ipv4);
  460. stream_putl (s, nexthop->ifindex);
  461. break;
  462. #ifdef HAVE_IPV6
  463. case ZEBRA_NEXTHOP_IPV6:
  464. stream_put (s, &nexthop->gate.ipv6, 16);
  465. break;
  466. case ZEBRA_NEXTHOP_IPV6_IFINDEX:
  467. case ZEBRA_NEXTHOP_IPV6_IFNAME:
  468. stream_put (s, &nexthop->gate.ipv6, 16);
  469. stream_putl (s, nexthop->ifindex);
  470. break;
  471. #endif /* HAVE_IPV6 */
  472. default:
  473. /* do nothing */
  474. break;
  475. }
  476. num++;
  477. }
  478. stream_putc_at (s, nump, num);
  479. }
  480. else
  481. {
  482. stream_putl (s, 0);
  483. stream_putc (s, 0);
  484. }
  485. stream_putw_at (s, 0, stream_get_endp (s));
  486. client->nh_last_upd_time = quagga_time(NULL);
  487. client->last_write_cmd = ZEBRA_NEXTHOP_UPDATE;
  488. return zebra_server_send_message(client);
  489. }
  490. static void
  491. print_nh (struct nexthop *nexthop, struct vty *vty)
  492. {
  493. char buf[BUFSIZ];
  494. switch (nexthop->type)
  495. {
  496. case NEXTHOP_TYPE_IPV4:
  497. case NEXTHOP_TYPE_IPV4_IFINDEX:
  498. vty_out (vty, " via %s", inet_ntoa (nexthop->gate.ipv4));
  499. if (nexthop->ifindex)
  500. vty_out (vty, ", %s", ifindex2ifname (nexthop->ifindex));
  501. break;
  502. case NEXTHOP_TYPE_IPV6:
  503. case NEXTHOP_TYPE_IPV6_IFINDEX:
  504. case NEXTHOP_TYPE_IPV6_IFNAME:
  505. vty_out (vty, " %s",
  506. inet_ntop (AF_INET6, &nexthop->gate.ipv6, buf, BUFSIZ));
  507. if (nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME)
  508. vty_out (vty, ", %s", nexthop->ifname);
  509. else if (nexthop->ifindex)
  510. vty_out (vty, ", via %s", ifindex2ifname (nexthop->ifindex));
  511. break;
  512. case NEXTHOP_TYPE_IFINDEX:
  513. vty_out (vty, " is directly connected, %s",
  514. ifindex2ifname (nexthop->ifindex));
  515. break;
  516. case NEXTHOP_TYPE_IFNAME:
  517. vty_out (vty, " is directly connected, %s", nexthop->ifname);
  518. break;
  519. case NEXTHOP_TYPE_BLACKHOLE:
  520. vty_out (vty, " is directly connected, Null0");
  521. break;
  522. default:
  523. break;
  524. }
  525. vty_out(vty, "%s", VTY_NEWLINE);
  526. }
  527. static void
  528. print_rnh (struct route_node *rn, struct vty *vty)
  529. {
  530. struct rnh *rnh;
  531. struct nexthop *nexthop;
  532. struct listnode *node;
  533. struct zserv *client;
  534. char buf[BUFSIZ];
  535. rnh = rn->info;
  536. vty_out(vty, "%s%s", inet_ntop(rn->p.family, &rn->p.u.prefix, buf, BUFSIZ),
  537. VTY_NEWLINE);
  538. if (rnh->state)
  539. {
  540. vty_out(vty, " resolved via %s%s",
  541. zebra_route_string(rnh->state->type), VTY_NEWLINE);
  542. for (nexthop = rnh->state->nexthop; nexthop; nexthop = nexthop->next)
  543. print_nh(nexthop, vty);
  544. }
  545. else
  546. vty_out(vty, " unresolved%s%s",
  547. CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED) ? "(Connected)" : "",
  548. VTY_NEWLINE);
  549. vty_out(vty, " Client list:");
  550. for (ALL_LIST_ELEMENTS_RO(rnh->client_list, node, client))
  551. vty_out(vty, " %s(fd %d)", zebra_route_string(client->proto),
  552. client->sock);
  553. vty_out(vty, "%s", VTY_NEWLINE);
  554. }