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