]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_updgrp_adv.c
If the default route is removed from the BGP table we must re-evaluate "neighbor...
[mirror_frr.git] / bgpd / bgp_updgrp_adv.c
CommitLineData
3f9c7369
DS
1/**
2 * bgp_updgrp_adv.c: BGP update group advertisement and adjacency
3 * maintenance
4 *
5 *
6 * @copyright Copyright (C) 2014 Cumulus Networks, Inc.
7 *
8 * @author Avneesh Sachdev <avneesh@sproute.net>
9 * @author Rajesh Varadarajan <rajesh@sproute.net>
10 * @author Pradosh Mohapatra <pradosh@sproute.net>
11 *
12 * This file is part of GNU Zebra.
13 *
14 * GNU Zebra is free software; you can redistribute it and/or modify it
15 * under the terms of the GNU General Public License as published by the
16 * Free Software Foundation; either version 2, or (at your option) any
17 * later version.
18 *
19 * GNU Zebra is distributed in the hope that it will be useful, but
20 * WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 * General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with GNU Zebra; see the file COPYING. If not, write to the Free
26 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
27 * 02111-1307, USA.
28 */
29
30#include <zebra.h>
31
32#include "command.h"
33#include "memory.h"
34#include "prefix.h"
35#include "hash.h"
36#include "thread.h"
37#include "queue.h"
38#include "routemap.h"
39
40#include "bgpd/bgpd.h"
41#include "bgpd/bgp_table.h"
42#include "bgpd/bgp_debug.h"
43#include "bgpd/bgp_route.h"
44#include "bgpd/bgp_advertise.h"
45#include "bgpd/bgp_attr.h"
46#include "bgpd/bgp_aspath.h"
47#include "bgpd/bgp_packet.h"
48#include "bgpd/bgp_fsm.h"
49#include "bgpd/bgp_mplsvpn.h"
50#include "bgpd/bgp_updgrp.h"
51#include "bgpd/bgp_advertise.h"
52
53
54/********************
55 * PRIVATE FUNCTIONS
56 ********************/
57
58static inline struct bgp_adj_out *
59adj_lookup (struct bgp_node *rn, struct update_subgroup *subgrp)
60{
61 struct bgp_adj_out *adj;
62
63 if (!rn || !subgrp)
64 return NULL;
65 for (adj = rn->adj_out; adj; adj = adj->next)
66 if (adj->subgroup == subgrp)
67 break;
68 return adj;
69}
70
71static void
72adj_free (struct bgp_adj_out *adj)
73{
74 TAILQ_REMOVE (&(adj->subgroup->adjq), adj, subgrp_adj_train);
75 SUBGRP_DECR_STAT (adj->subgroup, adj_count);
76 XFREE (MTYPE_BGP_ADJ_OUT, adj);
77}
78
79static int
80group_announce_route_walkcb (struct update_group *updgrp, void *arg)
81{
82 struct updwalk_context *ctx = arg;
83 struct update_subgroup *subgrp;
84
85 UPDGRP_FOREACH_SUBGRP (updgrp, subgrp)
86 {
87
88 /*
89 * Skip the subgroups that have coalesce timer running. We will
90 * walk the entire prefix table for those subgroups when the
91 * coalesce timer fires.
92 */
93 if (!subgrp->t_coalesce)
94 subgroup_process_announce_selected (subgrp, ctx->ri, ctx->rn);
95 }
96
97 return UPDWALK_CONTINUE;
98}
99
100static void
101subgrp_show_adjq_vty (struct update_subgroup *subgrp, struct vty *vty,
102 u_int8_t flags)
103{
104 struct bgp_table *table;
105 struct bgp_adj_out *adj;
106 unsigned long output_count;
107 struct bgp_node *rn;
108 int header1 = 1;
109 struct bgp *bgp;
110 int header2 = 1;
111
112 bgp = SUBGRP_INST (subgrp);
113 if (!bgp)
114 return;
115
116 table = bgp->rib[SUBGRP_AFI (subgrp)][SUBGRP_SAFI (subgrp)];
117
118 output_count = 0;
119
120 for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn))
121 for (adj = rn->adj_out; adj; adj = adj->next)
122 if (adj->subgroup == subgrp)
123 {
124 if (header1)
125 {
126 vty_out (vty,
ffd0c037 127 "BGP table version is %" PRIu64 ", local router ID is %s%s",
3f9c7369
DS
128 table->version, inet_ntoa (bgp->router_id),
129 VTY_NEWLINE);
130 vty_out (vty, BGP_SHOW_SCODE_HEADER, VTY_NEWLINE, VTY_NEWLINE);
131 vty_out (vty, BGP_SHOW_OCODE_HEADER, VTY_NEWLINE, VTY_NEWLINE);
132 header1 = 0;
133 }
134 if (header2)
135 {
136 vty_out (vty, BGP_SHOW_HEADER, VTY_NEWLINE);
137 header2 = 0;
138 }
139 if ((flags & UPDWALK_FLAGS_ADVQUEUE) && adj->adv && adj->adv->baa)
140 {
141 route_vty_out_tmp (vty, &rn->p, adj->adv->baa->attr,
b05a1c8b 142 SUBGRP_SAFI (subgrp));
3f9c7369
DS
143 output_count++;
144 }
145 if ((flags & UPDWALK_FLAGS_ADVERTISED) && adj->attr)
146 {
b05a1c8b 147 route_vty_out_tmp (vty, &rn->p, adj->attr, SUBGRP_SAFI (subgrp));
3f9c7369
DS
148 output_count++;
149 }
150 }
151 if (output_count != 0)
152 vty_out (vty, "%sTotal number of prefixes %ld%s",
153 VTY_NEWLINE, output_count, VTY_NEWLINE);
154}
155
156static int
157updgrp_show_adj_walkcb (struct update_group *updgrp, void *arg)
158{
159 struct updwalk_context *ctx = arg;
160 struct update_subgroup *subgrp;
161 struct vty *vty;
162
163 vty = ctx->vty;
164 UPDGRP_FOREACH_SUBGRP (updgrp, subgrp)
165 {
166 if (ctx->subgrp_id && (ctx->subgrp_id != subgrp->id))
167 continue;
ffd0c037 168 vty_out (vty, "update group %" PRIu64 ", subgroup %" PRIu64 "%s", updgrp->id,
3f9c7369
DS
169 subgrp->id, VTY_NEWLINE);
170 subgrp_show_adjq_vty (subgrp, vty, ctx->flags);
171 }
172 return UPDWALK_CONTINUE;
173}
174
175static void
176updgrp_show_adj (struct bgp *bgp, afi_t afi, safi_t safi,
177 struct vty *vty, u_int64_t id, u_int8_t flags)
178{
179 struct updwalk_context ctx;
180 memset (&ctx, 0, sizeof (ctx));
181 ctx.vty = vty;
182 ctx.subgrp_id = id;
183 ctx.flags = flags;
184
185 update_group_af_walk (bgp, afi, safi, updgrp_show_adj_walkcb, &ctx);
186}
187
188static int
189subgroup_coalesce_timer (struct thread *thread)
190{
191 struct update_subgroup *subgrp;
192
193 subgrp = THREAD_ARG (thread);
194 if (bgp_debug_update(NULL, NULL, subgrp->update_group, 0))
ffd0c037 195 zlog_debug ("u%" PRIu64 ":s%" PRIu64 " announcing routes upon coalesce timer expiry",
3f9c7369
DS
196 (SUBGRP_UPDGRP (subgrp))->id, subgrp->id);
197 subgrp->t_coalesce = NULL;
198 subgrp->v_coalesce = 0;
199 subgroup_announce_route (subgrp);
200
201
202 /* While the announce_route() may kick off the route advertisement timer for
203 * the members of the subgroup, we'd like to send the initial updates much
204 * faster (i.e., without enforcing MRAI). Also, if there were no routes to
205 * announce, this is the method currently employed to trigger the EOR.
206 */
207 if (!bgp_update_delay_active(SUBGRP_INST(subgrp)))
208 {
209 struct peer_af *paf;
210 struct peer *peer;
211
212 SUBGRP_FOREACH_PEER (subgrp, paf)
213 {
214 peer = PAF_PEER(paf);
215 BGP_TIMER_OFF(peer->t_routeadv);
216 BGP_TIMER_ON (peer->t_routeadv, bgp_routeadv_timer, 0);
217 }
218 }
219
220 return 0;
221}
222
223static int
224update_group_announce_walkcb (struct update_group *updgrp, void *arg)
225{
226 struct update_subgroup *subgrp;
227
228 UPDGRP_FOREACH_SUBGRP (updgrp, subgrp)
229 {
230 subgroup_announce_all (subgrp);
231 }
232
233 return UPDWALK_CONTINUE;
234}
235
236static int
237update_group_announce_rrc_walkcb (struct update_group *updgrp, void *arg)
238{
239 struct update_subgroup *subgrp;
240 afi_t afi;
241 safi_t safi;
242 struct peer *peer;
243
244 afi = UPDGRP_AFI (updgrp);
245 safi = UPDGRP_SAFI (updgrp);
246 peer = UPDGRP_PEER (updgrp);
247
248 /* Only announce if this is a group of route-reflector-clients */
249 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_REFLECTOR_CLIENT))
250 {
251 UPDGRP_FOREACH_SUBGRP (updgrp, subgrp)
252 {
253 subgroup_announce_all (subgrp);
254 }
255 }
256
257 return UPDWALK_CONTINUE;
258}
259
260/********************
261 * PUBLIC FUNCTIONS
262 ********************/
263
264/**
265 * Allocate an adj-out object. Do proper initialization of its fields,
266 * primarily its association with the subgroup and the prefix.
267 */
268struct bgp_adj_out *
269bgp_adj_out_alloc (struct update_subgroup *subgrp, struct bgp_node *rn)
270{
271 struct bgp_adj_out *adj;
272
273 adj = XCALLOC (MTYPE_BGP_ADJ_OUT, sizeof (struct bgp_adj_out));
274 adj->subgroup = subgrp;
275 if (rn)
276 {
277 BGP_ADJ_OUT_ADD (rn, adj);
278 bgp_lock_node (rn);
279 adj->rn = rn;
280 }
281 TAILQ_INSERT_TAIL (&(subgrp->adjq), adj, subgrp_adj_train);
282 SUBGRP_INCR_STAT (subgrp, adj_count);
283 return adj;
284}
285
286
287struct bgp_advertise *
288bgp_advertise_clean_subgroup (struct update_subgroup *subgrp,
289 struct bgp_adj_out *adj)
290{
291 struct bgp_advertise *adv;
292 struct bgp_advertise_attr *baa;
293 struct bgp_advertise *next;
294 struct bgp_advertise_fifo *fhead;
295
296 adv = adj->adv;
297 baa = adv->baa;
298 next = NULL;
299
300 if (baa)
301 {
302 fhead = &subgrp->sync->update;
303
304 /* Unlink myself from advertise attribute FIFO. */
305 bgp_advertise_delete (baa, adv);
306
307 /* Fetch next advertise candidate. */
308 next = baa->adv;
309
310 /* Unintern BGP advertise attribute. */
311 bgp_advertise_unintern (subgrp->hash, baa);
312 }
313 else
314 fhead = &subgrp->sync->withdraw;
315
316
317 /* Unlink myself from advertisement FIFO. */
318 BGP_ADV_FIFO_DEL (fhead, adv);
319
320 /* Free memory. */
321 bgp_advertise_free (adj->adv);
322 adj->adv = NULL;
323
324 return next;
325}
326
327void
328bgp_adj_out_set_subgroup (struct bgp_node *rn,
329 struct update_subgroup *subgrp,
330 struct attr *attr, struct bgp_info *binfo)
331{
332 struct bgp_adj_out *adj = NULL;
333 struct bgp_advertise *adv;
334
335 if (DISABLE_BGP_ANNOUNCE)
336 return;
337
338 /* Look for adjacency information. */
339 adj = adj_lookup (rn, subgrp);
340
341 if (!adj)
342 {
343 adj = bgp_adj_out_alloc (subgrp, rn);
344 if (!adj)
345 return;
346 }
347
348 if (adj->adv)
349 bgp_advertise_clean_subgroup (subgrp, adj);
350 adj->adv = bgp_advertise_new ();
351
352 adv = adj->adv;
353 adv->rn = rn;
354 assert (adv->binfo == NULL);
355 adv->binfo = bgp_info_lock (binfo); /* bgp_info adj_out reference */
356
357 if (attr)
358 adv->baa = bgp_advertise_intern (subgrp->hash, attr);
359 else
360 adv->baa = baa_new ();
361 adv->adj = adj;
362
363 /* Add new advertisement to advertisement attribute list. */
364 bgp_advertise_add (adv->baa, adv);
365
366 /*
367 * If the update adv list is empty, trigger the member peers'
368 * mrai timers so the socket writes can happen.
369 */
370 if (BGP_ADV_FIFO_EMPTY (&subgrp->sync->update))
371 {
372 struct peer_af *paf;
373
374 SUBGRP_FOREACH_PEER (subgrp, paf)
375 {
376 bgp_adjust_routeadv (PAF_PEER (paf));
377 }
378 }
379
380 BGP_ADV_FIFO_ADD (&subgrp->sync->update, &adv->fifo);
381
382 subgrp->version = max (subgrp->version, rn->version);
383}
384
4125bb67
DS
385/* The only time 'withdraw' will be false is if we are sending
386 * the "neighbor x.x.x.x default-originate" default and need to clear
387 * bgp_adj_out for the 0.0.0.0/0 route in the BGP table.
388 */
3f9c7369
DS
389void
390bgp_adj_out_unset_subgroup (struct bgp_node *rn,
4125bb67
DS
391 struct update_subgroup *subgrp,
392 char withdraw)
3f9c7369
DS
393{
394 struct bgp_adj_out *adj;
395 struct bgp_advertise *adv;
4125bb67 396 char trigger_write;
3f9c7369
DS
397
398 if (DISABLE_BGP_ANNOUNCE)
399 return;
400
401 /* Lookup existing adjacency, if it is not there return immediately. */
402 adj = adj_lookup (rn, subgrp);
403
404 if (!adj)
405 goto done;
406
4125bb67 407 /* Clean up previous advertisement. */
3f9c7369
DS
408 if (adj->adv)
409 bgp_advertise_clean_subgroup (subgrp, adj);
410
4125bb67 411 if (adj->attr && withdraw)
3f9c7369
DS
412 {
413 /* We need advertisement structure. */
414 adj->adv = bgp_advertise_new ();
415 adv = adj->adv;
416 adv->rn = rn;
417 adv->adj = adj;
418
4125bb67 419 /* Note if we need to trigger a packet write */
3f9c7369 420 if (BGP_ADV_FIFO_EMPTY (&subgrp->sync->withdraw))
4125bb67
DS
421 trigger_write = 1;
422 else
423 trigger_write = 0;
3f9c7369
DS
424
425 /* Add to synchronization entry for withdraw announcement. */
426 BGP_ADV_FIFO_ADD (&subgrp->sync->withdraw, &adv->fifo);
4125bb67
DS
427
428 /* Schedule packet write, if FIFO is getting its first entry. */
429 if (trigger_write)
430 subgroup_trigger_write(subgrp);
3f9c7369
DS
431 }
432 else
433 {
434 /* Remove myself from adjacency. */
435 BGP_ADJ_OUT_DEL (rn, adj);
436
437 /* Free allocated information. */
438 adj_free (adj);
439
440 bgp_unlock_node (rn);
441 }
442
443 /*
444 * Fall through.
445 */
446
447done:
448 subgrp->version = max (subgrp->version, rn->version);
449}
450
451void
452bgp_adj_out_remove_subgroup (struct bgp_node *rn, struct bgp_adj_out *adj,
453 struct update_subgroup *subgrp)
454{
455 if (adj->attr)
456 bgp_attr_unintern (&adj->attr);
457
458 if (adj->adv)
459 bgp_advertise_clean_subgroup (subgrp, adj);
460
461 BGP_ADJ_OUT_DEL (rn, adj);
462 adj_free (adj);
463}
464
465/*
466 * Go through all the routes and clean up the adj/adv structures corresponding
467 * to the subgroup.
468 */
469void
470subgroup_clear_table (struct update_subgroup *subgrp)
471{
472 struct bgp_adj_out *aout, *taout;
473
474 SUBGRP_FOREACH_ADJ_SAFE (subgrp, aout, taout)
475 {
476 bgp_unlock_node (aout->rn);
477 bgp_adj_out_remove_subgroup (aout->rn, aout, subgrp);
478 }
479}
480
481/*
482 * subgroup_announce_table
483 */
484void
485subgroup_announce_table (struct update_subgroup *subgrp,
486 struct bgp_table *table, int rsclient)
487{
488 struct bgp_node *rn;
489 struct bgp_info *ri;
490 struct attr attr;
491 struct attr_extra extra;
492 struct peer *peer;
493 struct peer *onlypeer;
494 afi_t afi;
495 safi_t safi;
496
497 peer = SUBGRP_PEER (subgrp);
498 afi = SUBGRP_AFI (subgrp);
499 safi = SUBGRP_SAFI (subgrp);
500
501 onlypeer = ((SUBGRP_PCOUNT (subgrp) == 1) ?
502 (SUBGRP_PFIRST (subgrp))->peer : NULL);
503 if (rsclient)
504 assert(onlypeer);
505
506 if (!table)
507 table = (rsclient) ? onlypeer->rib[afi][safi] : peer->bgp->rib[afi][safi];
508
509 if (safi != SAFI_MPLS_VPN
510 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE))
511 subgroup_default_originate (subgrp, 0);
512
513 /* It's initialized in bgp_announce_[check|check_rsclient]() */
514 attr.extra = &extra;
515
516 for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn))
517 for (ri = rn->info; ri; ri = ri->next)
518
519 if (CHECK_FLAG (ri->flags, BGP_INFO_SELECTED))
520 {
521 if (!rsclient
522 && subgroup_announce_check (ri, subgrp, &rn->p, &attr))
523 bgp_adj_out_set_subgroup (rn, subgrp, &attr, ri);
524 else
4125bb67 525 bgp_adj_out_unset_subgroup (rn, subgrp, 1);
3f9c7369
DS
526 }
527
528 /*
529 * We walked through the whole table -- make sure our version number
530 * is consistent with the one on the table. This should allow
531 * subgroups to merge sooner if a peer comes up when the route node
532 * with the largest version is no longer in the table. This also
533 * covers the pathological case where all routes in the table have
534 * now been deleted.
535 */
536 subgrp->version = max (subgrp->version, table->version);
537
538 /*
539 * Start a task to merge the subgroup if necessary.
540 */
541 update_subgroup_trigger_merge_check (subgrp, 0);
542}
543
544/*
545 * subgroup_announce_route
546 *
547 * Refresh all routes out to a subgroup.
548 */
549void
550subgroup_announce_route (struct update_subgroup *subgrp)
551{
552 struct bgp_node *rn;
553 struct bgp_table *table;
554 struct peer *onlypeer;
555 struct peer *peer;
556
557 if (update_subgroup_needs_refresh (subgrp))
558 {
559 update_subgroup_set_needs_refresh (subgrp, 0);
560 }
561
562 /*
563 * First update is deferred until ORF or ROUTE-REFRESH is received
564 */
565 onlypeer = ((SUBGRP_PCOUNT (subgrp) == 1) ?
566 (SUBGRP_PFIRST (subgrp))->peer : NULL);
567 if (onlypeer &&
568 CHECK_FLAG (onlypeer->
569 af_sflags[SUBGRP_AFI (subgrp)][SUBGRP_SAFI (subgrp)],
570 PEER_STATUS_ORF_WAIT_REFRESH))
571 return;
572
573 if (SUBGRP_SAFI (subgrp) != SAFI_MPLS_VPN)
574 subgroup_announce_table (subgrp, NULL, 0);
575 else
576 for (rn = bgp_table_top (update_subgroup_rib (subgrp)); rn;
577 rn = bgp_route_next (rn))
578 if ((table = (rn->info)) != NULL)
579 subgroup_announce_table (subgrp, table, 0);
580
581 peer = SUBGRP_PEER(subgrp);
582 if (CHECK_FLAG(peer->af_flags[SUBGRP_AFI(subgrp)][SUBGRP_SAFI(subgrp)],
583 PEER_FLAG_RSERVER_CLIENT))
584 subgroup_announce_table (subgrp, NULL, 1);
585}
586
587void
588subgroup_default_originate (struct update_subgroup *subgrp, int withdraw)
589{
590 struct bgp *bgp;
591 struct attr attr;
592 struct aspath *aspath;
593 struct prefix p;
594 struct peer *from;
595 struct bgp_node *rn;
596 struct bgp_info *ri;
597 struct peer *peer;
598 int ret = RMAP_DENYMATCH;
599 afi_t afi;
600 safi_t safi;
601
602 if (!subgrp)
603 return;
604
605 peer = SUBGRP_PEER (subgrp);
606 afi = SUBGRP_AFI (subgrp);
607 safi = SUBGRP_SAFI (subgrp);
608
609 if (!(afi == AFI_IP || afi == AFI_IP6))
610 return;
611
612 bgp = peer->bgp;
613 from = bgp->peer_self;
614
615 bgp_attr_default_set (&attr, BGP_ORIGIN_IGP);
616 aspath = attr.aspath;
617 attr.local_pref = bgp->default_local_pref;
618 memcpy (&attr.nexthop, &peer->nexthop.v4, IPV4_MAX_BYTELEN);
619
620 if (afi == AFI_IP)
621 str2prefix ("0.0.0.0/0", &p);
622#ifdef HAVE_IPV6
623 else if (afi == AFI_IP6)
624 {
625 struct attr_extra *ae = attr.extra;
626
627 str2prefix ("::/0", &p);
628
629 /* IPv6 global nexthop must be included. */
630 memcpy (&ae->mp_nexthop_global, &peer->nexthop.v6_global,
631 IPV6_MAX_BYTELEN);
801a9bcc 632 ae->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
3f9c7369
DS
633
634 /* If the peer is on shared nextwork and we have link-local
635 nexthop set it. */
636 if (peer->shared_network
637 && !IN6_IS_ADDR_UNSPECIFIED (&peer->nexthop.v6_local))
638 {
639 memcpy (&ae->mp_nexthop_local, &peer->nexthop.v6_local,
640 IPV6_MAX_BYTELEN);
801a9bcc 641 ae->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
3f9c7369
DS
642 }
643 }
644#endif /* HAVE_IPV6 */
645
646 if (peer->default_rmap[afi][safi].name)
647 {
648 SET_FLAG (bgp->peer_self->rmap_type, PEER_RMAP_TYPE_DEFAULT);
649 for (rn = bgp_table_top (bgp->rib[afi][safi]); rn;
650 rn = bgp_route_next (rn))
651 {
652 for (ri = rn->info; ri; ri = ri->next)
653 {
654 struct attr dummy_attr;
655 struct attr_extra dummy_extra;
656 struct bgp_info info;
657
658 /* Provide dummy so the route-map can't modify the attributes */
659 dummy_attr.extra = &dummy_extra;
660 bgp_attr_dup (&dummy_attr, ri->attr);
661 info.peer = ri->peer;
662 info.attr = &dummy_attr;
663
664 ret =
665 route_map_apply (peer->default_rmap[afi][safi].map, &rn->p,
666 RMAP_BGP, &info);
667
668 /* The route map might have set attributes. If we don't flush them
669 * here, they will be leaked. */
670 bgp_attr_flush (&dummy_attr);
671 if (ret != RMAP_DENYMATCH)
672 break;
673 }
674 if (ret != RMAP_DENYMATCH)
675 break;
676 }
677 bgp->peer_self->rmap_type = 0;
678
679 if (ret == RMAP_DENYMATCH)
680 withdraw = 1;
681 }
682
683 if (withdraw)
684 {
685 if (CHECK_FLAG (subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE))
686 subgroup_default_withdraw_packet (subgrp);
687 UNSET_FLAG (subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE);
688 }
689 else
690 {
691 if (!CHECK_FLAG (subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE))
692 {
693 SET_FLAG (subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE);
694 subgroup_default_update_packet (subgrp, &attr, from);
4125bb67
DS
695
696 /* The 'neighbor x.x.x.x default-originate' default will act as an
697 * implicit withdraw for any previous UPDATEs sent for 0.0.0.0/0 so
698 * clear adj_out for the 0.0.0.0/0 prefix in the BGP table.
699 */
700 if (afi == AFI_IP)
701 str2prefix ("0.0.0.0/0", &p);
702#ifdef HAVE_IPV6
703 else
704 str2prefix ("::/0", &p);
705#endif /* HAVE_IPV6 */
706
707 rn = bgp_afi_node_get (bgp->rib[afi][safi], afi, safi, &p, NULL);
708 bgp_adj_out_unset_subgroup (rn, subgrp, 0);
3f9c7369
DS
709 }
710 }
711
712 bgp_attr_extra_free (&attr);
713 aspath_unintern (&aspath);
714}
715
716/*
717 * Announce the BGP table to a subgroup.
718 *
719 * At startup, we try to optimize route announcement by coalescing the
720 * peer-up events. This is done only the first time - from then on,
721 * subgrp->v_coalesce will be set to zero and the normal logic
722 * prevails.
723 */
724void
725subgroup_announce_all (struct update_subgroup *subgrp)
726{
727 if (!subgrp)
728 return;
729
730 /*
731 * If coalesce timer value is not set, announce routes immediately.
732 */
733 if (!subgrp->v_coalesce)
734 {
735 if (bgp_debug_update(NULL, NULL, subgrp->update_group, 0))
ffd0c037 736 zlog_debug ("u%" PRIu64 ":s%" PRIu64 " announcing all routes",
3f9c7369
DS
737 subgrp->update_group->id, subgrp->id);
738 subgroup_announce_route (subgrp);
739 return;
740 }
741
742 /*
743 * We should wait for the coalesce timer. Arm the timer if not done.
744 */
745 if (!subgrp->t_coalesce)
746 {
747 THREAD_TIMER_MSEC_ON (master, subgrp->t_coalesce, subgroup_coalesce_timer,
748 subgrp, subgrp->v_coalesce);
749 }
750}
751
752/*
753 * Go through all update subgroups and set up the adv queue for the
754 * input route.
755 */
756void
757group_announce_route (struct bgp *bgp, afi_t afi, safi_t safi,
758 struct bgp_node *rn, struct bgp_info *ri)
759{
760 struct updwalk_context ctx;
761 ctx.ri = ri;
762 ctx.rn = rn;
763 update_group_af_walk (bgp, afi, safi, group_announce_route_walkcb, &ctx);
764}
765
766void
767update_group_show_adj_queue (struct bgp *bgp, afi_t afi, safi_t safi,
768 struct vty *vty, u_int64_t id)
769{
770 updgrp_show_adj (bgp, afi, safi, vty, id, UPDWALK_FLAGS_ADVQUEUE);
771}
772
773void
774update_group_show_advertised (struct bgp *bgp, afi_t afi, safi_t safi,
775 struct vty *vty, u_int64_t id)
776{
777 updgrp_show_adj (bgp, afi, safi, vty, id, UPDWALK_FLAGS_ADVERTISED);
778}
779
780void
781update_group_announce (struct bgp *bgp)
782{
783 update_group_walk (bgp, update_group_announce_walkcb, NULL);
784}
785
786void
787update_group_announce_rrclients (struct bgp *bgp)
788{
789 update_group_walk (bgp, update_group_announce_rrc_walkcb, NULL);
790}