bgp_mpath.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799
  1. /* $QuaggaId: Format:%an, %ai, %h$ $
  2. *
  3. * BGP Multipath
  4. * Copyright (C) 2010 Google Inc.
  5. *
  6. * This file is part of Quagga
  7. *
  8. * Quagga is free software; you can redistribute it and/or modify it
  9. * under the terms of the GNU General Public License as published by the
  10. * Free Software Foundation; either version 2, or (at your option) any
  11. * later version.
  12. *
  13. * Quagga is distributed in the hope that it will be useful, but
  14. * WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16. * General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with Quagga; see the file COPYING. If not, write to the Free
  20. * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
  21. * 02111-1307, USA.
  22. */
  23. #include <zebra.h>
  24. #include "command.h"
  25. #include "prefix.h"
  26. #include "linklist.h"
  27. #include "sockunion.h"
  28. #include "memory.h"
  29. #include "filter.h"
  30. #include "bgpd/bgpd.h"
  31. #include "bgpd/bgp_table.h"
  32. #include "bgpd/bgp_route.h"
  33. #include "bgpd/bgp_attr.h"
  34. #include "bgpd/bgp_debug.h"
  35. #include "bgpd/bgp_aspath.h"
  36. #include "bgpd/bgp_community.h"
  37. #include "bgpd/bgp_ecommunity.h"
  38. #include "bgpd/bgp_lcommunity.h"
  39. #include "bgpd/bgp_mpath.h"
  40. bool
  41. bgp_mpath_is_configured_sort (struct bgp *bgp, bgp_peer_sort_t sort,
  42. afi_t afi, safi_t safi)
  43. {
  44. struct bgp_maxpaths_cfg *cfg = &bgp->maxpaths[afi][safi];
  45. /* XXX: BGP_DEFAULT_MAXPATHS is 1, and this test only seems to make sense
  46. * if if it stays 1, so not sure the DEFAULT define is that useful.
  47. */
  48. switch (sort)
  49. {
  50. case BGP_PEER_IBGP:
  51. return cfg->maxpaths_ibgp != BGP_DEFAULT_MAXPATHS;
  52. case BGP_PEER_EBGP:
  53. return cfg->maxpaths_ebgp != BGP_DEFAULT_MAXPATHS;
  54. default:
  55. return false;
  56. }
  57. }
  58. bool
  59. bgp_mpath_is_configured (struct bgp *bgp, afi_t afi, safi_t safi)
  60. {
  61. return bgp_mpath_is_configured_sort (bgp, BGP_PEER_IBGP, afi, safi)
  62. || bgp_mpath_is_configured_sort (bgp, BGP_PEER_EBGP, afi, safi);
  63. }
  64. /*
  65. * bgp_maximum_paths_set
  66. *
  67. * Record maximum-paths configuration for BGP instance
  68. */
  69. int
  70. bgp_maximum_paths_set (struct bgp *bgp, afi_t afi, safi_t safi,
  71. int peertype, u_int16_t maxpaths)
  72. {
  73. if (!bgp || (afi >= AFI_MAX) || (safi >= SAFI_MAX))
  74. return -1;
  75. switch (peertype)
  76. {
  77. case BGP_PEER_IBGP:
  78. bgp->maxpaths[afi][safi].maxpaths_ibgp = maxpaths;
  79. break;
  80. case BGP_PEER_EBGP:
  81. bgp->maxpaths[afi][safi].maxpaths_ebgp = maxpaths;
  82. break;
  83. default:
  84. return -1;
  85. }
  86. return 0;
  87. }
  88. /*
  89. * bgp_maximum_paths_unset
  90. *
  91. * Remove maximum-paths configuration from BGP instance
  92. */
  93. int
  94. bgp_maximum_paths_unset (struct bgp *bgp, afi_t afi, safi_t safi,
  95. int peertype)
  96. {
  97. if (!bgp || (afi >= AFI_MAX) || (safi >= SAFI_MAX))
  98. return -1;
  99. switch (peertype)
  100. {
  101. case BGP_PEER_IBGP:
  102. bgp->maxpaths[afi][safi].maxpaths_ibgp = BGP_DEFAULT_MAXPATHS;
  103. break;
  104. case BGP_PEER_EBGP:
  105. bgp->maxpaths[afi][safi].maxpaths_ebgp = BGP_DEFAULT_MAXPATHS;
  106. break;
  107. default:
  108. return -1;
  109. }
  110. return 0;
  111. }
  112. /*
  113. * bgp_info_nexthop_cmp
  114. *
  115. * Compare the nexthops of two paths. Return value is less than, equal to,
  116. * or greater than zero if bi1 is respectively less than, equal to,
  117. * or greater than bi2.
  118. */
  119. static int
  120. bgp_info_nexthop_cmp (struct bgp_info *bi1, struct bgp_info *bi2)
  121. {
  122. struct attr_extra *ae1, *ae2;
  123. int compare;
  124. ae1 = bi1->attr->extra;
  125. ae2 = bi2->attr->extra;
  126. compare = IPV4_ADDR_CMP (&bi1->attr->nexthop, &bi2->attr->nexthop);
  127. if (!compare && ae1 && ae2)
  128. {
  129. if (ae1->mp_nexthop_len == ae2->mp_nexthop_len)
  130. {
  131. switch (ae1->mp_nexthop_len)
  132. {
  133. case 4:
  134. case 12:
  135. compare = IPV4_ADDR_CMP (&ae1->mp_nexthop_global_in,
  136. &ae2->mp_nexthop_global_in);
  137. break;
  138. case 16:
  139. compare = IPV6_ADDR_CMP (&ae1->mp_nexthop_global,
  140. &ae2->mp_nexthop_global);
  141. break;
  142. case 32:
  143. compare = IPV6_ADDR_CMP (&ae1->mp_nexthop_global,
  144. &ae2->mp_nexthop_global);
  145. if (!compare)
  146. compare = IPV6_ADDR_CMP (&ae1->mp_nexthop_local,
  147. &ae2->mp_nexthop_local);
  148. break;
  149. }
  150. }
  151. /* This can happen if one IPv6 peer sends you global and link-local
  152. * nexthops but another IPv6 peer only sends you global
  153. */
  154. else if (ae1->mp_nexthop_len == 16 || ae1->mp_nexthop_len == 32)
  155. {
  156. compare = IPV6_ADDR_CMP (&ae1->mp_nexthop_global,
  157. &ae2->mp_nexthop_global);
  158. if (!compare)
  159. {
  160. if (ae1->mp_nexthop_len < ae2->mp_nexthop_len)
  161. compare = -1;
  162. else
  163. compare = 1;
  164. }
  165. }
  166. }
  167. return compare;
  168. }
  169. /*
  170. * bgp_info_mpath_cmp
  171. *
  172. * This function determines our multipath list ordering. By ordering
  173. * the list we can deterministically select which paths are included
  174. * in the multipath set. The ordering also helps in detecting changes
  175. * in the multipath selection so we can detect whether to send an
  176. * update to zebra.
  177. *
  178. * The order of paths is determined first by received nexthop, and then
  179. * by peer address if the nexthops are the same.
  180. */
  181. static int
  182. bgp_info_mpath_cmp (void *val1, void *val2)
  183. {
  184. struct bgp_info *bi1, *bi2;
  185. int compare;
  186. bi1 = val1;
  187. bi2 = val2;
  188. compare = bgp_info_nexthop_cmp (bi1, bi2);
  189. if (!compare)
  190. compare = sockunion_cmp (bi1->peer->su_remote, bi2->peer->su_remote);
  191. return compare;
  192. }
  193. /*
  194. * bgp_mp_list_init
  195. *
  196. * Initialize the mp_list, which holds the list of multipaths
  197. * selected by bgp_best_selection
  198. */
  199. void
  200. bgp_mp_list_init (struct list *mp_list)
  201. {
  202. assert (mp_list);
  203. memset (mp_list, 0, sizeof (struct list));
  204. mp_list->cmp = bgp_info_mpath_cmp;
  205. }
  206. /*
  207. * bgp_mp_list_clear
  208. *
  209. * Clears all entries out of the mp_list
  210. */
  211. void
  212. bgp_mp_list_clear (struct list *mp_list)
  213. {
  214. assert (mp_list);
  215. list_delete_all_node (mp_list);
  216. }
  217. /*
  218. * bgp_mp_list_add
  219. *
  220. * Adds a multipath entry to the mp_list
  221. */
  222. void
  223. bgp_mp_list_add (struct list *mp_list, struct bgp_info *mpinfo)
  224. {
  225. assert (mp_list && mpinfo);
  226. listnode_add_sort (mp_list, mpinfo);
  227. }
  228. /*
  229. * bgp_info_mpath_new
  230. *
  231. * Allocate and zero memory for a new bgp_info_mpath element
  232. */
  233. static struct bgp_info_mpath *
  234. bgp_info_mpath_new (void)
  235. {
  236. struct bgp_info_mpath *new_mpath;
  237. new_mpath = XCALLOC (MTYPE_BGP_MPATH_INFO, sizeof (struct bgp_info_mpath));
  238. return new_mpath;
  239. }
  240. /*
  241. * bgp_info_mpath_free
  242. *
  243. * Release resources for a bgp_info_mpath element and zero out pointer
  244. */
  245. void
  246. bgp_info_mpath_free (struct bgp_info_mpath **mpath)
  247. {
  248. if (mpath && *mpath)
  249. {
  250. if ((*mpath)->mp_attr)
  251. bgp_attr_unintern (&(*mpath)->mp_attr);
  252. XFREE (MTYPE_BGP_MPATH_INFO, *mpath);
  253. *mpath = NULL;
  254. }
  255. }
  256. /*
  257. * bgp_info_mpath_get
  258. *
  259. * Fetch the mpath element for the given bgp_info. Used for
  260. * doing lazy allocation.
  261. */
  262. static struct bgp_info_mpath *
  263. bgp_info_mpath_get (struct bgp_info *binfo)
  264. {
  265. struct bgp_info_mpath *mpath;
  266. if (!binfo->mpath)
  267. {
  268. mpath = bgp_info_mpath_new();
  269. if (!mpath)
  270. return NULL;
  271. binfo->mpath = mpath;
  272. mpath->mp_info = binfo;
  273. }
  274. return binfo->mpath;
  275. }
  276. /*
  277. * bgp_info_mpath_enqueue
  278. *
  279. * Enqueue a path onto the multipath list given the previous multipath
  280. * list entry
  281. */
  282. static void
  283. bgp_info_mpath_enqueue (struct bgp_info *prev_info, struct bgp_info *binfo)
  284. {
  285. struct bgp_info_mpath *prev, *mpath;
  286. prev = bgp_info_mpath_get (prev_info);
  287. mpath = bgp_info_mpath_get (binfo);
  288. if (!prev || !mpath)
  289. return;
  290. mpath->mp_next = prev->mp_next;
  291. mpath->mp_prev = prev;
  292. if (prev->mp_next)
  293. prev->mp_next->mp_prev = mpath;
  294. prev->mp_next = mpath;
  295. SET_FLAG (binfo->flags, BGP_INFO_MULTIPATH);
  296. }
  297. /*
  298. * bgp_info_mpath_dequeue
  299. *
  300. * Remove a path from the multipath list
  301. */
  302. void
  303. bgp_info_mpath_dequeue (struct bgp_info *binfo)
  304. {
  305. struct bgp_info_mpath *mpath = binfo->mpath;
  306. if (!mpath)
  307. return;
  308. if (mpath->mp_prev)
  309. mpath->mp_prev->mp_next = mpath->mp_next;
  310. if (mpath->mp_next)
  311. mpath->mp_next->mp_prev = mpath->mp_prev;
  312. mpath->mp_next = mpath->mp_prev = NULL;
  313. UNSET_FLAG (binfo->flags, BGP_INFO_MULTIPATH);
  314. }
  315. /*
  316. * bgp_info_mpath_next
  317. *
  318. * Given a bgp_info, return the next multipath entry
  319. */
  320. struct bgp_info *
  321. bgp_info_mpath_next (struct bgp_info *binfo)
  322. {
  323. if (!binfo->mpath || !binfo->mpath->mp_next)
  324. return NULL;
  325. return binfo->mpath->mp_next->mp_info;
  326. }
  327. /*
  328. * bgp_info_mpath_first
  329. *
  330. * Given bestpath bgp_info, return the first multipath entry.
  331. */
  332. struct bgp_info *
  333. bgp_info_mpath_first (struct bgp_info *binfo)
  334. {
  335. return bgp_info_mpath_next (binfo);
  336. }
  337. /*
  338. * bgp_info_mpath_count
  339. *
  340. * Given the bestpath bgp_info, return the number of multipath entries
  341. */
  342. u_int32_t
  343. bgp_info_mpath_count (struct bgp_info *binfo)
  344. {
  345. if (!binfo->mpath)
  346. return 0;
  347. return binfo->mpath->mp_count;
  348. }
  349. /*
  350. * bgp_info_mpath_count_set
  351. *
  352. * Sets the count of multipaths into bestpath's mpath element
  353. */
  354. static void
  355. bgp_info_mpath_count_set (struct bgp_info *binfo, u_int32_t count)
  356. {
  357. struct bgp_info_mpath *mpath;
  358. if (!count && !binfo->mpath)
  359. return;
  360. mpath = bgp_info_mpath_get (binfo);
  361. if (!mpath)
  362. return;
  363. mpath->mp_count = count;
  364. }
  365. /*
  366. * bgp_info_mpath_attr
  367. *
  368. * Given bestpath bgp_info, return aggregated attribute set used
  369. * for advertising the multipath route
  370. */
  371. struct attr *
  372. bgp_info_mpath_attr (struct bgp_info *binfo)
  373. {
  374. if (!binfo->mpath)
  375. return NULL;
  376. return binfo->mpath->mp_attr;
  377. }
  378. /*
  379. * bgp_info_mpath_attr_set
  380. *
  381. * Sets the aggregated attribute into bestpath's mpath element
  382. */
  383. static void
  384. bgp_info_mpath_attr_set (struct bgp_info *binfo, struct attr *attr)
  385. {
  386. struct bgp_info_mpath *mpath;
  387. if (!attr && !binfo->mpath)
  388. return;
  389. mpath = bgp_info_mpath_get (binfo);
  390. if (!mpath)
  391. return;
  392. mpath->mp_attr = attr;
  393. }
  394. /*
  395. * bgp_info_mpath_update
  396. *
  397. * Compare and sync up the multipath list with the mp_list generated by
  398. * bgp_best_selection
  399. */
  400. void
  401. bgp_info_mpath_update (struct bgp_node *rn, struct bgp_info *new_best,
  402. struct bgp_info *old_best, struct list *mp_list,
  403. afi_t afi, safi_t safi)
  404. {
  405. u_int16_t maxpaths, mpath_count, old_mpath_count;
  406. struct listnode *mp_node, *mp_next_node;
  407. struct bgp_info *cur_mpath, *new_mpath, *next_mpath, *prev_mpath;
  408. int mpath_changed, debug;
  409. char pfx_buf[INET6_ADDRSTRLEN], nh_buf[2][INET6_ADDRSTRLEN];
  410. struct bgp_maxpaths_cfg *mpath_cfg = NULL;
  411. mpath_changed = 0;
  412. maxpaths = BGP_DEFAULT_MAXPATHS;
  413. mpath_count = 0;
  414. cur_mpath = NULL;
  415. old_mpath_count = 0;
  416. prev_mpath = new_best;
  417. mp_node = listhead (mp_list);
  418. debug = BGP_DEBUG (events, EVENTS);
  419. if (debug)
  420. prefix2str (&rn->p, pfx_buf, sizeof (pfx_buf));
  421. if (new_best)
  422. {
  423. mpath_cfg = &new_best->peer->bgp->maxpaths[afi][safi];
  424. mpath_count++;
  425. if (new_best != old_best)
  426. bgp_info_mpath_dequeue (new_best);
  427. maxpaths = (new_best->peer->sort == BGP_PEER_IBGP) ?
  428. mpath_cfg->maxpaths_ibgp : mpath_cfg->maxpaths_ebgp;
  429. }
  430. if (old_best)
  431. {
  432. cur_mpath = bgp_info_mpath_first (old_best);
  433. old_mpath_count = bgp_info_mpath_count (old_best);
  434. bgp_info_mpath_count_set (old_best, 0);
  435. bgp_info_mpath_dequeue (old_best);
  436. }
  437. /*
  438. * We perform an ordered walk through both lists in parallel.
  439. * The reason for the ordered walk is that if there are paths
  440. * that were previously multipaths and are still multipaths, the walk
  441. * should encounter them in both lists at the same time. Otherwise
  442. * there will be paths that are in one list or another, and we
  443. * will deal with these separately.
  444. *
  445. * Note that new_best might be somewhere in the mp_list, so we need
  446. * to skip over it
  447. */
  448. while (mp_node || cur_mpath)
  449. {
  450. /*
  451. * We can bail out of this loop if all existing paths on the
  452. * multipath list have been visited (for cleanup purposes) and
  453. * the maxpath requirement is fulfulled
  454. */
  455. if (!cur_mpath && (mpath_count >= maxpaths))
  456. break;
  457. mp_next_node = mp_node ? listnextnode (mp_node) : NULL;
  458. next_mpath = cur_mpath ? bgp_info_mpath_next (cur_mpath) : NULL;
  459. /*
  460. * If equal, the path was a multipath and is still a multipath.
  461. * Insert onto new multipath list if maxpaths allows.
  462. */
  463. if (mp_node && (listgetdata (mp_node) == cur_mpath))
  464. {
  465. list_delete_node (mp_list, mp_node);
  466. bgp_info_mpath_dequeue (cur_mpath);
  467. if ((mpath_count < maxpaths) &&
  468. bgp_info_nexthop_cmp (prev_mpath, cur_mpath))
  469. {
  470. bgp_info_mpath_enqueue (prev_mpath, cur_mpath);
  471. prev_mpath = cur_mpath;
  472. mpath_count++;
  473. }
  474. else
  475. {
  476. mpath_changed = 1;
  477. if (debug)
  478. zlog_debug ("%s remove mpath nexthop %s peer %s", pfx_buf,
  479. inet_ntop (AF_INET, &cur_mpath->attr->nexthop,
  480. nh_buf[0], sizeof (nh_buf[0])),
  481. sockunion2str (cur_mpath->peer->su_remote,
  482. nh_buf[1], sizeof (nh_buf[1])));
  483. }
  484. mp_node = mp_next_node;
  485. cur_mpath = next_mpath;
  486. continue;
  487. }
  488. if (cur_mpath && (!mp_node ||
  489. (bgp_info_mpath_cmp (cur_mpath,
  490. listgetdata (mp_node)) < 0)))
  491. {
  492. /*
  493. * If here, we have an old multipath and either the mp_list
  494. * is finished or the next mp_node points to a later
  495. * multipath, so we need to purge this path from the
  496. * multipath list
  497. */
  498. bgp_info_mpath_dequeue (cur_mpath);
  499. mpath_changed = 1;
  500. if (debug)
  501. zlog_debug ("%s remove mpath nexthop %s peer %s", pfx_buf,
  502. inet_ntop (AF_INET, &cur_mpath->attr->nexthop,
  503. nh_buf[0], sizeof (nh_buf[0])),
  504. sockunion2str (cur_mpath->peer->su_remote,
  505. nh_buf[1], sizeof (nh_buf[1])));
  506. cur_mpath = next_mpath;
  507. }
  508. else
  509. {
  510. /*
  511. * If here, we have a path on the mp_list that was not previously
  512. * a multipath (due to non-equivalance or maxpaths exceeded),
  513. * or the matching multipath is sorted later in the multipath
  514. * list. Before we enqueue the path on the new multipath list,
  515. * make sure its not on the old_best multipath list or referenced
  516. * via next_mpath:
  517. * - If next_mpath points to this new path, update next_mpath to
  518. * point to the multipath after this one
  519. * - Dequeue the path from the multipath list just to make sure
  520. */
  521. new_mpath = listgetdata (mp_node);
  522. list_delete_node (mp_list, mp_node);
  523. if ((mpath_count < maxpaths) && (new_mpath != new_best) &&
  524. bgp_info_nexthop_cmp (prev_mpath, new_mpath))
  525. {
  526. if (new_mpath == next_mpath)
  527. next_mpath = bgp_info_mpath_next (new_mpath);
  528. bgp_info_mpath_dequeue (new_mpath);
  529. bgp_info_mpath_enqueue (prev_mpath, new_mpath);
  530. prev_mpath = new_mpath;
  531. mpath_changed = 1;
  532. mpath_count++;
  533. if (debug)
  534. zlog_debug ("%s add mpath nexthop %s peer %s", pfx_buf,
  535. inet_ntop (AF_INET, &new_mpath->attr->nexthop,
  536. nh_buf[0], sizeof (nh_buf[0])),
  537. sockunion2str (new_mpath->peer->su_remote,
  538. nh_buf[1], sizeof (nh_buf[1])));
  539. }
  540. mp_node = mp_next_node;
  541. }
  542. }
  543. if (new_best)
  544. {
  545. bgp_info_mpath_count_set (new_best, mpath_count-1);
  546. if (mpath_changed || (bgp_info_mpath_count (new_best) != old_mpath_count))
  547. SET_FLAG (new_best->flags, BGP_INFO_MULTIPATH_CHG);
  548. }
  549. }
  550. /*
  551. * bgp_mp_dmed_deselect
  552. *
  553. * Clean up multipath information for BGP_INFO_DMED_SELECTED path that
  554. * is not selected as best path
  555. */
  556. void
  557. bgp_mp_dmed_deselect (struct bgp_info *dmed_best)
  558. {
  559. struct bgp_info *mpinfo, *mpnext;
  560. if (!dmed_best)
  561. return;
  562. for (mpinfo = bgp_info_mpath_first (dmed_best); mpinfo; mpinfo = mpnext)
  563. {
  564. mpnext = bgp_info_mpath_next (mpinfo);
  565. bgp_info_mpath_dequeue (mpinfo);
  566. }
  567. bgp_info_mpath_count_set (dmed_best, 0);
  568. UNSET_FLAG (dmed_best->flags, BGP_INFO_MULTIPATH_CHG);
  569. assert (bgp_info_mpath_first (dmed_best) == 0);
  570. }
  571. /*
  572. * bgp_info_mpath_aggregate_update
  573. *
  574. * Set the multipath aggregate attribute. We need to see if the
  575. * aggregate has changed and then set the ATTR_CHANGED flag on the
  576. * bestpath info so that a peer update will be generated. The
  577. * change is detected by generating the current attribute,
  578. * interning it, and then comparing the interned pointer with the
  579. * current value. We can skip this generate/compare step if there
  580. * is no change in multipath selection and no attribute change in
  581. * any multipath.
  582. */
  583. void
  584. bgp_info_mpath_aggregate_update (struct bgp_info *new_best,
  585. struct bgp_info *old_best)
  586. {
  587. struct bgp_info *mpinfo;
  588. struct aspath *aspath;
  589. struct aspath *asmerge;
  590. struct attr *new_attr, *old_attr;
  591. u_char origin, attr_chg;
  592. struct community *community, *commerge;
  593. struct ecommunity *ecomm, *ecommerge;
  594. struct lcommunity *lcomm, *lcommerge;
  595. struct attr_extra *ae;
  596. struct attr attr = { 0 };
  597. if (old_best && (old_best != new_best) &&
  598. (old_attr = bgp_info_mpath_attr (old_best)))
  599. {
  600. bgp_attr_unintern (&old_attr);
  601. bgp_info_mpath_attr_set (old_best, NULL);
  602. }
  603. if (!new_best)
  604. return;
  605. if (!bgp_info_mpath_count (new_best))
  606. {
  607. if ((new_attr = bgp_info_mpath_attr (new_best)))
  608. {
  609. bgp_attr_unintern (&new_attr);
  610. bgp_info_mpath_attr_set (new_best, NULL);
  611. SET_FLAG (new_best->flags, BGP_INFO_ATTR_CHANGED);
  612. }
  613. return;
  614. }
  615. /*
  616. * Bail out here if the following is true:
  617. * - MULTIPATH_CHG bit is not set on new_best, and
  618. * - No change in bestpath, and
  619. * - ATTR_CHANGED bit is not set on new_best or any of the multipaths
  620. */
  621. if (!CHECK_FLAG (new_best->flags, BGP_INFO_MULTIPATH_CHG) &&
  622. (old_best == new_best))
  623. {
  624. attr_chg = 0;
  625. if (CHECK_FLAG (new_best->flags, BGP_INFO_ATTR_CHANGED))
  626. attr_chg = 1;
  627. else
  628. for (mpinfo = bgp_info_mpath_first (new_best); mpinfo;
  629. mpinfo = bgp_info_mpath_next (mpinfo))
  630. {
  631. if (CHECK_FLAG (mpinfo->flags, BGP_INFO_ATTR_CHANGED))
  632. {
  633. attr_chg = 1;
  634. break;
  635. }
  636. }
  637. if (!attr_chg)
  638. {
  639. assert (bgp_info_mpath_attr (new_best));
  640. return;
  641. }
  642. }
  643. bgp_attr_dup (&attr, new_best->attr);
  644. /* aggregate attribute from multipath constituents */
  645. aspath = aspath_dup (attr.aspath);
  646. origin = attr.origin;
  647. community = attr.community ? community_dup (attr.community) : NULL;
  648. ae = attr.extra;
  649. ecomm = (ae && ae->ecommunity) ? ecommunity_dup (ae->ecommunity) : NULL;
  650. lcomm = (ae && ae->lcommunity) ? lcommunity_dup (ae->lcommunity) : NULL;
  651. for (mpinfo = bgp_info_mpath_first (new_best); mpinfo;
  652. mpinfo = bgp_info_mpath_next (mpinfo))
  653. {
  654. asmerge = aspath_aggregate_mpath (aspath, mpinfo->attr->aspath);
  655. aspath_free (aspath);
  656. aspath = asmerge;
  657. if (origin < mpinfo->attr->origin)
  658. origin = mpinfo->attr->origin;
  659. if (mpinfo->attr->community)
  660. {
  661. if (community)
  662. {
  663. commerge = community_merge (community, mpinfo->attr->community);
  664. community = community_uniq_sort (commerge);
  665. community_free (commerge);
  666. }
  667. else
  668. community = community_dup (mpinfo->attr->community);
  669. }
  670. ae = mpinfo->attr->extra;
  671. if (ae && ae->ecommunity)
  672. {
  673. if (ecomm)
  674. {
  675. ecommerge = ecommunity_merge (ecomm, ae->ecommunity);
  676. ecomm = ecommunity_uniq_sort (ecommerge);
  677. ecommunity_free (&ecommerge);
  678. }
  679. else
  680. ecomm = ecommunity_dup (ae->ecommunity);
  681. }
  682. if (ae && ae->lcommunity)
  683. {
  684. if (lcomm)
  685. {
  686. lcommerge = lcommunity_merge (lcomm, ae->lcommunity);
  687. lcomm = lcommunity_uniq_sort (lcommerge);
  688. lcommunity_free (&lcommerge);
  689. }
  690. else
  691. lcomm = lcommunity_dup (ae->lcommunity);
  692. }
  693. }
  694. attr.aspath = aspath;
  695. attr.origin = origin;
  696. if (community)
  697. {
  698. attr.community = community;
  699. attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES);
  700. }
  701. if (ecomm)
  702. {
  703. ae = bgp_attr_extra_get (&attr);
  704. ae->ecommunity = ecomm;
  705. attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES);
  706. }
  707. /* Zap multipath attr nexthop so we set nexthop to self */
  708. attr.nexthop.s_addr = 0;
  709. if (attr.extra)
  710. memset (&attr.extra->mp_nexthop_global, 0, sizeof (struct in6_addr));
  711. /* TODO: should we set ATOMIC_AGGREGATE and AGGREGATOR? */
  712. new_attr = bgp_attr_intern (&attr);
  713. bgp_attr_extra_free (&attr);
  714. if (new_attr != bgp_info_mpath_attr (new_best))
  715. {
  716. if ((old_attr = bgp_info_mpath_attr (new_best)))
  717. bgp_attr_unintern (&old_attr);
  718. bgp_info_mpath_attr_set (new_best, new_attr);
  719. SET_FLAG (new_best->flags, BGP_INFO_ATTR_CHANGED);
  720. }
  721. else
  722. bgp_attr_unintern (&new_attr);
  723. }