Line data Source code
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 along
25 : * with this program; see the file COPYING; if not, write to the Free Software
26 : * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
27 : */
28 :
29 : #include <zebra.h>
30 :
31 : #include "command.h"
32 : #include "memory.h"
33 : #include "prefix.h"
34 : #include "hash.h"
35 : #include "thread.h"
36 : #include "queue.h"
37 : #include "routemap.h"
38 : #include "filter.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 : #include "bgpd/bgp_addpath.h"
53 :
54 :
55 : /********************
56 : * PRIVATE FUNCTIONS
57 : ********************/
58 0 : static int bgp_adj_out_compare(const struct bgp_adj_out *o1,
59 : const struct bgp_adj_out *o2)
60 : {
61 0 : if (o1->subgroup < o2->subgroup)
62 : return -1;
63 :
64 0 : if (o1->subgroup > o2->subgroup)
65 : return 1;
66 :
67 0 : if (o1->addpath_tx_id < o2->addpath_tx_id)
68 : return -1;
69 :
70 0 : if (o1->addpath_tx_id > o2->addpath_tx_id)
71 : return 1;
72 :
73 : return 0;
74 : }
75 0 : RB_GENERATE(bgp_adj_out_rb, bgp_adj_out, adj_entry, bgp_adj_out_compare);
76 :
77 0 : static inline struct bgp_adj_out *adj_lookup(struct bgp_dest *dest,
78 : struct update_subgroup *subgrp,
79 : uint32_t addpath_tx_id)
80 : {
81 0 : struct bgp_adj_out lookup;
82 :
83 0 : if (!dest || !subgrp)
84 : return NULL;
85 :
86 : /* update-groups that do not support addpath will pass 0 for
87 : * addpath_tx_id. */
88 0 : lookup.subgroup = subgrp;
89 0 : lookup.addpath_tx_id = addpath_tx_id;
90 :
91 0 : return RB_FIND(bgp_adj_out_rb, &dest->adj_out, &lookup);
92 : }
93 :
94 0 : static void adj_free(struct bgp_adj_out *adj)
95 : {
96 0 : TAILQ_REMOVE(&(adj->subgroup->adjq), adj, subgrp_adj_train);
97 0 : SUBGRP_DECR_STAT(adj->subgroup, adj_count);
98 :
99 0 : RB_REMOVE(bgp_adj_out_rb, &adj->dest->adj_out, adj);
100 0 : bgp_dest_unlock_node(adj->dest);
101 :
102 0 : XFREE(MTYPE_BGP_ADJ_OUT, adj);
103 0 : }
104 :
105 0 : static void subgrp_withdraw_stale_addpath(struct updwalk_context *ctx,
106 : struct update_subgroup *subgrp)
107 : {
108 0 : struct bgp_adj_out *adj, *adj_next;
109 0 : uint32_t id;
110 0 : struct bgp_path_info *pi;
111 0 : afi_t afi = SUBGRP_AFI(subgrp);
112 0 : safi_t safi = SUBGRP_SAFI(subgrp);
113 0 : struct peer *peer = SUBGRP_PEER(subgrp);
114 :
115 : /* Look through all of the paths we have advertised for this rn and send
116 : * a withdraw for the ones that are no longer present */
117 0 : RB_FOREACH_SAFE (adj, bgp_adj_out_rb, &ctx->dest->adj_out, adj_next) {
118 0 : if (adj->subgroup != subgrp)
119 0 : continue;
120 :
121 0 : for (pi = bgp_dest_get_bgp_path_info(ctx->dest); pi;
122 0 : pi = pi->next) {
123 0 : id = bgp_addpath_id_for_peer(peer, afi, safi,
124 : &pi->tx_addpath);
125 :
126 0 : if (id == adj->addpath_tx_id) {
127 : break;
128 : }
129 : }
130 :
131 0 : if (!pi) {
132 0 : subgroup_process_announce_selected(
133 : subgrp, NULL, ctx->dest, adj->addpath_tx_id);
134 : }
135 : }
136 0 : }
137 :
138 0 : static int group_announce_route_walkcb(struct update_group *updgrp, void *arg)
139 : {
140 0 : struct updwalk_context *ctx = arg;
141 0 : struct update_subgroup *subgrp;
142 0 : struct bgp_path_info *pi;
143 0 : afi_t afi;
144 0 : safi_t safi;
145 0 : struct peer *peer;
146 0 : struct bgp_adj_out *adj, *adj_next;
147 0 : bool addpath_capable;
148 :
149 0 : afi = UPDGRP_AFI(updgrp);
150 0 : safi = UPDGRP_SAFI(updgrp);
151 0 : peer = UPDGRP_PEER(updgrp);
152 0 : addpath_capable = bgp_addpath_encode_tx(peer, afi, safi);
153 :
154 0 : if (BGP_DEBUG(update, UPDATE_OUT))
155 0 : zlog_debug("%s: afi=%s, safi=%s, p=%pRN", __func__,
156 : afi2str(afi), safi2str(safi),
157 : bgp_dest_to_rnode(ctx->dest));
158 :
159 0 : UPDGRP_FOREACH_SUBGRP (updgrp, subgrp) {
160 :
161 : /*
162 : * Skip the subgroups that have coalesce timer running. We will
163 : * walk the entire prefix table for those subgroups when the
164 : * coalesce timer fires.
165 : */
166 0 : if (!subgrp->t_coalesce) {
167 :
168 : /* An update-group that uses addpath */
169 0 : if (addpath_capable) {
170 0 : subgrp_withdraw_stale_addpath(ctx, subgrp);
171 :
172 0 : for (pi = bgp_dest_get_bgp_path_info(ctx->dest);
173 0 : pi; pi = pi->next) {
174 : /* Skip the bestpath for now */
175 0 : if (pi == ctx->pi)
176 0 : continue;
177 :
178 0 : subgroup_process_announce_selected(
179 : subgrp, pi, ctx->dest,
180 : bgp_addpath_id_for_peer(
181 : peer, afi, safi,
182 : &pi->tx_addpath));
183 : }
184 :
185 : /* Process the bestpath last so the "show [ip]
186 : * bgp neighbor x.x.x.x advertised"
187 : * output shows the attributes from the bestpath
188 : */
189 0 : if (ctx->pi)
190 0 : subgroup_process_announce_selected(
191 : subgrp, ctx->pi, ctx->dest,
192 : bgp_addpath_id_for_peer(
193 : peer, afi, safi,
194 : &ctx->pi->tx_addpath));
195 : }
196 : /* An update-group that does not use addpath */
197 : else {
198 0 : if (ctx->pi) {
199 0 : subgroup_process_announce_selected(
200 : subgrp, ctx->pi, ctx->dest,
201 : bgp_addpath_id_for_peer(
202 : peer, afi, safi,
203 : &ctx->pi->tx_addpath));
204 : } else {
205 : /* Find the addpath_tx_id of the path we
206 : * had advertised and
207 : * send a withdraw */
208 0 : RB_FOREACH_SAFE (adj, bgp_adj_out_rb,
209 : &ctx->dest->adj_out,
210 : adj_next) {
211 0 : if (adj->subgroup == subgrp) {
212 0 : subgroup_process_announce_selected(
213 : subgrp, NULL,
214 : ctx->dest,
215 : adj->addpath_tx_id);
216 : }
217 : }
218 : }
219 : }
220 : }
221 :
222 : /* Notify BGP Conditional advertisement */
223 0 : bgp_notify_conditional_adv_scanner(subgrp);
224 : }
225 :
226 0 : return UPDWALK_CONTINUE;
227 : }
228 :
229 0 : static void subgrp_show_adjq_vty(struct update_subgroup *subgrp,
230 : struct vty *vty, uint8_t flags)
231 : {
232 0 : struct bgp_table *table;
233 0 : struct bgp_adj_out *adj;
234 0 : unsigned long output_count;
235 0 : struct bgp_dest *dest;
236 0 : int header1 = 1;
237 0 : struct bgp *bgp;
238 0 : int header2 = 1;
239 :
240 0 : bgp = SUBGRP_INST(subgrp);
241 0 : if (!bgp)
242 : return;
243 :
244 0 : table = bgp->rib[SUBGRP_AFI(subgrp)][SUBGRP_SAFI(subgrp)];
245 :
246 0 : output_count = 0;
247 :
248 0 : for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
249 0 : const struct prefix *dest_p = bgp_dest_get_prefix(dest);
250 :
251 0 : RB_FOREACH (adj, bgp_adj_out_rb, &dest->adj_out) {
252 0 : if (adj->subgroup != subgrp)
253 0 : continue;
254 :
255 0 : if (header1) {
256 0 : vty_out(vty,
257 : "BGP table version is %" PRIu64
258 : ", local router ID is %pI4\n",
259 : table->version, &bgp->router_id);
260 0 : vty_out(vty, BGP_SHOW_SCODE_HEADER);
261 0 : vty_out(vty, BGP_SHOW_OCODE_HEADER);
262 0 : header1 = 0;
263 : }
264 0 : if (header2) {
265 0 : vty_out(vty, BGP_SHOW_HEADER);
266 0 : header2 = 0;
267 : }
268 0 : if ((flags & UPDWALK_FLAGS_ADVQUEUE) && adj->adv &&
269 0 : adj->adv->baa) {
270 0 : route_vty_out_tmp(
271 : vty, dest, dest_p, adj->adv->baa->attr,
272 0 : SUBGRP_SAFI(subgrp), 0, NULL, false);
273 0 : output_count++;
274 : }
275 0 : if ((flags & UPDWALK_FLAGS_ADVERTISED) && adj->attr) {
276 0 : route_vty_out_tmp(vty, dest, dest_p, adj->attr,
277 0 : SUBGRP_SAFI(subgrp), 0, NULL,
278 : false);
279 0 : output_count++;
280 : }
281 : }
282 : }
283 0 : if (output_count != 0)
284 0 : vty_out(vty, "\nTotal number of prefixes %ld\n", output_count);
285 : }
286 :
287 0 : static int updgrp_show_adj_walkcb(struct update_group *updgrp, void *arg)
288 : {
289 0 : struct updwalk_context *ctx = arg;
290 0 : struct update_subgroup *subgrp;
291 0 : struct vty *vty;
292 :
293 0 : vty = ctx->vty;
294 0 : UPDGRP_FOREACH_SUBGRP (updgrp, subgrp) {
295 0 : if (ctx->subgrp_id && (ctx->subgrp_id != subgrp->id))
296 0 : continue;
297 0 : vty_out(vty, "update group %" PRIu64 ", subgroup %" PRIu64 "\n",
298 : updgrp->id, subgrp->id);
299 0 : subgrp_show_adjq_vty(subgrp, vty, ctx->flags);
300 : }
301 0 : return UPDWALK_CONTINUE;
302 : }
303 :
304 0 : static void updgrp_show_adj(struct bgp *bgp, afi_t afi, safi_t safi,
305 : struct vty *vty, uint64_t id, uint8_t flags)
306 : {
307 0 : struct updwalk_context ctx;
308 0 : memset(&ctx, 0, sizeof(ctx));
309 0 : ctx.vty = vty;
310 0 : ctx.subgrp_id = id;
311 0 : ctx.flags = flags;
312 :
313 0 : update_group_af_walk(bgp, afi, safi, updgrp_show_adj_walkcb, &ctx);
314 0 : }
315 :
316 0 : static void subgroup_coalesce_timer(struct thread *thread)
317 : {
318 0 : struct update_subgroup *subgrp;
319 0 : struct bgp *bgp;
320 :
321 0 : subgrp = THREAD_ARG(thread);
322 0 : if (bgp_debug_update(NULL, NULL, subgrp->update_group, 0))
323 0 : zlog_debug("u%" PRIu64 ":s%" PRIu64" announcing routes upon coalesce timer expiry(%u ms)",
324 : (SUBGRP_UPDGRP(subgrp))->id, subgrp->id,
325 : subgrp->v_coalesce);
326 0 : subgrp->t_coalesce = NULL;
327 0 : subgrp->v_coalesce = 0;
328 0 : bgp = SUBGRP_INST(subgrp);
329 0 : subgroup_announce_route(subgrp);
330 :
331 :
332 : /* While the announce_route() may kick off the route advertisement timer
333 : * for
334 : * the members of the subgroup, we'd like to send the initial updates
335 : * much
336 : * faster (i.e., without enforcing MRAI). Also, if there were no routes
337 : * to
338 : * announce, this is the method currently employed to trigger the EOR.
339 : */
340 0 : if (!bgp_update_delay_active(SUBGRP_INST(subgrp)) &&
341 0 : !(BGP_SUPPRESS_FIB_ENABLED(bgp))) {
342 0 : struct peer_af *paf;
343 0 : struct peer *peer;
344 :
345 0 : SUBGRP_FOREACH_PEER (subgrp, paf) {
346 0 : peer = PAF_PEER(paf);
347 0 : THREAD_OFF(peer->t_routeadv);
348 0 : BGP_TIMER_ON(peer->t_routeadv, bgp_routeadv_timer, 0);
349 : }
350 : }
351 0 : }
352 :
353 0 : static int update_group_announce_walkcb(struct update_group *updgrp, void *arg)
354 : {
355 0 : struct update_subgroup *subgrp;
356 :
357 0 : UPDGRP_FOREACH_SUBGRP (updgrp, subgrp) {
358 : /* Avoid supressing duplicate routes later
359 : * when processing in subgroup_announce_table().
360 : */
361 0 : SET_FLAG(subgrp->sflags, SUBGRP_STATUS_FORCE_UPDATES);
362 :
363 0 : subgroup_announce_all(subgrp);
364 : }
365 :
366 0 : return UPDWALK_CONTINUE;
367 : }
368 :
369 0 : static int update_group_announce_rrc_walkcb(struct update_group *updgrp,
370 : void *arg)
371 : {
372 0 : struct update_subgroup *subgrp;
373 0 : afi_t afi;
374 0 : safi_t safi;
375 0 : struct peer *peer;
376 :
377 0 : afi = UPDGRP_AFI(updgrp);
378 0 : safi = UPDGRP_SAFI(updgrp);
379 0 : peer = UPDGRP_PEER(updgrp);
380 :
381 : /* Only announce if this is a group of route-reflector-clients */
382 0 : if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_REFLECTOR_CLIENT)) {
383 0 : UPDGRP_FOREACH_SUBGRP (updgrp, subgrp) {
384 0 : subgroup_announce_all(subgrp);
385 : }
386 : }
387 :
388 0 : return UPDWALK_CONTINUE;
389 : }
390 :
391 : /********************
392 : * PUBLIC FUNCTIONS
393 : ********************/
394 :
395 : /**
396 : * Allocate an adj-out object. Do proper initialization of its fields,
397 : * primarily its association with the subgroup and the prefix.
398 : */
399 0 : struct bgp_adj_out *bgp_adj_out_alloc(struct update_subgroup *subgrp,
400 : struct bgp_dest *dest,
401 : uint32_t addpath_tx_id)
402 : {
403 0 : struct bgp_adj_out *adj;
404 :
405 0 : adj = XCALLOC(MTYPE_BGP_ADJ_OUT, sizeof(struct bgp_adj_out));
406 0 : adj->subgroup = subgrp;
407 0 : adj->addpath_tx_id = addpath_tx_id;
408 :
409 0 : RB_INSERT(bgp_adj_out_rb, &dest->adj_out, adj);
410 0 : bgp_dest_lock_node(dest);
411 0 : adj->dest = dest;
412 :
413 0 : TAILQ_INSERT_TAIL(&(subgrp->adjq), adj, subgrp_adj_train);
414 0 : SUBGRP_INCR_STAT(subgrp, adj_count);
415 0 : return adj;
416 : }
417 :
418 :
419 : struct bgp_advertise *
420 0 : bgp_advertise_clean_subgroup(struct update_subgroup *subgrp,
421 : struct bgp_adj_out *adj)
422 : {
423 0 : struct bgp_advertise *adv;
424 0 : struct bgp_advertise_attr *baa;
425 0 : struct bgp_advertise *next;
426 0 : struct bgp_adv_fifo_head *fhead;
427 :
428 0 : adv = adj->adv;
429 0 : baa = adv->baa;
430 0 : next = NULL;
431 :
432 0 : if (baa) {
433 0 : fhead = &subgrp->sync->update;
434 :
435 : /* Unlink myself from advertise attribute FIFO. */
436 0 : bgp_advertise_delete(baa, adv);
437 :
438 : /* Fetch next advertise candidate. */
439 0 : next = baa->adv;
440 :
441 : /* Unintern BGP advertise attribute. */
442 0 : bgp_advertise_attr_unintern(subgrp->hash, baa);
443 : } else
444 0 : fhead = &subgrp->sync->withdraw;
445 :
446 :
447 : /* Unlink myself from advertisement FIFO. */
448 0 : bgp_adv_fifo_del(fhead, adv);
449 :
450 : /* Free memory. */
451 0 : bgp_advertise_free(adj->adv);
452 0 : adj->adv = NULL;
453 :
454 0 : return next;
455 : }
456 :
457 0 : void bgp_adj_out_set_subgroup(struct bgp_dest *dest,
458 : struct update_subgroup *subgrp, struct attr *attr,
459 : struct bgp_path_info *path)
460 : {
461 0 : struct bgp_adj_out *adj = NULL;
462 0 : struct bgp_advertise *adv;
463 0 : struct peer *peer;
464 0 : afi_t afi;
465 0 : safi_t safi;
466 0 : struct peer *adv_peer;
467 0 : struct peer_af *paf;
468 0 : struct bgp *bgp;
469 0 : uint32_t attr_hash = attrhash_key_make(attr);
470 :
471 0 : peer = SUBGRP_PEER(subgrp);
472 0 : afi = SUBGRP_AFI(subgrp);
473 0 : safi = SUBGRP_SAFI(subgrp);
474 0 : bgp = SUBGRP_INST(subgrp);
475 :
476 0 : if (DISABLE_BGP_ANNOUNCE)
477 : return;
478 :
479 : /* Look for adjacency information. */
480 0 : adj = adj_lookup(
481 : dest, subgrp,
482 : bgp_addpath_id_for_peer(peer, afi, safi, &path->tx_addpath));
483 :
484 0 : if (adj) {
485 0 : if (CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_TABLE_REPARSING))
486 0 : subgrp->pscount++;
487 : } else {
488 0 : adj = bgp_adj_out_alloc(
489 : subgrp, dest,
490 : bgp_addpath_id_for_peer(peer, afi, safi,
491 : &path->tx_addpath));
492 0 : if (!adj)
493 : return;
494 :
495 0 : subgrp->pscount++;
496 : }
497 :
498 : /* Check if we are sending the same route. This is needed to
499 : * avoid duplicate UPDATES. For instance, filtering communities
500 : * at egress, neighbors will see duplicate UPDATES despite
501 : * the route wasn't changed actually.
502 : * Do not suppress BGP UPDATES for route-refresh.
503 : */
504 0 : if (CHECK_FLAG(bgp->flags, BGP_FLAG_SUPPRESS_DUPLICATES)
505 0 : && !CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_FORCE_UPDATES)
506 0 : && adj->attr_hash == attr_hash) {
507 0 : if (BGP_DEBUG(update, UPDATE_OUT)) {
508 0 : char attr_str[BUFSIZ] = {0};
509 :
510 0 : bgp_dump_attr(attr, attr_str, sizeof(attr_str));
511 :
512 0 : zlog_debug("%s suppress UPDATE w/ attr: %s", peer->host,
513 : attr_str);
514 : }
515 0 : return;
516 : }
517 :
518 0 : if (adj->adv)
519 0 : bgp_advertise_clean_subgroup(subgrp, adj);
520 0 : adj->adv = bgp_advertise_new();
521 :
522 0 : adv = adj->adv;
523 0 : adv->dest = dest;
524 0 : assert(adv->pathi == NULL);
525 : /* bgp_path_info adj_out reference */
526 0 : adv->pathi = bgp_path_info_lock(path);
527 :
528 0 : adv->baa = bgp_advertise_attr_intern(subgrp->hash, attr);
529 0 : adv->adj = adj;
530 0 : adj->attr_hash = attr_hash;
531 :
532 : /* Add new advertisement to advertisement attribute list. */
533 0 : bgp_advertise_add(adv->baa, adv);
534 :
535 : /*
536 : * If the update adv list is empty, trigger the member peers'
537 : * mrai timers so the socket writes can happen.
538 : */
539 0 : if (!bgp_adv_fifo_count(&subgrp->sync->update)) {
540 0 : SUBGRP_FOREACH_PEER (subgrp, paf) {
541 : /* If there are no routes in the withdraw list, set
542 : * the flag PEER_STATUS_ADV_DELAY which will allow
543 : * more routes to be sent in the update message
544 : */
545 0 : if (BGP_SUPPRESS_FIB_ENABLED(bgp)) {
546 0 : adv_peer = PAF_PEER(paf);
547 0 : if (!bgp_adv_fifo_count(
548 0 : &subgrp->sync->withdraw))
549 0 : SET_FLAG(adv_peer->thread_flags,
550 : PEER_THREAD_SUBGRP_ADV_DELAY);
551 : else
552 0 : UNSET_FLAG(adv_peer->thread_flags,
553 : PEER_THREAD_SUBGRP_ADV_DELAY);
554 : }
555 0 : bgp_adjust_routeadv(PAF_PEER(paf));
556 : }
557 : }
558 :
559 0 : bgp_adv_fifo_add_tail(&subgrp->sync->update, adv);
560 :
561 0 : subgrp->version = MAX(subgrp->version, dest->version);
562 : }
563 :
564 : /* The only time 'withdraw' will be false is if we are sending
565 : * the "neighbor x.x.x.x default-originate" default and need to clear
566 : * bgp_adj_out for the 0.0.0.0/0 route in the BGP table.
567 : */
568 0 : void bgp_adj_out_unset_subgroup(struct bgp_dest *dest,
569 : struct update_subgroup *subgrp, char withdraw,
570 : uint32_t addpath_tx_id)
571 : {
572 0 : struct bgp_adj_out *adj;
573 0 : struct bgp_advertise *adv;
574 0 : bool trigger_write;
575 :
576 0 : if (DISABLE_BGP_ANNOUNCE)
577 : return;
578 :
579 : /* Lookup existing adjacency */
580 0 : adj = adj_lookup(dest, subgrp, addpath_tx_id);
581 0 : if (adj != NULL) {
582 : /* Clean up previous advertisement. */
583 0 : if (adj->adv)
584 0 : bgp_advertise_clean_subgroup(subgrp, adj);
585 :
586 : /* If default originate is enabled and the route is default
587 : * route, do not send withdraw. This will prevent deletion of
588 : * the default route at the peer.
589 : */
590 0 : if (CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)
591 0 : && is_default_prefix(bgp_dest_get_prefix(dest)))
592 : return;
593 :
594 0 : if (adj->attr && withdraw) {
595 : /* We need advertisement structure. */
596 0 : adj->adv = bgp_advertise_new();
597 0 : adv = adj->adv;
598 0 : adv->dest = dest;
599 0 : adv->adj = adj;
600 :
601 : /* Note if we need to trigger a packet write */
602 0 : trigger_write =
603 0 : !bgp_adv_fifo_count(&subgrp->sync->withdraw);
604 :
605 : /* Add to synchronization entry for withdraw
606 : * announcement. */
607 0 : bgp_adv_fifo_add_tail(&subgrp->sync->withdraw, adv);
608 :
609 0 : if (trigger_write)
610 0 : subgroup_trigger_write(subgrp);
611 : } else {
612 : /* Free allocated information. */
613 0 : adj_free(adj);
614 : }
615 0 : if (!CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_TABLE_REPARSING))
616 0 : subgrp->pscount--;
617 : }
618 :
619 0 : subgrp->version = MAX(subgrp->version, dest->version);
620 : }
621 :
622 0 : void bgp_adj_out_remove_subgroup(struct bgp_dest *dest, struct bgp_adj_out *adj,
623 : struct update_subgroup *subgrp)
624 : {
625 0 : if (adj->attr)
626 0 : bgp_attr_unintern(&adj->attr);
627 :
628 0 : if (adj->adv)
629 0 : bgp_advertise_clean_subgroup(subgrp, adj);
630 :
631 0 : adj_free(adj);
632 0 : }
633 :
634 : /*
635 : * Go through all the routes and clean up the adj/adv structures corresponding
636 : * to the subgroup.
637 : */
638 1 : void subgroup_clear_table(struct update_subgroup *subgrp)
639 : {
640 1 : struct bgp_adj_out *aout, *taout;
641 :
642 1 : SUBGRP_FOREACH_ADJ_SAFE (subgrp, aout, taout)
643 0 : bgp_adj_out_remove_subgroup(aout->dest, aout, subgrp);
644 1 : }
645 :
646 : /*
647 : * subgroup_announce_table
648 : */
649 0 : void subgroup_announce_table(struct update_subgroup *subgrp,
650 : struct bgp_table *table)
651 : {
652 0 : struct bgp_dest *dest;
653 0 : struct bgp_path_info *ri;
654 0 : struct attr attr;
655 0 : struct peer *peer;
656 0 : afi_t afi;
657 0 : safi_t safi;
658 0 : safi_t safi_rib;
659 0 : bool addpath_capable;
660 0 : struct bgp *bgp;
661 0 : bool advertise;
662 :
663 0 : peer = SUBGRP_PEER(subgrp);
664 0 : afi = SUBGRP_AFI(subgrp);
665 0 : safi = SUBGRP_SAFI(subgrp);
666 0 : bgp = SUBGRP_INST(subgrp);
667 0 : addpath_capable = bgp_addpath_encode_tx(peer, afi, safi);
668 :
669 0 : if (safi == SAFI_LABELED_UNICAST)
670 : safi_rib = SAFI_UNICAST;
671 : else
672 0 : safi_rib = safi;
673 :
674 0 : if (!table)
675 0 : table = peer->bgp->rib[afi][safi_rib];
676 :
677 0 : if (safi != SAFI_MPLS_VPN && safi != SAFI_ENCAP && safi != SAFI_EVPN
678 0 : && CHECK_FLAG(peer->af_flags[afi][safi],
679 : PEER_FLAG_DEFAULT_ORIGINATE))
680 0 : subgroup_default_originate(subgrp, 0);
681 :
682 0 : subgrp->pscount = 0;
683 0 : SET_FLAG(subgrp->sflags, SUBGRP_STATUS_TABLE_REPARSING);
684 :
685 0 : for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
686 0 : const struct prefix *dest_p = bgp_dest_get_prefix(dest);
687 :
688 : /* Check if the route can be advertised */
689 0 : advertise = bgp_check_advertise(bgp, dest);
690 :
691 0 : for (ri = bgp_dest_get_bgp_path_info(dest); ri; ri = ri->next) {
692 :
693 0 : if (!bgp_check_selected(ri, peer, addpath_capable, afi,
694 : safi_rib))
695 0 : continue;
696 :
697 0 : if (subgroup_announce_check(dest, ri, subgrp, dest_p,
698 : &attr, NULL)) {
699 : /* Check if route can be advertised */
700 0 : if (advertise) {
701 0 : if (!bgp_check_withdrawal(bgp, dest))
702 0 : bgp_adj_out_set_subgroup(
703 : dest, subgrp, &attr,
704 : ri);
705 : else
706 0 : bgp_adj_out_unset_subgroup(
707 : dest, subgrp, 1,
708 : bgp_addpath_id_for_peer(
709 : peer, afi,
710 : safi_rib,
711 : &ri->tx_addpath));
712 : }
713 : } else {
714 : /* If default originate is enabled for
715 : * the peer, do not send explicit
716 : * withdraw. This will prevent deletion
717 : * of default route advertised through
718 : * default originate
719 : */
720 0 : if (CHECK_FLAG(peer->af_flags[afi][safi],
721 0 : PEER_FLAG_DEFAULT_ORIGINATE) &&
722 0 : is_default_prefix(
723 : bgp_dest_get_prefix(dest)))
724 : break;
725 :
726 0 : bgp_adj_out_unset_subgroup(
727 : dest, subgrp, 1,
728 : bgp_addpath_id_for_peer(
729 : peer, afi, safi_rib,
730 : &ri->tx_addpath));
731 : }
732 : }
733 : }
734 0 : UNSET_FLAG(subgrp->sflags, SUBGRP_STATUS_TABLE_REPARSING);
735 :
736 : /*
737 : * We walked through the whole table -- make sure our version number
738 : * is consistent with the one on the table. This should allow
739 : * subgroups to merge sooner if a peer comes up when the route node
740 : * with the largest version is no longer in the table. This also
741 : * covers the pathological case where all routes in the table have
742 : * now been deleted.
743 : */
744 0 : subgrp->version = MAX(subgrp->version, table->version);
745 :
746 : /*
747 : * Start a task to merge the subgroup if necessary.
748 : */
749 0 : update_subgroup_trigger_merge_check(subgrp, 0);
750 0 : }
751 :
752 : /*
753 : * subgroup_announce_route
754 : *
755 : * Refresh all routes out to a subgroup.
756 : */
757 0 : void subgroup_announce_route(struct update_subgroup *subgrp)
758 : {
759 0 : struct bgp_dest *dest;
760 0 : struct bgp_table *table;
761 0 : struct peer *onlypeer;
762 :
763 0 : if (update_subgroup_needs_refresh(subgrp)) {
764 0 : update_subgroup_set_needs_refresh(subgrp, 0);
765 : }
766 :
767 : /*
768 : * First update is deferred until ORF or ROUTE-REFRESH is received
769 : */
770 0 : onlypeer = ((SUBGRP_PCOUNT(subgrp) == 1) ? (SUBGRP_PFIRST(subgrp))->peer
771 0 : : NULL);
772 0 : if (onlypeer && CHECK_FLAG(onlypeer->af_sflags[SUBGRP_AFI(subgrp)]
773 : [SUBGRP_SAFI(subgrp)],
774 : PEER_STATUS_ORF_WAIT_REFRESH))
775 : return;
776 :
777 0 : if (SUBGRP_SAFI(subgrp) != SAFI_MPLS_VPN
778 : && SUBGRP_SAFI(subgrp) != SAFI_ENCAP
779 0 : && SUBGRP_SAFI(subgrp) != SAFI_EVPN)
780 0 : subgroup_announce_table(subgrp, NULL);
781 : else
782 0 : for (dest = bgp_table_top(update_subgroup_rib(subgrp)); dest;
783 0 : dest = bgp_route_next(dest)) {
784 0 : table = bgp_dest_get_bgp_table_info(dest);
785 0 : if (!table)
786 0 : continue;
787 0 : subgroup_announce_table(subgrp, table);
788 : }
789 : }
790 :
791 0 : void subgroup_default_originate(struct update_subgroup *subgrp, int withdraw)
792 : {
793 0 : struct bgp *bgp;
794 0 : struct attr attr;
795 0 : struct attr *new_attr = &attr;
796 0 : struct prefix p;
797 0 : struct peer *from;
798 0 : struct bgp_dest *dest;
799 0 : struct bgp_path_info *pi;
800 0 : struct peer *peer;
801 0 : struct bgp_adj_out *adj;
802 0 : route_map_result_t ret = RMAP_DENYMATCH;
803 0 : route_map_result_t new_ret = RMAP_DENYMATCH;
804 0 : afi_t afi;
805 0 : safi_t safi;
806 0 : safi_t safi_rib;
807 0 : int pref = 65536;
808 0 : int new_pref = 0;
809 :
810 0 : if (!subgrp)
811 0 : return;
812 :
813 0 : peer = SUBGRP_PEER(subgrp);
814 0 : afi = SUBGRP_AFI(subgrp);
815 0 : safi = SUBGRP_SAFI(subgrp);
816 :
817 0 : if (!(afi == AFI_IP || afi == AFI_IP6))
818 : return;
819 :
820 0 : if (safi == SAFI_LABELED_UNICAST)
821 : safi_rib = SAFI_UNICAST;
822 : else
823 0 : safi_rib = safi;
824 :
825 0 : bgp = peer->bgp;
826 0 : from = bgp->peer_self;
827 :
828 0 : bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_IGP);
829 :
830 : /* make coverity happy */
831 0 : assert(attr.aspath);
832 :
833 0 : attr.med = 0;
834 0 : attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
835 :
836 0 : if ((afi == AFI_IP6) || peer_cap_enhe(peer, afi, safi)) {
837 : /* IPv6 global nexthop must be included. */
838 0 : attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
839 :
840 : /* If the peer is on shared nextwork and we have link-local
841 : nexthop set it. */
842 0 : if (peer->shared_network
843 0 : && !IN6_IS_ADDR_UNSPECIFIED(&peer->nexthop.v6_local))
844 0 : attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
845 : }
846 :
847 0 : if (peer->default_rmap[afi][safi].name) {
848 0 : struct bgp_path_info tmp_pi = {0};
849 :
850 0 : tmp_pi.peer = bgp->peer_self;
851 :
852 0 : SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_DEFAULT);
853 :
854 : /* Iterate over the RIB to see if we can announce
855 : * the default route. We announce the default
856 : * route only if route-map has a match.
857 : */
858 0 : for (dest = bgp_table_top(bgp->rib[afi][safi_rib]); dest;
859 0 : dest = bgp_route_next(dest)) {
860 0 : if (!bgp_dest_has_bgp_path_info_data(dest))
861 0 : continue;
862 :
863 0 : for (pi = bgp_dest_get_bgp_path_info(dest); pi;
864 0 : pi = pi->next) {
865 0 : struct attr tmp_attr = attr;
866 :
867 0 : tmp_pi.attr = &tmp_attr;
868 :
869 0 : new_ret = route_map_apply_ext(
870 : peer->default_rmap[afi][safi].map,
871 : bgp_dest_get_prefix(dest), pi, &tmp_pi,
872 : &new_pref);
873 :
874 0 : if (new_ret == RMAP_PERMITMATCH) {
875 0 : if (new_pref < pref) {
876 0 : pref = new_pref;
877 0 : bgp_attr_flush(new_attr);
878 0 : new_attr = bgp_attr_intern(
879 : tmp_pi.attr);
880 0 : bgp_attr_flush(tmp_pi.attr);
881 : }
882 0 : subgroup_announce_reset_nhop(
883 0 : (peer_cap_enhe(peer, afi, safi)
884 : ? AF_INET6
885 : : AF_INET),
886 : new_attr);
887 0 : ret = new_ret;
888 : } else
889 0 : bgp_attr_flush(&tmp_attr);
890 : }
891 : }
892 0 : bgp->peer_self->rmap_type = 0;
893 :
894 0 : if (ret == RMAP_DENYMATCH) {
895 : /*
896 : * If its a implicit withdraw due to routemap
897 : * deny operation need to set the flag back.
898 : * This is a convertion of update flow to
899 : * withdraw flow.
900 : */
901 0 : if (!withdraw &&
902 0 : (!CHECK_FLAG(subgrp->sflags,
903 : SUBGRP_STATUS_DEFAULT_ORIGINATE)))
904 0 : SET_FLAG(subgrp->sflags,
905 : SUBGRP_STATUS_DEFAULT_ORIGINATE);
906 : withdraw = 1;
907 : }
908 : }
909 :
910 : /* Check if the default route is in local BGP RIB which is
911 : * installed through redistribute or network command
912 : */
913 0 : memset(&p, 0, sizeof(p));
914 0 : p.family = afi2family(afi);
915 0 : p.prefixlen = 0;
916 0 : dest = bgp_afi_node_lookup(bgp->rib[afi][safi_rib], afi, safi_rib, &p,
917 : NULL);
918 :
919 0 : if (withdraw) {
920 : /* Withdraw the default route advertised using default
921 : * originate
922 : */
923 0 : if (CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE))
924 0 : subgroup_default_withdraw_packet(subgrp);
925 0 : UNSET_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE);
926 :
927 : /* If default route is present in the local RIB, advertise the
928 : * route
929 : */
930 0 : if (dest) {
931 0 : for (pi = bgp_dest_get_bgp_path_info(dest); pi;
932 0 : pi = pi->next) {
933 0 : if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
934 0 : if (subgroup_announce_check(
935 : dest, pi, subgrp,
936 : bgp_dest_get_prefix(dest),
937 : &attr, NULL))
938 0 : bgp_adj_out_set_subgroup(
939 : dest, subgrp, &attr,
940 : pi);
941 : }
942 0 : bgp_dest_unlock_node(dest);
943 : }
944 : } else {
945 0 : if (!CHECK_FLAG(subgrp->sflags,
946 : SUBGRP_STATUS_DEFAULT_ORIGINATE)) {
947 :
948 : /* The 'neighbor x.x.x.x default-originate' default will
949 : * act as an
950 : * implicit withdraw for any previous UPDATEs sent for
951 : * 0.0.0.0/0 so
952 : * clear adj_out for the 0.0.0.0/0 prefix in the BGP
953 : * table.
954 : */
955 0 : if (dest) {
956 : /* Remove the adjacency for the previously
957 : * advertised default route
958 : */
959 0 : adj = adj_lookup(
960 : dest, subgrp,
961 : BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE);
962 0 : if (adj != NULL) {
963 : /* Clean up previous advertisement. */
964 0 : if (adj->adv)
965 0 : bgp_advertise_clean_subgroup(
966 : subgrp, adj);
967 :
968 : /* Free allocated information. */
969 0 : adj_free(adj);
970 : }
971 0 : bgp_dest_unlock_node(dest);
972 : }
973 :
974 : /* Advertise the default route */
975 0 : if (bgp_in_graceful_shutdown(bgp))
976 0 : bgp_attr_add_gshut_community(new_attr);
977 :
978 0 : SET_FLAG(subgrp->sflags,
979 : SUBGRP_STATUS_DEFAULT_ORIGINATE);
980 0 : subgroup_default_update_packet(subgrp, new_attr, from);
981 : }
982 : }
983 :
984 0 : aspath_unintern(&attr.aspath);
985 : }
986 :
987 : /*
988 : * Announce the BGP table to a subgroup.
989 : *
990 : * At startup, we try to optimize route announcement by coalescing the
991 : * peer-up events. This is done only the first time - from then on,
992 : * subgrp->v_coalesce will be set to zero and the normal logic
993 : * prevails.
994 : */
995 2 : void subgroup_announce_all(struct update_subgroup *subgrp)
996 : {
997 2 : if (!subgrp)
998 : return;
999 :
1000 : /*
1001 : * If coalesce timer value is not set, announce routes immediately.
1002 : */
1003 2 : if (!subgrp->v_coalesce) {
1004 0 : if (bgp_debug_update(NULL, NULL, subgrp->update_group, 0))
1005 0 : zlog_debug("u%" PRIu64 ":s%" PRIu64" announcing all routes",
1006 : subgrp->update_group->id, subgrp->id);
1007 0 : subgroup_announce_route(subgrp);
1008 0 : return;
1009 : }
1010 :
1011 : /*
1012 : * We should wait for the coalesce timer. Arm the timer if not done.
1013 : */
1014 2 : if (!subgrp->t_coalesce) {
1015 1 : thread_add_timer_msec(bm->master, subgroup_coalesce_timer,
1016 : subgrp, subgrp->v_coalesce,
1017 : &subgrp->t_coalesce);
1018 : }
1019 : }
1020 :
1021 : /*
1022 : * Go through all update subgroups and set up the adv queue for the
1023 : * input route.
1024 : */
1025 0 : void group_announce_route(struct bgp *bgp, afi_t afi, safi_t safi,
1026 : struct bgp_dest *dest, struct bgp_path_info *pi)
1027 : {
1028 0 : struct updwalk_context ctx;
1029 0 : ctx.pi = pi;
1030 0 : ctx.dest = dest;
1031 :
1032 : /* If suppress fib is enabled, the route will be advertised when
1033 : * FIB status is received
1034 : */
1035 0 : if (!bgp_check_advertise(bgp, dest))
1036 0 : return;
1037 :
1038 0 : update_group_af_walk(bgp, afi, safi, group_announce_route_walkcb, &ctx);
1039 : }
1040 :
1041 0 : void update_group_show_adj_queue(struct bgp *bgp, afi_t afi, safi_t safi,
1042 : struct vty *vty, uint64_t id)
1043 : {
1044 0 : updgrp_show_adj(bgp, afi, safi, vty, id, UPDWALK_FLAGS_ADVQUEUE);
1045 0 : }
1046 :
1047 0 : void update_group_show_advertised(struct bgp *bgp, afi_t afi, safi_t safi,
1048 : struct vty *vty, uint64_t id)
1049 : {
1050 0 : updgrp_show_adj(bgp, afi, safi, vty, id, UPDWALK_FLAGS_ADVERTISED);
1051 0 : }
1052 :
1053 0 : void update_group_announce(struct bgp *bgp)
1054 : {
1055 0 : update_group_walk(bgp, update_group_announce_walkcb, NULL);
1056 0 : }
1057 :
1058 0 : void update_group_announce_rrclients(struct bgp *bgp)
1059 : {
1060 0 : update_group_walk(bgp, update_group_announce_rrc_walkcb, NULL);
1061 0 : }
|