]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_updgrp.c
Merge pull request #11903 from sri-mohan1/sri-bfd-dbg1
[mirror_frr.git] / bgpd / bgp_updgrp.c
CommitLineData
3f9c7369
DS
1/**
2 * bgp_updgrp.c: BGP update group structures
3 *
4 * @copyright Copyright (C) 2014 Cumulus Networks, Inc.
5 *
6 * @author Avneesh Sachdev <avneesh@sproute.net>
7 * @author Rajesh Varadarajan <rajesh@sproute.net>
8 * @author Pradosh Mohapatra <pradosh@sproute.net>
9 *
10 * This file is part of GNU Zebra.
11 *
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
15 * later version.
16 *
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.
21 *
896014f4
DL
22 * You should have received a copy of the GNU General Public License along
23 * with this program; see the file COPYING; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
3f9c7369
DS
25 */
26
27#include <zebra.h>
28
29#include "prefix.h"
30#include "thread.h"
31#include "buffer.h"
32#include "stream.h"
33#include "command.h"
34#include "sockunion.h"
35#include "network.h"
36#include "memory.h"
37#include "filter.h"
38#include "routemap.h"
3f9c7369
DS
39#include "log.h"
40#include "plist.h"
41#include "linklist.h"
42#include "workqueue.h"
43#include "hash.h"
44#include "jhash.h"
45#include "queue.h"
46
47#include "bgpd/bgpd.h"
48#include "bgpd/bgp_table.h"
49#include "bgpd/bgp_debug.h"
14454c9f 50#include "bgpd/bgp_errors.h"
3f9c7369 51#include "bgpd/bgp_fsm.h"
b1dd7180 52#include "bgpd/bgp_addpath.h"
3f9c7369
DS
53#include "bgpd/bgp_advertise.h"
54#include "bgpd/bgp_packet.h"
55#include "bgpd/bgp_updgrp.h"
56#include "bgpd/bgp_route.h"
57#include "bgpd/bgp_filter.h"
2fc102e1 58#include "bgpd/bgp_io.h"
3f9c7369
DS
59
60/********************
61 * PRIVATE FUNCTIONS
62 ********************/
63
64/**
65 * assign a unique ID to update group and subgroup. Mostly for display/
66 * debugging purposes. It's a 64-bit space - used leisurely without a
67 * worry about its wrapping and about filling gaps. While at it, timestamp
68 * the creation.
69 */
d62a17ae 70static void update_group_checkin(struct update_group *updgrp)
3f9c7369 71{
d62a17ae 72 updgrp->id = ++bm->updgrp_idspace;
083ec940 73 updgrp->uptime = monotime(NULL);
3f9c7369
DS
74}
75
d62a17ae 76static void update_subgroup_checkin(struct update_subgroup *subgrp,
77 struct update_group *updgrp)
3f9c7369 78{
d62a17ae 79 subgrp->id = ++bm->subgrp_idspace;
083ec940 80 subgrp->uptime = monotime(NULL);
3f9c7369
DS
81}
82
ef56aee4
DA
83static void sync_init(struct update_subgroup *subgrp,
84 struct update_group *updgrp)
3f9c7369 85{
ef56aee4
DA
86 struct peer *peer = UPDGRP_PEER(updgrp);
87
d62a17ae 88 subgrp->sync =
89 XCALLOC(MTYPE_BGP_SYNCHRONISE, sizeof(struct bgp_synchronize));
a274fef8
DL
90 bgp_adv_fifo_init(&subgrp->sync->update);
91 bgp_adv_fifo_init(&subgrp->sync->withdraw);
92 bgp_adv_fifo_init(&subgrp->sync->withdraw_low);
996c9314 93 subgrp->hash =
4d28080c
DA
94 hash_create(bgp_advertise_attr_hash_key,
95 bgp_advertise_attr_hash_cmp, "BGP SubGroup Hash");
d62a17ae 96
97 /* We use a larger buffer for subgrp->work in the event that:
98 * - We RX a BGP_UPDATE where the attributes alone are just
ef56aee4 99 * under 4096 or 65535 (if Extended Message capability negotiated).
d62a17ae 100 * - The user configures an outbound route-map that does many as-path
101 * prepends or adds many communities. At most they can have
102 * CMD_ARGC_MAX
103 * args in a route-map so there is a finite limit on how large they
104 * can
105 * make the attributes.
106 *
107 * Having a buffer with BGP_MAX_PACKET_SIZE_OVERFLOW allows us to avoid
108 * bounds
109 * checking for every single attribute as we construct an UPDATE.
110 */
ef56aee4
DA
111 subgrp->work = stream_new(peer->max_packet_size
112 + BGP_MAX_PACKET_SIZE_OVERFLOW);
113 subgrp->scratch = stream_new(peer->max_packet_size);
3f9c7369
DS
114}
115
d62a17ae 116static void sync_delete(struct update_subgroup *subgrp)
3f9c7369 117{
0a22ddfb 118 XFREE(MTYPE_BGP_SYNCHRONISE, subgrp->sync);
e92cf867 119 if (subgrp->hash) {
4d28080c
DA
120 hash_clean(subgrp->hash,
121 (void (*)(void *))bgp_advertise_attr_free);
d62a17ae 122 hash_free(subgrp->hash);
e92cf867 123 }
d62a17ae 124 subgrp->hash = NULL;
125 if (subgrp->work)
126 stream_free(subgrp->work);
127 subgrp->work = NULL;
128 if (subgrp->scratch)
129 stream_free(subgrp->scratch);
130 subgrp->scratch = NULL;
3f9c7369
DS
131}
132
133/**
134 * conf_copy
135 *
136 * copy only those fields that are relevant to update group match
137 */
d62a17ae 138static void conf_copy(struct peer *dst, struct peer *src, afi_t afi,
139 safi_t safi)
3f9c7369 140{
d62a17ae 141 struct bgp_filter *srcfilter;
142 struct bgp_filter *dstfilter;
143
144 srcfilter = &src->filter[afi][safi];
145 dstfilter = &dst->filter[afi][safi];
146
147 dst->bgp = src->bgp;
148 dst->sort = src->sort;
149 dst->as = src->as;
150 dst->v_routeadv = src->v_routeadv;
151 dst->flags = src->flags;
152 dst->af_flags[afi][safi] = src->af_flags[afi][safi];
fde246e8 153 dst->pmax_out[afi][safi] = src->pmax_out[afi][safi];
ef56aee4 154 dst->max_packet_size = src->max_packet_size;
0a22ddfb 155 XFREE(MTYPE_BGP_PEER_HOST, dst->host);
d62a17ae 156
157 dst->host = XSTRDUP(MTYPE_BGP_PEER_HOST, src->host);
158 dst->cap = src->cap;
159 dst->af_cap[afi][safi] = src->af_cap[afi][safi];
160 dst->afc_nego[afi][safi] = src->afc_nego[afi][safi];
161 dst->orf_plist[afi][safi] = src->orf_plist[afi][safi];
dcc68b5e 162 dst->addpath_type[afi][safi] = src->addpath_type[afi][safi];
d62a17ae 163 dst->local_as = src->local_as;
164 dst->change_local_as = src->change_local_as;
165 dst->shared_network = src->shared_network;
d864dd9e 166 dst->local_role = src->local_role;
01da2d26
DA
167
168 if (src->soo[afi][safi]) {
169 ecommunity_free(&dst->soo[afi][safi]);
170 dst->soo[afi][safi] = ecommunity_dup(src->soo[afi][safi]);
171 }
172
d62a17ae 173 memcpy(&(dst->nexthop), &(src->nexthop), sizeof(struct bgp_nexthop));
174
175 dst->group = src->group;
176
177 if (src->default_rmap[afi][safi].name) {
178 dst->default_rmap[afi][safi].name =
179 XSTRDUP(MTYPE_ROUTE_MAP_NAME,
180 src->default_rmap[afi][safi].name);
181 dst->default_rmap[afi][safi].map =
182 src->default_rmap[afi][safi].map;
183 }
184
185 if (DISTRIBUTE_OUT_NAME(srcfilter)) {
186 DISTRIBUTE_OUT_NAME(dstfilter) = XSTRDUP(
187 MTYPE_BGP_FILTER_NAME, DISTRIBUTE_OUT_NAME(srcfilter));
188 DISTRIBUTE_OUT(dstfilter) = DISTRIBUTE_OUT(srcfilter);
189 }
190
191 if (PREFIX_LIST_OUT_NAME(srcfilter)) {
192 PREFIX_LIST_OUT_NAME(dstfilter) = XSTRDUP(
193 MTYPE_BGP_FILTER_NAME, PREFIX_LIST_OUT_NAME(srcfilter));
194 PREFIX_LIST_OUT(dstfilter) = PREFIX_LIST_OUT(srcfilter);
195 }
196
197 if (FILTER_LIST_OUT_NAME(srcfilter)) {
198 FILTER_LIST_OUT_NAME(dstfilter) = XSTRDUP(
199 MTYPE_BGP_FILTER_NAME, FILTER_LIST_OUT_NAME(srcfilter));
200 FILTER_LIST_OUT(dstfilter) = FILTER_LIST_OUT(srcfilter);
201 }
202
203 if (ROUTE_MAP_OUT_NAME(srcfilter)) {
204 ROUTE_MAP_OUT_NAME(dstfilter) = XSTRDUP(
205 MTYPE_BGP_FILTER_NAME, ROUTE_MAP_OUT_NAME(srcfilter));
206 ROUTE_MAP_OUT(dstfilter) = ROUTE_MAP_OUT(srcfilter);
207 }
208
209 if (UNSUPPRESS_MAP_NAME(srcfilter)) {
210 UNSUPPRESS_MAP_NAME(dstfilter) = XSTRDUP(
211 MTYPE_BGP_FILTER_NAME, UNSUPPRESS_MAP_NAME(srcfilter));
212 UNSUPPRESS_MAP(dstfilter) = UNSUPPRESS_MAP(srcfilter);
213 }
7f7940e6
MK
214
215 if (ADVERTISE_MAP_NAME(srcfilter)) {
216 ADVERTISE_MAP_NAME(dstfilter) = XSTRDUP(
217 MTYPE_BGP_FILTER_NAME, ADVERTISE_MAP_NAME(srcfilter));
218 ADVERTISE_MAP(dstfilter) = ADVERTISE_MAP(srcfilter);
219 ADVERTISE_CONDITION(dstfilter) = ADVERTISE_CONDITION(srcfilter);
220 }
221
222 if (CONDITION_MAP_NAME(srcfilter)) {
223 CONDITION_MAP_NAME(dstfilter) = XSTRDUP(
224 MTYPE_BGP_FILTER_NAME, CONDITION_MAP_NAME(srcfilter));
225 CONDITION_MAP(dstfilter) = CONDITION_MAP(srcfilter);
226 }
f373ce6c
QY
227
228 dstfilter->advmap.update_type = srcfilter->advmap.update_type;
3f9c7369
DS
229}
230
231/**
6e919709 232 * since we did a bunch of XSTRDUP's in conf_copy, time to free them up
3f9c7369 233 */
d62a17ae 234static void conf_release(struct peer *src, afi_t afi, safi_t safi)
3f9c7369 235{
d62a17ae 236 struct bgp_filter *srcfilter;
3f9c7369 237
d62a17ae 238 srcfilter = &src->filter[afi][safi];
3f9c7369 239
0a22ddfb 240 XFREE(MTYPE_ROUTE_MAP_NAME, src->default_rmap[afi][safi].name);
3f9c7369 241
0a22ddfb 242 XFREE(MTYPE_BGP_FILTER_NAME, srcfilter->dlist[FILTER_OUT].name);
3f9c7369 243
0a22ddfb 244 XFREE(MTYPE_BGP_FILTER_NAME, srcfilter->plist[FILTER_OUT].name);
3f9c7369 245
0a22ddfb 246 XFREE(MTYPE_BGP_FILTER_NAME, srcfilter->aslist[FILTER_OUT].name);
3f9c7369 247
0a22ddfb 248 XFREE(MTYPE_BGP_FILTER_NAME, srcfilter->map[RMAP_OUT].name);
3f9c7369 249
0a22ddfb 250 XFREE(MTYPE_BGP_FILTER_NAME, srcfilter->usmap.name);
495f0b13 251
7f7940e6
MK
252 XFREE(MTYPE_BGP_FILTER_NAME, srcfilter->advmap.aname);
253
254 XFREE(MTYPE_BGP_FILTER_NAME, srcfilter->advmap.cname);
255
0a22ddfb 256 XFREE(MTYPE_BGP_PEER_HOST, src->host);
3f9c7369
DS
257}
258
d62a17ae 259static void peer2_updgrp_copy(struct update_group *updgrp, struct peer_af *paf)
3f9c7369 260{
d62a17ae 261 struct peer *src;
262 struct peer *dst;
3f9c7369 263
d62a17ae 264 if (!updgrp || !paf)
265 return;
3f9c7369 266
d62a17ae 267 src = paf->peer;
268 dst = updgrp->conf;
269 if (!src || !dst)
270 return;
3f9c7369 271
d62a17ae 272 updgrp->afi = paf->afi;
273 updgrp->safi = paf->safi;
274 updgrp->afid = paf->afid;
275 updgrp->bgp = src->bgp;
3f9c7369 276
d62a17ae 277 conf_copy(dst, src, paf->afi, paf->safi);
3f9c7369
DS
278}
279
280/**
281 * auxiliary functions to maintain the hash table.
282 * - updgrp_hash_alloc - to create a new entry, passed to hash_get
283 * - updgrp_hash_key_make - makes the key for update group search
284 * - updgrp_hash_cmp - compare two update groups.
285 */
d62a17ae 286static void *updgrp_hash_alloc(void *p)
3f9c7369 287{
d62a17ae 288 struct update_group *updgrp;
289 const struct update_group *in;
290
291 in = (const struct update_group *)p;
292 updgrp = XCALLOC(MTYPE_BGP_UPDGRP, sizeof(struct update_group));
293 memcpy(updgrp, in, sizeof(struct update_group));
294 updgrp->conf = XCALLOC(MTYPE_BGP_PEER, sizeof(struct peer));
295 conf_copy(updgrp->conf, in->conf, in->afi, in->safi);
296 return updgrp;
3f9c7369
DS
297}
298
299/**
300 * The hash value for a peer is computed from the following variables:
301 * v = f(
302 * 1. IBGP (1) or EBGP (2)
303 * 2. FLAGS based on configuration:
304 * LOCAL_AS_NO_PREPEND
305 * LOCAL_AS_REPLACE_AS
306 * 3. AF_FLAGS based on configuration:
307 * Refer to definition in bgp_updgrp.h
308 * 4. (AF-independent) Capability flags:
309 * AS4_RCV capability
310 * 5. (AF-dependent) Capability flags:
311 * ORF_PREFIX_SM_RCV (peer can send prefix ORF)
312 * 6. MRAI
313 * 7. peer-group name
314 * 8. Outbound route-map name (neighbor route-map <> out)
315 * 9. Outbound distribute-list name (neighbor distribute-list <> out)
316 * 10. Outbound prefix-list name (neighbor prefix-list <> out)
317 * 11. Outbound as-list name (neighbor filter-list <> out)
318 * 12. Unsuppress map name (neighbor unsuppress-map <>)
319 * 13. default rmap name (neighbor default-originate route-map <>)
320 * 14. encoding both global and link-local nexthop?
321 * 15. If peer is configured to be a lonesoul, peer ip address
322 * 16. Local-as should match, if configured.
e0267260 323 * 17. maximum-prefix-out
d864dd9e 324 * 18. Local-role should also match, if configured.
3f9c7369
DS
325 * )
326 */
d8b87afe 327static unsigned int updgrp_hash_key_make(const void *p)
3f9c7369 328{
d62a17ae 329 const struct update_group *updgrp;
330 const struct peer *peer;
331 const struct bgp_filter *filter;
332 uint32_t flags;
333 uint32_t key;
334 afi_t afi;
335 safi_t safi;
3f9c7369
DS
336
337#define SEED1 999331
338#define SEED2 2147483647
339
d62a17ae 340 updgrp = p;
341 peer = updgrp->conf;
342 afi = updgrp->afi;
343 safi = updgrp->safi;
344 flags = peer->af_flags[afi][safi];
345 filter = &peer->filter[afi][safi];
346
347 key = 0;
348
349 key = jhash_1word(peer->sort, key); /* EBGP or IBGP */
350 key = jhash_1word((peer->flags & PEER_UPDGRP_FLAGS), key);
351 key = jhash_1word((flags & PEER_UPDGRP_AF_FLAGS), key);
dcc68b5e 352 key = jhash_1word((uint32_t)peer->addpath_type[afi][safi], key);
d62a17ae 353 key = jhash_1word((peer->cap & PEER_UPDGRP_CAP_FLAGS), key);
354 key = jhash_1word((peer->af_cap[afi][safi] & PEER_UPDGRP_AF_CAP_FLAGS),
355 key);
356 key = jhash_1word(peer->v_routeadv, key);
357 key = jhash_1word(peer->change_local_as, key);
cecd7358 358 key = jhash_1word(peer->max_packet_size, key);
e0267260 359 key = jhash_1word(peer->pmax_out[afi][safi], key);
d62a17ae 360
361 if (peer->group)
362 key = jhash_1word(jhash(peer->group->name,
363 strlen(peer->group->name), SEED1),
364 key);
365
366 if (filter->map[RMAP_OUT].name)
367 key = jhash_1word(jhash(filter->map[RMAP_OUT].name,
368 strlen(filter->map[RMAP_OUT].name),
369 SEED1),
370 key);
371
372 if (filter->dlist[FILTER_OUT].name)
373 key = jhash_1word(jhash(filter->dlist[FILTER_OUT].name,
374 strlen(filter->dlist[FILTER_OUT].name),
375 SEED1),
376 key);
377
378 if (filter->plist[FILTER_OUT].name)
379 key = jhash_1word(jhash(filter->plist[FILTER_OUT].name,
380 strlen(filter->plist[FILTER_OUT].name),
381 SEED1),
382 key);
383
384 if (filter->aslist[FILTER_OUT].name)
385 key = jhash_1word(jhash(filter->aslist[FILTER_OUT].name,
386 strlen(filter->aslist[FILTER_OUT].name),
387 SEED1),
388 key);
389
390 if (filter->usmap.name)
391 key = jhash_1word(jhash(filter->usmap.name,
392 strlen(filter->usmap.name), SEED1),
393 key);
394
7f7940e6
MK
395 if (filter->advmap.aname)
396 key = jhash_1word(jhash(filter->advmap.aname,
397 strlen(filter->advmap.aname), SEED1),
398 key);
399
f373ce6c
QY
400 if (filter->advmap.update_type)
401 key = jhash_1word(filter->advmap.update_type, key);
402
d62a17ae 403 if (peer->default_rmap[afi][safi].name)
404 key = jhash_1word(
405 jhash(peer->default_rmap[afi][safi].name,
406 strlen(peer->default_rmap[afi][safi].name),
407 SEED1),
408 key);
409
410 /* If peer is on a shared network and is exchanging IPv6 prefixes,
411 * it needs to include link-local address. That's different from
412 * non-shared-network peers (nexthop encoded with 32 bytes vs 16
413 * bytes). We create different update groups to take care of that.
414 */
415 key = jhash_1word(
416 (peer->shared_network && peer_afi_active_nego(peer, AFI_IP6)),
417 key);
d62a17ae 418 /*
419 * There are certain peers that must get their own update-group:
420 * - lonesoul peers
421 * - peers that negotiated ORF
a849a3fe 422 * - maximum-prefix-out is set
d62a17ae 423 */
424 if (CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL)
425 || CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)
426 || CHECK_FLAG(peer->af_cap[afi][safi],
a849a3fe
DA
427 PEER_CAP_ORF_PREFIX_SM_OLD_RCV)
428 || CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_OUT))
d62a17ae 429 key = jhash_1word(jhash(peer->host, strlen(peer->host), SEED2),
430 key);
d864dd9e
EB
431 /*
432 * Multiple sessions with the same neighbor should get their own
433 * update-group if they have different roles.
434 */
435 key = jhash_1word(peer->local_role, key);
d62a17ae 436
01da2d26
DA
437 if (peer->soo[afi][safi]) {
438 char *soo_str = ecommunity_str(peer->soo[afi][safi]);
439
440 key = jhash_1word(jhash(soo_str, strlen(soo_str), SEED1), key);
441 }
442
34d8aff1
DS
443 if (bgp_debug_neighbor_events(peer)) {
444 zlog_debug(
da5e1a58 445 "%pBP Update Group Hash: sort: %d UpdGrpFlags: %ju UpdGrpAFFlags: %ju",
0ebabd41 446 peer, peer->sort,
da5e1a58
DA
447 (intmax_t)CHECK_FLAG(peer->flags, PEER_UPDGRP_FLAGS),
448 (intmax_t)CHECK_FLAG(flags, PEER_UPDGRP_AF_FLAGS));
34d8aff1
DS
449 zlog_debug(
450 "%pBP Update Group Hash: addpath: %u UpdGrpCapFlag: %u UpdGrpCapAFFlag: %u route_adv: %u change local as: %u",
451 peer, (uint32_t)peer->addpath_type[afi][safi],
da5e1a58
DA
452 CHECK_FLAG(peer->cap, PEER_UPDGRP_CAP_FLAGS),
453 CHECK_FLAG(peer->af_cap[afi][safi],
454 PEER_UPDGRP_AF_CAP_FLAGS),
34d8aff1
DS
455 peer->v_routeadv, peer->change_local_as);
456 zlog_debug(
457 "%pBP Update Group Hash: max packet size: %u pmax_out: %u Peer Group: %s rmap out: %s",
458 peer, peer->max_packet_size, peer->pmax_out[afi][safi],
459 peer->group ? peer->group->name : "(NONE)",
460 ROUTE_MAP_OUT_NAME(filter) ? ROUTE_MAP_OUT_NAME(filter)
461 : "(NONE)");
462 zlog_debug(
463 "%pBP Update Group Hash: dlist out: %s plist out: %s aslist out: %s usmap out: %s advmap: %s",
464 peer,
465 DISTRIBUTE_OUT_NAME(filter)
466 ? DISTRIBUTE_OUT_NAME(filter)
467 : "(NONE)",
468 PREFIX_LIST_OUT_NAME(filter)
469 ? PREFIX_LIST_OUT_NAME(filter)
470 : "(NONE)",
471 FILTER_LIST_OUT_NAME(filter)
472 ? FILTER_LIST_OUT_NAME(filter)
473 : "(NONE)",
474 UNSUPPRESS_MAP_NAME(filter)
475 ? UNSUPPRESS_MAP_NAME(filter)
476 : "(NONE)",
477 ADVERTISE_MAP_NAME(filter) ? ADVERTISE_MAP_NAME(filter)
478 : "(NONE)");
479 zlog_debug(
480 "%pBP Update Group Hash: default rmap: %s shared network and afi active network: %d",
481 peer,
482 peer->default_rmap[afi][safi].name
483 ? peer->default_rmap[afi][safi].name
484 : "(NONE)",
485 peer->shared_network &&
486 peer_afi_active_nego(peer, AFI_IP6));
487 zlog_debug(
da5e1a58 488 "%pBP Update Group Hash: Lonesoul: %d ORF prefix: %u ORF old: %u max prefix out: %ju",
37e70073 489 peer, !!CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL),
34d8aff1
DS
490 CHECK_FLAG(peer->af_cap[afi][safi],
491 PEER_CAP_ORF_PREFIX_SM_RCV),
492 CHECK_FLAG(peer->af_cap[afi][safi],
493 PEER_CAP_ORF_PREFIX_SM_OLD_RCV),
da5e1a58
DA
494 (intmax_t)CHECK_FLAG(peer->af_flags[afi][safi],
495 PEER_FLAG_MAX_PREFIX_OUT));
34d8aff1
DS
496 zlog_debug("%pBP Update Group Hash key: %u", peer, key);
497 }
d62a17ae 498 return key;
3f9c7369
DS
499}
500
74df8d6d 501static bool updgrp_hash_cmp(const void *p1, const void *p2)
3f9c7369 502{
d62a17ae 503 const struct update_group *grp1;
504 const struct update_group *grp2;
505 const struct peer *pe1;
506 const struct peer *pe2;
507 uint32_t flags1;
508 uint32_t flags2;
509 const struct bgp_filter *fl1;
510 const struct bgp_filter *fl2;
511 afi_t afi;
512 safi_t safi;
513
514 if (!p1 || !p2)
74df8d6d 515 return false;
d62a17ae 516
517 grp1 = p1;
518 grp2 = p2;
519 pe1 = grp1->conf;
520 pe2 = grp2->conf;
521 afi = grp1->afi;
522 safi = grp1->safi;
523 flags1 = pe1->af_flags[afi][safi];
524 flags2 = pe2->af_flags[afi][safi];
525 fl1 = &pe1->filter[afi][safi];
526 fl2 = &pe2->filter[afi][safi];
527
528 /* put EBGP and IBGP peers in different update groups */
529 if (pe1->sort != pe2->sort)
74df8d6d 530 return false;
d62a17ae 531
532 /* check peer flags */
533 if ((pe1->flags & PEER_UPDGRP_FLAGS)
534 != (pe2->flags & PEER_UPDGRP_FLAGS))
74df8d6d 535 return false;
d62a17ae 536
537 /* If there is 'local-as' configured, it should match. */
538 if (pe1->change_local_as != pe2->change_local_as)
74df8d6d 539 return false;
d62a17ae 540
e0267260
LS
541 if (pe1->pmax_out[afi][safi] != pe2->pmax_out[afi][safi])
542 return false;
543
d62a17ae 544 /* flags like route reflector client */
545 if ((flags1 & PEER_UPDGRP_AF_FLAGS) != (flags2 & PEER_UPDGRP_AF_FLAGS))
74df8d6d 546 return false;
d62a17ae 547
dcc68b5e 548 if (pe1->addpath_type[afi][safi] != pe2->addpath_type[afi][safi])
b08047f8 549 return false;
dcc68b5e 550
d62a17ae 551 if ((pe1->cap & PEER_UPDGRP_CAP_FLAGS)
552 != (pe2->cap & PEER_UPDGRP_CAP_FLAGS))
74df8d6d 553 return false;
d62a17ae 554
555 if ((pe1->af_cap[afi][safi] & PEER_UPDGRP_AF_CAP_FLAGS)
556 != (pe2->af_cap[afi][safi] & PEER_UPDGRP_AF_CAP_FLAGS))
74df8d6d 557 return false;
d62a17ae 558
559 if (pe1->v_routeadv != pe2->v_routeadv)
74df8d6d 560 return false;
d62a17ae 561
562 if (pe1->group != pe2->group)
74df8d6d 563 return false;
d62a17ae 564
d864dd9e
EB
565 /* Roles can affect filtering */
566 if (pe1->local_role != pe2->local_role)
567 return false;
568
d62a17ae 569 /* route-map names should be the same */
570 if ((fl1->map[RMAP_OUT].name && !fl2->map[RMAP_OUT].name)
571 || (!fl1->map[RMAP_OUT].name && fl2->map[RMAP_OUT].name)
572 || (fl1->map[RMAP_OUT].name && fl2->map[RMAP_OUT].name
573 && strcmp(fl1->map[RMAP_OUT].name, fl2->map[RMAP_OUT].name)))
74df8d6d 574 return false;
d62a17ae 575
576 if ((fl1->dlist[FILTER_OUT].name && !fl2->dlist[FILTER_OUT].name)
577 || (!fl1->dlist[FILTER_OUT].name && fl2->dlist[FILTER_OUT].name)
578 || (fl1->dlist[FILTER_OUT].name && fl2->dlist[FILTER_OUT].name
579 && strcmp(fl1->dlist[FILTER_OUT].name,
580 fl2->dlist[FILTER_OUT].name)))
74df8d6d 581 return false;
d62a17ae 582
583 if ((fl1->plist[FILTER_OUT].name && !fl2->plist[FILTER_OUT].name)
584 || (!fl1->plist[FILTER_OUT].name && fl2->plist[FILTER_OUT].name)
585 || (fl1->plist[FILTER_OUT].name && fl2->plist[FILTER_OUT].name
586 && strcmp(fl1->plist[FILTER_OUT].name,
587 fl2->plist[FILTER_OUT].name)))
74df8d6d 588 return false;
d62a17ae 589
590 if ((fl1->aslist[FILTER_OUT].name && !fl2->aslist[FILTER_OUT].name)
591 || (!fl1->aslist[FILTER_OUT].name && fl2->aslist[FILTER_OUT].name)
592 || (fl1->aslist[FILTER_OUT].name && fl2->aslist[FILTER_OUT].name
593 && strcmp(fl1->aslist[FILTER_OUT].name,
594 fl2->aslist[FILTER_OUT].name)))
74df8d6d 595 return false;
d62a17ae 596
597 if ((fl1->usmap.name && !fl2->usmap.name)
598 || (!fl1->usmap.name && fl2->usmap.name)
599 || (fl1->usmap.name && fl2->usmap.name
600 && strcmp(fl1->usmap.name, fl2->usmap.name)))
74df8d6d 601 return false;
d62a17ae 602
7f7940e6
MK
603 if ((fl1->advmap.aname && !fl2->advmap.aname)
604 || (!fl1->advmap.aname && fl2->advmap.aname)
605 || (fl1->advmap.aname && fl2->advmap.aname
606 && strcmp(fl1->advmap.aname, fl2->advmap.aname)))
607 return false;
608
f373ce6c
QY
609 if (fl1->advmap.update_type != fl2->advmap.update_type)
610 return false;
611
d62a17ae 612 if ((pe1->default_rmap[afi][safi].name
613 && !pe2->default_rmap[afi][safi].name)
614 || (!pe1->default_rmap[afi][safi].name
615 && pe2->default_rmap[afi][safi].name)
616 || (pe1->default_rmap[afi][safi].name
617 && pe2->default_rmap[afi][safi].name
618 && strcmp(pe1->default_rmap[afi][safi].name,
619 pe2->default_rmap[afi][safi].name)))
74df8d6d 620 return false;
d62a17ae 621
622 if ((afi == AFI_IP6) && (pe1->shared_network != pe2->shared_network))
74df8d6d 623 return false;
d62a17ae 624
625 if ((CHECK_FLAG(pe1->flags, PEER_FLAG_LONESOUL)
626 || CHECK_FLAG(pe1->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)
627 || CHECK_FLAG(pe1->af_cap[afi][safi],
628 PEER_CAP_ORF_PREFIX_SM_OLD_RCV))
629 && !sockunion_same(&pe1->su, &pe2->su))
74df8d6d 630 return false;
d62a17ae 631
74df8d6d 632 return true;
3f9c7369
DS
633}
634
d62a17ae 635static void peer_lonesoul_or_not(struct peer *peer, int set)
3f9c7369 636{
d62a17ae 637 /* no change in status? */
638 if (set == (CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL) > 0))
639 return;
3f9c7369 640
d62a17ae 641 if (set)
642 SET_FLAG(peer->flags, PEER_FLAG_LONESOUL);
643 else
644 UNSET_FLAG(peer->flags, PEER_FLAG_LONESOUL);
3f9c7369 645
d62a17ae 646 update_group_adjust_peer_afs(peer);
3f9c7369
DS
647}
648
649/*
650 * subgroup_total_packets_enqueued
651 *
652 * Returns the total number of packets enqueued to a subgroup.
653 */
654static unsigned int
d62a17ae 655subgroup_total_packets_enqueued(struct update_subgroup *subgrp)
3f9c7369 656{
d62a17ae 657 struct bpacket *pkt;
3f9c7369 658
d62a17ae 659 pkt = bpacket_queue_last(SUBGRP_PKTQ(subgrp));
3f9c7369 660
d62a17ae 661 return pkt->ver - 1;
3f9c7369
DS
662}
663
d62a17ae 664static int update_group_show_walkcb(struct update_group *updgrp, void *arg)
3f9c7369 665{
d62a17ae 666 struct updwalk_context *ctx = arg;
667 struct vty *vty;
668 struct update_subgroup *subgrp;
669 struct peer_af *paf;
670 struct bgp_filter *filter;
0997ee26 671 struct peer *peer = UPDGRP_PEER(updgrp);
d62a17ae 672 int match = 0;
673
674 if (!ctx)
675 return CMD_SUCCESS;
676
677 if (ctx->subgrp_id) {
a2addae8 678 UPDGRP_FOREACH_SUBGRP (updgrp, subgrp) {
d62a17ae 679 if (ctx->subgrp_id && (ctx->subgrp_id != subgrp->id))
680 continue;
681 else {
682 match = 1;
683 break;
684 }
685 }
686 } else {
687 match = 1;
688 }
689
690 if (!match) {
691 /* Since this routine is invoked from a walk, we cannot signal
692 * any */
693 /* error here, can only return. */
694 return CMD_SUCCESS;
695 }
696
697 vty = ctx->vty;
698
699 vty_out(vty, "Update-group %" PRIu64 ":\n", updgrp->id);
700 vty_out(vty, " Created: %s", timestamp_string(updgrp->uptime));
701 filter = &updgrp->conf->filter[updgrp->afi][updgrp->safi];
702 if (filter->map[RMAP_OUT].name)
7dba67ff 703 vty_out(vty, " Outgoing route map: %s\n",
d62a17ae 704 filter->map[RMAP_OUT].name);
705 vty_out(vty, " MRAI value (seconds): %d\n", updgrp->conf->v_routeadv);
706 if (updgrp->conf->change_local_as)
707 vty_out(vty, " Local AS %u%s%s\n",
708 updgrp->conf->change_local_as,
709 CHECK_FLAG(updgrp->conf->flags,
710 PEER_FLAG_LOCAL_AS_NO_PREPEND)
711 ? " no-prepend"
712 : "",
713 CHECK_FLAG(updgrp->conf->flags,
714 PEER_FLAG_LOCAL_AS_REPLACE_AS)
715 ? " replace-as"
716 : "");
717
a2addae8 718 UPDGRP_FOREACH_SUBGRP (updgrp, subgrp) {
d62a17ae 719 if (ctx->subgrp_id && (ctx->subgrp_id != subgrp->id))
720 continue;
721 vty_out(vty, "\n");
722 vty_out(vty, " Update-subgroup %" PRIu64 ":\n", subgrp->id);
723 vty_out(vty, " Created: %s",
724 timestamp_string(subgrp->uptime));
725
726 if (subgrp->split_from.update_group_id
727 || subgrp->split_from.subgroup_id) {
728 vty_out(vty, " Split from group id: %" PRIu64 "\n",
729 subgrp->split_from.update_group_id);
730 vty_out(vty,
731 " Split from subgroup id: %" PRIu64 "\n",
732 subgrp->split_from.subgroup_id);
733 }
734
735 vty_out(vty, " Join events: %u\n", subgrp->join_events);
736 vty_out(vty, " Prune events: %u\n", subgrp->prune_events);
737 vty_out(vty, " Merge events: %u\n", subgrp->merge_events);
738 vty_out(vty, " Split events: %u\n", subgrp->split_events);
739 vty_out(vty, " Update group switch events: %u\n",
740 subgrp->updgrp_switch_events);
741 vty_out(vty, " Peer refreshes combined: %u\n",
742 subgrp->peer_refreshes_combined);
743 vty_out(vty, " Merge checks triggered: %u\n",
744 subgrp->merge_checks_triggered);
5b18ef82
DS
745 vty_out(vty, " Coalesce Time: %u%s\n",
746 (UPDGRP_INST(subgrp->update_group))->coalesce_time,
747 subgrp->t_coalesce ? "(Running)" : "");
d62a17ae 748 vty_out(vty, " Version: %" PRIu64 "\n", subgrp->version);
749 vty_out(vty, " Packet queue length: %d\n",
750 bpacket_queue_length(SUBGRP_PKTQ(subgrp)));
751 vty_out(vty, " Total packets enqueued: %u\n",
752 subgroup_total_packets_enqueued(subgrp));
753 vty_out(vty, " Packet queue high watermark: %d\n",
754 bpacket_queue_hwm_length(SUBGRP_PKTQ(subgrp)));
755 vty_out(vty, " Adj-out list count: %u\n", subgrp->adj_count);
756 vty_out(vty, " Advertise list: %s\n",
757 advertise_list_is_empty(subgrp) ? "empty"
758 : "not empty");
759 vty_out(vty, " Flags: %s\n",
760 CHECK_FLAG(subgrp->flags, SUBGRP_FLAG_NEEDS_REFRESH)
761 ? "R"
762 : "");
0997ee26
DA
763 if (peer)
764 vty_out(vty, " Max packet size: %d\n",
765 peer->max_packet_size);
d62a17ae 766 if (subgrp->peer_count > 0) {
767 vty_out(vty, " Peers:\n");
a2addae8
RW
768 SUBGRP_FOREACH_PEER (subgrp, paf)
769 vty_out(vty, " - %s\n", paf->peer->host);
d62a17ae 770 }
8fe8a7f6 771 }
d62a17ae 772 return UPDWALK_CONTINUE;
3f9c7369
DS
773}
774
775/*
776 * Helper function to show the packet queue for each subgroup of update group.
777 * Will be constrained to a particular subgroup id if id !=0
778 */
d62a17ae 779static int updgrp_show_packet_queue_walkcb(struct update_group *updgrp,
780 void *arg)
3f9c7369 781{
d62a17ae 782 struct updwalk_context *ctx = arg;
783 struct update_subgroup *subgrp;
784 struct vty *vty;
785
786 vty = ctx->vty;
a2addae8 787 UPDGRP_FOREACH_SUBGRP (updgrp, subgrp) {
d62a17ae 788 if (ctx->subgrp_id && (ctx->subgrp_id != subgrp->id))
789 continue;
790 vty_out(vty, "update group %" PRIu64 ", subgroup %" PRIu64 "\n",
791 updgrp->id, subgrp->id);
792 bpacket_queue_show_vty(SUBGRP_PKTQ(subgrp), vty);
793 }
794 return UPDWALK_CONTINUE;
3f9c7369
DS
795}
796
797/*
798 * Show the packet queue for each subgroup of update group. Will be
799 * constrained to a particular subgroup id if id !=0
800 */
d62a17ae 801void update_group_show_packet_queue(struct bgp *bgp, afi_t afi, safi_t safi,
802 struct vty *vty, uint64_t id)
3f9c7369 803{
d62a17ae 804 struct updwalk_context ctx;
805
806 memset(&ctx, 0, sizeof(ctx));
807 ctx.vty = vty;
808 ctx.subgrp_id = id;
809 ctx.flags = 0;
810 update_group_af_walk(bgp, afi, safi, updgrp_show_packet_queue_walkcb,
811 &ctx);
3f9c7369
DS
812}
813
d62a17ae 814static struct update_group *update_group_find(struct peer_af *paf)
3f9c7369 815{
d62a17ae 816 struct update_group *updgrp;
817 struct update_group tmp;
818 struct peer tmp_conf;
3f9c7369 819
d62a17ae 820 if (!peer_established(PAF_PEER(paf)))
821 return NULL;
3f9c7369 822
d62a17ae 823 memset(&tmp, 0, sizeof(tmp));
824 memset(&tmp_conf, 0, sizeof(tmp_conf));
825 tmp.conf = &tmp_conf;
826 peer2_updgrp_copy(&tmp, paf);
3f9c7369 827
d62a17ae 828 updgrp = hash_lookup(paf->peer->bgp->update_groups[paf->afid], &tmp);
829 conf_release(&tmp_conf, paf->afi, paf->safi);
830 return updgrp;
3f9c7369
DS
831}
832
d62a17ae 833static struct update_group *update_group_create(struct peer_af *paf)
3f9c7369 834{
d62a17ae 835 struct update_group *updgrp;
836 struct update_group tmp;
837 struct peer tmp_conf;
3f9c7369 838
d62a17ae 839 memset(&tmp, 0, sizeof(tmp));
840 memset(&tmp_conf, 0, sizeof(tmp_conf));
841 tmp.conf = &tmp_conf;
842 peer2_updgrp_copy(&tmp, paf);
3f9c7369 843
d62a17ae 844 updgrp = hash_get(paf->peer->bgp->update_groups[paf->afid], &tmp,
845 updgrp_hash_alloc);
d62a17ae 846 update_group_checkin(updgrp);
3f9c7369 847
d62a17ae 848 if (BGP_DEBUG(update_groups, UPDATE_GROUPS))
849 zlog_debug("create update group %" PRIu64, updgrp->id);
3f9c7369 850
d62a17ae 851 UPDGRP_GLOBAL_STAT(updgrp, updgrps_created) += 1;
3f9c7369 852
d62a17ae 853 conf_release(&tmp_conf, paf->afi, paf->safi);
854 return updgrp;
3f9c7369
DS
855}
856
d62a17ae 857static void update_group_delete(struct update_group *updgrp)
3f9c7369 858{
d62a17ae 859 if (BGP_DEBUG(update_groups, UPDATE_GROUPS))
860 zlog_debug("delete update group %" PRIu64, updgrp->id);
3f9c7369 861
d62a17ae 862 UPDGRP_GLOBAL_STAT(updgrp, updgrps_deleted) += 1;
3f9c7369 863
d62a17ae 864 hash_release(updgrp->bgp->update_groups[updgrp->afid], updgrp);
865 conf_release(updgrp->conf, updgrp->afi, updgrp->safi);
3d68677e 866
0a22ddfb 867 XFREE(MTYPE_BGP_PEER_HOST, updgrp->conf->host);
6e919709 868
0a22ddfb 869 XFREE(MTYPE_BGP_PEER_IFNAME, updgrp->conf->ifname);
6e919709 870
d62a17ae 871 XFREE(MTYPE_BGP_PEER, updgrp->conf);
872 XFREE(MTYPE_BGP_UPDGRP, updgrp);
3f9c7369
DS
873}
874
d62a17ae 875static void update_group_add_subgroup(struct update_group *updgrp,
876 struct update_subgroup *subgrp)
3f9c7369 877{
d62a17ae 878 if (!updgrp || !subgrp)
879 return;
3f9c7369 880
d62a17ae 881 LIST_INSERT_HEAD(&(updgrp->subgrps), subgrp, updgrp_train);
882 subgrp->update_group = updgrp;
3f9c7369
DS
883}
884
d62a17ae 885static void update_group_remove_subgroup(struct update_group *updgrp,
886 struct update_subgroup *subgrp)
3f9c7369 887{
d62a17ae 888 if (!updgrp || !subgrp)
889 return;
3f9c7369 890
d62a17ae 891 LIST_REMOVE(subgrp, updgrp_train);
892 subgrp->update_group = NULL;
893 if (LIST_EMPTY(&(updgrp->subgrps)))
894 update_group_delete(updgrp);
3f9c7369
DS
895}
896
897static struct update_subgroup *
d62a17ae 898update_subgroup_create(struct update_group *updgrp)
3f9c7369 899{
d62a17ae 900 struct update_subgroup *subgrp;
3f9c7369 901
d62a17ae 902 subgrp = XCALLOC(MTYPE_BGP_UPD_SUBGRP, sizeof(struct update_subgroup));
903 update_subgroup_checkin(subgrp, updgrp);
904 subgrp->v_coalesce = (UPDGRP_INST(updgrp))->coalesce_time;
ef56aee4 905 sync_init(subgrp, updgrp);
d62a17ae 906 bpacket_queue_init(SUBGRP_PKTQ(subgrp));
907 bpacket_queue_add(SUBGRP_PKTQ(subgrp), NULL, NULL);
908 TAILQ_INIT(&(subgrp->adjq));
909 if (BGP_DEBUG(update_groups, UPDATE_GROUPS))
910 zlog_debug("create subgroup u%" PRIu64 ":s%" PRIu64, updgrp->id,
911 subgrp->id);
3f9c7369 912
d62a17ae 913 update_group_add_subgroup(updgrp, subgrp);
3f9c7369 914
d62a17ae 915 UPDGRP_INCR_STAT(updgrp, subgrps_created);
3f9c7369 916
d62a17ae 917 return subgrp;
3f9c7369
DS
918}
919
d62a17ae 920static void update_subgroup_delete(struct update_subgroup *subgrp)
3f9c7369 921{
d62a17ae 922 if (!subgrp)
923 return;
3f9c7369 924
d62a17ae 925 if (subgrp->update_group)
926 UPDGRP_INCR_STAT(subgrp->update_group, subgrps_deleted);
3f9c7369 927
28ef0ee1 928 THREAD_OFF(subgrp->t_merge_check);
50478845 929 THREAD_OFF(subgrp->t_coalesce);
3f9c7369 930
d62a17ae 931 bpacket_queue_cleanup(SUBGRP_PKTQ(subgrp));
932 subgroup_clear_table(subgrp);
3f9c7369 933
d62a17ae 934 sync_delete(subgrp);
3f9c7369 935
4f9a63ad 936 if (BGP_DEBUG(update_groups, UPDATE_GROUPS) && subgrp->update_group)
d62a17ae 937 zlog_debug("delete subgroup u%" PRIu64 ":s%" PRIu64,
938 subgrp->update_group->id, subgrp->id);
3f9c7369 939
d62a17ae 940 update_group_remove_subgroup(subgrp->update_group, subgrp);
3f9c7369 941
d62a17ae 942 XFREE(MTYPE_BGP_UPD_SUBGRP, subgrp);
3f9c7369
DS
943}
944
d62a17ae 945void update_subgroup_inherit_info(struct update_subgroup *to,
946 struct update_subgroup *from)
3f9c7369 947{
d62a17ae 948 if (!to || !from)
949 return;
3f9c7369 950
d62a17ae 951 to->sflags = from->sflags;
3f9c7369
DS
952}
953
954/*
955 * update_subgroup_check_delete
956 *
957 * Delete a subgroup if it is ready to be deleted.
958 *
2951a7a4 959 * Returns true if the subgroup was deleted.
3f9c7369 960 */
3dc339cd 961static bool update_subgroup_check_delete(struct update_subgroup *subgrp)
3f9c7369 962{
d62a17ae 963 if (!subgrp)
3dc339cd 964 return false;
3f9c7369 965
d62a17ae 966 if (!LIST_EMPTY(&(subgrp->peers)))
3dc339cd 967 return false;
3f9c7369 968
d62a17ae 969 update_subgroup_delete(subgrp);
3f9c7369 970
3dc339cd 971 return true;
3f9c7369
DS
972}
973
974/*
975 * update_subgroup_add_peer
976 *
977 * @param send_enqueued_packets If true all currently enqueued packets will
978 * also be sent to the peer.
979 */
d62a17ae 980static void update_subgroup_add_peer(struct update_subgroup *subgrp,
981 struct peer_af *paf,
982 int send_enqueued_pkts)
3f9c7369 983{
d62a17ae 984 struct bpacket *pkt;
3f9c7369 985
d62a17ae 986 if (!subgrp || !paf)
987 return;
3f9c7369 988
d62a17ae 989 LIST_INSERT_HEAD(&(subgrp->peers), paf, subgrp_train);
990 paf->subgroup = subgrp;
991 subgrp->peer_count++;
3f9c7369 992
d62a17ae 993 if (bgp_debug_peer_updout_enabled(paf->peer->host)) {
994 UPDGRP_PEER_DBG_EN(subgrp->update_group);
995 }
3f9c7369 996
d62a17ae 997 SUBGRP_INCR_STAT(subgrp, join_events);
3f9c7369 998
d62a17ae 999 if (send_enqueued_pkts) {
1000 pkt = bpacket_queue_first(SUBGRP_PKTQ(subgrp));
1001 } else {
3f9c7369 1002
d62a17ae 1003 /*
1004 * Hang the peer off of the last, placeholder, packet in the
1005 * queue. This means it won't see any of the packets that are
1006 * currently the queue.
1007 */
1008 pkt = bpacket_queue_last(SUBGRP_PKTQ(subgrp));
1009 assert(pkt->buffer == NULL);
1010 }
3f9c7369 1011
d62a17ae 1012 bpacket_add_peer(pkt, paf);
3f9c7369 1013
7bfdba54
S
1014 if (BGP_DEBUG(update_groups, UPDATE_GROUPS))
1015 zlog_debug("peer %s added to subgroup s%" PRIu64,
1016 paf->peer->host, subgrp->id);
3f9c7369
DS
1017}
1018
1019/*
1020 * update_subgroup_remove_peer_internal
1021 *
1022 * Internal function that removes a peer from a subgroup, but does not
1023 * delete the subgroup. A call to this function must almost always be
1024 * followed by a call to update_subgroup_check_delete().
1025 *
1026 * @see update_subgroup_remove_peer
1027 */
d62a17ae 1028static void update_subgroup_remove_peer_internal(struct update_subgroup *subgrp,
1029 struct peer_af *paf)
3f9c7369 1030{
d3e51db0 1031 assert(subgrp && paf && subgrp->update_group);
3f9c7369 1032
d62a17ae 1033 if (bgp_debug_peer_updout_enabled(paf->peer->host)) {
1034 UPDGRP_PEER_DBG_DIS(subgrp->update_group);
1035 }
3f9c7369 1036
d62a17ae 1037 bpacket_queue_remove_peer(paf);
1038 LIST_REMOVE(paf, subgrp_train);
1039 paf->subgroup = NULL;
1040 subgrp->peer_count--;
3f9c7369 1041
7bfdba54
S
1042 if (BGP_DEBUG(update_groups, UPDATE_GROUPS))
1043 zlog_debug("peer %s deleted from subgroup s%"
4882d296 1044 PRIu64 " peer cnt %d",
7bfdba54 1045 paf->peer->host, subgrp->id, subgrp->peer_count);
d62a17ae 1046 SUBGRP_INCR_STAT(subgrp, prune_events);
3f9c7369
DS
1047}
1048
1049/*
1050 * update_subgroup_remove_peer
1051 */
d62a17ae 1052void update_subgroup_remove_peer(struct update_subgroup *subgrp,
1053 struct peer_af *paf)
3f9c7369 1054{
d62a17ae 1055 if (!subgrp || !paf)
1056 return;
3f9c7369 1057
d62a17ae 1058 update_subgroup_remove_peer_internal(subgrp, paf);
3f9c7369 1059
d62a17ae 1060 if (update_subgroup_check_delete(subgrp))
1061 return;
3f9c7369 1062
d62a17ae 1063 /*
1064 * The deletion of the peer may have caused some packets to be
1065 * deleted from the subgroup packet queue. Check if the subgroup can
1066 * be merged now.
1067 */
1068 update_subgroup_check_merge(subgrp, "removed peer from subgroup");
3f9c7369
DS
1069}
1070
d62a17ae 1071static struct update_subgroup *update_subgroup_find(struct update_group *updgrp,
1072 struct peer_af *paf)
3f9c7369 1073{
d62a17ae 1074 struct update_subgroup *subgrp = NULL;
1075 uint64_t version;
1076
1077 if (paf->subgroup) {
1078 assert(0);
1079 return NULL;
1080 } else
1081 version = 0;
1082
1083 if (!peer_established(PAF_PEER(paf)))
1084 return NULL;
1085
a2addae8 1086 UPDGRP_FOREACH_SUBGRP (updgrp, subgrp) {
d62a17ae 1087 if (subgrp->version != version
1088 || CHECK_FLAG(subgrp->sflags,
1089 SUBGRP_STATUS_DEFAULT_ORIGINATE))
1090 continue;
1091
1092 /*
1093 * The version number is not meaningful on a subgroup that needs
1094 * a refresh.
1095 */
1096 if (update_subgroup_needs_refresh(subgrp))
1097 continue;
1098
1099 break;
1100 }
1101
1102 return subgrp;
3f9c7369
DS
1103}
1104
1105/*
1106 * update_subgroup_ready_for_merge
1107 *
2951a7a4 1108 * Returns true if this subgroup is in a state that allows it to be
3f9c7369
DS
1109 * merged into another subgroup.
1110 */
3dc339cd 1111static bool update_subgroup_ready_for_merge(struct update_subgroup *subgrp)
3f9c7369
DS
1112{
1113
d62a17ae 1114 /*
1115 * Not ready if there are any encoded packets waiting to be written
1116 * out to peers.
1117 */
1118 if (!bpacket_queue_is_empty(SUBGRP_PKTQ(subgrp)))
3dc339cd 1119 return false;
d62a17ae 1120
1121 /*
1122 * Not ready if there enqueued updates waiting to be encoded.
1123 */
1124 if (!advertise_list_is_empty(subgrp))
3dc339cd 1125 return false;
d62a17ae 1126
1127 /*
1128 * Don't attempt to merge a subgroup that needs a refresh. For one,
1129 * we can't determine if the adj_out of such a group matches that of
1130 * another group.
1131 */
1132 if (update_subgroup_needs_refresh(subgrp))
3dc339cd 1133 return false;
d62a17ae 1134
3dc339cd 1135 return true;
3f9c7369
DS
1136}
1137
1138/*
1139 * update_subgrp_can_merge_into
1140 *
2951a7a4 1141 * Returns true if the first subgroup can merge into the second
3f9c7369
DS
1142 * subgroup.
1143 */
d62a17ae 1144static int update_subgroup_can_merge_into(struct update_subgroup *subgrp,
1145 struct update_subgroup *target)
3f9c7369
DS
1146{
1147
d62a17ae 1148 if (subgrp == target)
1149 return 0;
3f9c7369 1150
d62a17ae 1151 /*
1152 * Both must have processed the BRIB to the same point in order to
1153 * be merged.
1154 */
1155 if (subgrp->version != target->version)
1156 return 0;
3f9c7369 1157
d62a17ae 1158 if (CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)
1159 != CHECK_FLAG(target->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE))
1160 return 0;
f910ef58 1161
d62a17ae 1162 if (subgrp->adj_count != target->adj_count)
1163 return 0;
3f9c7369 1164
d62a17ae 1165 return update_subgroup_ready_for_merge(target);
3f9c7369
DS
1166}
1167
1168/*
1169 * update_subgroup_merge
1170 *
1171 * Merge the first subgroup into the second one.
1172 */
d62a17ae 1173static void update_subgroup_merge(struct update_subgroup *subgrp,
1174 struct update_subgroup *target,
1175 const char *reason)
3f9c7369 1176{
d62a17ae 1177 struct peer_af *paf;
1178 int result;
1179 int peer_count;
3f9c7369 1180
d62a17ae 1181 assert(subgrp->adj_count == target->adj_count);
3f9c7369 1182
d62a17ae 1183 peer_count = subgrp->peer_count;
3f9c7369 1184
d62a17ae 1185 while (1) {
1186 paf = LIST_FIRST(&subgrp->peers);
1187 if (!paf)
1188 break;
3f9c7369 1189
d62a17ae 1190 update_subgroup_remove_peer_internal(subgrp, paf);
3f9c7369 1191
d62a17ae 1192 /*
1193 * Add the peer to the target subgroup, while making sure that
1194 * any currently enqueued packets won't be sent to it. Enqueued
1195 * packets could, for example, result in an unnecessary withdraw
1196 * followed by an advertise.
1197 */
1198 update_subgroup_add_peer(target, paf, 0);
1199 }
3f9c7369 1200
d62a17ae 1201 SUBGRP_INCR_STAT(target, merge_events);
3f9c7369 1202
d62a17ae 1203 if (BGP_DEBUG(update_groups, UPDATE_GROUPS))
6cde4b45 1204 zlog_debug("u%" PRIu64 ":s%" PRIu64" (%d peers) merged into u%" PRIu64 ":s%" PRIu64", trigger: %s",
d62a17ae 1205 subgrp->update_group->id, subgrp->id, peer_count,
1206 target->update_group->id, target->id,
1207 reason ? reason : "unknown");
3f9c7369 1208
d62a17ae 1209 result = update_subgroup_check_delete(subgrp);
1210 assert(result);
3f9c7369
DS
1211}
1212
1213/*
1214 * update_subgroup_check_merge
1215 *
1216 * Merge this subgroup into another subgroup if possible.
1217 *
2951a7a4 1218 * Returns true if the subgroup has been merged. The subgroup pointer
3f9c7369
DS
1219 * should not be accessed in this case.
1220 */
3dc339cd
DA
1221bool update_subgroup_check_merge(struct update_subgroup *subgrp,
1222 const char *reason)
3f9c7369 1223{
d62a17ae 1224 struct update_subgroup *target;
3f9c7369 1225
d62a17ae 1226 if (!update_subgroup_ready_for_merge(subgrp))
3dc339cd 1227 return false;
3f9c7369 1228
d62a17ae 1229 /*
1230 * Look for a subgroup to merge into.
1231 */
a2addae8 1232 UPDGRP_FOREACH_SUBGRP (subgrp->update_group, target) {
d62a17ae 1233 if (update_subgroup_can_merge_into(subgrp, target))
1234 break;
1235 }
3f9c7369 1236
d62a17ae 1237 if (!target)
3dc339cd 1238 return false;
3f9c7369 1239
d62a17ae 1240 update_subgroup_merge(subgrp, target, reason);
3dc339cd 1241 return true;
3f9c7369
DS
1242}
1243
d62a17ae 1244/*
9d303b37
DL
1245* update_subgroup_merge_check_thread_cb
1246*/
cc9f21da 1247static void update_subgroup_merge_check_thread_cb(struct thread *thread)
3f9c7369 1248{
d62a17ae 1249 struct update_subgroup *subgrp;
3f9c7369 1250
d62a17ae 1251 subgrp = THREAD_ARG(thread);
3f9c7369 1252
d62a17ae 1253 subgrp->t_merge_check = NULL;
3f9c7369 1254
d62a17ae 1255 update_subgroup_check_merge(subgrp, "triggered merge check");
3f9c7369
DS
1256}
1257
1258/*
1259 * update_subgroup_trigger_merge_check
1260 *
1261 * Triggers a call to update_subgroup_check_merge() on a clean context.
1262 *
1263 * @param force If true, the merge check will be triggered even if the
1264 * subgroup doesn't currently look ready for a merge.
1265 *
2951a7a4 1266 * Returns true if a merge check will be performed shortly.
3f9c7369 1267 */
3dc339cd
DA
1268bool update_subgroup_trigger_merge_check(struct update_subgroup *subgrp,
1269 int force)
3f9c7369 1270{
d62a17ae 1271 if (subgrp->t_merge_check)
3dc339cd 1272 return true;
3f9c7369 1273
d62a17ae 1274 if (!force && !update_subgroup_ready_for_merge(subgrp))
3dc339cd 1275 return false;
3f9c7369 1276
d62a17ae 1277 subgrp->t_merge_check = NULL;
1278 thread_add_timer_msec(bm->master, update_subgroup_merge_check_thread_cb,
1279 subgrp, 0, &subgrp->t_merge_check);
3f9c7369 1280
d62a17ae 1281 SUBGRP_INCR_STAT(subgrp, merge_checks_triggered);
3f9c7369 1282
3dc339cd 1283 return true;
3f9c7369
DS
1284}
1285
1286/*
1287 * update_subgroup_copy_adj_out
1288 *
1289 * Helper function that clones the adj out (state about advertised
1290 * routes) from one subgroup to another. It assumes that the adj out
1291 * of the target subgroup is empty.
1292 */
d62a17ae 1293static void update_subgroup_copy_adj_out(struct update_subgroup *source,
1294 struct update_subgroup *dest)
3f9c7369 1295{
d62a17ae 1296 struct bgp_adj_out *aout, *aout_copy;
1297
a2addae8 1298 SUBGRP_FOREACH_ADJ (source, aout) {
d62a17ae 1299 /*
1300 * Copy the adj out.
1301 */
9bcb3eef
DS
1302 aout_copy = bgp_adj_out_alloc(dest, aout->dest,
1303 aout->addpath_tx_id);
d62a17ae 1304 aout_copy->attr =
7c87afac 1305 aout->attr ? bgp_attr_intern(aout->attr) : NULL;
d62a17ae 1306 }
0ab7b206
AD
1307
1308 dest->scount = source->scount;
3f9c7369
DS
1309}
1310
1311/*
1312 * update_subgroup_copy_packets
1313 *
1314 * Copy packets after and including the given packet to the subgroup
1315 * 'dest'.
1316 *
1317 * Returns the number of packets copied.
1318 */
d62a17ae 1319static int update_subgroup_copy_packets(struct update_subgroup *dest,
1320 struct bpacket *pkt)
3f9c7369 1321{
d62a17ae 1322 int count;
1323
1324 count = 0;
1325 while (pkt && pkt->buffer) {
1326 bpacket_queue_add(SUBGRP_PKTQ(dest), stream_dup(pkt->buffer),
1327 &pkt->arr);
1328 count++;
1329 pkt = bpacket_next(pkt);
1330 }
3f9c7369 1331
d62a17ae 1332 return count;
3f9c7369
DS
1333}
1334
3dc339cd
DA
1335static bool updgrp_prefix_list_update(struct update_group *updgrp,
1336 const char *name)
3f9c7369 1337{
d62a17ae 1338 struct peer *peer;
1339 struct bgp_filter *filter;
1340
1341 peer = UPDGRP_PEER(updgrp);
1342 filter = &peer->filter[UPDGRP_AFI(updgrp)][UPDGRP_SAFI(updgrp)];
1343
1344 if (PREFIX_LIST_OUT_NAME(filter)
1345 && (strcmp(name, PREFIX_LIST_OUT_NAME(filter)) == 0)) {
1346 PREFIX_LIST_OUT(filter) = prefix_list_lookup(
1347 UPDGRP_AFI(updgrp), PREFIX_LIST_OUT_NAME(filter));
3dc339cd 1348 return true;
d62a17ae 1349 }
3dc339cd 1350 return false;
3f9c7369
DS
1351}
1352
3dc339cd
DA
1353static bool updgrp_filter_list_update(struct update_group *updgrp,
1354 const char *name)
3f9c7369 1355{
d62a17ae 1356 struct peer *peer;
1357 struct bgp_filter *filter;
1358
1359 peer = UPDGRP_PEER(updgrp);
1360 filter = &peer->filter[UPDGRP_AFI(updgrp)][UPDGRP_SAFI(updgrp)];
1361
1362 if (FILTER_LIST_OUT_NAME(filter)
1363 && (strcmp(name, FILTER_LIST_OUT_NAME(filter)) == 0)) {
1364 FILTER_LIST_OUT(filter) =
1365 as_list_lookup(FILTER_LIST_OUT_NAME(filter));
3dc339cd 1366 return true;
d62a17ae 1367 }
3dc339cd 1368 return false;
3f9c7369
DS
1369}
1370
3dc339cd
DA
1371static bool updgrp_distribute_list_update(struct update_group *updgrp,
1372 const char *name)
3f9c7369 1373{
d62a17ae 1374 struct peer *peer;
1375 struct bgp_filter *filter;
1376
1377 peer = UPDGRP_PEER(updgrp);
1378 filter = &peer->filter[UPDGRP_AFI(updgrp)][UPDGRP_SAFI(updgrp)];
1379
1380 if (DISTRIBUTE_OUT_NAME(filter)
1381 && (strcmp(name, DISTRIBUTE_OUT_NAME(filter)) == 0)) {
1382 DISTRIBUTE_OUT(filter) = access_list_lookup(
1383 UPDGRP_AFI(updgrp), DISTRIBUTE_OUT_NAME(filter));
3dc339cd 1384 return true;
d62a17ae 1385 }
3dc339cd 1386 return false;
3f9c7369
DS
1387}
1388
d62a17ae 1389static int updgrp_route_map_update(struct update_group *updgrp,
1390 const char *name, int *def_rmap_changed)
3f9c7369 1391{
d62a17ae 1392 struct peer *peer;
1393 struct bgp_filter *filter;
1394 int changed = 0;
1395 afi_t afi;
1396 safi_t safi;
1397
1398 peer = UPDGRP_PEER(updgrp);
1399 afi = UPDGRP_AFI(updgrp);
1400 safi = UPDGRP_SAFI(updgrp);
1401 filter = &peer->filter[afi][safi];
1402
1403 if (ROUTE_MAP_OUT_NAME(filter)
1404 && (strcmp(name, ROUTE_MAP_OUT_NAME(filter)) == 0)) {
1405 ROUTE_MAP_OUT(filter) = route_map_lookup_by_name(name);
1406
1407 changed = 1;
1408 }
1409
1410 if (UNSUPPRESS_MAP_NAME(filter)
1411 && (strcmp(name, UNSUPPRESS_MAP_NAME(filter)) == 0)) {
1412 UNSUPPRESS_MAP(filter) = route_map_lookup_by_name(name);
1413 changed = 1;
1414 }
1415
1416 /* process default-originate route-map */
1417 if (peer->default_rmap[afi][safi].name
1418 && (strcmp(name, peer->default_rmap[afi][safi].name) == 0)) {
1419 peer->default_rmap[afi][safi].map =
1420 route_map_lookup_by_name(name);
1421 if (def_rmap_changed)
1422 *def_rmap_changed = 1;
1423 }
1424 return changed;
3f9c7369
DS
1425}
1426
1427/*
1428 * hash iteration callback function to process a policy change for an
1429 * update group. Check if the changed policy matches the updgrp's
1430 * outbound route-map or unsuppress-map or default-originate map or
1431 * filter-list or prefix-list or distribute-list.
1432 * Trigger update generation accordingly.
1433 */
d62a17ae 1434static int updgrp_policy_update_walkcb(struct update_group *updgrp, void *arg)
3f9c7369 1435{
d62a17ae 1436 struct updwalk_context *ctx = arg;
1437 struct update_subgroup *subgrp;
1438 int changed = 0;
1439 int def_changed = 0;
1440
1441 if (!updgrp || !ctx || !ctx->policy_name)
1442 return UPDWALK_CONTINUE;
1443
1444 switch (ctx->policy_type) {
1445 case BGP_POLICY_ROUTE_MAP:
1446 changed = updgrp_route_map_update(updgrp, ctx->policy_name,
1447 &def_changed);
1448 break;
1449 case BGP_POLICY_FILTER_LIST:
1450 changed = updgrp_filter_list_update(updgrp, ctx->policy_name);
1451 break;
1452 case BGP_POLICY_PREFIX_LIST:
1453 changed = updgrp_prefix_list_update(updgrp, ctx->policy_name);
1454 break;
1455 case BGP_POLICY_DISTRIBUTE_LIST:
1456 changed =
1457 updgrp_distribute_list_update(updgrp, ctx->policy_name);
1458 break;
1459 default:
1460 break;
1461 }
1462
1463 /* If not doing route update, return after updating "config" */
1464 if (!ctx->policy_route_update)
1465 return UPDWALK_CONTINUE;
1466
1467 /* If nothing has changed, return after updating "config" */
1468 if (!changed && !def_changed)
1469 return UPDWALK_CONTINUE;
1470
1471 /*
1472 * If something has changed, at the beginning of a route-map
1473 * modification
1474 * event, mark each subgroup's needs-refresh bit. For one, it signals to
1475 * whoever that the subgroup needs a refresh. Second, it prevents
1476 * premature
1477 * merge of this subgroup with another before a complete (outbound)
1478 * refresh.
1479 */
1480 if (ctx->policy_event_start_flag) {
a2addae8 1481 UPDGRP_FOREACH_SUBGRP (updgrp, subgrp) {
d62a17ae 1482 update_subgroup_set_needs_refresh(subgrp, 1);
1483 }
1484 return UPDWALK_CONTINUE;
1485 }
1486
a2addae8 1487 UPDGRP_FOREACH_SUBGRP (updgrp, subgrp) {
2adac256
DA
1488 /* Avoid supressing duplicate routes later
1489 * when processing in subgroup_announce_table().
1490 */
1491 SET_FLAG(subgrp->sflags, SUBGRP_STATUS_FORCE_UPDATES);
1492
d62a17ae 1493 if (changed) {
1494 if (bgp_debug_update(NULL, NULL, updgrp, 0))
1495 zlog_debug(
6cde4b45 1496 "u%" PRIu64 ":s%" PRIu64" announcing routes upon policy %s (type %d) change",
d62a17ae 1497 updgrp->id, subgrp->id,
1498 ctx->policy_name, ctx->policy_type);
1499 subgroup_announce_route(subgrp);
1500 }
1501 if (def_changed) {
1502 if (bgp_debug_update(NULL, NULL, updgrp, 0))
1503 zlog_debug(
6cde4b45 1504 "u%" PRIu64 ":s%" PRIu64" announcing default upon default routemap %s change",
d62a17ae 1505 updgrp->id, subgrp->id,
1506 ctx->policy_name);
a9ae9fb5
AR
1507 if (route_map_lookup_by_name(ctx->policy_name)) {
1508 /*
1509 * When there is change in routemap, this flow
1510 * is triggered. the routemap is still present
1511 * in lib, hence its a update flow. The flag
1512 * needs to be unset.
1513 */
1514 UNSET_FLAG(subgrp->sflags,
1515 SUBGRP_STATUS_DEFAULT_ORIGINATE);
1516 subgroup_default_originate(subgrp, 0);
1517 } else {
1518 /*
1519 * This is a explicit withdraw, since the
1520 * routemap is not present in routemap lib. need
1521 * to pass 1 for withdraw arg.
1522 */
1523 subgroup_default_originate(subgrp, 1);
1524 }
d62a17ae 1525 }
1526 update_subgroup_set_needs_refresh(subgrp, 0);
1527 }
1528 return UPDWALK_CONTINUE;
3f9c7369
DS
1529}
1530
e3b78da8 1531static int update_group_walkcb(struct hash_bucket *bucket, void *arg)
3f9c7369 1532{
e3b78da8 1533 struct update_group *updgrp = bucket->data;
d62a17ae 1534 struct updwalk_context *wctx = arg;
1535 int ret = (*wctx->cb)(updgrp, wctx->context);
1536 return ret;
3f9c7369
DS
1537}
1538
d62a17ae 1539static int update_group_periodic_merge_walkcb(struct update_group *updgrp,
1540 void *arg)
3f9c7369 1541{
d62a17ae 1542 struct update_subgroup *subgrp;
1543 struct update_subgroup *tmp_subgrp;
1544 const char *reason = arg;
3f9c7369 1545
a2addae8
RW
1546 UPDGRP_FOREACH_SUBGRP_SAFE (updgrp, subgrp, tmp_subgrp)
1547 update_subgroup_check_merge(subgrp, reason);
d62a17ae 1548 return UPDWALK_CONTINUE;
3f9c7369
DS
1549}
1550
1551/********************
1552 * PUBLIC FUNCTIONS
1553 ********************/
1554
1555/*
1556 * trigger function when a policy (route-map/filter-list/prefix-list/
1557 * distribute-list etc.) content changes. Go through all the
1558 * update groups and process the change.
1559 *
1560 * bgp: the bgp instance
1561 * ptype: the type of policy that got modified, see bgpd.h
1562 * pname: name of the policy
1563 * route_update: flag to control if an automatic update generation should
1564 * occur
1565 * start_event: flag that indicates if it's the beginning of the change.
1566 * Esp. when the user is changing the content interactively
1567 * over multiple statements. Useful to set dirty flag on
1568 * update groups.
1569 */
d54f55f2 1570void update_group_policy_update(struct bgp *bgp, enum bgp_policy_type ptype,
f1aa4929 1571 const char *pname, bool route_update,
d62a17ae 1572 int start_event)
3f9c7369 1573{
d62a17ae 1574 struct updwalk_context ctx;
3f9c7369 1575
d62a17ae 1576 memset(&ctx, 0, sizeof(ctx));
1577 ctx.policy_type = ptype;
1578 ctx.policy_name = pname;
1579 ctx.policy_route_update = route_update;
1580 ctx.policy_event_start_flag = start_event;
1581 ctx.flags = 0;
3f9c7369 1582
d62a17ae 1583 update_group_walk(bgp, updgrp_policy_update_walkcb, &ctx);
3f9c7369
DS
1584}
1585
1586/*
1587 * update_subgroup_split_peer
1588 *
1589 * Ensure that the given peer is in a subgroup of its own in the
1590 * specified update group.
1591 */
d62a17ae 1592void update_subgroup_split_peer(struct peer_af *paf,
1593 struct update_group *updgrp)
3f9c7369 1594{
d62a17ae 1595 struct update_subgroup *old_subgrp, *subgrp;
1596 uint64_t old_id;
1597
1598
1599 old_subgrp = paf->subgroup;
1600
1601 if (!updgrp)
1602 updgrp = old_subgrp->update_group;
1603
1604 /*
1605 * If the peer is alone in its subgroup, reuse the existing
1606 * subgroup.
1607 */
1608 if (old_subgrp->peer_count == 1) {
1609 if (updgrp == old_subgrp->update_group)
1610 return;
1611
1612 subgrp = old_subgrp;
1613 old_id = old_subgrp->update_group->id;
1614
1615 if (bgp_debug_peer_updout_enabled(paf->peer->host)) {
1616 UPDGRP_PEER_DBG_DIS(old_subgrp->update_group);
1617 }
1618
1619 update_group_remove_subgroup(old_subgrp->update_group,
1620 old_subgrp);
1621 update_group_add_subgroup(updgrp, subgrp);
1622
1623 if (bgp_debug_peer_updout_enabled(paf->peer->host)) {
1624 UPDGRP_PEER_DBG_EN(updgrp);
1625 }
1626 if (BGP_DEBUG(update_groups, UPDATE_GROUPS))
6cde4b45 1627 zlog_debug("u%" PRIu64 ":s%" PRIu64" peer %s moved to u%" PRIu64 ":s%" PRIu64,
d62a17ae 1628 old_id, subgrp->id, paf->peer->host,
1629 updgrp->id, subgrp->id);
1630
1631 /*
1632 * The state of the subgroup (adj_out, advs, packet queue etc)
1633 * is consistent internally, but may not be identical to other
1634 * subgroups in the new update group even if the version number
1635 * matches up. Make sure a full refresh is done before the
1636 * subgroup is merged with another.
1637 */
1638 update_subgroup_set_needs_refresh(subgrp, 1);
1639
1640 SUBGRP_INCR_STAT(subgrp, updgrp_switch_events);
1641 return;
1642 }
3f9c7369 1643
d62a17ae 1644 /*
1645 * Create a new subgroup under the specified update group, and copy
1646 * over relevant state to it.
1647 */
1648 subgrp = update_subgroup_create(updgrp);
1649 update_subgroup_inherit_info(subgrp, old_subgrp);
1650
1651 subgrp->split_from.update_group_id = old_subgrp->update_group->id;
1652 subgrp->split_from.subgroup_id = old_subgrp->id;
1653
1654 /*
1655 * Copy out relevant state from the old subgroup.
1656 */
1657 update_subgroup_copy_adj_out(paf->subgroup, subgrp);
1658 update_subgroup_copy_packets(subgrp, paf->next_pkt_to_send);
1659
1660 if (BGP_DEBUG(update_groups, UPDATE_GROUPS))
6cde4b45 1661 zlog_debug("u%" PRIu64 ":s%" PRIu64" peer %s split and moved into u%" PRIu64":s%" PRIu64,
d62a17ae 1662 paf->subgroup->update_group->id, paf->subgroup->id,
1663 paf->peer->host, updgrp->id, subgrp->id);
1664
1665 SUBGRP_INCR_STAT(paf->subgroup, split_events);
1666
1667 /*
1668 * Since queued advs were left behind, this new subgroup needs a
1669 * refresh.
1670 */
1671 update_subgroup_set_needs_refresh(subgrp, 1);
1672
1673 /*
1674 * Remove peer from old subgroup, and add it to the new one.
1675 */
1676 update_subgroup_remove_peer(paf->subgroup, paf);
1677
1678 update_subgroup_add_peer(subgrp, paf, 1);
3f9c7369
DS
1679}
1680
d62a17ae 1681void update_bgp_group_init(struct bgp *bgp)
3f9c7369 1682{
d62a17ae 1683 int afid;
3f9c7369 1684
a2addae8 1685 AF_FOREACH (afid)
3f65c5b1 1686 bgp->update_groups[afid] =
996c9314 1687 hash_create(updgrp_hash_key_make, updgrp_hash_cmp,
3f65c5b1 1688 "BGP Update Group Hash");
3f9c7369
DS
1689}
1690
d62a17ae 1691void update_bgp_group_free(struct bgp *bgp)
3d68677e 1692{
d62a17ae 1693 int afid;
1694
a2addae8 1695 AF_FOREACH (afid) {
d62a17ae 1696 if (bgp->update_groups[afid]) {
1697 hash_free(bgp->update_groups[afid]);
1698 bgp->update_groups[afid] = NULL;
1699 }
1700 }
3d68677e
DS
1701}
1702
d62a17ae 1703void update_group_show(struct bgp *bgp, afi_t afi, safi_t safi, struct vty *vty,
1704 uint64_t subgrp_id)
3f9c7369 1705{
d62a17ae 1706 struct updwalk_context ctx;
1707 memset(&ctx, 0, sizeof(ctx));
1708 ctx.vty = vty;
1709 ctx.subgrp_id = subgrp_id;
8fe8a7f6 1710
d62a17ae 1711 update_group_af_walk(bgp, afi, safi, update_group_show_walkcb, &ctx);
3f9c7369
DS
1712}
1713
1714/*
1715 * update_group_show_stats
1716 *
1717 * Show global statistics about update groups.
1718 */
d62a17ae 1719void update_group_show_stats(struct bgp *bgp, struct vty *vty)
3f9c7369 1720{
d62a17ae 1721 vty_out(vty, "Update groups created: %u\n",
1722 bgp->update_group_stats.updgrps_created);
1723 vty_out(vty, "Update groups deleted: %u\n",
1724 bgp->update_group_stats.updgrps_deleted);
1725 vty_out(vty, "Update subgroups created: %u\n",
1726 bgp->update_group_stats.subgrps_created);
1727 vty_out(vty, "Update subgroups deleted: %u\n",
1728 bgp->update_group_stats.subgrps_deleted);
1729 vty_out(vty, "Join events: %u\n", bgp->update_group_stats.join_events);
1730 vty_out(vty, "Prune events: %u\n",
1731 bgp->update_group_stats.prune_events);
1732 vty_out(vty, "Merge events: %u\n",
1733 bgp->update_group_stats.merge_events);
1734 vty_out(vty, "Split events: %u\n",
1735 bgp->update_group_stats.split_events);
1736 vty_out(vty, "Update group switch events: %u\n",
1737 bgp->update_group_stats.updgrp_switch_events);
1738 vty_out(vty, "Peer route refreshes combined: %u\n",
1739 bgp->update_group_stats.peer_refreshes_combined);
1740 vty_out(vty, "Merge checks triggered: %u\n",
1741 bgp->update_group_stats.merge_checks_triggered);
3f9c7369
DS
1742}
1743
1744/*
1745 * update_group_adjust_peer
1746 */
d62a17ae 1747void update_group_adjust_peer(struct peer_af *paf)
3f9c7369 1748{
d62a17ae 1749 struct update_group *updgrp;
1750 struct update_subgroup *subgrp, *old_subgrp;
1751 struct peer *peer;
1752
1753 if (!paf)
1754 return;
1755
1756 peer = PAF_PEER(paf);
1757 if (!peer_established(peer)) {
1758 return;
1759 }
1760
1761 if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE)) {
1762 return;
3f9c7369 1763 }
3f9c7369 1764
d62a17ae 1765 if (!peer->afc_nego[paf->afi][paf->safi]) {
1766 return;
1767 }
3f9c7369 1768
d62a17ae 1769 updgrp = update_group_find(paf);
1770 if (!updgrp) {
1771 updgrp = update_group_create(paf);
1772 if (!updgrp) {
e50f7cfd 1773 flog_err(EC_BGP_UPDGRP_CREATE,
1c50c1c0
QY
1774 "couldn't create update group for peer %s",
1775 paf->peer->host);
d62a17ae 1776 return;
1777 }
1778 }
3f9c7369 1779
d62a17ae 1780 old_subgrp = paf->subgroup;
3f9c7369 1781
d62a17ae 1782 if (old_subgrp) {
3f9c7369 1783
d62a17ae 1784 /*
1785 * If the update group of the peer is unchanged, the peer can
1786 * stay
1787 * in its existing subgroup and we're done.
1788 */
1789 if (old_subgrp->update_group == updgrp)
1790 return;
1791
1792 /*
1793 * The peer is switching between update groups. Put it in its
1794 * own subgroup under the new update group.
1795 */
1796 update_subgroup_split_peer(paf, updgrp);
1797 return;
1798 }
1799
1800 subgrp = update_subgroup_find(updgrp, paf);
1801 if (!subgrp) {
1802 subgrp = update_subgroup_create(updgrp);
1803 if (!subgrp)
1804 return;
1805 }
3f9c7369 1806
d62a17ae 1807 update_subgroup_add_peer(subgrp, paf, 1);
1808 if (BGP_DEBUG(update_groups, UPDATE_GROUPS))
1809 zlog_debug("u%" PRIu64 ":s%" PRIu64 " add peer %s", updgrp->id,
1810 subgrp->id, paf->peer->host);
1811
1812 return;
3f9c7369
DS
1813}
1814
d62a17ae 1815int update_group_adjust_soloness(struct peer *peer, int set)
3f9c7369 1816{
d62a17ae 1817 struct peer_group *group;
1818 struct listnode *node, *nnode;
1819
1820 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
1821 peer_lonesoul_or_not(peer, set);
feb17238 1822 if (peer_established(peer))
d62a17ae 1823 bgp_announce_route_all(peer);
1824 } else {
1825 group = peer->group;
1826 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
1827 peer_lonesoul_or_not(peer, set);
feb17238 1828 if (peer_established(peer))
d62a17ae 1829 bgp_announce_route_all(peer);
1830 }
1831 }
1832 return 0;
3f9c7369
DS
1833}
1834
1835/*
1836 * update_subgroup_rib
1837 */
d62a17ae 1838struct bgp_table *update_subgroup_rib(struct update_subgroup *subgrp)
3f9c7369 1839{
d62a17ae 1840 struct bgp *bgp;
3f9c7369 1841
d62a17ae 1842 bgp = SUBGRP_INST(subgrp);
1843 if (!bgp)
1844 return NULL;
3f9c7369 1845
d62a17ae 1846 return bgp->rib[SUBGRP_AFI(subgrp)][SUBGRP_SAFI(subgrp)];
3f9c7369
DS
1847}
1848
d62a17ae 1849void update_group_af_walk(struct bgp *bgp, afi_t afi, safi_t safi,
1850 updgrp_walkcb cb, void *ctx)
3f9c7369 1851{
d62a17ae 1852 struct updwalk_context wctx;
1853 int afid;
3f9c7369 1854
d62a17ae 1855 if (!bgp)
1856 return;
1857 afid = afindex(afi, safi);
1858 if (afid >= BGP_AF_MAX)
1859 return;
3f9c7369 1860
d62a17ae 1861 memset(&wctx, 0, sizeof(wctx));
1862 wctx.cb = cb;
1863 wctx.context = ctx;
0de4848d 1864
d62a17ae 1865 if (bgp->update_groups[afid])
1866 hash_walk(bgp->update_groups[afid], update_group_walkcb, &wctx);
3f9c7369
DS
1867}
1868
d62a17ae 1869void update_group_walk(struct bgp *bgp, updgrp_walkcb cb, void *ctx)
3f9c7369 1870{
d62a17ae 1871 afi_t afi;
1872 safi_t safi;
3f9c7369 1873
a2addae8 1874 FOREACH_AFI_SAFI (afi, safi) {
d62a17ae 1875 update_group_af_walk(bgp, afi, safi, cb, ctx);
1876 }
3f9c7369
DS
1877}
1878
d62a17ae 1879void update_group_periodic_merge(struct bgp *bgp)
3f9c7369 1880{
d62a17ae 1881 char reason[] = "periodic merge check";
3f9c7369 1882
d62a17ae 1883 update_group_walk(bgp, update_group_periodic_merge_walkcb,
1884 (void *)reason);
3f9c7369
DS
1885}
1886
0de4848d
DS
1887static int
1888update_group_default_originate_route_map_walkcb(struct update_group *updgrp,
d62a17ae 1889 void *arg)
0de4848d 1890{
d62a17ae 1891 struct update_subgroup *subgrp;
1892 struct peer *peer;
1893 afi_t afi;
1894 safi_t safi;
1895
a2addae8 1896 UPDGRP_FOREACH_SUBGRP (updgrp, subgrp) {
d62a17ae 1897 peer = SUBGRP_PEER(subgrp);
1898 afi = SUBGRP_AFI(subgrp);
1899 safi = SUBGRP_SAFI(subgrp);
1900
1901 if (peer->default_rmap[afi][safi].name) {
a9ae9fb5
AR
1902 /*
1903 * When there is change in routemap this flow will
1904 * be triggered. We need to unset the Flag to ensure
1905 * the update flow gets triggered.
1906 */
1907 UNSET_FLAG(subgrp->sflags,
1908 SUBGRP_STATUS_DEFAULT_ORIGINATE);
d62a17ae 1909 subgroup_default_originate(subgrp, 0);
1910 }
1911 }
1912
1913 return UPDWALK_CONTINUE;
0de4848d
DS
1914}
1915
cc9f21da 1916void update_group_refresh_default_originate_route_map(struct thread *thread)
0de4848d 1917{
d62a17ae 1918 struct bgp *bgp;
1919 char reason[] = "refresh default-originate route-map";
0de4848d 1920
d62a17ae 1921 bgp = THREAD_ARG(thread);
1922 update_group_walk(bgp, update_group_default_originate_route_map_walkcb,
1923 reason);
c3aaa89a 1924 THREAD_OFF(bgp->t_rmap_def_originate_eval);
d62a17ae 1925 bgp_unlock(bgp);
0de4848d
DS
1926}
1927
3f9c7369
DS
1928/*
1929 * peer_af_announce_route
1930 *
1931 * Refreshes routes out to a peer_af immediately.
1932 *
2951a7a4 1933 * If the combine parameter is true, then this function will try to
3f9c7369
DS
1934 * gather other peers in the subgroup for which a route announcement
1935 * is pending and efficently announce routes to all of them.
1936 *
1937 * For now, the 'combine' option has an effect only if all peers in
1938 * the subgroup have a route announcement pending.
1939 */
d62a17ae 1940void peer_af_announce_route(struct peer_af *paf, int combine)
3f9c7369 1941{
d62a17ae 1942 struct update_subgroup *subgrp;
1943 struct peer_af *cur_paf;
1944 int all_pending;
1945
1946 subgrp = paf->subgroup;
1947 all_pending = 0;
1948
1949 if (combine) {
1950 /*
1951 * If there are other peers in the old subgroup that also need
1952 * routes to be announced, pull them into the peer's new
1953 * subgroup.
1954 * Combine route announcement with other peers if possible.
1955 *
1956 * For now, we combine only if all peers in the subgroup have an
1957 * announcement pending.
1958 */
1959 all_pending = 1;
1960
a2addae8 1961 SUBGRP_FOREACH_PEER (subgrp, cur_paf) {
d62a17ae 1962 if (cur_paf == paf)
1963 continue;
1964
1965 if (cur_paf->t_announce_route)
1966 continue;
1967
1968 all_pending = 0;
1969 break;
1970 }
1971 }
1972 /*
1973 * Announce to the peer alone if we were not asked to combine peers,
1974 * or if some peers don't have a route annoucement pending.
1975 */
1976 if (!combine || !all_pending) {
1977 update_subgroup_split_peer(paf, NULL);
7bfdba54 1978 subgrp = paf->subgroup;
d62a17ae 1979
7bfdba54 1980 assert(subgrp && subgrp->update_group);
d62a17ae 1981 if (bgp_debug_update(paf->peer, NULL, subgrp->update_group, 0))
6cde4b45 1982 zlog_debug("u%" PRIu64 ":s%" PRIu64" %s announcing routes",
d62a17ae 1983 subgrp->update_group->id, subgrp->id,
1984 paf->peer->host);
1985
1986 subgroup_announce_route(paf->subgroup);
1987 return;
3f9c7369 1988 }
3f9c7369 1989
d62a17ae 1990 /*
1991 * We will announce routes the entire subgroup.
1992 *
1993 * First stop refresh timers on all the other peers.
1994 */
a2addae8 1995 SUBGRP_FOREACH_PEER (subgrp, cur_paf) {
d62a17ae 1996 if (cur_paf == paf)
1997 continue;
3f9c7369 1998
d62a17ae 1999 bgp_stop_announce_route_timer(cur_paf);
2000 }
3f9c7369 2001
d62a17ae 2002 if (bgp_debug_update(paf->peer, NULL, subgrp->update_group, 0))
6cde4b45 2003 zlog_debug("u%" PRIu64 ":s%" PRIu64" announcing routes to %s, combined into %d peers",
d62a17ae 2004 subgrp->update_group->id, subgrp->id,
2005 paf->peer->host, subgrp->peer_count);
3f9c7369 2006
d62a17ae 2007 subgroup_announce_route(subgrp);
3f9c7369 2008
d62a17ae 2009 SUBGRP_INCR_STAT_BY(subgrp, peer_refreshes_combined,
2010 subgrp->peer_count - 1);
3f9c7369
DS
2011}
2012
2fc102e1
QY
2013void subgroup_trigger_write(struct update_subgroup *subgrp)
2014{
2015 struct peer_af *paf;
2016
becedef6
QY
2017 /*
2018 * For each peer in the subgroup, schedule a job to pull packets from
2019 * the subgroup output queue into their own output queue. This action
2020 * will trigger a write job on the I/O thread.
2021 */
996c9314 2022 SUBGRP_FOREACH_PEER (subgrp, paf)
feb17238 2023 if (peer_established(paf->peer))
996c9314
LB
2024 thread_add_timer_msec(
2025 bm->master, bgp_generate_updgrp_packets,
2026 paf->peer, 0,
2027 &paf->peer->t_generate_updgrp_packets);
2fc102e1
QY
2028}
2029
d62a17ae 2030int update_group_clear_update_dbg(struct update_group *updgrp, void *arg)
3f9c7369 2031{
d62a17ae 2032 UPDGRP_PEER_DBG_OFF(updgrp);
2033 return UPDWALK_CONTINUE;
3f9c7369 2034}
adbac85e 2035
06370dac 2036/* Return true if we should addpath encode NLRI to this peer */
be92fc9f 2037bool bgp_addpath_encode_tx(struct peer *peer, afi_t afi, safi_t safi)
adbac85e 2038{
d62a17ae 2039 return (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_TX_ADV)
2040 && CHECK_FLAG(peer->af_cap[afi][safi],
2041 PEER_CAP_ADDPATH_AF_RX_RCV));
adbac85e 2042}
b1dd7180
DA
2043
2044bool bgp_check_selected(struct bgp_path_info *bpi, struct peer *peer,
2045 bool addpath_capable, afi_t afi, safi_t safi)
2046{
2047 return (CHECK_FLAG(bpi->flags, BGP_PATH_SELECTED) ||
2048 (addpath_capable &&
2049 bgp_addpath_tx_path(peer->addpath_type[afi][safi], bpi)));
2050}