bgp_nht.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477
  1. /* BGP Nexthop tracking
  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 "command.h"
  23. #include "thread.h"
  24. #include "prefix.h"
  25. #include "zclient.h"
  26. #include "stream.h"
  27. #include "network.h"
  28. #include "log.h"
  29. #include "memory.h"
  30. #include "nexthop.h"
  31. #include "filter.h"
  32. #include "bgpd/bgpd.h"
  33. #include "bgpd/bgp_table.h"
  34. #include "bgpd/bgp_route.h"
  35. #include "bgpd/bgp_attr.h"
  36. #include "bgpd/bgp_nexthop.h"
  37. #include "bgpd/bgp_debug.h"
  38. #include "bgpd/bgp_nht.h"
  39. extern struct zclient *zclient;
  40. extern struct bgp_table *bgp_nexthop_cache_table[AFI_MAX];
  41. static void register_nexthop(struct bgp_nexthop_cache *bnc);
  42. static void unregister_nexthop (struct bgp_nexthop_cache *bnc);
  43. static void evaluate_paths(struct bgp_nexthop_cache *bnc);
  44. static int make_prefix(int afi, struct bgp_info *ri, struct prefix *p);
  45. static void path_nh_map(struct bgp_info *path, struct bgp_nexthop_cache *bnc,
  46. int keep);
  47. int
  48. bgp_find_nexthop (struct bgp_info *path, int *changed, int *metricchanged)
  49. {
  50. struct bgp_nexthop_cache *bnc = path->nexthop;
  51. if (!bnc)
  52. return 0;
  53. if (changed)
  54. *changed = CHECK_FLAG(bnc->change_flags, BGP_NEXTHOP_CHANGED);
  55. if (metricchanged)
  56. *metricchanged = CHECK_FLAG(bnc->change_flags,
  57. BGP_NEXTHOP_METRIC_CHANGED);
  58. return (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID));
  59. }
  60. void
  61. bgp_unlink_nexthop (struct bgp_info *path)
  62. {
  63. struct bgp_nexthop_cache *bnc = path->nexthop;
  64. if (!bnc)
  65. return;
  66. path_nh_map(path, NULL, 0);
  67. if (LIST_EMPTY(&(bnc->paths)))
  68. {
  69. if (BGP_DEBUG(nht, NHT))
  70. {
  71. char buf[INET6_ADDRSTRLEN];
  72. zlog_debug("bgp_unlink_nexthop: freeing bnc %s",
  73. bnc_str(bnc, buf, INET6_ADDRSTRLEN));
  74. }
  75. unregister_nexthop(bnc);
  76. bnc->node->info = NULL;
  77. bgp_unlock_node(bnc->node);
  78. bnc_free(bnc);
  79. }
  80. }
  81. int
  82. bgp_find_or_add_nexthop (afi_t afi, struct bgp_info *ri, int *changed,
  83. int *metricchanged)
  84. {
  85. struct bgp_node *rn;
  86. struct bgp_nexthop_cache *bnc;
  87. struct prefix p;
  88. if (make_prefix(afi, ri, &p) < 0)
  89. return 1;
  90. rn = bgp_node_get (bgp_nexthop_cache_table[afi], &p);
  91. if (!rn->info)
  92. {
  93. bnc = bnc_new();
  94. rn->info = bnc;
  95. bnc->node = rn;
  96. bgp_lock_node(rn);
  97. register_nexthop(bnc);
  98. }
  99. bnc = rn->info;
  100. bgp_unlock_node (rn);
  101. path_nh_map(ri, bnc, 1);
  102. if (changed)
  103. *changed = CHECK_FLAG(bnc->change_flags, BGP_NEXTHOP_CHANGED);
  104. if (metricchanged)
  105. *metricchanged = CHECK_FLAG(bnc->change_flags,
  106. BGP_NEXTHOP_METRIC_CHANGED);
  107. if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID) && bnc->metric)
  108. (bgp_info_extra_get(ri))->igpmetric = bnc->metric;
  109. else if (ri->extra)
  110. ri->extra->igpmetric = 0;
  111. return (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID));
  112. }
  113. void
  114. bgp_parse_nexthop_update (void)
  115. {
  116. struct stream *s;
  117. struct bgp_node *rn;
  118. struct bgp_nexthop_cache *bnc;
  119. struct nexthop *nexthop;
  120. struct nexthop *oldnh;
  121. struct nexthop *nhlist_head = NULL;
  122. struct nexthop *nhlist_tail = NULL;
  123. uint32_t metric;
  124. u_char nexthop_num;
  125. struct prefix p;
  126. int i;
  127. s = zclient->ibuf;
  128. memset(&p, 0, sizeof(struct prefix));
  129. p.family = stream_getw(s);
  130. p.prefixlen = stream_getc(s);
  131. switch (p.family)
  132. {
  133. case AF_INET:
  134. p.u.prefix4.s_addr = stream_get_ipv4 (s);
  135. break;
  136. case AF_INET6:
  137. stream_get(&p.u.prefix6, s, 16);
  138. break;
  139. default:
  140. break;
  141. }
  142. rn = bgp_node_lookup(bgp_nexthop_cache_table[family2afi(p.family)], &p);
  143. if (!rn || !rn->info)
  144. {
  145. if (BGP_DEBUG(nht, NHT))
  146. {
  147. char buf[INET6_ADDRSTRLEN];
  148. prefix2str(&p, buf, INET6_ADDRSTRLEN);
  149. zlog_debug("parse nexthop update(%s): rn not found", buf);
  150. }
  151. if (rn)
  152. bgp_unlock_node (rn);
  153. return;
  154. }
  155. bnc = rn->info;
  156. bgp_unlock_node (rn);
  157. bnc->last_update = bgp_clock();
  158. bnc->change_flags = 0;
  159. metric = stream_getl (s);
  160. nexthop_num = stream_getc (s);
  161. /* debug print the input */
  162. if (BGP_DEBUG(nht, NHT))
  163. {
  164. char buf[INET6_ADDRSTRLEN];
  165. prefix2str(&p, buf, INET6_ADDRSTRLEN);
  166. zlog_debug("parse nexthop update(%s): metric=%d, #nexthop=%d", buf,
  167. metric, nexthop_num);
  168. }
  169. if (metric != bnc->metric)
  170. bnc->change_flags |= BGP_NEXTHOP_METRIC_CHANGED;
  171. if(nexthop_num != bnc->nexthop_num)
  172. bnc->change_flags |= BGP_NEXTHOP_CHANGED;
  173. if (nexthop_num)
  174. {
  175. bnc->flags |= BGP_NEXTHOP_VALID;
  176. bnc->metric = metric;
  177. bnc->nexthop_num = nexthop_num;
  178. for (i = 0; i < nexthop_num; i++)
  179. {
  180. nexthop = nexthop_new();
  181. nexthop->type = stream_getc (s);
  182. switch (nexthop->type)
  183. {
  184. case ZEBRA_NEXTHOP_IPV4:
  185. nexthop->gate.ipv4.s_addr = stream_get_ipv4 (s);
  186. break;
  187. case ZEBRA_NEXTHOP_IFINDEX:
  188. case ZEBRA_NEXTHOP_IFNAME:
  189. nexthop->ifindex = stream_getl (s);
  190. break;
  191. case ZEBRA_NEXTHOP_IPV4_IFINDEX:
  192. case ZEBRA_NEXTHOP_IPV4_IFNAME:
  193. nexthop->gate.ipv4.s_addr = stream_get_ipv4 (s);
  194. nexthop->ifindex = stream_getl (s);
  195. break;
  196. #ifdef HAVE_IPV6
  197. case ZEBRA_NEXTHOP_IPV6:
  198. stream_get (&nexthop->gate.ipv6, s, 16);
  199. break;
  200. case ZEBRA_NEXTHOP_IPV6_IFINDEX:
  201. case ZEBRA_NEXTHOP_IPV6_IFNAME:
  202. stream_get (&nexthop->gate.ipv6, s, 16);
  203. nexthop->ifindex = stream_getl (s);
  204. break;
  205. #endif
  206. default:
  207. /* do nothing */
  208. break;
  209. }
  210. if (nhlist_tail)
  211. {
  212. nhlist_tail->next = nexthop;
  213. nhlist_tail = nexthop;
  214. }
  215. else
  216. {
  217. nhlist_tail = nexthop;
  218. nhlist_head = nexthop;
  219. }
  220. /* No need to evaluate the nexthop if we have already determined
  221. * that there has been a change.
  222. */
  223. if (bnc->change_flags & BGP_NEXTHOP_CHANGED)
  224. continue;
  225. for (oldnh = bnc->nexthop; oldnh; oldnh = oldnh->next)
  226. if (nexthop_same_no_recurse(oldnh, nexthop))
  227. break;
  228. if (!oldnh)
  229. bnc->change_flags |= BGP_NEXTHOP_CHANGED;
  230. }
  231. bnc_nexthop_free(bnc);
  232. bnc->nexthop = nhlist_head;
  233. }
  234. else
  235. {
  236. bnc->flags &= ~BGP_NEXTHOP_VALID;
  237. bnc_nexthop_free(bnc);
  238. bnc->nexthop = NULL;
  239. }
  240. evaluate_paths(bnc);
  241. }
  242. /**
  243. * make_prefix - make a prefix structure from the path (essentially
  244. * path's node.
  245. */
  246. static int
  247. make_prefix (int afi, struct bgp_info *ri, struct prefix *p)
  248. {
  249. memset (p, 0, sizeof (struct prefix));
  250. switch (afi)
  251. {
  252. case AFI_IP:
  253. p->family = AF_INET;
  254. p->prefixlen = IPV4_MAX_BITLEN;
  255. p->u.prefix4 = ri->attr->nexthop;
  256. break;
  257. #ifdef HAVE_IPV6
  258. case AFI_IP6:
  259. if (ri->attr->extra->mp_nexthop_len != 16
  260. || IN6_IS_ADDR_LINKLOCAL (&ri->attr->extra->mp_nexthop_global))
  261. return -1;
  262. p->family = AF_INET6;
  263. p->prefixlen = IPV6_MAX_BITLEN;
  264. p->u.prefix6 = ri->attr->extra->mp_nexthop_global;
  265. break;
  266. #endif
  267. default:
  268. break;
  269. }
  270. return 0;
  271. }
  272. /**
  273. * sendmsg_nexthop -- Format and send a nexthop register/Unregister
  274. * command to Zebra.
  275. * ARGUMENTS:
  276. * struct bgp_nexthop_cache *bnc -- the nexthop structure.
  277. * int command -- either ZEBRA_NEXTHOP_REGISTER or ZEBRA_NEXTHOP_UNREGISTER
  278. * RETURNS:
  279. * void.
  280. */
  281. static void
  282. sendmsg_nexthop (struct bgp_nexthop_cache *bnc, int command)
  283. {
  284. struct stream *s;
  285. struct prefix *p;
  286. int ret;
  287. /* Check socket. */
  288. if (!zclient || zclient->sock < 0)
  289. return;
  290. p = &(bnc->node->p);
  291. s = zclient->obuf;
  292. stream_reset (s);
  293. zclient_create_header (s, command, VRF_DEFAULT);
  294. stream_putw(s, PREFIX_FAMILY(p));
  295. stream_putc(s, p->prefixlen);
  296. switch (PREFIX_FAMILY(p))
  297. {
  298. case AF_INET:
  299. stream_put_in_addr (s, &p->u.prefix4);
  300. break;
  301. #ifdef HAVE_IPV6
  302. case AF_INET6:
  303. stream_put(s, &(p->u.prefix6), 16);
  304. break;
  305. #endif
  306. default:
  307. break;
  308. }
  309. stream_putw_at (s, 0, stream_get_endp (s));
  310. ret = zclient_send_message(zclient);
  311. /* TBD: handle the failure */
  312. if (ret < 0)
  313. zlog_warn("sendmsg_nexthop: zclient_send_message() failed");
  314. return;
  315. }
  316. /**
  317. * register_nexthop - register a nexthop with Zebra for notification
  318. * when the route to the nexthop changes.
  319. * ARGUMENTS:
  320. * struct bgp_nexthop_cache *bnc -- the nexthop structure.
  321. * RETURNS:
  322. * void.
  323. */
  324. static void
  325. register_nexthop (struct bgp_nexthop_cache *bnc)
  326. {
  327. /* Check if we have already registered */
  328. if (bnc->flags & BGP_NEXTHOP_REGISTERED)
  329. return;
  330. sendmsg_nexthop(bnc, ZEBRA_NEXTHOP_REGISTER);
  331. SET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED);
  332. }
  333. /**
  334. * unregister_nexthop -- Unregister the nexthop from Zebra.
  335. * ARGUMENTS:
  336. * struct bgp_nexthop_cache *bnc -- the nexthop structure.
  337. * RETURNS:
  338. * void.
  339. */
  340. static void
  341. unregister_nexthop (struct bgp_nexthop_cache *bnc)
  342. {
  343. /* Check if we have already registered */
  344. if (!CHECK_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED))
  345. return;
  346. sendmsg_nexthop(bnc, ZEBRA_NEXTHOP_UNREGISTER);
  347. UNSET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED);
  348. }
  349. /**
  350. * evaluate_paths - Evaluate the paths/nets associated with a nexthop.
  351. * ARGUMENTS:
  352. * struct bgp_nexthop_cache *bnc -- the nexthop structure.
  353. * RETURNS:
  354. * void.
  355. */
  356. static void
  357. evaluate_paths (struct bgp_nexthop_cache *bnc)
  358. {
  359. struct bgp_node *rn;
  360. struct bgp_info *path;
  361. struct bgp *bgp = bgp_get_default();
  362. int afi;
  363. LIST_FOREACH(path, &(bnc->paths), nh_thread)
  364. {
  365. if (!(path->type == ZEBRA_ROUTE_BGP &&
  366. path->sub_type == BGP_ROUTE_NORMAL))
  367. continue;
  368. rn = path->net;
  369. afi = family2afi(rn->p.family);
  370. /* Path becomes valid/invalid depending on whether the nexthop
  371. * reachable/unreachable.
  372. */
  373. if ((CHECK_FLAG(path->flags, BGP_INFO_VALID) ? 1 : 0) !=
  374. (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID) ? 1 : 0))
  375. {
  376. if (CHECK_FLAG (path->flags, BGP_INFO_VALID))
  377. {
  378. bgp_aggregate_decrement (bgp, &rn->p, path,
  379. afi, SAFI_UNICAST);
  380. bgp_info_unset_flag (rn, path, BGP_INFO_VALID);
  381. }
  382. else
  383. {
  384. bgp_info_set_flag (rn, path, BGP_INFO_VALID);
  385. bgp_aggregate_increment (bgp, &rn->p, path,
  386. afi, SAFI_UNICAST);
  387. }
  388. }
  389. /* Copy the metric to the path. Will be used for bestpath computation */
  390. if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID) && bnc->metric)
  391. (bgp_info_extra_get(path))->igpmetric = bnc->metric;
  392. else if (path->extra)
  393. path->extra->igpmetric = 0;
  394. if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_METRIC_CHANGED) ||
  395. CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CHANGED))
  396. SET_FLAG(path->flags, BGP_INFO_IGP_CHANGED);
  397. bgp_process(bgp, rn, afi, SAFI_UNICAST);
  398. }
  399. RESET_FLAG(bnc->change_flags);
  400. }
  401. /**
  402. * path_nh_map - make or break path-to-nexthop association.
  403. * ARGUMENTS:
  404. * path - pointer to the path structure
  405. * bnc - pointer to the nexthop structure
  406. * make - if set, make the association. if unset, just break the existing
  407. * association.
  408. */
  409. static void
  410. path_nh_map (struct bgp_info *path, struct bgp_nexthop_cache *bnc, int make)
  411. {
  412. if (path->nexthop)
  413. {
  414. LIST_REMOVE(path, nh_thread);
  415. path->nexthop->path_count--;
  416. path->nexthop = NULL;
  417. }
  418. if (make)
  419. {
  420. LIST_INSERT_HEAD(&(bnc->paths), path, nh_thread);
  421. path->nexthop = bnc;
  422. path->nexthop->path_count++;
  423. }
  424. }