bgp_mpath.c 21 KB

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