2 * bgp_updgrp.c: BGP update group structures
4 * @copyright Copyright (C) 2014 Cumulus Networks, Inc.
6 * @author Avneesh Sachdev <avneesh@sproute.net>
7 * @author Rajesh Varadarajan <rajesh@sproute.net>
8 * @author Pradosh Mohapatra <pradosh@sproute.net>
10 * This file is part of GNU Zebra.
12 * GNU Zebra is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 2, or (at your option) any
17 * GNU Zebra is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with GNU Zebra; see the file COPYING. If not, write to the Free
24 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
35 #include "sockunion.h"
43 #include "workqueue.h"
48 #include "bgpd/bgpd.h"
49 #include "bgpd/bgp_table.h"
50 #include "bgpd/bgp_debug.h"
51 #include "bgpd/bgp_fsm.h"
52 #include "bgpd/bgp_advertise.h"
53 #include "bgpd/bgp_packet.h"
54 #include "bgpd/bgp_updgrp.h"
55 #include "bgpd/bgp_route.h"
56 #include "bgpd/bgp_filter.h"
63 * assign a unique ID to update group and subgroup. Mostly for display/
64 * debugging purposes. It's a 64-bit space - used leisurely without a
65 * worry about its wrapping and about filling gaps. While at it, timestamp
68 static void update_group_checkin(struct update_group
*updgrp
)
70 updgrp
->id
= ++bm
->updgrp_idspace
;
71 updgrp
->uptime
= bgp_clock();
74 static void update_subgroup_checkin(struct update_subgroup
*subgrp
,
75 struct update_group
*updgrp
)
77 subgrp
->id
= ++bm
->subgrp_idspace
;
78 subgrp
->uptime
= bgp_clock();
81 static void sync_init(struct update_subgroup
*subgrp
)
84 XCALLOC(MTYPE_BGP_SYNCHRONISE
, sizeof(struct bgp_synchronize
));
85 BGP_ADV_FIFO_INIT(&subgrp
->sync
->update
);
86 BGP_ADV_FIFO_INIT(&subgrp
->sync
->withdraw
);
87 BGP_ADV_FIFO_INIT(&subgrp
->sync
->withdraw_low
);
88 subgrp
->hash
= hash_create(baa_hash_key
, baa_hash_cmp
);
90 /* We use a larger buffer for subgrp->work in the event that:
91 * - We RX a BGP_UPDATE where the attributes alone are just
92 * under BGP_MAX_PACKET_SIZE
93 * - The user configures an outbound route-map that does many as-path
94 * prepends or adds many communities. At most they can have
96 * args in a route-map so there is a finite limit on how large they
98 * make the attributes.
100 * Having a buffer with BGP_MAX_PACKET_SIZE_OVERFLOW allows us to avoid
102 * checking for every single attribute as we construct an UPDATE.
105 stream_new(BGP_MAX_PACKET_SIZE
+ BGP_MAX_PACKET_SIZE_OVERFLOW
);
106 subgrp
->scratch
= stream_new(BGP_MAX_PACKET_SIZE
);
109 static void sync_delete(struct update_subgroup
*subgrp
)
112 XFREE(MTYPE_BGP_SYNCHRONISE
, subgrp
->sync
);
115 hash_free(subgrp
->hash
);
118 stream_free(subgrp
->work
);
121 stream_free(subgrp
->scratch
);
122 subgrp
->scratch
= NULL
;
128 * copy only those fields that are relevant to update group match
130 static void conf_copy(struct peer
*dst
, struct peer
*src
, afi_t afi
,
133 struct bgp_filter
*srcfilter
;
134 struct bgp_filter
*dstfilter
;
136 srcfilter
= &src
->filter
[afi
][safi
];
137 dstfilter
= &dst
->filter
[afi
][safi
];
140 dst
->sort
= src
->sort
;
142 dst
->v_routeadv
= src
->v_routeadv
;
143 dst
->flags
= src
->flags
;
144 dst
->af_flags
[afi
][safi
] = src
->af_flags
[afi
][safi
];
146 XFREE(MTYPE_BGP_PEER_HOST
, dst
->host
);
148 dst
->host
= XSTRDUP(MTYPE_BGP_PEER_HOST
, src
->host
);
150 dst
->af_cap
[afi
][safi
] = src
->af_cap
[afi
][safi
];
151 dst
->afc_nego
[afi
][safi
] = src
->afc_nego
[afi
][safi
];
152 dst
->orf_plist
[afi
][safi
] = src
->orf_plist
[afi
][safi
];
153 dst
->local_as
= src
->local_as
;
154 dst
->change_local_as
= src
->change_local_as
;
155 dst
->shared_network
= src
->shared_network
;
156 memcpy(&(dst
->nexthop
), &(src
->nexthop
), sizeof(struct bgp_nexthop
));
158 dst
->group
= src
->group
;
160 if (src
->default_rmap
[afi
][safi
].name
) {
161 dst
->default_rmap
[afi
][safi
].name
=
162 XSTRDUP(MTYPE_ROUTE_MAP_NAME
,
163 src
->default_rmap
[afi
][safi
].name
);
164 dst
->default_rmap
[afi
][safi
].map
=
165 src
->default_rmap
[afi
][safi
].map
;
168 if (DISTRIBUTE_OUT_NAME(srcfilter
)) {
169 DISTRIBUTE_OUT_NAME(dstfilter
) = XSTRDUP(
170 MTYPE_BGP_FILTER_NAME
, DISTRIBUTE_OUT_NAME(srcfilter
));
171 DISTRIBUTE_OUT(dstfilter
) = DISTRIBUTE_OUT(srcfilter
);
174 if (PREFIX_LIST_OUT_NAME(srcfilter
)) {
175 PREFIX_LIST_OUT_NAME(dstfilter
) = XSTRDUP(
176 MTYPE_BGP_FILTER_NAME
, PREFIX_LIST_OUT_NAME(srcfilter
));
177 PREFIX_LIST_OUT(dstfilter
) = PREFIX_LIST_OUT(srcfilter
);
180 if (FILTER_LIST_OUT_NAME(srcfilter
)) {
181 FILTER_LIST_OUT_NAME(dstfilter
) = XSTRDUP(
182 MTYPE_BGP_FILTER_NAME
, FILTER_LIST_OUT_NAME(srcfilter
));
183 FILTER_LIST_OUT(dstfilter
) = FILTER_LIST_OUT(srcfilter
);
186 if (ROUTE_MAP_OUT_NAME(srcfilter
)) {
187 ROUTE_MAP_OUT_NAME(dstfilter
) = XSTRDUP(
188 MTYPE_BGP_FILTER_NAME
, ROUTE_MAP_OUT_NAME(srcfilter
));
189 ROUTE_MAP_OUT(dstfilter
) = ROUTE_MAP_OUT(srcfilter
);
192 if (UNSUPPRESS_MAP_NAME(srcfilter
)) {
193 UNSUPPRESS_MAP_NAME(dstfilter
) = XSTRDUP(
194 MTYPE_BGP_FILTER_NAME
, UNSUPPRESS_MAP_NAME(srcfilter
));
195 UNSUPPRESS_MAP(dstfilter
) = UNSUPPRESS_MAP(srcfilter
);
200 * since we did a bunch of XSTRDUP's in conf_copy, time to free them up
202 static void conf_release(struct peer
*src
, afi_t afi
, safi_t safi
)
204 struct bgp_filter
*srcfilter
;
206 srcfilter
= &src
->filter
[afi
][safi
];
208 if (src
->default_rmap
[afi
][safi
].name
)
209 XFREE(MTYPE_ROUTE_MAP_NAME
, src
->default_rmap
[afi
][safi
].name
);
211 if (srcfilter
->dlist
[FILTER_OUT
].name
)
212 XFREE(MTYPE_BGP_FILTER_NAME
, srcfilter
->dlist
[FILTER_OUT
].name
);
214 if (srcfilter
->plist
[FILTER_OUT
].name
)
215 XFREE(MTYPE_BGP_FILTER_NAME
, srcfilter
->plist
[FILTER_OUT
].name
);
217 if (srcfilter
->aslist
[FILTER_OUT
].name
)
218 XFREE(MTYPE_BGP_FILTER_NAME
,
219 srcfilter
->aslist
[FILTER_OUT
].name
);
221 if (srcfilter
->map
[RMAP_OUT
].name
)
222 XFREE(MTYPE_BGP_FILTER_NAME
, srcfilter
->map
[RMAP_OUT
].name
);
224 if (srcfilter
->usmap
.name
)
225 XFREE(MTYPE_BGP_FILTER_NAME
, srcfilter
->usmap
.name
);
228 XFREE(MTYPE_BGP_PEER_HOST
, src
->host
);
232 static void peer2_updgrp_copy(struct update_group
*updgrp
, struct peer_af
*paf
)
245 updgrp
->afi
= paf
->afi
;
246 updgrp
->safi
= paf
->safi
;
247 updgrp
->afid
= paf
->afid
;
248 updgrp
->bgp
= src
->bgp
;
250 conf_copy(dst
, src
, paf
->afi
, paf
->safi
);
254 * auxiliary functions to maintain the hash table.
255 * - updgrp_hash_alloc - to create a new entry, passed to hash_get
256 * - updgrp_hash_key_make - makes the key for update group search
257 * - updgrp_hash_cmp - compare two update groups.
259 static void *updgrp_hash_alloc(void *p
)
261 struct update_group
*updgrp
;
262 const struct update_group
*in
;
264 in
= (const struct update_group
*)p
;
265 updgrp
= XCALLOC(MTYPE_BGP_UPDGRP
, sizeof(struct update_group
));
266 memcpy(updgrp
, in
, sizeof(struct update_group
));
267 updgrp
->conf
= XCALLOC(MTYPE_BGP_PEER
, sizeof(struct peer
));
268 conf_copy(updgrp
->conf
, in
->conf
, in
->afi
, in
->safi
);
273 * The hash value for a peer is computed from the following variables:
275 * 1. IBGP (1) or EBGP (2)
276 * 2. FLAGS based on configuration:
277 * LOCAL_AS_NO_PREPEND
278 * LOCAL_AS_REPLACE_AS
279 * 3. AF_FLAGS based on configuration:
280 * Refer to definition in bgp_updgrp.h
281 * 4. (AF-independent) Capability flags:
283 * 5. (AF-dependent) Capability flags:
284 * ORF_PREFIX_SM_RCV (peer can send prefix ORF)
287 * 8. Outbound route-map name (neighbor route-map <> out)
288 * 9. Outbound distribute-list name (neighbor distribute-list <> out)
289 * 10. Outbound prefix-list name (neighbor prefix-list <> out)
290 * 11. Outbound as-list name (neighbor filter-list <> out)
291 * 12. Unsuppress map name (neighbor unsuppress-map <>)
292 * 13. default rmap name (neighbor default-originate route-map <>)
293 * 14. encoding both global and link-local nexthop?
294 * 15. If peer is configured to be a lonesoul, peer ip address
295 * 16. Local-as should match, if configured.
298 static unsigned int updgrp_hash_key_make(void *p
)
300 const struct update_group
*updgrp
;
301 const struct peer
*peer
;
302 const struct bgp_filter
*filter
;
309 #define SEED2 2147483647
315 flags
= peer
->af_flags
[afi
][safi
];
316 filter
= &peer
->filter
[afi
][safi
];
320 key
= jhash_1word(peer
->sort
, key
); /* EBGP or IBGP */
321 key
= jhash_1word((peer
->flags
& PEER_UPDGRP_FLAGS
), key
);
322 key
= jhash_1word((flags
& PEER_UPDGRP_AF_FLAGS
), key
);
323 key
= jhash_1word((peer
->cap
& PEER_UPDGRP_CAP_FLAGS
), key
);
324 key
= jhash_1word((peer
->af_cap
[afi
][safi
] & PEER_UPDGRP_AF_CAP_FLAGS
),
326 key
= jhash_1word(peer
->v_routeadv
, key
);
327 key
= jhash_1word(peer
->change_local_as
, key
);
330 key
= jhash_1word(jhash(peer
->group
->name
,
331 strlen(peer
->group
->name
), SEED1
),
334 if (filter
->map
[RMAP_OUT
].name
)
335 key
= jhash_1word(jhash(filter
->map
[RMAP_OUT
].name
,
336 strlen(filter
->map
[RMAP_OUT
].name
),
340 if (filter
->dlist
[FILTER_OUT
].name
)
341 key
= jhash_1word(jhash(filter
->dlist
[FILTER_OUT
].name
,
342 strlen(filter
->dlist
[FILTER_OUT
].name
),
346 if (filter
->plist
[FILTER_OUT
].name
)
347 key
= jhash_1word(jhash(filter
->plist
[FILTER_OUT
].name
,
348 strlen(filter
->plist
[FILTER_OUT
].name
),
352 if (filter
->aslist
[FILTER_OUT
].name
)
353 key
= jhash_1word(jhash(filter
->aslist
[FILTER_OUT
].name
,
354 strlen(filter
->aslist
[FILTER_OUT
].name
),
358 if (filter
->usmap
.name
)
359 key
= jhash_1word(jhash(filter
->usmap
.name
,
360 strlen(filter
->usmap
.name
), SEED1
),
363 if (peer
->default_rmap
[afi
][safi
].name
)
365 jhash(peer
->default_rmap
[afi
][safi
].name
,
366 strlen(peer
->default_rmap
[afi
][safi
].name
),
370 /* If peer is on a shared network and is exchanging IPv6 prefixes,
371 * it needs to include link-local address. That's different from
372 * non-shared-network peers (nexthop encoded with 32 bytes vs 16
373 * bytes). We create different update groups to take care of that.
376 (peer
->shared_network
&& peer_afi_active_nego(peer
, AFI_IP6
)),
380 * There are certain peers that must get their own update-group:
382 * - peers that negotiated ORF
384 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_LONESOUL
)
385 || CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_SM_RCV
)
386 || CHECK_FLAG(peer
->af_cap
[afi
][safi
],
387 PEER_CAP_ORF_PREFIX_SM_OLD_RCV
))
388 key
= jhash_1word(jhash(peer
->host
, strlen(peer
->host
), SEED2
),
394 static int updgrp_hash_cmp(const void *p1
, const void *p2
)
396 const struct update_group
*grp1
;
397 const struct update_group
*grp2
;
398 const struct peer
*pe1
;
399 const struct peer
*pe2
;
402 const struct bgp_filter
*fl1
;
403 const struct bgp_filter
*fl2
;
416 flags1
= pe1
->af_flags
[afi
][safi
];
417 flags2
= pe2
->af_flags
[afi
][safi
];
418 fl1
= &pe1
->filter
[afi
][safi
];
419 fl2
= &pe2
->filter
[afi
][safi
];
421 /* put EBGP and IBGP peers in different update groups */
422 if (pe1
->sort
!= pe2
->sort
)
425 /* check peer flags */
426 if ((pe1
->flags
& PEER_UPDGRP_FLAGS
)
427 != (pe2
->flags
& PEER_UPDGRP_FLAGS
))
430 /* If there is 'local-as' configured, it should match. */
431 if (pe1
->change_local_as
!= pe2
->change_local_as
)
434 /* flags like route reflector client */
435 if ((flags1
& PEER_UPDGRP_AF_FLAGS
) != (flags2
& PEER_UPDGRP_AF_FLAGS
))
438 if ((pe1
->cap
& PEER_UPDGRP_CAP_FLAGS
)
439 != (pe2
->cap
& PEER_UPDGRP_CAP_FLAGS
))
442 if ((pe1
->af_cap
[afi
][safi
] & PEER_UPDGRP_AF_CAP_FLAGS
)
443 != (pe2
->af_cap
[afi
][safi
] & PEER_UPDGRP_AF_CAP_FLAGS
))
446 if (pe1
->v_routeadv
!= pe2
->v_routeadv
)
449 if (pe1
->group
!= pe2
->group
)
452 /* route-map names should be the same */
453 if ((fl1
->map
[RMAP_OUT
].name
&& !fl2
->map
[RMAP_OUT
].name
)
454 || (!fl1
->map
[RMAP_OUT
].name
&& fl2
->map
[RMAP_OUT
].name
)
455 || (fl1
->map
[RMAP_OUT
].name
&& fl2
->map
[RMAP_OUT
].name
456 && strcmp(fl1
->map
[RMAP_OUT
].name
, fl2
->map
[RMAP_OUT
].name
)))
459 if ((fl1
->dlist
[FILTER_OUT
].name
&& !fl2
->dlist
[FILTER_OUT
].name
)
460 || (!fl1
->dlist
[FILTER_OUT
].name
&& fl2
->dlist
[FILTER_OUT
].name
)
461 || (fl1
->dlist
[FILTER_OUT
].name
&& fl2
->dlist
[FILTER_OUT
].name
462 && strcmp(fl1
->dlist
[FILTER_OUT
].name
,
463 fl2
->dlist
[FILTER_OUT
].name
)))
466 if ((fl1
->plist
[FILTER_OUT
].name
&& !fl2
->plist
[FILTER_OUT
].name
)
467 || (!fl1
->plist
[FILTER_OUT
].name
&& fl2
->plist
[FILTER_OUT
].name
)
468 || (fl1
->plist
[FILTER_OUT
].name
&& fl2
->plist
[FILTER_OUT
].name
469 && strcmp(fl1
->plist
[FILTER_OUT
].name
,
470 fl2
->plist
[FILTER_OUT
].name
)))
473 if ((fl1
->aslist
[FILTER_OUT
].name
&& !fl2
->aslist
[FILTER_OUT
].name
)
474 || (!fl1
->aslist
[FILTER_OUT
].name
&& fl2
->aslist
[FILTER_OUT
].name
)
475 || (fl1
->aslist
[FILTER_OUT
].name
&& fl2
->aslist
[FILTER_OUT
].name
476 && strcmp(fl1
->aslist
[FILTER_OUT
].name
,
477 fl2
->aslist
[FILTER_OUT
].name
)))
480 if ((fl1
->usmap
.name
&& !fl2
->usmap
.name
)
481 || (!fl1
->usmap
.name
&& fl2
->usmap
.name
)
482 || (fl1
->usmap
.name
&& fl2
->usmap
.name
483 && strcmp(fl1
->usmap
.name
, fl2
->usmap
.name
)))
486 if ((pe1
->default_rmap
[afi
][safi
].name
487 && !pe2
->default_rmap
[afi
][safi
].name
)
488 || (!pe1
->default_rmap
[afi
][safi
].name
489 && pe2
->default_rmap
[afi
][safi
].name
)
490 || (pe1
->default_rmap
[afi
][safi
].name
491 && pe2
->default_rmap
[afi
][safi
].name
492 && strcmp(pe1
->default_rmap
[afi
][safi
].name
,
493 pe2
->default_rmap
[afi
][safi
].name
)))
496 if ((afi
== AFI_IP6
) && (pe1
->shared_network
!= pe2
->shared_network
))
499 if ((CHECK_FLAG(pe1
->flags
, PEER_FLAG_LONESOUL
)
500 || CHECK_FLAG(pe1
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_SM_RCV
)
501 || CHECK_FLAG(pe1
->af_cap
[afi
][safi
],
502 PEER_CAP_ORF_PREFIX_SM_OLD_RCV
))
503 && !sockunion_same(&pe1
->su
, &pe2
->su
))
509 static void peer_lonesoul_or_not(struct peer
*peer
, int set
)
511 /* no change in status? */
512 if (set
== (CHECK_FLAG(peer
->flags
, PEER_FLAG_LONESOUL
) > 0))
516 SET_FLAG(peer
->flags
, PEER_FLAG_LONESOUL
);
518 UNSET_FLAG(peer
->flags
, PEER_FLAG_LONESOUL
);
520 update_group_adjust_peer_afs(peer
);
524 * subgroup_total_packets_enqueued
526 * Returns the total number of packets enqueued to a subgroup.
529 subgroup_total_packets_enqueued(struct update_subgroup
*subgrp
)
533 pkt
= bpacket_queue_last(SUBGRP_PKTQ(subgrp
));
538 static int update_group_show_walkcb(struct update_group
*updgrp
, void *arg
)
540 struct updwalk_context
*ctx
= arg
;
542 struct update_subgroup
*subgrp
;
544 struct bgp_filter
*filter
;
550 if (ctx
->subgrp_id
) {
551 UPDGRP_FOREACH_SUBGRP(updgrp
, subgrp
)
553 if (ctx
->subgrp_id
&& (ctx
->subgrp_id
!= subgrp
->id
))
565 /* Since this routine is invoked from a walk, we cannot signal
567 /* error here, can only return. */
573 vty_out(vty
, "Update-group %" PRIu64
":%s", updgrp
->id
, VTY_NEWLINE
);
574 vty_out(vty
, " Created: %s", timestamp_string(updgrp
->uptime
));
575 filter
= &updgrp
->conf
->filter
[updgrp
->afi
][updgrp
->safi
];
576 if (filter
->map
[RMAP_OUT
].name
)
577 vty_out(vty
, " Outgoing route map: %s%s%s",
578 filter
->map
[RMAP_OUT
].map
? "X" : "",
579 filter
->map
[RMAP_OUT
].name
, VTY_NEWLINE
);
580 vty_out(vty
, " MRAI value (seconds): %d%s", updgrp
->conf
->v_routeadv
,
582 if (updgrp
->conf
->change_local_as
)
583 vty_out(vty
, " Local AS %u%s%s%s",
584 updgrp
->conf
->change_local_as
,
585 CHECK_FLAG(updgrp
->conf
->flags
,
586 PEER_FLAG_LOCAL_AS_NO_PREPEND
)
589 CHECK_FLAG(updgrp
->conf
->flags
,
590 PEER_FLAG_LOCAL_AS_REPLACE_AS
)
595 UPDGRP_FOREACH_SUBGRP(updgrp
, subgrp
)
597 if (ctx
->subgrp_id
&& (ctx
->subgrp_id
!= subgrp
->id
))
599 vty_out(vty
, "%s", VTY_NEWLINE
);
600 vty_out(vty
, " Update-subgroup %" PRIu64
":%s", subgrp
->id
,
602 vty_out(vty
, " Created: %s",
603 timestamp_string(subgrp
->uptime
));
605 if (subgrp
->split_from
.update_group_id
606 || subgrp
->split_from
.subgroup_id
) {
607 vty_out(vty
, " Split from group id: %" PRIu64
"%s",
608 subgrp
->split_from
.update_group_id
,
611 " Split from subgroup id: %" PRIu64
"%s",
612 subgrp
->split_from
.subgroup_id
, VTY_NEWLINE
);
615 vty_out(vty
, " Join events: %u%s", subgrp
->join_events
,
617 vty_out(vty
, " Prune events: %u%s", subgrp
->prune_events
,
619 vty_out(vty
, " Merge events: %u%s", subgrp
->merge_events
,
621 vty_out(vty
, " Split events: %u%s", subgrp
->split_events
,
623 vty_out(vty
, " Update group switch events: %u%s",
624 subgrp
->updgrp_switch_events
, VTY_NEWLINE
);
625 vty_out(vty
, " Peer refreshes combined: %u%s",
626 subgrp
->peer_refreshes_combined
, VTY_NEWLINE
);
627 vty_out(vty
, " Merge checks triggered: %u%s",
628 subgrp
->merge_checks_triggered
, VTY_NEWLINE
);
629 vty_out(vty
, " Version: %" PRIu64
"%s", subgrp
->version
,
631 vty_out(vty
, " Packet queue length: %d%s",
632 bpacket_queue_length(SUBGRP_PKTQ(subgrp
)), VTY_NEWLINE
);
633 vty_out(vty
, " Total packets enqueued: %u%s",
634 subgroup_total_packets_enqueued(subgrp
), VTY_NEWLINE
);
635 vty_out(vty
, " Packet queue high watermark: %d%s",
636 bpacket_queue_hwm_length(SUBGRP_PKTQ(subgrp
)),
638 vty_out(vty
, " Adj-out list count: %u%s", subgrp
->adj_count
,
640 vty_out(vty
, " Advertise list: %s%s",
641 advertise_list_is_empty(subgrp
) ? "empty" : "not empty",
643 vty_out(vty
, " Flags: %s%s",
644 CHECK_FLAG(subgrp
->flags
, SUBGRP_FLAG_NEEDS_REFRESH
)
648 if (subgrp
->peer_count
> 0) {
649 vty_out(vty
, " Peers:%s", VTY_NEWLINE
);
650 SUBGRP_FOREACH_PEER(subgrp
, paf
)
651 vty_out(vty
, " - %s%s", paf
->peer
->host
,
655 return UPDWALK_CONTINUE
;
659 * Helper function to show the packet queue for each subgroup of update group.
660 * Will be constrained to a particular subgroup id if id !=0
662 static int updgrp_show_packet_queue_walkcb(struct update_group
*updgrp
,
665 struct updwalk_context
*ctx
= arg
;
666 struct update_subgroup
*subgrp
;
670 UPDGRP_FOREACH_SUBGRP(updgrp
, subgrp
)
672 if (ctx
->subgrp_id
&& (ctx
->subgrp_id
!= subgrp
->id
))
674 vty_out(vty
, "update group %" PRIu64
", subgroup %" PRIu64
"%s",
675 updgrp
->id
, subgrp
->id
, VTY_NEWLINE
);
676 bpacket_queue_show_vty(SUBGRP_PKTQ(subgrp
), vty
);
678 return UPDWALK_CONTINUE
;
682 * Show the packet queue for each subgroup of update group. Will be
683 * constrained to a particular subgroup id if id !=0
685 void update_group_show_packet_queue(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
686 struct vty
*vty
, uint64_t id
)
688 struct updwalk_context ctx
;
690 memset(&ctx
, 0, sizeof(ctx
));
694 update_group_af_walk(bgp
, afi
, safi
, updgrp_show_packet_queue_walkcb
,
698 static struct update_group
*update_group_find(struct peer_af
*paf
)
700 struct update_group
*updgrp
;
701 struct update_group tmp
;
702 struct peer tmp_conf
;
704 if (!peer_established(PAF_PEER(paf
)))
707 memset(&tmp
, 0, sizeof(tmp
));
708 memset(&tmp_conf
, 0, sizeof(tmp_conf
));
709 tmp
.conf
= &tmp_conf
;
710 peer2_updgrp_copy(&tmp
, paf
);
712 updgrp
= hash_lookup(paf
->peer
->bgp
->update_groups
[paf
->afid
], &tmp
);
713 conf_release(&tmp_conf
, paf
->afi
, paf
->safi
);
717 static struct update_group
*update_group_create(struct peer_af
*paf
)
719 struct update_group
*updgrp
;
720 struct update_group tmp
;
721 struct peer tmp_conf
;
723 memset(&tmp
, 0, sizeof(tmp
));
724 memset(&tmp_conf
, 0, sizeof(tmp_conf
));
725 tmp
.conf
= &tmp_conf
;
726 peer2_updgrp_copy(&tmp
, paf
);
728 updgrp
= hash_get(paf
->peer
->bgp
->update_groups
[paf
->afid
], &tmp
,
732 update_group_checkin(updgrp
);
734 if (BGP_DEBUG(update_groups
, UPDATE_GROUPS
))
735 zlog_debug("create update group %" PRIu64
, updgrp
->id
);
737 UPDGRP_GLOBAL_STAT(updgrp
, updgrps_created
) += 1;
739 conf_release(&tmp_conf
, paf
->afi
, paf
->safi
);
743 static void update_group_delete(struct update_group
*updgrp
)
745 if (BGP_DEBUG(update_groups
, UPDATE_GROUPS
))
746 zlog_debug("delete update group %" PRIu64
, updgrp
->id
);
748 UPDGRP_GLOBAL_STAT(updgrp
, updgrps_deleted
) += 1;
750 hash_release(updgrp
->bgp
->update_groups
[updgrp
->afid
], updgrp
);
751 conf_release(updgrp
->conf
, updgrp
->afi
, updgrp
->safi
);
753 if (updgrp
->conf
->host
)
754 XFREE(MTYPE_BGP_PEER_HOST
, updgrp
->conf
->host
);
755 updgrp
->conf
->host
= NULL
;
757 if (updgrp
->conf
->ifname
)
758 XFREE(MTYPE_BGP_PEER_IFNAME
, updgrp
->conf
->ifname
);
760 XFREE(MTYPE_BGP_PEER
, updgrp
->conf
);
761 XFREE(MTYPE_BGP_UPDGRP
, updgrp
);
764 static void update_group_add_subgroup(struct update_group
*updgrp
,
765 struct update_subgroup
*subgrp
)
767 if (!updgrp
|| !subgrp
)
770 LIST_INSERT_HEAD(&(updgrp
->subgrps
), subgrp
, updgrp_train
);
771 subgrp
->update_group
= updgrp
;
774 static void update_group_remove_subgroup(struct update_group
*updgrp
,
775 struct update_subgroup
*subgrp
)
777 if (!updgrp
|| !subgrp
)
780 LIST_REMOVE(subgrp
, updgrp_train
);
781 subgrp
->update_group
= NULL
;
782 if (LIST_EMPTY(&(updgrp
->subgrps
)))
783 update_group_delete(updgrp
);
786 static struct update_subgroup
*
787 update_subgroup_create(struct update_group
*updgrp
)
789 struct update_subgroup
*subgrp
;
791 subgrp
= XCALLOC(MTYPE_BGP_UPD_SUBGRP
, sizeof(struct update_subgroup
));
792 update_subgroup_checkin(subgrp
, updgrp
);
793 subgrp
->v_coalesce
= (UPDGRP_INST(updgrp
))->coalesce_time
;
795 bpacket_queue_init(SUBGRP_PKTQ(subgrp
));
796 bpacket_queue_add(SUBGRP_PKTQ(subgrp
), NULL
, NULL
);
797 TAILQ_INIT(&(subgrp
->adjq
));
798 if (BGP_DEBUG(update_groups
, UPDATE_GROUPS
))
799 zlog_debug("create subgroup u%" PRIu64
":s%" PRIu64
, updgrp
->id
,
802 update_group_add_subgroup(updgrp
, subgrp
);
804 UPDGRP_INCR_STAT(updgrp
, subgrps_created
);
809 static void update_subgroup_delete(struct update_subgroup
*subgrp
)
814 if (subgrp
->update_group
)
815 UPDGRP_INCR_STAT(subgrp
->update_group
, subgrps_deleted
);
817 if (subgrp
->t_merge_check
)
818 THREAD_OFF(subgrp
->t_merge_check
);
820 if (subgrp
->t_coalesce
)
821 THREAD_TIMER_OFF(subgrp
->t_coalesce
);
823 bpacket_queue_cleanup(SUBGRP_PKTQ(subgrp
));
824 subgroup_clear_table(subgrp
);
826 if (subgrp
->t_coalesce
)
827 THREAD_TIMER_OFF(subgrp
->t_coalesce
);
830 if (BGP_DEBUG(update_groups
, UPDATE_GROUPS
))
831 zlog_debug("delete subgroup u%" PRIu64
":s%" PRIu64
,
832 subgrp
->update_group
->id
, subgrp
->id
);
834 update_group_remove_subgroup(subgrp
->update_group
, subgrp
);
836 XFREE(MTYPE_BGP_UPD_SUBGRP
, subgrp
);
839 void update_subgroup_inherit_info(struct update_subgroup
*to
,
840 struct update_subgroup
*from
)
845 to
->sflags
= from
->sflags
;
849 * update_subgroup_check_delete
851 * Delete a subgroup if it is ready to be deleted.
853 * Returns TRUE if the subgroup was deleted.
855 static int update_subgroup_check_delete(struct update_subgroup
*subgrp
)
860 if (!LIST_EMPTY(&(subgrp
->peers
)))
863 update_subgroup_delete(subgrp
);
869 * update_subgroup_add_peer
871 * @param send_enqueued_packets If true all currently enqueued packets will
872 * also be sent to the peer.
874 static void update_subgroup_add_peer(struct update_subgroup
*subgrp
,
876 int send_enqueued_pkts
)
883 LIST_INSERT_HEAD(&(subgrp
->peers
), paf
, subgrp_train
);
884 paf
->subgroup
= subgrp
;
885 subgrp
->peer_count
++;
887 if (bgp_debug_peer_updout_enabled(paf
->peer
->host
)) {
888 UPDGRP_PEER_DBG_EN(subgrp
->update_group
);
891 SUBGRP_INCR_STAT(subgrp
, join_events
);
893 if (send_enqueued_pkts
) {
894 pkt
= bpacket_queue_first(SUBGRP_PKTQ(subgrp
));
898 * Hang the peer off of the last, placeholder, packet in the
899 * queue. This means it won't see any of the packets that are
900 * currently the queue.
902 pkt
= bpacket_queue_last(SUBGRP_PKTQ(subgrp
));
903 assert(pkt
->buffer
== NULL
);
906 bpacket_add_peer(pkt
, paf
);
908 bpacket_queue_sanity_check(SUBGRP_PKTQ(subgrp
));
912 * update_subgroup_remove_peer_internal
914 * Internal function that removes a peer from a subgroup, but does not
915 * delete the subgroup. A call to this function must almost always be
916 * followed by a call to update_subgroup_check_delete().
918 * @see update_subgroup_remove_peer
920 static void update_subgroup_remove_peer_internal(struct update_subgroup
*subgrp
,
923 assert(subgrp
&& paf
);
925 if (bgp_debug_peer_updout_enabled(paf
->peer
->host
)) {
926 UPDGRP_PEER_DBG_DIS(subgrp
->update_group
);
929 bpacket_queue_remove_peer(paf
);
930 LIST_REMOVE(paf
, subgrp_train
);
931 paf
->subgroup
= NULL
;
932 subgrp
->peer_count
--;
934 SUBGRP_INCR_STAT(subgrp
, prune_events
);
938 * update_subgroup_remove_peer
940 void update_subgroup_remove_peer(struct update_subgroup
*subgrp
,
946 update_subgroup_remove_peer_internal(subgrp
, paf
);
948 if (update_subgroup_check_delete(subgrp
))
952 * The deletion of the peer may have caused some packets to be
953 * deleted from the subgroup packet queue. Check if the subgroup can
956 update_subgroup_check_merge(subgrp
, "removed peer from subgroup");
959 static struct update_subgroup
*update_subgroup_find(struct update_group
*updgrp
,
962 struct update_subgroup
*subgrp
= NULL
;
971 if (!peer_established(PAF_PEER(paf
)))
974 UPDGRP_FOREACH_SUBGRP(updgrp
, subgrp
)
976 if (subgrp
->version
!= version
977 || CHECK_FLAG(subgrp
->sflags
,
978 SUBGRP_STATUS_DEFAULT_ORIGINATE
))
982 * The version number is not meaningful on a subgroup that needs
985 if (update_subgroup_needs_refresh(subgrp
))
995 * update_subgroup_ready_for_merge
997 * Returns TRUE if this subgroup is in a state that allows it to be
998 * merged into another subgroup.
1000 static int update_subgroup_ready_for_merge(struct update_subgroup
*subgrp
)
1004 * Not ready if there are any encoded packets waiting to be written
1007 if (!bpacket_queue_is_empty(SUBGRP_PKTQ(subgrp
)))
1011 * Not ready if there enqueued updates waiting to be encoded.
1013 if (!advertise_list_is_empty(subgrp
))
1017 * Don't attempt to merge a subgroup that needs a refresh. For one,
1018 * we can't determine if the adj_out of such a group matches that of
1021 if (update_subgroup_needs_refresh(subgrp
))
1028 * update_subgrp_can_merge_into
1030 * Returns TRUE if the first subgroup can merge into the second
1033 static int update_subgroup_can_merge_into(struct update_subgroup
*subgrp
,
1034 struct update_subgroup
*target
)
1037 if (subgrp
== target
)
1041 * Both must have processed the BRIB to the same point in order to
1044 if (subgrp
->version
!= target
->version
)
1047 if (CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)
1048 != CHECK_FLAG(target
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
))
1051 if (subgrp
->adj_count
!= target
->adj_count
)
1054 return update_subgroup_ready_for_merge(target
);
1058 * update_subgroup_merge
1060 * Merge the first subgroup into the second one.
1062 static void update_subgroup_merge(struct update_subgroup
*subgrp
,
1063 struct update_subgroup
*target
,
1066 struct peer_af
*paf
;
1070 assert(subgrp
->adj_count
== target
->adj_count
);
1072 peer_count
= subgrp
->peer_count
;
1075 paf
= LIST_FIRST(&subgrp
->peers
);
1079 update_subgroup_remove_peer_internal(subgrp
, paf
);
1082 * Add the peer to the target subgroup, while making sure that
1083 * any currently enqueued packets won't be sent to it. Enqueued
1084 * packets could, for example, result in an unnecessary withdraw
1085 * followed by an advertise.
1087 update_subgroup_add_peer(target
, paf
, 0);
1090 SUBGRP_INCR_STAT(target
, merge_events
);
1092 if (BGP_DEBUG(update_groups
, UPDATE_GROUPS
))
1093 zlog_debug("u%" PRIu64
":s%" PRIu64
1094 " (%d peers) merged into u%" PRIu64
":s%" PRIu64
1097 subgrp
->update_group
->id
, subgrp
->id
, peer_count
,
1098 target
->update_group
->id
, target
->id
,
1099 reason
? reason
: "unknown");
1101 result
= update_subgroup_check_delete(subgrp
);
1106 * update_subgroup_check_merge
1108 * Merge this subgroup into another subgroup if possible.
1110 * Returns TRUE if the subgroup has been merged. The subgroup pointer
1111 * should not be accessed in this case.
1113 int update_subgroup_check_merge(struct update_subgroup
*subgrp
,
1116 struct update_subgroup
*target
;
1118 if (!update_subgroup_ready_for_merge(subgrp
))
1122 * Look for a subgroup to merge into.
1124 UPDGRP_FOREACH_SUBGRP(subgrp
->update_group
, target
)
1126 if (update_subgroup_can_merge_into(subgrp
, target
))
1133 update_subgroup_merge(subgrp
, target
, reason
);
1138 * update_subgroup_merge_check_thread_cb
1140 static int update_subgroup_merge_check_thread_cb(struct thread
*thread
)
1142 struct update_subgroup
*subgrp
;
1144 subgrp
= THREAD_ARG(thread
);
1146 subgrp
->t_merge_check
= NULL
;
1148 update_subgroup_check_merge(subgrp
, "triggered merge check");
1153 * update_subgroup_trigger_merge_check
1155 * Triggers a call to update_subgroup_check_merge() on a clean context.
1157 * @param force If true, the merge check will be triggered even if the
1158 * subgroup doesn't currently look ready for a merge.
1160 * Returns TRUE if a merge check will be performed shortly.
1162 int update_subgroup_trigger_merge_check(struct update_subgroup
*subgrp
,
1165 if (subgrp
->t_merge_check
)
1168 if (!force
&& !update_subgroup_ready_for_merge(subgrp
))
1171 subgrp
->t_merge_check
= thread_add_background(
1172 bm
->master
, update_subgroup_merge_check_thread_cb
, subgrp
, 0);
1174 SUBGRP_INCR_STAT(subgrp
, merge_checks_triggered
);
1180 * update_subgroup_copy_adj_out
1182 * Helper function that clones the adj out (state about advertised
1183 * routes) from one subgroup to another. It assumes that the adj out
1184 * of the target subgroup is empty.
1186 static void update_subgroup_copy_adj_out(struct update_subgroup
*source
,
1187 struct update_subgroup
*dest
)
1189 struct bgp_adj_out
*aout
, *aout_copy
;
1191 SUBGRP_FOREACH_ADJ(source
, aout
)
1197 bgp_adj_out_alloc(dest
, aout
->rn
, aout
->addpath_tx_id
);
1199 aout
->attr
? bgp_attr_refcount(aout
->attr
) : NULL
;
1204 * update_subgroup_copy_packets
1206 * Copy packets after and including the given packet to the subgroup
1209 * Returns the number of packets copied.
1211 static int update_subgroup_copy_packets(struct update_subgroup
*dest
,
1212 struct bpacket
*pkt
)
1217 while (pkt
&& pkt
->buffer
) {
1218 bpacket_queue_add(SUBGRP_PKTQ(dest
), stream_dup(pkt
->buffer
),
1221 pkt
= bpacket_next(pkt
);
1224 bpacket_queue_sanity_check(SUBGRP_PKTQ(dest
));
1229 static int updgrp_prefix_list_update(struct update_group
*updgrp
,
1233 struct bgp_filter
*filter
;
1235 peer
= UPDGRP_PEER(updgrp
);
1236 filter
= &peer
->filter
[UPDGRP_AFI(updgrp
)][UPDGRP_SAFI(updgrp
)];
1238 if (PREFIX_LIST_OUT_NAME(filter
)
1239 && (strcmp(name
, PREFIX_LIST_OUT_NAME(filter
)) == 0)) {
1240 PREFIX_LIST_OUT(filter
) = prefix_list_lookup(
1241 UPDGRP_AFI(updgrp
), PREFIX_LIST_OUT_NAME(filter
));
1247 static int updgrp_filter_list_update(struct update_group
*updgrp
,
1251 struct bgp_filter
*filter
;
1253 peer
= UPDGRP_PEER(updgrp
);
1254 filter
= &peer
->filter
[UPDGRP_AFI(updgrp
)][UPDGRP_SAFI(updgrp
)];
1256 if (FILTER_LIST_OUT_NAME(filter
)
1257 && (strcmp(name
, FILTER_LIST_OUT_NAME(filter
)) == 0)) {
1258 FILTER_LIST_OUT(filter
) =
1259 as_list_lookup(FILTER_LIST_OUT_NAME(filter
));
1265 static int updgrp_distribute_list_update(struct update_group
*updgrp
,
1269 struct bgp_filter
*filter
;
1271 peer
= UPDGRP_PEER(updgrp
);
1272 filter
= &peer
->filter
[UPDGRP_AFI(updgrp
)][UPDGRP_SAFI(updgrp
)];
1274 if (DISTRIBUTE_OUT_NAME(filter
)
1275 && (strcmp(name
, DISTRIBUTE_OUT_NAME(filter
)) == 0)) {
1276 DISTRIBUTE_OUT(filter
) = access_list_lookup(
1277 UPDGRP_AFI(updgrp
), DISTRIBUTE_OUT_NAME(filter
));
1283 static int updgrp_route_map_update(struct update_group
*updgrp
,
1284 const char *name
, int *def_rmap_changed
)
1287 struct bgp_filter
*filter
;
1292 peer
= UPDGRP_PEER(updgrp
);
1293 afi
= UPDGRP_AFI(updgrp
);
1294 safi
= UPDGRP_SAFI(updgrp
);
1295 filter
= &peer
->filter
[afi
][safi
];
1297 if (ROUTE_MAP_OUT_NAME(filter
)
1298 && (strcmp(name
, ROUTE_MAP_OUT_NAME(filter
)) == 0)) {
1299 ROUTE_MAP_OUT(filter
) = route_map_lookup_by_name(name
);
1304 if (UNSUPPRESS_MAP_NAME(filter
)
1305 && (strcmp(name
, UNSUPPRESS_MAP_NAME(filter
)) == 0)) {
1306 UNSUPPRESS_MAP(filter
) = route_map_lookup_by_name(name
);
1310 /* process default-originate route-map */
1311 if (peer
->default_rmap
[afi
][safi
].name
1312 && (strcmp(name
, peer
->default_rmap
[afi
][safi
].name
) == 0)) {
1313 peer
->default_rmap
[afi
][safi
].map
=
1314 route_map_lookup_by_name(name
);
1315 if (def_rmap_changed
)
1316 *def_rmap_changed
= 1;
1322 * hash iteration callback function to process a policy change for an
1323 * update group. Check if the changed policy matches the updgrp's
1324 * outbound route-map or unsuppress-map or default-originate map or
1325 * filter-list or prefix-list or distribute-list.
1326 * Trigger update generation accordingly.
1328 static int updgrp_policy_update_walkcb(struct update_group
*updgrp
, void *arg
)
1330 struct updwalk_context
*ctx
= arg
;
1331 struct update_subgroup
*subgrp
;
1333 int def_changed
= 0;
1335 if (!updgrp
|| !ctx
|| !ctx
->policy_name
)
1336 return UPDWALK_CONTINUE
;
1338 switch (ctx
->policy_type
) {
1339 case BGP_POLICY_ROUTE_MAP
:
1340 changed
= updgrp_route_map_update(updgrp
, ctx
->policy_name
,
1343 case BGP_POLICY_FILTER_LIST
:
1344 changed
= updgrp_filter_list_update(updgrp
, ctx
->policy_name
);
1346 case BGP_POLICY_PREFIX_LIST
:
1347 changed
= updgrp_prefix_list_update(updgrp
, ctx
->policy_name
);
1349 case BGP_POLICY_DISTRIBUTE_LIST
:
1351 updgrp_distribute_list_update(updgrp
, ctx
->policy_name
);
1357 /* If not doing route update, return after updating "config" */
1358 if (!ctx
->policy_route_update
)
1359 return UPDWALK_CONTINUE
;
1361 /* If nothing has changed, return after updating "config" */
1362 if (!changed
&& !def_changed
)
1363 return UPDWALK_CONTINUE
;
1366 * If something has changed, at the beginning of a route-map
1368 * event, mark each subgroup's needs-refresh bit. For one, it signals to
1369 * whoever that the subgroup needs a refresh. Second, it prevents
1371 * merge of this subgroup with another before a complete (outbound)
1374 if (ctx
->policy_event_start_flag
) {
1375 UPDGRP_FOREACH_SUBGRP(updgrp
, subgrp
)
1377 update_subgroup_set_needs_refresh(subgrp
, 1);
1379 return UPDWALK_CONTINUE
;
1382 UPDGRP_FOREACH_SUBGRP(updgrp
, subgrp
)
1385 if (bgp_debug_update(NULL
, NULL
, updgrp
, 0))
1387 "u%" PRIu64
":s%" PRIu64
1388 " announcing routes upon policy %s (type %d) change",
1389 updgrp
->id
, subgrp
->id
,
1390 ctx
->policy_name
, ctx
->policy_type
);
1391 subgroup_announce_route(subgrp
);
1394 if (bgp_debug_update(NULL
, NULL
, updgrp
, 0))
1396 "u%" PRIu64
":s%" PRIu64
1397 " announcing default upon default routemap %s change",
1398 updgrp
->id
, subgrp
->id
,
1400 subgroup_default_originate(subgrp
, 0);
1402 update_subgroup_set_needs_refresh(subgrp
, 0);
1404 return UPDWALK_CONTINUE
;
1407 static int update_group_walkcb(struct hash_backet
*backet
, void *arg
)
1409 struct update_group
*updgrp
= backet
->data
;
1410 struct updwalk_context
*wctx
= arg
;
1411 int ret
= (*wctx
->cb
)(updgrp
, wctx
->context
);
1415 static int update_group_periodic_merge_walkcb(struct update_group
*updgrp
,
1418 struct update_subgroup
*subgrp
;
1419 struct update_subgroup
*tmp_subgrp
;
1420 const char *reason
= arg
;
1422 UPDGRP_FOREACH_SUBGRP_SAFE(updgrp
, subgrp
, tmp_subgrp
)
1423 update_subgroup_check_merge(subgrp
, reason
);
1424 return UPDWALK_CONTINUE
;
1427 /********************
1429 ********************/
1432 * trigger function when a policy (route-map/filter-list/prefix-list/
1433 * distribute-list etc.) content changes. Go through all the
1434 * update groups and process the change.
1436 * bgp: the bgp instance
1437 * ptype: the type of policy that got modified, see bgpd.h
1438 * pname: name of the policy
1439 * route_update: flag to control if an automatic update generation should
1441 * start_event: flag that indicates if it's the beginning of the change.
1442 * Esp. when the user is changing the content interactively
1443 * over multiple statements. Useful to set dirty flag on
1446 void update_group_policy_update(struct bgp
*bgp
, bgp_policy_type_e ptype
,
1447 const char *pname
, int route_update
,
1450 struct updwalk_context ctx
;
1452 memset(&ctx
, 0, sizeof(ctx
));
1453 ctx
.policy_type
= ptype
;
1454 ctx
.policy_name
= pname
;
1455 ctx
.policy_route_update
= route_update
;
1456 ctx
.policy_event_start_flag
= start_event
;
1459 update_group_walk(bgp
, updgrp_policy_update_walkcb
, &ctx
);
1463 * update_subgroup_split_peer
1465 * Ensure that the given peer is in a subgroup of its own in the
1466 * specified update group.
1468 void update_subgroup_split_peer(struct peer_af
*paf
,
1469 struct update_group
*updgrp
)
1471 struct update_subgroup
*old_subgrp
, *subgrp
;
1475 old_subgrp
= paf
->subgroup
;
1478 updgrp
= old_subgrp
->update_group
;
1481 * If the peer is alone in its subgroup, reuse the existing
1484 if (old_subgrp
->peer_count
== 1) {
1485 if (updgrp
== old_subgrp
->update_group
)
1488 subgrp
= old_subgrp
;
1489 old_id
= old_subgrp
->update_group
->id
;
1491 if (bgp_debug_peer_updout_enabled(paf
->peer
->host
)) {
1492 UPDGRP_PEER_DBG_DIS(old_subgrp
->update_group
);
1495 update_group_remove_subgroup(old_subgrp
->update_group
,
1497 update_group_add_subgroup(updgrp
, subgrp
);
1499 if (bgp_debug_peer_updout_enabled(paf
->peer
->host
)) {
1500 UPDGRP_PEER_DBG_EN(updgrp
);
1502 if (BGP_DEBUG(update_groups
, UPDATE_GROUPS
))
1503 zlog_debug("u%" PRIu64
":s%" PRIu64
1504 " peer %s moved to u%" PRIu64
":s%" PRIu64
,
1505 old_id
, subgrp
->id
, paf
->peer
->host
,
1506 updgrp
->id
, subgrp
->id
);
1509 * The state of the subgroup (adj_out, advs, packet queue etc)
1510 * is consistent internally, but may not be identical to other
1511 * subgroups in the new update group even if the version number
1512 * matches up. Make sure a full refresh is done before the
1513 * subgroup is merged with another.
1515 update_subgroup_set_needs_refresh(subgrp
, 1);
1517 SUBGRP_INCR_STAT(subgrp
, updgrp_switch_events
);
1522 * Create a new subgroup under the specified update group, and copy
1523 * over relevant state to it.
1525 subgrp
= update_subgroup_create(updgrp
);
1526 update_subgroup_inherit_info(subgrp
, old_subgrp
);
1528 subgrp
->split_from
.update_group_id
= old_subgrp
->update_group
->id
;
1529 subgrp
->split_from
.subgroup_id
= old_subgrp
->id
;
1532 * Copy out relevant state from the old subgroup.
1534 update_subgroup_copy_adj_out(paf
->subgroup
, subgrp
);
1535 update_subgroup_copy_packets(subgrp
, paf
->next_pkt_to_send
);
1537 if (BGP_DEBUG(update_groups
, UPDATE_GROUPS
))
1538 zlog_debug("u%" PRIu64
":s%" PRIu64
1539 " peer %s split and moved into u%" PRIu64
1541 paf
->subgroup
->update_group
->id
, paf
->subgroup
->id
,
1542 paf
->peer
->host
, updgrp
->id
, subgrp
->id
);
1544 SUBGRP_INCR_STAT(paf
->subgroup
, split_events
);
1547 * Since queued advs were left behind, this new subgroup needs a
1550 update_subgroup_set_needs_refresh(subgrp
, 1);
1553 * Remove peer from old subgroup, and add it to the new one.
1555 update_subgroup_remove_peer(paf
->subgroup
, paf
);
1557 update_subgroup_add_peer(subgrp
, paf
, 1);
1560 void update_bgp_group_init(struct bgp
*bgp
)
1565 bgp
->update_groups
[afid
] =
1566 hash_create(updgrp_hash_key_make
, updgrp_hash_cmp
);
1569 void update_bgp_group_free(struct bgp
*bgp
)
1575 if (bgp
->update_groups
[afid
]) {
1576 hash_free(bgp
->update_groups
[afid
]);
1577 bgp
->update_groups
[afid
] = NULL
;
1582 void update_group_show(struct bgp
*bgp
, afi_t afi
, safi_t safi
, struct vty
*vty
,
1585 struct updwalk_context ctx
;
1586 memset(&ctx
, 0, sizeof(ctx
));
1588 ctx
.subgrp_id
= subgrp_id
;
1590 update_group_af_walk(bgp
, afi
, safi
, update_group_show_walkcb
, &ctx
);
1594 * update_group_show_stats
1596 * Show global statistics about update groups.
1598 void update_group_show_stats(struct bgp
*bgp
, struct vty
*vty
)
1600 vty_out(vty
, "Update groups created: %u%s",
1601 bgp
->update_group_stats
.updgrps_created
, VTY_NEWLINE
);
1602 vty_out(vty
, "Update groups deleted: %u%s",
1603 bgp
->update_group_stats
.updgrps_deleted
, VTY_NEWLINE
);
1604 vty_out(vty
, "Update subgroups created: %u%s",
1605 bgp
->update_group_stats
.subgrps_created
, VTY_NEWLINE
);
1606 vty_out(vty
, "Update subgroups deleted: %u%s",
1607 bgp
->update_group_stats
.subgrps_deleted
, VTY_NEWLINE
);
1608 vty_out(vty
, "Join events: %u%s", bgp
->update_group_stats
.join_events
,
1610 vty_out(vty
, "Prune events: %u%s", bgp
->update_group_stats
.prune_events
,
1612 vty_out(vty
, "Merge events: %u%s", bgp
->update_group_stats
.merge_events
,
1614 vty_out(vty
, "Split events: %u%s", bgp
->update_group_stats
.split_events
,
1616 vty_out(vty
, "Update group switch events: %u%s",
1617 bgp
->update_group_stats
.updgrp_switch_events
, VTY_NEWLINE
);
1618 vty_out(vty
, "Peer route refreshes combined: %u%s",
1619 bgp
->update_group_stats
.peer_refreshes_combined
, VTY_NEWLINE
);
1620 vty_out(vty
, "Merge checks triggered: %u%s",
1621 bgp
->update_group_stats
.merge_checks_triggered
, VTY_NEWLINE
);
1625 * update_group_adjust_peer
1627 void update_group_adjust_peer(struct peer_af
*paf
)
1629 struct update_group
*updgrp
;
1630 struct update_subgroup
*subgrp
, *old_subgrp
;
1636 peer
= PAF_PEER(paf
);
1637 if (!peer_established(peer
)) {
1641 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_CONFIG_NODE
)) {
1645 if (!peer
->afc_nego
[paf
->afi
][paf
->safi
]) {
1649 updgrp
= update_group_find(paf
);
1651 updgrp
= update_group_create(paf
);
1653 zlog_err("couldn't create update group for peer %s",
1659 old_subgrp
= paf
->subgroup
;
1664 * If the update group of the peer is unchanged, the peer can
1666 * in its existing subgroup and we're done.
1668 if (old_subgrp
->update_group
== updgrp
)
1672 * The peer is switching between update groups. Put it in its
1673 * own subgroup under the new update group.
1675 update_subgroup_split_peer(paf
, updgrp
);
1679 subgrp
= update_subgroup_find(updgrp
, paf
);
1681 subgrp
= update_subgroup_create(updgrp
);
1686 update_subgroup_add_peer(subgrp
, paf
, 1);
1687 if (BGP_DEBUG(update_groups
, UPDATE_GROUPS
))
1688 zlog_debug("u%" PRIu64
":s%" PRIu64
" add peer %s", updgrp
->id
,
1689 subgrp
->id
, paf
->peer
->host
);
1694 int update_group_adjust_soloness(struct peer
*peer
, int set
)
1696 struct peer_group
*group
;
1697 struct listnode
*node
, *nnode
;
1699 if (!CHECK_FLAG(peer
->sflags
, PEER_STATUS_GROUP
)) {
1700 peer_lonesoul_or_not(peer
, set
);
1701 if (peer
->status
== Established
)
1702 bgp_announce_route_all(peer
);
1704 group
= peer
->group
;
1705 for (ALL_LIST_ELEMENTS(group
->peer
, node
, nnode
, peer
)) {
1706 peer_lonesoul_or_not(peer
, set
);
1707 if (peer
->status
== Established
)
1708 bgp_announce_route_all(peer
);
1715 * update_subgroup_rib
1717 struct bgp_table
*update_subgroup_rib(struct update_subgroup
*subgrp
)
1721 bgp
= SUBGRP_INST(subgrp
);
1725 return bgp
->rib
[SUBGRP_AFI(subgrp
)][SUBGRP_SAFI(subgrp
)];
1728 void update_group_af_walk(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1729 updgrp_walkcb cb
, void *ctx
)
1731 struct updwalk_context wctx
;
1736 afid
= afindex(afi
, safi
);
1737 if (afid
>= BGP_AF_MAX
)
1740 memset(&wctx
, 0, sizeof(wctx
));
1744 if (bgp
->update_groups
[afid
])
1745 hash_walk(bgp
->update_groups
[afid
], update_group_walkcb
, &wctx
);
1748 void update_group_walk(struct bgp
*bgp
, updgrp_walkcb cb
, void *ctx
)
1753 FOREACH_AFI_SAFI(afi
, safi
)
1755 update_group_af_walk(bgp
, afi
, safi
, cb
, ctx
);
1759 void update_group_periodic_merge(struct bgp
*bgp
)
1761 char reason
[] = "periodic merge check";
1763 update_group_walk(bgp
, update_group_periodic_merge_walkcb
,
1768 update_group_default_originate_route_map_walkcb(struct update_group
*updgrp
,
1771 struct update_subgroup
*subgrp
;
1776 UPDGRP_FOREACH_SUBGRP(updgrp
, subgrp
)
1778 peer
= SUBGRP_PEER(subgrp
);
1779 afi
= SUBGRP_AFI(subgrp
);
1780 safi
= SUBGRP_SAFI(subgrp
);
1782 if (peer
->default_rmap
[afi
][safi
].name
) {
1783 subgroup_default_originate(subgrp
, 0);
1787 return UPDWALK_CONTINUE
;
1790 int update_group_refresh_default_originate_route_map(struct thread
*thread
)
1793 char reason
[] = "refresh default-originate route-map";
1795 bgp
= THREAD_ARG(thread
);
1796 update_group_walk(bgp
, update_group_default_originate_route_map_walkcb
,
1798 THREAD_TIMER_OFF(bgp
->t_rmap_def_originate_eval
);
1805 * peer_af_announce_route
1807 * Refreshes routes out to a peer_af immediately.
1809 * If the combine parameter is TRUE, then this function will try to
1810 * gather other peers in the subgroup for which a route announcement
1811 * is pending and efficently announce routes to all of them.
1813 * For now, the 'combine' option has an effect only if all peers in
1814 * the subgroup have a route announcement pending.
1816 void peer_af_announce_route(struct peer_af
*paf
, int combine
)
1818 struct update_subgroup
*subgrp
;
1819 struct peer_af
*cur_paf
;
1822 subgrp
= paf
->subgroup
;
1827 * If there are other peers in the old subgroup that also need
1828 * routes to be announced, pull them into the peer's new
1830 * Combine route announcement with other peers if possible.
1832 * For now, we combine only if all peers in the subgroup have an
1833 * announcement pending.
1837 SUBGRP_FOREACH_PEER(subgrp
, cur_paf
)
1842 if (cur_paf
->t_announce_route
)
1850 * Announce to the peer alone if we were not asked to combine peers,
1851 * or if some peers don't have a route annoucement pending.
1853 if (!combine
|| !all_pending
) {
1854 update_subgroup_split_peer(paf
, NULL
);
1858 if (bgp_debug_update(paf
->peer
, NULL
, subgrp
->update_group
, 0))
1859 zlog_debug("u%" PRIu64
":s%" PRIu64
1860 " %s announcing routes",
1861 subgrp
->update_group
->id
, subgrp
->id
,
1864 subgroup_announce_route(paf
->subgroup
);
1869 * We will announce routes the entire subgroup.
1871 * First stop refresh timers on all the other peers.
1873 SUBGRP_FOREACH_PEER(subgrp
, cur_paf
)
1878 bgp_stop_announce_route_timer(cur_paf
);
1881 if (bgp_debug_update(paf
->peer
, NULL
, subgrp
->update_group
, 0))
1882 zlog_debug("u%" PRIu64
":s%" PRIu64
1883 " announcing routes to %s, combined into %d peers",
1884 subgrp
->update_group
->id
, subgrp
->id
,
1885 paf
->peer
->host
, subgrp
->peer_count
);
1887 subgroup_announce_route(subgrp
);
1889 SUBGRP_INCR_STAT_BY(subgrp
, peer_refreshes_combined
,
1890 subgrp
->peer_count
- 1);
1893 void subgroup_trigger_write(struct update_subgroup
*subgrp
)
1895 struct peer_af
*paf
;
1898 if (bgp_debug_update(NULL
, NULL
, subgrp
->update_group
, 0))
1899 zlog_debug("u%llu:s%llu scheduling write thread for peers",
1900 subgrp
->update_group
->id
, subgrp
->id
);
1902 SUBGRP_FOREACH_PEER(subgrp
, paf
)
1904 if (paf
->peer
->status
== Established
) {
1905 BGP_PEER_WRITE_ON(paf
->peer
->t_write
, bgp_write
,
1906 paf
->peer
->fd
, paf
->peer
);
1911 int update_group_clear_update_dbg(struct update_group
*updgrp
, void *arg
)
1913 UPDGRP_PEER_DBG_OFF(updgrp
);
1914 return UPDWALK_CONTINUE
;
1917 /* Return true if we should addpath encode NLRI to this peer */
1918 int bgp_addpath_encode_tx(struct peer
*peer
, afi_t afi
, safi_t safi
)
1920 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_TX_ADV
)
1921 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
1922 PEER_CAP_ADDPATH_AF_RX_RCV
));
1926 * Return true if this is a path we should advertise due to a
1927 * configured addpath-tx knob
1929 int bgp_addpath_tx_path(struct peer
*peer
, afi_t afi
, safi_t safi
,
1930 struct bgp_info
*ri
)
1932 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1933 PEER_FLAG_ADDPATH_TX_ALL_PATHS
))
1936 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1937 PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS
)
1938 && CHECK_FLAG(ri
->flags
, BGP_INFO_DMED_SELECTED
))