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