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