]> git.proxmox.com Git - mirror_frr.git/blob - bgpd/bgp_route.c
bgpd: Figure out rpki validation state earlier
[mirror_frr.git] / bgpd / bgp_route.c
1 /* BGP routing information
2 * Copyright (C) 1996, 97, 98, 99 Kunihiro Ishiguro
3 * Copyright (C) 2016 Job Snijders <job@instituut.net>
4 *
5 * This file is part of GNU Zebra.
6 *
7 * GNU Zebra is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
10 * later version.
11 *
12 * GNU Zebra is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; see the file COPYING; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22 #include <zebra.h>
23 #include <math.h>
24
25 #include "printfrr.h"
26 #include "prefix.h"
27 #include "linklist.h"
28 #include "memory.h"
29 #include "command.h"
30 #include "stream.h"
31 #include "filter.h"
32 #include "log.h"
33 #include "routemap.h"
34 #include "buffer.h"
35 #include "sockunion.h"
36 #include "plist.h"
37 #include "thread.h"
38 #include "workqueue.h"
39 #include "queue.h"
40 #include "memory.h"
41 #include "srv6.h"
42 #include "lib/json.h"
43 #include "lib_errors.h"
44 #include "zclient.h"
45 #include "bgpd/bgpd.h"
46 #include "bgpd/bgp_table.h"
47 #include "bgpd/bgp_route.h"
48 #include "bgpd/bgp_attr.h"
49 #include "bgpd/bgp_debug.h"
50 #include "bgpd/bgp_errors.h"
51 #include "bgpd/bgp_aspath.h"
52 #include "bgpd/bgp_regex.h"
53 #include "bgpd/bgp_community.h"
54 #include "bgpd/bgp_ecommunity.h"
55 #include "bgpd/bgp_lcommunity.h"
56 #include "bgpd/bgp_clist.h"
57 #include "bgpd/bgp_packet.h"
58 #include "bgpd/bgp_filter.h"
59 #include "bgpd/bgp_fsm.h"
60 #include "bgpd/bgp_mplsvpn.h"
61 #include "bgpd/bgp_nexthop.h"
62 #include "bgpd/bgp_damp.h"
63 #include "bgpd/bgp_advertise.h"
64 #include "bgpd/bgp_zebra.h"
65 #include "bgpd/bgp_vty.h"
66 #include "bgpd/bgp_mpath.h"
67 #include "bgpd/bgp_nht.h"
68 #include "bgpd/bgp_updgrp.h"
69 #include "bgpd/bgp_label.h"
70 #include "bgpd/bgp_addpath.h"
71 #include "bgpd/bgp_mac.h"
72 #include "bgpd/bgp_network.h"
73 #include "bgpd/bgp_trace.h"
74 #include "bgpd/bgp_rpki.h"
75
76 #ifdef ENABLE_BGP_VNC
77 #include "bgpd/rfapi/rfapi_backend.h"
78 #include "bgpd/rfapi/vnc_import_bgp.h"
79 #include "bgpd/rfapi/vnc_export_bgp.h"
80 #endif
81 #include "bgpd/bgp_encap_types.h"
82 #include "bgpd/bgp_encap_tlv.h"
83 #include "bgpd/bgp_evpn.h"
84 #include "bgpd/bgp_evpn_mh.h"
85 #include "bgpd/bgp_evpn_vty.h"
86 #include "bgpd/bgp_flowspec.h"
87 #include "bgpd/bgp_flowspec_util.h"
88 #include "bgpd/bgp_pbr.h"
89 #include "northbound.h"
90 #include "northbound_cli.h"
91 #include "bgpd/bgp_nb.h"
92
93 #ifndef VTYSH_EXTRACT_PL
94 #include "bgpd/bgp_route_clippy.c"
95 #endif
96
97 DEFINE_HOOK(bgp_snmp_update_stats,
98 (struct bgp_node *rn, struct bgp_path_info *pi, bool added),
99 (rn, pi, added));
100
101 DEFINE_HOOK(bgp_rpki_prefix_status,
102 (struct peer *peer, struct attr *attr,
103 const struct prefix *prefix),
104 (peer, attr, prefix));
105
106 /* Extern from bgp_dump.c */
107 extern const char *bgp_origin_str[];
108 extern const char *bgp_origin_long_str[];
109
110 /* PMSI strings. */
111 #define PMSI_TNLTYPE_STR_NO_INFO "No info"
112 #define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
113 static const struct message bgp_pmsi_tnltype_str[] = {
114 {PMSI_TNLTYPE_NO_INFO, PMSI_TNLTYPE_STR_NO_INFO},
115 {PMSI_TNLTYPE_RSVP_TE_P2MP, "RSVP-TE P2MP"},
116 {PMSI_TNLTYPE_MLDP_P2MP, "mLDP P2MP"},
117 {PMSI_TNLTYPE_PIM_SSM, "PIM-SSM"},
118 {PMSI_TNLTYPE_PIM_SM, "PIM-SM"},
119 {PMSI_TNLTYPE_PIM_BIDIR, "PIM-BIDIR"},
120 {PMSI_TNLTYPE_INGR_REPL, "Ingress Replication"},
121 {PMSI_TNLTYPE_MLDP_MP2MP, "mLDP MP2MP"},
122 {0}
123 };
124
125 #define VRFID_NONE_STR "-"
126
127 DEFINE_HOOK(bgp_process,
128 (struct bgp * bgp, afi_t afi, safi_t safi, struct bgp_dest *bn,
129 struct peer *peer, bool withdraw),
130 (bgp, afi, safi, bn, peer, withdraw));
131
132 /** Test if path is suppressed. */
133 static bool bgp_path_suppressed(struct bgp_path_info *pi)
134 {
135 if (pi->extra == NULL || pi->extra->aggr_suppressors == NULL)
136 return false;
137
138 return listcount(pi->extra->aggr_suppressors) > 0;
139 }
140
141 struct bgp_dest *bgp_afi_node_get(struct bgp_table *table, afi_t afi,
142 safi_t safi, const struct prefix *p,
143 struct prefix_rd *prd)
144 {
145 struct bgp_dest *dest;
146 struct bgp_dest *pdest = NULL;
147
148 assert(table);
149
150 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
151 || (safi == SAFI_EVPN)) {
152 pdest = bgp_node_get(table, (struct prefix *)prd);
153
154 if (!bgp_dest_has_bgp_path_info_data(pdest))
155 bgp_dest_set_bgp_table_info(
156 pdest, bgp_table_init(table->bgp, afi, safi));
157 else
158 bgp_dest_unlock_node(pdest);
159 table = bgp_dest_get_bgp_table_info(pdest);
160 }
161
162 dest = bgp_node_get(table, p);
163
164 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
165 || (safi == SAFI_EVPN))
166 dest->pdest = pdest;
167
168 return dest;
169 }
170
171 struct bgp_dest *bgp_afi_node_lookup(struct bgp_table *table, afi_t afi,
172 safi_t safi, const struct prefix *p,
173 struct prefix_rd *prd)
174 {
175 struct bgp_dest *dest;
176 struct bgp_dest *pdest = NULL;
177
178 if (!table)
179 return NULL;
180
181 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
182 || (safi == SAFI_EVPN)) {
183 pdest = bgp_node_lookup(table, (struct prefix *)prd);
184 if (!pdest)
185 return NULL;
186
187 if (!bgp_dest_has_bgp_path_info_data(pdest)) {
188 bgp_dest_unlock_node(pdest);
189 return NULL;
190 }
191
192 table = bgp_dest_get_bgp_table_info(pdest);
193 }
194
195 dest = bgp_node_lookup(table, p);
196
197 return dest;
198 }
199
200 /* Allocate bgp_path_info_extra */
201 static struct bgp_path_info_extra *bgp_path_info_extra_new(void)
202 {
203 struct bgp_path_info_extra *new;
204 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA,
205 sizeof(struct bgp_path_info_extra));
206 new->label[0] = MPLS_INVALID_LABEL;
207 new->num_labels = 0;
208 new->bgp_fs_pbr = NULL;
209 new->bgp_fs_iprule = NULL;
210 return new;
211 }
212
213 void bgp_path_info_extra_free(struct bgp_path_info_extra **extra)
214 {
215 struct bgp_path_info_extra *e;
216
217 if (!extra || !*extra)
218 return;
219
220 e = *extra;
221
222 e->damp_info = NULL;
223 if (e->parent) {
224 struct bgp_path_info *bpi = (struct bgp_path_info *)e->parent;
225
226 if (bpi->net) {
227 /* FIXME: since multiple e may have the same e->parent
228 * and e->parent->net is holding a refcount for each
229 * of them, we need to do some fudging here.
230 *
231 * WARNING: if bpi->net->lock drops to 0, bpi may be
232 * freed as well (because bpi->net was holding the
233 * last reference to bpi) => write after free!
234 */
235 unsigned refcount;
236
237 bpi = bgp_path_info_lock(bpi);
238 refcount = bgp_dest_get_lock_count(bpi->net) - 1;
239 bgp_dest_unlock_node((struct bgp_dest *)bpi->net);
240 if (!refcount)
241 bpi->net = NULL;
242 bgp_path_info_unlock(bpi);
243 }
244 bgp_path_info_unlock(e->parent);
245 e->parent = NULL;
246 }
247
248 if (e->bgp_orig)
249 bgp_unlock(e->bgp_orig);
250
251 if (e->aggr_suppressors)
252 list_delete(&e->aggr_suppressors);
253
254 if (e->mh_info)
255 bgp_evpn_path_mh_info_free(e->mh_info);
256
257 if ((*extra)->bgp_fs_iprule)
258 list_delete(&((*extra)->bgp_fs_iprule));
259 if ((*extra)->bgp_fs_pbr)
260 list_delete(&((*extra)->bgp_fs_pbr));
261 XFREE(MTYPE_BGP_ROUTE_EXTRA, *extra);
262 }
263
264 /* Get bgp_path_info extra information for the given bgp_path_info, lazy
265 * allocated if required.
266 */
267 struct bgp_path_info_extra *bgp_path_info_extra_get(struct bgp_path_info *pi)
268 {
269 if (!pi->extra)
270 pi->extra = bgp_path_info_extra_new();
271 return pi->extra;
272 }
273
274 /* Free bgp route information. */
275 static void bgp_path_info_free(struct bgp_path_info *path)
276 {
277 bgp_attr_unintern(&path->attr);
278
279 bgp_unlink_nexthop(path);
280 bgp_path_info_extra_free(&path->extra);
281 bgp_path_info_mpath_free(&path->mpath);
282 if (path->net)
283 bgp_addpath_free_info_data(&path->tx_addpath,
284 &path->net->tx_addpath);
285
286 peer_unlock(path->peer); /* bgp_path_info peer reference */
287
288 XFREE(MTYPE_BGP_ROUTE, path);
289 }
290
291 struct bgp_path_info *bgp_path_info_lock(struct bgp_path_info *path)
292 {
293 path->lock++;
294 return path;
295 }
296
297 struct bgp_path_info *bgp_path_info_unlock(struct bgp_path_info *path)
298 {
299 assert(path && path->lock > 0);
300 path->lock--;
301
302 if (path->lock == 0) {
303 #if 0
304 zlog_debug ("%s: unlocked and freeing", __func__);
305 zlog_backtrace (LOG_DEBUG);
306 #endif
307 bgp_path_info_free(path);
308 return NULL;
309 }
310
311 #if 0
312 if (path->lock == 1)
313 {
314 zlog_debug ("%s: unlocked to 1", __func__);
315 zlog_backtrace (LOG_DEBUG);
316 }
317 #endif
318
319 return path;
320 }
321
322 /* This function sets flag BGP_NODE_SELECT_DEFER based on condition */
323 static int bgp_dest_set_defer_flag(struct bgp_dest *dest, bool delete)
324 {
325 struct peer *peer;
326 struct bgp_path_info *old_pi, *nextpi;
327 bool set_flag = false;
328 struct bgp *bgp = NULL;
329 struct bgp_table *table = NULL;
330 afi_t afi = 0;
331 safi_t safi = 0;
332
333 /* If the flag BGP_NODE_SELECT_DEFER is set and new path is added
334 * then the route selection is deferred
335 */
336 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER) && (!delete))
337 return 0;
338
339 if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED)) {
340 if (BGP_DEBUG(update, UPDATE_OUT))
341 zlog_debug(
342 "Route %pBD is in workqueue and being processed, not deferred.",
343 dest);
344
345 return 0;
346 }
347
348 table = bgp_dest_table(dest);
349 if (table) {
350 bgp = table->bgp;
351 afi = table->afi;
352 safi = table->safi;
353 }
354
355 for (old_pi = bgp_dest_get_bgp_path_info(dest);
356 (old_pi != NULL) && (nextpi = old_pi->next, 1); old_pi = nextpi) {
357 if (CHECK_FLAG(old_pi->flags, BGP_PATH_SELECTED))
358 continue;
359
360 /* Route selection is deferred if there is a stale path which
361 * which indicates peer is in restart mode
362 */
363 if (CHECK_FLAG(old_pi->flags, BGP_PATH_STALE)
364 && (old_pi->sub_type == BGP_ROUTE_NORMAL)) {
365 set_flag = true;
366 } else {
367 /* If the peer is graceful restart capable and peer is
368 * restarting mode, set the flag BGP_NODE_SELECT_DEFER
369 */
370 peer = old_pi->peer;
371 if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer)
372 && BGP_PEER_RESTARTING_MODE(peer)
373 && (old_pi
374 && old_pi->sub_type == BGP_ROUTE_NORMAL)) {
375 set_flag = true;
376 }
377 }
378 if (set_flag)
379 break;
380 }
381
382 /* Set the flag BGP_NODE_SELECT_DEFER if route selection deferral timer
383 * is active
384 */
385 if (set_flag && table) {
386 if (bgp && (bgp->gr_info[afi][safi].t_select_deferral)) {
387 if (!CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER))
388 bgp->gr_info[afi][safi].gr_deferred++;
389 SET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
390 if (BGP_DEBUG(update, UPDATE_OUT))
391 zlog_debug("DEFER route %pBD, dest %p", dest,
392 dest);
393 return 0;
394 }
395 }
396 return -1;
397 }
398
399 void bgp_path_info_add(struct bgp_dest *dest, struct bgp_path_info *pi)
400 {
401 struct bgp_path_info *top;
402
403 top = bgp_dest_get_bgp_path_info(dest);
404
405 pi->next = top;
406 pi->prev = NULL;
407 if (top)
408 top->prev = pi;
409 bgp_dest_set_bgp_path_info(dest, pi);
410
411 bgp_path_info_lock(pi);
412 bgp_dest_lock_node(dest);
413 peer_lock(pi->peer); /* bgp_path_info peer reference */
414 bgp_dest_set_defer_flag(dest, false);
415 hook_call(bgp_snmp_update_stats, dest, pi, true);
416 }
417
418 /* Do the actual removal of info from RIB, for use by bgp_process
419 completion callback *only* */
420 void bgp_path_info_reap(struct bgp_dest *dest, struct bgp_path_info *pi)
421 {
422 if (pi->next)
423 pi->next->prev = pi->prev;
424 if (pi->prev)
425 pi->prev->next = pi->next;
426 else
427 bgp_dest_set_bgp_path_info(dest, pi->next);
428
429 bgp_path_info_mpath_dequeue(pi);
430 bgp_path_info_unlock(pi);
431 hook_call(bgp_snmp_update_stats, dest, pi, false);
432 bgp_dest_unlock_node(dest);
433 }
434
435 void bgp_path_info_delete(struct bgp_dest *dest, struct bgp_path_info *pi)
436 {
437 bgp_path_info_set_flag(dest, pi, BGP_PATH_REMOVED);
438 /* set of previous already took care of pcount */
439 UNSET_FLAG(pi->flags, BGP_PATH_VALID);
440 }
441
442 /* undo the effects of a previous call to bgp_path_info_delete; typically
443 called when a route is deleted and then quickly re-added before the
444 deletion has been processed */
445 void bgp_path_info_restore(struct bgp_dest *dest, struct bgp_path_info *pi)
446 {
447 bgp_path_info_unset_flag(dest, pi, BGP_PATH_REMOVED);
448 /* unset of previous already took care of pcount */
449 SET_FLAG(pi->flags, BGP_PATH_VALID);
450 }
451
452 /* Adjust pcount as required */
453 static void bgp_pcount_adjust(struct bgp_dest *dest, struct bgp_path_info *pi)
454 {
455 struct bgp_table *table;
456
457 assert(dest && bgp_dest_table(dest));
458 assert(pi && pi->peer && pi->peer->bgp);
459
460 table = bgp_dest_table(dest);
461
462 if (pi->peer == pi->peer->bgp->peer_self)
463 return;
464
465 if (!BGP_PATH_COUNTABLE(pi)
466 && CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
467
468 UNSET_FLAG(pi->flags, BGP_PATH_COUNTED);
469
470 /* slight hack, but more robust against errors. */
471 if (pi->peer->pcount[table->afi][table->safi])
472 pi->peer->pcount[table->afi][table->safi]--;
473 else
474 flog_err(EC_LIB_DEVELOPMENT,
475 "Asked to decrement 0 prefix count for peer");
476 } else if (BGP_PATH_COUNTABLE(pi)
477 && !CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
478 SET_FLAG(pi->flags, BGP_PATH_COUNTED);
479 pi->peer->pcount[table->afi][table->safi]++;
480 }
481 }
482
483 static int bgp_label_index_differs(struct bgp_path_info *pi1,
484 struct bgp_path_info *pi2)
485 {
486 return (!(pi1->attr->label_index == pi2->attr->label_index));
487 }
488
489 /* Set/unset bgp_path_info flags, adjusting any other state as needed.
490 * This is here primarily to keep prefix-count in check.
491 */
492 void bgp_path_info_set_flag(struct bgp_dest *dest, struct bgp_path_info *pi,
493 uint32_t flag)
494 {
495 SET_FLAG(pi->flags, flag);
496
497 /* early bath if we know it's not a flag that changes countability state
498 */
499 if (!CHECK_FLAG(flag,
500 BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
501 return;
502
503 bgp_pcount_adjust(dest, pi);
504 }
505
506 void bgp_path_info_unset_flag(struct bgp_dest *dest, struct bgp_path_info *pi,
507 uint32_t flag)
508 {
509 UNSET_FLAG(pi->flags, flag);
510
511 /* early bath if we know it's not a flag that changes countability state
512 */
513 if (!CHECK_FLAG(flag,
514 BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
515 return;
516
517 bgp_pcount_adjust(dest, pi);
518 }
519
520 /* Get MED value. If MED value is missing and "bgp bestpath
521 missing-as-worst" is specified, treat it as the worst value. */
522 static uint32_t bgp_med_value(struct attr *attr, struct bgp *bgp)
523 {
524 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
525 return attr->med;
526 else {
527 if (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_MISSING_AS_WORST))
528 return BGP_MED_MAX;
529 else
530 return 0;
531 }
532 }
533
534 void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info *pi, char *buf,
535 size_t buf_len)
536 {
537 if (pi->addpath_rx_id)
538 snprintf(buf, buf_len, "path %s (addpath rxid %d)",
539 pi->peer->host, pi->addpath_rx_id);
540 else
541 snprintf(buf, buf_len, "path %s", pi->peer->host);
542 }
543
544 /* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
545 */
546 static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
547 struct bgp_path_info *exist, int *paths_eq,
548 struct bgp_maxpaths_cfg *mpath_cfg, int debug,
549 char *pfx_buf, afi_t afi, safi_t safi,
550 enum bgp_path_selection_reason *reason)
551 {
552 struct attr *newattr, *existattr;
553 bgp_peer_sort_t new_sort;
554 bgp_peer_sort_t exist_sort;
555 uint32_t new_pref;
556 uint32_t exist_pref;
557 uint32_t new_med;
558 uint32_t exist_med;
559 uint32_t new_weight;
560 uint32_t exist_weight;
561 uint32_t newm, existm;
562 struct in_addr new_id;
563 struct in_addr exist_id;
564 int new_cluster;
565 int exist_cluster;
566 int internal_as_route;
567 int confed_as_route;
568 int ret = 0;
569 char new_buf[PATH_ADDPATH_STR_BUFFER];
570 char exist_buf[PATH_ADDPATH_STR_BUFFER];
571 uint32_t new_mm_seq;
572 uint32_t exist_mm_seq;
573 int nh_cmp;
574 esi_t *exist_esi;
575 esi_t *new_esi;
576 bool same_esi;
577 bool old_proxy;
578 bool new_proxy;
579 bool new_origin, exist_origin;
580
581 *paths_eq = 0;
582
583 /* 0. Null check. */
584 if (new == NULL) {
585 *reason = bgp_path_selection_none;
586 if (debug)
587 zlog_debug("%s: new is NULL", pfx_buf);
588 return 0;
589 }
590
591 if (debug)
592 bgp_path_info_path_with_addpath_rx_str(new, new_buf,
593 sizeof(new_buf));
594
595 if (exist == NULL) {
596 *reason = bgp_path_selection_first;
597 if (debug)
598 zlog_debug("%s: %s is the initial bestpath", pfx_buf,
599 new_buf);
600 return 1;
601 }
602
603 if (debug) {
604 bgp_path_info_path_with_addpath_rx_str(exist, exist_buf,
605 sizeof(exist_buf));
606 zlog_debug("%s: Comparing %s flags 0x%x with %s flags 0x%x",
607 pfx_buf, new_buf, new->flags, exist_buf,
608 exist->flags);
609 }
610
611 newattr = new->attr;
612 existattr = exist->attr;
613
614 /* For EVPN routes, we cannot just go by local vs remote, we have to
615 * look at the MAC mobility sequence number, if present.
616 */
617 if (safi == SAFI_EVPN) {
618 /* This is an error condition described in RFC 7432 Section
619 * 15.2. The RFC
620 * states that in this scenario "the PE MUST alert the operator"
621 * but it
622 * does not state what other action to take. In order to provide
623 * some
624 * consistency in this scenario we are going to prefer the path
625 * with the
626 * sticky flag.
627 */
628 if (newattr->sticky != existattr->sticky) {
629 if (!debug) {
630 prefix2str(
631 bgp_dest_get_prefix(new->net), pfx_buf,
632 sizeof(*pfx_buf) * PREFIX2STR_BUFFER);
633 bgp_path_info_path_with_addpath_rx_str(
634 new, new_buf, sizeof(new_buf));
635 bgp_path_info_path_with_addpath_rx_str(
636 exist, exist_buf, sizeof(exist_buf));
637 }
638
639 if (newattr->sticky && !existattr->sticky) {
640 *reason = bgp_path_selection_evpn_sticky_mac;
641 if (debug)
642 zlog_debug(
643 "%s: %s wins over %s due to sticky MAC flag",
644 pfx_buf, new_buf, exist_buf);
645 return 1;
646 }
647
648 if (!newattr->sticky && existattr->sticky) {
649 *reason = bgp_path_selection_evpn_sticky_mac;
650 if (debug)
651 zlog_debug(
652 "%s: %s loses to %s due to sticky MAC flag",
653 pfx_buf, new_buf, exist_buf);
654 return 0;
655 }
656 }
657
658 new_esi = bgp_evpn_attr_get_esi(newattr);
659 exist_esi = bgp_evpn_attr_get_esi(existattr);
660 if (bgp_evpn_is_esi_valid(new_esi) &&
661 !memcmp(new_esi, exist_esi, sizeof(esi_t))) {
662 same_esi = true;
663 } else {
664 same_esi = false;
665 }
666
667 /* If both paths have the same non-zero ES and
668 * one path is local it wins.
669 * PS: Note the local path wins even if the remote
670 * has the higher MM seq. The local path's
671 * MM seq will be fixed up to match the highest
672 * rem seq, subsequently.
673 */
674 if (same_esi) {
675 char esi_buf[ESI_STR_LEN];
676
677 if (bgp_evpn_is_path_local(bgp, new)) {
678 *reason = bgp_path_selection_evpn_local_path;
679 if (debug)
680 zlog_debug(
681 "%s: %s wins over %s as ES %s is same and local",
682 pfx_buf, new_buf, exist_buf,
683 esi_to_str(new_esi, esi_buf,
684 sizeof(esi_buf)));
685 return 1;
686 }
687 if (bgp_evpn_is_path_local(bgp, exist)) {
688 *reason = bgp_path_selection_evpn_local_path;
689 if (debug)
690 zlog_debug(
691 "%s: %s loses to %s as ES %s is same and local",
692 pfx_buf, new_buf, exist_buf,
693 esi_to_str(new_esi, esi_buf,
694 sizeof(esi_buf)));
695 return 0;
696 }
697 }
698
699 new_mm_seq = mac_mobility_seqnum(newattr);
700 exist_mm_seq = mac_mobility_seqnum(existattr);
701
702 if (new_mm_seq > exist_mm_seq) {
703 *reason = bgp_path_selection_evpn_seq;
704 if (debug)
705 zlog_debug(
706 "%s: %s wins over %s due to MM seq %u > %u",
707 pfx_buf, new_buf, exist_buf, new_mm_seq,
708 exist_mm_seq);
709 return 1;
710 }
711
712 if (new_mm_seq < exist_mm_seq) {
713 *reason = bgp_path_selection_evpn_seq;
714 if (debug)
715 zlog_debug(
716 "%s: %s loses to %s due to MM seq %u < %u",
717 pfx_buf, new_buf, exist_buf, new_mm_seq,
718 exist_mm_seq);
719 return 0;
720 }
721
722 /* if the sequence numbers and ESI are the same and one path
723 * is non-proxy it wins (over proxy)
724 */
725 new_proxy = bgp_evpn_attr_is_proxy(newattr);
726 old_proxy = bgp_evpn_attr_is_proxy(existattr);
727 if (same_esi && bgp_evpn_attr_is_local_es(newattr) &&
728 old_proxy != new_proxy) {
729 if (!new_proxy) {
730 *reason = bgp_path_selection_evpn_non_proxy;
731 if (debug)
732 zlog_debug(
733 "%s: %s wins over %s, same seq/es and non-proxy",
734 pfx_buf, new_buf, exist_buf);
735 return 1;
736 }
737
738 *reason = bgp_path_selection_evpn_non_proxy;
739 if (debug)
740 zlog_debug(
741 "%s: %s loses to %s, same seq/es and non-proxy",
742 pfx_buf, new_buf, exist_buf);
743 return 0;
744 }
745
746 /*
747 * if sequence numbers are the same path with the lowest IP
748 * wins
749 */
750 nh_cmp = bgp_path_info_nexthop_cmp(new, exist);
751 if (nh_cmp < 0) {
752 *reason = bgp_path_selection_evpn_lower_ip;
753 if (debug)
754 zlog_debug(
755 "%s: %s wins over %s due to same MM seq %u and lower IP %pI4",
756 pfx_buf, new_buf, exist_buf, new_mm_seq,
757 &new->attr->nexthop);
758 return 1;
759 }
760 if (nh_cmp > 0) {
761 *reason = bgp_path_selection_evpn_lower_ip;
762 if (debug)
763 zlog_debug(
764 "%s: %s loses to %s due to same MM seq %u and higher IP %pI4",
765 pfx_buf, new_buf, exist_buf, new_mm_seq,
766 &new->attr->nexthop);
767 return 0;
768 }
769 }
770
771 /* 1. Weight check. */
772 new_weight = newattr->weight;
773 exist_weight = existattr->weight;
774
775 if (new_weight > exist_weight) {
776 *reason = bgp_path_selection_weight;
777 if (debug)
778 zlog_debug("%s: %s wins over %s due to weight %d > %d",
779 pfx_buf, new_buf, exist_buf, new_weight,
780 exist_weight);
781 return 1;
782 }
783
784 if (new_weight < exist_weight) {
785 *reason = bgp_path_selection_weight;
786 if (debug)
787 zlog_debug("%s: %s loses to %s due to weight %d < %d",
788 pfx_buf, new_buf, exist_buf, new_weight,
789 exist_weight);
790 return 0;
791 }
792
793 /* 2. Local preference check. */
794 new_pref = exist_pref = bgp->default_local_pref;
795
796 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
797 new_pref = newattr->local_pref;
798 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
799 exist_pref = existattr->local_pref;
800
801 if (new_pref > exist_pref) {
802 *reason = bgp_path_selection_local_pref;
803 if (debug)
804 zlog_debug(
805 "%s: %s wins over %s due to localpref %d > %d",
806 pfx_buf, new_buf, exist_buf, new_pref,
807 exist_pref);
808 return 1;
809 }
810
811 if (new_pref < exist_pref) {
812 *reason = bgp_path_selection_local_pref;
813 if (debug)
814 zlog_debug(
815 "%s: %s loses to %s due to localpref %d < %d",
816 pfx_buf, new_buf, exist_buf, new_pref,
817 exist_pref);
818 return 0;
819 }
820
821 /* 3. Local route check. We prefer:
822 * - BGP_ROUTE_STATIC
823 * - BGP_ROUTE_AGGREGATE
824 * - BGP_ROUTE_REDISTRIBUTE
825 */
826 new_origin = !(new->sub_type == BGP_ROUTE_NORMAL ||
827 new->sub_type == BGP_ROUTE_IMPORTED);
828 exist_origin = !(exist->sub_type == BGP_ROUTE_NORMAL ||
829 exist->sub_type == BGP_ROUTE_IMPORTED);
830
831 if (new_origin && !exist_origin) {
832 *reason = bgp_path_selection_local_route;
833 if (debug)
834 zlog_debug(
835 "%s: %s wins over %s due to preferred BGP_ROUTE type",
836 pfx_buf, new_buf, exist_buf);
837 return 1;
838 }
839
840 if (!new_origin && exist_origin) {
841 *reason = bgp_path_selection_local_route;
842 if (debug)
843 zlog_debug(
844 "%s: %s loses to %s due to preferred BGP_ROUTE type",
845 pfx_buf, new_buf, exist_buf);
846 return 0;
847 }
848
849 /* 4. AS path length check. */
850 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_IGNORE)) {
851 int exist_hops = aspath_count_hops(existattr->aspath);
852 int exist_confeds = aspath_count_confeds(existattr->aspath);
853
854 if (CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_CONFED)) {
855 int aspath_hops;
856
857 aspath_hops = aspath_count_hops(newattr->aspath);
858 aspath_hops += aspath_count_confeds(newattr->aspath);
859
860 if (aspath_hops < (exist_hops + exist_confeds)) {
861 *reason = bgp_path_selection_confed_as_path;
862 if (debug)
863 zlog_debug(
864 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
865 pfx_buf, new_buf, exist_buf,
866 aspath_hops,
867 (exist_hops + exist_confeds));
868 return 1;
869 }
870
871 if (aspath_hops > (exist_hops + exist_confeds)) {
872 *reason = bgp_path_selection_confed_as_path;
873 if (debug)
874 zlog_debug(
875 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
876 pfx_buf, new_buf, exist_buf,
877 aspath_hops,
878 (exist_hops + exist_confeds));
879 return 0;
880 }
881 } else {
882 int newhops = aspath_count_hops(newattr->aspath);
883
884 if (newhops < exist_hops) {
885 *reason = bgp_path_selection_as_path;
886 if (debug)
887 zlog_debug(
888 "%s: %s wins over %s due to aspath hopcount %d < %d",
889 pfx_buf, new_buf, exist_buf,
890 newhops, exist_hops);
891 return 1;
892 }
893
894 if (newhops > exist_hops) {
895 *reason = bgp_path_selection_as_path;
896 if (debug)
897 zlog_debug(
898 "%s: %s loses to %s due to aspath hopcount %d > %d",
899 pfx_buf, new_buf, exist_buf,
900 newhops, exist_hops);
901 return 0;
902 }
903 }
904 }
905
906 /* 5. Origin check. */
907 if (newattr->origin < existattr->origin) {
908 *reason = bgp_path_selection_origin;
909 if (debug)
910 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
911 pfx_buf, new_buf, exist_buf,
912 bgp_origin_long_str[newattr->origin],
913 bgp_origin_long_str[existattr->origin]);
914 return 1;
915 }
916
917 if (newattr->origin > existattr->origin) {
918 *reason = bgp_path_selection_origin;
919 if (debug)
920 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
921 pfx_buf, new_buf, exist_buf,
922 bgp_origin_long_str[newattr->origin],
923 bgp_origin_long_str[existattr->origin]);
924 return 0;
925 }
926
927 /* 6. MED check. */
928 internal_as_route = (aspath_count_hops(newattr->aspath) == 0
929 && aspath_count_hops(existattr->aspath) == 0);
930 confed_as_route = (aspath_count_confeds(newattr->aspath) > 0
931 && aspath_count_confeds(existattr->aspath) > 0
932 && aspath_count_hops(newattr->aspath) == 0
933 && aspath_count_hops(existattr->aspath) == 0);
934
935 if (CHECK_FLAG(bgp->flags, BGP_FLAG_ALWAYS_COMPARE_MED)
936 || (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_CONFED) && confed_as_route)
937 || aspath_cmp_left(newattr->aspath, existattr->aspath)
938 || aspath_cmp_left_confed(newattr->aspath, existattr->aspath)
939 || internal_as_route) {
940 new_med = bgp_med_value(new->attr, bgp);
941 exist_med = bgp_med_value(exist->attr, bgp);
942
943 if (new_med < exist_med) {
944 *reason = bgp_path_selection_med;
945 if (debug)
946 zlog_debug(
947 "%s: %s wins over %s due to MED %d < %d",
948 pfx_buf, new_buf, exist_buf, new_med,
949 exist_med);
950 return 1;
951 }
952
953 if (new_med > exist_med) {
954 *reason = bgp_path_selection_med;
955 if (debug)
956 zlog_debug(
957 "%s: %s loses to %s due to MED %d > %d",
958 pfx_buf, new_buf, exist_buf, new_med,
959 exist_med);
960 return 0;
961 }
962 }
963
964 /* 7. Peer type check. */
965 new_sort = new->peer->sort;
966 exist_sort = exist->peer->sort;
967
968 if (new_sort == BGP_PEER_EBGP
969 && (exist_sort == BGP_PEER_IBGP || exist_sort == BGP_PEER_CONFED)) {
970 *reason = bgp_path_selection_peer;
971 if (debug)
972 zlog_debug(
973 "%s: %s wins over %s due to eBGP peer > iBGP peer",
974 pfx_buf, new_buf, exist_buf);
975 return 1;
976 }
977
978 if (exist_sort == BGP_PEER_EBGP
979 && (new_sort == BGP_PEER_IBGP || new_sort == BGP_PEER_CONFED)) {
980 *reason = bgp_path_selection_peer;
981 if (debug)
982 zlog_debug(
983 "%s: %s loses to %s due to iBGP peer < eBGP peer",
984 pfx_buf, new_buf, exist_buf);
985 return 0;
986 }
987
988 /* 8. IGP metric check. */
989 newm = existm = 0;
990
991 if (new->extra)
992 newm = new->extra->igpmetric;
993 if (exist->extra)
994 existm = exist->extra->igpmetric;
995
996 if (newm < existm) {
997 if (debug)
998 zlog_debug(
999 "%s: %s wins over %s due to IGP metric %u < %u",
1000 pfx_buf, new_buf, exist_buf, newm, existm);
1001 ret = 1;
1002 }
1003
1004 if (newm > existm) {
1005 if (debug)
1006 zlog_debug(
1007 "%s: %s loses to %s due to IGP metric %u > %u",
1008 pfx_buf, new_buf, exist_buf, newm, existm);
1009 ret = 0;
1010 }
1011
1012 /* 9. Same IGP metric. Compare the cluster list length as
1013 representative of IGP hops metric. Rewrite the metric value
1014 pair (newm, existm) with the cluster list length. Prefer the
1015 path with smaller cluster list length. */
1016 if (newm == existm) {
1017 if (peer_sort_lookup(new->peer) == BGP_PEER_IBGP
1018 && peer_sort_lookup(exist->peer) == BGP_PEER_IBGP
1019 && (mpath_cfg == NULL
1020 || CHECK_FLAG(
1021 mpath_cfg->ibgp_flags,
1022 BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN))) {
1023 newm = BGP_CLUSTER_LIST_LENGTH(new->attr);
1024 existm = BGP_CLUSTER_LIST_LENGTH(exist->attr);
1025
1026 if (newm < existm) {
1027 if (debug)
1028 zlog_debug(
1029 "%s: %s wins over %s due to CLUSTER_LIST length %u < %u",
1030 pfx_buf, new_buf, exist_buf,
1031 newm, existm);
1032 ret = 1;
1033 }
1034
1035 if (newm > existm) {
1036 if (debug)
1037 zlog_debug(
1038 "%s: %s loses to %s due to CLUSTER_LIST length %u > %u",
1039 pfx_buf, new_buf, exist_buf,
1040 newm, existm);
1041 ret = 0;
1042 }
1043 }
1044 }
1045
1046 /* 10. confed-external vs. confed-internal */
1047 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
1048 if (new_sort == BGP_PEER_CONFED
1049 && exist_sort == BGP_PEER_IBGP) {
1050 *reason = bgp_path_selection_confed;
1051 if (debug)
1052 zlog_debug(
1053 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
1054 pfx_buf, new_buf, exist_buf);
1055 return 1;
1056 }
1057
1058 if (exist_sort == BGP_PEER_CONFED
1059 && new_sort == BGP_PEER_IBGP) {
1060 *reason = bgp_path_selection_confed;
1061 if (debug)
1062 zlog_debug(
1063 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
1064 pfx_buf, new_buf, exist_buf);
1065 return 0;
1066 }
1067 }
1068
1069 /* 11. Maximum path check. */
1070 if (newm == existm) {
1071 /* If one path has a label but the other does not, do not treat
1072 * them as equals for multipath
1073 */
1074 if ((new->extra &&bgp_is_valid_label(&new->extra->label[0]))
1075 != (exist->extra
1076 && bgp_is_valid_label(&exist->extra->label[0]))) {
1077 if (debug)
1078 zlog_debug(
1079 "%s: %s and %s cannot be multipath, one has a label while the other does not",
1080 pfx_buf, new_buf, exist_buf);
1081 } else if (CHECK_FLAG(bgp->flags,
1082 BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
1083
1084 /*
1085 * For the two paths, all comparison steps till IGP
1086 * metric
1087 * have succeeded - including AS_PATH hop count. Since
1088 * 'bgp
1089 * bestpath as-path multipath-relax' knob is on, we
1090 * don't need
1091 * an exact match of AS_PATH. Thus, mark the paths are
1092 * equal.
1093 * That will trigger both these paths to get into the
1094 * multipath
1095 * array.
1096 */
1097 *paths_eq = 1;
1098
1099 if (debug)
1100 zlog_debug(
1101 "%s: %s and %s are equal via multipath-relax",
1102 pfx_buf, new_buf, exist_buf);
1103 } else if (new->peer->sort == BGP_PEER_IBGP) {
1104 if (aspath_cmp(new->attr->aspath,
1105 exist->attr->aspath)) {
1106 *paths_eq = 1;
1107
1108 if (debug)
1109 zlog_debug(
1110 "%s: %s and %s are equal via matching aspaths",
1111 pfx_buf, new_buf, exist_buf);
1112 }
1113 } else if (new->peer->as == exist->peer->as) {
1114 *paths_eq = 1;
1115
1116 if (debug)
1117 zlog_debug(
1118 "%s: %s and %s are equal via same remote-as",
1119 pfx_buf, new_buf, exist_buf);
1120 }
1121 } else {
1122 /*
1123 * TODO: If unequal cost ibgp multipath is enabled we can
1124 * mark the paths as equal here instead of returning
1125 */
1126 if (debug) {
1127 if (ret == 1)
1128 zlog_debug(
1129 "%s: %s wins over %s after IGP metric comparison",
1130 pfx_buf, new_buf, exist_buf);
1131 else
1132 zlog_debug(
1133 "%s: %s loses to %s after IGP metric comparison",
1134 pfx_buf, new_buf, exist_buf);
1135 }
1136 *reason = bgp_path_selection_igp_metric;
1137 return ret;
1138 }
1139
1140 /* 12. If both paths are external, prefer the path that was received
1141 first (the oldest one). This step minimizes route-flap, since a
1142 newer path won't displace an older one, even if it was the
1143 preferred route based on the additional decision criteria below. */
1144 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_COMPARE_ROUTER_ID)
1145 && new_sort == BGP_PEER_EBGP && exist_sort == BGP_PEER_EBGP) {
1146 if (CHECK_FLAG(new->flags, BGP_PATH_SELECTED)) {
1147 *reason = bgp_path_selection_older;
1148 if (debug)
1149 zlog_debug(
1150 "%s: %s wins over %s due to oldest external",
1151 pfx_buf, new_buf, exist_buf);
1152 return 1;
1153 }
1154
1155 if (CHECK_FLAG(exist->flags, BGP_PATH_SELECTED)) {
1156 *reason = bgp_path_selection_older;
1157 if (debug)
1158 zlog_debug(
1159 "%s: %s loses to %s due to oldest external",
1160 pfx_buf, new_buf, exist_buf);
1161 return 0;
1162 }
1163 }
1164
1165 /* 13. Router-ID comparision. */
1166 /* If one of the paths is "stale", the corresponding peer router-id will
1167 * be 0 and would always win over the other path. If originator id is
1168 * used for the comparision, it will decide which path is better.
1169 */
1170 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1171 new_id.s_addr = newattr->originator_id.s_addr;
1172 else
1173 new_id.s_addr = new->peer->remote_id.s_addr;
1174 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1175 exist_id.s_addr = existattr->originator_id.s_addr;
1176 else
1177 exist_id.s_addr = exist->peer->remote_id.s_addr;
1178
1179 if (ntohl(new_id.s_addr) < ntohl(exist_id.s_addr)) {
1180 *reason = bgp_path_selection_router_id;
1181 if (debug)
1182 zlog_debug(
1183 "%s: %s wins over %s due to Router-ID comparison",
1184 pfx_buf, new_buf, exist_buf);
1185 return 1;
1186 }
1187
1188 if (ntohl(new_id.s_addr) > ntohl(exist_id.s_addr)) {
1189 *reason = bgp_path_selection_router_id;
1190 if (debug)
1191 zlog_debug(
1192 "%s: %s loses to %s due to Router-ID comparison",
1193 pfx_buf, new_buf, exist_buf);
1194 return 0;
1195 }
1196
1197 /* 14. Cluster length comparision. */
1198 new_cluster = BGP_CLUSTER_LIST_LENGTH(new->attr);
1199 exist_cluster = BGP_CLUSTER_LIST_LENGTH(exist->attr);
1200
1201 if (new_cluster < exist_cluster) {
1202 *reason = bgp_path_selection_cluster_length;
1203 if (debug)
1204 zlog_debug(
1205 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1206 pfx_buf, new_buf, exist_buf, new_cluster,
1207 exist_cluster);
1208 return 1;
1209 }
1210
1211 if (new_cluster > exist_cluster) {
1212 *reason = bgp_path_selection_cluster_length;
1213 if (debug)
1214 zlog_debug(
1215 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1216 pfx_buf, new_buf, exist_buf, new_cluster,
1217 exist_cluster);
1218 return 0;
1219 }
1220
1221 /* 15. Neighbor address comparision. */
1222 /* Do this only if neither path is "stale" as stale paths do not have
1223 * valid peer information (as the connection may or may not be up).
1224 */
1225 if (CHECK_FLAG(exist->flags, BGP_PATH_STALE)) {
1226 *reason = bgp_path_selection_stale;
1227 if (debug)
1228 zlog_debug(
1229 "%s: %s wins over %s due to latter path being STALE",
1230 pfx_buf, new_buf, exist_buf);
1231 return 1;
1232 }
1233
1234 if (CHECK_FLAG(new->flags, BGP_PATH_STALE)) {
1235 *reason = bgp_path_selection_stale;
1236 if (debug)
1237 zlog_debug(
1238 "%s: %s loses to %s due to former path being STALE",
1239 pfx_buf, new_buf, exist_buf);
1240 return 0;
1241 }
1242
1243 /* locally configured routes to advertise do not have su_remote */
1244 if (new->peer->su_remote == NULL) {
1245 *reason = bgp_path_selection_local_configured;
1246 return 0;
1247 }
1248 if (exist->peer->su_remote == NULL) {
1249 *reason = bgp_path_selection_local_configured;
1250 return 1;
1251 }
1252
1253 ret = sockunion_cmp(new->peer->su_remote, exist->peer->su_remote);
1254
1255 if (ret == 1) {
1256 *reason = bgp_path_selection_neighbor_ip;
1257 if (debug)
1258 zlog_debug(
1259 "%s: %s loses to %s due to Neighor IP comparison",
1260 pfx_buf, new_buf, exist_buf);
1261 return 0;
1262 }
1263
1264 if (ret == -1) {
1265 *reason = bgp_path_selection_neighbor_ip;
1266 if (debug)
1267 zlog_debug(
1268 "%s: %s wins over %s due to Neighor IP comparison",
1269 pfx_buf, new_buf, exist_buf);
1270 return 1;
1271 }
1272
1273 *reason = bgp_path_selection_default;
1274 if (debug)
1275 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1276 pfx_buf, new_buf, exist_buf);
1277
1278 return 1;
1279 }
1280
1281
1282 int bgp_evpn_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
1283 struct bgp_path_info *exist, int *paths_eq)
1284 {
1285 enum bgp_path_selection_reason reason;
1286 char pfx_buf[PREFIX2STR_BUFFER];
1287
1288 return bgp_path_info_cmp(bgp, new, exist, paths_eq, NULL, 0, pfx_buf,
1289 AFI_L2VPN, SAFI_EVPN, &reason);
1290 }
1291
1292 /* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1293 * is preferred, or 0 if they are the same (usually will only occur if
1294 * multipath is enabled
1295 * This version is compatible with */
1296 int bgp_path_info_cmp_compatible(struct bgp *bgp, struct bgp_path_info *new,
1297 struct bgp_path_info *exist, char *pfx_buf,
1298 afi_t afi, safi_t safi,
1299 enum bgp_path_selection_reason *reason)
1300 {
1301 int paths_eq;
1302 int ret;
1303 ret = bgp_path_info_cmp(bgp, new, exist, &paths_eq, NULL, 0, pfx_buf,
1304 afi, safi, reason);
1305
1306 if (paths_eq)
1307 ret = 0;
1308 else {
1309 if (ret == 1)
1310 ret = -1;
1311 else
1312 ret = 1;
1313 }
1314 return ret;
1315 }
1316
1317 static enum filter_type bgp_input_filter(struct peer *peer,
1318 const struct prefix *p,
1319 struct attr *attr, afi_t afi,
1320 safi_t safi)
1321 {
1322 struct bgp_filter *filter;
1323 enum filter_type ret = FILTER_PERMIT;
1324
1325 filter = &peer->filter[afi][safi];
1326
1327 #define FILTER_EXIST_WARN(F, f, filter) \
1328 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
1329 zlog_debug("%s: Could not find configured input %s-list %s!", \
1330 peer->host, #f, F##_IN_NAME(filter));
1331
1332 if (DISTRIBUTE_IN_NAME(filter)) {
1333 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
1334
1335 if (access_list_apply(DISTRIBUTE_IN(filter), p)
1336 == FILTER_DENY) {
1337 ret = FILTER_DENY;
1338 goto done;
1339 }
1340 }
1341
1342 if (PREFIX_LIST_IN_NAME(filter)) {
1343 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
1344
1345 if (prefix_list_apply(PREFIX_LIST_IN(filter), p)
1346 == PREFIX_DENY) {
1347 ret = FILTER_DENY;
1348 goto done;
1349 }
1350 }
1351
1352 if (FILTER_LIST_IN_NAME(filter)) {
1353 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
1354
1355 if (as_list_apply(FILTER_LIST_IN(filter), attr->aspath)
1356 == AS_FILTER_DENY) {
1357 ret = FILTER_DENY;
1358 goto done;
1359 }
1360 }
1361
1362 done:
1363 if (frrtrace_enabled(frr_bgp, input_filter)) {
1364 char pfxprint[PREFIX2STR_BUFFER];
1365
1366 prefix2str(p, pfxprint, sizeof(pfxprint));
1367 frrtrace(5, frr_bgp, input_filter, peer, pfxprint, afi, safi,
1368 ret == FILTER_PERMIT ? "permit" : "deny");
1369 }
1370
1371 return ret;
1372 #undef FILTER_EXIST_WARN
1373 }
1374
1375 static enum filter_type bgp_output_filter(struct peer *peer,
1376 const struct prefix *p,
1377 struct attr *attr, afi_t afi,
1378 safi_t safi)
1379 {
1380 struct bgp_filter *filter;
1381 enum filter_type ret = FILTER_PERMIT;
1382
1383 filter = &peer->filter[afi][safi];
1384
1385 #define FILTER_EXIST_WARN(F, f, filter) \
1386 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
1387 zlog_debug("%s: Could not find configured output %s-list %s!", \
1388 peer->host, #f, F##_OUT_NAME(filter));
1389
1390 if (DISTRIBUTE_OUT_NAME(filter)) {
1391 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
1392
1393 if (access_list_apply(DISTRIBUTE_OUT(filter), p)
1394 == FILTER_DENY) {
1395 ret = FILTER_DENY;
1396 goto done;
1397 }
1398 }
1399
1400 if (PREFIX_LIST_OUT_NAME(filter)) {
1401 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
1402
1403 if (prefix_list_apply(PREFIX_LIST_OUT(filter), p)
1404 == PREFIX_DENY) {
1405 ret = FILTER_DENY;
1406 goto done;
1407 }
1408 }
1409
1410 if (FILTER_LIST_OUT_NAME(filter)) {
1411 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
1412
1413 if (as_list_apply(FILTER_LIST_OUT(filter), attr->aspath)
1414 == AS_FILTER_DENY) {
1415 ret = FILTER_DENY;
1416 goto done;
1417 }
1418 }
1419
1420 if (frrtrace_enabled(frr_bgp, output_filter)) {
1421 char pfxprint[PREFIX2STR_BUFFER];
1422
1423 prefix2str(p, pfxprint, sizeof(pfxprint));
1424 frrtrace(5, frr_bgp, output_filter, peer, pfxprint, afi, safi,
1425 ret == FILTER_PERMIT ? "permit" : "deny");
1426 }
1427
1428 done:
1429 return ret;
1430 #undef FILTER_EXIST_WARN
1431 }
1432
1433 /* If community attribute includes no_export then return 1. */
1434 static bool bgp_community_filter(struct peer *peer, struct attr *attr)
1435 {
1436 if (attr->community) {
1437 /* NO_ADVERTISE check. */
1438 if (community_include(attr->community, COMMUNITY_NO_ADVERTISE))
1439 return true;
1440
1441 /* NO_EXPORT check. */
1442 if (peer->sort == BGP_PEER_EBGP
1443 && community_include(attr->community, COMMUNITY_NO_EXPORT))
1444 return true;
1445
1446 /* NO_EXPORT_SUBCONFED check. */
1447 if (peer->sort == BGP_PEER_EBGP
1448 || peer->sort == BGP_PEER_CONFED)
1449 if (community_include(attr->community,
1450 COMMUNITY_NO_EXPORT_SUBCONFED))
1451 return true;
1452 }
1453 return false;
1454 }
1455
1456 /* Route reflection loop check. */
1457 static bool bgp_cluster_filter(struct peer *peer, struct attr *attr)
1458 {
1459 struct in_addr cluster_id;
1460 struct cluster_list *cluster = bgp_attr_get_cluster(attr);
1461
1462 if (cluster) {
1463 if (peer->bgp->config & BGP_CONFIG_CLUSTER_ID)
1464 cluster_id = peer->bgp->cluster_id;
1465 else
1466 cluster_id = peer->bgp->router_id;
1467
1468 if (cluster_loop_check(cluster, cluster_id))
1469 return true;
1470 }
1471 return false;
1472 }
1473
1474 static int bgp_input_modifier(struct peer *peer, const struct prefix *p,
1475 struct attr *attr, afi_t afi, safi_t safi,
1476 const char *rmap_name, mpls_label_t *label,
1477 uint32_t num_labels, struct bgp_dest *dest)
1478 {
1479 struct bgp_filter *filter;
1480 struct bgp_path_info rmap_path = { 0 };
1481 struct bgp_path_info_extra extra = { 0 };
1482 route_map_result_t ret;
1483 struct route_map *rmap = NULL;
1484
1485 filter = &peer->filter[afi][safi];
1486
1487 /* Apply default weight value. */
1488 if (peer->weight[afi][safi])
1489 attr->weight = peer->weight[afi][safi];
1490
1491 if (rmap_name) {
1492 rmap = route_map_lookup_by_name(rmap_name);
1493
1494 if (rmap == NULL)
1495 return RMAP_DENY;
1496 } else {
1497 if (ROUTE_MAP_IN_NAME(filter)) {
1498 rmap = ROUTE_MAP_IN(filter);
1499
1500 if (rmap == NULL)
1501 return RMAP_DENY;
1502 }
1503 }
1504
1505 /* Route map apply. */
1506 if (rmap) {
1507 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
1508 /* Duplicate current value to new strucutre for modification. */
1509 rmap_path.peer = peer;
1510 rmap_path.attr = attr;
1511 rmap_path.extra = &extra;
1512 rmap_path.net = dest;
1513
1514 extra.num_labels = num_labels;
1515 if (label && num_labels && num_labels <= BGP_MAX_LABELS)
1516 memcpy(extra.label, label,
1517 num_labels * sizeof(mpls_label_t));
1518
1519 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN);
1520
1521 /* Apply BGP route map to the attribute. */
1522 ret = route_map_apply(rmap, p, &rmap_path);
1523
1524 peer->rmap_type = 0;
1525
1526 if (ret == RMAP_DENYMATCH)
1527 return RMAP_DENY;
1528 }
1529 return RMAP_PERMIT;
1530 }
1531
1532 static int bgp_output_modifier(struct peer *peer, const struct prefix *p,
1533 struct attr *attr, afi_t afi, safi_t safi,
1534 const char *rmap_name)
1535 {
1536 struct bgp_path_info rmap_path;
1537 route_map_result_t ret;
1538 struct route_map *rmap = NULL;
1539 uint8_t rmap_type;
1540
1541 /*
1542 * So if we get to this point and have no rmap_name
1543 * we want to just show the output as it currently
1544 * exists.
1545 */
1546 if (!rmap_name)
1547 return RMAP_PERMIT;
1548
1549 /* Apply default weight value. */
1550 if (peer->weight[afi][safi])
1551 attr->weight = peer->weight[afi][safi];
1552
1553 rmap = route_map_lookup_by_name(rmap_name);
1554
1555 /*
1556 * If we have a route map name and we do not find
1557 * the routemap that means we have an implicit
1558 * deny.
1559 */
1560 if (rmap == NULL)
1561 return RMAP_DENY;
1562
1563 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
1564 /* Route map apply. */
1565 /* Duplicate current value to new strucutre for modification. */
1566 rmap_path.peer = peer;
1567 rmap_path.attr = attr;
1568
1569 rmap_type = peer->rmap_type;
1570 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
1571
1572 /* Apply BGP route map to the attribute. */
1573 ret = route_map_apply(rmap, p, &rmap_path);
1574
1575 peer->rmap_type = rmap_type;
1576
1577 if (ret == RMAP_DENYMATCH)
1578 /*
1579 * caller has multiple error paths with bgp_attr_flush()
1580 */
1581 return RMAP_DENY;
1582
1583 return RMAP_PERMIT;
1584 }
1585
1586 /* If this is an EBGP peer with remove-private-AS */
1587 static void bgp_peer_remove_private_as(struct bgp *bgp, afi_t afi, safi_t safi,
1588 struct peer *peer, struct attr *attr)
1589 {
1590 if (peer->sort == BGP_PEER_EBGP
1591 && (peer_af_flag_check(peer, afi, safi,
1592 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1593 || peer_af_flag_check(peer, afi, safi,
1594 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)
1595 || peer_af_flag_check(peer, afi, safi,
1596 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)
1597 || peer_af_flag_check(peer, afi, safi,
1598 PEER_FLAG_REMOVE_PRIVATE_AS))) {
1599 // Take action on the entire aspath
1600 if (peer_af_flag_check(peer, afi, safi,
1601 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1602 || peer_af_flag_check(peer, afi, safi,
1603 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)) {
1604 if (peer_af_flag_check(
1605 peer, afi, safi,
1606 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE))
1607 attr->aspath = aspath_replace_private_asns(
1608 attr->aspath, bgp->as, peer->as);
1609
1610 // The entire aspath consists of private ASNs so create
1611 // an empty aspath
1612 else if (aspath_private_as_check(attr->aspath))
1613 attr->aspath = aspath_empty_get();
1614
1615 // There are some public and some private ASNs, remove
1616 // the private ASNs
1617 else
1618 attr->aspath = aspath_remove_private_asns(
1619 attr->aspath, peer->as);
1620 }
1621
1622 // 'all' was not specified so the entire aspath must be private
1623 // ASNs
1624 // for us to do anything
1625 else if (aspath_private_as_check(attr->aspath)) {
1626 if (peer_af_flag_check(
1627 peer, afi, safi,
1628 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE))
1629 attr->aspath = aspath_replace_private_asns(
1630 attr->aspath, bgp->as, peer->as);
1631 else
1632 attr->aspath = aspath_empty_get();
1633 }
1634 }
1635 }
1636
1637 /* If this is an EBGP peer with as-override */
1638 static void bgp_peer_as_override(struct bgp *bgp, afi_t afi, safi_t safi,
1639 struct peer *peer, struct attr *attr)
1640 {
1641 if (peer->sort == BGP_PEER_EBGP
1642 && peer_af_flag_check(peer, afi, safi, PEER_FLAG_AS_OVERRIDE)) {
1643 if (aspath_single_asn_check(attr->aspath, peer->as))
1644 attr->aspath = aspath_replace_specific_asn(
1645 attr->aspath, peer->as, bgp->as);
1646 }
1647 }
1648
1649 void bgp_attr_add_gshut_community(struct attr *attr)
1650 {
1651 struct community *old;
1652 struct community *new;
1653 struct community *merge;
1654 struct community *gshut;
1655
1656 old = attr->community;
1657 gshut = community_str2com("graceful-shutdown");
1658
1659 assert(gshut);
1660
1661 if (old) {
1662 merge = community_merge(community_dup(old), gshut);
1663
1664 if (old->refcnt == 0)
1665 community_free(&old);
1666
1667 new = community_uniq_sort(merge);
1668 community_free(&merge);
1669 } else {
1670 new = community_dup(gshut);
1671 }
1672
1673 community_free(&gshut);
1674 attr->community = new;
1675 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
1676
1677 /* When we add the graceful-shutdown community we must also
1678 * lower the local-preference */
1679 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1680 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
1681 }
1682
1683
1684 /* Notify BGP Conditional advertisement scanner process. */
1685 void bgp_notify_conditional_adv_scanner(struct update_subgroup *subgrp)
1686 {
1687 struct peer *temp_peer;
1688 struct peer *peer = SUBGRP_PEER(subgrp);
1689 struct listnode *temp_node, *temp_nnode = NULL;
1690 afi_t afi = SUBGRP_AFI(subgrp);
1691 safi_t safi = SUBGRP_SAFI(subgrp);
1692 struct bgp *bgp = SUBGRP_INST(subgrp);
1693 struct bgp_filter *filter = &peer->filter[afi][safi];
1694
1695 if (!ADVERTISE_MAP_NAME(filter))
1696 return;
1697
1698 for (ALL_LIST_ELEMENTS(bgp->peer, temp_node, temp_nnode, temp_peer)) {
1699 if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
1700 continue;
1701
1702 if (peer != temp_peer)
1703 continue;
1704
1705 temp_peer->advmap_table_change = true;
1706 break;
1707 }
1708 }
1709
1710
1711 void subgroup_announce_reset_nhop(uint8_t family, struct attr *attr)
1712 {
1713 if (family == AF_INET) {
1714 attr->nexthop.s_addr = INADDR_ANY;
1715 attr->mp_nexthop_global_in.s_addr = INADDR_ANY;
1716 }
1717 if (family == AF_INET6)
1718 memset(&attr->mp_nexthop_global, 0, IPV6_MAX_BYTELEN);
1719 if (family == AF_EVPN)
1720 memset(&attr->mp_nexthop_global_in, 0, BGP_ATTR_NHLEN_IPV4);
1721 }
1722
1723 bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
1724 struct update_subgroup *subgrp,
1725 const struct prefix *p, struct attr *attr,
1726 bool skip_rmap_check)
1727 {
1728 struct bgp_filter *filter;
1729 struct peer *from;
1730 struct peer *peer;
1731 struct peer *onlypeer;
1732 struct bgp *bgp;
1733 struct attr *piattr;
1734 route_map_result_t ret;
1735 int transparent;
1736 int reflect;
1737 afi_t afi;
1738 safi_t safi;
1739 int samepeer_safe = 0; /* for synthetic mplsvpns routes */
1740 bool nh_reset = false;
1741 uint64_t cum_bw;
1742
1743 if (DISABLE_BGP_ANNOUNCE)
1744 return false;
1745
1746 afi = SUBGRP_AFI(subgrp);
1747 safi = SUBGRP_SAFI(subgrp);
1748 peer = SUBGRP_PEER(subgrp);
1749 onlypeer = NULL;
1750 if (CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL))
1751 onlypeer = SUBGRP_PFIRST(subgrp)->peer;
1752
1753 from = pi->peer;
1754 filter = &peer->filter[afi][safi];
1755 bgp = SUBGRP_INST(subgrp);
1756 piattr = bgp_path_info_mpath_count(pi) ? bgp_path_info_mpath_attr(pi)
1757 : pi->attr;
1758
1759 #ifdef ENABLE_BGP_VNC
1760 if (((afi == AFI_IP) || (afi == AFI_IP6)) && (safi == SAFI_MPLS_VPN)
1761 && ((pi->type == ZEBRA_ROUTE_BGP_DIRECT)
1762 || (pi->type == ZEBRA_ROUTE_BGP_DIRECT_EXT))) {
1763
1764 /*
1765 * direct and direct_ext type routes originate internally even
1766 * though they can have peer pointers that reference other
1767 * systems
1768 */
1769 zlog_debug("%s: pfx %pFX bgp_direct->vpn route peer safe",
1770 __func__, p);
1771 samepeer_safe = 1;
1772 }
1773 #endif
1774
1775 if (((afi == AFI_IP) || (afi == AFI_IP6))
1776 && ((safi == SAFI_MPLS_VPN) || (safi == SAFI_UNICAST))
1777 && (pi->type == ZEBRA_ROUTE_BGP)
1778 && (pi->sub_type == BGP_ROUTE_IMPORTED)) {
1779
1780 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1781
1782 samepeer_safe = 1;
1783 }
1784
1785 /* With addpath we may be asked to TX all kinds of paths so make sure
1786 * pi is valid */
1787 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID)
1788 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)
1789 || CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
1790 return false;
1791 }
1792
1793 /* If this is not the bestpath then check to see if there is an enabled
1794 * addpath
1795 * feature that requires us to advertise it */
1796 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
1797 if (!bgp_addpath_tx_path(peer->addpath_type[afi][safi], pi)) {
1798 return false;
1799 }
1800 }
1801
1802 /* Aggregate-address suppress check. */
1803 if (bgp_path_suppressed(pi) && !UNSUPPRESS_MAP_NAME(filter))
1804 return false;
1805
1806 /*
1807 * If we are doing VRF 2 VRF leaking via the import
1808 * statement, we want to prevent the route going
1809 * off box as that the RT and RD created are localy
1810 * significant and globaly useless.
1811 */
1812 if (safi == SAFI_MPLS_VPN && pi->extra && pi->extra->num_labels
1813 && pi->extra->label[0] == BGP_PREVENT_VRF_2_VRF_LEAK)
1814 return false;
1815
1816 /* If it's labeled safi, make sure the route has a valid label. */
1817 if (safi == SAFI_LABELED_UNICAST) {
1818 mpls_label_t label = bgp_adv_label(dest, pi, peer, afi, safi);
1819 if (!bgp_is_valid_label(&label)) {
1820 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1821 zlog_debug("u%" PRIu64 ":s%" PRIu64
1822 " %pFX is filtered - no label (%p)",
1823 subgrp->update_group->id, subgrp->id,
1824 p, &label);
1825 return false;
1826 }
1827 }
1828
1829 /* Do not send back route to sender. */
1830 if (onlypeer && from == onlypeer) {
1831 return false;
1832 }
1833
1834 /* Do not send the default route in the BGP table if the neighbor is
1835 * configured for default-originate */
1836 if (CHECK_FLAG(peer->af_flags[afi][safi],
1837 PEER_FLAG_DEFAULT_ORIGINATE)) {
1838 if (p->family == AF_INET && p->u.prefix4.s_addr == INADDR_ANY)
1839 return false;
1840 else if (p->family == AF_INET6 && p->prefixlen == 0)
1841 return false;
1842 }
1843
1844 /* Transparency check. */
1845 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1846 && CHECK_FLAG(from->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1847 transparent = 1;
1848 else
1849 transparent = 0;
1850
1851 /* If community is not disabled check the no-export and local. */
1852 if (!transparent && bgp_community_filter(peer, piattr)) {
1853 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1854 zlog_debug("%s: community filter check fail for %pFX",
1855 __func__, p);
1856 return false;
1857 }
1858
1859 /* If the attribute has originator-id and it is same as remote
1860 peer's id. */
1861 if (onlypeer && piattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
1862 && (IPV4_ADDR_SAME(&onlypeer->remote_id, &piattr->originator_id))) {
1863 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1864 zlog_debug(
1865 "%s [Update:SEND] %pFX originator-id is same as remote router-id",
1866 onlypeer->host, p);
1867 return false;
1868 }
1869
1870 /* ORF prefix-list filter check */
1871 if (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV)
1872 && (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)
1873 || CHECK_FLAG(peer->af_cap[afi][safi],
1874 PEER_CAP_ORF_PREFIX_SM_OLD_RCV)))
1875 if (peer->orf_plist[afi][safi]) {
1876 if (prefix_list_apply(peer->orf_plist[afi][safi], p)
1877 == PREFIX_DENY) {
1878 if (bgp_debug_update(NULL, p,
1879 subgrp->update_group, 0))
1880 zlog_debug(
1881 "%s [Update:SEND] %pFX is filtered via ORF",
1882 peer->host, p);
1883 return false;
1884 }
1885 }
1886
1887 /* Output filter check. */
1888 if (bgp_output_filter(peer, p, piattr, afi, safi) == FILTER_DENY) {
1889 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1890 zlog_debug("%s [Update:SEND] %pFX is filtered",
1891 peer->host, p);
1892 return false;
1893 }
1894
1895 /* AS path loop check. */
1896 if (onlypeer && onlypeer->as_path_loop_detection
1897 && aspath_loop_check(piattr->aspath, onlypeer->as)) {
1898 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1899 zlog_debug(
1900 "%s [Update:SEND] suppress announcement to peer AS %u that is part of AS path.",
1901 onlypeer->host, onlypeer->as);
1902 return false;
1903 }
1904
1905 /* If we're a CONFED we need to loop check the CONFED ID too */
1906 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
1907 if (aspath_loop_check(piattr->aspath, bgp->confed_id)) {
1908 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1909 zlog_debug(
1910 "%s [Update:SEND] suppress announcement to peer AS %u is AS path.",
1911 peer->host, bgp->confed_id);
1912 return false;
1913 }
1914 }
1915
1916 /* Route-Reflect check. */
1917 if (from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
1918 reflect = 1;
1919 else
1920 reflect = 0;
1921
1922 /* IBGP reflection check. */
1923 if (reflect && !samepeer_safe) {
1924 /* A route from a Client peer. */
1925 if (CHECK_FLAG(from->af_flags[afi][safi],
1926 PEER_FLAG_REFLECTOR_CLIENT)) {
1927 /* Reflect to all the Non-Client peers and also to the
1928 Client peers other than the originator. Originator
1929 check
1930 is already done. So there is noting to do. */
1931 /* no bgp client-to-client reflection check. */
1932 if (CHECK_FLAG(bgp->flags,
1933 BGP_FLAG_NO_CLIENT_TO_CLIENT))
1934 if (CHECK_FLAG(peer->af_flags[afi][safi],
1935 PEER_FLAG_REFLECTOR_CLIENT))
1936 return false;
1937 } else {
1938 /* A route from a Non-client peer. Reflect to all other
1939 clients. */
1940 if (!CHECK_FLAG(peer->af_flags[afi][safi],
1941 PEER_FLAG_REFLECTOR_CLIENT))
1942 return false;
1943 }
1944 }
1945
1946 /* For modify attribute, copy it to temporary structure. */
1947 *attr = *piattr;
1948
1949 /* If local-preference is not set. */
1950 if ((peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED)
1951 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)))) {
1952 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1953 attr->local_pref = bgp->default_local_pref;
1954 }
1955
1956 /* If originator-id is not set and the route is to be reflected,
1957 set the originator id */
1958 if (reflect
1959 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)))) {
1960 IPV4_ADDR_COPY(&(attr->originator_id), &(from->remote_id));
1961 SET_FLAG(attr->flag, BGP_ATTR_ORIGINATOR_ID);
1962 }
1963
1964 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
1965 */
1966 if (peer->sort == BGP_PEER_EBGP
1967 && attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
1968 if (from != bgp->peer_self && !transparent
1969 && !CHECK_FLAG(peer->af_flags[afi][safi],
1970 PEER_FLAG_MED_UNCHANGED))
1971 attr->flag &=
1972 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC));
1973 }
1974
1975 /* Since the nexthop attribute can vary per peer, it is not explicitly
1976 * set
1977 * in announce check, only certain flags and length (or number of
1978 * nexthops
1979 * -- for IPv6/MP_REACH) are set here in order to guide the update
1980 * formation
1981 * code in setting the nexthop(s) on a per peer basis in
1982 * reformat_peer().
1983 * Typically, the source nexthop in the attribute is preserved but in
1984 * the
1985 * scenarios where we know it will always be overwritten, we reset the
1986 * nexthop to "0" in an attempt to achieve better Update packing. An
1987 * example of this is when a prefix from each of 2 IBGP peers needs to
1988 * be
1989 * announced to an EBGP peer (and they have the same attributes barring
1990 * their nexthop).
1991 */
1992 if (reflect)
1993 SET_FLAG(attr->rmap_change_flags, BATTR_REFLECTED);
1994
1995 #define NEXTHOP_IS_V6 \
1996 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
1997 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
1998 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
1999 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
2000
2001 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
2002 * if
2003 * the peer (group) is configured to receive link-local nexthop
2004 * unchanged
2005 * and it is available in the prefix OR we're not reflecting the route,
2006 * link-local nexthop address is valid and
2007 * the peer (group) to whom we're going to announce is on a shared
2008 * network
2009 * and this is either a self-originated route or the peer is EBGP.
2010 * By checking if nexthop LL address is valid we are sure that
2011 * we do not announce LL address as `::`.
2012 */
2013 if (NEXTHOP_IS_V6) {
2014 attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
2015 if ((CHECK_FLAG(peer->af_flags[afi][safi],
2016 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
2017 && IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_local))
2018 || (!reflect
2019 && IN6_IS_ADDR_LINKLOCAL(&peer->nexthop.v6_local)
2020 && peer->shared_network
2021 && (from == bgp->peer_self
2022 || peer->sort == BGP_PEER_EBGP))) {
2023 attr->mp_nexthop_len =
2024 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
2025 }
2026
2027 /* Clear off link-local nexthop in source, whenever it is not
2028 * needed to
2029 * ensure more prefixes share the same attribute for
2030 * announcement.
2031 */
2032 if (!(CHECK_FLAG(peer->af_flags[afi][safi],
2033 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)))
2034 memset(&attr->mp_nexthop_local, 0, IPV6_MAX_BYTELEN);
2035 }
2036
2037 bgp_peer_remove_private_as(bgp, afi, safi, peer, attr);
2038 bgp_peer_as_override(bgp, afi, safi, peer, attr);
2039
2040 /* Route map & unsuppress-map apply. */
2041 if (!skip_rmap_check
2042 && (ROUTE_MAP_OUT_NAME(filter) || bgp_path_suppressed(pi))) {
2043 struct bgp_path_info rmap_path = {0};
2044 struct bgp_path_info_extra dummy_rmap_path_extra = {0};
2045 struct attr dummy_attr = {0};
2046
2047 /* Fill temp path_info */
2048 prep_for_rmap_apply(&rmap_path, &dummy_rmap_path_extra, dest,
2049 pi, peer, attr);
2050
2051 /* don't confuse inbound and outbound setting */
2052 RESET_FLAG(attr->rmap_change_flags);
2053
2054 /*
2055 * The route reflector is not allowed to modify the attributes
2056 * of the reflected IBGP routes unless explicitly allowed.
2057 */
2058 if ((from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
2059 && !CHECK_FLAG(bgp->flags,
2060 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) {
2061 dummy_attr = *attr;
2062 rmap_path.attr = &dummy_attr;
2063 }
2064
2065 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
2066
2067 if (bgp_path_suppressed(pi))
2068 ret = route_map_apply(UNSUPPRESS_MAP(filter), p,
2069 &rmap_path);
2070 else
2071 ret = route_map_apply(ROUTE_MAP_OUT(filter), p,
2072 &rmap_path);
2073
2074 peer->rmap_type = 0;
2075
2076 if (ret == RMAP_DENYMATCH) {
2077 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2078 zlog_debug(
2079 "%s [Update:SEND] %pFX is filtered by route-map",
2080 peer->host, p);
2081
2082 bgp_attr_flush(attr);
2083 return false;
2084 }
2085 }
2086
2087 /* RFC 8212 to prevent route leaks.
2088 * This specification intends to improve this situation by requiring the
2089 * explicit configuration of both BGP Import and Export Policies for any
2090 * External BGP (EBGP) session such as customers, peers, or
2091 * confederation boundaries for all enabled address families. Through
2092 * codification of the aforementioned requirement, operators will
2093 * benefit from consistent behavior across different BGP
2094 * implementations.
2095 */
2096 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
2097 if (!bgp_outbound_policy_exists(peer, filter))
2098 return false;
2099
2100 /* draft-ietf-idr-deprecate-as-set-confed-set
2101 * Filter routes having AS_SET or AS_CONFED_SET in the path.
2102 * Eventually, This document (if approved) updates RFC 4271
2103 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
2104 * and obsoletes RFC 6472.
2105 */
2106 if (peer->bgp->reject_as_sets)
2107 if (aspath_check_as_sets(attr->aspath))
2108 return false;
2109
2110 /* Codification of AS 0 Processing */
2111 if (aspath_check_as_zero(attr->aspath))
2112 return false;
2113
2114 if (bgp_in_graceful_shutdown(bgp)) {
2115 if (peer->sort == BGP_PEER_IBGP
2116 || peer->sort == BGP_PEER_CONFED) {
2117 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
2118 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
2119 } else {
2120 bgp_attr_add_gshut_community(attr);
2121 }
2122 }
2123
2124 /* After route-map has been applied, we check to see if the nexthop to
2125 * be carried in the attribute (that is used for the announcement) can
2126 * be cleared off or not. We do this in all cases where we would be
2127 * setting the nexthop to "ourselves". For IPv6, we only need to
2128 * consider
2129 * the global nexthop here; the link-local nexthop would have been
2130 * cleared
2131 * already, and if not, it is required by the update formation code.
2132 * Also see earlier comments in this function.
2133 */
2134 /*
2135 * If route-map has performed some operation on the nexthop or the peer
2136 * configuration says to pass it unchanged, we cannot reset the nexthop
2137 * here, so only attempt to do it if these aren't true. Note that the
2138 * route-map handler itself might have cleared the nexthop, if for
2139 * example,
2140 * it is configured as 'peer-address'.
2141 */
2142 if (!bgp_rmap_nhop_changed(attr->rmap_change_flags,
2143 piattr->rmap_change_flags)
2144 && !transparent
2145 && !CHECK_FLAG(peer->af_flags[afi][safi],
2146 PEER_FLAG_NEXTHOP_UNCHANGED)) {
2147 /* We can reset the nexthop, if setting (or forcing) it to
2148 * 'self' */
2149 if (CHECK_FLAG(peer->af_flags[afi][safi],
2150 PEER_FLAG_NEXTHOP_SELF)
2151 || CHECK_FLAG(peer->af_flags[afi][safi],
2152 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
2153 if (!reflect
2154 || CHECK_FLAG(peer->af_flags[afi][safi],
2155 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
2156 subgroup_announce_reset_nhop(
2157 (peer_cap_enhe(peer, afi, safi)
2158 ? AF_INET6
2159 : p->family),
2160 attr);
2161 nh_reset = true;
2162 }
2163 } else if (peer->sort == BGP_PEER_EBGP) {
2164 /* Can also reset the nexthop if announcing to EBGP, but
2165 * only if
2166 * no peer in the subgroup is on a shared subnet.
2167 * Note: 3rd party nexthop currently implemented for
2168 * IPv4 only.
2169 */
2170 if ((p->family == AF_INET) &&
2171 (!bgp_subgrp_multiaccess_check_v4(
2172 piattr->nexthop,
2173 subgrp, from))) {
2174 subgroup_announce_reset_nhop(
2175 (peer_cap_enhe(peer, afi, safi)
2176 ? AF_INET6
2177 : p->family),
2178 attr);
2179 nh_reset = true;
2180 }
2181
2182 if ((p->family == AF_INET6) &&
2183 (!bgp_subgrp_multiaccess_check_v6(
2184 piattr->mp_nexthop_global,
2185 subgrp, from))) {
2186 subgroup_announce_reset_nhop(
2187 (peer_cap_enhe(peer, afi, safi)
2188 ? AF_INET6
2189 : p->family),
2190 attr);
2191 nh_reset = true;
2192 }
2193
2194
2195
2196 } else if (CHECK_FLAG(pi->flags, BGP_PATH_ANNC_NH_SELF)) {
2197 /*
2198 * This flag is used for leaked vpn-vrf routes
2199 */
2200 int family = p->family;
2201
2202 if (peer_cap_enhe(peer, afi, safi))
2203 family = AF_INET6;
2204
2205 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2206 zlog_debug(
2207 "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
2208 __func__, family2str(family));
2209 subgroup_announce_reset_nhop(family, attr);
2210 nh_reset = true;
2211 }
2212 }
2213
2214 /* If IPv6/MP and nexthop does not have any override and happens
2215 * to
2216 * be a link-local address, reset it so that we don't pass along
2217 * the
2218 * source's link-local IPv6 address to recipients who may not be
2219 * on
2220 * the same interface.
2221 */
2222 if (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi)) {
2223 if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global)) {
2224 subgroup_announce_reset_nhop(AF_INET6, attr);
2225 nh_reset = true;
2226 }
2227 }
2228
2229 /*
2230 * When the next hop is set to ourselves, if all multipaths have
2231 * link-bandwidth announce the cumulative bandwidth as that makes
2232 * the most sense. However, don't modify if the link-bandwidth has
2233 * been explicitly set by user policy.
2234 */
2235 if (nh_reset &&
2236 bgp_path_info_mpath_chkwtd(bgp, pi) &&
2237 (cum_bw = bgp_path_info_mpath_cumbw(pi)) != 0 &&
2238 !CHECK_FLAG(attr->rmap_change_flags, BATTR_RMAP_LINK_BW_SET))
2239 attr->ecommunity = ecommunity_replace_linkbw(
2240 bgp->as, attr->ecommunity, cum_bw);
2241
2242 return true;
2243 }
2244
2245 static int bgp_route_select_timer_expire(struct thread *thread)
2246 {
2247 struct afi_safi_info *info;
2248 afi_t afi;
2249 safi_t safi;
2250 struct bgp *bgp;
2251
2252 info = THREAD_ARG(thread);
2253 afi = info->afi;
2254 safi = info->safi;
2255 bgp = info->bgp;
2256
2257 if (BGP_DEBUG(update, UPDATE_OUT))
2258 zlog_debug("afi %d, safi %d : route select timer expired", afi,
2259 safi);
2260
2261 bgp->gr_info[afi][safi].t_route_select = NULL;
2262
2263 XFREE(MTYPE_TMP, info);
2264
2265 /* Best path selection */
2266 return bgp_best_path_select_defer(bgp, afi, safi);
2267 }
2268
2269 void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
2270 struct bgp_maxpaths_cfg *mpath_cfg,
2271 struct bgp_path_info_pair *result, afi_t afi,
2272 safi_t safi)
2273 {
2274 struct bgp_path_info *new_select;
2275 struct bgp_path_info *old_select;
2276 struct bgp_path_info *pi;
2277 struct bgp_path_info *pi1;
2278 struct bgp_path_info *pi2;
2279 struct bgp_path_info *nextpi = NULL;
2280 int paths_eq, do_mpath, debug;
2281 struct list mp_list;
2282 char pfx_buf[PREFIX2STR_BUFFER];
2283 char path_buf[PATH_ADDPATH_STR_BUFFER];
2284
2285 bgp_mp_list_init(&mp_list);
2286 do_mpath =
2287 (mpath_cfg->maxpaths_ebgp > 1 || mpath_cfg->maxpaths_ibgp > 1);
2288
2289 debug = bgp_debug_bestpath(dest);
2290
2291 if (debug)
2292 prefix2str(bgp_dest_get_prefix(dest), pfx_buf, sizeof(pfx_buf));
2293
2294 dest->reason = bgp_path_selection_none;
2295 /* bgp deterministic-med */
2296 new_select = NULL;
2297 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)) {
2298
2299 /* Clear BGP_PATH_DMED_SELECTED for all paths */
2300 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
2301 pi1 = pi1->next)
2302 bgp_path_info_unset_flag(dest, pi1,
2303 BGP_PATH_DMED_SELECTED);
2304
2305 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
2306 pi1 = pi1->next) {
2307 if (CHECK_FLAG(pi1->flags, BGP_PATH_DMED_CHECK))
2308 continue;
2309 if (BGP_PATH_HOLDDOWN(pi1))
2310 continue;
2311 if (pi1->peer != bgp->peer_self)
2312 if (pi1->peer->status != Established)
2313 continue;
2314
2315 new_select = pi1;
2316 if (pi1->next) {
2317 for (pi2 = pi1->next; pi2; pi2 = pi2->next) {
2318 if (CHECK_FLAG(pi2->flags,
2319 BGP_PATH_DMED_CHECK))
2320 continue;
2321 if (BGP_PATH_HOLDDOWN(pi2))
2322 continue;
2323 if (pi2->peer != bgp->peer_self
2324 && !CHECK_FLAG(
2325 pi2->peer->sflags,
2326 PEER_STATUS_NSF_WAIT))
2327 if (pi2->peer->status
2328 != Established)
2329 continue;
2330
2331 if (!aspath_cmp_left(pi1->attr->aspath,
2332 pi2->attr->aspath)
2333 && !aspath_cmp_left_confed(
2334 pi1->attr->aspath,
2335 pi2->attr->aspath))
2336 continue;
2337
2338 if (bgp_path_info_cmp(
2339 bgp, pi2, new_select,
2340 &paths_eq, mpath_cfg, debug,
2341 pfx_buf, afi, safi,
2342 &dest->reason)) {
2343 bgp_path_info_unset_flag(
2344 dest, new_select,
2345 BGP_PATH_DMED_SELECTED);
2346 new_select = pi2;
2347 }
2348
2349 bgp_path_info_set_flag(
2350 dest, pi2, BGP_PATH_DMED_CHECK);
2351 }
2352 }
2353 bgp_path_info_set_flag(dest, new_select,
2354 BGP_PATH_DMED_CHECK);
2355 bgp_path_info_set_flag(dest, new_select,
2356 BGP_PATH_DMED_SELECTED);
2357
2358 if (debug) {
2359 bgp_path_info_path_with_addpath_rx_str(
2360 new_select, path_buf, sizeof(path_buf));
2361 zlog_debug(
2362 "%pBD: %s is the bestpath from AS %u",
2363 dest, path_buf,
2364 aspath_get_first_as(
2365 new_select->attr->aspath));
2366 }
2367 }
2368 }
2369
2370 /* Check old selected route and new selected route. */
2371 old_select = NULL;
2372 new_select = NULL;
2373 for (pi = bgp_dest_get_bgp_path_info(dest);
2374 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
2375 enum bgp_path_selection_reason reason;
2376
2377 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
2378 old_select = pi;
2379
2380 if (BGP_PATH_HOLDDOWN(pi)) {
2381 /* reap REMOVED routes, if needs be
2382 * selected route must stay for a while longer though
2383 */
2384 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
2385 && (pi != old_select))
2386 bgp_path_info_reap(dest, pi);
2387
2388 if (debug)
2389 zlog_debug("%s: pi %p in holddown", __func__,
2390 pi);
2391
2392 continue;
2393 }
2394
2395 if (pi->peer && pi->peer != bgp->peer_self
2396 && !CHECK_FLAG(pi->peer->sflags, PEER_STATUS_NSF_WAIT))
2397 if (pi->peer->status != Established) {
2398
2399 if (debug)
2400 zlog_debug(
2401 "%s: pi %p non self peer %s not estab state",
2402 __func__, pi, pi->peer->host);
2403
2404 continue;
2405 }
2406
2407 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)
2408 && (!CHECK_FLAG(pi->flags, BGP_PATH_DMED_SELECTED))) {
2409 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
2410 if (debug)
2411 zlog_debug("%s: pi %p dmed", __func__, pi);
2412 continue;
2413 }
2414
2415 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
2416
2417 reason = dest->reason;
2418 if (bgp_path_info_cmp(bgp, pi, new_select, &paths_eq, mpath_cfg,
2419 debug, pfx_buf, afi, safi,
2420 &dest->reason)) {
2421 if (new_select == NULL &&
2422 reason != bgp_path_selection_none)
2423 dest->reason = reason;
2424 new_select = pi;
2425 }
2426 }
2427
2428 /* Now that we know which path is the bestpath see if any of the other
2429 * paths
2430 * qualify as multipaths
2431 */
2432 if (debug) {
2433 if (new_select)
2434 bgp_path_info_path_with_addpath_rx_str(
2435 new_select, path_buf, sizeof(path_buf));
2436 else
2437 snprintf(path_buf, sizeof(path_buf), "NONE");
2438 zlog_debug(
2439 "%pBD: After path selection, newbest is %s oldbest was %s",
2440 dest, path_buf,
2441 old_select ? old_select->peer->host : "NONE");
2442 }
2443
2444 if (do_mpath && new_select) {
2445 for (pi = bgp_dest_get_bgp_path_info(dest);
2446 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
2447
2448 if (debug)
2449 bgp_path_info_path_with_addpath_rx_str(
2450 pi, path_buf, sizeof(path_buf));
2451
2452 if (pi == new_select) {
2453 if (debug)
2454 zlog_debug(
2455 "%pBD: %s is the bestpath, add to the multipath list",
2456 dest, path_buf);
2457 bgp_mp_list_add(&mp_list, pi);
2458 continue;
2459 }
2460
2461 if (BGP_PATH_HOLDDOWN(pi))
2462 continue;
2463
2464 if (pi->peer && pi->peer != bgp->peer_self
2465 && !CHECK_FLAG(pi->peer->sflags,
2466 PEER_STATUS_NSF_WAIT))
2467 if (pi->peer->status != Established)
2468 continue;
2469
2470 if (!bgp_path_info_nexthop_cmp(pi, new_select)) {
2471 if (debug)
2472 zlog_debug(
2473 "%pBD: %s has the same nexthop as the bestpath, skip it",
2474 dest, path_buf);
2475 continue;
2476 }
2477
2478 bgp_path_info_cmp(bgp, pi, new_select, &paths_eq,
2479 mpath_cfg, debug, pfx_buf, afi, safi,
2480 &dest->reason);
2481
2482 if (paths_eq) {
2483 if (debug)
2484 zlog_debug(
2485 "%pBD: %s is equivalent to the bestpath, add to the multipath list",
2486 dest, path_buf);
2487 bgp_mp_list_add(&mp_list, pi);
2488 }
2489 }
2490 }
2491
2492 bgp_path_info_mpath_update(dest, new_select, old_select, &mp_list,
2493 mpath_cfg);
2494 bgp_path_info_mpath_aggregate_update(new_select, old_select);
2495 bgp_mp_list_clear(&mp_list);
2496
2497 bgp_addpath_update_ids(bgp, dest, afi, safi);
2498
2499 result->old = old_select;
2500 result->new = new_select;
2501
2502 return;
2503 }
2504
2505 /*
2506 * A new route/change in bestpath of an existing route. Evaluate the path
2507 * for advertisement to the subgroup.
2508 */
2509 void subgroup_process_announce_selected(struct update_subgroup *subgrp,
2510 struct bgp_path_info *selected,
2511 struct bgp_dest *dest,
2512 uint32_t addpath_tx_id)
2513 {
2514 const struct prefix *p;
2515 struct peer *onlypeer;
2516 struct attr attr;
2517 afi_t afi;
2518 safi_t safi;
2519 struct bgp *bgp;
2520 bool advertise;
2521
2522 p = bgp_dest_get_prefix(dest);
2523 afi = SUBGRP_AFI(subgrp);
2524 safi = SUBGRP_SAFI(subgrp);
2525 bgp = SUBGRP_INST(subgrp);
2526 onlypeer = ((SUBGRP_PCOUNT(subgrp) == 1) ? (SUBGRP_PFIRST(subgrp))->peer
2527 : NULL);
2528
2529 if (BGP_DEBUG(update, UPDATE_OUT))
2530 zlog_debug("%s: p=%pFX, selected=%p", __func__, p, selected);
2531
2532 /* First update is deferred until ORF or ROUTE-REFRESH is received */
2533 if (onlypeer && CHECK_FLAG(onlypeer->af_sflags[afi][safi],
2534 PEER_STATUS_ORF_WAIT_REFRESH))
2535 return;
2536
2537 memset(&attr, 0, sizeof(struct attr));
2538 /* It's initialized in bgp_announce_check() */
2539
2540 /* Announcement to the subgroup. If the route is filtered withdraw it.
2541 * If BGP_NODE_FIB_INSTALL_PENDING is set and data plane install status
2542 * is pending (BGP_NODE_FIB_INSTALL_PENDING), do not advertise the
2543 * route
2544 */
2545 advertise = bgp_check_advertise(bgp, dest);
2546
2547 if (selected) {
2548 if (subgroup_announce_check(dest, selected, subgrp, p, &attr,
2549 false)) {
2550 /* Route is selected, if the route is already installed
2551 * in FIB, then it is advertised
2552 */
2553 if (advertise)
2554 bgp_adj_out_set_subgroup(dest, subgrp, &attr,
2555 selected);
2556 } else
2557 bgp_adj_out_unset_subgroup(dest, subgrp, 1,
2558 addpath_tx_id);
2559 }
2560
2561 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2562 else {
2563 bgp_adj_out_unset_subgroup(dest, subgrp, 1, addpath_tx_id);
2564 }
2565 }
2566
2567 /*
2568 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2569 * This is called at the end of route processing.
2570 */
2571 void bgp_zebra_clear_route_change_flags(struct bgp_dest *dest)
2572 {
2573 struct bgp_path_info *pi;
2574
2575 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
2576 if (BGP_PATH_HOLDDOWN(pi))
2577 continue;
2578 UNSET_FLAG(pi->flags, BGP_PATH_IGP_CHANGED);
2579 UNSET_FLAG(pi->flags, BGP_PATH_ATTR_CHANGED);
2580 }
2581 }
2582
2583 /*
2584 * Has the route changed from the RIB's perspective? This is invoked only
2585 * if the route selection returns the same best route as earlier - to
2586 * determine if we need to update zebra or not.
2587 */
2588 bool bgp_zebra_has_route_changed(struct bgp_path_info *selected)
2589 {
2590 struct bgp_path_info *mpinfo;
2591
2592 /* If this is multipath, check all selected paths for any nexthop
2593 * change or attribute change. Some attribute changes (e.g., community)
2594 * aren't of relevance to the RIB, but we'll update zebra to ensure
2595 * we handle the case of BGP nexthop change. This is the behavior
2596 * when the best path has an attribute change anyway.
2597 */
2598 if (CHECK_FLAG(selected->flags, BGP_PATH_IGP_CHANGED)
2599 || CHECK_FLAG(selected->flags, BGP_PATH_MULTIPATH_CHG)
2600 || CHECK_FLAG(selected->flags, BGP_PATH_LINK_BW_CHG))
2601 return true;
2602
2603 /*
2604 * If this is multipath, check all selected paths for any nexthop change
2605 */
2606 for (mpinfo = bgp_path_info_mpath_first(selected); mpinfo;
2607 mpinfo = bgp_path_info_mpath_next(mpinfo)) {
2608 if (CHECK_FLAG(mpinfo->flags, BGP_PATH_IGP_CHANGED)
2609 || CHECK_FLAG(mpinfo->flags, BGP_PATH_ATTR_CHANGED))
2610 return true;
2611 }
2612
2613 /* Nothing has changed from the RIB's perspective. */
2614 return false;
2615 }
2616
2617 struct bgp_process_queue {
2618 struct bgp *bgp;
2619 STAILQ_HEAD(, bgp_dest) pqueue;
2620 #define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2621 unsigned int flags;
2622 unsigned int queued;
2623 };
2624
2625 static void bgp_process_evpn_route_injection(struct bgp *bgp, afi_t afi,
2626 safi_t safi, struct bgp_dest *dest,
2627 struct bgp_path_info *new_select,
2628 struct bgp_path_info *old_select)
2629 {
2630 const struct prefix *p = bgp_dest_get_prefix(dest);
2631
2632 if ((afi != AFI_IP && afi != AFI_IP6) || (safi != SAFI_UNICAST))
2633 return;
2634
2635 if (advertise_type5_routes(bgp, afi) && new_select
2636 && is_route_injectable_into_evpn(new_select)) {
2637
2638 /* apply the route-map */
2639 if (bgp->adv_cmd_rmap[afi][safi].map) {
2640 route_map_result_t ret;
2641 struct bgp_path_info rmap_path;
2642 struct bgp_path_info_extra rmap_path_extra;
2643 struct attr dummy_attr;
2644
2645 dummy_attr = *new_select->attr;
2646
2647 /* Fill temp path_info */
2648 prep_for_rmap_apply(&rmap_path, &rmap_path_extra, dest,
2649 new_select, new_select->peer,
2650 &dummy_attr);
2651
2652 RESET_FLAG(dummy_attr.rmap_change_flags);
2653
2654 ret = route_map_apply(bgp->adv_cmd_rmap[afi][safi].map,
2655 p, &rmap_path);
2656
2657 if (ret == RMAP_DENYMATCH) {
2658 bgp_attr_flush(&dummy_attr);
2659 bgp_evpn_withdraw_type5_route(bgp, p, afi,
2660 safi);
2661 } else
2662 bgp_evpn_advertise_type5_route(
2663 bgp, p, &dummy_attr, afi, safi);
2664 } else {
2665 bgp_evpn_advertise_type5_route(bgp, p, new_select->attr,
2666 afi, safi);
2667 }
2668 } else if (advertise_type5_routes(bgp, afi) && old_select
2669 && is_route_injectable_into_evpn(old_select))
2670 bgp_evpn_withdraw_type5_route(bgp, p, afi, safi);
2671 }
2672
2673 /*
2674 * old_select = The old best path
2675 * new_select = the new best path
2676 *
2677 * if (!old_select && new_select)
2678 * We are sending new information on.
2679 *
2680 * if (old_select && new_select) {
2681 * if (new_select != old_select)
2682 * We have a new best path send a change
2683 * else
2684 * We've received a update with new attributes that needs
2685 * to be passed on.
2686 * }
2687 *
2688 * if (old_select && !new_select)
2689 * We have no eligible route that we can announce or the rn
2690 * is being removed.
2691 */
2692 static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
2693 afi_t afi, safi_t safi)
2694 {
2695 struct bgp_path_info *new_select;
2696 struct bgp_path_info *old_select;
2697 struct bgp_path_info_pair old_and_new;
2698 int debug = 0;
2699
2700 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)) {
2701 if (dest)
2702 debug = bgp_debug_bestpath(dest);
2703 if (debug)
2704 zlog_debug(
2705 "%s: bgp delete in progress, ignoring event, p=%pBD",
2706 __func__, dest);
2707 return;
2708 }
2709 /* Is it end of initial update? (after startup) */
2710 if (!dest) {
2711 quagga_timestamp(3, bgp->update_delay_zebra_resume_time,
2712 sizeof(bgp->update_delay_zebra_resume_time));
2713
2714 bgp->main_zebra_update_hold = 0;
2715 FOREACH_AFI_SAFI (afi, safi) {
2716 if (bgp_fibupd_safi(safi))
2717 bgp_zebra_announce_table(bgp, afi, safi);
2718 }
2719 bgp->main_peers_update_hold = 0;
2720
2721 bgp_start_routeadv(bgp);
2722 return;
2723 }
2724
2725 const struct prefix *p = bgp_dest_get_prefix(dest);
2726
2727 debug = bgp_debug_bestpath(dest);
2728 if (debug)
2729 zlog_debug("%s: p=%pBD afi=%s, safi=%s start", __func__, dest,
2730 afi2str(afi), safi2str(safi));
2731
2732 /* The best path calculation for the route is deferred if
2733 * BGP_NODE_SELECT_DEFER is set
2734 */
2735 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
2736 if (BGP_DEBUG(update, UPDATE_OUT))
2737 zlog_debug("SELECT_DEFER flag set for route %p", dest);
2738 return;
2739 }
2740
2741 /* Best path selection. */
2742 bgp_best_selection(bgp, dest, &bgp->maxpaths[afi][safi], &old_and_new,
2743 afi, safi);
2744 old_select = old_and_new.old;
2745 new_select = old_and_new.new;
2746
2747 /* Do we need to allocate or free labels?
2748 * Right now, since we only deal with per-prefix labels, it is not
2749 * necessary to do this upon changes to best path. Exceptions:
2750 * - label index has changed -> recalculate resulting label
2751 * - path_info sub_type changed -> switch to/from implicit-null
2752 * - no valid label (due to removed static label binding) -> get new one
2753 */
2754 if (bgp->allocate_mpls_labels[afi][safi]) {
2755 if (new_select) {
2756 if (!old_select
2757 || bgp_label_index_differs(new_select, old_select)
2758 || new_select->sub_type != old_select->sub_type
2759 || !bgp_is_valid_label(&dest->local_label)) {
2760 /* Enforced penultimate hop popping:
2761 * implicit-null for local routes, aggregate
2762 * and redistributed routes
2763 */
2764 if (new_select->sub_type == BGP_ROUTE_STATIC
2765 || new_select->sub_type
2766 == BGP_ROUTE_AGGREGATE
2767 || new_select->sub_type
2768 == BGP_ROUTE_REDISTRIBUTE) {
2769 if (CHECK_FLAG(
2770 dest->flags,
2771 BGP_NODE_REGISTERED_FOR_LABEL)
2772 || CHECK_FLAG(
2773 dest->flags,
2774 BGP_NODE_LABEL_REQUESTED))
2775 bgp_unregister_for_label(dest);
2776 label_ntop(MPLS_LABEL_IMPLICIT_NULL, 1,
2777 &dest->local_label);
2778 bgp_set_valid_label(&dest->local_label);
2779 } else
2780 bgp_register_for_label(dest,
2781 new_select);
2782 }
2783 } else if (CHECK_FLAG(dest->flags,
2784 BGP_NODE_REGISTERED_FOR_LABEL)
2785 || CHECK_FLAG(dest->flags,
2786 BGP_NODE_LABEL_REQUESTED)) {
2787 bgp_unregister_for_label(dest);
2788 }
2789 } else if (CHECK_FLAG(dest->flags, BGP_NODE_REGISTERED_FOR_LABEL)
2790 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_REQUESTED)) {
2791 bgp_unregister_for_label(dest);
2792 }
2793
2794 if (debug)
2795 zlog_debug(
2796 "%s: p=%pBD afi=%s, safi=%s, old_select=%p, new_select=%p",
2797 __func__, dest, afi2str(afi), safi2str(safi),
2798 old_select, new_select);
2799
2800 /* If best route remains the same and this is not due to user-initiated
2801 * clear, see exactly what needs to be done.
2802 */
2803 if (old_select && old_select == new_select
2804 && !CHECK_FLAG(dest->flags, BGP_NODE_USER_CLEAR)
2805 && !CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
2806 && !bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
2807 if (bgp_zebra_has_route_changed(old_select)) {
2808 #ifdef ENABLE_BGP_VNC
2809 vnc_import_bgp_add_route(bgp, p, old_select);
2810 vnc_import_bgp_exterior_add_route(bgp, p, old_select);
2811 #endif
2812 if (bgp_fibupd_safi(safi)
2813 && !bgp_option_check(BGP_OPT_NO_FIB)) {
2814
2815 if (new_select->type == ZEBRA_ROUTE_BGP
2816 && (new_select->sub_type == BGP_ROUTE_NORMAL
2817 || new_select->sub_type
2818 == BGP_ROUTE_IMPORTED))
2819
2820 bgp_zebra_announce(dest, p, old_select,
2821 bgp, afi, safi);
2822 }
2823 }
2824
2825 /* If there is a change of interest to peers, reannounce the
2826 * route. */
2827 if (CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
2828 || CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
2829 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED)) {
2830 group_announce_route(bgp, afi, safi, dest, new_select);
2831
2832 /* unicast routes must also be annouced to
2833 * labeled-unicast update-groups */
2834 if (safi == SAFI_UNICAST)
2835 group_announce_route(bgp, afi,
2836 SAFI_LABELED_UNICAST, dest,
2837 new_select);
2838
2839 UNSET_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED);
2840 UNSET_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED);
2841 }
2842
2843 /* advertise/withdraw type-5 routes */
2844 if (CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
2845 || CHECK_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG))
2846 bgp_process_evpn_route_injection(
2847 bgp, afi, safi, dest, old_select, old_select);
2848
2849 UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG);
2850 UNSET_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG);
2851 bgp_zebra_clear_route_change_flags(dest);
2852 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
2853 return;
2854 }
2855
2856 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2857 */
2858 UNSET_FLAG(dest->flags, BGP_NODE_USER_CLEAR);
2859
2860 /* bestpath has changed; bump version */
2861 if (old_select || new_select) {
2862 bgp_bump_version(dest);
2863
2864 if (!bgp->t_rmap_def_originate_eval) {
2865 bgp_lock(bgp);
2866 thread_add_timer(
2867 bm->master,
2868 update_group_refresh_default_originate_route_map,
2869 bgp, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER,
2870 &bgp->t_rmap_def_originate_eval);
2871 }
2872 }
2873
2874 if (old_select)
2875 bgp_path_info_unset_flag(dest, old_select, BGP_PATH_SELECTED);
2876 if (new_select) {
2877 if (debug)
2878 zlog_debug("%s: setting SELECTED flag", __func__);
2879 bgp_path_info_set_flag(dest, new_select, BGP_PATH_SELECTED);
2880 bgp_path_info_unset_flag(dest, new_select,
2881 BGP_PATH_ATTR_CHANGED);
2882 UNSET_FLAG(new_select->flags, BGP_PATH_MULTIPATH_CHG);
2883 UNSET_FLAG(new_select->flags, BGP_PATH_LINK_BW_CHG);
2884 }
2885
2886 #ifdef ENABLE_BGP_VNC
2887 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
2888 if (old_select != new_select) {
2889 if (old_select) {
2890 vnc_import_bgp_exterior_del_route(bgp, p,
2891 old_select);
2892 vnc_import_bgp_del_route(bgp, p, old_select);
2893 }
2894 if (new_select) {
2895 vnc_import_bgp_exterior_add_route(bgp, p,
2896 new_select);
2897 vnc_import_bgp_add_route(bgp, p, new_select);
2898 }
2899 }
2900 }
2901 #endif
2902
2903 group_announce_route(bgp, afi, safi, dest, new_select);
2904
2905 /* unicast routes must also be annouced to labeled-unicast update-groups
2906 */
2907 if (safi == SAFI_UNICAST)
2908 group_announce_route(bgp, afi, SAFI_LABELED_UNICAST, dest,
2909 new_select);
2910
2911 /* FIB update. */
2912 if (bgp_fibupd_safi(safi) && (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW)
2913 && !bgp_option_check(BGP_OPT_NO_FIB)) {
2914 if (new_select && new_select->type == ZEBRA_ROUTE_BGP
2915 && (new_select->sub_type == BGP_ROUTE_NORMAL
2916 || new_select->sub_type == BGP_ROUTE_AGGREGATE
2917 || new_select->sub_type == BGP_ROUTE_IMPORTED)) {
2918
2919 /* if this is an evpn imported type-5 prefix,
2920 * we need to withdraw the route first to clear
2921 * the nh neigh and the RMAC entry.
2922 */
2923 if (old_select &&
2924 is_route_parent_evpn(old_select))
2925 bgp_zebra_withdraw(p, old_select, bgp, safi);
2926
2927 bgp_zebra_announce(dest, p, new_select, bgp, afi, safi);
2928 } else {
2929 /* Withdraw the route from the kernel. */
2930 if (old_select && old_select->type == ZEBRA_ROUTE_BGP
2931 && (old_select->sub_type == BGP_ROUTE_NORMAL
2932 || old_select->sub_type == BGP_ROUTE_AGGREGATE
2933 || old_select->sub_type == BGP_ROUTE_IMPORTED))
2934
2935 bgp_zebra_withdraw(p, old_select, bgp, safi);
2936 }
2937 }
2938
2939 bgp_process_evpn_route_injection(bgp, afi, safi, dest, new_select,
2940 old_select);
2941
2942 /* Clear any route change flags. */
2943 bgp_zebra_clear_route_change_flags(dest);
2944
2945 /* Reap old select bgp_path_info, if it has been removed */
2946 if (old_select && CHECK_FLAG(old_select->flags, BGP_PATH_REMOVED))
2947 bgp_path_info_reap(dest, old_select);
2948
2949 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
2950 return;
2951 }
2952
2953 /* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
2954 int bgp_best_path_select_defer(struct bgp *bgp, afi_t afi, safi_t safi)
2955 {
2956 struct bgp_dest *dest;
2957 int cnt = 0;
2958 struct afi_safi_info *thread_info;
2959
2960 if (bgp->gr_info[afi][safi].t_route_select) {
2961 struct thread *t = bgp->gr_info[afi][safi].t_route_select;
2962
2963 thread_info = THREAD_ARG(t);
2964 XFREE(MTYPE_TMP, thread_info);
2965 BGP_TIMER_OFF(bgp->gr_info[afi][safi].t_route_select);
2966 }
2967
2968 if (BGP_DEBUG(update, UPDATE_OUT)) {
2969 zlog_debug("%s: processing route for %s : cnt %d", __func__,
2970 get_afi_safi_str(afi, safi, false),
2971 bgp->gr_info[afi][safi].gr_deferred);
2972 }
2973
2974 /* Process the route list */
2975 for (dest = bgp_table_top(bgp->rib[afi][safi]);
2976 dest && bgp->gr_info[afi][safi].gr_deferred != 0;
2977 dest = bgp_route_next(dest)) {
2978 if (!CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER))
2979 continue;
2980
2981 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
2982 bgp->gr_info[afi][safi].gr_deferred--;
2983 bgp_process_main_one(bgp, dest, afi, safi);
2984 cnt++;
2985 if (cnt >= BGP_MAX_BEST_ROUTE_SELECT) {
2986 bgp_dest_unlock_node(dest);
2987 break;
2988 }
2989 }
2990
2991 /* Send EOR message when all routes are processed */
2992 if (!bgp->gr_info[afi][safi].gr_deferred) {
2993 bgp_send_delayed_eor(bgp);
2994 /* Send route processing complete message to RIB */
2995 bgp_zebra_update(afi, safi, bgp->vrf_id,
2996 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE);
2997 return 0;
2998 }
2999
3000 thread_info = XMALLOC(MTYPE_TMP, sizeof(struct afi_safi_info));
3001
3002 thread_info->afi = afi;
3003 thread_info->safi = safi;
3004 thread_info->bgp = bgp;
3005
3006 /* If there are more routes to be processed, start the
3007 * selection timer
3008 */
3009 thread_add_timer(bm->master, bgp_route_select_timer_expire, thread_info,
3010 BGP_ROUTE_SELECT_DELAY,
3011 &bgp->gr_info[afi][safi].t_route_select);
3012 return 0;
3013 }
3014
3015 static wq_item_status bgp_process_wq(struct work_queue *wq, void *data)
3016 {
3017 struct bgp_process_queue *pqnode = data;
3018 struct bgp *bgp = pqnode->bgp;
3019 struct bgp_table *table;
3020 struct bgp_dest *dest;
3021
3022 /* eoiu marker */
3023 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)) {
3024 bgp_process_main_one(bgp, NULL, 0, 0);
3025 /* should always have dedicated wq call */
3026 assert(STAILQ_FIRST(&pqnode->pqueue) == NULL);
3027 return WQ_SUCCESS;
3028 }
3029
3030 while (!STAILQ_EMPTY(&pqnode->pqueue)) {
3031 dest = STAILQ_FIRST(&pqnode->pqueue);
3032 STAILQ_REMOVE_HEAD(&pqnode->pqueue, pq);
3033 STAILQ_NEXT(dest, pq) = NULL; /* complete unlink */
3034 table = bgp_dest_table(dest);
3035 /* note, new DESTs may be added as part of processing */
3036 bgp_process_main_one(bgp, dest, table->afi, table->safi);
3037
3038 bgp_dest_unlock_node(dest);
3039 bgp_table_unlock(table);
3040 }
3041
3042 return WQ_SUCCESS;
3043 }
3044
3045 static void bgp_processq_del(struct work_queue *wq, void *data)
3046 {
3047 struct bgp_process_queue *pqnode = data;
3048
3049 bgp_unlock(pqnode->bgp);
3050
3051 XFREE(MTYPE_BGP_PROCESS_QUEUE, pqnode);
3052 }
3053
3054 void bgp_process_queue_init(struct bgp *bgp)
3055 {
3056 if (!bgp->process_queue) {
3057 char name[BUFSIZ];
3058
3059 snprintf(name, BUFSIZ, "process_queue %s", bgp->name_pretty);
3060 bgp->process_queue = work_queue_new(bm->master, name);
3061 }
3062
3063 bgp->process_queue->spec.workfunc = &bgp_process_wq;
3064 bgp->process_queue->spec.del_item_data = &bgp_processq_del;
3065 bgp->process_queue->spec.max_retries = 0;
3066 bgp->process_queue->spec.hold = 50;
3067 /* Use a higher yield value of 50ms for main queue processing */
3068 bgp->process_queue->spec.yield = 50 * 1000L;
3069 }
3070
3071 static struct bgp_process_queue *bgp_processq_alloc(struct bgp *bgp)
3072 {
3073 struct bgp_process_queue *pqnode;
3074
3075 pqnode = XCALLOC(MTYPE_BGP_PROCESS_QUEUE,
3076 sizeof(struct bgp_process_queue));
3077
3078 /* unlocked in bgp_processq_del */
3079 pqnode->bgp = bgp_lock(bgp);
3080 STAILQ_INIT(&pqnode->pqueue);
3081
3082 return pqnode;
3083 }
3084
3085 void bgp_process(struct bgp *bgp, struct bgp_dest *dest, afi_t afi, safi_t safi)
3086 {
3087 #define ARBITRARY_PROCESS_QLEN 10000
3088 struct work_queue *wq = bgp->process_queue;
3089 struct bgp_process_queue *pqnode;
3090 int pqnode_reuse = 0;
3091
3092 /* already scheduled for processing? */
3093 if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED))
3094 return;
3095
3096 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
3097 * the workqueue
3098 */
3099 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
3100 if (BGP_DEBUG(update, UPDATE_OUT))
3101 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
3102 dest);
3103 return;
3104 }
3105
3106 if (wq == NULL)
3107 return;
3108
3109 /* Add route nodes to an existing work queue item until reaching the
3110 limit only if is from the same BGP view and it's not an EOIU marker
3111 */
3112 if (work_queue_item_count(wq)) {
3113 struct work_queue_item *item = work_queue_last_item(wq);
3114 pqnode = item->data;
3115
3116 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)
3117 || pqnode->bgp != bgp
3118 || pqnode->queued >= ARBITRARY_PROCESS_QLEN)
3119 pqnode = bgp_processq_alloc(bgp);
3120 else
3121 pqnode_reuse = 1;
3122 } else
3123 pqnode = bgp_processq_alloc(bgp);
3124 /* all unlocked in bgp_process_wq */
3125 bgp_table_lock(bgp_dest_table(dest));
3126
3127 SET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
3128 bgp_dest_lock_node(dest);
3129
3130 /* can't be enqueued twice */
3131 assert(STAILQ_NEXT(dest, pq) == NULL);
3132 STAILQ_INSERT_TAIL(&pqnode->pqueue, dest, pq);
3133 pqnode->queued++;
3134
3135 if (!pqnode_reuse)
3136 work_queue_add(wq, pqnode);
3137
3138 return;
3139 }
3140
3141 void bgp_add_eoiu_mark(struct bgp *bgp)
3142 {
3143 struct bgp_process_queue *pqnode;
3144
3145 if (bgp->process_queue == NULL)
3146 return;
3147
3148 pqnode = bgp_processq_alloc(bgp);
3149
3150 SET_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER);
3151 work_queue_add(bgp->process_queue, pqnode);
3152 }
3153
3154 static int bgp_maximum_prefix_restart_timer(struct thread *thread)
3155 {
3156 struct peer *peer;
3157
3158 peer = THREAD_ARG(thread);
3159 peer->t_pmax_restart = NULL;
3160
3161 if (bgp_debug_neighbor_events(peer))
3162 zlog_debug(
3163 "%s Maximum-prefix restart timer expired, restore peering",
3164 peer->host);
3165
3166 if ((peer_clear(peer, NULL) < 0) && bgp_debug_neighbor_events(peer))
3167 zlog_debug("%s: %s peer_clear failed", __func__, peer->host);
3168
3169 return 0;
3170 }
3171
3172 static uint32_t bgp_filtered_routes_count(struct peer *peer, afi_t afi,
3173 safi_t safi)
3174 {
3175 uint32_t count = 0;
3176 bool filtered = false;
3177 struct bgp_dest *dest;
3178 struct bgp_adj_in *ain;
3179 struct attr attr = {};
3180 struct bgp_table *table = peer->bgp->rib[afi][safi];
3181
3182 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
3183 for (ain = dest->adj_in; ain; ain = ain->next) {
3184 const struct prefix *rn_p = bgp_dest_get_prefix(dest);
3185
3186 attr = *ain->attr;
3187
3188 if (bgp_input_filter(peer, rn_p, &attr, afi, safi)
3189 == FILTER_DENY)
3190 filtered = true;
3191
3192 if (bgp_input_modifier(
3193 peer, rn_p, &attr, afi, safi,
3194 ROUTE_MAP_IN_NAME(&peer->filter[afi][safi]),
3195 NULL, 0, NULL)
3196 == RMAP_DENY)
3197 filtered = true;
3198
3199 if (filtered)
3200 count++;
3201
3202 bgp_attr_undup(&attr, ain->attr);
3203 }
3204 }
3205
3206 return count;
3207 }
3208
3209 bool bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi,
3210 int always)
3211 {
3212 iana_afi_t pkt_afi;
3213 iana_safi_t pkt_safi;
3214 uint32_t pcount = (CHECK_FLAG(peer->af_flags[afi][safi],
3215 PEER_FLAG_MAX_PREFIX_FORCE))
3216 ? bgp_filtered_routes_count(peer, afi, safi)
3217 + peer->pcount[afi][safi]
3218 : peer->pcount[afi][safi];
3219
3220 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
3221 return false;
3222
3223 if (pcount > peer->pmax[afi][safi]) {
3224 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3225 PEER_STATUS_PREFIX_LIMIT)
3226 && !always)
3227 return false;
3228
3229 zlog_info(
3230 "%%MAXPFXEXCEED: No. of %s prefix received from %s %u exceed, limit %u",
3231 get_afi_safi_str(afi, safi, false), peer->host, pcount,
3232 peer->pmax[afi][safi]);
3233 SET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT);
3234
3235 if (CHECK_FLAG(peer->af_flags[afi][safi],
3236 PEER_FLAG_MAX_PREFIX_WARNING))
3237 return false;
3238
3239 /* Convert AFI, SAFI to values for packet. */
3240 pkt_afi = afi_int2iana(afi);
3241 pkt_safi = safi_int2iana(safi);
3242 {
3243 uint8_t ndata[7];
3244
3245 ndata[0] = (pkt_afi >> 8);
3246 ndata[1] = pkt_afi;
3247 ndata[2] = pkt_safi;
3248 ndata[3] = (peer->pmax[afi][safi] >> 24);
3249 ndata[4] = (peer->pmax[afi][safi] >> 16);
3250 ndata[5] = (peer->pmax[afi][safi] >> 8);
3251 ndata[6] = (peer->pmax[afi][safi]);
3252
3253 SET_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
3254 bgp_notify_send_with_data(peer, BGP_NOTIFY_CEASE,
3255 BGP_NOTIFY_CEASE_MAX_PREFIX,
3256 ndata, 7);
3257 }
3258
3259 /* Dynamic peers will just close their connection. */
3260 if (peer_dynamic_neighbor(peer))
3261 return true;
3262
3263 /* restart timer start */
3264 if (peer->pmax_restart[afi][safi]) {
3265 peer->v_pmax_restart =
3266 peer->pmax_restart[afi][safi] * 60;
3267
3268 if (bgp_debug_neighbor_events(peer))
3269 zlog_debug(
3270 "%s Maximum-prefix restart timer started for %d secs",
3271 peer->host, peer->v_pmax_restart);
3272
3273 BGP_TIMER_ON(peer->t_pmax_restart,
3274 bgp_maximum_prefix_restart_timer,
3275 peer->v_pmax_restart);
3276 }
3277
3278 return true;
3279 } else
3280 UNSET_FLAG(peer->af_sflags[afi][safi],
3281 PEER_STATUS_PREFIX_LIMIT);
3282
3283 if (pcount
3284 > (peer->pmax[afi][safi] * peer->pmax_threshold[afi][safi] / 100)) {
3285 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3286 PEER_STATUS_PREFIX_THRESHOLD)
3287 && !always)
3288 return false;
3289
3290 zlog_info(
3291 "%%MAXPFX: No. of %s prefix received from %s reaches %u, max %u",
3292 get_afi_safi_str(afi, safi, false), peer->host, pcount,
3293 peer->pmax[afi][safi]);
3294 SET_FLAG(peer->af_sflags[afi][safi],
3295 PEER_STATUS_PREFIX_THRESHOLD);
3296 } else
3297 UNSET_FLAG(peer->af_sflags[afi][safi],
3298 PEER_STATUS_PREFIX_THRESHOLD);
3299 return false;
3300 }
3301
3302 /* Unconditionally remove the route from the RIB, without taking
3303 * damping into consideration (eg, because the session went down)
3304 */
3305 void bgp_rib_remove(struct bgp_dest *dest, struct bgp_path_info *pi,
3306 struct peer *peer, afi_t afi, safi_t safi)
3307 {
3308
3309 struct bgp *bgp = NULL;
3310 bool delete_route = false;
3311
3312 bgp_aggregate_decrement(peer->bgp, bgp_dest_get_prefix(dest), pi, afi,
3313 safi);
3314
3315 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
3316 bgp_path_info_delete(dest, pi); /* keep historical info */
3317
3318 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3319 * flag
3320 */
3321 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3322 delete_route = true;
3323 else if (bgp_dest_set_defer_flag(dest, true) < 0)
3324 delete_route = true;
3325 if (delete_route) {
3326 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
3327 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
3328 bgp = pi->peer->bgp;
3329 bgp->gr_info[afi][safi].gr_deferred--;
3330 }
3331 }
3332 }
3333
3334 hook_call(bgp_process, peer->bgp, afi, safi, dest, peer, true);
3335 bgp_process(peer->bgp, dest, afi, safi);
3336 }
3337
3338 static void bgp_rib_withdraw(struct bgp_dest *dest, struct bgp_path_info *pi,
3339 struct peer *peer, afi_t afi, safi_t safi,
3340 struct prefix_rd *prd)
3341 {
3342 const struct prefix *p = bgp_dest_get_prefix(dest);
3343
3344 /* apply dampening, if result is suppressed, we'll be retaining
3345 * the bgp_path_info in the RIB for historical reference.
3346 */
3347 if (peer->sort == BGP_PEER_EBGP) {
3348 if (get_active_bdc_from_pi(pi, afi, safi)) {
3349 if (bgp_damp_withdraw(pi, dest, afi, safi, 0)
3350 == BGP_DAMP_SUPPRESSED) {
3351 bgp_aggregate_decrement(peer->bgp, p, pi, afi,
3352 safi);
3353 return;
3354 }
3355 }
3356 }
3357
3358 #ifdef ENABLE_BGP_VNC
3359 if (safi == SAFI_MPLS_VPN) {
3360 struct bgp_dest *pdest = NULL;
3361 struct bgp_table *table = NULL;
3362
3363 pdest = bgp_node_get(peer->bgp->rib[afi][safi],
3364 (struct prefix *)prd);
3365 if (bgp_dest_has_bgp_path_info_data(pdest)) {
3366 table = bgp_dest_get_bgp_table_info(pdest);
3367
3368 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3369 peer->bgp, prd, table, p, pi);
3370 }
3371 bgp_dest_unlock_node(pdest);
3372 }
3373 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
3374 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
3375
3376 vnc_import_bgp_del_route(peer->bgp, p, pi);
3377 vnc_import_bgp_exterior_del_route(peer->bgp, p, pi);
3378 }
3379 }
3380 #endif
3381
3382 /* If this is an EVPN route, process for un-import. */
3383 if (safi == SAFI_EVPN)
3384 bgp_evpn_unimport_route(peer->bgp, afi, safi, p, pi);
3385
3386 bgp_rib_remove(dest, pi, peer, afi, safi);
3387 }
3388
3389 struct bgp_path_info *info_make(int type, int sub_type, unsigned short instance,
3390 struct peer *peer, struct attr *attr,
3391 struct bgp_dest *dest)
3392 {
3393 struct bgp_path_info *new;
3394
3395 /* Make new BGP info. */
3396 new = XCALLOC(MTYPE_BGP_ROUTE, sizeof(struct bgp_path_info));
3397 new->type = type;
3398 new->instance = instance;
3399 new->sub_type = sub_type;
3400 new->peer = peer;
3401 new->attr = attr;
3402 new->uptime = bgp_clock();
3403 new->net = dest;
3404 return new;
3405 }
3406
3407 static void overlay_index_update(struct attr *attr,
3408 union gw_addr *gw_ip)
3409 {
3410 if (!attr)
3411 return;
3412 if (gw_ip == NULL) {
3413 struct bgp_route_evpn eo;
3414
3415 memset(&eo, 0, sizeof(eo));
3416 bgp_attr_set_evpn_overlay(attr, &eo);
3417 } else {
3418 struct bgp_route_evpn eo = {.gw_ip = *gw_ip};
3419
3420 bgp_attr_set_evpn_overlay(attr, &eo);
3421 }
3422 }
3423
3424 static bool overlay_index_equal(afi_t afi, struct bgp_path_info *path,
3425 union gw_addr *gw_ip)
3426 {
3427 const struct bgp_route_evpn *eo = bgp_attr_get_evpn_overlay(path->attr);
3428 union gw_addr path_gw_ip, *path_gw_ip_remote;
3429 union {
3430 esi_t esi;
3431 union gw_addr ip;
3432 } temp;
3433
3434 if (afi != AFI_L2VPN)
3435 return true;
3436
3437 path_gw_ip = eo->gw_ip;
3438
3439 if (gw_ip == NULL) {
3440 memset(&temp, 0, sizeof(temp));
3441 path_gw_ip_remote = &temp.ip;
3442 } else
3443 path_gw_ip_remote = gw_ip;
3444
3445 return !!memcmp(&path_gw_ip, path_gw_ip_remote, sizeof(union gw_addr));
3446 }
3447
3448 /* Check if received nexthop is valid or not. */
3449 bool bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
3450 uint8_t type, uint8_t stype, struct attr *attr,
3451 struct bgp_dest *dest)
3452 {
3453 bool ret = false;
3454 bool is_bgp_static_route =
3455 (type == ZEBRA_ROUTE_BGP && stype == BGP_ROUTE_STATIC) ? true
3456 : false;
3457
3458 /*
3459 * Only validated for unicast and multicast currently.
3460 * Also valid for EVPN where the nexthop is an IP address.
3461 * If we are a bgp static route being checked then there is
3462 * no need to check to see if the nexthop is martian as
3463 * that it should be ok.
3464 */
3465 if (is_bgp_static_route ||
3466 (safi != SAFI_UNICAST && safi != SAFI_MULTICAST && safi != SAFI_EVPN))
3467 return false;
3468
3469 /* If NEXT_HOP is present, validate it. */
3470 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
3471 if (attr->nexthop.s_addr == INADDR_ANY
3472 || IPV4_CLASS_DE(ntohl(attr->nexthop.s_addr))
3473 || bgp_nexthop_self(bgp, afi, type, stype, attr, dest))
3474 return true;
3475 }
3476
3477 /* If MP_NEXTHOP is present, validate it. */
3478 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3479 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3480 * it is not an IPv6 link-local address.
3481 *
3482 * If we receive an UPDATE with nexthop length set to 32 bytes
3483 * we shouldn't discard an UPDATE if it's set to (::).
3484 * The link-local (2st) is validated along the code path later.
3485 */
3486 if (attr->mp_nexthop_len) {
3487 switch (attr->mp_nexthop_len) {
3488 case BGP_ATTR_NHLEN_IPV4:
3489 case BGP_ATTR_NHLEN_VPNV4:
3490 ret = (attr->mp_nexthop_global_in.s_addr == INADDR_ANY
3491 || IPV4_CLASS_DE(
3492 ntohl(attr->mp_nexthop_global_in.s_addr))
3493 || bgp_nexthop_self(bgp, afi, type, stype, attr,
3494 dest));
3495 break;
3496
3497 case BGP_ATTR_NHLEN_IPV6_GLOBAL:
3498 case BGP_ATTR_NHLEN_VPNV6_GLOBAL:
3499 ret = (IN6_IS_ADDR_UNSPECIFIED(
3500 &attr->mp_nexthop_global)
3501 || IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3502 || IN6_IS_ADDR_MULTICAST(
3503 &attr->mp_nexthop_global)
3504 || bgp_nexthop_self(bgp, afi, type, stype, attr,
3505 dest));
3506 break;
3507 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
3508 ret = (IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3509 || IN6_IS_ADDR_MULTICAST(
3510 &attr->mp_nexthop_global)
3511 || bgp_nexthop_self(bgp, afi, type, stype, attr,
3512 dest));
3513 break;
3514
3515 default:
3516 ret = true;
3517 break;
3518 }
3519 }
3520
3521 return ret;
3522 }
3523
3524 static void bgp_attr_add_no_export_community(struct attr *attr)
3525 {
3526 struct community *old;
3527 struct community *new;
3528 struct community *merge;
3529 struct community *no_export;
3530
3531 old = attr->community;
3532 no_export = community_str2com("no-export");
3533
3534 assert(no_export);
3535
3536 if (old) {
3537 merge = community_merge(community_dup(old), no_export);
3538
3539 if (!old->refcnt)
3540 community_free(&old);
3541
3542 new = community_uniq_sort(merge);
3543 community_free(&merge);
3544 } else {
3545 new = community_dup(no_export);
3546 }
3547
3548 community_free(&no_export);
3549
3550 attr->community = new;
3551 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
3552 }
3553
3554 int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
3555 struct attr *attr, afi_t afi, safi_t safi, int type,
3556 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
3557 uint32_t num_labels, int soft_reconfig,
3558 struct bgp_route_evpn *evpn)
3559 {
3560 int ret;
3561 int aspath_loop_count = 0;
3562 struct bgp_dest *dest;
3563 struct bgp *bgp;
3564 struct attr new_attr;
3565 struct attr *attr_new;
3566 struct bgp_path_info *pi;
3567 struct bgp_path_info *new;
3568 struct bgp_path_info_extra *extra;
3569 const char *reason;
3570 char pfx_buf[BGP_PRD_PATH_STRLEN];
3571 int connected = 0;
3572 int do_loop_check = 1;
3573 int has_valid_label = 0;
3574 afi_t nh_afi;
3575 uint8_t pi_type = 0;
3576 uint8_t pi_sub_type = 0;
3577
3578 if (frrtrace_enabled(frr_bgp, process_update)) {
3579 char pfxprint[PREFIX2STR_BUFFER];
3580
3581 prefix2str(p, pfxprint, sizeof(pfxprint));
3582 frrtrace(6, frr_bgp, process_update, peer, pfxprint, addpath_id,
3583 afi, safi, attr);
3584 }
3585
3586 #ifdef ENABLE_BGP_VNC
3587 int vnc_implicit_withdraw = 0;
3588 #endif
3589 int same_attr = 0;
3590
3591 memset(&new_attr, 0, sizeof(struct attr));
3592 new_attr.label_index = BGP_INVALID_LABEL_INDEX;
3593 new_attr.label = MPLS_INVALID_LABEL;
3594
3595 bgp = peer->bgp;
3596 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
3597 /* TODO: Check to see if we can get rid of "is_valid_label" */
3598 if (afi == AFI_L2VPN && safi == SAFI_EVPN)
3599 has_valid_label = (num_labels > 0) ? 1 : 0;
3600 else
3601 has_valid_label = bgp_is_valid_label(label);
3602
3603 if (has_valid_label)
3604 assert(label != NULL);
3605
3606 /* When peer's soft reconfiguration enabled. Record input packet in
3607 Adj-RIBs-In. */
3608 if (!soft_reconfig
3609 && CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
3610 && peer != bgp->peer_self)
3611 bgp_adj_in_set(dest, peer, attr, addpath_id);
3612
3613 /* Check previously received route. */
3614 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
3615 if (pi->peer == peer && pi->type == type
3616 && pi->sub_type == sub_type
3617 && pi->addpath_rx_id == addpath_id)
3618 break;
3619
3620 /* AS path local-as loop check. */
3621 if (peer->change_local_as) {
3622 if (peer->allowas_in[afi][safi])
3623 aspath_loop_count = peer->allowas_in[afi][safi];
3624 else if (!CHECK_FLAG(peer->flags,
3625 PEER_FLAG_LOCAL_AS_NO_PREPEND))
3626 aspath_loop_count = 1;
3627
3628 if (aspath_loop_check(attr->aspath, peer->change_local_as)
3629 > aspath_loop_count) {
3630 peer->stat_pfx_aspath_loop++;
3631 reason = "as-path contains our own AS A;";
3632 goto filtered;
3633 }
3634 }
3635
3636 /* If the peer is configured for "allowas-in origin" and the last ASN in
3637 * the
3638 * as-path is our ASN then we do not need to call aspath_loop_check
3639 */
3640 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN))
3641 if (aspath_get_last_as(attr->aspath) == bgp->as)
3642 do_loop_check = 0;
3643
3644 /* AS path loop check. */
3645 if (do_loop_check) {
3646 if (aspath_loop_check(attr->aspath, bgp->as)
3647 > peer->allowas_in[afi][safi]
3648 || (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)
3649 && aspath_loop_check(attr->aspath, bgp->confed_id)
3650 > peer->allowas_in[afi][safi])) {
3651 peer->stat_pfx_aspath_loop++;
3652 reason = "as-path contains our own AS;";
3653 goto filtered;
3654 }
3655 }
3656
3657 /* Route reflector originator ID check. */
3658 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
3659 && IPV4_ADDR_SAME(&bgp->router_id, &attr->originator_id)) {
3660 peer->stat_pfx_originator_loop++;
3661 reason = "originator is us;";
3662 goto filtered;
3663 }
3664
3665 /* Route reflector cluster ID check. */
3666 if (bgp_cluster_filter(peer, attr)) {
3667 peer->stat_pfx_cluster_loop++;
3668 reason = "reflected from the same cluster;";
3669 goto filtered;
3670 }
3671
3672 /* Apply incoming filter. */
3673 if (bgp_input_filter(peer, p, attr, afi, safi) == FILTER_DENY) {
3674 peer->stat_pfx_filter++;
3675 reason = "filter;";
3676 goto filtered;
3677 }
3678
3679 /* RFC 8212 to prevent route leaks.
3680 * This specification intends to improve this situation by requiring the
3681 * explicit configuration of both BGP Import and Export Policies for any
3682 * External BGP (EBGP) session such as customers, peers, or
3683 * confederation boundaries for all enabled address families. Through
3684 * codification of the aforementioned requirement, operators will
3685 * benefit from consistent behavior across different BGP
3686 * implementations.
3687 */
3688 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
3689 if (!bgp_inbound_policy_exists(peer,
3690 &peer->filter[afi][safi])) {
3691 reason = "inbound policy missing";
3692 goto filtered;
3693 }
3694
3695 /* draft-ietf-idr-deprecate-as-set-confed-set
3696 * Filter routes having AS_SET or AS_CONFED_SET in the path.
3697 * Eventually, This document (if approved) updates RFC 4271
3698 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
3699 * and obsoletes RFC 6472.
3700 */
3701 if (peer->bgp->reject_as_sets)
3702 if (aspath_check_as_sets(attr->aspath)) {
3703 reason =
3704 "as-path contains AS_SET or AS_CONFED_SET type;";
3705 goto filtered;
3706 }
3707
3708 new_attr = *attr;
3709
3710 /* Apply incoming route-map.
3711 * NB: new_attr may now contain newly allocated values from route-map
3712 * "set"
3713 * commands, so we need bgp_attr_flush in the error paths, until we
3714 * intern
3715 * the attr (which takes over the memory references) */
3716 if (bgp_input_modifier(peer, p, &new_attr, afi, safi, NULL, label,
3717 num_labels, dest)
3718 == RMAP_DENY) {
3719 peer->stat_pfx_filter++;
3720 reason = "route-map;";
3721 bgp_attr_flush(&new_attr);
3722 goto filtered;
3723 }
3724
3725 if (pi && pi->attr->rmap_table_id != new_attr.rmap_table_id) {
3726 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3727 /* remove from RIB previous entry */
3728 bgp_zebra_withdraw(p, pi, bgp, safi);
3729 }
3730
3731 if (peer->sort == BGP_PEER_EBGP) {
3732
3733 /* rfc7999:
3734 * A BGP speaker receiving an announcement tagged with the
3735 * BLACKHOLE community SHOULD add the NO_ADVERTISE or
3736 * NO_EXPORT community as defined in RFC1997, or a
3737 * similar community, to prevent propagation of the
3738 * prefix outside the local AS. The community to prevent
3739 * propagation SHOULD be chosen according to the operator's
3740 * routing policy.
3741 */
3742 if (new_attr.community
3743 && community_include(new_attr.community,
3744 COMMUNITY_BLACKHOLE))
3745 bgp_attr_add_no_export_community(&new_attr);
3746
3747 /* If we receive the graceful-shutdown community from an eBGP
3748 * peer we must lower local-preference */
3749 if (new_attr.community
3750 && community_include(new_attr.community, COMMUNITY_GSHUT)) {
3751 new_attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
3752 new_attr.local_pref = BGP_GSHUT_LOCAL_PREF;
3753
3754 /* If graceful-shutdown is configured then add the GSHUT
3755 * community to all paths received from eBGP peers */
3756 } else if (bgp_in_graceful_shutdown(peer->bgp))
3757 bgp_attr_add_gshut_community(&new_attr);
3758 }
3759
3760 if (pi) {
3761 pi_type = pi->type;
3762 pi_sub_type = pi->sub_type;
3763 }
3764
3765 /* next hop check. */
3766 if (!CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD)
3767 && bgp_update_martian_nexthop(bgp, afi, safi, pi_type, pi_sub_type,
3768 &new_attr, dest)) {
3769 peer->stat_pfx_nh_invalid++;
3770 reason = "martian or self next-hop;";
3771 bgp_attr_flush(&new_attr);
3772 goto filtered;
3773 }
3774
3775 if (bgp_mac_entry_exists(p) || bgp_mac_exist(&attr->rmac)) {
3776 peer->stat_pfx_nh_invalid++;
3777 reason = "self mac;";
3778 goto filtered;
3779 }
3780
3781 /* Update Overlay Index */
3782 if (afi == AFI_L2VPN) {
3783 overlay_index_update(&new_attr,
3784 evpn == NULL ? NULL : &evpn->gw_ip);
3785 }
3786
3787 /* The flag BGP_NODE_FIB_INSTALL_PENDING is for the following
3788 * condition :
3789 * Suppress fib is enabled
3790 * BGP_OPT_NO_FIB is not enabled
3791 * Route type is BGP_ROUTE_NORMAL (peer learnt routes)
3792 * Route is being installed first time (BGP_NODE_FIB_INSTALLED not set)
3793 */
3794 if (bgp_fibupd_safi(safi) && BGP_SUPPRESS_FIB_ENABLED(bgp)
3795 && (sub_type == BGP_ROUTE_NORMAL)
3796 && (!bgp_option_check(BGP_OPT_NO_FIB))
3797 && (!CHECK_FLAG(dest->flags, BGP_NODE_FIB_INSTALLED)))
3798 SET_FLAG(dest->flags, BGP_NODE_FIB_INSTALL_PENDING);
3799
3800 attr_new = bgp_attr_intern(&new_attr);
3801
3802 /* If maximum prefix count is configured and current prefix
3803 * count exeed it.
3804 */
3805 if (bgp_maximum_prefix_overflow(peer, afi, safi, 0))
3806 return -1;
3807
3808 /* If the update is implicit withdraw. */
3809 if (pi) {
3810 pi->uptime = bgp_clock();
3811 same_attr = attrhash_cmp(pi->attr, attr_new);
3812
3813 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
3814
3815 /* Same attribute comes in. */
3816 if (!CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
3817 && same_attr
3818 && (!has_valid_label
3819 || memcmp(&(bgp_path_info_extra_get(pi))->label, label,
3820 num_labels * sizeof(mpls_label_t))
3821 == 0)
3822 && (overlay_index_equal(
3823 afi, pi,
3824 evpn == NULL ? NULL : &evpn->gw_ip))) {
3825 if (get_active_bdc_from_pi(pi, afi, safi)
3826 && peer->sort == BGP_PEER_EBGP
3827 && CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
3828 if (bgp_debug_update(peer, p, NULL, 1)) {
3829 bgp_debug_rdpfxpath2str(
3830 afi, safi, prd, p, label,
3831 num_labels, addpath_id ? 1 : 0,
3832 addpath_id, pfx_buf,
3833 sizeof(pfx_buf));
3834 zlog_debug("%s rcvd %s", peer->host,
3835 pfx_buf);
3836 }
3837
3838 if (bgp_damp_update(pi, dest, afi, safi)
3839 != BGP_DAMP_SUPPRESSED) {
3840 bgp_aggregate_increment(bgp, p, pi, afi,
3841 safi);
3842 bgp_process(bgp, dest, afi, safi);
3843 }
3844 } else /* Duplicate - odd */
3845 {
3846 if (bgp_debug_update(peer, p, NULL, 1)) {
3847 if (!peer->rcvd_attr_printed) {
3848 zlog_debug(
3849 "%s rcvd UPDATE w/ attr: %s",
3850 peer->host,
3851 peer->rcvd_attr_str);
3852 peer->rcvd_attr_printed = 1;
3853 }
3854
3855 bgp_debug_rdpfxpath2str(
3856 afi, safi, prd, p, label,
3857 num_labels, addpath_id ? 1 : 0,
3858 addpath_id, pfx_buf,
3859 sizeof(pfx_buf));
3860 zlog_debug(
3861 "%s rcvd %s...duplicate ignored",
3862 peer->host, pfx_buf);
3863 }
3864
3865 /* graceful restart STALE flag unset. */
3866 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
3867 bgp_path_info_unset_flag(
3868 dest, pi, BGP_PATH_STALE);
3869 bgp_dest_set_defer_flag(dest, false);
3870 bgp_process(bgp, dest, afi, safi);
3871 }
3872 }
3873
3874 bgp_dest_unlock_node(dest);
3875 bgp_attr_unintern(&attr_new);
3876
3877 return 0;
3878 }
3879
3880 /* Withdraw/Announce before we fully processed the withdraw */
3881 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
3882 if (bgp_debug_update(peer, p, NULL, 1)) {
3883 bgp_debug_rdpfxpath2str(
3884 afi, safi, prd, p, label, num_labels,
3885 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3886 sizeof(pfx_buf));
3887 zlog_debug(
3888 "%s rcvd %s, flapped quicker than processing",
3889 peer->host, pfx_buf);
3890 }
3891
3892 bgp_path_info_restore(dest, pi);
3893 }
3894
3895 /* Received Logging. */
3896 if (bgp_debug_update(peer, p, NULL, 1)) {
3897 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label,
3898 num_labels, addpath_id ? 1 : 0,
3899 addpath_id, pfx_buf,
3900 sizeof(pfx_buf));
3901 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
3902 }
3903
3904 /* graceful restart STALE flag unset. */
3905 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
3906 bgp_path_info_unset_flag(dest, pi, BGP_PATH_STALE);
3907 bgp_dest_set_defer_flag(dest, false);
3908 }
3909
3910 /* The attribute is changed. */
3911 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
3912
3913 /* implicit withdraw, decrement aggregate and pcount here.
3914 * only if update is accepted, they'll increment below.
3915 */
3916 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
3917
3918 /* Update bgp route dampening information. */
3919 if (get_active_bdc_from_pi(pi, afi, safi)
3920 && peer->sort == BGP_PEER_EBGP) {
3921 /* This is implicit withdraw so we should update
3922 * dampening information.
3923 */
3924 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
3925 bgp_damp_withdraw(pi, dest, afi, safi, 1);
3926 }
3927 #ifdef ENABLE_BGP_VNC
3928 if (safi == SAFI_MPLS_VPN) {
3929 struct bgp_dest *pdest = NULL;
3930 struct bgp_table *table = NULL;
3931
3932 pdest = bgp_node_get(bgp->rib[afi][safi],
3933 (struct prefix *)prd);
3934 if (bgp_dest_has_bgp_path_info_data(pdest)) {
3935 table = bgp_dest_get_bgp_table_info(pdest);
3936
3937 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3938 bgp, prd, table, p, pi);
3939 }
3940 bgp_dest_unlock_node(pdest);
3941 }
3942 if ((afi == AFI_IP || afi == AFI_IP6)
3943 && (safi == SAFI_UNICAST)) {
3944 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
3945 /*
3946 * Implicit withdraw case.
3947 */
3948 ++vnc_implicit_withdraw;
3949 vnc_import_bgp_del_route(bgp, p, pi);
3950 vnc_import_bgp_exterior_del_route(bgp, p, pi);
3951 }
3952 }
3953 #endif
3954
3955 /* Special handling for EVPN update of an existing route. If the
3956 * extended community attribute has changed, we need to
3957 * un-import
3958 * the route using its existing extended community. It will be
3959 * subsequently processed for import with the new extended
3960 * community.
3961 */
3962 if (((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN))
3963 && !same_attr) {
3964 if ((pi->attr->flag
3965 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))
3966 && (attr_new->flag
3967 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
3968 int cmp;
3969
3970 cmp = ecommunity_cmp(pi->attr->ecommunity,
3971 attr_new->ecommunity);
3972 if (!cmp) {
3973 if (bgp_debug_update(peer, p, NULL, 1))
3974 zlog_debug(
3975 "Change in EXT-COMM, existing %s new %s",
3976 ecommunity_str(
3977 pi->attr->ecommunity),
3978 ecommunity_str(
3979 attr_new->ecommunity));
3980 if (safi == SAFI_EVPN)
3981 bgp_evpn_unimport_route(
3982 bgp, afi, safi, p, pi);
3983 else /* SAFI_MPLS_VPN */
3984 vpn_leak_to_vrf_withdraw(bgp,
3985 pi);
3986 }
3987 }
3988 }
3989
3990 /* Update to new attribute. */
3991 bgp_attr_unintern(&pi->attr);
3992 pi->attr = attr_new;
3993
3994 /* Update MPLS label */
3995 if (has_valid_label) {
3996 extra = bgp_path_info_extra_get(pi);
3997 if (extra->label != label) {
3998 memcpy(&extra->label, label,
3999 num_labels * sizeof(mpls_label_t));
4000 extra->num_labels = num_labels;
4001 }
4002 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4003 bgp_set_valid_label(&extra->label[0]);
4004 }
4005
4006 /* Update SRv6 SID */
4007 if (attr->srv6_l3vpn) {
4008 extra = bgp_path_info_extra_get(pi);
4009 if (sid_diff(&extra->sid[0], &attr->srv6_l3vpn->sid)) {
4010 sid_copy(&extra->sid[0],
4011 &attr->srv6_l3vpn->sid);
4012 extra->num_sids = 1;
4013 }
4014 } else if (attr->srv6_vpn) {
4015 extra = bgp_path_info_extra_get(pi);
4016 if (sid_diff(&extra->sid[0], &attr->srv6_vpn->sid)) {
4017 sid_copy(&extra->sid[0], &attr->srv6_vpn->sid);
4018 extra->num_sids = 1;
4019 }
4020 }
4021
4022 #ifdef ENABLE_BGP_VNC
4023 if ((afi == AFI_IP || afi == AFI_IP6)
4024 && (safi == SAFI_UNICAST)) {
4025 if (vnc_implicit_withdraw) {
4026 /*
4027 * Add back the route with its new attributes
4028 * (e.g., nexthop).
4029 * The route is still selected, until the route
4030 * selection
4031 * queued by bgp_process actually runs. We have
4032 * to make this
4033 * update to the VNC side immediately to avoid
4034 * racing against
4035 * configuration changes (e.g., route-map
4036 * changes) which
4037 * trigger re-importation of the entire RIB.
4038 */
4039 vnc_import_bgp_add_route(bgp, p, pi);
4040 vnc_import_bgp_exterior_add_route(bgp, p, pi);
4041 }
4042 }
4043 #endif
4044
4045 /* Update bgp route dampening information. */
4046 if (get_active_bdc_from_pi(pi, afi, safi)
4047 && peer->sort == BGP_PEER_EBGP) {
4048 /* Now we do normal update dampening. */
4049 ret = bgp_damp_update(pi, dest, afi, safi);
4050 if (ret == BGP_DAMP_SUPPRESSED) {
4051 bgp_dest_unlock_node(dest);
4052 return 0;
4053 }
4054 }
4055
4056 /* Nexthop reachability check - for unicast and
4057 * labeled-unicast.. */
4058 if (((afi == AFI_IP || afi == AFI_IP6)
4059 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4060 || (safi == SAFI_EVPN &&
4061 bgp_evpn_is_prefix_nht_supported(p))) {
4062 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4063 && peer->ttl == BGP_DEFAULT_TTL
4064 && !CHECK_FLAG(peer->flags,
4065 PEER_FLAG_DISABLE_CONNECTED_CHECK)
4066 && !CHECK_FLAG(bgp->flags,
4067 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
4068 connected = 1;
4069 else
4070 connected = 0;
4071
4072 struct bgp *bgp_nexthop = bgp;
4073
4074 if (pi->extra && pi->extra->bgp_orig)
4075 bgp_nexthop = pi->extra->bgp_orig;
4076
4077 nh_afi = BGP_ATTR_NH_AFI(afi, pi->attr);
4078
4079 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop, nh_afi,
4080 safi, pi, NULL, connected)
4081 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
4082 bgp_path_info_set_flag(dest, pi,
4083 BGP_PATH_VALID);
4084 else {
4085 if (BGP_DEBUG(nht, NHT)) {
4086 zlog_debug("%s(%pI4): NH unresolved",
4087 __func__,
4088 (in_addr_t *)&attr_new->nexthop);
4089 }
4090 bgp_path_info_unset_flag(dest, pi,
4091 BGP_PATH_VALID);
4092 }
4093 } else
4094 bgp_path_info_set_flag(dest, pi, BGP_PATH_VALID);
4095
4096 #ifdef ENABLE_BGP_VNC
4097 if (safi == SAFI_MPLS_VPN) {
4098 struct bgp_dest *pdest = NULL;
4099 struct bgp_table *table = NULL;
4100
4101 pdest = bgp_node_get(bgp->rib[afi][safi],
4102 (struct prefix *)prd);
4103 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4104 table = bgp_dest_get_bgp_table_info(pdest);
4105
4106 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4107 bgp, prd, table, p, pi);
4108 }
4109 bgp_dest_unlock_node(pdest);
4110 }
4111 #endif
4112
4113 /* If this is an EVPN route and some attribute has changed,
4114 * process
4115 * route for import. If the extended community has changed, we
4116 * would
4117 * have done the un-import earlier and the import would result
4118 * in the
4119 * route getting injected into appropriate L2 VNIs. If it is
4120 * just
4121 * some other attribute change, the import will result in
4122 * updating
4123 * the attributes for the route in the VNI(s).
4124 */
4125 if (safi == SAFI_EVPN && !same_attr &&
4126 CHECK_FLAG(pi->flags, BGP_PATH_VALID))
4127 bgp_evpn_import_route(bgp, afi, safi, p, pi);
4128
4129 /* Process change. */
4130 bgp_aggregate_increment(bgp, p, pi, afi, safi);
4131
4132 bgp_process(bgp, dest, afi, safi);
4133 bgp_dest_unlock_node(dest);
4134
4135 if (SAFI_UNICAST == safi
4136 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4137 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4138
4139 vpn_leak_from_vrf_update(bgp_get_default(), bgp, pi);
4140 }
4141 if ((SAFI_MPLS_VPN == safi)
4142 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4143
4144 vpn_leak_to_vrf_update(bgp, pi);
4145 }
4146
4147 #ifdef ENABLE_BGP_VNC
4148 if (SAFI_MPLS_VPN == safi) {
4149 mpls_label_t label_decoded = decode_label(label);
4150
4151 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4152 type, sub_type, &label_decoded);
4153 }
4154 if (SAFI_ENCAP == safi) {
4155 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4156 type, sub_type, NULL);
4157 }
4158 #endif
4159
4160 return 0;
4161 } // End of implicit withdraw
4162
4163 /* Received Logging. */
4164 if (bgp_debug_update(peer, p, NULL, 1)) {
4165 if (!peer->rcvd_attr_printed) {
4166 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
4167 peer->rcvd_attr_str);
4168 peer->rcvd_attr_printed = 1;
4169 }
4170
4171 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
4172 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4173 sizeof(pfx_buf));
4174 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
4175 }
4176
4177 /* Make new BGP info. */
4178 new = info_make(type, sub_type, 0, peer, attr_new, dest);
4179
4180 /* Update MPLS label */
4181 if (has_valid_label) {
4182 extra = bgp_path_info_extra_get(new);
4183 if (extra->label != label) {
4184 memcpy(&extra->label, label,
4185 num_labels * sizeof(mpls_label_t));
4186 extra->num_labels = num_labels;
4187 }
4188 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4189 bgp_set_valid_label(&extra->label[0]);
4190 }
4191
4192 /* Update SRv6 SID */
4193 if (safi == SAFI_MPLS_VPN) {
4194 extra = bgp_path_info_extra_get(new);
4195 if (attr->srv6_l3vpn) {
4196 sid_copy(&extra->sid[0], &attr->srv6_l3vpn->sid);
4197 extra->num_sids = 1;
4198 } else if (attr->srv6_vpn) {
4199 sid_copy(&extra->sid[0], &attr->srv6_vpn->sid);
4200 extra->num_sids = 1;
4201 }
4202 }
4203
4204 /* Update Overlay Index */
4205 if (afi == AFI_L2VPN) {
4206 overlay_index_update(new->attr,
4207 evpn == NULL ? NULL : &evpn->gw_ip);
4208 }
4209 /* Nexthop reachability check. */
4210 if (((afi == AFI_IP || afi == AFI_IP6)
4211 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4212 || (safi == SAFI_EVPN && bgp_evpn_is_prefix_nht_supported(p))) {
4213 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4214 && peer->ttl == BGP_DEFAULT_TTL
4215 && !CHECK_FLAG(peer->flags,
4216 PEER_FLAG_DISABLE_CONNECTED_CHECK)
4217 && !CHECK_FLAG(bgp->flags,
4218 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
4219 connected = 1;
4220 else
4221 connected = 0;
4222
4223 nh_afi = BGP_ATTR_NH_AFI(afi, new->attr);
4224
4225 if (bgp_find_or_add_nexthop(bgp, bgp, nh_afi, safi, new, NULL,
4226 connected)
4227 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
4228 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
4229 else {
4230 if (BGP_DEBUG(nht, NHT)) {
4231 char buf1[INET6_ADDRSTRLEN];
4232 inet_ntop(AF_INET,
4233 (const void *)&attr_new->nexthop,
4234 buf1, INET6_ADDRSTRLEN);
4235 zlog_debug("%s(%s): NH unresolved", __func__,
4236 buf1);
4237 }
4238 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
4239 }
4240 } else
4241 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
4242
4243 /* Addpath ID */
4244 new->addpath_rx_id = addpath_id;
4245
4246 /* Increment prefix */
4247 bgp_aggregate_increment(bgp, p, new, afi, safi);
4248
4249 /* Register new BGP information. */
4250 bgp_path_info_add(dest, new);
4251
4252 /* route_node_get lock */
4253 bgp_dest_unlock_node(dest);
4254
4255 #ifdef ENABLE_BGP_VNC
4256 if (safi == SAFI_MPLS_VPN) {
4257 struct bgp_dest *pdest = NULL;
4258 struct bgp_table *table = NULL;
4259
4260 pdest = bgp_node_get(bgp->rib[afi][safi], (struct prefix *)prd);
4261 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4262 table = bgp_dest_get_bgp_table_info(pdest);
4263
4264 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4265 bgp, prd, table, p, new);
4266 }
4267 bgp_dest_unlock_node(pdest);
4268 }
4269 #endif
4270
4271 /* If this is an EVPN route, process for import. */
4272 if (safi == SAFI_EVPN && CHECK_FLAG(new->flags, BGP_PATH_VALID))
4273 bgp_evpn_import_route(bgp, afi, safi, p, new);
4274
4275 hook_call(bgp_process, bgp, afi, safi, dest, peer, false);
4276
4277 /* Process change. */
4278 bgp_process(bgp, dest, afi, safi);
4279
4280 if (SAFI_UNICAST == safi
4281 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4282 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4283 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
4284 }
4285 if ((SAFI_MPLS_VPN == safi)
4286 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4287
4288 vpn_leak_to_vrf_update(bgp, new);
4289 }
4290 #ifdef ENABLE_BGP_VNC
4291 if (SAFI_MPLS_VPN == safi) {
4292 mpls_label_t label_decoded = decode_label(label);
4293
4294 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4295 sub_type, &label_decoded);
4296 }
4297 if (SAFI_ENCAP == safi) {
4298 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4299 sub_type, NULL);
4300 }
4301 #endif
4302
4303 return 0;
4304
4305 /* This BGP update is filtered. Log the reason then update BGP
4306 entry. */
4307 filtered:
4308 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4309
4310 if (bgp_debug_update(peer, p, NULL, 1)) {
4311 if (!peer->rcvd_attr_printed) {
4312 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
4313 peer->rcvd_attr_str);
4314 peer->rcvd_attr_printed = 1;
4315 }
4316
4317 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
4318 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4319 sizeof(pfx_buf));
4320 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
4321 peer->host, pfx_buf, reason);
4322 }
4323
4324 if (pi) {
4325 /* If this is an EVPN route, un-import it as it is now filtered.
4326 */
4327 if (safi == SAFI_EVPN)
4328 bgp_evpn_unimport_route(bgp, afi, safi, p, pi);
4329
4330 if (SAFI_UNICAST == safi
4331 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4332 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4333
4334 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
4335 }
4336 if ((SAFI_MPLS_VPN == safi)
4337 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4338
4339 vpn_leak_to_vrf_withdraw(bgp, pi);
4340 }
4341
4342 bgp_rib_remove(dest, pi, peer, afi, safi);
4343 }
4344
4345 bgp_dest_unlock_node(dest);
4346
4347 #ifdef ENABLE_BGP_VNC
4348 /*
4349 * Filtered update is treated as an implicit withdrawal (see
4350 * bgp_rib_remove()
4351 * a few lines above)
4352 */
4353 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4354 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4355 0);
4356 }
4357 #endif
4358
4359 return 0;
4360 }
4361
4362 int bgp_withdraw(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
4363 struct attr *attr, afi_t afi, safi_t safi, int type,
4364 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
4365 uint32_t num_labels, struct bgp_route_evpn *evpn)
4366 {
4367 struct bgp *bgp;
4368 char pfx_buf[BGP_PRD_PATH_STRLEN];
4369 struct bgp_dest *dest;
4370 struct bgp_path_info *pi;
4371
4372 #ifdef ENABLE_BGP_VNC
4373 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4374 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4375 0);
4376 }
4377 #endif
4378
4379 bgp = peer->bgp;
4380
4381 /* Lookup node. */
4382 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
4383
4384 /* If peer is soft reconfiguration enabled. Record input packet for
4385 * further calculation.
4386 *
4387 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4388 * routes that are filtered. This tanks out Quagga RS pretty badly due
4389 * to
4390 * the iteration over all RS clients.
4391 * Since we need to remove the entry from adj_in anyway, do that first
4392 * and
4393 * if there was no entry, we don't need to do anything more.
4394 */
4395 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
4396 && peer != bgp->peer_self)
4397 if (!bgp_adj_in_unset(dest, peer, addpath_id)) {
4398 peer->stat_pfx_dup_withdraw++;
4399
4400 if (bgp_debug_update(peer, p, NULL, 1)) {
4401 bgp_debug_rdpfxpath2str(
4402 afi, safi, prd, p, label, num_labels,
4403 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4404 sizeof(pfx_buf));
4405 zlog_debug(
4406 "%s withdrawing route %s not in adj-in",
4407 peer->host, pfx_buf);
4408 }
4409 bgp_dest_unlock_node(dest);
4410 return 0;
4411 }
4412
4413 /* Lookup withdrawn route. */
4414 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
4415 if (pi->peer == peer && pi->type == type
4416 && pi->sub_type == sub_type
4417 && pi->addpath_rx_id == addpath_id)
4418 break;
4419
4420 /* Logging. */
4421 if (bgp_debug_update(peer, p, NULL, 1)) {
4422 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
4423 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4424 sizeof(pfx_buf));
4425 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer->host,
4426 pfx_buf);
4427 }
4428
4429 /* Withdraw specified route from routing table. */
4430 if (pi && !CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
4431 bgp_rib_withdraw(dest, pi, peer, afi, safi, prd);
4432 if (SAFI_UNICAST == safi
4433 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4434 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4435 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
4436 }
4437 if ((SAFI_MPLS_VPN == safi)
4438 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4439
4440 vpn_leak_to_vrf_withdraw(bgp, pi);
4441 }
4442 } else if (bgp_debug_update(peer, p, NULL, 1)) {
4443 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
4444 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4445 sizeof(pfx_buf));
4446 zlog_debug("%s Can't find the route %s", peer->host, pfx_buf);
4447 }
4448
4449 /* Unlock bgp_node_get() lock. */
4450 bgp_dest_unlock_node(dest);
4451
4452 return 0;
4453 }
4454
4455 void bgp_default_originate(struct peer *peer, afi_t afi, safi_t safi,
4456 int withdraw)
4457 {
4458 struct update_subgroup *subgrp;
4459 subgrp = peer_subgroup(peer, afi, safi);
4460 subgroup_default_originate(subgrp, withdraw);
4461 }
4462
4463
4464 /*
4465 * bgp_stop_announce_route_timer
4466 */
4467 void bgp_stop_announce_route_timer(struct peer_af *paf)
4468 {
4469 if (!paf->t_announce_route)
4470 return;
4471
4472 thread_cancel(&paf->t_announce_route);
4473 }
4474
4475 /*
4476 * bgp_announce_route_timer_expired
4477 *
4478 * Callback that is invoked when the route announcement timer for a
4479 * peer_af expires.
4480 */
4481 static int bgp_announce_route_timer_expired(struct thread *t)
4482 {
4483 struct peer_af *paf;
4484 struct peer *peer;
4485
4486 paf = THREAD_ARG(t);
4487 peer = paf->peer;
4488
4489 if (peer->status != Established)
4490 return 0;
4491
4492 if (!peer->afc_nego[paf->afi][paf->safi])
4493 return 0;
4494
4495 peer_af_announce_route(paf, 1);
4496
4497 /* Notify BGP conditional advertisement scanner percess */
4498 peer->advmap_config_change[paf->afi][paf->safi] = true;
4499
4500 return 0;
4501 }
4502
4503 /*
4504 * bgp_announce_route
4505 *
4506 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
4507 */
4508 void bgp_announce_route(struct peer *peer, afi_t afi, safi_t safi)
4509 {
4510 struct peer_af *paf;
4511 struct update_subgroup *subgrp;
4512
4513 paf = peer_af_find(peer, afi, safi);
4514 if (!paf)
4515 return;
4516 subgrp = PAF_SUBGRP(paf);
4517
4518 /*
4519 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
4520 * or a refresh has already been triggered.
4521 */
4522 if (!subgrp || paf->t_announce_route)
4523 return;
4524
4525 /*
4526 * Start a timer to stagger/delay the announce. This serves
4527 * two purposes - announcement can potentially be combined for
4528 * multiple peers and the announcement doesn't happen in the
4529 * vty context.
4530 */
4531 thread_add_timer_msec(bm->master, bgp_announce_route_timer_expired, paf,
4532 (subgrp->peer_count == 1)
4533 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
4534 : BGP_ANNOUNCE_ROUTE_DELAY_MS,
4535 &paf->t_announce_route);
4536 }
4537
4538 /*
4539 * Announce routes from all AF tables to a peer.
4540 *
4541 * This should ONLY be called when there is a need to refresh the
4542 * routes to the peer based on a policy change for this peer alone
4543 * or a route refresh request received from the peer.
4544 * The operation will result in splitting the peer from its existing
4545 * subgroups and putting it in new subgroups.
4546 */
4547 void bgp_announce_route_all(struct peer *peer)
4548 {
4549 afi_t afi;
4550 safi_t safi;
4551
4552 FOREACH_AFI_SAFI (afi, safi)
4553 bgp_announce_route(peer, afi, safi);
4554 }
4555
4556 static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi,
4557 struct bgp_table *table,
4558 struct prefix_rd *prd)
4559 {
4560 int ret;
4561 struct bgp_dest *dest;
4562 struct bgp_adj_in *ain;
4563
4564 if (!table)
4565 table = peer->bgp->rib[afi][safi];
4566
4567 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
4568 for (ain = dest->adj_in; ain; ain = ain->next) {
4569 if (ain->peer != peer)
4570 continue;
4571
4572 struct bgp_path_info *pi;
4573 uint32_t num_labels = 0;
4574 mpls_label_t *label_pnt = NULL;
4575 struct bgp_route_evpn evpn;
4576
4577 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
4578 pi = pi->next)
4579 if (pi->peer == peer)
4580 break;
4581
4582 if (pi && pi->extra)
4583 num_labels = pi->extra->num_labels;
4584 if (num_labels)
4585 label_pnt = &pi->extra->label[0];
4586 if (pi)
4587 memcpy(&evpn,
4588 bgp_attr_get_evpn_overlay(pi->attr),
4589 sizeof(evpn));
4590 else
4591 memset(&evpn, 0, sizeof(evpn));
4592
4593 ret = bgp_update(peer, bgp_dest_get_prefix(dest),
4594 ain->addpath_rx_id, ain->attr, afi,
4595 safi, ZEBRA_ROUTE_BGP,
4596 BGP_ROUTE_NORMAL, prd, label_pnt,
4597 num_labels, 1, &evpn);
4598
4599 if (ret < 0) {
4600 bgp_dest_unlock_node(dest);
4601 return;
4602 }
4603 }
4604 }
4605
4606 void bgp_soft_reconfig_in(struct peer *peer, afi_t afi, safi_t safi)
4607 {
4608 struct bgp_dest *dest;
4609 struct bgp_table *table;
4610
4611 if (peer->status != Established)
4612 return;
4613
4614 if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP)
4615 && (safi != SAFI_EVPN))
4616 bgp_soft_reconfig_table(peer, afi, safi, NULL, NULL);
4617 else
4618 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4619 dest = bgp_route_next(dest)) {
4620 table = bgp_dest_get_bgp_table_info(dest);
4621
4622 if (table == NULL)
4623 continue;
4624
4625 const struct prefix *p = bgp_dest_get_prefix(dest);
4626 struct prefix_rd prd;
4627
4628 prd.family = AF_UNSPEC;
4629 prd.prefixlen = 64;
4630 memcpy(&prd.val, p->u.val, 8);
4631
4632 bgp_soft_reconfig_table(peer, afi, safi, table, &prd);
4633 }
4634 }
4635
4636
4637 struct bgp_clear_node_queue {
4638 struct bgp_dest *dest;
4639 };
4640
4641 static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data)
4642 {
4643 struct bgp_clear_node_queue *cnq = data;
4644 struct bgp_dest *dest = cnq->dest;
4645 struct peer *peer = wq->spec.data;
4646 struct bgp_path_info *pi;
4647 struct bgp *bgp;
4648 afi_t afi = bgp_dest_table(dest)->afi;
4649 safi_t safi = bgp_dest_table(dest)->safi;
4650
4651 assert(dest && peer);
4652 bgp = peer->bgp;
4653
4654 /* It is possible that we have multiple paths for a prefix from a peer
4655 * if that peer is using AddPath.
4656 */
4657 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
4658 if (pi->peer != peer)
4659 continue;
4660
4661 /* graceful restart STALE flag set. */
4662 if (((CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)
4663 && peer->nsf[afi][safi])
4664 || CHECK_FLAG(peer->af_sflags[afi][safi],
4665 PEER_STATUS_ENHANCED_REFRESH))
4666 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
4667 && !CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
4668 bgp_path_info_set_flag(dest, pi, BGP_PATH_STALE);
4669 else {
4670 /* If this is an EVPN route, process for
4671 * un-import. */
4672 if (safi == SAFI_EVPN)
4673 bgp_evpn_unimport_route(
4674 bgp, afi, safi,
4675 bgp_dest_get_prefix(dest), pi);
4676 /* Handle withdraw for VRF route-leaking and L3VPN */
4677 if (SAFI_UNICAST == safi
4678 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF ||
4679 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4680 vpn_leak_from_vrf_withdraw(bgp_get_default(),
4681 bgp, pi);
4682 }
4683 if (SAFI_MPLS_VPN == safi &&
4684 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
4685 vpn_leak_to_vrf_withdraw(bgp, pi);
4686 }
4687
4688 bgp_rib_remove(dest, pi, peer, afi, safi);
4689 }
4690 }
4691 return WQ_SUCCESS;
4692 }
4693
4694 static void bgp_clear_node_queue_del(struct work_queue *wq, void *data)
4695 {
4696 struct bgp_clear_node_queue *cnq = data;
4697 struct bgp_dest *dest = cnq->dest;
4698 struct bgp_table *table = bgp_dest_table(dest);
4699
4700 bgp_dest_unlock_node(dest);
4701 bgp_table_unlock(table);
4702 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE, cnq);
4703 }
4704
4705 static void bgp_clear_node_complete(struct work_queue *wq)
4706 {
4707 struct peer *peer = wq->spec.data;
4708
4709 /* Tickle FSM to start moving again */
4710 BGP_EVENT_ADD(peer, Clearing_Completed);
4711
4712 peer_unlock(peer); /* bgp_clear_route */
4713 }
4714
4715 static void bgp_clear_node_queue_init(struct peer *peer)
4716 {
4717 char wname[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
4718
4719 snprintf(wname, sizeof(wname), "clear %s", peer->host);
4720 #undef CLEAR_QUEUE_NAME_LEN
4721
4722 peer->clear_node_queue = work_queue_new(bm->master, wname);
4723 peer->clear_node_queue->spec.hold = 10;
4724 peer->clear_node_queue->spec.workfunc = &bgp_clear_route_node;
4725 peer->clear_node_queue->spec.del_item_data = &bgp_clear_node_queue_del;
4726 peer->clear_node_queue->spec.completion_func = &bgp_clear_node_complete;
4727 peer->clear_node_queue->spec.max_retries = 0;
4728
4729 /* we only 'lock' this peer reference when the queue is actually active
4730 */
4731 peer->clear_node_queue->spec.data = peer;
4732 }
4733
4734 static void bgp_clear_route_table(struct peer *peer, afi_t afi, safi_t safi,
4735 struct bgp_table *table)
4736 {
4737 struct bgp_dest *dest;
4738 int force = peer->bgp->process_queue ? 0 : 1;
4739
4740 if (!table)
4741 table = peer->bgp->rib[afi][safi];
4742
4743 /* If still no table => afi/safi isn't configured at all or smth. */
4744 if (!table)
4745 return;
4746
4747 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
4748 struct bgp_path_info *pi, *next;
4749 struct bgp_adj_in *ain;
4750 struct bgp_adj_in *ain_next;
4751
4752 /* XXX:TODO: This is suboptimal, every non-empty route_node is
4753 * queued for every clearing peer, regardless of whether it is
4754 * relevant to the peer at hand.
4755 *
4756 * Overview: There are 3 different indices which need to be
4757 * scrubbed, potentially, when a peer is removed:
4758 *
4759 * 1 peer's routes visible via the RIB (ie accepted routes)
4760 * 2 peer's routes visible by the (optional) peer's adj-in index
4761 * 3 other routes visible by the peer's adj-out index
4762 *
4763 * 3 there is no hurry in scrubbing, once the struct peer is
4764 * removed from bgp->peer, we could just GC such deleted peer's
4765 * adj-outs at our leisure.
4766 *
4767 * 1 and 2 must be 'scrubbed' in some way, at least made
4768 * invisible via RIB index before peer session is allowed to be
4769 * brought back up. So one needs to know when such a 'search' is
4770 * complete.
4771 *
4772 * Ideally:
4773 *
4774 * - there'd be a single global queue or a single RIB walker
4775 * - rather than tracking which route_nodes still need to be
4776 * examined on a peer basis, we'd track which peers still
4777 * aren't cleared
4778 *
4779 * Given that our per-peer prefix-counts now should be reliable,
4780 * this may actually be achievable. It doesn't seem to be a huge
4781 * problem at this time,
4782 *
4783 * It is possible that we have multiple paths for a prefix from
4784 * a peer
4785 * if that peer is using AddPath.
4786 */
4787 ain = dest->adj_in;
4788 while (ain) {
4789 ain_next = ain->next;
4790
4791 if (ain->peer == peer) {
4792 bgp_adj_in_remove(dest, ain);
4793 bgp_dest_unlock_node(dest);
4794 }
4795
4796 ain = ain_next;
4797 }
4798
4799 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
4800 next = pi->next;
4801 if (pi->peer != peer)
4802 continue;
4803
4804 if (force)
4805 bgp_path_info_reap(dest, pi);
4806 else {
4807 struct bgp_clear_node_queue *cnq;
4808
4809 /* both unlocked in bgp_clear_node_queue_del */
4810 bgp_table_lock(bgp_dest_table(dest));
4811 bgp_dest_lock_node(dest);
4812 cnq = XCALLOC(
4813 MTYPE_BGP_CLEAR_NODE_QUEUE,
4814 sizeof(struct bgp_clear_node_queue));
4815 cnq->dest = dest;
4816 work_queue_add(peer->clear_node_queue, cnq);
4817 break;
4818 }
4819 }
4820 }
4821 return;
4822 }
4823
4824 void bgp_clear_route(struct peer *peer, afi_t afi, safi_t safi)
4825 {
4826 struct bgp_dest *dest;
4827 struct bgp_table *table;
4828
4829 if (peer->clear_node_queue == NULL)
4830 bgp_clear_node_queue_init(peer);
4831
4832 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
4833 * Idle until it receives a Clearing_Completed event. This protects
4834 * against peers which flap faster than we can we clear, which could
4835 * lead to:
4836 *
4837 * a) race with routes from the new session being installed before
4838 * clear_route_node visits the node (to delete the route of that
4839 * peer)
4840 * b) resource exhaustion, clear_route_node likely leads to an entry
4841 * on the process_main queue. Fast-flapping could cause that queue
4842 * to grow and grow.
4843 */
4844
4845 /* lock peer in assumption that clear-node-queue will get nodes; if so,
4846 * the unlock will happen upon work-queue completion; other wise, the
4847 * unlock happens at the end of this function.
4848 */
4849 if (!peer->clear_node_queue->thread)
4850 peer_lock(peer);
4851
4852 if (safi != SAFI_MPLS_VPN && safi != SAFI_ENCAP && safi != SAFI_EVPN)
4853 bgp_clear_route_table(peer, afi, safi, NULL);
4854 else
4855 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4856 dest = bgp_route_next(dest)) {
4857 table = bgp_dest_get_bgp_table_info(dest);
4858 if (!table)
4859 continue;
4860
4861 bgp_clear_route_table(peer, afi, safi, table);
4862 }
4863
4864 /* unlock if no nodes got added to the clear-node-queue. */
4865 if (!peer->clear_node_queue->thread)
4866 peer_unlock(peer);
4867 }
4868
4869 void bgp_clear_route_all(struct peer *peer)
4870 {
4871 afi_t afi;
4872 safi_t safi;
4873
4874 FOREACH_AFI_SAFI (afi, safi)
4875 bgp_clear_route(peer, afi, safi);
4876
4877 #ifdef ENABLE_BGP_VNC
4878 rfapiProcessPeerDown(peer);
4879 #endif
4880 }
4881
4882 void bgp_clear_adj_in(struct peer *peer, afi_t afi, safi_t safi)
4883 {
4884 struct bgp_table *table;
4885 struct bgp_dest *dest;
4886 struct bgp_adj_in *ain;
4887 struct bgp_adj_in *ain_next;
4888
4889 table = peer->bgp->rib[afi][safi];
4890
4891 /* It is possible that we have multiple paths for a prefix from a peer
4892 * if that peer is using AddPath.
4893 */
4894 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
4895 ain = dest->adj_in;
4896
4897 while (ain) {
4898 ain_next = ain->next;
4899
4900 if (ain->peer == peer) {
4901 bgp_adj_in_remove(dest, ain);
4902 bgp_dest_unlock_node(dest);
4903 }
4904
4905 ain = ain_next;
4906 }
4907 }
4908 }
4909
4910 void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
4911 {
4912 struct bgp_dest *dest;
4913 struct bgp_path_info *pi;
4914 struct bgp_table *table;
4915
4916 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
4917 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4918 dest = bgp_route_next(dest)) {
4919 struct bgp_dest *rm;
4920
4921 /* look for neighbor in tables */
4922 table = bgp_dest_get_bgp_table_info(dest);
4923 if (!table)
4924 continue;
4925
4926 for (rm = bgp_table_top(table); rm;
4927 rm = bgp_route_next(rm))
4928 for (pi = bgp_dest_get_bgp_path_info(rm); pi;
4929 pi = pi->next) {
4930 if (pi->peer != peer)
4931 continue;
4932 if (!CHECK_FLAG(pi->flags,
4933 BGP_PATH_STALE))
4934 break;
4935
4936 bgp_rib_remove(rm, pi, peer, afi, safi);
4937 break;
4938 }
4939 }
4940 } else {
4941 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4942 dest = bgp_route_next(dest))
4943 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
4944 pi = pi->next) {
4945 if (pi->peer != peer)
4946 continue;
4947 if (!CHECK_FLAG(pi->flags, BGP_PATH_STALE))
4948 break;
4949 bgp_rib_remove(dest, pi, peer, afi, safi);
4950 break;
4951 }
4952 }
4953 }
4954
4955 void bgp_set_stale_route(struct peer *peer, afi_t afi, safi_t safi)
4956 {
4957 struct bgp_dest *dest, *ndest;
4958 struct bgp_path_info *pi;
4959 struct bgp_table *table;
4960
4961 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
4962 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4963 dest = bgp_route_next(dest)) {
4964 table = bgp_dest_get_bgp_table_info(dest);
4965 if (!table)
4966 continue;
4967
4968 for (ndest = bgp_table_top(table); ndest;
4969 ndest = bgp_route_next(ndest)) {
4970 for (pi = bgp_dest_get_bgp_path_info(ndest); pi;
4971 pi = pi->next) {
4972 if (pi->peer != peer)
4973 continue;
4974
4975 if ((CHECK_FLAG(
4976 peer->af_sflags[afi][safi],
4977 PEER_STATUS_ENHANCED_REFRESH))
4978 && !CHECK_FLAG(pi->flags,
4979 BGP_PATH_STALE)
4980 && !CHECK_FLAG(
4981 pi->flags,
4982 BGP_PATH_UNUSEABLE)) {
4983 if (bgp_debug_neighbor_events(
4984 peer))
4985 zlog_debug(
4986 "%s: route-refresh for %s/%s, marking prefix %pFX as stale",
4987 peer->host,
4988 afi2str(afi),
4989 safi2str(safi),
4990 bgp_dest_get_prefix(
4991 ndest));
4992
4993 bgp_path_info_set_flag(
4994 ndest, pi,
4995 BGP_PATH_STALE);
4996 }
4997 }
4998 }
4999 }
5000 } else {
5001 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5002 dest = bgp_route_next(dest)) {
5003 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
5004 pi = pi->next) {
5005 if (pi->peer != peer)
5006 continue;
5007
5008 if ((CHECK_FLAG(peer->af_sflags[afi][safi],
5009 PEER_STATUS_ENHANCED_REFRESH))
5010 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
5011 && !CHECK_FLAG(pi->flags,
5012 BGP_PATH_UNUSEABLE)) {
5013 if (bgp_debug_neighbor_events(peer))
5014 zlog_debug(
5015 "%s: route-refresh for %s/%s, marking prefix %pFX as stale",
5016 peer->host,
5017 afi2str(afi),
5018 safi2str(safi),
5019 bgp_dest_get_prefix(
5020 dest));
5021
5022 bgp_path_info_set_flag(dest, pi,
5023 BGP_PATH_STALE);
5024 }
5025 }
5026 }
5027 }
5028 }
5029
5030 bool bgp_outbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
5031 {
5032 if (peer->sort == BGP_PEER_IBGP)
5033 return true;
5034
5035 if (peer->sort == BGP_PEER_EBGP
5036 && (ROUTE_MAP_OUT_NAME(filter) || PREFIX_LIST_OUT_NAME(filter)
5037 || FILTER_LIST_OUT_NAME(filter)
5038 || DISTRIBUTE_OUT_NAME(filter)))
5039 return true;
5040 return false;
5041 }
5042
5043 bool bgp_inbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
5044 {
5045 if (peer->sort == BGP_PEER_IBGP)
5046 return true;
5047
5048 if (peer->sort == BGP_PEER_EBGP
5049 && (ROUTE_MAP_IN_NAME(filter) || PREFIX_LIST_IN_NAME(filter)
5050 || FILTER_LIST_IN_NAME(filter)
5051 || DISTRIBUTE_IN_NAME(filter)))
5052 return true;
5053 return false;
5054 }
5055
5056 static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table,
5057 safi_t safi)
5058 {
5059 struct bgp_dest *dest;
5060 struct bgp_path_info *pi;
5061 struct bgp_path_info *next;
5062
5063 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
5064 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
5065 const struct prefix *p = bgp_dest_get_prefix(dest);
5066
5067 next = pi->next;
5068
5069 /* Unimport EVPN routes from VRFs */
5070 if (safi == SAFI_EVPN)
5071 bgp_evpn_unimport_route(bgp, AFI_L2VPN,
5072 SAFI_EVPN, p, pi);
5073
5074 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)
5075 && pi->type == ZEBRA_ROUTE_BGP
5076 && (pi->sub_type == BGP_ROUTE_NORMAL
5077 || pi->sub_type == BGP_ROUTE_AGGREGATE
5078 || pi->sub_type == BGP_ROUTE_IMPORTED)) {
5079
5080 if (bgp_fibupd_safi(safi))
5081 bgp_zebra_withdraw(p, pi, bgp, safi);
5082 }
5083
5084 bgp_path_info_reap(dest, pi);
5085 }
5086 }
5087
5088 /* Delete all kernel routes. */
5089 void bgp_cleanup_routes(struct bgp *bgp)
5090 {
5091 afi_t afi;
5092 struct bgp_dest *dest;
5093 struct bgp_table *table;
5094
5095 for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
5096 if (afi == AFI_L2VPN)
5097 continue;
5098 bgp_cleanup_table(bgp, bgp->rib[afi][SAFI_UNICAST],
5099 SAFI_UNICAST);
5100 /*
5101 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
5102 */
5103 if (afi != AFI_L2VPN) {
5104 safi_t safi;
5105 safi = SAFI_MPLS_VPN;
5106 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
5107 dest = bgp_route_next(dest)) {
5108 table = bgp_dest_get_bgp_table_info(dest);
5109 if (table != NULL) {
5110 bgp_cleanup_table(bgp, table, safi);
5111 bgp_table_finish(&table);
5112 bgp_dest_set_bgp_table_info(dest, NULL);
5113 bgp_dest_unlock_node(dest);
5114 }
5115 }
5116 safi = SAFI_ENCAP;
5117 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
5118 dest = bgp_route_next(dest)) {
5119 table = bgp_dest_get_bgp_table_info(dest);
5120 if (table != NULL) {
5121 bgp_cleanup_table(bgp, table, safi);
5122 bgp_table_finish(&table);
5123 bgp_dest_set_bgp_table_info(dest, NULL);
5124 bgp_dest_unlock_node(dest);
5125 }
5126 }
5127 }
5128 }
5129 for (dest = bgp_table_top(bgp->rib[AFI_L2VPN][SAFI_EVPN]); dest;
5130 dest = bgp_route_next(dest)) {
5131 table = bgp_dest_get_bgp_table_info(dest);
5132 if (table != NULL) {
5133 bgp_cleanup_table(bgp, table, SAFI_EVPN);
5134 bgp_table_finish(&table);
5135 bgp_dest_set_bgp_table_info(dest, NULL);
5136 bgp_dest_unlock_node(dest);
5137 }
5138 }
5139 }
5140
5141 void bgp_reset(void)
5142 {
5143 vty_reset();
5144 bgp_zclient_reset();
5145 access_list_reset();
5146 prefix_list_reset();
5147 }
5148
5149 static int bgp_addpath_encode_rx(struct peer *peer, afi_t afi, safi_t safi)
5150 {
5151 return (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV)
5152 && CHECK_FLAG(peer->af_cap[afi][safi],
5153 PEER_CAP_ADDPATH_AF_TX_RCV));
5154 }
5155
5156 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
5157 value. */
5158 int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
5159 struct bgp_nlri *packet)
5160 {
5161 uint8_t *pnt;
5162 uint8_t *lim;
5163 struct prefix p;
5164 int psize;
5165 int ret;
5166 afi_t afi;
5167 safi_t safi;
5168 int addpath_encoded;
5169 uint32_t addpath_id;
5170
5171 pnt = packet->nlri;
5172 lim = pnt + packet->length;
5173 afi = packet->afi;
5174 safi = packet->safi;
5175 addpath_id = 0;
5176 addpath_encoded = bgp_addpath_encode_rx(peer, afi, safi);
5177
5178 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
5179 syntactic validity. If the field is syntactically incorrect,
5180 then the Error Subcode is set to Invalid Network Field. */
5181 for (; pnt < lim; pnt += psize) {
5182 /* Clear prefix structure. */
5183 memset(&p, 0, sizeof(struct prefix));
5184
5185 if (addpath_encoded) {
5186
5187 /* When packet overflow occurs return immediately. */
5188 if (pnt + BGP_ADDPATH_ID_LEN >= lim)
5189 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
5190
5191 memcpy(&addpath_id, pnt, BGP_ADDPATH_ID_LEN);
5192 addpath_id = ntohl(addpath_id);
5193 pnt += BGP_ADDPATH_ID_LEN;
5194 }
5195
5196 /* Fetch prefix length. */
5197 p.prefixlen = *pnt++;
5198 /* afi/safi validity already verified by caller,
5199 * bgp_update_receive */
5200 p.family = afi2family(afi);
5201
5202 /* Prefix length check. */
5203 if (p.prefixlen > prefix_blen(&p) * 8) {
5204 flog_err(
5205 EC_BGP_UPDATE_RCV,
5206 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
5207 peer->host, p.prefixlen, packet->afi);
5208 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH;
5209 }
5210
5211 /* Packet size overflow check. */
5212 psize = PSIZE(p.prefixlen);
5213
5214 /* When packet overflow occur return immediately. */
5215 if (pnt + psize > lim) {
5216 flog_err(
5217 EC_BGP_UPDATE_RCV,
5218 "%s [Error] Update packet error (prefix length %d overflows packet)",
5219 peer->host, p.prefixlen);
5220 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
5221 }
5222
5223 /* Defensive coding, double-check the psize fits in a struct
5224 * prefix */
5225 if (psize > (ssize_t)sizeof(p.u)) {
5226 flog_err(
5227 EC_BGP_UPDATE_RCV,
5228 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
5229 peer->host, p.prefixlen, sizeof(p.u));
5230 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
5231 }
5232
5233 /* Fetch prefix from NLRI packet. */
5234 memcpy(p.u.val, pnt, psize);
5235
5236 /* Check address. */
5237 if (afi == AFI_IP && safi == SAFI_UNICAST) {
5238 if (IN_CLASSD(ntohl(p.u.prefix4.s_addr))) {
5239 /* From RFC4271 Section 6.3:
5240 *
5241 * If a prefix in the NLRI field is semantically
5242 * incorrect
5243 * (e.g., an unexpected multicast IP address),
5244 * an error SHOULD
5245 * be logged locally, and the prefix SHOULD be
5246 * ignored.
5247 */
5248 flog_err(
5249 EC_BGP_UPDATE_RCV,
5250 "%s: IPv4 unicast NLRI is multicast address %pI4, ignoring",
5251 peer->host, &p.u.prefix4);
5252 continue;
5253 }
5254 }
5255
5256 /* Check address. */
5257 if (afi == AFI_IP6 && safi == SAFI_UNICAST) {
5258 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
5259 flog_err(
5260 EC_BGP_UPDATE_RCV,
5261 "%s: IPv6 unicast NLRI is link-local address %pI6, ignoring",
5262 peer->host, &p.u.prefix6);
5263
5264 continue;
5265 }
5266 if (IN6_IS_ADDR_MULTICAST(&p.u.prefix6)) {
5267 flog_err(
5268 EC_BGP_UPDATE_RCV,
5269 "%s: IPv6 unicast NLRI is multicast address %pI6, ignoring",
5270 peer->host, &p.u.prefix6);
5271
5272 continue;
5273 }
5274 }
5275
5276 /* Normal process. */
5277 if (attr)
5278 ret = bgp_update(peer, &p, addpath_id, attr, afi, safi,
5279 ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
5280 NULL, NULL, 0, 0, NULL);
5281 else
5282 ret = bgp_withdraw(peer, &p, addpath_id, attr, afi,
5283 safi, ZEBRA_ROUTE_BGP,
5284 BGP_ROUTE_NORMAL, NULL, NULL, 0,
5285 NULL);
5286
5287 /* Do not send BGP notification twice when maximum-prefix count
5288 * overflow. */
5289 if (CHECK_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
5290 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW;
5291
5292 /* Address family configuration mismatch. */
5293 if (ret < 0)
5294 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY;
5295 }
5296
5297 /* Packet length consistency check. */
5298 if (pnt != lim) {
5299 flog_err(
5300 EC_BGP_UPDATE_RCV,
5301 "%s [Error] Update packet error (prefix length mismatch with total length)",
5302 peer->host);
5303 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
5304 }
5305
5306 return BGP_NLRI_PARSE_OK;
5307 }
5308
5309 static struct bgp_static *bgp_static_new(void)
5310 {
5311 return XCALLOC(MTYPE_BGP_STATIC, sizeof(struct bgp_static));
5312 }
5313
5314 static void bgp_static_free(struct bgp_static *bgp_static)
5315 {
5316 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
5317 route_map_counter_decrement(bgp_static->rmap.map);
5318
5319 XFREE(MTYPE_ATTR, bgp_static->eth_s_id);
5320 XFREE(MTYPE_BGP_STATIC, bgp_static);
5321 }
5322
5323 void bgp_static_update(struct bgp *bgp, const struct prefix *p,
5324 struct bgp_static *bgp_static, afi_t afi, safi_t safi)
5325 {
5326 struct bgp_dest *dest;
5327 struct bgp_path_info *pi;
5328 struct bgp_path_info *new;
5329 struct bgp_path_info rmap_path;
5330 struct attr attr;
5331 struct attr *attr_new;
5332 route_map_result_t ret;
5333 #ifdef ENABLE_BGP_VNC
5334 int vnc_implicit_withdraw = 0;
5335 #endif
5336
5337 assert(bgp_static);
5338
5339 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
5340
5341 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
5342
5343 attr.nexthop = bgp_static->igpnexthop;
5344 attr.med = bgp_static->igpmetric;
5345 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
5346
5347 if (bgp_static->atomic)
5348 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
5349
5350 /* Store label index, if required. */
5351 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX) {
5352 attr.label_index = bgp_static->label_index;
5353 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
5354 }
5355
5356 /* Apply route-map. */
5357 if (bgp_static->rmap.name) {
5358 struct attr attr_tmp = attr;
5359
5360 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
5361 rmap_path.peer = bgp->peer_self;
5362 rmap_path.attr = &attr_tmp;
5363
5364 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
5365
5366 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
5367
5368 bgp->peer_self->rmap_type = 0;
5369
5370 if (ret == RMAP_DENYMATCH) {
5371 /* Free uninterned attribute. */
5372 bgp_attr_flush(&attr_tmp);
5373
5374 /* Unintern original. */
5375 aspath_unintern(&attr.aspath);
5376 bgp_static_withdraw(bgp, p, afi, safi);
5377 return;
5378 }
5379
5380 if (bgp_in_graceful_shutdown(bgp))
5381 bgp_attr_add_gshut_community(&attr_tmp);
5382
5383 attr_new = bgp_attr_intern(&attr_tmp);
5384 } else {
5385
5386 if (bgp_in_graceful_shutdown(bgp))
5387 bgp_attr_add_gshut_community(&attr);
5388
5389 attr_new = bgp_attr_intern(&attr);
5390 }
5391
5392 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
5393 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5394 && pi->sub_type == BGP_ROUTE_STATIC)
5395 break;
5396
5397 if (pi) {
5398 if (attrhash_cmp(pi->attr, attr_new)
5399 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
5400 && !CHECK_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS)) {
5401 bgp_dest_unlock_node(dest);
5402 bgp_attr_unintern(&attr_new);
5403 aspath_unintern(&attr.aspath);
5404 return;
5405 } else {
5406 /* The attribute is changed. */
5407 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
5408
5409 /* Rewrite BGP route information. */
5410 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
5411 bgp_path_info_restore(dest, pi);
5412 else
5413 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
5414 #ifdef ENABLE_BGP_VNC
5415 if ((afi == AFI_IP || afi == AFI_IP6)
5416 && (safi == SAFI_UNICAST)) {
5417 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
5418 /*
5419 * Implicit withdraw case.
5420 * We have to do this before pi is
5421 * changed
5422 */
5423 ++vnc_implicit_withdraw;
5424 vnc_import_bgp_del_route(bgp, p, pi);
5425 vnc_import_bgp_exterior_del_route(
5426 bgp, p, pi);
5427 }
5428 }
5429 #endif
5430 bgp_attr_unintern(&pi->attr);
5431 pi->attr = attr_new;
5432 pi->uptime = bgp_clock();
5433 #ifdef ENABLE_BGP_VNC
5434 if ((afi == AFI_IP || afi == AFI_IP6)
5435 && (safi == SAFI_UNICAST)) {
5436 if (vnc_implicit_withdraw) {
5437 vnc_import_bgp_add_route(bgp, p, pi);
5438 vnc_import_bgp_exterior_add_route(
5439 bgp, p, pi);
5440 }
5441 }
5442 #endif
5443
5444 /* Nexthop reachability check. */
5445 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
5446 && (safi == SAFI_UNICAST
5447 || safi == SAFI_LABELED_UNICAST)) {
5448
5449 struct bgp *bgp_nexthop = bgp;
5450
5451 if (pi->extra && pi->extra->bgp_orig)
5452 bgp_nexthop = pi->extra->bgp_orig;
5453
5454 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop,
5455 afi, safi, pi, NULL,
5456 0))
5457 bgp_path_info_set_flag(dest, pi,
5458 BGP_PATH_VALID);
5459 else {
5460 if (BGP_DEBUG(nht, NHT)) {
5461 char buf1[INET6_ADDRSTRLEN];
5462 inet_ntop(p->family,
5463 &p->u.prefix, buf1,
5464 INET6_ADDRSTRLEN);
5465 zlog_debug(
5466 "%s(%s): Route not in table, not advertising",
5467 __func__, buf1);
5468 }
5469 bgp_path_info_unset_flag(
5470 dest, pi, BGP_PATH_VALID);
5471 }
5472 } else {
5473 /* Delete the NHT structure if any, if we're
5474 * toggling between
5475 * enabling/disabling import check. We
5476 * deregister the route
5477 * from NHT to avoid overloading NHT and the
5478 * process interaction
5479 */
5480 bgp_unlink_nexthop(pi);
5481 bgp_path_info_set_flag(dest, pi,
5482 BGP_PATH_VALID);
5483 }
5484 /* Process change. */
5485 bgp_aggregate_increment(bgp, p, pi, afi, safi);
5486 bgp_process(bgp, dest, afi, safi);
5487
5488 if (SAFI_UNICAST == safi
5489 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5490 || bgp->inst_type
5491 == BGP_INSTANCE_TYPE_DEFAULT)) {
5492 vpn_leak_from_vrf_update(bgp_get_default(), bgp,
5493 pi);
5494 }
5495
5496 bgp_dest_unlock_node(dest);
5497 aspath_unintern(&attr.aspath);
5498 return;
5499 }
5500 }
5501
5502 /* Make new BGP info. */
5503 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
5504 attr_new, dest);
5505 /* Nexthop reachability check. */
5506 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
5507 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
5508 if (bgp_find_or_add_nexthop(bgp, bgp, afi, safi, new, NULL, 0))
5509 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
5510 else {
5511 if (BGP_DEBUG(nht, NHT)) {
5512 char buf1[INET6_ADDRSTRLEN];
5513 inet_ntop(p->family, &p->u.prefix, buf1,
5514 INET6_ADDRSTRLEN);
5515 zlog_debug(
5516 "%s(%s): Route not in table, not advertising",
5517 __func__, buf1);
5518 }
5519 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
5520 }
5521 } else {
5522 /* Delete the NHT structure if any, if we're toggling between
5523 * enabling/disabling import check. We deregister the route
5524 * from NHT to avoid overloading NHT and the process interaction
5525 */
5526 bgp_unlink_nexthop(new);
5527
5528 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
5529 }
5530
5531 /* Aggregate address increment. */
5532 bgp_aggregate_increment(bgp, p, new, afi, safi);
5533
5534 /* Register new BGP information. */
5535 bgp_path_info_add(dest, new);
5536
5537 /* route_node_get lock */
5538 bgp_dest_unlock_node(dest);
5539
5540 /* Process change. */
5541 bgp_process(bgp, dest, afi, safi);
5542
5543 if (SAFI_UNICAST == safi
5544 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5545 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
5546 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
5547 }
5548
5549 /* Unintern original. */
5550 aspath_unintern(&attr.aspath);
5551 }
5552
5553 void bgp_static_withdraw(struct bgp *bgp, const struct prefix *p, afi_t afi,
5554 safi_t safi)
5555 {
5556 struct bgp_dest *dest;
5557 struct bgp_path_info *pi;
5558
5559 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
5560
5561 /* Check selected route and self inserted route. */
5562 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
5563 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5564 && pi->sub_type == BGP_ROUTE_STATIC)
5565 break;
5566
5567 /* Withdraw static BGP route from routing table. */
5568 if (pi) {
5569 if (SAFI_UNICAST == safi
5570 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5571 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
5572 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
5573 }
5574 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
5575 bgp_unlink_nexthop(pi);
5576 bgp_path_info_delete(dest, pi);
5577 bgp_process(bgp, dest, afi, safi);
5578 }
5579
5580 /* Unlock bgp_node_lookup. */
5581 bgp_dest_unlock_node(dest);
5582 }
5583
5584 /*
5585 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
5586 */
5587 static void bgp_static_withdraw_safi(struct bgp *bgp, const struct prefix *p,
5588 afi_t afi, safi_t safi,
5589 struct prefix_rd *prd)
5590 {
5591 struct bgp_dest *dest;
5592 struct bgp_path_info *pi;
5593
5594 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
5595
5596 /* Check selected route and self inserted route. */
5597 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
5598 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5599 && pi->sub_type == BGP_ROUTE_STATIC)
5600 break;
5601
5602 /* Withdraw static BGP route from routing table. */
5603 if (pi) {
5604 #ifdef ENABLE_BGP_VNC
5605 rfapiProcessWithdraw(
5606 pi->peer, NULL, p, prd, pi->attr, afi, safi, pi->type,
5607 1); /* Kill, since it is an administrative change */
5608 #endif
5609 if (SAFI_MPLS_VPN == safi
5610 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
5611 vpn_leak_to_vrf_withdraw(bgp, pi);
5612 }
5613 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
5614 bgp_path_info_delete(dest, pi);
5615 bgp_process(bgp, dest, afi, safi);
5616 }
5617
5618 /* Unlock bgp_node_lookup. */
5619 bgp_dest_unlock_node(dest);
5620 }
5621
5622 static void bgp_static_update_safi(struct bgp *bgp, const struct prefix *p,
5623 struct bgp_static *bgp_static, afi_t afi,
5624 safi_t safi)
5625 {
5626 struct bgp_dest *dest;
5627 struct bgp_path_info *new;
5628 struct attr *attr_new;
5629 struct attr attr = {0};
5630 struct bgp_path_info *pi;
5631 #ifdef ENABLE_BGP_VNC
5632 mpls_label_t label = 0;
5633 #endif
5634 uint32_t num_labels = 0;
5635 union gw_addr add;
5636
5637 assert(bgp_static);
5638
5639 if (bgp_static->label != MPLS_INVALID_LABEL)
5640 num_labels = 1;
5641 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p,
5642 &bgp_static->prd);
5643
5644 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
5645
5646 attr.nexthop = bgp_static->igpnexthop;
5647 attr.med = bgp_static->igpmetric;
5648 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
5649
5650 if ((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN)
5651 || (safi == SAFI_ENCAP)) {
5652 if (afi == AFI_IP) {
5653 attr.mp_nexthop_global_in = bgp_static->igpnexthop;
5654 attr.mp_nexthop_len = IPV4_MAX_BYTELEN;
5655 }
5656 }
5657 if (afi == AFI_L2VPN) {
5658 if (bgp_static->gatewayIp.family == AF_INET)
5659 add.ipv4.s_addr =
5660 bgp_static->gatewayIp.u.prefix4.s_addr;
5661 else if (bgp_static->gatewayIp.family == AF_INET6)
5662 memcpy(&(add.ipv6), &(bgp_static->gatewayIp.u.prefix6),
5663 sizeof(struct in6_addr));
5664 memcpy(&attr.esi, bgp_static->eth_s_id, sizeof(esi_t));
5665 if (bgp_static->encap_tunneltype == BGP_ENCAP_TYPE_VXLAN) {
5666 struct bgp_encap_type_vxlan bet;
5667 memset(&bet, 0, sizeof(struct bgp_encap_type_vxlan));
5668 bet.vnid = p->u.prefix_evpn.prefix_addr.eth_tag;
5669 bgp_encap_type_vxlan_to_tlv(&bet, &attr);
5670 }
5671 if (bgp_static->router_mac) {
5672 bgp_add_routermac_ecom(&attr, bgp_static->router_mac);
5673 }
5674 }
5675 /* Apply route-map. */
5676 if (bgp_static->rmap.name) {
5677 struct attr attr_tmp = attr;
5678 struct bgp_path_info rmap_path;
5679 route_map_result_t ret;
5680
5681 rmap_path.peer = bgp->peer_self;
5682 rmap_path.attr = &attr_tmp;
5683
5684 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
5685
5686 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
5687
5688 bgp->peer_self->rmap_type = 0;
5689
5690 if (ret == RMAP_DENYMATCH) {
5691 /* Free uninterned attribute. */
5692 bgp_attr_flush(&attr_tmp);
5693
5694 /* Unintern original. */
5695 aspath_unintern(&attr.aspath);
5696 bgp_static_withdraw_safi(bgp, p, afi, safi,
5697 &bgp_static->prd);
5698 return;
5699 }
5700
5701 attr_new = bgp_attr_intern(&attr_tmp);
5702 } else {
5703 attr_new = bgp_attr_intern(&attr);
5704 }
5705
5706 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
5707 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5708 && pi->sub_type == BGP_ROUTE_STATIC)
5709 break;
5710
5711 if (pi) {
5712 memset(&add, 0, sizeof(union gw_addr));
5713 if (attrhash_cmp(pi->attr, attr_new)
5714 && overlay_index_equal(afi, pi, &add)
5715 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
5716 bgp_dest_unlock_node(dest);
5717 bgp_attr_unintern(&attr_new);
5718 aspath_unintern(&attr.aspath);
5719 return;
5720 } else {
5721 /* The attribute is changed. */
5722 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
5723
5724 /* Rewrite BGP route information. */
5725 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
5726 bgp_path_info_restore(dest, pi);
5727 else
5728 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
5729 bgp_attr_unintern(&pi->attr);
5730 pi->attr = attr_new;
5731 pi->uptime = bgp_clock();
5732 #ifdef ENABLE_BGP_VNC
5733 if (pi->extra)
5734 label = decode_label(&pi->extra->label[0]);
5735 #endif
5736
5737 /* Process change. */
5738 bgp_aggregate_increment(bgp, p, pi, afi, safi);
5739 bgp_process(bgp, dest, afi, safi);
5740
5741 if (SAFI_MPLS_VPN == safi
5742 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
5743 vpn_leak_to_vrf_update(bgp, pi);
5744 }
5745 #ifdef ENABLE_BGP_VNC
5746 rfapiProcessUpdate(pi->peer, NULL, p, &bgp_static->prd,
5747 pi->attr, afi, safi, pi->type,
5748 pi->sub_type, &label);
5749 #endif
5750 bgp_dest_unlock_node(dest);
5751 aspath_unintern(&attr.aspath);
5752 return;
5753 }
5754 }
5755
5756
5757 /* Make new BGP info. */
5758 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
5759 attr_new, dest);
5760 SET_FLAG(new->flags, BGP_PATH_VALID);
5761 new->extra = bgp_path_info_extra_new();
5762 if (num_labels) {
5763 new->extra->label[0] = bgp_static->label;
5764 new->extra->num_labels = num_labels;
5765 }
5766 #ifdef ENABLE_BGP_VNC
5767 label = decode_label(&bgp_static->label);
5768 #endif
5769
5770 /* Aggregate address increment. */
5771 bgp_aggregate_increment(bgp, p, new, afi, safi);
5772
5773 /* Register new BGP information. */
5774 bgp_path_info_add(dest, new);
5775 /* route_node_get lock */
5776 bgp_dest_unlock_node(dest);
5777
5778 /* Process change. */
5779 bgp_process(bgp, dest, afi, safi);
5780
5781 if (SAFI_MPLS_VPN == safi
5782 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
5783 vpn_leak_to_vrf_update(bgp, new);
5784 }
5785 #ifdef ENABLE_BGP_VNC
5786 rfapiProcessUpdate(new->peer, NULL, p, &bgp_static->prd, new->attr, afi,
5787 safi, new->type, new->sub_type, &label);
5788 #endif
5789
5790 /* Unintern original. */
5791 aspath_unintern(&attr.aspath);
5792 }
5793
5794 /* Configure static BGP network. When user don't run zebra, static
5795 route should be installed as valid. */
5796 int bgp_static_set(struct bgp *bgp, const char *negate, struct prefix *pfx,
5797 afi_t afi, safi_t safi, const char *rmap, int backdoor,
5798 uint32_t label_index, char *errmsg, size_t errmsg_len)
5799 {
5800 struct prefix p;
5801 struct bgp_static *bgp_static;
5802 struct bgp_dest *dest;
5803 uint8_t need_update = 0;
5804
5805 prefix_copy(&p, pfx);
5806 apply_mask(&p);
5807
5808 if (negate) {
5809
5810 /* Set BGP static route configuration. */
5811 dest = bgp_node_lookup(bgp->route[afi][safi], &p);
5812
5813 if (!dest) {
5814 snprintf(errmsg, errmsg_len,
5815 "Can't find static route specified\n");
5816 return -1;
5817 }
5818
5819 bgp_static = bgp_dest_get_bgp_static_info(dest);
5820
5821 if ((label_index != BGP_INVALID_LABEL_INDEX)
5822 && (label_index != bgp_static->label_index)) {
5823 snprintf(errmsg, errmsg_len,
5824 "label-index doesn't match static route\n");
5825 return -1;
5826 }
5827
5828 if ((rmap && bgp_static->rmap.name)
5829 && strcmp(rmap, bgp_static->rmap.name)) {
5830 snprintf(errmsg, errmsg_len,
5831 "route-map name doesn't match static route\n");
5832 return -1;
5833 }
5834
5835 /* Update BGP RIB. */
5836 if (!bgp_static->backdoor)
5837 bgp_static_withdraw(bgp, &p, afi, safi);
5838
5839 /* Clear configuration. */
5840 bgp_static_free(bgp_static);
5841 bgp_dest_set_bgp_static_info(dest, NULL);
5842 bgp_dest_unlock_node(dest);
5843 bgp_dest_unlock_node(dest);
5844 } else {
5845
5846 /* Set BGP static route configuration. */
5847 dest = bgp_node_get(bgp->route[afi][safi], &p);
5848 bgp_static = bgp_dest_get_bgp_static_info(dest);
5849 if (bgp_static) {
5850 /* Configuration change. */
5851 /* Label index cannot be changed. */
5852 if (bgp_static->label_index != label_index) {
5853 snprintf(errmsg, errmsg_len,
5854 "cannot change label-index\n");
5855 return -1;
5856 }
5857
5858 /* Check previous routes are installed into BGP. */
5859 if (bgp_static->valid
5860 && bgp_static->backdoor != backdoor)
5861 need_update = 1;
5862
5863 bgp_static->backdoor = backdoor;
5864
5865 if (rmap) {
5866 XFREE(MTYPE_ROUTE_MAP_NAME,
5867 bgp_static->rmap.name);
5868 route_map_counter_decrement(
5869 bgp_static->rmap.map);
5870 bgp_static->rmap.name =
5871 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
5872 bgp_static->rmap.map =
5873 route_map_lookup_by_name(rmap);
5874 route_map_counter_increment(
5875 bgp_static->rmap.map);
5876 } else {
5877 XFREE(MTYPE_ROUTE_MAP_NAME,
5878 bgp_static->rmap.name);
5879 route_map_counter_decrement(
5880 bgp_static->rmap.map);
5881 bgp_static->rmap.map = NULL;
5882 bgp_static->valid = 0;
5883 }
5884 bgp_dest_unlock_node(dest);
5885 } else {
5886 /* New configuration. */
5887 bgp_static = bgp_static_new();
5888 bgp_static->backdoor = backdoor;
5889 bgp_static->valid = 0;
5890 bgp_static->igpmetric = 0;
5891 bgp_static->igpnexthop.s_addr = INADDR_ANY;
5892 bgp_static->label_index = label_index;
5893
5894 if (rmap) {
5895 XFREE(MTYPE_ROUTE_MAP_NAME,
5896 bgp_static->rmap.name);
5897 route_map_counter_decrement(
5898 bgp_static->rmap.map);
5899 bgp_static->rmap.name =
5900 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
5901 bgp_static->rmap.map =
5902 route_map_lookup_by_name(rmap);
5903 route_map_counter_increment(
5904 bgp_static->rmap.map);
5905 }
5906 bgp_dest_set_bgp_static_info(dest, bgp_static);
5907 }
5908
5909 bgp_static->valid = 1;
5910 if (need_update)
5911 bgp_static_withdraw(bgp, &p, afi, safi);
5912
5913 if (!bgp_static->backdoor)
5914 bgp_static_update(bgp, &p, bgp_static, afi, safi);
5915 }
5916
5917 return 0;
5918 }
5919
5920 void bgp_static_add(struct bgp *bgp)
5921 {
5922 afi_t afi;
5923 safi_t safi;
5924 struct bgp_dest *dest;
5925 struct bgp_dest *rm;
5926 struct bgp_table *table;
5927 struct bgp_static *bgp_static;
5928
5929 FOREACH_AFI_SAFI (afi, safi)
5930 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
5931 dest = bgp_route_next(dest)) {
5932 if (!bgp_dest_has_bgp_path_info_data(dest))
5933 continue;
5934
5935 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
5936 || (safi == SAFI_EVPN)) {
5937 table = bgp_dest_get_bgp_table_info(dest);
5938
5939 for (rm = bgp_table_top(table); rm;
5940 rm = bgp_route_next(rm)) {
5941 bgp_static =
5942 bgp_dest_get_bgp_static_info(
5943 rm);
5944 bgp_static_update_safi(
5945 bgp, bgp_dest_get_prefix(rm),
5946 bgp_static, afi, safi);
5947 }
5948 } else {
5949 bgp_static_update(
5950 bgp, bgp_dest_get_prefix(dest),
5951 bgp_dest_get_bgp_static_info(dest), afi,
5952 safi);
5953 }
5954 }
5955 }
5956
5957 /* Called from bgp_delete(). Delete all static routes from the BGP
5958 instance. */
5959 void bgp_static_delete(struct bgp *bgp)
5960 {
5961 afi_t afi;
5962 safi_t safi;
5963 struct bgp_dest *dest;
5964 struct bgp_dest *rm;
5965 struct bgp_table *table;
5966 struct bgp_static *bgp_static;
5967
5968 FOREACH_AFI_SAFI (afi, safi)
5969 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
5970 dest = bgp_route_next(dest)) {
5971 if (!bgp_dest_has_bgp_path_info_data(dest))
5972 continue;
5973
5974 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
5975 || (safi == SAFI_EVPN)) {
5976 table = bgp_dest_get_bgp_table_info(dest);
5977
5978 for (rm = bgp_table_top(table); rm;
5979 rm = bgp_route_next(rm)) {
5980 bgp_static =
5981 bgp_dest_get_bgp_static_info(
5982 rm);
5983 if (!bgp_static)
5984 continue;
5985
5986 bgp_static_withdraw_safi(
5987 bgp, bgp_dest_get_prefix(rm),
5988 AFI_IP, safi,
5989 (struct prefix_rd *)
5990 bgp_dest_get_prefix(
5991 dest));
5992 bgp_static_free(bgp_static);
5993 bgp_dest_set_bgp_static_info(rm,
5994 NULL);
5995 bgp_dest_unlock_node(rm);
5996 }
5997 } else {
5998 bgp_static = bgp_dest_get_bgp_static_info(dest);
5999 bgp_static_withdraw(bgp,
6000 bgp_dest_get_prefix(dest),
6001 afi, safi);
6002 bgp_static_free(bgp_static);
6003 bgp_dest_set_bgp_static_info(dest, NULL);
6004 bgp_dest_unlock_node(dest);
6005 }
6006 }
6007 }
6008
6009 void bgp_static_redo_import_check(struct bgp *bgp)
6010 {
6011 afi_t afi;
6012 safi_t safi;
6013 struct bgp_dest *dest;
6014 struct bgp_dest *rm;
6015 struct bgp_table *table;
6016 struct bgp_static *bgp_static;
6017
6018 /* Use this flag to force reprocessing of the route */
6019 SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
6020 FOREACH_AFI_SAFI (afi, safi) {
6021 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6022 dest = bgp_route_next(dest)) {
6023 if (!bgp_dest_has_bgp_path_info_data(dest))
6024 continue;
6025
6026 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6027 || (safi == SAFI_EVPN)) {
6028 table = bgp_dest_get_bgp_table_info(dest);
6029
6030 for (rm = bgp_table_top(table); rm;
6031 rm = bgp_route_next(rm)) {
6032 bgp_static =
6033 bgp_dest_get_bgp_static_info(
6034 rm);
6035 bgp_static_update_safi(
6036 bgp, bgp_dest_get_prefix(rm),
6037 bgp_static, afi, safi);
6038 }
6039 } else {
6040 bgp_static = bgp_dest_get_bgp_static_info(dest);
6041 bgp_static_update(bgp,
6042 bgp_dest_get_prefix(dest),
6043 bgp_static, afi, safi);
6044 }
6045 }
6046 }
6047 UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
6048 }
6049
6050 static void bgp_purge_af_static_redist_routes(struct bgp *bgp, afi_t afi,
6051 safi_t safi)
6052 {
6053 struct bgp_table *table;
6054 struct bgp_dest *dest;
6055 struct bgp_path_info *pi;
6056
6057 /* Do not install the aggregate route if BGP is in the
6058 * process of termination.
6059 */
6060 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
6061 || (bgp->peer_self == NULL))
6062 return;
6063
6064 table = bgp->rib[afi][safi];
6065 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6066 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
6067 if (pi->peer == bgp->peer_self
6068 && ((pi->type == ZEBRA_ROUTE_BGP
6069 && pi->sub_type == BGP_ROUTE_STATIC)
6070 || (pi->type != ZEBRA_ROUTE_BGP
6071 && pi->sub_type
6072 == BGP_ROUTE_REDISTRIBUTE))) {
6073 bgp_aggregate_decrement(
6074 bgp, bgp_dest_get_prefix(dest), pi, afi,
6075 safi);
6076 bgp_unlink_nexthop(pi);
6077 bgp_path_info_delete(dest, pi);
6078 bgp_process(bgp, dest, afi, safi);
6079 }
6080 }
6081 }
6082 }
6083
6084 /*
6085 * Purge all networks and redistributed routes from routing table.
6086 * Invoked upon the instance going down.
6087 */
6088 void bgp_purge_static_redist_routes(struct bgp *bgp)
6089 {
6090 afi_t afi;
6091 safi_t safi;
6092
6093 FOREACH_AFI_SAFI (afi, safi)
6094 bgp_purge_af_static_redist_routes(bgp, afi, safi);
6095 }
6096
6097 /*
6098 * gpz 110624
6099 * Currently this is used to set static routes for VPN and ENCAP.
6100 * I think it can probably be factored with bgp_static_set.
6101 */
6102 int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty,
6103 const char *ip_str, const char *rd_str,
6104 const char *label_str, const char *rmap_str,
6105 int evpn_type, const char *esi, const char *gwip,
6106 const char *ethtag, const char *routermac)
6107 {
6108 VTY_DECLVAR_CONTEXT(bgp, bgp);
6109 int ret;
6110 struct prefix p;
6111 struct prefix_rd prd;
6112 struct bgp_dest *pdest;
6113 struct bgp_dest *dest;
6114 struct bgp_table *table;
6115 struct bgp_static *bgp_static;
6116 mpls_label_t label = MPLS_INVALID_LABEL;
6117 struct prefix gw_ip;
6118
6119 /* validate ip prefix */
6120 ret = str2prefix(ip_str, &p);
6121 if (!ret) {
6122 vty_out(vty, "%% Malformed prefix\n");
6123 return CMD_WARNING_CONFIG_FAILED;
6124 }
6125 apply_mask(&p);
6126 if ((afi == AFI_L2VPN)
6127 && (bgp_build_evpn_prefix(evpn_type,
6128 ethtag != NULL ? atol(ethtag) : 0, &p))) {
6129 vty_out(vty, "%% L2VPN prefix could not be forged\n");
6130 return CMD_WARNING_CONFIG_FAILED;
6131 }
6132
6133 ret = str2prefix_rd(rd_str, &prd);
6134 if (!ret) {
6135 vty_out(vty, "%% Malformed rd\n");
6136 return CMD_WARNING_CONFIG_FAILED;
6137 }
6138
6139 if (label_str) {
6140 unsigned long label_val;
6141 label_val = strtoul(label_str, NULL, 10);
6142 encode_label(label_val, &label);
6143 }
6144
6145 if (safi == SAFI_EVPN) {
6146 if (esi && str2esi(esi, NULL) == 0) {
6147 vty_out(vty, "%% Malformed ESI\n");
6148 return CMD_WARNING_CONFIG_FAILED;
6149 }
6150 if (routermac && prefix_str2mac(routermac, NULL) == 0) {
6151 vty_out(vty, "%% Malformed Router MAC\n");
6152 return CMD_WARNING_CONFIG_FAILED;
6153 }
6154 if (gwip) {
6155 memset(&gw_ip, 0, sizeof(struct prefix));
6156 ret = str2prefix(gwip, &gw_ip);
6157 if (!ret) {
6158 vty_out(vty, "%% Malformed GatewayIp\n");
6159 return CMD_WARNING_CONFIG_FAILED;
6160 }
6161 if ((gw_ip.family == AF_INET
6162 && is_evpn_prefix_ipaddr_v6(
6163 (struct prefix_evpn *)&p))
6164 || (gw_ip.family == AF_INET6
6165 && is_evpn_prefix_ipaddr_v4(
6166 (struct prefix_evpn *)&p))) {
6167 vty_out(vty,
6168 "%% GatewayIp family differs with IP prefix\n");
6169 return CMD_WARNING_CONFIG_FAILED;
6170 }
6171 }
6172 }
6173 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
6174 if (!bgp_dest_has_bgp_path_info_data(pdest))
6175 bgp_dest_set_bgp_table_info(pdest,
6176 bgp_table_init(bgp, afi, safi));
6177 table = bgp_dest_get_bgp_table_info(pdest);
6178
6179 dest = bgp_node_get(table, &p);
6180
6181 if (bgp_dest_has_bgp_path_info_data(dest)) {
6182 vty_out(vty, "%% Same network configuration exists\n");
6183 bgp_dest_unlock_node(dest);
6184 } else {
6185 /* New configuration. */
6186 bgp_static = bgp_static_new();
6187 bgp_static->backdoor = 0;
6188 bgp_static->valid = 0;
6189 bgp_static->igpmetric = 0;
6190 bgp_static->igpnexthop.s_addr = INADDR_ANY;
6191 bgp_static->label = label;
6192 bgp_static->prd = prd;
6193
6194 if (rmap_str) {
6195 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
6196 route_map_counter_decrement(bgp_static->rmap.map);
6197 bgp_static->rmap.name =
6198 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_str);
6199 bgp_static->rmap.map =
6200 route_map_lookup_by_name(rmap_str);
6201 route_map_counter_increment(bgp_static->rmap.map);
6202 }
6203
6204 if (safi == SAFI_EVPN) {
6205 if (esi) {
6206 bgp_static->eth_s_id =
6207 XCALLOC(MTYPE_ATTR,
6208 sizeof(esi_t));
6209 str2esi(esi, bgp_static->eth_s_id);
6210 }
6211 if (routermac) {
6212 bgp_static->router_mac =
6213 XCALLOC(MTYPE_ATTR, ETH_ALEN + 1);
6214 (void)prefix_str2mac(routermac,
6215 bgp_static->router_mac);
6216 }
6217 if (gwip)
6218 prefix_copy(&bgp_static->gatewayIp, &gw_ip);
6219 }
6220 bgp_dest_set_bgp_static_info(dest, bgp_static);
6221
6222 bgp_static->valid = 1;
6223 bgp_static_update_safi(bgp, &p, bgp_static, afi, safi);
6224 }
6225
6226 return CMD_SUCCESS;
6227 }
6228
6229 /* Configure static BGP network. */
6230 int bgp_static_unset_safi(afi_t afi, safi_t safi, struct vty *vty,
6231 const char *ip_str, const char *rd_str,
6232 const char *label_str, int evpn_type, const char *esi,
6233 const char *gwip, const char *ethtag)
6234 {
6235 VTY_DECLVAR_CONTEXT(bgp, bgp);
6236 int ret;
6237 struct prefix p;
6238 struct prefix_rd prd;
6239 struct bgp_dest *pdest;
6240 struct bgp_dest *dest;
6241 struct bgp_table *table;
6242 struct bgp_static *bgp_static;
6243 mpls_label_t label = MPLS_INVALID_LABEL;
6244
6245 /* Convert IP prefix string to struct prefix. */
6246 ret = str2prefix(ip_str, &p);
6247 if (!ret) {
6248 vty_out(vty, "%% Malformed prefix\n");
6249 return CMD_WARNING_CONFIG_FAILED;
6250 }
6251 apply_mask(&p);
6252 if ((afi == AFI_L2VPN)
6253 && (bgp_build_evpn_prefix(evpn_type,
6254 ethtag != NULL ? atol(ethtag) : 0, &p))) {
6255 vty_out(vty, "%% L2VPN prefix could not be forged\n");
6256 return CMD_WARNING_CONFIG_FAILED;
6257 }
6258 ret = str2prefix_rd(rd_str, &prd);
6259 if (!ret) {
6260 vty_out(vty, "%% Malformed rd\n");
6261 return CMD_WARNING_CONFIG_FAILED;
6262 }
6263
6264 if (label_str) {
6265 unsigned long label_val;
6266 label_val = strtoul(label_str, NULL, 10);
6267 encode_label(label_val, &label);
6268 }
6269
6270 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
6271 if (!bgp_dest_has_bgp_path_info_data(pdest))
6272 bgp_dest_set_bgp_table_info(pdest,
6273 bgp_table_init(bgp, afi, safi));
6274 else
6275 bgp_dest_unlock_node(pdest);
6276 table = bgp_dest_get_bgp_table_info(pdest);
6277
6278 dest = bgp_node_lookup(table, &p);
6279
6280 if (dest) {
6281 bgp_static_withdraw_safi(bgp, &p, afi, safi, &prd);
6282
6283 bgp_static = bgp_dest_get_bgp_static_info(dest);
6284 bgp_static_free(bgp_static);
6285 bgp_dest_set_bgp_static_info(dest, NULL);
6286 bgp_dest_unlock_node(dest);
6287 bgp_dest_unlock_node(dest);
6288 } else
6289 vty_out(vty, "%% Can't find the route\n");
6290
6291 return CMD_SUCCESS;
6292 }
6293
6294 static int bgp_table_map_set(struct vty *vty, afi_t afi, safi_t safi,
6295 const char *rmap_name)
6296 {
6297 VTY_DECLVAR_CONTEXT(bgp, bgp);
6298 struct bgp_rmap *rmap;
6299
6300 rmap = &bgp->table_map[afi][safi];
6301 if (rmap_name) {
6302 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
6303 route_map_counter_decrement(rmap->map);
6304 rmap->name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name);
6305 rmap->map = route_map_lookup_by_name(rmap_name);
6306 route_map_counter_increment(rmap->map);
6307 } else {
6308 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
6309 route_map_counter_decrement(rmap->map);
6310 rmap->map = NULL;
6311 }
6312
6313 if (bgp_fibupd_safi(safi))
6314 bgp_zebra_announce_table(bgp, afi, safi);
6315
6316 return CMD_SUCCESS;
6317 }
6318
6319 static int bgp_table_map_unset(struct vty *vty, afi_t afi, safi_t safi,
6320 const char *rmap_name)
6321 {
6322 VTY_DECLVAR_CONTEXT(bgp, bgp);
6323 struct bgp_rmap *rmap;
6324
6325 rmap = &bgp->table_map[afi][safi];
6326 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
6327 route_map_counter_decrement(rmap->map);
6328 rmap->map = NULL;
6329
6330 if (bgp_fibupd_safi(safi))
6331 bgp_zebra_announce_table(bgp, afi, safi);
6332
6333 return CMD_SUCCESS;
6334 }
6335
6336 void bgp_config_write_table_map(struct vty *vty, struct bgp *bgp, afi_t afi,
6337 safi_t safi)
6338 {
6339 if (bgp->table_map[afi][safi].name) {
6340 vty_out(vty, " table-map %s\n",
6341 bgp->table_map[afi][safi].name);
6342 }
6343 }
6344
6345 DEFUN (bgp_table_map,
6346 bgp_table_map_cmd,
6347 "table-map WORD",
6348 "BGP table to RIB route download filter\n"
6349 "Name of the route map\n")
6350 {
6351 int idx_word = 1;
6352 return bgp_table_map_set(vty, bgp_node_afi(vty), bgp_node_safi(vty),
6353 argv[idx_word]->arg);
6354 }
6355 DEFUN (no_bgp_table_map,
6356 no_bgp_table_map_cmd,
6357 "no table-map WORD",
6358 NO_STR
6359 "BGP table to RIB route download filter\n"
6360 "Name of the route map\n")
6361 {
6362 int idx_word = 2;
6363 return bgp_table_map_unset(vty, bgp_node_afi(vty), bgp_node_safi(vty),
6364 argv[idx_word]->arg);
6365 }
6366
6367 DEFPY_YANG (bgp_network, bgp_network_cmd,
6368 "[no] network \
6369 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
6370 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
6371 backdoor$backdoor}]",
6372 NO_STR
6373 "Specify a network to announce via BGP\n"
6374 "IPv4 prefix\n"
6375 "Network number\n"
6376 "Network mask\n"
6377 "Network mask\n"
6378 "Route-map to modify the attributes\n"
6379 "Name of the route map\n"
6380 "Label index to associate with the prefix\n"
6381 "Label index value\n"
6382 "Specify a BGP backdoor route\n")
6383 {
6384 char addr_prefix_str[PREFIX_STRLEN];
6385 char base_xpath[XPATH_MAXLEN];
6386 afi_t afi;
6387 safi_t safi;
6388
6389 if (address_str) {
6390 int ret;
6391
6392 ret = netmask_str2prefix_str(address_str, netmask_str,
6393 addr_prefix_str,
6394 sizeof(addr_prefix_str));
6395 if (!ret) {
6396 vty_out(vty, "%% Inconsistent address and mask\n");
6397 return CMD_WARNING_CONFIG_FAILED;
6398 }
6399 }
6400
6401 afi = bgp_node_afi(vty);
6402 safi = bgp_node_safi(vty);
6403
6404 if (no) {
6405 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
6406 } else {
6407 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
6408
6409 if (map_name)
6410 nb_cli_enqueue_change(vty, "./rmap-policy-export",
6411 NB_OP_CREATE, map_name);
6412 else
6413 nb_cli_enqueue_change(vty, "./rmap-policy-export",
6414 NB_OP_DESTROY, NULL);
6415
6416 if (label_index_str)
6417 nb_cli_enqueue_change(vty, "./label-index",
6418 NB_OP_MODIFY, label_index_str);
6419
6420 nb_cli_enqueue_change(vty, "./backdoor", NB_OP_MODIFY,
6421 backdoor ? "true" : "false");
6422 }
6423
6424 snprintf(
6425 base_xpath, sizeof(base_xpath),
6426 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/network-config[prefix='%s']",
6427 yang_afi_safi_value2identity(afi, safi),
6428 bgp_afi_safi_get_container_str(afi, safi),
6429 address_str ? addr_prefix_str : prefix_str);
6430
6431 return nb_cli_apply_changes(vty, base_xpath);
6432 }
6433
6434 DEFPY_YANG (ipv6_bgp_network,
6435 ipv6_bgp_network_cmd,
6436 "[no] network X:X::X:X/M$prefix \
6437 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
6438 NO_STR
6439 "Specify a network to announce via BGP\n"
6440 "IPv6 prefix\n"
6441 "Route-map to modify the attributes\n"
6442 "Name of the route map\n"
6443 "Label index to associate with the prefix\n"
6444 "Label index value\n")
6445 {
6446 char base_xpath[XPATH_MAXLEN];
6447 afi_t afi;
6448 safi_t safi;
6449
6450 afi = bgp_node_afi(vty);
6451 safi = bgp_node_safi(vty);
6452
6453 if (no) {
6454 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
6455 } else {
6456 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
6457
6458 if (map_name)
6459 nb_cli_enqueue_change(vty, "./rmap-policy-export",
6460 NB_OP_MODIFY, map_name);
6461 else
6462 nb_cli_enqueue_change(vty, "./rmap-policy-export",
6463 NB_OP_DESTROY, NULL);
6464
6465 if (label_index_str)
6466 nb_cli_enqueue_change(vty, "./label-index",
6467 NB_OP_MODIFY, label_index_str);
6468 }
6469
6470 snprintf(
6471 base_xpath, sizeof(base_xpath),
6472 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/network-config[prefix='%s']",
6473 yang_afi_safi_value2identity(afi, safi),
6474 bgp_afi_safi_get_container_str(afi, safi), prefix_str);
6475
6476 return nb_cli_apply_changes(vty, base_xpath);
6477 }
6478
6479 void cli_show_bgp_global_afi_safi_network_config(struct vty *vty,
6480 struct lyd_node *dnode,
6481 bool show_defaults)
6482 {
6483 vty_out(vty, " network %s", yang_dnode_get_string(dnode, "./prefix"));
6484
6485 if (yang_dnode_exists(dnode, "./label-index"))
6486 vty_out(vty, " label-index %s",
6487 yang_dnode_get_string(dnode, "./label-index"));
6488
6489 if (yang_dnode_exists(dnode, "./rmap-policy-export"))
6490 vty_out(vty, " route-map %s",
6491 yang_dnode_get_string(dnode, "./rmap-policy-export"));
6492
6493 if (yang_dnode_get_bool(dnode, "./backdoor"))
6494 vty_out(vty, " backdoor");
6495
6496 vty_out(vty, "\n");
6497 }
6498
6499 static struct bgp_aggregate *bgp_aggregate_new(void)
6500 {
6501 return XCALLOC(MTYPE_BGP_AGGREGATE, sizeof(struct bgp_aggregate));
6502 }
6503
6504 static void bgp_aggregate_free(struct bgp_aggregate *aggregate)
6505 {
6506 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
6507 route_map_counter_decrement(aggregate->suppress_map);
6508 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
6509 route_map_counter_decrement(aggregate->rmap.map);
6510 XFREE(MTYPE_BGP_AGGREGATE, aggregate);
6511 }
6512
6513 /**
6514 * Helper function to avoid repeated code: prepare variables for a
6515 * `route_map_apply` call.
6516 *
6517 * \returns `true` on route map match, otherwise `false`.
6518 */
6519 static bool aggr_suppress_map_test(struct bgp *bgp,
6520 struct bgp_aggregate *aggregate,
6521 struct bgp_path_info *pi)
6522 {
6523 const struct prefix *p = bgp_dest_get_prefix(pi->net);
6524 route_map_result_t rmr = RMAP_DENYMATCH;
6525 struct bgp_path_info rmap_path = {};
6526 struct attr attr = {};
6527
6528 /* No route map entries created, just don't match. */
6529 if (aggregate->suppress_map == NULL)
6530 return false;
6531
6532 /* Call route map matching and return result. */
6533 attr.aspath = aspath_empty();
6534 rmap_path.peer = bgp->peer_self;
6535 rmap_path.attr = &attr;
6536
6537 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_AGGREGATE);
6538 rmr = route_map_apply(aggregate->suppress_map, p, &rmap_path);
6539 bgp->peer_self->rmap_type = 0;
6540
6541 bgp_attr_flush(&attr);
6542
6543 return rmr == RMAP_PERMITMATCH;
6544 }
6545
6546 /** Test whether the aggregation has suppressed this path or not. */
6547 static bool aggr_suppress_exists(struct bgp_aggregate *aggregate,
6548 struct bgp_path_info *pi)
6549 {
6550 if (pi->extra == NULL || pi->extra->aggr_suppressors == NULL)
6551 return false;
6552
6553 return listnode_lookup(pi->extra->aggr_suppressors, aggregate) != NULL;
6554 }
6555
6556 /**
6557 * Suppress this path and keep the reference.
6558 *
6559 * \returns `true` if needs processing otherwise `false`.
6560 */
6561 static bool aggr_suppress_path(struct bgp_aggregate *aggregate,
6562 struct bgp_path_info *pi)
6563 {
6564 struct bgp_path_info_extra *pie;
6565
6566 /* Path is already suppressed by this aggregation. */
6567 if (aggr_suppress_exists(aggregate, pi))
6568 return false;
6569
6570 pie = bgp_path_info_extra_get(pi);
6571
6572 /* This is the first suppression, allocate memory and list it. */
6573 if (pie->aggr_suppressors == NULL)
6574 pie->aggr_suppressors = list_new();
6575
6576 listnode_add(pie->aggr_suppressors, aggregate);
6577
6578 /* Only mark for processing if suppressed. */
6579 if (listcount(pie->aggr_suppressors) == 1) {
6580 if (BGP_DEBUG(update, UPDATE_OUT))
6581 zlog_debug("aggregate-address suppressing: %pFX",
6582 bgp_dest_get_prefix(pi->net));
6583
6584 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
6585 return true;
6586 }
6587
6588 return false;
6589 }
6590
6591 /**
6592 * Unsuppress this path and remove the reference.
6593 *
6594 * \returns `true` if needs processing otherwise `false`.
6595 */
6596 static bool aggr_unsuppress_path(struct bgp_aggregate *aggregate,
6597 struct bgp_path_info *pi)
6598 {
6599 /* Path wasn't suppressed. */
6600 if (!aggr_suppress_exists(aggregate, pi))
6601 return false;
6602
6603 listnode_delete(pi->extra->aggr_suppressors, aggregate);
6604
6605 /* Unsuppress and free extra memory if last item. */
6606 if (listcount(pi->extra->aggr_suppressors) == 0) {
6607 if (BGP_DEBUG(update, UPDATE_OUT))
6608 zlog_debug("aggregate-address unsuppressing: %pFX",
6609 bgp_dest_get_prefix(pi->net));
6610
6611 list_delete(&pi->extra->aggr_suppressors);
6612 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
6613 return true;
6614 }
6615
6616 return false;
6617 }
6618
6619 static bool bgp_aggregate_info_same(struct bgp_path_info *pi, uint8_t origin,
6620 struct aspath *aspath,
6621 struct community *comm,
6622 struct ecommunity *ecomm,
6623 struct lcommunity *lcomm)
6624 {
6625 static struct aspath *ae = NULL;
6626
6627 if (!ae)
6628 ae = aspath_empty();
6629
6630 if (!pi)
6631 return false;
6632
6633 if (origin != pi->attr->origin)
6634 return false;
6635
6636 if (!aspath_cmp(pi->attr->aspath, (aspath) ? aspath : ae))
6637 return false;
6638
6639 if (!community_cmp(pi->attr->community, comm))
6640 return false;
6641
6642 if (!ecommunity_cmp(pi->attr->ecommunity, ecomm))
6643 return false;
6644
6645 if (!lcommunity_cmp(pi->attr->lcommunity, lcomm))
6646 return false;
6647
6648 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID))
6649 return false;
6650
6651 return true;
6652 }
6653
6654 static void bgp_aggregate_install(
6655 struct bgp *bgp, afi_t afi, safi_t safi, const struct prefix *p,
6656 uint8_t origin, struct aspath *aspath, struct community *community,
6657 struct ecommunity *ecommunity, struct lcommunity *lcommunity,
6658 uint8_t atomic_aggregate, struct bgp_aggregate *aggregate)
6659 {
6660 struct bgp_dest *dest;
6661 struct bgp_table *table;
6662 struct bgp_path_info *pi, *orig, *new;
6663 struct attr *attr;
6664
6665 table = bgp->rib[afi][safi];
6666
6667 dest = bgp_node_get(table, p);
6668
6669 for (orig = pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
6670 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6671 && pi->sub_type == BGP_ROUTE_AGGREGATE)
6672 break;
6673
6674 /*
6675 * If we have paths with different MEDs, then don't install
6676 * (or uninstall) the aggregate route.
6677 */
6678 if (aggregate->match_med && aggregate->med_mismatched)
6679 goto uninstall_aggregate_route;
6680
6681 if (aggregate->count > 0) {
6682 /*
6683 * If the aggregate information has not changed
6684 * no need to re-install it again.
6685 */
6686 if (bgp_aggregate_info_same(orig, origin, aspath, community,
6687 ecommunity, lcommunity)) {
6688 bgp_dest_unlock_node(dest);
6689
6690 if (aspath)
6691 aspath_free(aspath);
6692 if (community)
6693 community_free(&community);
6694 if (ecommunity)
6695 ecommunity_free(&ecommunity);
6696 if (lcommunity)
6697 lcommunity_free(&lcommunity);
6698
6699 return;
6700 }
6701
6702 /*
6703 * Mark the old as unusable
6704 */
6705 if (pi)
6706 bgp_path_info_delete(dest, pi);
6707
6708 attr = bgp_attr_aggregate_intern(
6709 bgp, origin, aspath, community, ecommunity, lcommunity,
6710 aggregate, atomic_aggregate, p);
6711
6712 if (!attr) {
6713 bgp_aggregate_delete(bgp, p, afi, safi, aggregate);
6714 if (BGP_DEBUG(update_groups, UPDATE_GROUPS))
6715 zlog_debug("%s: %pFX null attribute", __func__,
6716 p);
6717 return;
6718 }
6719
6720 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0,
6721 bgp->peer_self, attr, dest);
6722
6723 SET_FLAG(new->flags, BGP_PATH_VALID);
6724
6725 bgp_path_info_add(dest, new);
6726 bgp_process(bgp, dest, afi, safi);
6727 } else {
6728 uninstall_aggregate_route:
6729 for (pi = orig; pi; pi = pi->next)
6730 if (pi->peer == bgp->peer_self
6731 && pi->type == ZEBRA_ROUTE_BGP
6732 && pi->sub_type == BGP_ROUTE_AGGREGATE)
6733 break;
6734
6735 /* Withdraw static BGP route from routing table. */
6736 if (pi) {
6737 bgp_path_info_delete(dest, pi);
6738 bgp_process(bgp, dest, afi, safi);
6739 }
6740 }
6741
6742 bgp_dest_unlock_node(dest);
6743 }
6744
6745 /**
6746 * Check if the current path has different MED than other known paths.
6747 *
6748 * \returns `true` if the MED matched the others else `false`.
6749 */
6750 static bool bgp_aggregate_med_match(struct bgp_aggregate *aggregate,
6751 struct bgp *bgp, struct bgp_path_info *pi)
6752 {
6753 uint32_t cur_med = bgp_med_value(pi->attr, bgp);
6754
6755 /* This is the first route being analyzed. */
6756 if (!aggregate->med_initialized) {
6757 aggregate->med_initialized = true;
6758 aggregate->med_mismatched = false;
6759 aggregate->med_matched_value = cur_med;
6760 } else {
6761 /* Check if routes with different MED showed up. */
6762 if (cur_med != aggregate->med_matched_value)
6763 aggregate->med_mismatched = true;
6764 }
6765
6766 return !aggregate->med_mismatched;
6767 }
6768
6769 /**
6770 * Initializes and tests all routes in the aggregate address path for MED
6771 * values.
6772 *
6773 * \returns `true` if all MEDs are the same otherwise `false`.
6774 */
6775 static bool bgp_aggregate_test_all_med(struct bgp_aggregate *aggregate,
6776 struct bgp *bgp, const struct prefix *p,
6777 afi_t afi, safi_t safi)
6778 {
6779 struct bgp_table *table = bgp->rib[afi][safi];
6780 const struct prefix *dest_p;
6781 struct bgp_dest *dest, *top;
6782 struct bgp_path_info *pi;
6783 bool med_matched = true;
6784
6785 aggregate->med_initialized = false;
6786
6787 top = bgp_node_get(table, p);
6788 for (dest = bgp_node_get(table, p); dest;
6789 dest = bgp_route_next_until(dest, top)) {
6790 dest_p = bgp_dest_get_prefix(dest);
6791 if (dest_p->prefixlen <= p->prefixlen)
6792 continue;
6793
6794 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
6795 if (BGP_PATH_HOLDDOWN(pi))
6796 continue;
6797 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
6798 continue;
6799 if (!bgp_aggregate_med_match(aggregate, bgp, pi)) {
6800 med_matched = false;
6801 break;
6802 }
6803 }
6804 if (!med_matched)
6805 break;
6806 }
6807 bgp_dest_unlock_node(top);
6808
6809 return med_matched;
6810 }
6811
6812 /**
6813 * Toggles the route suppression status for this aggregate address
6814 * configuration.
6815 */
6816 void bgp_aggregate_toggle_suppressed(struct bgp_aggregate *aggregate,
6817 struct bgp *bgp, const struct prefix *p,
6818 afi_t afi, safi_t safi, bool suppress)
6819 {
6820 struct bgp_table *table = bgp->rib[afi][safi];
6821 const struct prefix *dest_p;
6822 struct bgp_dest *dest, *top;
6823 struct bgp_path_info *pi;
6824 bool toggle_suppression;
6825
6826 /* We've found a different MED we must revert any suppressed routes. */
6827 top = bgp_node_get(table, p);
6828 for (dest = bgp_node_get(table, p); dest;
6829 dest = bgp_route_next_until(dest, top)) {
6830 dest_p = bgp_dest_get_prefix(dest);
6831 if (dest_p->prefixlen <= p->prefixlen)
6832 continue;
6833
6834 toggle_suppression = false;
6835 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
6836 if (BGP_PATH_HOLDDOWN(pi))
6837 continue;
6838 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
6839 continue;
6840
6841 /* We are toggling suppression back. */
6842 if (suppress) {
6843 /* Suppress route if not suppressed already. */
6844 if (aggr_suppress_path(aggregate, pi))
6845 toggle_suppression = true;
6846 continue;
6847 }
6848
6849 /* Install route if there is no more suppression. */
6850 if (aggr_unsuppress_path(aggregate, pi))
6851 toggle_suppression = true;
6852 }
6853
6854 if (toggle_suppression)
6855 bgp_process(bgp, dest, afi, safi);
6856 }
6857 bgp_dest_unlock_node(top);
6858 }
6859
6860 /**
6861 * Aggregate address MED matching incremental test: this function is called
6862 * when the initial aggregation occurred and we are only testing a single
6863 * new path.
6864 *
6865 * In addition to testing and setting the MED validity it also installs back
6866 * suppressed routes (if summary is configured).
6867 *
6868 * Must not be called in `bgp_aggregate_route`.
6869 */
6870 static void bgp_aggregate_med_update(struct bgp_aggregate *aggregate,
6871 struct bgp *bgp, const struct prefix *p,
6872 afi_t afi, safi_t safi,
6873 struct bgp_path_info *pi, bool is_adding)
6874 {
6875 /* MED matching disabled. */
6876 if (!aggregate->match_med)
6877 return;
6878
6879 /* Aggregation with different MED, nothing to do. */
6880 if (aggregate->med_mismatched)
6881 return;
6882
6883 /*
6884 * Test the current entry:
6885 *
6886 * is_adding == true: if the new entry doesn't match then we must
6887 * install all suppressed routes.
6888 *
6889 * is_adding == false: if the entry being removed was the last
6890 * unmatching entry then we can suppress all routes.
6891 */
6892 if (!is_adding) {
6893 if (bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi)
6894 && aggregate->summary_only)
6895 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi,
6896 safi, true);
6897 } else
6898 bgp_aggregate_med_match(aggregate, bgp, pi);
6899
6900 /* No mismatches, just quit. */
6901 if (!aggregate->med_mismatched)
6902 return;
6903
6904 /* Route summarization is disabled. */
6905 if (!aggregate->summary_only)
6906 return;
6907
6908 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi, safi, false);
6909 }
6910
6911 /* Update an aggregate as routes are added/removed from the BGP table */
6912 void bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi,
6913 safi_t safi, struct bgp_aggregate *aggregate)
6914 {
6915 struct bgp_table *table;
6916 struct bgp_dest *top;
6917 struct bgp_dest *dest;
6918 uint8_t origin;
6919 struct aspath *aspath = NULL;
6920 struct community *community = NULL;
6921 struct ecommunity *ecommunity = NULL;
6922 struct lcommunity *lcommunity = NULL;
6923 struct bgp_path_info *pi;
6924 unsigned long match = 0;
6925 uint8_t atomic_aggregate = 0;
6926
6927 /* If the bgp instance is being deleted or self peer is deleted
6928 * then do not create aggregate route
6929 */
6930 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
6931 || (bgp->peer_self == NULL))
6932 return;
6933
6934 /* Initialize and test routes for MED difference. */
6935 if (aggregate->match_med)
6936 bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi);
6937
6938 /*
6939 * Reset aggregate count: we might've been called from route map
6940 * update so in that case we must retest all more specific routes.
6941 *
6942 * \see `bgp_route_map_process_update`.
6943 */
6944 aggregate->count = 0;
6945 aggregate->incomplete_origin_count = 0;
6946 aggregate->incomplete_origin_count = 0;
6947 aggregate->egp_origin_count = 0;
6948
6949 /* ORIGIN attribute: If at least one route among routes that are
6950 aggregated has ORIGIN with the value INCOMPLETE, then the
6951 aggregated route must have the ORIGIN attribute with the value
6952 INCOMPLETE. Otherwise, if at least one route among routes that
6953 are aggregated has ORIGIN with the value EGP, then the aggregated
6954 route must have the origin attribute with the value EGP. In all
6955 other case the value of the ORIGIN attribute of the aggregated
6956 route is INTERNAL. */
6957 origin = BGP_ORIGIN_IGP;
6958
6959 table = bgp->rib[afi][safi];
6960
6961 top = bgp_node_get(table, p);
6962 for (dest = bgp_node_get(table, p); dest;
6963 dest = bgp_route_next_until(dest, top)) {
6964 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
6965
6966 if (dest_p->prefixlen <= p->prefixlen)
6967 continue;
6968
6969 /* If suppress fib is enabled and route not installed
6970 * in FIB, skip the route
6971 */
6972 if (!bgp_check_advertise(bgp, dest))
6973 continue;
6974
6975 match = 0;
6976
6977 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
6978 if (BGP_PATH_HOLDDOWN(pi))
6979 continue;
6980
6981 if (pi->attr->flag
6982 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
6983 atomic_aggregate = 1;
6984
6985 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
6986 continue;
6987
6988 /*
6989 * summary-only aggregate route suppress
6990 * aggregated route announcements.
6991 *
6992 * MED matching:
6993 * Don't create summaries if MED didn't match
6994 * otherwise neither the specific routes and the
6995 * aggregation will be announced.
6996 */
6997 if (aggregate->summary_only
6998 && AGGREGATE_MED_VALID(aggregate)) {
6999 if (aggr_suppress_path(aggregate, pi))
7000 match++;
7001 }
7002
7003 /*
7004 * Suppress more specific routes that match the route
7005 * map results.
7006 *
7007 * MED matching:
7008 * Don't suppress routes if MED matching is enabled and
7009 * it mismatched otherwise we might end up with no
7010 * routes for this path.
7011 */
7012 if (aggregate->suppress_map_name
7013 && AGGREGATE_MED_VALID(aggregate)
7014 && aggr_suppress_map_test(bgp, aggregate, pi)) {
7015 if (aggr_suppress_path(aggregate, pi))
7016 match++;
7017 }
7018
7019 aggregate->count++;
7020
7021 /*
7022 * If at least one route among routes that are
7023 * aggregated has ORIGIN with the value INCOMPLETE,
7024 * then the aggregated route MUST have the ORIGIN
7025 * attribute with the value INCOMPLETE. Otherwise, if
7026 * at least one route among routes that are aggregated
7027 * has ORIGIN with the value EGP, then the aggregated
7028 * route MUST have the ORIGIN attribute with the value
7029 * EGP.
7030 */
7031 switch (pi->attr->origin) {
7032 case BGP_ORIGIN_INCOMPLETE:
7033 aggregate->incomplete_origin_count++;
7034 break;
7035 case BGP_ORIGIN_EGP:
7036 aggregate->egp_origin_count++;
7037 break;
7038 default:
7039 /*Do nothing.
7040 */
7041 break;
7042 }
7043
7044 if (!aggregate->as_set)
7045 continue;
7046
7047 /*
7048 * as-set aggregate route generate origin, as path,
7049 * and community aggregation.
7050 */
7051 /* Compute aggregate route's as-path.
7052 */
7053 bgp_compute_aggregate_aspath_hash(aggregate,
7054 pi->attr->aspath);
7055
7056 /* Compute aggregate route's community.
7057 */
7058 if (pi->attr->community)
7059 bgp_compute_aggregate_community_hash(
7060 aggregate,
7061 pi->attr->community);
7062
7063 /* Compute aggregate route's extended community.
7064 */
7065 if (pi->attr->ecommunity)
7066 bgp_compute_aggregate_ecommunity_hash(
7067 aggregate,
7068 pi->attr->ecommunity);
7069
7070 /* Compute aggregate route's large community.
7071 */
7072 if (pi->attr->lcommunity)
7073 bgp_compute_aggregate_lcommunity_hash(
7074 aggregate,
7075 pi->attr->lcommunity);
7076 }
7077 if (match)
7078 bgp_process(bgp, dest, afi, safi);
7079 }
7080 if (aggregate->as_set) {
7081 bgp_compute_aggregate_aspath_val(aggregate);
7082 bgp_compute_aggregate_community_val(aggregate);
7083 bgp_compute_aggregate_ecommunity_val(aggregate);
7084 bgp_compute_aggregate_lcommunity_val(aggregate);
7085 }
7086
7087
7088 bgp_dest_unlock_node(top);
7089
7090
7091 if (aggregate->incomplete_origin_count > 0)
7092 origin = BGP_ORIGIN_INCOMPLETE;
7093 else if (aggregate->egp_origin_count > 0)
7094 origin = BGP_ORIGIN_EGP;
7095
7096 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7097 origin = aggregate->origin;
7098
7099 if (aggregate->as_set) {
7100 if (aggregate->aspath)
7101 /* Retrieve aggregate route's as-path.
7102 */
7103 aspath = aspath_dup(aggregate->aspath);
7104
7105 if (aggregate->community)
7106 /* Retrieve aggregate route's community.
7107 */
7108 community = community_dup(aggregate->community);
7109
7110 if (aggregate->ecommunity)
7111 /* Retrieve aggregate route's ecommunity.
7112 */
7113 ecommunity = ecommunity_dup(aggregate->ecommunity);
7114
7115 if (aggregate->lcommunity)
7116 /* Retrieve aggregate route's lcommunity.
7117 */
7118 lcommunity = lcommunity_dup(aggregate->lcommunity);
7119 }
7120
7121 bgp_aggregate_install(bgp, afi, safi, p, origin, aspath, community,
7122 ecommunity, lcommunity, atomic_aggregate,
7123 aggregate);
7124 }
7125
7126 void bgp_aggregate_delete(struct bgp *bgp, const struct prefix *p, afi_t afi,
7127 safi_t safi, struct bgp_aggregate *aggregate)
7128 {
7129 struct bgp_table *table;
7130 struct bgp_dest *top;
7131 struct bgp_dest *dest;
7132 struct bgp_path_info *pi;
7133 unsigned long match;
7134
7135 table = bgp->rib[afi][safi];
7136
7137 /* If routes exists below this node, generate aggregate routes. */
7138 top = bgp_node_get(table, p);
7139 for (dest = bgp_node_get(table, p); dest;
7140 dest = bgp_route_next_until(dest, top)) {
7141 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
7142
7143 if (dest_p->prefixlen <= p->prefixlen)
7144 continue;
7145 match = 0;
7146
7147 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
7148 if (BGP_PATH_HOLDDOWN(pi))
7149 continue;
7150
7151 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7152 continue;
7153
7154 if (aggregate->summary_only && pi->extra
7155 && AGGREGATE_MED_VALID(aggregate)) {
7156 if (aggr_unsuppress_path(aggregate, pi))
7157 match++;
7158 }
7159
7160 if (aggregate->suppress_map_name
7161 && AGGREGATE_MED_VALID(aggregate)
7162 && aggr_suppress_map_test(bgp, aggregate, pi)) {
7163 if (aggr_unsuppress_path(aggregate, pi))
7164 match++;
7165 }
7166
7167 aggregate->count--;
7168
7169 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
7170 aggregate->incomplete_origin_count--;
7171 else if (pi->attr->origin == BGP_ORIGIN_EGP)
7172 aggregate->egp_origin_count--;
7173
7174 if (aggregate->as_set) {
7175 /* Remove as-path from aggregate.
7176 */
7177 bgp_remove_aspath_from_aggregate_hash(
7178 aggregate,
7179 pi->attr->aspath);
7180
7181 if (pi->attr->community)
7182 /* Remove community from aggregate.
7183 */
7184 bgp_remove_comm_from_aggregate_hash(
7185 aggregate,
7186 pi->attr->community);
7187
7188 if (pi->attr->ecommunity)
7189 /* Remove ecommunity from aggregate.
7190 */
7191 bgp_remove_ecomm_from_aggregate_hash(
7192 aggregate,
7193 pi->attr->ecommunity);
7194
7195 if (pi->attr->lcommunity)
7196 /* Remove lcommunity from aggregate.
7197 */
7198 bgp_remove_lcomm_from_aggregate_hash(
7199 aggregate,
7200 pi->attr->lcommunity);
7201 }
7202 }
7203
7204 /* If this node was suppressed, process the change. */
7205 if (match)
7206 bgp_process(bgp, dest, afi, safi);
7207 }
7208 if (aggregate->as_set) {
7209 aspath_free(aggregate->aspath);
7210 aggregate->aspath = NULL;
7211 if (aggregate->community)
7212 community_free(&aggregate->community);
7213 if (aggregate->ecommunity)
7214 ecommunity_free(&aggregate->ecommunity);
7215 if (aggregate->lcommunity)
7216 lcommunity_free(&aggregate->lcommunity);
7217 }
7218
7219 bgp_dest_unlock_node(top);
7220 }
7221
7222 static void bgp_add_route_to_aggregate(struct bgp *bgp,
7223 const struct prefix *aggr_p,
7224 struct bgp_path_info *pinew, afi_t afi,
7225 safi_t safi,
7226 struct bgp_aggregate *aggregate)
7227 {
7228 uint8_t origin;
7229 struct aspath *aspath = NULL;
7230 uint8_t atomic_aggregate = 0;
7231 struct community *community = NULL;
7232 struct ecommunity *ecommunity = NULL;
7233 struct lcommunity *lcommunity = NULL;
7234
7235 /* If the bgp instance is being deleted or self peer is deleted
7236 * then do not create aggregate route
7237 */
7238 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7239 || (bgp->peer_self == NULL))
7240 return;
7241
7242 /* ORIGIN attribute: If at least one route among routes that are
7243 * aggregated has ORIGIN with the value INCOMPLETE, then the
7244 * aggregated route must have the ORIGIN attribute with the value
7245 * INCOMPLETE. Otherwise, if at least one route among routes that
7246 * are aggregated has ORIGIN with the value EGP, then the aggregated
7247 * route must have the origin attribute with the value EGP. In all
7248 * other case the value of the ORIGIN attribute of the aggregated
7249 * route is INTERNAL.
7250 */
7251 origin = BGP_ORIGIN_IGP;
7252
7253 aggregate->count++;
7254
7255 /*
7256 * This must be called before `summary` check to avoid
7257 * "suppressing" twice.
7258 */
7259 if (aggregate->match_med)
7260 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi,
7261 pinew, true);
7262
7263 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
7264 aggr_suppress_path(aggregate, pinew);
7265
7266 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
7267 && aggr_suppress_map_test(bgp, aggregate, pinew))
7268 aggr_suppress_path(aggregate, pinew);
7269
7270 switch (pinew->attr->origin) {
7271 case BGP_ORIGIN_INCOMPLETE:
7272 aggregate->incomplete_origin_count++;
7273 break;
7274 case BGP_ORIGIN_EGP:
7275 aggregate->egp_origin_count++;
7276 break;
7277 default:
7278 /* Do nothing.
7279 */
7280 break;
7281 }
7282
7283 if (aggregate->incomplete_origin_count > 0)
7284 origin = BGP_ORIGIN_INCOMPLETE;
7285 else if (aggregate->egp_origin_count > 0)
7286 origin = BGP_ORIGIN_EGP;
7287
7288 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7289 origin = aggregate->origin;
7290
7291 if (aggregate->as_set) {
7292 /* Compute aggregate route's as-path.
7293 */
7294 bgp_compute_aggregate_aspath(aggregate,
7295 pinew->attr->aspath);
7296
7297 /* Compute aggregate route's community.
7298 */
7299 if (pinew->attr->community)
7300 bgp_compute_aggregate_community(
7301 aggregate,
7302 pinew->attr->community);
7303
7304 /* Compute aggregate route's extended community.
7305 */
7306 if (pinew->attr->ecommunity)
7307 bgp_compute_aggregate_ecommunity(
7308 aggregate,
7309 pinew->attr->ecommunity);
7310
7311 /* Compute aggregate route's large community.
7312 */
7313 if (pinew->attr->lcommunity)
7314 bgp_compute_aggregate_lcommunity(
7315 aggregate,
7316 pinew->attr->lcommunity);
7317
7318 /* Retrieve aggregate route's as-path.
7319 */
7320 if (aggregate->aspath)
7321 aspath = aspath_dup(aggregate->aspath);
7322
7323 /* Retrieve aggregate route's community.
7324 */
7325 if (aggregate->community)
7326 community = community_dup(aggregate->community);
7327
7328 /* Retrieve aggregate route's ecommunity.
7329 */
7330 if (aggregate->ecommunity)
7331 ecommunity = ecommunity_dup(aggregate->ecommunity);
7332
7333 /* Retrieve aggregate route's lcommunity.
7334 */
7335 if (aggregate->lcommunity)
7336 lcommunity = lcommunity_dup(aggregate->lcommunity);
7337 }
7338
7339 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
7340 aspath, community, ecommunity,
7341 lcommunity, atomic_aggregate, aggregate);
7342 }
7343
7344 static void bgp_remove_route_from_aggregate(struct bgp *bgp, afi_t afi,
7345 safi_t safi,
7346 struct bgp_path_info *pi,
7347 struct bgp_aggregate *aggregate,
7348 const struct prefix *aggr_p)
7349 {
7350 uint8_t origin;
7351 struct aspath *aspath = NULL;
7352 uint8_t atomic_aggregate = 0;
7353 struct community *community = NULL;
7354 struct ecommunity *ecommunity = NULL;
7355 struct lcommunity *lcommunity = NULL;
7356 unsigned long match = 0;
7357
7358 /* If the bgp instance is being deleted or self peer is deleted
7359 * then do not create aggregate route
7360 */
7361 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7362 || (bgp->peer_self == NULL))
7363 return;
7364
7365 if (BGP_PATH_HOLDDOWN(pi))
7366 return;
7367
7368 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7369 return;
7370
7371 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
7372 if (aggr_unsuppress_path(aggregate, pi))
7373 match++;
7374
7375 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
7376 && aggr_suppress_map_test(bgp, aggregate, pi))
7377 if (aggr_unsuppress_path(aggregate, pi))
7378 match++;
7379
7380 /*
7381 * This must be called after `summary`, `suppress-map` check to avoid
7382 * "unsuppressing" twice.
7383 */
7384 if (aggregate->match_med)
7385 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi, pi,
7386 true);
7387
7388 if (aggregate->count > 0)
7389 aggregate->count--;
7390
7391 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
7392 aggregate->incomplete_origin_count--;
7393 else if (pi->attr->origin == BGP_ORIGIN_EGP)
7394 aggregate->egp_origin_count--;
7395
7396 if (aggregate->as_set) {
7397 /* Remove as-path from aggregate.
7398 */
7399 bgp_remove_aspath_from_aggregate(aggregate,
7400 pi->attr->aspath);
7401
7402 if (pi->attr->community)
7403 /* Remove community from aggregate.
7404 */
7405 bgp_remove_community_from_aggregate(
7406 aggregate,
7407 pi->attr->community);
7408
7409 if (pi->attr->ecommunity)
7410 /* Remove ecommunity from aggregate.
7411 */
7412 bgp_remove_ecommunity_from_aggregate(
7413 aggregate,
7414 pi->attr->ecommunity);
7415
7416 if (pi->attr->lcommunity)
7417 /* Remove lcommunity from aggregate.
7418 */
7419 bgp_remove_lcommunity_from_aggregate(
7420 aggregate,
7421 pi->attr->lcommunity);
7422 }
7423
7424 /* If this node was suppressed, process the change. */
7425 if (match)
7426 bgp_process(bgp, pi->net, afi, safi);
7427
7428 origin = BGP_ORIGIN_IGP;
7429 if (aggregate->incomplete_origin_count > 0)
7430 origin = BGP_ORIGIN_INCOMPLETE;
7431 else if (aggregate->egp_origin_count > 0)
7432 origin = BGP_ORIGIN_EGP;
7433
7434 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7435 origin = aggregate->origin;
7436
7437 if (aggregate->as_set) {
7438 /* Retrieve aggregate route's as-path.
7439 */
7440 if (aggregate->aspath)
7441 aspath = aspath_dup(aggregate->aspath);
7442
7443 /* Retrieve aggregate route's community.
7444 */
7445 if (aggregate->community)
7446 community = community_dup(aggregate->community);
7447
7448 /* Retrieve aggregate route's ecommunity.
7449 */
7450 if (aggregate->ecommunity)
7451 ecommunity = ecommunity_dup(aggregate->ecommunity);
7452
7453 /* Retrieve aggregate route's lcommunity.
7454 */
7455 if (aggregate->lcommunity)
7456 lcommunity = lcommunity_dup(aggregate->lcommunity);
7457 }
7458
7459 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
7460 aspath, community, ecommunity,
7461 lcommunity, atomic_aggregate, aggregate);
7462 }
7463
7464 void bgp_aggregate_increment(struct bgp *bgp, const struct prefix *p,
7465 struct bgp_path_info *pi, afi_t afi, safi_t safi)
7466 {
7467 struct bgp_dest *child;
7468 struct bgp_dest *dest;
7469 struct bgp_aggregate *aggregate;
7470 struct bgp_table *table;
7471
7472 table = bgp->aggregate[afi][safi];
7473
7474 /* No aggregates configured. */
7475 if (bgp_table_top_nolock(table) == NULL)
7476 return;
7477
7478 if (p->prefixlen == 0)
7479 return;
7480
7481 if (BGP_PATH_HOLDDOWN(pi))
7482 return;
7483
7484 /* If suppress fib is enabled and route not installed
7485 * in FIB, do not update the aggregate route
7486 */
7487 if (!bgp_check_advertise(bgp, pi->net))
7488 return;
7489
7490 child = bgp_node_get(table, p);
7491
7492 /* Aggregate address configuration check. */
7493 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
7494 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
7495
7496 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
7497 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
7498 bgp_add_route_to_aggregate(bgp, dest_p, pi, afi, safi,
7499 aggregate);
7500 }
7501 }
7502 bgp_dest_unlock_node(child);
7503 }
7504
7505 void bgp_aggregate_decrement(struct bgp *bgp, const struct prefix *p,
7506 struct bgp_path_info *del, afi_t afi, safi_t safi)
7507 {
7508 struct bgp_dest *child;
7509 struct bgp_dest *dest;
7510 struct bgp_aggregate *aggregate;
7511 struct bgp_table *table;
7512
7513 table = bgp->aggregate[afi][safi];
7514
7515 /* No aggregates configured. */
7516 if (bgp_table_top_nolock(table) == NULL)
7517 return;
7518
7519 if (p->prefixlen == 0)
7520 return;
7521
7522 child = bgp_node_get(table, p);
7523
7524 /* Aggregate address configuration check. */
7525 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
7526 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
7527
7528 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
7529 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
7530 bgp_remove_route_from_aggregate(bgp, afi, safi, del,
7531 aggregate, dest_p);
7532 }
7533 }
7534 bgp_dest_unlock_node(child);
7535 }
7536
7537 /* Aggregate route attribute. */
7538 #define AGGREGATE_SUMMARY_ONLY 1
7539 #define AGGREGATE_AS_SET 1
7540 #define AGGREGATE_AS_UNSET 0
7541
7542 static const char *bgp_origin2str(uint8_t origin)
7543 {
7544 switch (origin) {
7545 case BGP_ORIGIN_IGP:
7546 return "igp";
7547 case BGP_ORIGIN_EGP:
7548 return "egp";
7549 case BGP_ORIGIN_INCOMPLETE:
7550 return "incomplete";
7551 }
7552 return "n/a";
7553 }
7554
7555 static const char *bgp_rpki_validation2str(enum rpki_states v_state)
7556 {
7557 switch (v_state) {
7558 case RPKI_NOT_BEING_USED:
7559 return "not used";
7560 case RPKI_VALID:
7561 return "valid";
7562 case RPKI_NOTFOUND:
7563 return "not found";
7564 case RPKI_INVALID:
7565 return "invalid";
7566 }
7567
7568 assert(!"We should never get here this is a dev escape");
7569 return "ERROR";
7570 }
7571
7572 int bgp_aggregate_unset(struct bgp *bgp, struct prefix *prefix, afi_t afi,
7573 safi_t safi, char *errmsg, size_t errmsg_len)
7574 {
7575 struct bgp_dest *dest;
7576 struct bgp_aggregate *aggregate;
7577
7578 /* If the bgp instance is being deleted or self peer is deleted
7579 * then do not create aggregate route
7580 */
7581 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7582 || (bgp->peer_self == NULL))
7583 return 0;
7584
7585 apply_mask(prefix);
7586 /* Old configuration check. */
7587 dest = bgp_node_lookup(bgp->aggregate[afi][safi], prefix);
7588 if (!dest) {
7589 snprintf(errmsg, errmsg_len,
7590 "There is no aggregate-address configuration.\n");
7591 return -1;
7592 }
7593
7594 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
7595 bgp_aggregate_delete(bgp, prefix, afi, safi, aggregate);
7596 bgp_aggregate_install(bgp, afi, safi, prefix, 0, NULL, NULL, NULL, NULL,
7597 0, aggregate);
7598
7599 /* Unlock aggregate address configuration. */
7600 bgp_dest_set_bgp_aggregate_info(dest, NULL);
7601
7602 if (aggregate->community)
7603 community_free(&aggregate->community);
7604
7605 if (aggregate->community_hash) {
7606 /* Delete all communities in the hash.
7607 */
7608 hash_clean(aggregate->community_hash,
7609 bgp_aggr_community_remove);
7610 /* Free up the community_hash.
7611 */
7612 hash_free(aggregate->community_hash);
7613 }
7614
7615 if (aggregate->ecommunity)
7616 ecommunity_free(&aggregate->ecommunity);
7617
7618 if (aggregate->ecommunity_hash) {
7619 /* Delete all ecommunities in the hash.
7620 */
7621 hash_clean(aggregate->ecommunity_hash,
7622 bgp_aggr_ecommunity_remove);
7623 /* Free up the ecommunity_hash.
7624 */
7625 hash_free(aggregate->ecommunity_hash);
7626 }
7627
7628 if (aggregate->lcommunity)
7629 lcommunity_free(&aggregate->lcommunity);
7630
7631 if (aggregate->lcommunity_hash) {
7632 /* Delete all lcommunities in the hash.
7633 */
7634 hash_clean(aggregate->lcommunity_hash,
7635 bgp_aggr_lcommunity_remove);
7636 /* Free up the lcommunity_hash.
7637 */
7638 hash_free(aggregate->lcommunity_hash);
7639 }
7640
7641 if (aggregate->aspath)
7642 aspath_free(aggregate->aspath);
7643
7644 if (aggregate->aspath_hash) {
7645 /* Delete all as-paths in the hash.
7646 */
7647 hash_clean(aggregate->aspath_hash,
7648 bgp_aggr_aspath_remove);
7649 /* Free up the aspath_hash.
7650 */
7651 hash_free(aggregate->aspath_hash);
7652 }
7653
7654 bgp_aggregate_free(aggregate);
7655 bgp_dest_unlock_node(dest);
7656 bgp_dest_unlock_node(dest);
7657
7658 return 0;
7659 }
7660
7661 int bgp_aggregate_set(struct bgp *bgp, struct prefix *prefix, afi_t afi,
7662 safi_t safi, const char *rmap, uint8_t summary_only,
7663 uint8_t as_set, uint8_t origin, bool match_med,
7664 const char *suppress_map,
7665 char *errmsg, size_t errmsg_len)
7666 {
7667 int ret;
7668 struct bgp_dest *dest;
7669 struct bgp_aggregate *aggregate;
7670 uint8_t as_set_new = as_set;
7671 char buf[PREFIX2STR_BUFFER];
7672
7673 if (suppress_map && summary_only) {
7674 snprintf(errmsg, errmsg_len,
7675 "'summary-only' and 'suppress-map' can't be used at the same time\n");
7676 return -1;
7677 }
7678
7679 apply_mask(prefix);
7680
7681 if ((afi == AFI_IP && prefix->prefixlen == IPV4_MAX_BITLEN)
7682 || (afi == AFI_IP6 && prefix->prefixlen == IPV6_MAX_BITLEN)) {
7683 snprintf(
7684 errmsg, errmsg_len,
7685 "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
7686 prefix2str(prefix, buf, PREFIX_STRLEN));
7687 return -1;
7688 }
7689
7690 /* Old configuration check. */
7691 dest = bgp_node_get(bgp->aggregate[afi][safi], prefix);
7692 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
7693
7694 if (aggregate) {
7695 snprintf(errmsg, errmsg_len,
7696 "There is already same aggregate network.\n");
7697 /* try to remove the old entry */
7698 ret = bgp_aggregate_unset(bgp, prefix, afi, safi, errmsg,
7699 errmsg_len);
7700 if (ret) {
7701 snprintf(errmsg, errmsg_len,
7702 "Error deleting aggregate.\n");
7703 bgp_dest_unlock_node(dest);
7704 return -1;
7705 }
7706 }
7707
7708 /* Make aggregate address structure. */
7709 aggregate = bgp_aggregate_new();
7710 aggregate->summary_only = summary_only;
7711 aggregate->match_med = match_med;
7712
7713 /* Network operators MUST NOT locally generate any new
7714 * announcements containing AS_SET or AS_CONFED_SET. If they have
7715 * announced routes with AS_SET or AS_CONFED_SET in them, then they
7716 * SHOULD withdraw those routes and re-announce routes for the
7717 * aggregate or component prefixes (i.e., the more-specific routes
7718 * subsumed by the previously aggregated route) without AS_SET
7719 * or AS_CONFED_SET in the updates.
7720 */
7721 if (bgp->reject_as_sets) {
7722 if (as_set == AGGREGATE_AS_SET) {
7723 as_set_new = AGGREGATE_AS_UNSET;
7724 zlog_warn(
7725 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
7726 __func__);
7727 snprintf(
7728 errmsg, errmsg_len,
7729 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
7730 }
7731 }
7732
7733 aggregate->as_set = as_set_new;
7734 aggregate->safi = safi;
7735 /* Override ORIGIN attribute if defined.
7736 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
7737 * to IGP which is not what rfc4271 says.
7738 * This enables the same behavior, optionally.
7739 */
7740 aggregate->origin = origin;
7741
7742 if (rmap) {
7743 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
7744 route_map_counter_decrement(aggregate->rmap.map);
7745 aggregate->rmap.name =
7746 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
7747 aggregate->rmap.map = route_map_lookup_by_name(rmap);
7748 route_map_counter_increment(aggregate->rmap.map);
7749 }
7750
7751 if (suppress_map) {
7752 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
7753 route_map_counter_decrement(aggregate->suppress_map);
7754
7755 aggregate->suppress_map_name =
7756 XSTRDUP(MTYPE_ROUTE_MAP_NAME, suppress_map);
7757 aggregate->suppress_map =
7758 route_map_lookup_by_name(aggregate->suppress_map_name);
7759 route_map_counter_increment(aggregate->suppress_map);
7760 }
7761
7762 bgp_dest_set_bgp_aggregate_info(dest, aggregate);
7763
7764 /* Aggregate address insert into BGP routing table. */
7765 bgp_aggregate_route(bgp, prefix, afi, safi, aggregate);
7766
7767 return 0;
7768 }
7769
7770 DEFPY_YANG(
7771 aggregate_addressv4, aggregate_addressv4_cmd,
7772 "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> {"
7773 "as-set$as_set_s"
7774 "|summary-only$summary_only"
7775 "|route-map WORD$rmap_name"
7776 "|origin <egp|igp|incomplete>$origin_s"
7777 "|matching-MED-only$match_med"
7778 "|suppress-map WORD$suppress_map"
7779 "}",
7780 NO_STR
7781 "Configure BGP aggregate entries\n"
7782 "Aggregate prefix\n"
7783 "Aggregate address\n"
7784 "Aggregate mask\n"
7785 "Generate AS set path information\n"
7786 "Filter more specific routes from updates\n"
7787 "Apply route map to aggregate network\n"
7788 "Route map name\n"
7789 "BGP origin code\n"
7790 "Remote EGP\n"
7791 "Local IGP\n"
7792 "Unknown heritage\n"
7793 "Only aggregate routes with matching MED\n"
7794 "Suppress the selected more specific routes\n"
7795 "Route map with the route selectors\n")
7796 {
7797 char base_xpath[XPATH_MAXLEN];
7798 safi_t safi = bgp_node_safi(vty);
7799 char prefix_buf[PREFIX2STR_BUFFER];
7800
7801 if (addr_str) {
7802 if (netmask_str2prefix_str(addr_str, mask_str, prefix_buf,
7803 sizeof(prefix_buf))
7804 == 0) {
7805 vty_out(vty, "%% Inconsistent address and mask\n");
7806 return CMD_WARNING_CONFIG_FAILED;
7807 }
7808 } else {
7809 strlcpy(prefix_buf, prefix_str, sizeof(prefix_buf));
7810 }
7811
7812 if (!no && origin_s)
7813 nb_cli_enqueue_change(vty, "./origin", NB_OP_MODIFY, origin_s);
7814
7815 if (!no && as_set_s)
7816 nb_cli_enqueue_change(vty, "./as-set", NB_OP_MODIFY, "true");
7817 else
7818 nb_cli_enqueue_change(vty, "./as-set", NB_OP_MODIFY, "false");
7819
7820 if (!no && summary_only)
7821 nb_cli_enqueue_change(vty, "./summary-only", NB_OP_MODIFY,
7822 "true");
7823 else
7824 nb_cli_enqueue_change(vty, "./summary-only", NB_OP_MODIFY,
7825 "false");
7826
7827 if (!no && match_med)
7828 nb_cli_enqueue_change(vty, "./match-med", NB_OP_MODIFY, "true");
7829 else
7830 nb_cli_enqueue_change(vty, "./match-med", NB_OP_MODIFY,
7831 "false");
7832
7833 if (rmap_name)
7834 nb_cli_enqueue_change(vty, "./rmap-policy-export", NB_OP_MODIFY,
7835 rmap_name);
7836 else
7837 nb_cli_enqueue_change(vty, "./rmap-policy-export",
7838 NB_OP_DESTROY, NULL);
7839
7840 if (suppress_map)
7841 nb_cli_enqueue_change(vty, "./suppress-map", NB_OP_MODIFY,
7842 suppress_map);
7843 else
7844 nb_cli_enqueue_change(vty, "./suppress-map", NB_OP_DESTROY,
7845 NULL);
7846
7847 snprintf(
7848 base_xpath, sizeof(base_xpath),
7849 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/aggregate-route[prefix='%s']",
7850 yang_afi_safi_value2identity(AFI_IP, safi),
7851 bgp_afi_safi_get_container_str(AFI_IP, safi), prefix_buf);
7852
7853 if (no)
7854 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
7855 else
7856 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
7857
7858 return nb_cli_apply_changes(vty, base_xpath);
7859 }
7860
7861 DEFPY_YANG(aggregate_addressv6, aggregate_addressv6_cmd,
7862 "[no] aggregate-address X:X::X:X/M$prefix {"
7863 "as-set$as_set_s"
7864 "|summary-only$summary_only"
7865 "|route-map WORD$rmap_name"
7866 "|origin <egp|igp|incomplete>$origin_s"
7867 "|matching-MED-only$match_med"
7868 "|suppress-map WORD$suppress_map"
7869 "}",
7870 NO_STR
7871 "Configure BGP aggregate entries\n"
7872 "Aggregate prefix\n"
7873 "Generate AS set path information\n"
7874 "Filter more specific routes from updates\n"
7875 "Apply route map to aggregate network\n"
7876 "Route map name\n"
7877 "BGP origin code\n"
7878 "Remote EGP\n"
7879 "Local IGP\n"
7880 "Unknown heritage\n"
7881 "Only aggregate routes with matching MED\n"
7882 "Suppress the selected more specific routes\n"
7883 "Route map with the route selectors\n")
7884 {
7885 char base_xpath[XPATH_MAXLEN];
7886 safi_t safi = bgp_node_safi(vty);
7887
7888 if (!no && origin_s)
7889 nb_cli_enqueue_change(vty, "./origin", NB_OP_MODIFY, origin_s);
7890
7891 if (!no && as_set_s)
7892 nb_cli_enqueue_change(vty, "./as-set", NB_OP_MODIFY, "true");
7893 else
7894 nb_cli_enqueue_change(vty, "./as-set", NB_OP_MODIFY, "false");
7895
7896 if (!no && summary_only)
7897 nb_cli_enqueue_change(vty, "./summary-only", NB_OP_MODIFY,
7898 "true");
7899 else
7900 nb_cli_enqueue_change(vty, "./summary-only", NB_OP_MODIFY,
7901 "false");
7902
7903 if (!no && match_med)
7904 nb_cli_enqueue_change(vty, "./match-med", NB_OP_MODIFY, "true");
7905 else
7906 nb_cli_enqueue_change(vty, "./match-med", NB_OP_MODIFY,
7907 "false");
7908
7909 if (rmap_name)
7910 nb_cli_enqueue_change(vty, "./rmap-policy-export", NB_OP_MODIFY,
7911 rmap_name);
7912
7913 if (suppress_map)
7914 nb_cli_enqueue_change(vty, "./suppress-map", NB_OP_MODIFY,
7915 suppress_map);
7916 else
7917 nb_cli_enqueue_change(vty, "./suppress-map", NB_OP_DESTROY,
7918 NULL);
7919
7920 snprintf(
7921 base_xpath, sizeof(base_xpath),
7922 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/aggregate-route[prefix='%s']",
7923 yang_afi_safi_value2identity(AFI_IP6, safi),
7924 bgp_afi_safi_get_container_str(AFI_IP6, safi), prefix_str);
7925
7926 if (no)
7927 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
7928 else
7929 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
7930
7931 return nb_cli_apply_changes(vty, base_xpath);
7932 }
7933
7934 void cli_show_bgp_global_afi_safi_unicast_aggregate_route(
7935 struct vty *vty, struct lyd_node *dnode, bool show_defaults)
7936 {
7937 uint8_t origin;
7938
7939 vty_out(vty, " aggregate-address %s",
7940 yang_dnode_get_string(dnode, "./prefix"));
7941
7942 if (yang_dnode_get_bool(dnode, "./as-set"))
7943 vty_out(vty, " as-set");
7944
7945 if (yang_dnode_get_bool(dnode, "./summary-only"))
7946 vty_out(vty, " summary-only");
7947
7948 if (yang_dnode_exists(dnode, "./rmap-policy-export"))
7949 vty_out(vty, " route-map %s",
7950 yang_dnode_get_string(dnode, "./rmap-policy-export"));
7951
7952 origin = yang_dnode_get_enum(dnode, "./origin");
7953 if (origin != BGP_ORIGIN_UNSPECIFIED)
7954 vty_out(vty, " origin %s", bgp_origin2str(origin));
7955
7956 if (yang_dnode_get_bool(dnode, "./match-med"))
7957 vty_out(vty, " matching-MED-only");
7958
7959 vty_out(vty, "\n");
7960 }
7961
7962 /* Redistribute route treatment. */
7963 void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
7964 const union g_addr *nexthop, ifindex_t ifindex,
7965 enum nexthop_types_t nhtype, uint32_t metric,
7966 uint8_t type, unsigned short instance,
7967 route_tag_t tag)
7968 {
7969 struct bgp_path_info *new;
7970 struct bgp_path_info *bpi;
7971 struct bgp_path_info rmap_path;
7972 struct bgp_dest *bn;
7973 struct attr attr;
7974 struct attr *new_attr;
7975 afi_t afi;
7976 route_map_result_t ret;
7977 struct bgp_redist *red;
7978
7979 /* Make default attribute. */
7980 bgp_attr_default_set(&attr, BGP_ORIGIN_INCOMPLETE);
7981 /*
7982 * This must not be NULL to satisfy Coverity SA
7983 */
7984 assert(attr.aspath);
7985
7986 switch (nhtype) {
7987 case NEXTHOP_TYPE_IFINDEX:
7988 break;
7989 case NEXTHOP_TYPE_IPV4:
7990 case NEXTHOP_TYPE_IPV4_IFINDEX:
7991 attr.nexthop = nexthop->ipv4;
7992 break;
7993 case NEXTHOP_TYPE_IPV6:
7994 case NEXTHOP_TYPE_IPV6_IFINDEX:
7995 attr.mp_nexthop_global = nexthop->ipv6;
7996 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
7997 break;
7998 case NEXTHOP_TYPE_BLACKHOLE:
7999 switch (p->family) {
8000 case AF_INET:
8001 attr.nexthop.s_addr = INADDR_ANY;
8002 break;
8003 case AF_INET6:
8004 memset(&attr.mp_nexthop_global, 0,
8005 sizeof(attr.mp_nexthop_global));
8006 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
8007 break;
8008 }
8009 break;
8010 }
8011 attr.nh_ifindex = ifindex;
8012
8013 attr.med = metric;
8014 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
8015 attr.tag = tag;
8016
8017 afi = family2afi(p->family);
8018
8019 red = bgp_redist_lookup(bgp, afi, type, instance);
8020 if (red) {
8021 struct attr attr_new;
8022
8023 /* Copy attribute for modification. */
8024 attr_new = attr;
8025
8026 if (red->redist_metric_flag)
8027 attr_new.med = red->redist_metric;
8028
8029 /* Apply route-map. */
8030 if (red->rmap.name) {
8031 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
8032 rmap_path.peer = bgp->peer_self;
8033 rmap_path.attr = &attr_new;
8034
8035 SET_FLAG(bgp->peer_self->rmap_type,
8036 PEER_RMAP_TYPE_REDISTRIBUTE);
8037
8038 ret = route_map_apply(red->rmap.map, p, &rmap_path);
8039
8040 bgp->peer_self->rmap_type = 0;
8041
8042 if (ret == RMAP_DENYMATCH) {
8043 /* Free uninterned attribute. */
8044 bgp_attr_flush(&attr_new);
8045
8046 /* Unintern original. */
8047 aspath_unintern(&attr.aspath);
8048 bgp_redistribute_delete(bgp, p, type, instance);
8049 return;
8050 }
8051 }
8052
8053 if (bgp_in_graceful_shutdown(bgp))
8054 bgp_attr_add_gshut_community(&attr_new);
8055
8056 bn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8057 SAFI_UNICAST, p, NULL);
8058
8059 new_attr = bgp_attr_intern(&attr_new);
8060
8061 for (bpi = bgp_dest_get_bgp_path_info(bn); bpi; bpi = bpi->next)
8062 if (bpi->peer == bgp->peer_self
8063 && bpi->sub_type == BGP_ROUTE_REDISTRIBUTE)
8064 break;
8065
8066 if (bpi) {
8067 /* Ensure the (source route) type is updated. */
8068 bpi->type = type;
8069 if (attrhash_cmp(bpi->attr, new_attr)
8070 && !CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
8071 bgp_attr_unintern(&new_attr);
8072 aspath_unintern(&attr.aspath);
8073 bgp_dest_unlock_node(bn);
8074 return;
8075 } else {
8076 /* The attribute is changed. */
8077 bgp_path_info_set_flag(bn, bpi,
8078 BGP_PATH_ATTR_CHANGED);
8079
8080 /* Rewrite BGP route information. */
8081 if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
8082 bgp_path_info_restore(bn, bpi);
8083 else
8084 bgp_aggregate_decrement(
8085 bgp, p, bpi, afi, SAFI_UNICAST);
8086 bgp_attr_unintern(&bpi->attr);
8087 bpi->attr = new_attr;
8088 bpi->uptime = bgp_clock();
8089
8090 /* Process change. */
8091 bgp_aggregate_increment(bgp, p, bpi, afi,
8092 SAFI_UNICAST);
8093 bgp_process(bgp, bn, afi, SAFI_UNICAST);
8094 bgp_dest_unlock_node(bn);
8095 aspath_unintern(&attr.aspath);
8096
8097 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8098 || (bgp->inst_type
8099 == BGP_INSTANCE_TYPE_DEFAULT)) {
8100
8101 vpn_leak_from_vrf_update(
8102 bgp_get_default(), bgp, bpi);
8103 }
8104 return;
8105 }
8106 }
8107
8108 new = info_make(type, BGP_ROUTE_REDISTRIBUTE, instance,
8109 bgp->peer_self, new_attr, bn);
8110 SET_FLAG(new->flags, BGP_PATH_VALID);
8111
8112 bgp_aggregate_increment(bgp, p, new, afi, SAFI_UNICAST);
8113 bgp_path_info_add(bn, new);
8114 bgp_dest_unlock_node(bn);
8115 bgp_process(bgp, bn, afi, SAFI_UNICAST);
8116
8117 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8118 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8119
8120 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
8121 }
8122 }
8123
8124 /* Unintern original. */
8125 aspath_unintern(&attr.aspath);
8126 }
8127
8128 void bgp_redistribute_delete(struct bgp *bgp, struct prefix *p, uint8_t type,
8129 unsigned short instance)
8130 {
8131 afi_t afi;
8132 struct bgp_dest *dest;
8133 struct bgp_path_info *pi;
8134 struct bgp_redist *red;
8135
8136 afi = family2afi(p->family);
8137
8138 red = bgp_redist_lookup(bgp, afi, type, instance);
8139 if (red) {
8140 dest = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8141 SAFI_UNICAST, p, NULL);
8142
8143 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
8144 if (pi->peer == bgp->peer_self && pi->type == type)
8145 break;
8146
8147 if (pi) {
8148 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8149 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8150
8151 vpn_leak_from_vrf_withdraw(bgp_get_default(),
8152 bgp, pi);
8153 }
8154 bgp_aggregate_decrement(bgp, p, pi, afi, SAFI_UNICAST);
8155 bgp_path_info_delete(dest, pi);
8156 bgp_process(bgp, dest, afi, SAFI_UNICAST);
8157 }
8158 bgp_dest_unlock_node(dest);
8159 }
8160 }
8161
8162 /* Withdraw specified route type's route. */
8163 void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type,
8164 unsigned short instance)
8165 {
8166 struct bgp_dest *dest;
8167 struct bgp_path_info *pi;
8168 struct bgp_table *table;
8169
8170 table = bgp->rib[afi][SAFI_UNICAST];
8171
8172 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
8173 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
8174 if (pi->peer == bgp->peer_self && pi->type == type
8175 && pi->instance == instance)
8176 break;
8177
8178 if (pi) {
8179 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8180 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8181
8182 vpn_leak_from_vrf_withdraw(bgp_get_default(),
8183 bgp, pi);
8184 }
8185 bgp_aggregate_decrement(bgp, bgp_dest_get_prefix(dest),
8186 pi, afi, SAFI_UNICAST);
8187 bgp_path_info_delete(dest, pi);
8188 bgp_process(bgp, dest, afi, SAFI_UNICAST);
8189 }
8190 }
8191 }
8192
8193 /* Static function to display route. */
8194 static void route_vty_out_route(const struct prefix *p, struct vty *vty,
8195 json_object *json, bool wide)
8196 {
8197 int len = 0;
8198 char buf[BUFSIZ];
8199 char buf2[BUFSIZ];
8200
8201 if (p->family == AF_INET) {
8202 if (!json) {
8203 len = vty_out(vty, "%pFX", p);
8204 } else {
8205 json_object_string_add(json, "prefix",
8206 inet_ntop(p->family,
8207 &p->u.prefix, buf,
8208 BUFSIZ));
8209 json_object_int_add(json, "prefixLen", p->prefixlen);
8210 prefix2str(p, buf2, PREFIX_STRLEN);
8211 json_object_string_add(json, "network", buf2);
8212 }
8213 } else if (p->family == AF_ETHERNET) {
8214 len = vty_out(vty, "%pFX", p);
8215 } else if (p->family == AF_EVPN) {
8216 if (!json)
8217 len = vty_out(vty, "%pFX", (struct prefix_evpn *)p);
8218 else
8219 bgp_evpn_route2json((struct prefix_evpn *)p, json);
8220 } else if (p->family == AF_FLOWSPEC) {
8221 route_vty_out_flowspec(vty, p, NULL,
8222 json ?
8223 NLRI_STRING_FORMAT_JSON_SIMPLE :
8224 NLRI_STRING_FORMAT_MIN, json);
8225 } else {
8226 if (!json)
8227 len = vty_out(vty, "%pFX", p);
8228 else {
8229 json_object_string_add(json, "prefix",
8230 inet_ntop(p->family,
8231 &p->u.prefix, buf,
8232 BUFSIZ));
8233 json_object_int_add(json, "prefixLen", p->prefixlen);
8234 prefix2str(p, buf2, PREFIX_STRLEN);
8235 json_object_string_add(json, "network", buf2);
8236 }
8237 }
8238
8239 if (!json) {
8240 len = wide ? (45 - len) : (17 - len);
8241 if (len < 1)
8242 vty_out(vty, "\n%*s", 20, " ");
8243 else
8244 vty_out(vty, "%*s", len, " ");
8245 }
8246 }
8247
8248 enum bgp_display_type {
8249 normal_list,
8250 };
8251
8252 static const char *
8253 bgp_path_selection_reason2str(enum bgp_path_selection_reason reason)
8254 {
8255 switch (reason) {
8256 case bgp_path_selection_none:
8257 return "Nothing to Select";
8258 case bgp_path_selection_first:
8259 return "First path received";
8260 case bgp_path_selection_evpn_sticky_mac:
8261 return "EVPN Sticky Mac";
8262 case bgp_path_selection_evpn_seq:
8263 return "EVPN sequence number";
8264 case bgp_path_selection_evpn_lower_ip:
8265 return "EVPN lower IP";
8266 case bgp_path_selection_evpn_local_path:
8267 return "EVPN local ES path";
8268 case bgp_path_selection_evpn_non_proxy:
8269 return "EVPN non proxy";
8270 case bgp_path_selection_weight:
8271 return "Weight";
8272 case bgp_path_selection_local_pref:
8273 return "Local Pref";
8274 case bgp_path_selection_local_route:
8275 return "Local Route";
8276 case bgp_path_selection_confed_as_path:
8277 return "Confederation based AS Path";
8278 case bgp_path_selection_as_path:
8279 return "AS Path";
8280 case bgp_path_selection_origin:
8281 return "Origin";
8282 case bgp_path_selection_med:
8283 return "MED";
8284 case bgp_path_selection_peer:
8285 return "Peer Type";
8286 case bgp_path_selection_confed:
8287 return "Confed Peer Type";
8288 case bgp_path_selection_igp_metric:
8289 return "IGP Metric";
8290 case bgp_path_selection_older:
8291 return "Older Path";
8292 case bgp_path_selection_router_id:
8293 return "Router ID";
8294 case bgp_path_selection_cluster_length:
8295 return "Cluster length";
8296 case bgp_path_selection_stale:
8297 return "Path Staleness";
8298 case bgp_path_selection_local_configured:
8299 return "Locally configured route";
8300 case bgp_path_selection_neighbor_ip:
8301 return "Neighbor IP";
8302 case bgp_path_selection_default:
8303 return "Nothing left to compare";
8304 }
8305 return "Invalid (internal error)";
8306 }
8307
8308 /* Print the short form route status for a bgp_path_info */
8309 static void route_vty_short_status_out(struct vty *vty,
8310 struct bgp_path_info *path,
8311 json_object *json_path)
8312 {
8313 if (json_path) {
8314
8315 /* Route status display. */
8316 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
8317 json_object_boolean_true_add(json_path, "removed");
8318
8319 if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
8320 json_object_boolean_true_add(json_path, "stale");
8321
8322 if (path->extra && bgp_path_suppressed(path))
8323 json_object_boolean_true_add(json_path, "suppressed");
8324
8325 if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
8326 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
8327 json_object_boolean_true_add(json_path, "valid");
8328
8329 /* Selected */
8330 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
8331 json_object_boolean_true_add(json_path, "history");
8332
8333 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
8334 json_object_boolean_true_add(json_path, "damped");
8335
8336 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
8337 json_object_boolean_true_add(json_path, "bestpath");
8338 json_object_string_add(json_path, "selectionReason",
8339 bgp_path_selection_reason2str(
8340 path->net->reason));
8341 }
8342
8343 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
8344 json_object_boolean_true_add(json_path, "multipath");
8345
8346 /* Internal route. */
8347 if ((path->peer->as)
8348 && (path->peer->as == path->peer->local_as))
8349 json_object_string_add(json_path, "pathFrom",
8350 "internal");
8351 else
8352 json_object_string_add(json_path, "pathFrom",
8353 "external");
8354
8355 return;
8356 }
8357
8358 /* Route status display. */
8359 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
8360 vty_out(vty, "R");
8361 else if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
8362 vty_out(vty, "S");
8363 else if (bgp_path_suppressed(path))
8364 vty_out(vty, "s");
8365 else if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
8366 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
8367 vty_out(vty, "*");
8368 else
8369 vty_out(vty, " ");
8370
8371 /* Selected */
8372 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
8373 vty_out(vty, "h");
8374 else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
8375 vty_out(vty, "d");
8376 else if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
8377 vty_out(vty, ">");
8378 else if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
8379 vty_out(vty, "=");
8380 else
8381 vty_out(vty, " ");
8382
8383 /* Internal route. */
8384 if (path->peer && (path->peer->as)
8385 && (path->peer->as == path->peer->local_as))
8386 vty_out(vty, "i");
8387 else
8388 vty_out(vty, " ");
8389 }
8390
8391 static char *bgp_nexthop_hostname(struct peer *peer,
8392 struct bgp_nexthop_cache *bnc)
8393 {
8394 if (peer->hostname
8395 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME))
8396 return peer->hostname;
8397 return NULL;
8398 }
8399
8400 /* called from terminal list command */
8401 void route_vty_out(struct vty *vty, const struct prefix *p,
8402 struct bgp_path_info *path, int display, safi_t safi,
8403 json_object *json_paths, bool wide)
8404 {
8405 int len;
8406 struct attr *attr = path->attr;
8407 json_object *json_path = NULL;
8408 json_object *json_nexthops = NULL;
8409 json_object *json_nexthop_global = NULL;
8410 json_object *json_nexthop_ll = NULL;
8411 json_object *json_ext_community = NULL;
8412 char vrf_id_str[VRF_NAMSIZ] = {0};
8413 bool nexthop_self =
8414 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
8415 bool nexthop_othervrf = false;
8416 vrf_id_t nexthop_vrfid = VRF_DEFAULT;
8417 const char *nexthop_vrfname = VRF_DEFAULT_NAME;
8418 char *nexthop_hostname =
8419 bgp_nexthop_hostname(path->peer, path->nexthop);
8420 char esi_buf[ESI_STR_LEN];
8421
8422 if (json_paths)
8423 json_path = json_object_new_object();
8424
8425 /* short status lead text */
8426 route_vty_short_status_out(vty, path, json_path);
8427
8428 if (!json_paths) {
8429 /* print prefix and mask */
8430 if (!display)
8431 route_vty_out_route(p, vty, json_path, wide);
8432 else
8433 vty_out(vty, "%*s", (wide ? 45 : 17), " ");
8434 } else {
8435 route_vty_out_route(p, vty, json_path, wide);
8436 }
8437
8438 /*
8439 * If vrf id of nexthop is different from that of prefix,
8440 * set up printable string to append
8441 */
8442 if (path->extra && path->extra->bgp_orig) {
8443 const char *self = "";
8444
8445 if (nexthop_self)
8446 self = "<";
8447
8448 nexthop_othervrf = true;
8449 nexthop_vrfid = path->extra->bgp_orig->vrf_id;
8450
8451 if (path->extra->bgp_orig->vrf_id == VRF_UNKNOWN)
8452 snprintf(vrf_id_str, sizeof(vrf_id_str),
8453 "@%s%s", VRFID_NONE_STR, self);
8454 else
8455 snprintf(vrf_id_str, sizeof(vrf_id_str), "@%u%s",
8456 path->extra->bgp_orig->vrf_id, self);
8457
8458 if (path->extra->bgp_orig->inst_type
8459 != BGP_INSTANCE_TYPE_DEFAULT)
8460
8461 nexthop_vrfname = path->extra->bgp_orig->name;
8462 } else {
8463 const char *self = "";
8464
8465 if (nexthop_self)
8466 self = "<";
8467
8468 snprintf(vrf_id_str, sizeof(vrf_id_str), "%s", self);
8469 }
8470
8471 /*
8472 * For ENCAP and EVPN routes, nexthop address family is not
8473 * neccessarily the same as the prefix address family.
8474 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
8475 * EVPN routes are also exchanged with a MP nexthop. Currently,
8476 * this
8477 * is only IPv4, the value will be present in either
8478 * attr->nexthop or
8479 * attr->mp_nexthop_global_in
8480 */
8481 if ((safi == SAFI_ENCAP) || (safi == SAFI_MPLS_VPN)) {
8482 char buf[BUFSIZ];
8483 char nexthop[128];
8484 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
8485
8486 switch (af) {
8487 case AF_INET:
8488 snprintf(nexthop, sizeof(nexthop), "%s",
8489 inet_ntop(af, &attr->mp_nexthop_global_in, buf,
8490 BUFSIZ));
8491 break;
8492 case AF_INET6:
8493 snprintf(nexthop, sizeof(nexthop), "%s",
8494 inet_ntop(af, &attr->mp_nexthop_global, buf,
8495 BUFSIZ));
8496 break;
8497 default:
8498 snprintf(nexthop, sizeof(nexthop), "?");
8499 break;
8500 }
8501
8502 if (json_paths) {
8503 json_nexthop_global = json_object_new_object();
8504
8505 json_object_string_add(json_nexthop_global, "ip",
8506 nexthop);
8507
8508 if (path->peer->hostname)
8509 json_object_string_add(json_nexthop_global,
8510 "hostname",
8511 path->peer->hostname);
8512
8513 json_object_string_add(json_nexthop_global, "afi",
8514 (af == AF_INET) ? "ipv4"
8515 : "ipv6");
8516 json_object_boolean_true_add(json_nexthop_global,
8517 "used");
8518 } else {
8519 if (nexthop_hostname)
8520 len = vty_out(vty, "%s(%s)%s", nexthop,
8521 nexthop_hostname, vrf_id_str);
8522 else
8523 len = vty_out(vty, "%s%s", nexthop, vrf_id_str);
8524
8525 len = wide ? (41 - len) : (16 - len);
8526 if (len < 1)
8527 vty_out(vty, "\n%*s", 36, " ");
8528 else
8529 vty_out(vty, "%*s", len, " ");
8530 }
8531 } else if (safi == SAFI_EVPN) {
8532 if (json_paths) {
8533 char buf[BUFSIZ] = {0};
8534
8535 json_nexthop_global = json_object_new_object();
8536
8537 json_object_string_add(json_nexthop_global, "ip",
8538 inet_ntop(AF_INET,
8539 &attr->nexthop, buf,
8540 sizeof(buf)));
8541
8542 if (path->peer->hostname)
8543 json_object_string_add(json_nexthop_global,
8544 "hostname",
8545 path->peer->hostname);
8546
8547 json_object_string_add(json_nexthop_global, "afi",
8548 "ipv4");
8549 json_object_boolean_true_add(json_nexthop_global,
8550 "used");
8551 } else {
8552 if (nexthop_hostname)
8553 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
8554 nexthop_hostname, vrf_id_str);
8555 else
8556 len = vty_out(vty, "%pI4%s", &attr->nexthop,
8557 vrf_id_str);
8558
8559 len = wide ? (41 - len) : (16 - len);
8560 if (len < 1)
8561 vty_out(vty, "\n%*s", 36, " ");
8562 else
8563 vty_out(vty, "%*s", len, " ");
8564 }
8565 } else if (safi == SAFI_FLOWSPEC) {
8566 if (attr->nexthop.s_addr != INADDR_ANY) {
8567 if (json_paths) {
8568 char buf[BUFSIZ] = {0};
8569
8570 json_nexthop_global = json_object_new_object();
8571
8572 json_object_string_add(json_nexthop_global,
8573 "afi", "ipv4");
8574 json_object_string_add(
8575 json_nexthop_global, "ip",
8576 inet_ntop(AF_INET, &attr->nexthop, buf,
8577 sizeof(buf)));
8578
8579 if (path->peer->hostname)
8580 json_object_string_add(
8581 json_nexthop_global, "hostname",
8582 path->peer->hostname);
8583
8584 json_object_boolean_true_add(
8585 json_nexthop_global,
8586 "used");
8587 } else {
8588 if (nexthop_hostname)
8589 len = vty_out(vty, "%pI4(%s)%s",
8590 &attr->nexthop,
8591 nexthop_hostname,
8592 vrf_id_str);
8593 else
8594 len = vty_out(vty, "%pI4%s",
8595 &attr->nexthop,
8596 vrf_id_str);
8597
8598 len = wide ? (41 - len) : (16 - len);
8599 if (len < 1)
8600 vty_out(vty, "\n%*s", 36, " ");
8601 else
8602 vty_out(vty, "%*s", len, " ");
8603 }
8604 }
8605 } else if (p->family == AF_INET && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
8606 if (json_paths) {
8607 char buf[BUFSIZ] = {0};
8608
8609 json_nexthop_global = json_object_new_object();
8610
8611 json_object_string_add(json_nexthop_global, "ip",
8612 inet_ntop(AF_INET,
8613 &attr->nexthop, buf,
8614 sizeof(buf)));
8615
8616 if (path->peer->hostname)
8617 json_object_string_add(json_nexthop_global,
8618 "hostname",
8619 path->peer->hostname);
8620
8621 json_object_string_add(json_nexthop_global, "afi",
8622 "ipv4");
8623 json_object_boolean_true_add(json_nexthop_global,
8624 "used");
8625 } else {
8626 if (nexthop_hostname)
8627 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
8628 nexthop_hostname, vrf_id_str);
8629 else
8630 len = vty_out(vty, "%pI4%s", &attr->nexthop,
8631 vrf_id_str);
8632
8633 len = wide ? (41 - len) : (16 - len);
8634 if (len < 1)
8635 vty_out(vty, "\n%*s", 36, " ");
8636 else
8637 vty_out(vty, "%*s", len, " ");
8638 }
8639 }
8640
8641 /* IPv6 Next Hop */
8642 else if (p->family == AF_INET6 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
8643 char buf[BUFSIZ];
8644
8645 if (json_paths) {
8646 json_nexthop_global = json_object_new_object();
8647 json_object_string_add(
8648 json_nexthop_global, "ip",
8649 inet_ntop(AF_INET6, &attr->mp_nexthop_global,
8650 buf, BUFSIZ));
8651
8652 if (path->peer->hostname)
8653 json_object_string_add(json_nexthop_global,
8654 "hostname",
8655 path->peer->hostname);
8656
8657 json_object_string_add(json_nexthop_global, "afi",
8658 "ipv6");
8659 json_object_string_add(json_nexthop_global, "scope",
8660 "global");
8661
8662 /* We display both LL & GL if both have been
8663 * received */
8664 if ((attr->mp_nexthop_len
8665 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
8666 || (path->peer->conf_if)) {
8667 json_nexthop_ll = json_object_new_object();
8668 json_object_string_add(
8669 json_nexthop_ll, "ip",
8670 inet_ntop(AF_INET6,
8671 &attr->mp_nexthop_local, buf,
8672 BUFSIZ));
8673
8674 if (path->peer->hostname)
8675 json_object_string_add(
8676 json_nexthop_ll, "hostname",
8677 path->peer->hostname);
8678
8679 json_object_string_add(json_nexthop_ll, "afi",
8680 "ipv6");
8681 json_object_string_add(json_nexthop_ll, "scope",
8682 "link-local");
8683
8684 if ((IPV6_ADDR_CMP(&attr->mp_nexthop_global,
8685 &attr->mp_nexthop_local)
8686 != 0)
8687 && !attr->mp_nexthop_prefer_global)
8688 json_object_boolean_true_add(
8689 json_nexthop_ll, "used");
8690 else
8691 json_object_boolean_true_add(
8692 json_nexthop_global, "used");
8693 } else
8694 json_object_boolean_true_add(
8695 json_nexthop_global, "used");
8696 } else {
8697 /* Display LL if LL/Global both in table unless
8698 * prefer-global is set */
8699 if (((attr->mp_nexthop_len
8700 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
8701 && !attr->mp_nexthop_prefer_global)
8702 || (path->peer->conf_if)) {
8703 if (path->peer->conf_if) {
8704 len = vty_out(vty, "%s",
8705 path->peer->conf_if);
8706 /* len of IPv6 addr + max len of def
8707 * ifname */
8708 len = wide ? (41 - len) : (16 - len);
8709
8710 if (len < 1)
8711 vty_out(vty, "\n%*s", 36, " ");
8712 else
8713 vty_out(vty, "%*s", len, " ");
8714 } else {
8715 if (nexthop_hostname)
8716 len = vty_out(
8717 vty, "%pI6(%s)%s",
8718 &attr->mp_nexthop_local,
8719 nexthop_hostname,
8720 vrf_id_str);
8721 else
8722 len = vty_out(
8723 vty, "%pI6%s",
8724 &attr->mp_nexthop_local,
8725 vrf_id_str);
8726
8727 len = wide ? (41 - len) : (16 - len);
8728
8729 if (len < 1)
8730 vty_out(vty, "\n%*s", 36, " ");
8731 else
8732 vty_out(vty, "%*s", len, " ");
8733 }
8734 } else {
8735 if (nexthop_hostname)
8736 len = vty_out(vty, "%pI6(%s)%s",
8737 &attr->mp_nexthop_global,
8738 nexthop_hostname,
8739 vrf_id_str);
8740 else
8741 len = vty_out(vty, "%pI6%s",
8742 &attr->mp_nexthop_global,
8743 vrf_id_str);
8744
8745 len = wide ? (41 - len) : (16 - len);
8746
8747 if (len < 1)
8748 vty_out(vty, "\n%*s", 36, " ");
8749 else
8750 vty_out(vty, "%*s", len, " ");
8751 }
8752 }
8753 }
8754
8755 /* MED/Metric */
8756 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
8757 if (json_paths)
8758 json_object_int_add(json_path, "metric", attr->med);
8759 else if (wide)
8760 vty_out(vty, "%7u", attr->med);
8761 else
8762 vty_out(vty, "%10u", attr->med);
8763 else if (!json_paths) {
8764 if (wide)
8765 vty_out(vty, "%*s", 7, " ");
8766 else
8767 vty_out(vty, "%*s", 10, " ");
8768 }
8769
8770 /* Local Pref */
8771 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
8772 if (json_paths)
8773 json_object_int_add(json_path, "locPrf",
8774 attr->local_pref);
8775 else
8776 vty_out(vty, "%7u", attr->local_pref);
8777 else if (!json_paths)
8778 vty_out(vty, " ");
8779
8780 if (json_paths)
8781 json_object_int_add(json_path, "weight", attr->weight);
8782 else
8783 vty_out(vty, "%7u ", attr->weight);
8784
8785 if (json_paths) {
8786 char buf[BUFSIZ];
8787 json_object_string_add(
8788 json_path, "peerId",
8789 sockunion2str(&path->peer->su, buf, SU_ADDRSTRLEN));
8790 }
8791
8792 /* Print aspath */
8793 if (attr->aspath) {
8794 if (json_paths)
8795 json_object_string_add(json_path, "path",
8796 attr->aspath->str);
8797 else
8798 aspath_print_vty(vty, "%s", attr->aspath, " ");
8799 }
8800
8801 /* Print origin */
8802 if (json_paths)
8803 json_object_string_add(json_path, "origin",
8804 bgp_origin_long_str[attr->origin]);
8805 else
8806 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
8807
8808 if (json_paths) {
8809 if (bgp_evpn_is_esi_valid(&attr->esi)) {
8810 json_object_string_add(json_path, "esi",
8811 esi_to_str(&attr->esi,
8812 esi_buf, sizeof(esi_buf)));
8813 }
8814 if (safi == SAFI_EVPN &&
8815 attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
8816 json_ext_community = json_object_new_object();
8817 json_object_string_add(json_ext_community,
8818 "string",
8819 attr->ecommunity->str);
8820 json_object_object_add(json_path,
8821 "extendedCommunity",
8822 json_ext_community);
8823 }
8824
8825 if (nexthop_self)
8826 json_object_boolean_true_add(json_path,
8827 "announceNexthopSelf");
8828 if (nexthop_othervrf) {
8829 json_object_string_add(json_path, "nhVrfName",
8830 nexthop_vrfname);
8831
8832 json_object_int_add(json_path, "nhVrfId",
8833 ((nexthop_vrfid == VRF_UNKNOWN)
8834 ? -1
8835 : (int)nexthop_vrfid));
8836 }
8837 }
8838
8839 if (json_paths) {
8840 if (json_nexthop_global || json_nexthop_ll) {
8841 json_nexthops = json_object_new_array();
8842
8843 if (json_nexthop_global)
8844 json_object_array_add(json_nexthops,
8845 json_nexthop_global);
8846
8847 if (json_nexthop_ll)
8848 json_object_array_add(json_nexthops,
8849 json_nexthop_ll);
8850
8851 json_object_object_add(json_path, "nexthops",
8852 json_nexthops);
8853 }
8854
8855 json_object_array_add(json_paths, json_path);
8856 } else {
8857 vty_out(vty, "\n");
8858
8859 if (safi == SAFI_EVPN) {
8860 struct bgp_path_es_info *path_es_info = NULL;
8861
8862 if (bgp_evpn_is_esi_valid(&attr->esi)) {
8863 /* XXX - add these params to the json out */
8864 vty_out(vty, "%*s", 20, " ");
8865 vty_out(vty, "ESI:%s",
8866 esi_to_str(&attr->esi, esi_buf,
8867 sizeof(esi_buf)));
8868
8869 if (path->extra && path->extra->mh_info)
8870 path_es_info =
8871 path->extra->mh_info->es_info;
8872
8873 if (path_es_info && path_es_info->es)
8874 vty_out(vty, " VNI: %u",
8875 path_es_info->vni);
8876 vty_out(vty, "\n");
8877 }
8878 if (attr->flag &
8879 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
8880 vty_out(vty, "%*s", 20, " ");
8881 vty_out(vty, "%s\n", attr->ecommunity->str);
8882 }
8883 }
8884
8885 #ifdef ENABLE_BGP_VNC
8886 /* prints an additional line, indented, with VNC info, if
8887 * present */
8888 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
8889 rfapi_vty_out_vncinfo(vty, p, path, safi);
8890 #endif
8891 }
8892 }
8893
8894 /* called from terminal list command */
8895 void route_vty_out_tmp(struct vty *vty, const struct prefix *p,
8896 struct attr *attr, safi_t safi, bool use_json,
8897 json_object *json_ar, bool wide)
8898 {
8899 json_object *json_status = NULL;
8900 json_object *json_net = NULL;
8901 int len;
8902 char buff[BUFSIZ];
8903
8904 /* Route status display. */
8905 if (use_json) {
8906 json_status = json_object_new_object();
8907 json_net = json_object_new_object();
8908 } else {
8909 vty_out(vty, "*");
8910 vty_out(vty, ">");
8911 vty_out(vty, " ");
8912 }
8913
8914 /* print prefix and mask */
8915 if (use_json) {
8916 if (safi == SAFI_EVPN)
8917 bgp_evpn_route2json((struct prefix_evpn *)p, json_net);
8918 else if (p->family == AF_INET || p->family == AF_INET6) {
8919 json_object_string_add(
8920 json_net, "addrPrefix",
8921 inet_ntop(p->family, &p->u.prefix, buff,
8922 BUFSIZ));
8923 json_object_int_add(json_net, "prefixLen",
8924 p->prefixlen);
8925 prefix2str(p, buff, PREFIX_STRLEN);
8926 json_object_string_add(json_net, "network", buff);
8927 }
8928 } else
8929 route_vty_out_route(p, vty, NULL, wide);
8930
8931 /* Print attribute */
8932 if (attr) {
8933 if (use_json) {
8934 char buf[BUFSIZ] = {0};
8935
8936 if (p->family == AF_INET
8937 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
8938 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
8939 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
8940 json_object_string_add(
8941 json_net, "nextHop",
8942 inet_ntop(
8943 AF_INET,
8944 &attr->mp_nexthop_global_in,
8945 buf, sizeof(buf)));
8946 else
8947 json_object_string_add(
8948 json_net, "nextHop",
8949 inet_ntop(AF_INET,
8950 &attr->nexthop, buf,
8951 sizeof(buf)));
8952 } else if (p->family == AF_INET6
8953 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
8954 char buf[BUFSIZ];
8955
8956 json_object_string_add(
8957 json_net, "nextHopGlobal",
8958 inet_ntop(AF_INET6,
8959 &attr->mp_nexthop_global, buf,
8960 BUFSIZ));
8961 } else if (p->family == AF_EVPN
8962 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
8963 char buf[BUFSIZ] = {0};
8964
8965 json_object_string_add(
8966 json_net, "nextHop",
8967 inet_ntop(AF_INET,
8968 &attr->mp_nexthop_global_in,
8969 buf, sizeof(buf)));
8970 }
8971
8972 if (attr->flag
8973 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
8974 json_object_int_add(json_net, "metric",
8975 attr->med);
8976
8977 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
8978 json_object_int_add(json_net, "locPrf",
8979 attr->local_pref);
8980
8981 json_object_int_add(json_net, "weight", attr->weight);
8982
8983 /* Print aspath */
8984 if (attr->aspath)
8985 json_object_string_add(json_net, "path",
8986 attr->aspath->str);
8987
8988 /* Print origin */
8989 json_object_string_add(json_net, "bgpOriginCode",
8990 bgp_origin_str[attr->origin]);
8991 } else {
8992 if (p->family == AF_INET
8993 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
8994 || safi == SAFI_EVPN
8995 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
8996 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
8997 || safi == SAFI_EVPN)
8998 vty_out(vty, "%-16pI4",
8999 &attr->mp_nexthop_global_in);
9000 else if (wide)
9001 vty_out(vty, "%-41pI4", &attr->nexthop);
9002 else
9003 vty_out(vty, "%-16pI4", &attr->nexthop);
9004 } else if (p->family == AF_INET6
9005 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
9006 char buf[BUFSIZ];
9007
9008 len = vty_out(
9009 vty, "%s",
9010 inet_ntop(AF_INET6,
9011 &attr->mp_nexthop_global, buf,
9012 BUFSIZ));
9013 len = wide ? (41 - len) : (16 - len);
9014 if (len < 1)
9015 vty_out(vty, "\n%*s", 36, " ");
9016 else
9017 vty_out(vty, "%*s", len, " ");
9018 }
9019 if (attr->flag
9020 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
9021 if (wide)
9022 vty_out(vty, "%7u", attr->med);
9023 else
9024 vty_out(vty, "%10u", attr->med);
9025 else if (wide)
9026 vty_out(vty, " ");
9027 else
9028 vty_out(vty, " ");
9029
9030 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
9031 vty_out(vty, "%7u", attr->local_pref);
9032 else
9033 vty_out(vty, " ");
9034
9035 vty_out(vty, "%7u ", attr->weight);
9036
9037 /* Print aspath */
9038 if (attr->aspath)
9039 aspath_print_vty(vty, "%s", attr->aspath, " ");
9040
9041 /* Print origin */
9042 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9043 }
9044 }
9045 if (use_json) {
9046 json_object_boolean_true_add(json_status, "*");
9047 json_object_boolean_true_add(json_status, ">");
9048 json_object_object_add(json_net, "appliedStatusSymbols",
9049 json_status);
9050
9051 prefix2str(p, buff, PREFIX_STRLEN);
9052 json_object_object_add(json_ar, buff, json_net);
9053 } else
9054 vty_out(vty, "\n");
9055 }
9056
9057 void route_vty_out_tag(struct vty *vty, const struct prefix *p,
9058 struct bgp_path_info *path, int display, safi_t safi,
9059 json_object *json)
9060 {
9061 json_object *json_out = NULL;
9062 struct attr *attr;
9063 mpls_label_t label = MPLS_INVALID_LABEL;
9064
9065 if (!path->extra)
9066 return;
9067
9068 if (json)
9069 json_out = json_object_new_object();
9070
9071 /* short status lead text */
9072 route_vty_short_status_out(vty, path, json_out);
9073
9074 /* print prefix and mask */
9075 if (json == NULL) {
9076 if (!display)
9077 route_vty_out_route(p, vty, NULL, false);
9078 else
9079 vty_out(vty, "%*s", 17, " ");
9080 }
9081
9082 /* Print attribute */
9083 attr = path->attr;
9084 if (((p->family == AF_INET)
9085 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
9086 || (safi == SAFI_EVPN && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))
9087 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
9088 char buf[BUFSIZ] = {0};
9089
9090 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9091 || safi == SAFI_EVPN) {
9092 if (json)
9093 json_object_string_add(
9094 json_out, "mpNexthopGlobalIn",
9095 inet_ntop(AF_INET,
9096 &attr->mp_nexthop_global_in,
9097 buf, sizeof(buf)));
9098 else
9099 vty_out(vty, "%-16pI4",
9100 &attr->mp_nexthop_global_in);
9101 } else {
9102 if (json)
9103 json_object_string_add(
9104 json_out, "nexthop",
9105 inet_ntop(AF_INET, &attr->nexthop, buf,
9106 sizeof(buf)));
9107 else
9108 vty_out(vty, "%-16pI4", &attr->nexthop);
9109 }
9110 } else if (((p->family == AF_INET6)
9111 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
9112 || (safi == SAFI_EVPN && BGP_ATTR_NEXTHOP_AFI_IP6(attr))
9113 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
9114 char buf_a[512];
9115
9116 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL) {
9117 if (json)
9118 json_object_string_add(
9119 json_out, "mpNexthopGlobalIn",
9120 inet_ntop(AF_INET6,
9121 &attr->mp_nexthop_global,
9122 buf_a, sizeof(buf_a)));
9123 else
9124 vty_out(vty, "%s",
9125 inet_ntop(AF_INET6,
9126 &attr->mp_nexthop_global,
9127 buf_a, sizeof(buf_a)));
9128 } else if (attr->mp_nexthop_len
9129 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
9130 snprintfrr(buf_a, sizeof(buf_a), "%pI6(%pI6)",
9131 &attr->mp_nexthop_global,
9132 &attr->mp_nexthop_local);
9133 if (json)
9134 json_object_string_add(json_out,
9135 "mpNexthopGlobalLocal",
9136 buf_a);
9137 else
9138 vty_out(vty, "%s", buf_a);
9139 }
9140 }
9141
9142 label = decode_label(&path->extra->label[0]);
9143
9144 if (bgp_is_valid_label(&label)) {
9145 if (json) {
9146 json_object_int_add(json_out, "notag", label);
9147 json_object_array_add(json, json_out);
9148 } else {
9149 vty_out(vty, "notag/%d", label);
9150 vty_out(vty, "\n");
9151 }
9152 }
9153 }
9154
9155 void route_vty_out_overlay(struct vty *vty, const struct prefix *p,
9156 struct bgp_path_info *path, int display,
9157 json_object *json_paths)
9158 {
9159 struct attr *attr;
9160 char buf[BUFSIZ] = {0};
9161 json_object *json_path = NULL;
9162 json_object *json_nexthop = NULL;
9163 json_object *json_overlay = NULL;
9164
9165 if (!path->extra)
9166 return;
9167
9168 if (json_paths) {
9169 json_path = json_object_new_object();
9170 json_overlay = json_object_new_object();
9171 json_nexthop = json_object_new_object();
9172 }
9173
9174 /* short status lead text */
9175 route_vty_short_status_out(vty, path, json_path);
9176
9177 /* print prefix and mask */
9178 if (!display)
9179 route_vty_out_route(p, vty, json_path, false);
9180 else
9181 vty_out(vty, "%*s", 17, " ");
9182
9183 /* Print attribute */
9184 attr = path->attr;
9185 char buf1[BUFSIZ];
9186 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
9187
9188 switch (af) {
9189 case AF_INET:
9190 inet_ntop(af, &attr->mp_nexthop_global_in, buf, BUFSIZ);
9191 if (!json_path) {
9192 vty_out(vty, "%-16s", buf);
9193 } else {
9194 json_object_string_add(json_nexthop, "ip", buf);
9195
9196 json_object_string_add(json_nexthop, "afi", "ipv4");
9197
9198 json_object_object_add(json_path, "nexthop",
9199 json_nexthop);
9200 }
9201 break;
9202 case AF_INET6:
9203 inet_ntop(af, &attr->mp_nexthop_global, buf, BUFSIZ);
9204 inet_ntop(af, &attr->mp_nexthop_local, buf1, BUFSIZ);
9205 if (!json_path) {
9206 vty_out(vty, "%s(%s)", buf, buf1);
9207 } else {
9208 json_object_string_add(json_nexthop, "ipv6Global", buf);
9209
9210 json_object_string_add(json_nexthop, "ipv6LinkLocal",
9211 buf1);
9212
9213 json_object_string_add(json_nexthop, "afi", "ipv6");
9214
9215 json_object_object_add(json_path, "nexthop",
9216 json_nexthop);
9217 }
9218 break;
9219 default:
9220 if (!json_path) {
9221 vty_out(vty, "?");
9222 } else {
9223 json_object_string_add(json_nexthop, "Error",
9224 "Unsupported address-family");
9225 }
9226 }
9227
9228 const struct bgp_route_evpn *eo = bgp_attr_get_evpn_overlay(attr);
9229
9230 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn *)p))
9231 inet_ntop(AF_INET, &eo->gw_ip.ipv4, buf, BUFSIZ);
9232 else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn *)p))
9233 inet_ntop(AF_INET6, &eo->gw_ip.ipv6, buf, BUFSIZ);
9234
9235 if (!json_path)
9236 vty_out(vty, "/%s", buf);
9237 else
9238 json_object_string_add(json_overlay, "gw", buf);
9239
9240 if (attr->ecommunity) {
9241 char *mac = NULL;
9242 struct ecommunity_val *routermac = ecommunity_lookup(
9243 attr->ecommunity, ECOMMUNITY_ENCODE_EVPN,
9244 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC);
9245
9246 if (routermac)
9247 mac = ecom_mac2str((char *)routermac->val);
9248 if (mac) {
9249 if (!json_path) {
9250 vty_out(vty, "/%s", mac);
9251 } else {
9252 json_object_string_add(json_overlay, "rmac",
9253 mac);
9254 }
9255 XFREE(MTYPE_TMP, mac);
9256 }
9257 }
9258
9259 if (!json_path) {
9260 vty_out(vty, "\n");
9261 } else {
9262 json_object_object_add(json_path, "overlay", json_overlay);
9263
9264 json_object_array_add(json_paths, json_path);
9265 }
9266 }
9267
9268 /* dampening route */
9269 static void damp_route_vty_out(struct vty *vty, const struct prefix *p,
9270 struct bgp_path_info *path, int display,
9271 afi_t afi, safi_t safi, bool use_json,
9272 json_object *json)
9273 {
9274 struct attr *attr;
9275 int len;
9276 char timebuf[BGP_UPTIME_LEN];
9277
9278 /* short status lead text */
9279 route_vty_short_status_out(vty, path, json);
9280
9281 /* print prefix and mask */
9282 if (!use_json) {
9283 if (!display)
9284 route_vty_out_route(p, vty, NULL, false);
9285 else
9286 vty_out(vty, "%*s", 17, " ");
9287 }
9288
9289 len = vty_out(vty, "%s", path->peer->host);
9290 len = 17 - len;
9291 if (len < 1) {
9292 if (!use_json)
9293 vty_out(vty, "\n%*s", 34, " ");
9294 } else {
9295 if (use_json)
9296 json_object_int_add(json, "peerHost", len);
9297 else
9298 vty_out(vty, "%*s", len, " ");
9299 }
9300
9301 if (use_json)
9302 bgp_damp_reuse_time_vty(vty, path, timebuf, BGP_UPTIME_LEN, afi,
9303 safi, use_json, json);
9304 else
9305 vty_out(vty, "%s ",
9306 bgp_damp_reuse_time_vty(vty, path, timebuf,
9307 BGP_UPTIME_LEN, afi, safi,
9308 use_json, json));
9309
9310 /* Print attribute */
9311 attr = path->attr;
9312
9313 /* Print aspath */
9314 if (attr->aspath) {
9315 if (use_json)
9316 json_object_string_add(json, "asPath",
9317 attr->aspath->str);
9318 else
9319 aspath_print_vty(vty, "%s", attr->aspath, " ");
9320 }
9321
9322 /* Print origin */
9323 if (use_json)
9324 json_object_string_add(json, "origin",
9325 bgp_origin_str[attr->origin]);
9326 else
9327 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9328
9329 if (!use_json)
9330 vty_out(vty, "\n");
9331 }
9332
9333 /* flap route */
9334 static void flap_route_vty_out(struct vty *vty, const struct prefix *p,
9335 struct bgp_path_info *path, int display,
9336 afi_t afi, safi_t safi, bool use_json,
9337 json_object *json)
9338 {
9339 struct attr *attr;
9340 struct bgp_damp_info *bdi;
9341 char timebuf[BGP_UPTIME_LEN];
9342 int len;
9343
9344 if (!path->extra)
9345 return;
9346
9347 bdi = path->extra->damp_info;
9348
9349 /* short status lead text */
9350 route_vty_short_status_out(vty, path, json);
9351
9352 /* print prefix and mask */
9353 if (!use_json) {
9354 if (!display)
9355 route_vty_out_route(p, vty, NULL, false);
9356 else
9357 vty_out(vty, "%*s", 17, " ");
9358 }
9359
9360 len = vty_out(vty, "%s", path->peer->host);
9361 len = 16 - len;
9362 if (len < 1) {
9363 if (!use_json)
9364 vty_out(vty, "\n%*s", 33, " ");
9365 } else {
9366 if (use_json)
9367 json_object_int_add(json, "peerHost", len);
9368 else
9369 vty_out(vty, "%*s", len, " ");
9370 }
9371
9372 len = vty_out(vty, "%d", bdi->flap);
9373 len = 5 - len;
9374 if (len < 1) {
9375 if (!use_json)
9376 vty_out(vty, " ");
9377 } else {
9378 if (use_json)
9379 json_object_int_add(json, "bdiFlap", len);
9380 else
9381 vty_out(vty, "%*s", len, " ");
9382 }
9383
9384 if (use_json)
9385 peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, use_json,
9386 json);
9387 else
9388 vty_out(vty, "%s ", peer_uptime(bdi->start_time, timebuf,
9389 BGP_UPTIME_LEN, 0, NULL));
9390
9391 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
9392 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
9393 if (use_json)
9394 bgp_damp_reuse_time_vty(vty, path, timebuf,
9395 BGP_UPTIME_LEN, afi, safi,
9396 use_json, json);
9397 else
9398 vty_out(vty, "%s ",
9399 bgp_damp_reuse_time_vty(vty, path, timebuf,
9400 BGP_UPTIME_LEN, afi,
9401 safi, use_json, json));
9402 } else {
9403 if (!use_json)
9404 vty_out(vty, "%*s ", 8, " ");
9405 }
9406
9407 /* Print attribute */
9408 attr = path->attr;
9409
9410 /* Print aspath */
9411 if (attr->aspath) {
9412 if (use_json)
9413 json_object_string_add(json, "asPath",
9414 attr->aspath->str);
9415 else
9416 aspath_print_vty(vty, "%s", attr->aspath, " ");
9417 }
9418
9419 /* Print origin */
9420 if (use_json)
9421 json_object_string_add(json, "origin",
9422 bgp_origin_str[attr->origin]);
9423 else
9424 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9425
9426 if (!use_json)
9427 vty_out(vty, "\n");
9428 }
9429
9430 static void route_vty_out_advertised_to(struct vty *vty, struct peer *peer,
9431 int *first, const char *header,
9432 json_object *json_adv_to)
9433 {
9434 char buf1[INET6_ADDRSTRLEN];
9435 json_object *json_peer = NULL;
9436
9437 if (json_adv_to) {
9438 /* 'advertised-to' is a dictionary of peers we have advertised
9439 * this
9440 * prefix too. The key is the peer's IP or swpX, the value is
9441 * the
9442 * hostname if we know it and "" if not.
9443 */
9444 json_peer = json_object_new_object();
9445
9446 if (peer->hostname)
9447 json_object_string_add(json_peer, "hostname",
9448 peer->hostname);
9449
9450 if (peer->conf_if)
9451 json_object_object_add(json_adv_to, peer->conf_if,
9452 json_peer);
9453 else
9454 json_object_object_add(
9455 json_adv_to,
9456 sockunion2str(&peer->su, buf1, SU_ADDRSTRLEN),
9457 json_peer);
9458 } else {
9459 if (*first) {
9460 vty_out(vty, "%s", header);
9461 *first = 0;
9462 }
9463
9464 if (peer->hostname
9465 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
9466 if (peer->conf_if)
9467 vty_out(vty, " %s(%s)", peer->hostname,
9468 peer->conf_if);
9469 else
9470 vty_out(vty, " %s(%s)", peer->hostname,
9471 sockunion2str(&peer->su, buf1,
9472 SU_ADDRSTRLEN));
9473 } else {
9474 if (peer->conf_if)
9475 vty_out(vty, " %s", peer->conf_if);
9476 else
9477 vty_out(vty, " %s",
9478 sockunion2str(&peer->su, buf1,
9479 SU_ADDRSTRLEN));
9480 }
9481 }
9482 }
9483
9484 static void route_vty_out_tx_ids(struct vty *vty,
9485 struct bgp_addpath_info_data *d)
9486 {
9487 int i;
9488
9489 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
9490 vty_out(vty, "TX-%s %u%s", bgp_addpath_names(i)->human_name,
9491 d->addpath_tx_id[i],
9492 i < BGP_ADDPATH_MAX - 1 ? " " : "\n");
9493 }
9494 }
9495
9496 static void route_vty_out_detail_es_info(struct vty *vty,
9497 struct bgp_path_info *pi,
9498 struct attr *attr,
9499 json_object *json_path)
9500 {
9501 char esi_buf[ESI_STR_LEN];
9502 bool es_local = !!CHECK_FLAG(attr->es_flags, ATTR_ES_IS_LOCAL);
9503 bool peer_router = !!CHECK_FLAG(attr->es_flags,
9504 ATTR_ES_PEER_ROUTER);
9505 bool peer_active = !!CHECK_FLAG(attr->es_flags,
9506 ATTR_ES_PEER_ACTIVE);
9507 bool peer_proxy = !!CHECK_FLAG(attr->es_flags,
9508 ATTR_ES_PEER_PROXY);
9509 esi_to_str(&attr->esi, esi_buf, sizeof(esi_buf));
9510 if (json_path) {
9511 json_object *json_es_info = NULL;
9512
9513 json_object_string_add(
9514 json_path, "esi",
9515 esi_buf);
9516 if (es_local || bgp_evpn_attr_is_sync(attr)) {
9517 json_es_info = json_object_new_object();
9518 if (es_local)
9519 json_object_boolean_true_add(
9520 json_es_info, "localEs");
9521 if (peer_active)
9522 json_object_boolean_true_add(
9523 json_es_info, "peerActive");
9524 if (peer_proxy)
9525 json_object_boolean_true_add(
9526 json_es_info, "peerProxy");
9527 if (peer_router)
9528 json_object_boolean_true_add(
9529 json_es_info, "peerRouter");
9530 if (attr->mm_sync_seqnum)
9531 json_object_int_add(
9532 json_es_info, "peerSeq",
9533 attr->mm_sync_seqnum);
9534 json_object_object_add(
9535 json_path, "es_info",
9536 json_es_info);
9537 }
9538 } else {
9539 if (bgp_evpn_attr_is_sync(attr))
9540 vty_out(vty,
9541 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
9542 esi_buf,
9543 es_local ? "local-es":"",
9544 peer_proxy ? "proxy " : "",
9545 peer_active ? "active ":"",
9546 peer_router ? "router ":"",
9547 attr->mm_sync_seqnum);
9548 else
9549 vty_out(vty, " ESI %s %s\n",
9550 esi_buf,
9551 es_local ? "local-es":"");
9552 }
9553 }
9554
9555 void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
9556 struct bgp_path_info *path, afi_t afi, safi_t safi,
9557 enum rpki_states curr_state, json_object *json_paths)
9558 {
9559 char buf[INET6_ADDRSTRLEN];
9560 char buf1[BUFSIZ];
9561 struct attr *attr = path->attr;
9562 int sockunion_vty_out(struct vty *, union sockunion *);
9563 time_t tbuf;
9564 json_object *json_bestpath = NULL;
9565 json_object *json_cluster_list = NULL;
9566 json_object *json_cluster_list_list = NULL;
9567 json_object *json_ext_community = NULL;
9568 json_object *json_last_update = NULL;
9569 json_object *json_pmsi = NULL;
9570 json_object *json_nexthop_global = NULL;
9571 json_object *json_nexthop_ll = NULL;
9572 json_object *json_nexthops = NULL;
9573 json_object *json_path = NULL;
9574 json_object *json_peer = NULL;
9575 json_object *json_string = NULL;
9576 json_object *json_adv_to = NULL;
9577 int first = 0;
9578 struct listnode *node, *nnode;
9579 struct peer *peer;
9580 int addpath_capable;
9581 int has_adj;
9582 unsigned int first_as;
9583 bool nexthop_self =
9584 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
9585 int i;
9586 char *nexthop_hostname =
9587 bgp_nexthop_hostname(path->peer, path->nexthop);
9588
9589 if (json_paths) {
9590 json_path = json_object_new_object();
9591 json_peer = json_object_new_object();
9592 json_nexthop_global = json_object_new_object();
9593 }
9594
9595 if (path->extra) {
9596 char tag_buf[30];
9597
9598 tag_buf[0] = '\0';
9599 if (path->extra && path->extra->num_labels) {
9600 bgp_evpn_label2str(path->extra->label,
9601 path->extra->num_labels, tag_buf,
9602 sizeof(tag_buf));
9603 }
9604 if (safi == SAFI_EVPN) {
9605 if (!json_paths) {
9606 vty_out(vty, " Route %pFX",
9607 (struct prefix_evpn *)
9608 bgp_dest_get_prefix(bn));
9609 if (tag_buf[0] != '\0')
9610 vty_out(vty, " VNI %s", tag_buf);
9611 vty_out(vty, "\n");
9612 } else {
9613 if (tag_buf[0])
9614 json_object_string_add(json_path, "VNI",
9615 tag_buf);
9616 }
9617 }
9618
9619 if (path->extra && path->extra->parent && !json_paths) {
9620 struct bgp_path_info *parent_ri;
9621 struct bgp_dest *dest, *pdest;
9622
9623 parent_ri = (struct bgp_path_info *)path->extra->parent;
9624 dest = parent_ri->net;
9625 if (dest && dest->pdest) {
9626 pdest = dest->pdest;
9627 prefix_rd2str(
9628 (struct prefix_rd *)bgp_dest_get_prefix(
9629 pdest),
9630 buf1, sizeof(buf1));
9631 if (is_pi_family_evpn(parent_ri)) {
9632 vty_out(vty,
9633 " Imported from %s:%pFX, VNI %s",
9634 buf1,
9635 (struct prefix_evpn *)
9636 bgp_dest_get_prefix(
9637 dest),
9638 tag_buf);
9639 if (attr->es_flags & ATTR_ES_L3_NHG)
9640 vty_out(vty, ", L3NHG %s",
9641 (attr->es_flags
9642 & ATTR_ES_L3_NHG_ACTIVE)
9643 ? "active"
9644 : "inactive");
9645 vty_out(vty, "\n");
9646
9647 } else
9648 vty_out(vty,
9649 " Imported from %s:%pFX\n",
9650 buf1,
9651 (struct prefix_evpn *)
9652 bgp_dest_get_prefix(
9653 dest));
9654 }
9655 }
9656 }
9657
9658 /* Line1 display AS-path, Aggregator */
9659 if (attr->aspath) {
9660 if (json_paths) {
9661 if (!attr->aspath->json)
9662 aspath_str_update(attr->aspath, true);
9663 json_object_lock(attr->aspath->json);
9664 json_object_object_add(json_path, "aspath",
9665 attr->aspath->json);
9666 } else {
9667 if (attr->aspath->segments)
9668 aspath_print_vty(vty, " %s", attr->aspath, "");
9669 else
9670 vty_out(vty, " Local");
9671 }
9672 }
9673
9674 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED)) {
9675 if (json_paths)
9676 json_object_boolean_true_add(json_path, "removed");
9677 else
9678 vty_out(vty, ", (removed)");
9679 }
9680
9681 if (CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
9682 if (json_paths)
9683 json_object_boolean_true_add(json_path, "stale");
9684 else
9685 vty_out(vty, ", (stale)");
9686 }
9687
9688 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
9689 if (json_paths) {
9690 char buf[BUFSIZ] = {0};
9691
9692 json_object_int_add(json_path, "aggregatorAs",
9693 attr->aggregator_as);
9694 json_object_string_add(json_path, "aggregatorId",
9695 inet_ntop(AF_INET,
9696 &attr->aggregator_addr,
9697 buf, sizeof(buf)));
9698 } else {
9699 vty_out(vty, ", (aggregated by %u %pI4)",
9700 attr->aggregator_as, &attr->aggregator_addr);
9701 }
9702 }
9703
9704 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
9705 PEER_FLAG_REFLECTOR_CLIENT)) {
9706 if (json_paths)
9707 json_object_boolean_true_add(json_path,
9708 "rxedFromRrClient");
9709 else
9710 vty_out(vty, ", (Received from a RR-client)");
9711 }
9712
9713 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
9714 PEER_FLAG_RSERVER_CLIENT)) {
9715 if (json_paths)
9716 json_object_boolean_true_add(json_path,
9717 "rxedFromRsClient");
9718 else
9719 vty_out(vty, ", (Received from a RS-client)");
9720 }
9721
9722 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
9723 if (json_paths)
9724 json_object_boolean_true_add(json_path,
9725 "dampeningHistoryEntry");
9726 else
9727 vty_out(vty, ", (history entry)");
9728 } else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)) {
9729 if (json_paths)
9730 json_object_boolean_true_add(json_path,
9731 "dampeningSuppressed");
9732 else
9733 vty_out(vty, ", (suppressed due to dampening)");
9734 }
9735
9736 if (!json_paths)
9737 vty_out(vty, "\n");
9738
9739 /* Line2 display Next-hop, Neighbor, Router-id */
9740 /* Display the nexthop */
9741 const struct prefix *bn_p = bgp_dest_get_prefix(bn);
9742
9743 if ((bn_p->family == AF_INET || bn_p->family == AF_ETHERNET
9744 || bn_p->family == AF_EVPN)
9745 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN
9746 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
9747 char buf[BUFSIZ] = {0};
9748
9749 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9750 || safi == SAFI_EVPN) {
9751 if (json_paths) {
9752 json_object_string_add(
9753 json_nexthop_global, "ip",
9754 inet_ntop(AF_INET,
9755 &attr->mp_nexthop_global_in,
9756 buf, sizeof(buf)));
9757
9758 if (path->peer->hostname)
9759 json_object_string_add(
9760 json_nexthop_global, "hostname",
9761 path->peer->hostname);
9762 } else {
9763 if (nexthop_hostname)
9764 vty_out(vty, " %pI4(%s)",
9765 &attr->mp_nexthop_global_in,
9766 nexthop_hostname);
9767 else
9768 vty_out(vty, " %pI4",
9769 &attr->mp_nexthop_global_in);
9770 }
9771 } else {
9772 if (json_paths) {
9773 json_object_string_add(
9774 json_nexthop_global, "ip",
9775 inet_ntop(AF_INET, &attr->nexthop, buf,
9776 sizeof(buf)));
9777
9778 if (path->peer->hostname)
9779 json_object_string_add(
9780 json_nexthop_global, "hostname",
9781 path->peer->hostname);
9782 } else {
9783 if (nexthop_hostname)
9784 vty_out(vty, " %pI4(%s)",
9785 &attr->nexthop,
9786 nexthop_hostname);
9787 else
9788 vty_out(vty, " %pI4",
9789 &attr->nexthop);
9790 }
9791 }
9792
9793 if (json_paths)
9794 json_object_string_add(json_nexthop_global, "afi",
9795 "ipv4");
9796 } else {
9797 if (json_paths) {
9798 json_object_string_add(
9799 json_nexthop_global, "ip",
9800 inet_ntop(AF_INET6, &attr->mp_nexthop_global,
9801 buf, INET6_ADDRSTRLEN));
9802
9803 if (path->peer->hostname)
9804 json_object_string_add(json_nexthop_global,
9805 "hostname",
9806 path->peer->hostname);
9807
9808 json_object_string_add(json_nexthop_global, "afi",
9809 "ipv6");
9810 json_object_string_add(json_nexthop_global, "scope",
9811 "global");
9812 } else {
9813 if (nexthop_hostname)
9814 vty_out(vty, " %pI6(%s)",
9815 &attr->mp_nexthop_global,
9816 nexthop_hostname);
9817 else
9818 vty_out(vty, " %pI6",
9819 &attr->mp_nexthop_global);
9820 }
9821 }
9822
9823 /* Display the IGP cost or 'inaccessible' */
9824 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
9825 if (json_paths)
9826 json_object_boolean_false_add(json_nexthop_global,
9827 "accessible");
9828 else
9829 vty_out(vty, " (inaccessible)");
9830 } else {
9831 if (path->extra && path->extra->igpmetric) {
9832 if (json_paths)
9833 json_object_int_add(json_nexthop_global,
9834 "metric",
9835 path->extra->igpmetric);
9836 else
9837 vty_out(vty, " (metric %u)",
9838 path->extra->igpmetric);
9839 }
9840
9841 /* IGP cost is 0, display this only for json */
9842 else {
9843 if (json_paths)
9844 json_object_int_add(json_nexthop_global,
9845 "metric", 0);
9846 }
9847
9848 if (json_paths)
9849 json_object_boolean_true_add(json_nexthop_global,
9850 "accessible");
9851 }
9852
9853 /* Display peer "from" output */
9854 /* This path was originated locally */
9855 if (path->peer == bgp->peer_self) {
9856
9857 if (safi == SAFI_EVPN
9858 || (bn_p->family == AF_INET
9859 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
9860 if (json_paths)
9861 json_object_string_add(json_peer, "peerId",
9862 "0.0.0.0");
9863 else
9864 vty_out(vty, " from 0.0.0.0 ");
9865 } else {
9866 if (json_paths)
9867 json_object_string_add(json_peer, "peerId",
9868 "::");
9869 else
9870 vty_out(vty, " from :: ");
9871 }
9872
9873 if (json_paths) {
9874 char buf[BUFSIZ] = {0};
9875
9876 json_object_string_add(json_peer, "routerId",
9877 inet_ntop(AF_INET,
9878 &bgp->router_id, buf,
9879 sizeof(buf)));
9880 } else {
9881 vty_out(vty, "(%pI4)", &bgp->router_id);
9882 }
9883 }
9884
9885 /* We RXed this path from one of our peers */
9886 else {
9887
9888 if (json_paths) {
9889 json_object_string_add(json_peer, "peerId",
9890 sockunion2str(&path->peer->su,
9891 buf,
9892 SU_ADDRSTRLEN));
9893 json_object_string_add(json_peer, "routerId",
9894 inet_ntop(AF_INET,
9895 &path->peer->remote_id,
9896 buf1, sizeof(buf1)));
9897
9898 if (path->peer->hostname)
9899 json_object_string_add(json_peer, "hostname",
9900 path->peer->hostname);
9901
9902 if (path->peer->domainname)
9903 json_object_string_add(json_peer, "domainname",
9904 path->peer->domainname);
9905
9906 if (path->peer->conf_if)
9907 json_object_string_add(json_peer, "interface",
9908 path->peer->conf_if);
9909 } else {
9910 if (path->peer->conf_if) {
9911 if (path->peer->hostname
9912 && CHECK_FLAG(path->peer->bgp->flags,
9913 BGP_FLAG_SHOW_HOSTNAME))
9914 vty_out(vty, " from %s(%s)",
9915 path->peer->hostname,
9916 path->peer->conf_if);
9917 else
9918 vty_out(vty, " from %s",
9919 path->peer->conf_if);
9920 } else {
9921 if (path->peer->hostname
9922 && CHECK_FLAG(path->peer->bgp->flags,
9923 BGP_FLAG_SHOW_HOSTNAME))
9924 vty_out(vty, " from %s(%s)",
9925 path->peer->hostname,
9926 path->peer->host);
9927 else
9928 vty_out(vty, " from %s",
9929 sockunion2str(&path->peer->su,
9930 buf,
9931 SU_ADDRSTRLEN));
9932 }
9933
9934 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
9935 vty_out(vty, " (%pI4)", &attr->originator_id);
9936 else
9937 vty_out(vty, " (%s)",
9938 inet_ntop(AF_INET,
9939 &path->peer->remote_id, buf1,
9940 sizeof(buf1)));
9941 }
9942 }
9943
9944 /*
9945 * Note when vrfid of nexthop is different from that of prefix
9946 */
9947 if (path->extra && path->extra->bgp_orig) {
9948 vrf_id_t nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9949
9950 if (json_paths) {
9951 const char *vn;
9952
9953 if (path->extra->bgp_orig->inst_type
9954 == BGP_INSTANCE_TYPE_DEFAULT)
9955 vn = VRF_DEFAULT_NAME;
9956 else
9957 vn = path->extra->bgp_orig->name;
9958
9959 json_object_string_add(json_path, "nhVrfName", vn);
9960
9961 if (nexthop_vrfid == VRF_UNKNOWN) {
9962 json_object_int_add(json_path, "nhVrfId", -1);
9963 } else {
9964 json_object_int_add(json_path, "nhVrfId",
9965 (int)nexthop_vrfid);
9966 }
9967 } else {
9968 if (nexthop_vrfid == VRF_UNKNOWN)
9969 vty_out(vty, " vrf ?");
9970 else {
9971 struct vrf *vrf;
9972
9973 vrf = vrf_lookup_by_id(nexthop_vrfid);
9974 vty_out(vty, " vrf %s(%u)",
9975 VRF_LOGNAME(vrf), nexthop_vrfid);
9976 }
9977 }
9978 }
9979
9980 if (nexthop_self) {
9981 if (json_paths) {
9982 json_object_boolean_true_add(json_path,
9983 "announceNexthopSelf");
9984 } else {
9985 vty_out(vty, " announce-nh-self");
9986 }
9987 }
9988
9989 if (!json_paths)
9990 vty_out(vty, "\n");
9991
9992 /* display the link-local nexthop */
9993 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
9994 if (json_paths) {
9995 json_nexthop_ll = json_object_new_object();
9996 json_object_string_add(
9997 json_nexthop_ll, "ip",
9998 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
9999 buf, INET6_ADDRSTRLEN));
10000
10001 if (path->peer->hostname)
10002 json_object_string_add(json_nexthop_ll,
10003 "hostname",
10004 path->peer->hostname);
10005
10006 json_object_string_add(json_nexthop_ll, "afi", "ipv6");
10007 json_object_string_add(json_nexthop_ll, "scope",
10008 "link-local");
10009
10010 json_object_boolean_true_add(json_nexthop_ll,
10011 "accessible");
10012
10013 if (!attr->mp_nexthop_prefer_global)
10014 json_object_boolean_true_add(json_nexthop_ll,
10015 "used");
10016 else
10017 json_object_boolean_true_add(
10018 json_nexthop_global, "used");
10019 } else {
10020 vty_out(vty, " (%s) %s\n",
10021 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
10022 buf, INET6_ADDRSTRLEN),
10023 attr->mp_nexthop_prefer_global
10024 ? "(prefer-global)"
10025 : "(used)");
10026 }
10027 }
10028 /* If we do not have a link-local nexthop then we must flag the
10029 global as "used" */
10030 else {
10031 if (json_paths)
10032 json_object_boolean_true_add(json_nexthop_global,
10033 "used");
10034 }
10035
10036 if (safi == SAFI_EVPN &&
10037 bgp_evpn_is_esi_valid(&attr->esi)) {
10038 route_vty_out_detail_es_info(vty, path, attr, json_path);
10039 }
10040
10041 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
10042 * Int/Ext/Local, Atomic, best */
10043 if (json_paths)
10044 json_object_string_add(json_path, "origin",
10045 bgp_origin_long_str[attr->origin]);
10046 else
10047 vty_out(vty, " Origin %s",
10048 bgp_origin_long_str[attr->origin]);
10049
10050 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
10051 if (json_paths)
10052 json_object_int_add(json_path, "metric", attr->med);
10053 else
10054 vty_out(vty, ", metric %u", attr->med);
10055 }
10056
10057 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
10058 if (json_paths)
10059 json_object_int_add(json_path, "locPrf",
10060 attr->local_pref);
10061 else
10062 vty_out(vty, ", localpref %u", attr->local_pref);
10063 }
10064
10065 if (attr->weight != 0) {
10066 if (json_paths)
10067 json_object_int_add(json_path, "weight", attr->weight);
10068 else
10069 vty_out(vty, ", weight %u", attr->weight);
10070 }
10071
10072 if (attr->tag != 0) {
10073 if (json_paths)
10074 json_object_int_add(json_path, "tag", attr->tag);
10075 else
10076 vty_out(vty, ", tag %" ROUTE_TAG_PRI, attr->tag);
10077 }
10078
10079 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
10080 if (json_paths)
10081 json_object_boolean_false_add(json_path, "valid");
10082 else
10083 vty_out(vty, ", invalid");
10084 } else if (!CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
10085 if (json_paths)
10086 json_object_boolean_true_add(json_path, "valid");
10087 else
10088 vty_out(vty, ", valid");
10089 }
10090
10091 if (path->peer != bgp->peer_self) {
10092 if (path->peer->as == path->peer->local_as) {
10093 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
10094 if (json_paths)
10095 json_object_string_add(
10096 json_peer, "type",
10097 "confed-internal");
10098 else
10099 vty_out(vty, ", confed-internal");
10100 } else {
10101 if (json_paths)
10102 json_object_string_add(
10103 json_peer, "type", "internal");
10104 else
10105 vty_out(vty, ", internal");
10106 }
10107 } else {
10108 if (bgp_confederation_peers_check(bgp,
10109 path->peer->as)) {
10110 if (json_paths)
10111 json_object_string_add(
10112 json_peer, "type",
10113 "confed-external");
10114 else
10115 vty_out(vty, ", confed-external");
10116 } else {
10117 if (json_paths)
10118 json_object_string_add(
10119 json_peer, "type", "external");
10120 else
10121 vty_out(vty, ", external");
10122 }
10123 }
10124 } else if (path->sub_type == BGP_ROUTE_AGGREGATE) {
10125 if (json_paths) {
10126 json_object_boolean_true_add(json_path, "aggregated");
10127 json_object_boolean_true_add(json_path, "local");
10128 } else {
10129 vty_out(vty, ", aggregated, local");
10130 }
10131 } else if (path->type != ZEBRA_ROUTE_BGP) {
10132 if (json_paths)
10133 json_object_boolean_true_add(json_path, "sourced");
10134 else
10135 vty_out(vty, ", sourced");
10136 } else {
10137 if (json_paths) {
10138 json_object_boolean_true_add(json_path, "sourced");
10139 json_object_boolean_true_add(json_path, "local");
10140 } else {
10141 vty_out(vty, ", sourced, local");
10142 }
10143 }
10144
10145 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
10146 if (json_paths)
10147 json_object_boolean_true_add(json_path,
10148 "atomicAggregate");
10149 else
10150 vty_out(vty, ", atomic-aggregate");
10151 }
10152
10153 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH)
10154 || (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)
10155 && bgp_path_info_mpath_count(path))) {
10156 if (json_paths)
10157 json_object_boolean_true_add(json_path, "multipath");
10158 else
10159 vty_out(vty, ", multipath");
10160 }
10161
10162 // Mark the bestpath(s)
10163 if (CHECK_FLAG(path->flags, BGP_PATH_DMED_SELECTED)) {
10164 first_as = aspath_get_first_as(attr->aspath);
10165
10166 if (json_paths) {
10167 if (!json_bestpath)
10168 json_bestpath = json_object_new_object();
10169 json_object_int_add(json_bestpath, "bestpathFromAs",
10170 first_as);
10171 } else {
10172 if (first_as)
10173 vty_out(vty, ", bestpath-from-AS %u", first_as);
10174 else
10175 vty_out(vty, ", bestpath-from-AS Local");
10176 }
10177 }
10178
10179 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
10180 if (json_paths) {
10181 if (!json_bestpath)
10182 json_bestpath = json_object_new_object();
10183 json_object_boolean_true_add(json_bestpath, "overall");
10184 json_object_string_add(
10185 json_bestpath, "selectionReason",
10186 bgp_path_selection_reason2str(bn->reason));
10187 } else {
10188 vty_out(vty, ", best");
10189 vty_out(vty, " (%s)",
10190 bgp_path_selection_reason2str(bn->reason));
10191 }
10192 }
10193
10194 if (curr_state != RPKI_NOT_BEING_USED) {
10195 if (json_paths)
10196 json_object_string_add(
10197 json_path, "rpkiValidationState",
10198 bgp_rpki_validation2str(curr_state));
10199 else
10200 vty_out(vty, ", rpki validation-state: %s",
10201 bgp_rpki_validation2str(curr_state));
10202 }
10203
10204 if (json_bestpath)
10205 json_object_object_add(json_path, "bestpath", json_bestpath);
10206
10207 if (!json_paths)
10208 vty_out(vty, "\n");
10209
10210 /* Line 4 display Community */
10211 if (attr->community) {
10212 if (json_paths) {
10213 if (!attr->community->json)
10214 community_str(attr->community, true);
10215 json_object_lock(attr->community->json);
10216 json_object_object_add(json_path, "community",
10217 attr->community->json);
10218 } else {
10219 vty_out(vty, " Community: %s\n",
10220 attr->community->str);
10221 }
10222 }
10223
10224 /* Line 5 display Extended-community */
10225 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
10226 if (json_paths) {
10227 json_ext_community = json_object_new_object();
10228 json_object_string_add(json_ext_community, "string",
10229 attr->ecommunity->str);
10230 json_object_object_add(json_path, "extendedCommunity",
10231 json_ext_community);
10232 } else {
10233 vty_out(vty, " Extended Community: %s\n",
10234 attr->ecommunity->str);
10235 }
10236 }
10237
10238 /* Line 6 display Large community */
10239 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
10240 if (json_paths) {
10241 if (!attr->lcommunity->json)
10242 lcommunity_str(attr->lcommunity, true);
10243 json_object_lock(attr->lcommunity->json);
10244 json_object_object_add(json_path, "largeCommunity",
10245 attr->lcommunity->json);
10246 } else {
10247 vty_out(vty, " Large Community: %s\n",
10248 attr->lcommunity->str);
10249 }
10250 }
10251
10252 /* Line 7 display Originator, Cluster-id */
10253 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
10254 || (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) {
10255 char buf[BUFSIZ] = {0};
10256
10257 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) {
10258 if (json_paths)
10259 json_object_string_add(
10260 json_path, "originatorId",
10261 inet_ntop(AF_INET, &attr->originator_id,
10262 buf, sizeof(buf)));
10263 else
10264 vty_out(vty, " Originator: %pI4",
10265 &attr->originator_id);
10266 }
10267
10268 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) {
10269 struct cluster_list *cluster =
10270 bgp_attr_get_cluster(attr);
10271 int i;
10272
10273 if (json_paths) {
10274 json_cluster_list = json_object_new_object();
10275 json_cluster_list_list =
10276 json_object_new_array();
10277
10278 for (i = 0; i < cluster->length / 4; i++) {
10279 json_string = json_object_new_string(
10280 inet_ntop(AF_INET,
10281 &cluster->list[i],
10282 buf, sizeof(buf)));
10283 json_object_array_add(
10284 json_cluster_list_list,
10285 json_string);
10286 }
10287
10288 /*
10289 * struct cluster_list does not have
10290 * "str" variable like aspath and community
10291 * do. Add this someday if someone asks
10292 * for it.
10293 * json_object_string_add(json_cluster_list,
10294 * "string", cluster->str);
10295 */
10296 json_object_object_add(json_cluster_list,
10297 "list",
10298 json_cluster_list_list);
10299 json_object_object_add(json_path, "clusterList",
10300 json_cluster_list);
10301 } else {
10302 vty_out(vty, ", Cluster list: ");
10303
10304 for (i = 0; i < cluster->length / 4; i++) {
10305 vty_out(vty, "%pI4 ",
10306 &cluster->list[i]);
10307 }
10308 }
10309 }
10310
10311 if (!json_paths)
10312 vty_out(vty, "\n");
10313 }
10314
10315 if (path->extra && path->extra->damp_info)
10316 bgp_damp_info_vty(vty, bgp, path, afi, safi, json_path);
10317
10318 /* Remote Label */
10319 if (path->extra && bgp_is_valid_label(&path->extra->label[0])
10320 && (safi != SAFI_EVPN && !is_route_parent_evpn(path))) {
10321 mpls_label_t label = label_pton(&path->extra->label[0]);
10322
10323 if (json_paths)
10324 json_object_int_add(json_path, "remoteLabel", label);
10325 else
10326 vty_out(vty, " Remote label: %d\n", label);
10327 }
10328
10329 /* Remote SID */
10330 if (path->extra && path->extra->num_sids > 0 && safi != SAFI_EVPN) {
10331 inet_ntop(AF_INET6, &path->extra->sid, buf, sizeof(buf));
10332 if (json_paths)
10333 json_object_string_add(json_path, "remoteSid", buf);
10334 else
10335 vty_out(vty, " Remote SID: %s\n", buf);
10336 }
10337
10338 /* Label Index */
10339 if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
10340 if (json_paths)
10341 json_object_int_add(json_path, "labelIndex",
10342 attr->label_index);
10343 else
10344 vty_out(vty, " Label Index: %d\n",
10345 attr->label_index);
10346 }
10347
10348 /* Line 8 display Addpath IDs */
10349 if (path->addpath_rx_id
10350 || bgp_addpath_info_has_ids(&path->tx_addpath)) {
10351 if (json_paths) {
10352 json_object_int_add(json_path, "addpathRxId",
10353 path->addpath_rx_id);
10354
10355 /* Keep backwards compatibility with the old API
10356 * by putting TX All's ID in the old field
10357 */
10358 json_object_int_add(
10359 json_path, "addpathTxId",
10360 path->tx_addpath
10361 .addpath_tx_id[BGP_ADDPATH_ALL]);
10362
10363 /* ... but create a specific field for each
10364 * strategy
10365 */
10366 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
10367 json_object_int_add(
10368 json_path,
10369 bgp_addpath_names(i)->id_json_name,
10370 path->tx_addpath.addpath_tx_id[i]);
10371 }
10372 } else {
10373 vty_out(vty, " AddPath ID: RX %u, ",
10374 path->addpath_rx_id);
10375
10376 route_vty_out_tx_ids(vty, &path->tx_addpath);
10377 }
10378 }
10379
10380 /* If we used addpath to TX a non-bestpath we need to display
10381 * "Advertised to" on a path-by-path basis
10382 */
10383 if (bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
10384 first = 1;
10385
10386 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
10387 addpath_capable =
10388 bgp_addpath_encode_tx(peer, afi, safi);
10389 has_adj = bgp_adj_out_lookup(
10390 peer, path->net,
10391 bgp_addpath_id_for_peer(peer, afi, safi,
10392 &path->tx_addpath));
10393
10394 if ((addpath_capable && has_adj)
10395 || (!addpath_capable && has_adj
10396 && CHECK_FLAG(path->flags,
10397 BGP_PATH_SELECTED))) {
10398 if (json_path && !json_adv_to)
10399 json_adv_to = json_object_new_object();
10400
10401 route_vty_out_advertised_to(
10402 vty, peer, &first,
10403 " Advertised to:", json_adv_to);
10404 }
10405 }
10406
10407 if (json_path) {
10408 if (json_adv_to) {
10409 json_object_object_add(
10410 json_path, "advertisedTo", json_adv_to);
10411 }
10412 } else {
10413 if (!first) {
10414 vty_out(vty, "\n");
10415 }
10416 }
10417 }
10418
10419 /* Line 9 display Uptime */
10420 tbuf = time(NULL) - (bgp_clock() - path->uptime);
10421 if (json_paths) {
10422 json_last_update = json_object_new_object();
10423 json_object_int_add(json_last_update, "epoch", tbuf);
10424 json_object_string_add(json_last_update, "string",
10425 ctime(&tbuf));
10426 json_object_object_add(json_path, "lastUpdate",
10427 json_last_update);
10428 } else
10429 vty_out(vty, " Last update: %s", ctime(&tbuf));
10430
10431 /* Line 10 display PMSI tunnel attribute, if present */
10432 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
10433 const char *str = lookup_msg(bgp_pmsi_tnltype_str,
10434 bgp_attr_get_pmsi_tnl_type(attr),
10435 PMSI_TNLTYPE_STR_DEFAULT);
10436
10437 if (json_paths) {
10438 json_pmsi = json_object_new_object();
10439 json_object_string_add(json_pmsi, "tunnelType", str);
10440 json_object_int_add(json_pmsi, "label",
10441 label2vni(&attr->label));
10442 json_object_object_add(json_path, "pmsi", json_pmsi);
10443 } else
10444 vty_out(vty, " PMSI Tunnel Type: %s, label: %d\n",
10445 str, label2vni(&attr->label));
10446 }
10447
10448 /* Output some debug about internal state of the dest flags */
10449 if (json_paths) {
10450 if (CHECK_FLAG(bn->flags, BGP_NODE_PROCESS_SCHEDULED))
10451 json_object_boolean_true_add(json_path, "processScheduled");
10452 if (CHECK_FLAG(bn->flags, BGP_NODE_USER_CLEAR))
10453 json_object_boolean_true_add(json_path, "userCleared");
10454 if (CHECK_FLAG(bn->flags, BGP_NODE_LABEL_CHANGED))
10455 json_object_boolean_true_add(json_path, "labelChanged");
10456 if (CHECK_FLAG(bn->flags, BGP_NODE_REGISTERED_FOR_LABEL))
10457 json_object_boolean_true_add(json_path, "registeredForLabel");
10458 if (CHECK_FLAG(bn->flags, BGP_NODE_SELECT_DEFER))
10459 json_object_boolean_true_add(json_path, "selectDefered");
10460 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALLED))
10461 json_object_boolean_true_add(json_path, "fibInstalled");
10462 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALL_PENDING))
10463 json_object_boolean_true_add(json_path, "fibPending");
10464 }
10465
10466 /* We've constructed the json object for this path, add it to the json
10467 * array of paths
10468 */
10469 if (json_paths) {
10470 if (json_nexthop_global || json_nexthop_ll) {
10471 json_nexthops = json_object_new_array();
10472
10473 if (json_nexthop_global)
10474 json_object_array_add(json_nexthops,
10475 json_nexthop_global);
10476
10477 if (json_nexthop_ll)
10478 json_object_array_add(json_nexthops,
10479 json_nexthop_ll);
10480
10481 json_object_object_add(json_path, "nexthops",
10482 json_nexthops);
10483 }
10484
10485 json_object_object_add(json_path, "peer", json_peer);
10486 json_object_array_add(json_paths, json_path);
10487 }
10488 }
10489
10490 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
10491 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
10492 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
10493
10494 static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
10495 const char *prefix_list_str, afi_t afi,
10496 safi_t safi, enum bgp_show_type type);
10497 static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
10498 const char *filter, afi_t afi, safi_t safi,
10499 enum bgp_show_type type);
10500 static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
10501 const char *rmap_str, afi_t afi, safi_t safi,
10502 enum bgp_show_type type);
10503 static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
10504 const char *com, int exact, afi_t afi,
10505 safi_t safi);
10506 static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
10507 const char *prefix, afi_t afi, safi_t safi,
10508 enum bgp_show_type type);
10509 static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
10510 afi_t afi, safi_t safi, enum bgp_show_type type,
10511 bool use_json);
10512 static int bgp_show_community(struct vty *vty, struct bgp *bgp,
10513 const char *comstr, int exact, afi_t afi,
10514 safi_t safi, uint8_t show_flags);
10515
10516
10517 static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
10518 struct bgp_table *table, enum bgp_show_type type,
10519 void *output_arg, char *rd, int is_last,
10520 unsigned long *output_cum, unsigned long *total_cum,
10521 unsigned long *json_header_depth, uint8_t show_flags)
10522 {
10523 struct bgp_path_info *pi;
10524 struct bgp_dest *dest;
10525 int header = 1;
10526 int display;
10527 unsigned long output_count = 0;
10528 unsigned long total_count = 0;
10529 struct prefix *p;
10530 json_object *json_paths = NULL;
10531 int first = 1;
10532 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
10533 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
10534 bool all = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
10535
10536 if (output_cum && *output_cum != 0)
10537 header = 0;
10538
10539 if (use_json && !*json_header_depth) {
10540 if (all)
10541 *json_header_depth = 1;
10542 else {
10543 vty_out(vty, "{\n");
10544 *json_header_depth = 2;
10545 }
10546
10547 vty_out(vty,
10548 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
10549 ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
10550 " \"localAS\": %u,\n \"routes\": { ",
10551 bgp->vrf_id == VRF_UNKNOWN ? -1 : (int)bgp->vrf_id,
10552 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
10553 ? VRF_DEFAULT_NAME
10554 : bgp->name,
10555 table->version, &bgp->router_id,
10556 bgp->default_local_pref, bgp->as);
10557 if (rd) {
10558 vty_out(vty, " \"routeDistinguishers\" : {");
10559 ++*json_header_depth;
10560 }
10561 }
10562
10563 if (use_json && rd) {
10564 vty_out(vty, " \"%s\" : { ", rd);
10565 }
10566
10567 /* Start processing of routes. */
10568 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
10569 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
10570
10571 pi = bgp_dest_get_bgp_path_info(dest);
10572 if (pi == NULL)
10573 continue;
10574
10575 display = 0;
10576 if (use_json)
10577 json_paths = json_object_new_array();
10578 else
10579 json_paths = NULL;
10580
10581 for (; pi; pi = pi->next) {
10582 total_count++;
10583 if (type == bgp_show_type_flap_statistics
10584 || type == bgp_show_type_flap_neighbor
10585 || type == bgp_show_type_dampend_paths
10586 || type == bgp_show_type_damp_neighbor) {
10587 if (!(pi->extra && pi->extra->damp_info))
10588 continue;
10589 }
10590 if (type == bgp_show_type_regexp) {
10591 regex_t *regex = output_arg;
10592
10593 if (bgp_regexec(regex, pi->attr->aspath)
10594 == REG_NOMATCH)
10595 continue;
10596 }
10597 if (type == bgp_show_type_prefix_list) {
10598 struct prefix_list *plist = output_arg;
10599
10600 if (prefix_list_apply(plist, dest_p)
10601 != PREFIX_PERMIT)
10602 continue;
10603 }
10604 if (type == bgp_show_type_filter_list) {
10605 struct as_list *as_list = output_arg;
10606
10607 if (as_list_apply(as_list, pi->attr->aspath)
10608 != AS_FILTER_PERMIT)
10609 continue;
10610 }
10611 if (type == bgp_show_type_route_map) {
10612 struct route_map *rmap = output_arg;
10613 struct bgp_path_info path;
10614 struct attr dummy_attr;
10615 route_map_result_t ret;
10616
10617 dummy_attr = *pi->attr;
10618
10619 path.peer = pi->peer;
10620 path.attr = &dummy_attr;
10621
10622 ret = route_map_apply(rmap, dest_p, &path);
10623 if (ret == RMAP_DENYMATCH)
10624 continue;
10625 }
10626 if (type == bgp_show_type_neighbor
10627 || type == bgp_show_type_flap_neighbor
10628 || type == bgp_show_type_damp_neighbor) {
10629 union sockunion *su = output_arg;
10630
10631 if (pi->peer == NULL
10632 || pi->peer->su_remote == NULL
10633 || !sockunion_same(pi->peer->su_remote, su))
10634 continue;
10635 }
10636 if (type == bgp_show_type_cidr_only) {
10637 uint32_t destination;
10638
10639 destination = ntohl(dest_p->u.prefix4.s_addr);
10640 if (IN_CLASSC(destination)
10641 && dest_p->prefixlen == 24)
10642 continue;
10643 if (IN_CLASSB(destination)
10644 && dest_p->prefixlen == 16)
10645 continue;
10646 if (IN_CLASSA(destination)
10647 && dest_p->prefixlen == 8)
10648 continue;
10649 }
10650 if (type == bgp_show_type_prefix_longer) {
10651 p = output_arg;
10652 if (!prefix_match(p, dest_p))
10653 continue;
10654 }
10655 if (type == bgp_show_type_community_all) {
10656 if (!pi->attr->community)
10657 continue;
10658 }
10659 if (type == bgp_show_type_community) {
10660 struct community *com = output_arg;
10661
10662 if (!pi->attr->community
10663 || !community_match(pi->attr->community,
10664 com))
10665 continue;
10666 }
10667 if (type == bgp_show_type_community_exact) {
10668 struct community *com = output_arg;
10669
10670 if (!pi->attr->community
10671 || !community_cmp(pi->attr->community, com))
10672 continue;
10673 }
10674 if (type == bgp_show_type_community_list) {
10675 struct community_list *list = output_arg;
10676
10677 if (!community_list_match(pi->attr->community,
10678 list))
10679 continue;
10680 }
10681 if (type == bgp_show_type_community_list_exact) {
10682 struct community_list *list = output_arg;
10683
10684 if (!community_list_exact_match(
10685 pi->attr->community, list))
10686 continue;
10687 }
10688 if (type == bgp_show_type_lcommunity) {
10689 struct lcommunity *lcom = output_arg;
10690
10691 if (!pi->attr->lcommunity
10692 || !lcommunity_match(pi->attr->lcommunity,
10693 lcom))
10694 continue;
10695 }
10696
10697 if (type == bgp_show_type_lcommunity_exact) {
10698 struct lcommunity *lcom = output_arg;
10699
10700 if (!pi->attr->lcommunity
10701 || !lcommunity_cmp(pi->attr->lcommunity,
10702 lcom))
10703 continue;
10704 }
10705 if (type == bgp_show_type_lcommunity_list) {
10706 struct community_list *list = output_arg;
10707
10708 if (!lcommunity_list_match(pi->attr->lcommunity,
10709 list))
10710 continue;
10711 }
10712 if (type
10713 == bgp_show_type_lcommunity_list_exact) {
10714 struct community_list *list = output_arg;
10715
10716 if (!lcommunity_list_exact_match(
10717 pi->attr->lcommunity, list))
10718 continue;
10719 }
10720 if (type == bgp_show_type_lcommunity_all) {
10721 if (!pi->attr->lcommunity)
10722 continue;
10723 }
10724 if (type == bgp_show_type_dampend_paths
10725 || type == bgp_show_type_damp_neighbor) {
10726 if (!CHECK_FLAG(pi->flags, BGP_PATH_DAMPED)
10727 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
10728 continue;
10729 }
10730
10731 if (!use_json && header) {
10732 vty_out(vty,
10733 "BGP table version is %" PRIu64
10734 ", local router ID is %pI4, vrf id ",
10735 table->version, &bgp->router_id);
10736 if (bgp->vrf_id == VRF_UNKNOWN)
10737 vty_out(vty, "%s", VRFID_NONE_STR);
10738 else
10739 vty_out(vty, "%u", bgp->vrf_id);
10740 vty_out(vty, "\n");
10741 vty_out(vty, "Default local pref %u, ",
10742 bgp->default_local_pref);
10743 vty_out(vty, "local AS %u\n", bgp->as);
10744 vty_out(vty, BGP_SHOW_SCODE_HEADER);
10745 vty_out(vty, BGP_SHOW_NCODE_HEADER);
10746 vty_out(vty, BGP_SHOW_OCODE_HEADER);
10747 if (type == bgp_show_type_dampend_paths
10748 || type == bgp_show_type_damp_neighbor)
10749 vty_out(vty, BGP_SHOW_DAMP_HEADER);
10750 else if (type == bgp_show_type_flap_statistics
10751 || type == bgp_show_type_flap_neighbor)
10752 vty_out(vty, BGP_SHOW_FLAP_HEADER);
10753 else
10754 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
10755 : BGP_SHOW_HEADER));
10756 header = 0;
10757 }
10758 if (rd != NULL && !display && !output_count) {
10759 if (!use_json)
10760 vty_out(vty,
10761 "Route Distinguisher: %s\n",
10762 rd);
10763 }
10764 if (type == bgp_show_type_dampend_paths
10765 || type == bgp_show_type_damp_neighbor)
10766 damp_route_vty_out(vty, dest_p, pi, display,
10767 AFI_IP, safi, use_json,
10768 json_paths);
10769 else if (type == bgp_show_type_flap_statistics
10770 || type == bgp_show_type_flap_neighbor)
10771 flap_route_vty_out(vty, dest_p, pi, display,
10772 AFI_IP, safi, use_json,
10773 json_paths);
10774 else
10775 route_vty_out(vty, dest_p, pi, display, safi,
10776 json_paths, wide);
10777 display++;
10778 }
10779
10780 if (display) {
10781 output_count++;
10782 if (!use_json)
10783 continue;
10784
10785 /* encode prefix */
10786 if (dest_p->family == AF_FLOWSPEC) {
10787 char retstr[BGP_FLOWSPEC_STRING_DISPLAY_MAX];
10788
10789
10790 bgp_fs_nlri_get_string(
10791 (unsigned char *)
10792 dest_p->u.prefix_flowspec.ptr,
10793 dest_p->u.prefix_flowspec.prefixlen,
10794 retstr, NLRI_STRING_FORMAT_MIN, NULL,
10795 family2afi(dest_p->u
10796 .prefix_flowspec.family));
10797 if (first)
10798 vty_out(vty, "\"%s/%d\": ", retstr,
10799 dest_p->u.prefix_flowspec
10800 .prefixlen);
10801 else
10802 vty_out(vty, ",\"%s/%d\": ", retstr,
10803 dest_p->u.prefix_flowspec
10804 .prefixlen);
10805 } else {
10806 if (first)
10807 vty_out(vty, "\"%pFX\": ", dest_p);
10808 else
10809 vty_out(vty, ",\"%pFX\": ", dest_p);
10810 }
10811 vty_out(vty, "%s",
10812 json_object_to_json_string_ext(
10813 json_paths, JSON_C_TO_STRING_PRETTY));
10814 json_object_free(json_paths);
10815 json_paths = NULL;
10816 first = 0;
10817 } else
10818 json_object_free(json_paths);
10819 }
10820
10821 if (output_cum) {
10822 output_count += *output_cum;
10823 *output_cum = output_count;
10824 }
10825 if (total_cum) {
10826 total_count += *total_cum;
10827 *total_cum = total_count;
10828 }
10829 if (use_json) {
10830 if (rd) {
10831 vty_out(vty, " }%s ", (is_last ? "" : ","));
10832 }
10833 if (is_last) {
10834 unsigned long i;
10835 for (i = 0; i < *json_header_depth; ++i)
10836 vty_out(vty, " } ");
10837 if (!all)
10838 vty_out(vty, "\n");
10839 }
10840 } else {
10841 if (is_last) {
10842 /* No route is displayed */
10843 if (output_count == 0) {
10844 if (type == bgp_show_type_normal)
10845 vty_out(vty,
10846 "No BGP prefixes displayed, %ld exist\n",
10847 total_count);
10848 } else
10849 vty_out(vty,
10850 "\nDisplayed %ld routes and %ld total paths\n",
10851 output_count, total_count);
10852 }
10853 }
10854
10855 return CMD_SUCCESS;
10856 }
10857
10858 int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi,
10859 struct bgp_table *table, struct prefix_rd *prd_match,
10860 enum bgp_show_type type, void *output_arg, bool use_json)
10861 {
10862 struct bgp_dest *dest, *next;
10863 unsigned long output_cum = 0;
10864 unsigned long total_cum = 0;
10865 unsigned long json_header_depth = 0;
10866 struct bgp_table *itable;
10867 bool show_msg;
10868 uint8_t show_flags = 0;
10869
10870 show_msg = (!use_json && type == bgp_show_type_normal);
10871
10872 if (use_json)
10873 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
10874
10875 for (dest = bgp_table_top(table); dest; dest = next) {
10876 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
10877
10878 next = bgp_route_next(dest);
10879 if (prd_match && memcmp(dest_p->u.val, prd_match->val, 8) != 0)
10880 continue;
10881
10882 itable = bgp_dest_get_bgp_table_info(dest);
10883 if (itable != NULL) {
10884 struct prefix_rd prd;
10885 char rd[RD_ADDRSTRLEN];
10886
10887 memcpy(&prd, dest_p, sizeof(struct prefix_rd));
10888 prefix_rd2str(&prd, rd, sizeof(rd));
10889 bgp_show_table(vty, bgp, safi, itable, type, output_arg,
10890 rd, next == NULL, &output_cum,
10891 &total_cum, &json_header_depth,
10892 show_flags);
10893 if (next == NULL)
10894 show_msg = false;
10895 }
10896 }
10897 if (show_msg) {
10898 if (output_cum == 0)
10899 vty_out(vty, "No BGP prefixes displayed, %ld exist\n",
10900 total_cum);
10901 else
10902 vty_out(vty,
10903 "\nDisplayed %ld routes and %ld total paths\n",
10904 output_cum, total_cum);
10905 }
10906 return CMD_SUCCESS;
10907 }
10908 static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
10909 enum bgp_show_type type, void *output_arg,
10910 uint8_t show_flags)
10911 {
10912 struct bgp_table *table;
10913 unsigned long json_header_depth = 0;
10914 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
10915
10916 if (bgp == NULL) {
10917 bgp = bgp_get_default();
10918 }
10919
10920 if (bgp == NULL) {
10921 if (!use_json)
10922 vty_out(vty, "No BGP process is configured\n");
10923 else
10924 vty_out(vty, "{}\n");
10925 return CMD_WARNING;
10926 }
10927
10928 table = bgp->rib[afi][safi];
10929 /* use MPLS and ENCAP specific shows until they are merged */
10930 if (safi == SAFI_MPLS_VPN) {
10931 return bgp_show_table_rd(vty, bgp, safi, table, NULL, type,
10932 output_arg, use_json);
10933 }
10934
10935 if (safi == SAFI_FLOWSPEC && type == bgp_show_type_detail) {
10936 return bgp_show_table_flowspec(vty, bgp, afi, table, type,
10937 output_arg, use_json,
10938 1, NULL, NULL);
10939 }
10940 /* labeled-unicast routes live in the unicast table */
10941 else if (safi == SAFI_LABELED_UNICAST)
10942 safi = SAFI_UNICAST;
10943
10944 return bgp_show_table(vty, bgp, safi, table, type, output_arg, NULL, 1,
10945 NULL, NULL, &json_header_depth, show_flags);
10946 }
10947
10948 static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi,
10949 safi_t safi, uint8_t show_flags)
10950 {
10951 struct listnode *node, *nnode;
10952 struct bgp *bgp;
10953 int is_first = 1;
10954 bool route_output = false;
10955 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
10956
10957 if (use_json)
10958 vty_out(vty, "{\n");
10959
10960 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
10961 route_output = true;
10962 if (use_json) {
10963 if (!is_first)
10964 vty_out(vty, ",\n");
10965 else
10966 is_first = 0;
10967
10968 vty_out(vty, "\"%s\":",
10969 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
10970 ? VRF_DEFAULT_NAME
10971 : bgp->name);
10972 } else {
10973 vty_out(vty, "\nInstance %s:\n",
10974 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
10975 ? VRF_DEFAULT_NAME
10976 : bgp->name);
10977 }
10978 bgp_show(vty, bgp, afi, safi, bgp_show_type_normal, NULL,
10979 show_flags);
10980 }
10981
10982 if (use_json)
10983 vty_out(vty, "}\n");
10984 else if (!route_output)
10985 vty_out(vty, "%% BGP instance not found\n");
10986 }
10987
10988 /* Header of detailed BGP route information */
10989 void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
10990 struct bgp_dest *dest, struct prefix_rd *prd,
10991 afi_t afi, safi_t safi, json_object *json)
10992 {
10993 struct bgp_path_info *pi;
10994 const struct prefix *p;
10995 struct peer *peer;
10996 struct listnode *node, *nnode;
10997 char buf1[RD_ADDRSTRLEN];
10998 char prefix_str[BUFSIZ];
10999 int count = 0;
11000 int best = 0;
11001 int suppress = 0;
11002 int accept_own = 0;
11003 int route_filter_translated_v4 = 0;
11004 int route_filter_v4 = 0;
11005 int route_filter_translated_v6 = 0;
11006 int route_filter_v6 = 0;
11007 int llgr_stale = 0;
11008 int no_llgr = 0;
11009 int accept_own_nexthop = 0;
11010 int blackhole = 0;
11011 int no_export = 0;
11012 int no_advertise = 0;
11013 int local_as = 0;
11014 int no_peer = 0;
11015 int first = 1;
11016 int has_valid_label = 0;
11017 mpls_label_t label = 0;
11018 json_object *json_adv_to = NULL;
11019
11020 p = bgp_dest_get_prefix(dest);
11021 has_valid_label = bgp_is_valid_label(&dest->local_label);
11022
11023 if (has_valid_label)
11024 label = label_pton(&dest->local_label);
11025
11026 if (safi == SAFI_EVPN) {
11027
11028 if (!json) {
11029 vty_out(vty, "BGP routing table entry for %s%s%pFX\n",
11030 prd ? prefix_rd2str(prd, buf1, sizeof(buf1))
11031 : "",
11032 prd ? ":" : "", (struct prefix_evpn *)p);
11033 } else {
11034 json_object_string_add(json, "rd",
11035 prd ? prefix_rd2str(prd, buf1, sizeof(buf1)) :
11036 "");
11037 bgp_evpn_route2json((struct prefix_evpn *)p, json);
11038 }
11039 } else {
11040 if (!json) {
11041 vty_out(vty, "BGP routing table entry for %s%s%pFX\n",
11042 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
11043 ? prefix_rd2str(prd, buf1,
11044 sizeof(buf1))
11045 : ""),
11046 safi == SAFI_MPLS_VPN ? ":" : "", p);
11047
11048 } else
11049 json_object_string_add(json, "prefix",
11050 prefix2str(p, prefix_str, sizeof(prefix_str)));
11051 }
11052
11053 if (has_valid_label) {
11054 if (json)
11055 json_object_int_add(json, "localLabel", label);
11056 else
11057 vty_out(vty, "Local label: %d\n", label);
11058 }
11059
11060 if (!json)
11061 if (bgp_labeled_safi(safi) && safi != SAFI_EVPN)
11062 vty_out(vty, "not allocated\n");
11063
11064 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
11065 count++;
11066 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
11067 best = count;
11068 if (bgp_path_suppressed(pi))
11069 suppress = 1;
11070
11071 if (pi->attr->community == NULL)
11072 continue;
11073
11074 no_advertise += community_include(
11075 pi->attr->community, COMMUNITY_NO_ADVERTISE);
11076 no_export += community_include(pi->attr->community,
11077 COMMUNITY_NO_EXPORT);
11078 local_as += community_include(pi->attr->community,
11079 COMMUNITY_LOCAL_AS);
11080 accept_own += community_include(pi->attr->community,
11081 COMMUNITY_ACCEPT_OWN);
11082 route_filter_translated_v4 += community_include(
11083 pi->attr->community,
11084 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4);
11085 route_filter_translated_v6 += community_include(
11086 pi->attr->community,
11087 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6);
11088 route_filter_v4 += community_include(
11089 pi->attr->community, COMMUNITY_ROUTE_FILTER_v4);
11090 route_filter_v6 += community_include(
11091 pi->attr->community, COMMUNITY_ROUTE_FILTER_v6);
11092 llgr_stale += community_include(pi->attr->community,
11093 COMMUNITY_LLGR_STALE);
11094 no_llgr += community_include(pi->attr->community,
11095 COMMUNITY_NO_LLGR);
11096 accept_own_nexthop +=
11097 community_include(pi->attr->community,
11098 COMMUNITY_ACCEPT_OWN_NEXTHOP);
11099 blackhole += community_include(pi->attr->community,
11100 COMMUNITY_BLACKHOLE);
11101 no_peer += community_include(pi->attr->community,
11102 COMMUNITY_NO_PEER);
11103 }
11104 }
11105
11106 if (!json) {
11107 vty_out(vty, "Paths: (%d available", count);
11108 if (best) {
11109 vty_out(vty, ", best #%d", best);
11110 if (safi == SAFI_UNICAST) {
11111 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
11112 vty_out(vty, ", table %s",
11113 VRF_DEFAULT_NAME);
11114 else
11115 vty_out(vty, ", vrf %s",
11116 bgp->name);
11117 }
11118 } else
11119 vty_out(vty, ", no best path");
11120
11121 if (accept_own)
11122 vty_out(vty,
11123 ", accept own local route exported and imported in different VRF");
11124 else if (route_filter_translated_v4)
11125 vty_out(vty,
11126 ", mark translated RTs for VPNv4 route filtering");
11127 else if (route_filter_v4)
11128 vty_out(vty,
11129 ", attach RT as-is for VPNv4 route filtering");
11130 else if (route_filter_translated_v6)
11131 vty_out(vty,
11132 ", mark translated RTs for VPNv6 route filtering");
11133 else if (route_filter_v6)
11134 vty_out(vty,
11135 ", attach RT as-is for VPNv6 route filtering");
11136 else if (llgr_stale)
11137 vty_out(vty,
11138 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
11139 else if (no_llgr)
11140 vty_out(vty,
11141 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
11142 else if (accept_own_nexthop)
11143 vty_out(vty,
11144 ", accept local nexthop");
11145 else if (blackhole)
11146 vty_out(vty, ", inform peer to blackhole prefix");
11147 else if (no_export)
11148 vty_out(vty, ", not advertised to EBGP peer");
11149 else if (no_advertise)
11150 vty_out(vty, ", not advertised to any peer");
11151 else if (local_as)
11152 vty_out(vty, ", not advertised outside local AS");
11153 else if (no_peer)
11154 vty_out(vty,
11155 ", inform EBGP peer not to advertise to their EBGP peers");
11156
11157 if (suppress)
11158 vty_out(vty,
11159 ", Advertisements suppressed by an aggregate.");
11160 vty_out(vty, ")\n");
11161 }
11162
11163 /* If we are not using addpath then we can display Advertised to and
11164 * that will
11165 * show what peers we advertised the bestpath to. If we are using
11166 * addpath
11167 * though then we must display Advertised to on a path-by-path basis. */
11168 if (!bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
11169 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
11170 if (bgp_adj_out_lookup(peer, dest, 0)) {
11171 if (json && !json_adv_to)
11172 json_adv_to = json_object_new_object();
11173
11174 route_vty_out_advertised_to(
11175 vty, peer, &first,
11176 " Advertised to non peer-group peers:\n ",
11177 json_adv_to);
11178 }
11179 }
11180
11181 if (json) {
11182 if (json_adv_to) {
11183 json_object_object_add(json, "advertisedTo",
11184 json_adv_to);
11185 }
11186 } else {
11187 if (first)
11188 vty_out(vty, " Not advertised to any peer");
11189 vty_out(vty, "\n");
11190 }
11191 }
11192 }
11193
11194 static void bgp_show_path_info(struct prefix_rd *pfx_rd,
11195 struct bgp_dest *bgp_node, struct vty *vty,
11196 struct bgp *bgp, afi_t afi, safi_t safi,
11197 json_object *json, enum bgp_path_type pathtype,
11198 int *display, enum rpki_states target_state)
11199 {
11200 struct bgp_path_info *pi;
11201 int header = 1;
11202 char rdbuf[RD_ADDRSTRLEN];
11203 json_object *json_header = NULL;
11204 json_object *json_paths = NULL;
11205 const struct prefix *p = bgp_dest_get_prefix(bgp_node);
11206
11207 for (pi = bgp_dest_get_bgp_path_info(bgp_node); pi; pi = pi->next) {
11208 enum rpki_states curr_state = RPKI_NOT_BEING_USED;
11209
11210 if (p->family == AF_INET || p->family == AF_INET6)
11211 curr_state = hook_call(bgp_rpki_prefix_status, pi->peer,
11212 pi->attr, p);
11213
11214 if (target_state != RPKI_NOT_BEING_USED
11215 && curr_state != target_state)
11216 continue;
11217
11218 if (json && !json_paths) {
11219 /* Instantiate json_paths only if path is valid */
11220 json_paths = json_object_new_array();
11221 if (pfx_rd) {
11222 prefix_rd2str(pfx_rd, rdbuf, sizeof(rdbuf));
11223 json_header = json_object_new_object();
11224 } else
11225 json_header = json;
11226 }
11227
11228 if (header) {
11229 route_vty_out_detail_header(
11230 vty, bgp, bgp_node, pfx_rd,
11231 AFI_IP, safi, json_header);
11232 header = 0;
11233 }
11234 (*display)++;
11235
11236 if (pathtype == BGP_PATH_SHOW_ALL
11237 || (pathtype == BGP_PATH_SHOW_BESTPATH
11238 && CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
11239 || (pathtype == BGP_PATH_SHOW_MULTIPATH
11240 && (CHECK_FLAG(pi->flags, BGP_PATH_MULTIPATH)
11241 || CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))))
11242 route_vty_out_detail(vty, bgp, bgp_node, pi, AFI_IP,
11243 safi, curr_state, json_paths);
11244 }
11245
11246 if (json && json_paths) {
11247 json_object_object_add(json_header, "paths", json_paths);
11248
11249 if (pfx_rd)
11250 json_object_object_add(json, rdbuf, json_header);
11251 }
11252 }
11253
11254 /* Display specified route of BGP table. */
11255 static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
11256 struct bgp_table *rib, const char *ip_str,
11257 afi_t afi, safi_t safi,
11258 struct prefix_rd *prd, int prefix_check,
11259 enum bgp_path_type pathtype, bool use_json)
11260 {
11261 int ret;
11262 int display = 0;
11263 struct prefix match;
11264 struct bgp_dest *dest;
11265 struct bgp_dest *rm;
11266 struct bgp_table *table;
11267 json_object *json = NULL;
11268 json_object *json_paths = NULL;
11269
11270 /* Check IP address argument. */
11271 ret = str2prefix(ip_str, &match);
11272 if (!ret) {
11273 vty_out(vty, "address is malformed\n");
11274 return CMD_WARNING;
11275 }
11276
11277 match.family = afi2family(afi);
11278
11279 if (use_json)
11280 json = json_object_new_object();
11281
11282 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP) {
11283 for (dest = bgp_table_top(rib); dest;
11284 dest = bgp_route_next(dest)) {
11285 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
11286
11287 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
11288 continue;
11289 table = bgp_dest_get_bgp_table_info(dest);
11290 if (!table)
11291 continue;
11292
11293 if ((rm = bgp_node_match(table, &match)) == NULL)
11294 continue;
11295
11296 const struct prefix *rm_p = bgp_dest_get_prefix(rm);
11297 if (prefix_check
11298 && rm_p->prefixlen != match.prefixlen) {
11299 bgp_dest_unlock_node(rm);
11300 continue;
11301 }
11302
11303 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
11304 bgp, afi, safi, json, pathtype,
11305 &display, RPKI_NOT_BEING_USED);
11306
11307 bgp_dest_unlock_node(rm);
11308 }
11309 } else if (safi == SAFI_EVPN) {
11310 struct bgp_dest *longest_pfx;
11311 bool is_exact_pfxlen_match = false;
11312
11313 for (dest = bgp_table_top(rib); dest;
11314 dest = bgp_route_next(dest)) {
11315 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
11316
11317 if (prd && memcmp(&dest_p->u.val, prd->val, 8) != 0)
11318 continue;
11319 table = bgp_dest_get_bgp_table_info(dest);
11320 if (!table)
11321 continue;
11322
11323 longest_pfx = NULL;
11324 is_exact_pfxlen_match = false;
11325 /*
11326 * Search through all the prefixes for a match. The
11327 * pfx's are enumerated in ascending order of pfxlens.
11328 * So, the last pfx match is the longest match. Set
11329 * is_exact_pfxlen_match when we get exact pfxlen match
11330 */
11331 for (rm = bgp_table_top(table); rm;
11332 rm = bgp_route_next(rm)) {
11333 const struct prefix *rm_p =
11334 bgp_dest_get_prefix(rm);
11335 /*
11336 * Get prefixlen of the ip-prefix within type5
11337 * evpn route
11338 */
11339 if (evpn_type5_prefix_match(rm_p, &match)
11340 && rm->info) {
11341 longest_pfx = rm;
11342 int type5_pfxlen =
11343 bgp_evpn_get_type5_prefixlen(
11344 rm_p);
11345 if (type5_pfxlen == match.prefixlen) {
11346 is_exact_pfxlen_match = true;
11347 bgp_dest_unlock_node(rm);
11348 break;
11349 }
11350 }
11351 }
11352
11353 if (!longest_pfx)
11354 continue;
11355
11356 if (prefix_check && !is_exact_pfxlen_match)
11357 continue;
11358
11359 rm = longest_pfx;
11360 bgp_dest_lock_node(rm);
11361
11362 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
11363 bgp, afi, safi, json, pathtype,
11364 &display, RPKI_NOT_BEING_USED);
11365
11366 bgp_dest_unlock_node(rm);
11367 }
11368 } else if (safi == SAFI_FLOWSPEC) {
11369 if (use_json)
11370 json_paths = json_object_new_array();
11371
11372 display = bgp_flowspec_display_match_per_ip(afi, rib,
11373 &match, prefix_check,
11374 vty,
11375 use_json,
11376 json_paths);
11377 if (use_json) {
11378 if (display)
11379 json_object_object_add(json, "paths",
11380 json_paths);
11381 else
11382 json_object_free(json_paths);
11383 }
11384 } else {
11385 if ((dest = bgp_node_match(rib, &match)) != NULL) {
11386 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
11387 if (!prefix_check
11388 || dest_p->prefixlen == match.prefixlen) {
11389 bgp_show_path_info(NULL, dest, vty, bgp, afi,
11390 safi, json, pathtype,
11391 &display,
11392 RPKI_NOT_BEING_USED);
11393 }
11394
11395 bgp_dest_unlock_node(dest);
11396 }
11397 }
11398
11399 if (use_json) {
11400 vty_out(vty, "%s\n", json_object_to_json_string_ext(
11401 json, JSON_C_TO_STRING_PRETTY |
11402 JSON_C_TO_STRING_NOSLASHESCAPE));
11403 json_object_free(json);
11404 } else {
11405 if (!display) {
11406 vty_out(vty, "%% Network not in table\n");
11407 return CMD_WARNING;
11408 }
11409 }
11410
11411 return CMD_SUCCESS;
11412 }
11413
11414 /* Display specified route of Main RIB */
11415 static int bgp_show_route(struct vty *vty, struct bgp *bgp, const char *ip_str,
11416 afi_t afi, safi_t safi, struct prefix_rd *prd,
11417 int prefix_check, enum bgp_path_type pathtype,
11418 bool use_json)
11419 {
11420 if (!bgp) {
11421 bgp = bgp_get_default();
11422 if (!bgp) {
11423 if (!use_json)
11424 vty_out(vty, "No BGP process is configured\n");
11425 else
11426 vty_out(vty, "{}\n");
11427 return CMD_WARNING;
11428 }
11429 }
11430
11431 /* labeled-unicast routes live in the unicast table */
11432 if (safi == SAFI_LABELED_UNICAST)
11433 safi = SAFI_UNICAST;
11434
11435 return bgp_show_route_in_table(vty, bgp, bgp->rib[afi][safi], ip_str,
11436 afi, safi, prd, prefix_check, pathtype,
11437 use_json);
11438 }
11439
11440 static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc,
11441 struct cmd_token **argv, bool exact, afi_t afi,
11442 safi_t safi, bool uj)
11443 {
11444 struct lcommunity *lcom;
11445 struct buffer *b;
11446 int i;
11447 char *str;
11448 int first = 0;
11449 uint8_t show_flags = 0;
11450 int ret;
11451
11452 if (uj)
11453 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11454
11455 b = buffer_new(1024);
11456 for (i = 0; i < argc; i++) {
11457 if (first)
11458 buffer_putc(b, ' ');
11459 else {
11460 if (strmatch(argv[i]->text, "AA:BB:CC")) {
11461 first = 1;
11462 buffer_putstr(b, argv[i]->arg);
11463 }
11464 }
11465 }
11466 buffer_putc(b, '\0');
11467
11468 str = buffer_getstr(b);
11469 buffer_free(b);
11470
11471 lcom = lcommunity_str2com(str);
11472 XFREE(MTYPE_TMP, str);
11473 if (!lcom) {
11474 vty_out(vty, "%% Large-community malformed\n");
11475 return CMD_WARNING;
11476 }
11477
11478 ret = bgp_show(vty, bgp, afi, safi,
11479 (exact ? bgp_show_type_lcommunity_exact
11480 : bgp_show_type_lcommunity),
11481 lcom, show_flags);
11482
11483 lcommunity_free(&lcom);
11484 return ret;
11485 }
11486
11487 static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp,
11488 const char *lcom, bool exact, afi_t afi,
11489 safi_t safi, bool uj)
11490 {
11491 struct community_list *list;
11492 uint8_t show_flags = 0;
11493
11494 if (uj)
11495 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11496
11497
11498 list = community_list_lookup(bgp_clist, lcom, 0,
11499 LARGE_COMMUNITY_LIST_MASTER);
11500 if (list == NULL) {
11501 vty_out(vty, "%% %s is not a valid large-community-list name\n",
11502 lcom);
11503 return CMD_WARNING;
11504 }
11505
11506 return bgp_show(vty, bgp, afi, safi,
11507 (exact ? bgp_show_type_lcommunity_list_exact
11508 : bgp_show_type_lcommunity_list),
11509 list, show_flags);
11510 }
11511
11512 DEFUN (show_ip_bgp_large_community_list,
11513 show_ip_bgp_large_community_list_cmd,
11514 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] large-community-list <(1-500)|WORD> [exact-match] [json]",
11515 SHOW_STR
11516 IP_STR
11517 BGP_STR
11518 BGP_INSTANCE_HELP_STR
11519 BGP_AFI_HELP_STR
11520 BGP_SAFI_WITH_LABEL_HELP_STR
11521 "Display routes matching the large-community-list\n"
11522 "large-community-list number\n"
11523 "large-community-list name\n"
11524 "Exact match of the large-communities\n"
11525 JSON_STR)
11526 {
11527 afi_t afi = AFI_IP6;
11528 safi_t safi = SAFI_UNICAST;
11529 int idx = 0;
11530 bool exact_match = 0;
11531 struct bgp *bgp = NULL;
11532 bool uj = use_json(argc, argv);
11533
11534 if (uj)
11535 argc--;
11536
11537 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11538 &bgp, uj);
11539 if (!idx)
11540 return CMD_WARNING;
11541
11542 argv_find(argv, argc, "large-community-list", &idx);
11543
11544 const char *clist_number_or_name = argv[++idx]->arg;
11545
11546 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
11547 exact_match = 1;
11548
11549 return bgp_show_lcommunity_list(vty, bgp, clist_number_or_name,
11550 exact_match, afi, safi, uj);
11551 }
11552 DEFUN (show_ip_bgp_large_community,
11553 show_ip_bgp_large_community_cmd,
11554 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] large-community [<AA:BB:CC> [exact-match]] [json]",
11555 SHOW_STR
11556 IP_STR
11557 BGP_STR
11558 BGP_INSTANCE_HELP_STR
11559 BGP_AFI_HELP_STR
11560 BGP_SAFI_WITH_LABEL_HELP_STR
11561 "Display routes matching the large-communities\n"
11562 "List of large-community numbers\n"
11563 "Exact match of the large-communities\n"
11564 JSON_STR)
11565 {
11566 afi_t afi = AFI_IP6;
11567 safi_t safi = SAFI_UNICAST;
11568 int idx = 0;
11569 bool exact_match = 0;
11570 struct bgp *bgp = NULL;
11571 bool uj = use_json(argc, argv);
11572 uint8_t show_flags = 0;
11573
11574 if (uj) {
11575 argc--;
11576 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11577 }
11578
11579 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11580 &bgp, uj);
11581 if (!idx)
11582 return CMD_WARNING;
11583
11584 if (argv_find(argv, argc, "AA:BB:CC", &idx)) {
11585 if (argv_find(argv, argc, "exact-match", &idx))
11586 exact_match = 1;
11587 return bgp_show_lcommunity(vty, bgp, argc, argv,
11588 exact_match, afi, safi, uj);
11589 } else
11590 return bgp_show(vty, bgp, afi, safi,
11591 bgp_show_type_lcommunity_all, NULL, show_flags);
11592 }
11593
11594 static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
11595 safi_t safi, struct json_object *json_array);
11596 static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
11597 safi_t safi, struct json_object *json);
11598
11599
11600 DEFUN(show_ip_bgp_statistics_all, show_ip_bgp_statistics_all_cmd,
11601 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
11602 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
11603 "Display number of prefixes for all afi/safi\n" JSON_STR)
11604 {
11605 bool uj = use_json(argc, argv);
11606 struct bgp *bgp = NULL;
11607 safi_t safi = SAFI_UNICAST;
11608 afi_t afi = AFI_IP6;
11609 int idx = 0;
11610 struct json_object *json_all = NULL;
11611 struct json_object *json_afi_safi = NULL;
11612
11613 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11614 &bgp, false);
11615 if (!idx)
11616 return CMD_WARNING;
11617
11618 if (uj)
11619 json_all = json_object_new_object();
11620
11621 FOREACH_AFI_SAFI (afi, safi) {
11622 /*
11623 * So limit output to those afi/safi pairs that
11624 * actually have something interesting in them
11625 */
11626 if (strmatch(get_afi_safi_str(afi, safi, true),
11627 "Unknown")) {
11628 continue;
11629 }
11630 if (uj) {
11631 json_afi_safi = json_object_new_array();
11632 json_object_object_add(
11633 json_all,
11634 get_afi_safi_str(afi, safi, true),
11635 json_afi_safi);
11636 } else {
11637 json_afi_safi = NULL;
11638 }
11639
11640 bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
11641 }
11642
11643 if (uj) {
11644 vty_out(vty, "%s",
11645 json_object_to_json_string_ext(
11646 json_all, JSON_C_TO_STRING_PRETTY));
11647 json_object_free(json_all);
11648 }
11649
11650 return CMD_SUCCESS;
11651 }
11652
11653 /* BGP route print out function without JSON */
11654 DEFUN (show_ip_bgp_l2vpn_evpn_statistics,
11655 show_ip_bgp_l2vpn_evpn_statistics_cmd,
11656 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
11657 SHOW_STR
11658 IP_STR
11659 BGP_STR
11660 BGP_INSTANCE_HELP_STR
11661 L2VPN_HELP_STR
11662 EVPN_HELP_STR
11663 "BGP RIB advertisement statistics\n"
11664 JSON_STR)
11665 {
11666 afi_t afi = AFI_IP6;
11667 safi_t safi = SAFI_UNICAST;
11668 struct bgp *bgp = NULL;
11669 int idx = 0, ret;
11670 bool uj = use_json(argc, argv);
11671 struct json_object *json_afi_safi = NULL, *json = NULL;
11672
11673 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11674 &bgp, false);
11675 if (!idx)
11676 return CMD_WARNING;
11677
11678 if (uj)
11679 json_afi_safi = json_object_new_array();
11680 else
11681 json_afi_safi = NULL;
11682
11683 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
11684
11685 if (uj) {
11686 json = json_object_new_object();
11687 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
11688 json_afi_safi);
11689 vty_out(vty, "%s", json_object_to_json_string_ext(
11690 json, JSON_C_TO_STRING_PRETTY));
11691 json_object_free(json);
11692 }
11693 return ret;
11694 }
11695
11696 /* BGP route print out function without JSON */
11697 DEFUN(show_ip_bgp_afi_safi_statistics, show_ip_bgp_afi_safi_statistics_cmd,
11698 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
11699 " [" BGP_SAFI_WITH_LABEL_CMD_STR
11700 "]]\
11701 statistics [json]",
11702 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
11703 BGP_SAFI_WITH_LABEL_HELP_STR
11704 "BGP RIB advertisement statistics\n" JSON_STR)
11705 {
11706 afi_t afi = AFI_IP6;
11707 safi_t safi = SAFI_UNICAST;
11708 struct bgp *bgp = NULL;
11709 int idx = 0, ret;
11710 bool uj = use_json(argc, argv);
11711 struct json_object *json_afi_safi = NULL, *json = NULL;
11712
11713 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11714 &bgp, false);
11715 if (!idx)
11716 return CMD_WARNING;
11717
11718 if (uj)
11719 json_afi_safi = json_object_new_array();
11720 else
11721 json_afi_safi = NULL;
11722
11723 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
11724
11725 if (uj) {
11726 json = json_object_new_object();
11727 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
11728 json_afi_safi);
11729 vty_out(vty, "%s",
11730 json_object_to_json_string_ext(
11731 json, JSON_C_TO_STRING_PRETTY));
11732 json_object_free(json);
11733 }
11734 return ret;
11735 }
11736
11737 /* BGP route print out function without JSON */
11738 DEFPY(show_ip_bgp, show_ip_bgp_cmd,
11739 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
11740 " [" BGP_SAFI_WITH_LABEL_CMD_STR
11741 "]]\
11742 <[all$all] dampening <parameters>\
11743 |route-map WORD\
11744 |prefix-list WORD\
11745 |filter-list WORD\
11746 |community-list <(1-500)|WORD> [exact-match]\
11747 |A.B.C.D/M longer-prefixes\
11748 |X:X::X:X/M longer-prefixes\
11749 >",
11750 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
11751 BGP_SAFI_WITH_LABEL_HELP_STR
11752 "Display the entries for all address families\n"
11753 "Display detailed information about dampening\n"
11754 "Display detail of configured dampening parameters\n"
11755 "Display routes matching the route-map\n"
11756 "A route-map to match on\n"
11757 "Display routes conforming to the prefix-list\n"
11758 "Prefix-list name\n"
11759 "Display routes conforming to the filter-list\n"
11760 "Regular expression access list name\n"
11761 "Display routes matching the community-list\n"
11762 "community-list number\n"
11763 "community-list name\n"
11764 "Exact match of the communities\n"
11765 "IPv4 prefix\n"
11766 "Display route and more specific routes\n"
11767 "IPv6 prefix\n"
11768 "Display route and more specific routes\n")
11769 {
11770 afi_t afi = AFI_IP6;
11771 safi_t safi = SAFI_UNICAST;
11772 int exact_match = 0;
11773 struct bgp *bgp = NULL;
11774 int idx = 0;
11775 uint8_t show_flags = 0;
11776
11777 /* [<ipv4|ipv6> [all]] */
11778 if (all) {
11779 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
11780 if (argv_find(argv, argc, "ipv4", &idx))
11781 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
11782
11783 if (argv_find(argv, argc, "ipv6", &idx))
11784 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
11785 }
11786
11787 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11788 &bgp, false);
11789 if (!idx)
11790 return CMD_WARNING;
11791
11792 if (argv_find(argv, argc, "dampening", &idx)) {
11793 if (argv_find(argv, argc, "parameters", &idx))
11794 return bgp_show_dampening_parameters(vty, afi, safi,
11795 show_flags);
11796 }
11797
11798 if (argv_find(argv, argc, "prefix-list", &idx))
11799 return bgp_show_prefix_list(vty, bgp, argv[idx + 1]->arg, afi,
11800 safi, bgp_show_type_prefix_list);
11801
11802 if (argv_find(argv, argc, "filter-list", &idx))
11803 return bgp_show_filter_list(vty, bgp, argv[idx + 1]->arg, afi,
11804 safi, bgp_show_type_filter_list);
11805
11806 if (argv_find(argv, argc, "route-map", &idx))
11807 return bgp_show_route_map(vty, bgp, argv[idx + 1]->arg, afi,
11808 safi, bgp_show_type_route_map);
11809
11810 if (argv_find(argv, argc, "community-list", &idx)) {
11811 const char *clist_number_or_name = argv[++idx]->arg;
11812 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
11813 exact_match = 1;
11814 return bgp_show_community_list(vty, bgp, clist_number_or_name,
11815 exact_match, afi, safi);
11816 }
11817 /* prefix-longer */
11818 if (argv_find(argv, argc, "A.B.C.D/M", &idx)
11819 || argv_find(argv, argc, "X:X::X:X/M", &idx))
11820 return bgp_show_prefix_longer(vty, bgp, argv[idx]->arg, afi,
11821 safi,
11822 bgp_show_type_prefix_longer);
11823
11824 return CMD_WARNING;
11825 }
11826
11827 /* BGP route print out function with JSON */
11828 DEFPY (show_ip_bgp_json,
11829 show_ip_bgp_json_cmd,
11830 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]\
11831 [all$all]\
11832 [cidr-only\
11833 |dampening <flap-statistics|dampened-paths>\
11834 |community [AA:NN|local-AS|no-advertise|no-export\
11835 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
11836 |accept-own|accept-own-nexthop|route-filter-v6\
11837 |route-filter-v4|route-filter-translated-v6\
11838 |route-filter-translated-v4] [exact-match]\
11839 ] [json$uj | wide$wide]",
11840 SHOW_STR
11841 IP_STR
11842 BGP_STR
11843 BGP_INSTANCE_HELP_STR
11844 BGP_AFI_HELP_STR
11845 BGP_SAFI_WITH_LABEL_HELP_STR
11846 "Display the entries for all address families\n"
11847 "Display only routes with non-natural netmasks\n"
11848 "Display detailed information about dampening\n"
11849 "Display flap statistics of routes\n"
11850 "Display paths suppressed due to dampening\n"
11851 "Display routes matching the communities\n"
11852 COMMUNITY_AANN_STR
11853 "Do not send outside local AS (well-known community)\n"
11854 "Do not advertise to any peer (well-known community)\n"
11855 "Do not export to next AS (well-known community)\n"
11856 "Graceful shutdown (well-known community)\n"
11857 "Do not export to any peer (well-known community)\n"
11858 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
11859 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
11860 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
11861 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
11862 "Should accept VPN route with local nexthop (well-known community)\n"
11863 "RT VPNv6 route filtering (well-known community)\n"
11864 "RT VPNv4 route filtering (well-known community)\n"
11865 "RT translated VPNv6 route filtering (well-known community)\n"
11866 "RT translated VPNv4 route filtering (well-known community)\n"
11867 "Exact match of the communities\n"
11868 JSON_STR
11869 "Increase table width for longer prefixes\n")
11870 {
11871 afi_t afi = AFI_IP6;
11872 safi_t safi = SAFI_UNICAST;
11873 enum bgp_show_type sh_type = bgp_show_type_normal;
11874 struct bgp *bgp = NULL;
11875 int idx = 0;
11876 int exact_match = 0;
11877 char *community = NULL;
11878 bool first = true;
11879 uint8_t show_flags = 0;
11880
11881
11882 if (uj) {
11883 argc--;
11884 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11885 }
11886
11887 /* [<ipv4|ipv6> [all]] */
11888 if (all) {
11889 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
11890
11891 if (argv_find(argv, argc, "ipv4", &idx))
11892 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
11893
11894 if (argv_find(argv, argc, "ipv6", &idx))
11895 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
11896 }
11897
11898 if (wide)
11899 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
11900
11901 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11902 &bgp, uj);
11903 if (!idx)
11904 return CMD_WARNING;
11905
11906 if (argv_find(argv, argc, "cidr-only", &idx))
11907 sh_type = bgp_show_type_cidr_only;
11908
11909 if (argv_find(argv, argc, "dampening", &idx)) {
11910 if (argv_find(argv, argc, "dampened-paths", &idx))
11911 sh_type = bgp_show_type_dampend_paths;
11912 else if (argv_find(argv, argc, "flap-statistics", &idx))
11913 sh_type = bgp_show_type_flap_statistics;
11914 }
11915
11916 if (argv_find(argv, argc, "community", &idx)) {
11917 char *maybecomm = NULL;
11918
11919 if (idx + 1 < argc) {
11920 if (argv[idx + 1]->type == VARIABLE_TKN)
11921 maybecomm = argv[idx + 1]->arg;
11922 else
11923 maybecomm = argv[idx + 1]->text;
11924 }
11925
11926 if (maybecomm && !strmatch(maybecomm, "json")
11927 && !strmatch(maybecomm, "exact-match"))
11928 community = maybecomm;
11929
11930 if (argv_find(argv, argc, "exact-match", &idx))
11931 exact_match = 1;
11932
11933 if (!community)
11934 sh_type = bgp_show_type_community_all;
11935 }
11936
11937 if (!all) {
11938 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
11939 if (community)
11940 return bgp_show_community(vty, bgp, community,
11941 exact_match, afi, safi,
11942 show_flags);
11943 else
11944 return bgp_show(vty, bgp, afi, safi, sh_type, NULL,
11945 show_flags);
11946 } else {
11947 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
11948 * AFI_IP6 */
11949
11950 if (uj)
11951 vty_out(vty, "{\n");
11952
11953 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
11954 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
11955 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
11956 ? AFI_IP
11957 : AFI_IP6;
11958 FOREACH_SAFI (safi) {
11959 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
11960 continue;
11961
11962 if (uj) {
11963 if (first)
11964 first = false;
11965 else
11966 vty_out(vty, ",\n");
11967 vty_out(vty, "\"%s\":{\n",
11968 get_afi_safi_str(afi, safi,
11969 true));
11970 } else
11971 vty_out(vty,
11972 "\nFor address family: %s\n",
11973 get_afi_safi_str(afi, safi,
11974 false));
11975
11976 if (community)
11977 bgp_show_community(vty, bgp, community,
11978 exact_match, afi,
11979 safi, show_flags);
11980 else
11981 bgp_show(vty, bgp, afi, safi, sh_type,
11982 NULL, show_flags);
11983 if (uj)
11984 vty_out(vty, "}\n");
11985 }
11986 } else {
11987 /* show <ip> bgp all: for each AFI and SAFI*/
11988 FOREACH_AFI_SAFI (afi, safi) {
11989 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
11990 continue;
11991
11992 if (uj) {
11993 if (first)
11994 first = false;
11995 else
11996 vty_out(vty, ",\n");
11997
11998 vty_out(vty, "\"%s\":{\n",
11999 get_afi_safi_str(afi, safi,
12000 true));
12001 } else
12002 vty_out(vty,
12003 "\nFor address family: %s\n",
12004 get_afi_safi_str(afi, safi,
12005 false));
12006
12007 if (community)
12008 bgp_show_community(vty, bgp, community,
12009 exact_match, afi,
12010 safi, show_flags);
12011 else
12012 bgp_show(vty, bgp, afi, safi, sh_type,
12013 NULL, show_flags);
12014 if (uj)
12015 vty_out(vty, "}\n");
12016 }
12017 }
12018 if (uj)
12019 vty_out(vty, "}\n");
12020 }
12021 return CMD_SUCCESS;
12022 }
12023
12024 DEFUN (show_ip_bgp_route,
12025 show_ip_bgp_route_cmd,
12026 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [json]",
12027 SHOW_STR
12028 IP_STR
12029 BGP_STR
12030 BGP_INSTANCE_HELP_STR
12031 BGP_AFI_HELP_STR
12032 BGP_SAFI_WITH_LABEL_HELP_STR
12033 "Network in the BGP routing table to display\n"
12034 "IPv4 prefix\n"
12035 "Network in the BGP routing table to display\n"
12036 "IPv6 prefix\n"
12037 "Display only the bestpath\n"
12038 "Display only multipaths\n"
12039 JSON_STR)
12040 {
12041 int prefix_check = 0;
12042
12043 afi_t afi = AFI_IP6;
12044 safi_t safi = SAFI_UNICAST;
12045 char *prefix = NULL;
12046 struct bgp *bgp = NULL;
12047 enum bgp_path_type path_type;
12048 bool uj = use_json(argc, argv);
12049
12050 int idx = 0;
12051
12052 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12053 &bgp, uj);
12054 if (!idx)
12055 return CMD_WARNING;
12056
12057 if (!bgp) {
12058 vty_out(vty,
12059 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
12060 return CMD_WARNING;
12061 }
12062
12063 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
12064 if (argv_find(argv, argc, "A.B.C.D", &idx)
12065 || argv_find(argv, argc, "X:X::X:X", &idx))
12066 prefix_check = 0;
12067 else if (argv_find(argv, argc, "A.B.C.D/M", &idx)
12068 || argv_find(argv, argc, "X:X::X:X/M", &idx))
12069 prefix_check = 1;
12070
12071 if ((argv[idx]->type == IPV6_TKN || argv[idx]->type == IPV6_PREFIX_TKN)
12072 && afi != AFI_IP6) {
12073 vty_out(vty,
12074 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
12075 return CMD_WARNING;
12076 }
12077 if ((argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV4_PREFIX_TKN)
12078 && afi != AFI_IP) {
12079 vty_out(vty,
12080 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
12081 return CMD_WARNING;
12082 }
12083
12084 prefix = argv[idx]->arg;
12085
12086 /* [<bestpath|multipath>] */
12087 if (argv_find(argv, argc, "bestpath", &idx))
12088 path_type = BGP_PATH_SHOW_BESTPATH;
12089 else if (argv_find(argv, argc, "multipath", &idx))
12090 path_type = BGP_PATH_SHOW_MULTIPATH;
12091 else
12092 path_type = BGP_PATH_SHOW_ALL;
12093
12094 return bgp_show_route(vty, bgp, prefix, afi, safi, NULL, prefix_check,
12095 path_type, uj);
12096 }
12097
12098 DEFUN (show_ip_bgp_regexp,
12099 show_ip_bgp_regexp_cmd,
12100 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] regexp REGEX [json]",
12101 SHOW_STR
12102 IP_STR
12103 BGP_STR
12104 BGP_INSTANCE_HELP_STR
12105 BGP_AFI_HELP_STR
12106 BGP_SAFI_WITH_LABEL_HELP_STR
12107 "Display routes matching the AS path regular expression\n"
12108 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
12109 JSON_STR)
12110 {
12111 afi_t afi = AFI_IP6;
12112 safi_t safi = SAFI_UNICAST;
12113 struct bgp *bgp = NULL;
12114 bool uj = use_json(argc, argv);
12115 char *regstr = NULL;
12116
12117 int idx = 0;
12118 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12119 &bgp, false);
12120 if (!idx)
12121 return CMD_WARNING;
12122
12123 // get index of regex
12124 if (argv_find(argv, argc, "REGEX", &idx))
12125 regstr = argv[idx]->arg;
12126
12127 assert(regstr);
12128 return bgp_show_regexp(vty, bgp, (const char *)regstr, afi, safi,
12129 bgp_show_type_regexp, uj);
12130 }
12131
12132 DEFPY (show_ip_bgp_instance_all,
12133 show_ip_bgp_instance_all_cmd,
12134 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [json$uj | wide$wide]",
12135 SHOW_STR
12136 IP_STR
12137 BGP_STR
12138 BGP_INSTANCE_ALL_HELP_STR
12139 BGP_AFI_HELP_STR
12140 BGP_SAFI_WITH_LABEL_HELP_STR
12141 JSON_STR
12142 "Increase table width for longer prefixes\n")
12143 {
12144 afi_t afi = AFI_IP;
12145 safi_t safi = SAFI_UNICAST;
12146 struct bgp *bgp = NULL;
12147 int idx = 0;
12148 uint8_t show_flags = 0;
12149
12150 if (uj) {
12151 argc--;
12152 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12153 }
12154
12155 if (wide)
12156 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
12157
12158 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12159 &bgp, uj);
12160 if (!idx)
12161 return CMD_WARNING;
12162
12163 bgp_show_all_instances_routes_vty(vty, afi, safi, show_flags);
12164 return CMD_SUCCESS;
12165 }
12166
12167 static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
12168 afi_t afi, safi_t safi, enum bgp_show_type type,
12169 bool use_json)
12170 {
12171 regex_t *regex;
12172 int rc;
12173 uint8_t show_flags = 0;
12174
12175 if (use_json)
12176 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12177
12178 if (!config_bgp_aspath_validate(regstr)) {
12179 vty_out(vty, "Invalid character in REGEX %s\n",
12180 regstr);
12181 return CMD_WARNING_CONFIG_FAILED;
12182 }
12183
12184 regex = bgp_regcomp(regstr);
12185 if (!regex) {
12186 vty_out(vty, "Can't compile regexp %s\n", regstr);
12187 return CMD_WARNING;
12188 }
12189
12190 rc = bgp_show(vty, bgp, afi, safi, type, regex, show_flags);
12191 bgp_regex_free(regex);
12192 return rc;
12193 }
12194
12195 static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
12196 const char *prefix_list_str, afi_t afi,
12197 safi_t safi, enum bgp_show_type type)
12198 {
12199 struct prefix_list *plist;
12200 uint8_t show_flags = 0;
12201
12202 plist = prefix_list_lookup(afi, prefix_list_str);
12203 if (plist == NULL) {
12204 vty_out(vty, "%% %s is not a valid prefix-list name\n",
12205 prefix_list_str);
12206 return CMD_WARNING;
12207 }
12208
12209 return bgp_show(vty, bgp, afi, safi, type, plist, show_flags);
12210 }
12211
12212 static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
12213 const char *filter, afi_t afi, safi_t safi,
12214 enum bgp_show_type type)
12215 {
12216 struct as_list *as_list;
12217 uint8_t show_flags = 0;
12218
12219 as_list = as_list_lookup(filter);
12220 if (as_list == NULL) {
12221 vty_out(vty, "%% %s is not a valid AS-path access-list name\n",
12222 filter);
12223 return CMD_WARNING;
12224 }
12225
12226 return bgp_show(vty, bgp, afi, safi, type, as_list, show_flags);
12227 }
12228
12229 static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
12230 const char *rmap_str, afi_t afi, safi_t safi,
12231 enum bgp_show_type type)
12232 {
12233 struct route_map *rmap;
12234 uint8_t show_flags = 0;
12235
12236 rmap = route_map_lookup_by_name(rmap_str);
12237 if (!rmap) {
12238 vty_out(vty, "%% %s is not a valid route-map name\n", rmap_str);
12239 return CMD_WARNING;
12240 }
12241
12242 return bgp_show(vty, bgp, afi, safi, type, rmap, show_flags);
12243 }
12244
12245 static int bgp_show_community(struct vty *vty, struct bgp *bgp,
12246 const char *comstr, int exact, afi_t afi,
12247 safi_t safi, uint8_t show_flags)
12248 {
12249 struct community *com;
12250 int ret = 0;
12251
12252 com = community_str2com(comstr);
12253 if (!com) {
12254 vty_out(vty, "%% Community malformed: %s\n", comstr);
12255 return CMD_WARNING;
12256 }
12257
12258 ret = bgp_show(vty, bgp, afi, safi,
12259 (exact ? bgp_show_type_community_exact
12260 : bgp_show_type_community),
12261 com, show_flags);
12262 community_free(&com);
12263
12264 return ret;
12265 }
12266
12267 static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
12268 const char *com, int exact, afi_t afi,
12269 safi_t safi)
12270 {
12271 struct community_list *list;
12272 uint8_t show_flags = 0;
12273
12274 list = community_list_lookup(bgp_clist, com, 0, COMMUNITY_LIST_MASTER);
12275 if (list == NULL) {
12276 vty_out(vty, "%% %s is not a valid community-list name\n", com);
12277 return CMD_WARNING;
12278 }
12279
12280 return bgp_show(vty, bgp, afi, safi,
12281 (exact ? bgp_show_type_community_list_exact
12282 : bgp_show_type_community_list),
12283 list, show_flags);
12284 }
12285
12286 static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
12287 const char *prefix, afi_t afi, safi_t safi,
12288 enum bgp_show_type type)
12289 {
12290 int ret;
12291 struct prefix *p;
12292 uint8_t show_flags = 0;
12293
12294 p = prefix_new();
12295
12296 ret = str2prefix(prefix, p);
12297 if (!ret) {
12298 vty_out(vty, "%% Malformed Prefix\n");
12299 return CMD_WARNING;
12300 }
12301
12302 ret = bgp_show(vty, bgp, afi, safi, type, p, show_flags);
12303 prefix_free(&p);
12304 return ret;
12305 }
12306
12307 enum bgp_stats {
12308 BGP_STATS_MAXBITLEN = 0,
12309 BGP_STATS_RIB,
12310 BGP_STATS_PREFIXES,
12311 BGP_STATS_TOTPLEN,
12312 BGP_STATS_UNAGGREGATEABLE,
12313 BGP_STATS_MAX_AGGREGATEABLE,
12314 BGP_STATS_AGGREGATES,
12315 BGP_STATS_SPACE,
12316 BGP_STATS_ASPATH_COUNT,
12317 BGP_STATS_ASPATH_MAXHOPS,
12318 BGP_STATS_ASPATH_TOTHOPS,
12319 BGP_STATS_ASPATH_MAXSIZE,
12320 BGP_STATS_ASPATH_TOTSIZE,
12321 BGP_STATS_ASN_HIGHEST,
12322 BGP_STATS_MAX,
12323 };
12324
12325 #define TABLE_STATS_IDX_VTY 0
12326 #define TABLE_STATS_IDX_JSON 1
12327
12328 static const char *table_stats_strs[][2] = {
12329 [BGP_STATS_PREFIXES] = {"Total Prefixes", "totalPrefixes"},
12330 [BGP_STATS_TOTPLEN] = {"Average prefix length", "averagePrefixLength"},
12331 [BGP_STATS_RIB] = {"Total Advertisements", "totalAdvertisements"},
12332 [BGP_STATS_UNAGGREGATEABLE] = {"Unaggregateable prefixes",
12333 "unaggregateablePrefixes"},
12334 [BGP_STATS_MAX_AGGREGATEABLE] = {"Maximum aggregateable prefixes",
12335 "maximumAggregateablePrefixes"},
12336 [BGP_STATS_AGGREGATES] = {"BGP Aggregate advertisements",
12337 "bgpAggregateAdvertisements"},
12338 [BGP_STATS_SPACE] = {"Address space advertised",
12339 "addressSpaceAdvertised"},
12340 [BGP_STATS_ASPATH_COUNT] = {"Advertisements with paths",
12341 "advertisementsWithPaths"},
12342 [BGP_STATS_ASPATH_MAXHOPS] = {"Longest AS-Path (hops)",
12343 "longestAsPath"},
12344 [BGP_STATS_ASPATH_MAXSIZE] = {"Largest AS-Path (bytes)",
12345 "largestAsPath"},
12346 [BGP_STATS_ASPATH_TOTHOPS] = {"Average AS-Path length (hops)",
12347 "averageAsPathLengthHops"},
12348 [BGP_STATS_ASPATH_TOTSIZE] = {"Average AS-Path size (bytes)",
12349 "averageAsPathSizeBytes"},
12350 [BGP_STATS_ASN_HIGHEST] = {"Highest public ASN", "highestPublicAsn"},
12351 [BGP_STATS_MAX] = {NULL, NULL}
12352 };
12353
12354 struct bgp_table_stats {
12355 struct bgp_table *table;
12356 unsigned long long counts[BGP_STATS_MAX];
12357 double total_space;
12358 };
12359
12360 static void bgp_table_stats_rn(struct bgp_dest *dest, struct bgp_dest *top,
12361 struct bgp_table_stats *ts, unsigned int space)
12362 {
12363 struct bgp_dest *pdest = bgp_dest_parent_nolock(dest);
12364 struct bgp_path_info *pi;
12365 const struct prefix *rn_p;
12366
12367 if (!bgp_dest_has_bgp_path_info_data(dest))
12368 return;
12369
12370 rn_p = bgp_dest_get_prefix(dest);
12371 ts->counts[BGP_STATS_PREFIXES]++;
12372 ts->counts[BGP_STATS_TOTPLEN] += rn_p->prefixlen;
12373
12374 /* check if the prefix is included by any other announcements */
12375 while (pdest && !bgp_dest_has_bgp_path_info_data(pdest))
12376 pdest = bgp_dest_parent_nolock(pdest);
12377
12378 if (pdest == NULL || pdest == top) {
12379 ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
12380 /* announced address space */
12381 if (space)
12382 ts->total_space += pow(2.0, space - rn_p->prefixlen);
12383 } else if (bgp_dest_has_bgp_path_info_data(pdest))
12384 ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
12385
12386
12387 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
12388 ts->counts[BGP_STATS_RIB]++;
12389
12390 if (CHECK_FLAG(pi->attr->flag,
12391 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)))
12392 ts->counts[BGP_STATS_AGGREGATES]++;
12393
12394 /* as-path stats */
12395 if (pi->attr->aspath) {
12396 unsigned int hops = aspath_count_hops(pi->attr->aspath);
12397 unsigned int size = aspath_size(pi->attr->aspath);
12398 as_t highest = aspath_highest(pi->attr->aspath);
12399
12400 ts->counts[BGP_STATS_ASPATH_COUNT]++;
12401
12402 if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS])
12403 ts->counts[BGP_STATS_ASPATH_MAXHOPS] = hops;
12404
12405 if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE])
12406 ts->counts[BGP_STATS_ASPATH_MAXSIZE] = size;
12407
12408 ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
12409 ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
12410 if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
12411 ts->counts[BGP_STATS_ASN_HIGHEST] = highest;
12412 }
12413 }
12414 }
12415
12416 static int bgp_table_stats_walker(struct thread *t)
12417 {
12418 struct bgp_dest *dest, *ndest;
12419 struct bgp_dest *top;
12420 struct bgp_table_stats *ts = THREAD_ARG(t);
12421 unsigned int space = 0;
12422
12423 if (!(top = bgp_table_top(ts->table)))
12424 return 0;
12425
12426 switch (ts->table->afi) {
12427 case AFI_IP:
12428 space = IPV4_MAX_BITLEN;
12429 break;
12430 case AFI_IP6:
12431 space = IPV6_MAX_BITLEN;
12432 break;
12433 case AFI_L2VPN:
12434 space = EVPN_ROUTE_PREFIXLEN;
12435 break;
12436 default:
12437 return 0;
12438 }
12439
12440 ts->counts[BGP_STATS_MAXBITLEN] = space;
12441
12442 for (dest = top; dest; dest = bgp_route_next(dest)) {
12443 if (ts->table->safi == SAFI_MPLS_VPN
12444 || ts->table->safi == SAFI_ENCAP
12445 || ts->table->safi == SAFI_EVPN) {
12446 struct bgp_table *table;
12447
12448 table = bgp_dest_get_bgp_table_info(dest);
12449 if (!table)
12450 continue;
12451
12452 top = bgp_table_top(table);
12453 for (ndest = bgp_table_top(table); ndest;
12454 ndest = bgp_route_next(ndest))
12455 bgp_table_stats_rn(ndest, top, ts, space);
12456 } else {
12457 bgp_table_stats_rn(dest, top, ts, space);
12458 }
12459 }
12460
12461 return 0;
12462 }
12463
12464 static void bgp_table_stats_all(struct vty *vty, afi_t afi, safi_t safi,
12465 struct json_object *json_array)
12466 {
12467 struct listnode *node, *nnode;
12468 struct bgp *bgp;
12469
12470 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
12471 bgp_table_stats_single(vty, bgp, afi, safi, json_array);
12472 }
12473
12474 static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
12475 safi_t safi, struct json_object *json_array)
12476 {
12477 struct bgp_table_stats ts;
12478 unsigned int i;
12479 int ret = CMD_SUCCESS;
12480 char temp_buf[20];
12481 struct json_object *json = NULL;
12482
12483 if (json_array)
12484 json = json_object_new_object();
12485
12486 if (!bgp->rib[afi][safi]) {
12487 char warning_msg[50];
12488
12489 snprintf(warning_msg, sizeof(warning_msg),
12490 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi,
12491 safi);
12492
12493 if (!json)
12494 vty_out(vty, "%s\n", warning_msg);
12495 else
12496 json_object_string_add(json, "warning", warning_msg);
12497
12498 ret = CMD_WARNING;
12499 goto end_table_stats;
12500 }
12501
12502 if (!json)
12503 vty_out(vty, "BGP %s RIB statistics (%s)\n",
12504 get_afi_safi_str(afi, safi, false), bgp->name_pretty);
12505 else
12506 json_object_string_add(json, "instance", bgp->name_pretty);
12507
12508 /* labeled-unicast routes live in the unicast table */
12509 if (safi == SAFI_LABELED_UNICAST)
12510 safi = SAFI_UNICAST;
12511
12512 memset(&ts, 0, sizeof(ts));
12513 ts.table = bgp->rib[afi][safi];
12514 thread_execute(bm->master, bgp_table_stats_walker, &ts, 0);
12515
12516 for (i = 0; i < BGP_STATS_MAX; i++) {
12517 if ((!json && !table_stats_strs[i][TABLE_STATS_IDX_VTY])
12518 || (json && !table_stats_strs[i][TABLE_STATS_IDX_JSON]))
12519 continue;
12520
12521 switch (i) {
12522 case BGP_STATS_ASPATH_TOTHOPS:
12523 case BGP_STATS_ASPATH_TOTSIZE:
12524 if (!json) {
12525 snprintf(
12526 temp_buf, sizeof(temp_buf), "%12.2f",
12527 ts.counts[i]
12528 ? (float)ts.counts[i]
12529 / (float)ts.counts
12530 [BGP_STATS_ASPATH_COUNT]
12531 : 0);
12532 vty_out(vty, "%-30s: %s",
12533 table_stats_strs[i]
12534 [TABLE_STATS_IDX_VTY],
12535 temp_buf);
12536 } else {
12537 json_object_double_add(
12538 json,
12539 table_stats_strs[i]
12540 [TABLE_STATS_IDX_JSON],
12541 ts.counts[i]
12542 ? (double)ts.counts[i]
12543 / (double)ts.counts
12544 [BGP_STATS_ASPATH_COUNT]
12545 : 0);
12546 }
12547 break;
12548 case BGP_STATS_TOTPLEN:
12549 if (!json) {
12550 snprintf(
12551 temp_buf, sizeof(temp_buf), "%12.2f",
12552 ts.counts[i]
12553 ? (float)ts.counts[i]
12554 / (float)ts.counts
12555 [BGP_STATS_PREFIXES]
12556 : 0);
12557 vty_out(vty, "%-30s: %s",
12558 table_stats_strs[i]
12559 [TABLE_STATS_IDX_VTY],
12560 temp_buf);
12561 } else {
12562 json_object_double_add(
12563 json,
12564 table_stats_strs[i]
12565 [TABLE_STATS_IDX_JSON],
12566 ts.counts[i]
12567 ? (double)ts.counts[i]
12568 / (double)ts.counts
12569 [BGP_STATS_PREFIXES]
12570 : 0);
12571 }
12572 break;
12573 case BGP_STATS_SPACE:
12574 if (!json) {
12575 snprintf(temp_buf, sizeof(temp_buf), "%12g",
12576 ts.total_space);
12577 vty_out(vty, "%-30s: %s\n",
12578 table_stats_strs[i]
12579 [TABLE_STATS_IDX_VTY],
12580 temp_buf);
12581 } else {
12582 json_object_double_add(
12583 json,
12584 table_stats_strs[i]
12585 [TABLE_STATS_IDX_JSON],
12586 (double)ts.total_space);
12587 }
12588 if (afi == AFI_IP6) {
12589 if (!json) {
12590 snprintf(temp_buf, sizeof(temp_buf),
12591 "%12g",
12592 ts.total_space
12593 * pow(2.0, -128 + 32));
12594 vty_out(vty, "%30s: %s\n",
12595 "/32 equivalent %s\n",
12596 temp_buf);
12597 } else {
12598 json_object_double_add(
12599 json, "/32equivalent",
12600 (double)(ts.total_space
12601 * pow(2.0,
12602 -128 + 32)));
12603 }
12604 if (!json) {
12605 snprintf(temp_buf, sizeof(temp_buf),
12606 "%12g",
12607 ts.total_space
12608 * pow(2.0, -128 + 48));
12609 vty_out(vty, "%30s: %s\n",
12610 "/48 equivalent %s\n",
12611 temp_buf);
12612 } else {
12613 json_object_double_add(
12614 json, "/48equivalent",
12615 (double)(ts.total_space
12616 * pow(2.0,
12617 -128 + 48)));
12618 }
12619 } else {
12620 if (!json) {
12621 snprintf(temp_buf, sizeof(temp_buf),
12622 "%12.2f",
12623 ts.total_space * 100.
12624 * pow(2.0, -32));
12625 vty_out(vty, "%30s: %s\n",
12626 "% announced ", temp_buf);
12627 } else {
12628 json_object_double_add(
12629 json, "%announced",
12630 (double)(ts.total_space * 100.
12631 * pow(2.0, -32)));
12632 }
12633 if (!json) {
12634 snprintf(temp_buf, sizeof(temp_buf),
12635 "%12.2f",
12636 ts.total_space
12637 * pow(2.0, -32 + 8));
12638 vty_out(vty, "%30s: %s\n",
12639 "/8 equivalent ", temp_buf);
12640 } else {
12641 json_object_double_add(
12642 json, "/8equivalent",
12643 (double)(ts.total_space
12644 * pow(2.0, -32 + 8)));
12645 }
12646 if (!json) {
12647 snprintf(temp_buf, sizeof(temp_buf),
12648 "%12.2f",
12649 ts.total_space
12650 * pow(2.0, -32 + 24));
12651 vty_out(vty, "%30s: %s\n",
12652 "/24 equivalent ", temp_buf);
12653 } else {
12654 json_object_double_add(
12655 json, "/24equivalent",
12656 (double)(ts.total_space
12657 * pow(2.0, -32 + 24)));
12658 }
12659 }
12660 break;
12661 default:
12662 if (!json) {
12663 snprintf(temp_buf, sizeof(temp_buf), "%12llu",
12664 ts.counts[i]);
12665 vty_out(vty, "%-30s: %s",
12666 table_stats_strs[i]
12667 [TABLE_STATS_IDX_VTY],
12668 temp_buf);
12669 } else {
12670 json_object_int_add(
12671 json,
12672 table_stats_strs[i]
12673 [TABLE_STATS_IDX_JSON],
12674 ts.counts[i]);
12675 }
12676 }
12677 if (!json)
12678 vty_out(vty, "\n");
12679 }
12680 end_table_stats:
12681 if (json)
12682 json_object_array_add(json_array, json);
12683 return ret;
12684 }
12685
12686 static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
12687 safi_t safi, struct json_object *json_array)
12688 {
12689 if (!bgp) {
12690 bgp_table_stats_all(vty, afi, safi, json_array);
12691 return CMD_SUCCESS;
12692 }
12693
12694 return bgp_table_stats_single(vty, bgp, afi, safi, json_array);
12695 }
12696
12697 enum bgp_pcounts {
12698 PCOUNT_ADJ_IN = 0,
12699 PCOUNT_DAMPED,
12700 PCOUNT_REMOVED,
12701 PCOUNT_HISTORY,
12702 PCOUNT_STALE,
12703 PCOUNT_VALID,
12704 PCOUNT_ALL,
12705 PCOUNT_COUNTED,
12706 PCOUNT_BPATH_SELECTED,
12707 PCOUNT_PFCNT, /* the figure we display to users */
12708 PCOUNT_MAX,
12709 };
12710
12711 static const char *const pcount_strs[] = {
12712 [PCOUNT_ADJ_IN] = "Adj-in",
12713 [PCOUNT_DAMPED] = "Damped",
12714 [PCOUNT_REMOVED] = "Removed",
12715 [PCOUNT_HISTORY] = "History",
12716 [PCOUNT_STALE] = "Stale",
12717 [PCOUNT_VALID] = "Valid",
12718 [PCOUNT_ALL] = "All RIB",
12719 [PCOUNT_COUNTED] = "PfxCt counted",
12720 [PCOUNT_BPATH_SELECTED] = "PfxCt Best Selected",
12721 [PCOUNT_PFCNT] = "Useable",
12722 [PCOUNT_MAX] = NULL,
12723 };
12724
12725 struct peer_pcounts {
12726 unsigned int count[PCOUNT_MAX];
12727 const struct peer *peer;
12728 const struct bgp_table *table;
12729 safi_t safi;
12730 };
12731
12732 static void bgp_peer_count_proc(struct bgp_dest *rn, struct peer_pcounts *pc)
12733 {
12734 const struct bgp_adj_in *ain;
12735 const struct bgp_path_info *pi;
12736 const struct peer *peer = pc->peer;
12737
12738 for (ain = rn->adj_in; ain; ain = ain->next)
12739 if (ain->peer == peer)
12740 pc->count[PCOUNT_ADJ_IN]++;
12741
12742 for (pi = bgp_dest_get_bgp_path_info(rn); pi; pi = pi->next) {
12743
12744 if (pi->peer != peer)
12745 continue;
12746
12747 pc->count[PCOUNT_ALL]++;
12748
12749 if (CHECK_FLAG(pi->flags, BGP_PATH_DAMPED))
12750 pc->count[PCOUNT_DAMPED]++;
12751 if (CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
12752 pc->count[PCOUNT_HISTORY]++;
12753 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
12754 pc->count[PCOUNT_REMOVED]++;
12755 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE))
12756 pc->count[PCOUNT_STALE]++;
12757 if (CHECK_FLAG(pi->flags, BGP_PATH_VALID))
12758 pc->count[PCOUNT_VALID]++;
12759 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
12760 pc->count[PCOUNT_PFCNT]++;
12761 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
12762 pc->count[PCOUNT_BPATH_SELECTED]++;
12763
12764 if (CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
12765 pc->count[PCOUNT_COUNTED]++;
12766 if (CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
12767 flog_err(
12768 EC_LIB_DEVELOPMENT,
12769 "Attempting to count but flags say it is unusable");
12770 } else {
12771 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
12772 flog_err(
12773 EC_LIB_DEVELOPMENT,
12774 "Not counted but flags say we should");
12775 }
12776 }
12777 }
12778
12779 static int bgp_peer_count_walker(struct thread *t)
12780 {
12781 struct bgp_dest *rn, *rm;
12782 const struct bgp_table *table;
12783 struct peer_pcounts *pc = THREAD_ARG(t);
12784
12785 if (pc->safi == SAFI_MPLS_VPN || pc->safi == SAFI_ENCAP
12786 || pc->safi == SAFI_EVPN) {
12787 /* Special handling for 2-level routing tables. */
12788 for (rn = bgp_table_top(pc->table); rn;
12789 rn = bgp_route_next(rn)) {
12790 table = bgp_dest_get_bgp_table_info(rn);
12791 if (table != NULL)
12792 for (rm = bgp_table_top(table); rm;
12793 rm = bgp_route_next(rm))
12794 bgp_peer_count_proc(rm, pc);
12795 }
12796 } else
12797 for (rn = bgp_table_top(pc->table); rn; rn = bgp_route_next(rn))
12798 bgp_peer_count_proc(rn, pc);
12799
12800 return 0;
12801 }
12802
12803 static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi,
12804 safi_t safi, bool use_json)
12805 {
12806 struct peer_pcounts pcounts = {.peer = peer};
12807 unsigned int i;
12808 json_object *json = NULL;
12809 json_object *json_loop = NULL;
12810
12811 if (use_json) {
12812 json = json_object_new_object();
12813 json_loop = json_object_new_object();
12814 }
12815
12816 if (!peer || !peer->bgp || !peer->afc[afi][safi]
12817 || !peer->bgp->rib[afi][safi]) {
12818 if (use_json) {
12819 json_object_string_add(
12820 json, "warning",
12821 "No such neighbor or address family");
12822 vty_out(vty, "%s\n", json_object_to_json_string(json));
12823 json_object_free(json);
12824 json_object_free(json_loop);
12825 } else
12826 vty_out(vty, "%% No such neighbor or address family\n");
12827
12828 return CMD_WARNING;
12829 }
12830
12831 memset(&pcounts, 0, sizeof(pcounts));
12832 pcounts.peer = peer;
12833 pcounts.table = peer->bgp->rib[afi][safi];
12834 pcounts.safi = safi;
12835
12836 /* in-place call via thread subsystem so as to record execution time
12837 * stats for the thread-walk (i.e. ensure this can't be blamed on
12838 * on just vty_read()).
12839 */
12840 thread_execute(bm->master, bgp_peer_count_walker, &pcounts, 0);
12841
12842 if (use_json) {
12843 json_object_string_add(json, "prefixCountsFor", peer->host);
12844 json_object_string_add(json, "multiProtocol",
12845 get_afi_safi_str(afi, safi, true));
12846 json_object_int_add(json, "pfxCounter",
12847 peer->pcount[afi][safi]);
12848
12849 for (i = 0; i < PCOUNT_MAX; i++)
12850 json_object_int_add(json_loop, pcount_strs[i],
12851 pcounts.count[i]);
12852
12853 json_object_object_add(json, "ribTableWalkCounters", json_loop);
12854
12855 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
12856 json_object_string_add(json, "pfxctDriftFor",
12857 peer->host);
12858 json_object_string_add(
12859 json, "recommended",
12860 "Please report this bug, with the above command output");
12861 }
12862 vty_out(vty, "%s\n", json_object_to_json_string_ext(
12863 json, JSON_C_TO_STRING_PRETTY));
12864 json_object_free(json);
12865 } else {
12866
12867 if (peer->hostname
12868 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
12869 vty_out(vty, "Prefix counts for %s/%s, %s\n",
12870 peer->hostname, peer->host,
12871 get_afi_safi_str(afi, safi, false));
12872 } else {
12873 vty_out(vty, "Prefix counts for %s, %s\n", peer->host,
12874 get_afi_safi_str(afi, safi, false));
12875 }
12876
12877 vty_out(vty, "PfxCt: %u\n", peer->pcount[afi][safi]);
12878 vty_out(vty, "\nCounts from RIB table walk:\n\n");
12879
12880 for (i = 0; i < PCOUNT_MAX; i++)
12881 vty_out(vty, "%20s: %-10d\n", pcount_strs[i],
12882 pcounts.count[i]);
12883
12884 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
12885 vty_out(vty, "%s [pcount] PfxCt drift!\n", peer->host);
12886 vty_out(vty,
12887 "Please report this bug, with the above command output\n");
12888 }
12889 }
12890
12891 return CMD_SUCCESS;
12892 }
12893
12894 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts,
12895 show_ip_bgp_instance_neighbor_prefix_counts_cmd,
12896 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_CMD_STR"]] neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
12897 SHOW_STR
12898 IP_STR
12899 BGP_STR
12900 BGP_INSTANCE_HELP_STR
12901 BGP_AFI_HELP_STR
12902 BGP_SAFI_HELP_STR
12903 "Detailed information on TCP and BGP neighbor connections\n"
12904 "Neighbor to display information about\n"
12905 "Neighbor to display information about\n"
12906 "Neighbor on BGP configured interface\n"
12907 "Display detailed prefix count information\n"
12908 JSON_STR)
12909 {
12910 afi_t afi = AFI_IP6;
12911 safi_t safi = SAFI_UNICAST;
12912 struct peer *peer;
12913 int idx = 0;
12914 struct bgp *bgp = NULL;
12915 bool uj = use_json(argc, argv);
12916
12917 if (uj)
12918 argc--;
12919
12920 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12921 &bgp, uj);
12922 if (!idx)
12923 return CMD_WARNING;
12924
12925 argv_find(argv, argc, "neighbors", &idx);
12926 peer = peer_lookup_in_view(vty, bgp, argv[idx + 1]->arg, uj);
12927 if (!peer)
12928 return CMD_WARNING;
12929
12930 return bgp_peer_counts(vty, peer, afi, safi, uj);
12931 }
12932
12933 #ifdef KEEP_OLD_VPN_COMMANDS
12934 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts,
12935 show_ip_bgp_vpn_neighbor_prefix_counts_cmd,
12936 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
12937 SHOW_STR
12938 IP_STR
12939 BGP_STR
12940 BGP_VPNVX_HELP_STR
12941 "Display information about all VPNv4 NLRIs\n"
12942 "Detailed information on TCP and BGP neighbor connections\n"
12943 "Neighbor to display information about\n"
12944 "Neighbor to display information about\n"
12945 "Neighbor on BGP configured interface\n"
12946 "Display detailed prefix count information\n"
12947 JSON_STR)
12948 {
12949 int idx_peer = 6;
12950 struct peer *peer;
12951 bool uj = use_json(argc, argv);
12952
12953 peer = peer_lookup_in_view(vty, NULL, argv[idx_peer]->arg, uj);
12954 if (!peer)
12955 return CMD_WARNING;
12956
12957 return bgp_peer_counts(vty, peer, AFI_IP, SAFI_MPLS_VPN, uj);
12958 }
12959
12960 DEFUN (show_ip_bgp_vpn_all_route_prefix,
12961 show_ip_bgp_vpn_all_route_prefix_cmd,
12962 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
12963 SHOW_STR
12964 IP_STR
12965 BGP_STR
12966 BGP_VPNVX_HELP_STR
12967 "Display information about all VPNv4 NLRIs\n"
12968 "Network in the BGP routing table to display\n"
12969 "Network in the BGP routing table to display\n"
12970 JSON_STR)
12971 {
12972 int idx = 0;
12973 char *network = NULL;
12974 struct bgp *bgp = bgp_get_default();
12975 if (!bgp) {
12976 vty_out(vty, "Can't find default instance\n");
12977 return CMD_WARNING;
12978 }
12979
12980 if (argv_find(argv, argc, "A.B.C.D", &idx))
12981 network = argv[idx]->arg;
12982 else if (argv_find(argv, argc, "A.B.C.D/M", &idx))
12983 network = argv[idx]->arg;
12984 else {
12985 vty_out(vty, "Unable to figure out Network\n");
12986 return CMD_WARNING;
12987 }
12988
12989 return bgp_show_route(vty, bgp, network, AFI_IP, SAFI_MPLS_VPN, NULL, 0,
12990 BGP_PATH_SHOW_ALL, use_json(argc, argv));
12991 }
12992 #endif /* KEEP_OLD_VPN_COMMANDS */
12993
12994 DEFUN (show_bgp_l2vpn_evpn_route_prefix,
12995 show_bgp_l2vpn_evpn_route_prefix_cmd,
12996 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
12997 SHOW_STR
12998 BGP_STR
12999 L2VPN_HELP_STR
13000 EVPN_HELP_STR
13001 "Network in the BGP routing table to display\n"
13002 "Network in the BGP routing table to display\n"
13003 "Network in the BGP routing table to display\n"
13004 "Network in the BGP routing table to display\n"
13005 JSON_STR)
13006 {
13007 int idx = 0;
13008 char *network = NULL;
13009 int prefix_check = 0;
13010
13011 if (argv_find(argv, argc, "A.B.C.D", &idx) ||
13012 argv_find(argv, argc, "X:X::X:X", &idx))
13013 network = argv[idx]->arg;
13014 else if (argv_find(argv, argc, "A.B.C.D/M", &idx) ||
13015 argv_find(argv, argc, "X:X::X:X/M", &idx)) {
13016 network = argv[idx]->arg;
13017 prefix_check = 1;
13018 } else {
13019 vty_out(vty, "Unable to figure out Network\n");
13020 return CMD_WARNING;
13021 }
13022 return bgp_show_route(vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL,
13023 prefix_check, BGP_PATH_SHOW_ALL,
13024 use_json(argc, argv));
13025 }
13026
13027 static void show_adj_route_header(struct vty *vty, struct bgp *bgp,
13028 struct bgp_table *table, int *header1,
13029 int *header2, json_object *json,
13030 json_object *json_scode,
13031 json_object *json_ocode, bool wide)
13032 {
13033 uint64_t version = table ? table->version : 0;
13034 char buf[BUFSIZ] = {0};
13035
13036 if (*header1) {
13037 if (json) {
13038 json_object_int_add(json, "bgpTableVersion", version);
13039 json_object_string_add(json, "bgpLocalRouterId",
13040 inet_ntop(AF_INET,
13041 &bgp->router_id, buf,
13042 sizeof(buf)));
13043 json_object_int_add(json, "defaultLocPrf",
13044 bgp->default_local_pref);
13045 json_object_int_add(json, "localAS", bgp->as);
13046 json_object_object_add(json, "bgpStatusCodes",
13047 json_scode);
13048 json_object_object_add(json, "bgpOriginCodes",
13049 json_ocode);
13050 } else {
13051 vty_out(vty,
13052 "BGP table version is %" PRIu64
13053 ", local router ID is %pI4, vrf id ",
13054 version, &bgp->router_id);
13055 if (bgp->vrf_id == VRF_UNKNOWN)
13056 vty_out(vty, "%s", VRFID_NONE_STR);
13057 else
13058 vty_out(vty, "%u", bgp->vrf_id);
13059 vty_out(vty, "\n");
13060 vty_out(vty, "Default local pref %u, ",
13061 bgp->default_local_pref);
13062 vty_out(vty, "local AS %u\n", bgp->as);
13063 vty_out(vty, BGP_SHOW_SCODE_HEADER);
13064 vty_out(vty, BGP_SHOW_NCODE_HEADER);
13065 vty_out(vty, BGP_SHOW_OCODE_HEADER);
13066 }
13067 *header1 = 0;
13068 }
13069 if (*header2) {
13070 if (!json)
13071 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
13072 : BGP_SHOW_HEADER));
13073 *header2 = 0;
13074 }
13075 }
13076
13077 static void
13078 show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
13079 afi_t afi, safi_t safi, enum bgp_show_adj_route_type type,
13080 const char *rmap_name, json_object *json, json_object *json_ar,
13081 json_object *json_scode, json_object *json_ocode,
13082 uint8_t show_flags, int *header1, int *header2, char *rd_str,
13083 unsigned long *output_count, unsigned long *filtered_count)
13084 {
13085 struct bgp_adj_in *ain;
13086 struct bgp_adj_out *adj;
13087 struct bgp_dest *dest;
13088 struct bgp *bgp;
13089 struct attr attr;
13090 int ret;
13091 struct update_subgroup *subgrp;
13092 struct peer_af *paf;
13093 bool route_filtered;
13094 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13095 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
13096 bool show_rd = ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
13097 || (safi == SAFI_EVPN))
13098 ? true
13099 : false;
13100
13101 bgp = peer->bgp;
13102
13103 if (!bgp) {
13104 if (use_json) {
13105 json_object_string_add(json, "alert", "no BGP");
13106 vty_out(vty, "%s\n", json_object_to_json_string(json));
13107 json_object_free(json);
13108 } else
13109 vty_out(vty, "%% No bgp\n");
13110 return;
13111 }
13112
13113 subgrp = peer_subgroup(peer, afi, safi);
13114
13115 if (type == bgp_show_adj_route_advertised && subgrp
13116 && CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) {
13117 char buf[BUFSIZ] = {0};
13118
13119 if (use_json) {
13120 json_object_int_add(json, "bgpTableVersion",
13121 table->version);
13122 json_object_string_add(json, "bgpLocalRouterId",
13123 inet_ntop(AF_INET,
13124 &bgp->router_id, buf,
13125 sizeof(buf)));
13126 json_object_int_add(json, "defaultLocPrf",
13127 bgp->default_local_pref);
13128 json_object_int_add(json, "localAS", bgp->as);
13129 json_object_object_add(json, "bgpStatusCodes",
13130 json_scode);
13131 json_object_object_add(json, "bgpOriginCodes",
13132 json_ocode);
13133 json_object_string_add(
13134 json, "bgpOriginatingDefaultNetwork",
13135 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
13136 } else {
13137 vty_out(vty,
13138 "BGP table version is %" PRIu64
13139 ", local router ID is %pI4, vrf id ",
13140 table->version, &bgp->router_id);
13141 if (bgp->vrf_id == VRF_UNKNOWN)
13142 vty_out(vty, "%s", VRFID_NONE_STR);
13143 else
13144 vty_out(vty, "%u", bgp->vrf_id);
13145 vty_out(vty, "\n");
13146 vty_out(vty, "Default local pref %u, ",
13147 bgp->default_local_pref);
13148 vty_out(vty, "local AS %u\n", bgp->as);
13149 vty_out(vty, BGP_SHOW_SCODE_HEADER);
13150 vty_out(vty, BGP_SHOW_NCODE_HEADER);
13151 vty_out(vty, BGP_SHOW_OCODE_HEADER);
13152
13153 vty_out(vty, "Originating default network %s\n\n",
13154 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
13155 }
13156 *header1 = 0;
13157 }
13158
13159 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
13160 if (type == bgp_show_adj_route_received
13161 || type == bgp_show_adj_route_filtered) {
13162 for (ain = dest->adj_in; ain; ain = ain->next) {
13163 if (ain->peer != peer)
13164 continue;
13165
13166 show_adj_route_header(vty, bgp, table, header1,
13167 header2, json, json_scode,
13168 json_ocode, wide);
13169
13170 if ((safi == SAFI_MPLS_VPN)
13171 || (safi == SAFI_ENCAP)
13172 || (safi == SAFI_EVPN)) {
13173 if (use_json)
13174 json_object_string_add(
13175 json_ar, "rd", rd_str);
13176 else if (show_rd && rd_str) {
13177 vty_out(vty,
13178 "Route Distinguisher: %s\n",
13179 rd_str);
13180 show_rd = false;
13181 }
13182 }
13183
13184 attr = *ain->attr;
13185 route_filtered = false;
13186
13187 /* Filter prefix using distribute list,
13188 * filter list or prefix list
13189 */
13190 const struct prefix *rn_p =
13191 bgp_dest_get_prefix(dest);
13192 if ((bgp_input_filter(peer, rn_p, &attr, afi,
13193 safi))
13194 == FILTER_DENY)
13195 route_filtered = true;
13196
13197 /* Filter prefix using route-map */
13198 ret = bgp_input_modifier(peer, rn_p, &attr, afi,
13199 safi, rmap_name, NULL,
13200 0, NULL);
13201
13202 if (type == bgp_show_adj_route_filtered &&
13203 !route_filtered && ret != RMAP_DENY) {
13204 bgp_attr_undup(&attr, ain->attr);
13205 continue;
13206 }
13207
13208 if (type == bgp_show_adj_route_received
13209 && (route_filtered || ret == RMAP_DENY))
13210 (*filtered_count)++;
13211
13212 route_vty_out_tmp(vty, rn_p, &attr, safi,
13213 use_json, json_ar, wide);
13214 bgp_attr_undup(&attr, ain->attr);
13215 (*output_count)++;
13216 }
13217 } else if (type == bgp_show_adj_route_advertised) {
13218 RB_FOREACH (adj, bgp_adj_out_rb, &dest->adj_out)
13219 SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
13220 if (paf->peer != peer || !adj->attr)
13221 continue;
13222
13223 show_adj_route_header(vty, bgp, table,
13224 header1, header2,
13225 json, json_scode,
13226 json_ocode, wide);
13227
13228 const struct prefix *rn_p =
13229 bgp_dest_get_prefix(dest);
13230
13231 attr = *adj->attr;
13232 ret = bgp_output_modifier(
13233 peer, rn_p, &attr, afi, safi,
13234 rmap_name);
13235
13236 if (ret != RMAP_DENY) {
13237 if ((safi == SAFI_MPLS_VPN)
13238 || (safi == SAFI_ENCAP)
13239 || (safi == SAFI_EVPN)) {
13240 if (use_json)
13241 json_object_string_add(
13242 json_ar,
13243 "rd",
13244 rd_str);
13245 else if (show_rd
13246 && rd_str) {
13247 vty_out(vty,
13248 "Route Distinguisher: %s\n",
13249 rd_str);
13250 show_rd = false;
13251 }
13252 }
13253 route_vty_out_tmp(
13254 vty, rn_p, &attr, safi,
13255 use_json, json_ar,
13256 wide);
13257 (*output_count)++;
13258 } else {
13259 (*filtered_count)++;
13260 }
13261
13262 bgp_attr_undup(&attr, adj->attr);
13263 }
13264 } else if (type == bgp_show_adj_route_bestpath) {
13265 struct bgp_path_info *pi;
13266
13267 show_adj_route_header(vty, bgp, table, header1, header2,
13268 json, json_scode, json_ocode,
13269 wide);
13270
13271 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
13272 pi = pi->next) {
13273 if (pi->peer != peer)
13274 continue;
13275
13276 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
13277 continue;
13278
13279 route_vty_out_tmp(vty,
13280 bgp_dest_get_prefix(dest),
13281 pi->attr, safi, use_json,
13282 json_ar, wide);
13283 (*output_count)++;
13284 }
13285 }
13286 }
13287 }
13288
13289 static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
13290 safi_t safi, enum bgp_show_adj_route_type type,
13291 const char *rmap_name, uint8_t show_flags)
13292 {
13293 struct bgp *bgp;
13294 struct bgp_table *table;
13295 json_object *json = NULL;
13296 json_object *json_scode = NULL;
13297 json_object *json_ocode = NULL;
13298 json_object *json_ar = NULL;
13299 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13300
13301 /* Init BGP headers here so they're only displayed once
13302 * even if 'table' is 2-tier (MPLS_VPN, ENCAP, EVPN).
13303 */
13304 int header1 = 1;
13305 int header2 = 1;
13306
13307 /*
13308 * Initialize variables for each RD
13309 * All prefixes under an RD is aggregated within "json_routes"
13310 */
13311 char rd_str[BUFSIZ] = {0};
13312 json_object *json_routes = NULL;
13313
13314
13315 /* For 2-tier tables, prefix counts need to be
13316 * maintained across multiple runs of show_adj_route()
13317 */
13318 unsigned long output_count_per_rd;
13319 unsigned long filtered_count_per_rd;
13320 unsigned long output_count = 0;
13321 unsigned long filtered_count = 0;
13322
13323 if (use_json) {
13324 json = json_object_new_object();
13325 json_ar = json_object_new_object();
13326 json_scode = json_object_new_object();
13327 json_ocode = json_object_new_object();
13328
13329 json_object_string_add(json_scode, "suppressed", "s");
13330 json_object_string_add(json_scode, "damped", "d");
13331 json_object_string_add(json_scode, "history", "h");
13332 json_object_string_add(json_scode, "valid", "*");
13333 json_object_string_add(json_scode, "best", ">");
13334 json_object_string_add(json_scode, "multipath", "=");
13335 json_object_string_add(json_scode, "internal", "i");
13336 json_object_string_add(json_scode, "ribFailure", "r");
13337 json_object_string_add(json_scode, "stale", "S");
13338 json_object_string_add(json_scode, "removed", "R");
13339
13340 json_object_string_add(json_ocode, "igp", "i");
13341 json_object_string_add(json_ocode, "egp", "e");
13342 json_object_string_add(json_ocode, "incomplete", "?");
13343 }
13344
13345 if (!peer || !peer->afc[afi][safi]) {
13346 if (use_json) {
13347 json_object_string_add(
13348 json, "warning",
13349 "No such neighbor or address family");
13350 vty_out(vty, "%s\n", json_object_to_json_string(json));
13351 json_object_free(json);
13352 } else
13353 vty_out(vty, "%% No such neighbor or address family\n");
13354
13355 return CMD_WARNING;
13356 }
13357
13358 if ((type == bgp_show_adj_route_received
13359 || type == bgp_show_adj_route_filtered)
13360 && !CHECK_FLAG(peer->af_flags[afi][safi],
13361 PEER_FLAG_SOFT_RECONFIG)) {
13362 if (use_json) {
13363 json_object_string_add(
13364 json, "warning",
13365 "Inbound soft reconfiguration not enabled");
13366 vty_out(vty, "%s\n", json_object_to_json_string(json));
13367 json_object_free(json);
13368 } else
13369 vty_out(vty,
13370 "%% Inbound soft reconfiguration not enabled\n");
13371
13372 return CMD_WARNING;
13373 }
13374
13375 bgp = peer->bgp;
13376
13377 /* labeled-unicast routes live in the unicast table */
13378 if (safi == SAFI_LABELED_UNICAST)
13379 table = bgp->rib[afi][SAFI_UNICAST];
13380 else
13381 table = bgp->rib[afi][safi];
13382
13383 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
13384 || (safi == SAFI_EVPN)) {
13385
13386 struct bgp_dest *dest;
13387
13388 for (dest = bgp_table_top(table); dest;
13389 dest = bgp_route_next(dest)) {
13390 table = bgp_dest_get_bgp_table_info(dest);
13391 if (!table)
13392 continue;
13393
13394 output_count_per_rd = 0;
13395 filtered_count_per_rd = 0;
13396
13397 if (use_json)
13398 json_routes = json_object_new_object();
13399
13400 const struct prefix_rd *prd;
13401 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
13402 dest);
13403
13404 prefix_rd2str(prd, rd_str, sizeof(rd_str));
13405
13406 show_adj_route(vty, peer, table, afi, safi, type,
13407 rmap_name, json, json_routes, json_scode,
13408 json_ocode, show_flags, &header1,
13409 &header2, rd_str, &output_count_per_rd,
13410 &filtered_count_per_rd);
13411
13412 /* Don't include an empty RD in the output! */
13413 if (json_routes && (output_count_per_rd > 0))
13414 json_object_object_add(json_ar, rd_str,
13415 json_routes);
13416
13417 output_count += output_count_per_rd;
13418 filtered_count += filtered_count_per_rd;
13419 }
13420 } else
13421 show_adj_route(vty, peer, table, afi, safi, type, rmap_name,
13422 json, json_ar, json_scode, json_ocode,
13423 show_flags, &header1, &header2, rd_str,
13424 &output_count, &filtered_count);
13425
13426 if (use_json) {
13427 json_object_object_add(json, "advertisedRoutes", json_ar);
13428 json_object_int_add(json, "totalPrefixCounter", output_count);
13429 json_object_int_add(json, "filteredPrefixCounter",
13430 filtered_count);
13431
13432 vty_out(vty, "%s\n",
13433 json_object_to_json_string_ext(
13434 json, JSON_C_TO_STRING_PRETTY));
13435
13436 if (!output_count && !filtered_count) {
13437 json_object_free(json_scode);
13438 json_object_free(json_ocode);
13439 }
13440
13441 if (json)
13442 json_object_free(json);
13443
13444 } else if (output_count > 0) {
13445 if (filtered_count > 0)
13446 vty_out(vty,
13447 "\nTotal number of prefixes %ld (%ld filtered)\n",
13448 output_count, filtered_count);
13449 else
13450 vty_out(vty, "\nTotal number of prefixes %ld\n",
13451 output_count);
13452 }
13453
13454 return CMD_SUCCESS;
13455 }
13456
13457 DEFPY (show_ip_bgp_instance_neighbor_bestpath_route,
13458 show_ip_bgp_instance_neighbor_bestpath_route_cmd,
13459 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] neighbors <A.B.C.D|X:X::X:X|WORD> bestpath-routes [json$uj | wide$wide]",
13460 SHOW_STR
13461 IP_STR
13462 BGP_STR
13463 BGP_INSTANCE_HELP_STR
13464 BGP_AFI_HELP_STR
13465 BGP_SAFI_WITH_LABEL_HELP_STR
13466 "Detailed information on TCP and BGP neighbor connections\n"
13467 "Neighbor to display information about\n"
13468 "Neighbor to display information about\n"
13469 "Neighbor on BGP configured interface\n"
13470 "Display the routes selected by best path\n"
13471 JSON_STR
13472 "Increase table width for longer prefixes\n")
13473 {
13474 afi_t afi = AFI_IP6;
13475 safi_t safi = SAFI_UNICAST;
13476 char *rmap_name = NULL;
13477 char *peerstr = NULL;
13478 struct bgp *bgp = NULL;
13479 struct peer *peer;
13480 enum bgp_show_adj_route_type type = bgp_show_adj_route_bestpath;
13481 int idx = 0;
13482 uint8_t show_flags = 0;
13483
13484 if (uj)
13485 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13486
13487 if (wide)
13488 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
13489
13490 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13491 &bgp, uj);
13492
13493 if (!idx)
13494 return CMD_WARNING;
13495
13496 argv_find(argv, argc, "neighbors", &idx);
13497 peerstr = argv[++idx]->arg;
13498
13499 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
13500 if (!peer)
13501 return CMD_WARNING;
13502
13503 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13504 show_flags);
13505 }
13506
13507 DEFPY (show_ip_bgp_instance_neighbor_advertised_route,
13508 show_ip_bgp_instance_neighbor_advertised_route_cmd,
13509 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [all$all] neighbors <A.B.C.D|X:X::X:X|WORD> <advertised-routes|received-routes|filtered-routes> [route-map WORD] [json$uj | wide$wide]",
13510 SHOW_STR
13511 IP_STR
13512 BGP_STR
13513 BGP_INSTANCE_HELP_STR
13514 BGP_AFI_HELP_STR
13515 BGP_SAFI_WITH_LABEL_HELP_STR
13516 "Display the entries for all address families\n"
13517 "Detailed information on TCP and BGP neighbor connections\n"
13518 "Neighbor to display information about\n"
13519 "Neighbor to display information about\n"
13520 "Neighbor on BGP configured interface\n"
13521 "Display the routes advertised to a BGP neighbor\n"
13522 "Display the received routes from neighbor\n"
13523 "Display the filtered routes received from neighbor\n"
13524 "Route-map to modify the attributes\n"
13525 "Name of the route map\n"
13526 JSON_STR
13527 "Increase table width for longer prefixes\n")
13528 {
13529 afi_t afi = AFI_IP6;
13530 safi_t safi = SAFI_UNICAST;
13531 char *rmap_name = NULL;
13532 char *peerstr = NULL;
13533 struct bgp *bgp = NULL;
13534 struct peer *peer;
13535 enum bgp_show_adj_route_type type = bgp_show_adj_route_advertised;
13536 int idx = 0;
13537 bool first = true;
13538 uint8_t show_flags = 0;
13539
13540 if (uj) {
13541 argc--;
13542 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13543 }
13544
13545 if (all) {
13546 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
13547 if (argv_find(argv, argc, "ipv4", &idx))
13548 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
13549
13550 if (argv_find(argv, argc, "ipv6", &idx))
13551 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
13552 }
13553
13554 if (wide)
13555 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
13556
13557 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13558 &bgp, uj);
13559 if (!idx)
13560 return CMD_WARNING;
13561
13562 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13563 argv_find(argv, argc, "neighbors", &idx);
13564 peerstr = argv[++idx]->arg;
13565
13566 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
13567 if (!peer)
13568 return CMD_WARNING;
13569
13570 if (argv_find(argv, argc, "advertised-routes", &idx))
13571 type = bgp_show_adj_route_advertised;
13572 else if (argv_find(argv, argc, "received-routes", &idx))
13573 type = bgp_show_adj_route_received;
13574 else if (argv_find(argv, argc, "filtered-routes", &idx))
13575 type = bgp_show_adj_route_filtered;
13576
13577 if (argv_find(argv, argc, "route-map", &idx))
13578 rmap_name = argv[++idx]->arg;
13579
13580 if (!all)
13581 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13582 show_flags);
13583 if (uj)
13584 vty_out(vty, "{\n");
13585
13586 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
13587 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
13588 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP) ? AFI_IP
13589 : AFI_IP6;
13590 FOREACH_SAFI (safi) {
13591 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
13592 continue;
13593
13594 if (uj) {
13595 if (first)
13596 first = false;
13597 else
13598 vty_out(vty, ",\n");
13599 vty_out(vty, "\"%s\":",
13600 get_afi_safi_str(afi, safi, true));
13601 } else
13602 vty_out(vty, "\nFor address family: %s\n",
13603 get_afi_safi_str(afi, safi, false));
13604
13605 peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13606 show_flags);
13607 }
13608 } else {
13609 FOREACH_AFI_SAFI (afi, safi) {
13610 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
13611 continue;
13612
13613 if (uj) {
13614 if (first)
13615 first = false;
13616 else
13617 vty_out(vty, ",\n");
13618 vty_out(vty, "\"%s\":",
13619 get_afi_safi_str(afi, safi, true));
13620 } else
13621 vty_out(vty, "\nFor address family: %s\n",
13622 get_afi_safi_str(afi, safi, false));
13623
13624 peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13625 show_flags);
13626 }
13627 }
13628 if (uj)
13629 vty_out(vty, "}\n");
13630
13631 return CMD_SUCCESS;
13632 }
13633
13634 DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
13635 show_ip_bgp_neighbor_received_prefix_filter_cmd,
13636 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
13637 SHOW_STR
13638 IP_STR
13639 BGP_STR
13640 "Address Family\n"
13641 "Address Family\n"
13642 "Address Family modifier\n"
13643 "Detailed information on TCP and BGP neighbor connections\n"
13644 "Neighbor to display information about\n"
13645 "Neighbor to display information about\n"
13646 "Neighbor on BGP configured interface\n"
13647 "Display information received from a BGP neighbor\n"
13648 "Display the prefixlist filter\n"
13649 JSON_STR)
13650 {
13651 afi_t afi = AFI_IP6;
13652 safi_t safi = SAFI_UNICAST;
13653 char *peerstr = NULL;
13654
13655 char name[BUFSIZ];
13656 union sockunion su;
13657 struct peer *peer;
13658 int count, ret;
13659
13660 int idx = 0;
13661
13662 /* show [ip] bgp */
13663 if (argv_find(argv, argc, "ip", &idx))
13664 afi = AFI_IP;
13665 /* [<ipv4|ipv6> [unicast]] */
13666 if (argv_find(argv, argc, "ipv4", &idx))
13667 afi = AFI_IP;
13668 if (argv_find(argv, argc, "ipv6", &idx))
13669 afi = AFI_IP6;
13670 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13671 argv_find(argv, argc, "neighbors", &idx);
13672 peerstr = argv[++idx]->arg;
13673
13674 bool uj = use_json(argc, argv);
13675
13676 ret = str2sockunion(peerstr, &su);
13677 if (ret < 0) {
13678 peer = peer_lookup_by_conf_if(NULL, peerstr);
13679 if (!peer) {
13680 if (uj)
13681 vty_out(vty, "{}\n");
13682 else
13683 vty_out(vty,
13684 "%% Malformed address or name: %s\n",
13685 peerstr);
13686 return CMD_WARNING;
13687 }
13688 } else {
13689 peer = peer_lookup(NULL, &su);
13690 if (!peer) {
13691 if (uj)
13692 vty_out(vty, "{}\n");
13693 else
13694 vty_out(vty, "No peer\n");
13695 return CMD_WARNING;
13696 }
13697 }
13698
13699 snprintf(name, sizeof(name), "%s.%d.%d", peer->host, afi, safi);
13700 count = prefix_bgp_show_prefix_list(NULL, afi, name, uj);
13701 if (count) {
13702 if (!uj)
13703 vty_out(vty, "Address Family: %s\n",
13704 get_afi_safi_str(afi, safi, false));
13705 prefix_bgp_show_prefix_list(vty, afi, name, uj);
13706 } else {
13707 if (uj)
13708 vty_out(vty, "{}\n");
13709 else
13710 vty_out(vty, "No functional output\n");
13711 }
13712
13713 return CMD_SUCCESS;
13714 }
13715
13716 static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer,
13717 afi_t afi, safi_t safi,
13718 enum bgp_show_type type, bool use_json)
13719 {
13720 uint8_t show_flags = 0;
13721
13722 if (use_json)
13723 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13724
13725 if (!peer || !peer->afc[afi][safi]) {
13726 if (use_json) {
13727 json_object *json_no = NULL;
13728 json_no = json_object_new_object();
13729 json_object_string_add(
13730 json_no, "warning",
13731 "No such neighbor or address family");
13732 vty_out(vty, "%s\n",
13733 json_object_to_json_string(json_no));
13734 json_object_free(json_no);
13735 } else
13736 vty_out(vty, "%% No such neighbor or address family\n");
13737 return CMD_WARNING;
13738 }
13739
13740 /* labeled-unicast routes live in the unicast table */
13741 if (safi == SAFI_LABELED_UNICAST)
13742 safi = SAFI_UNICAST;
13743
13744 return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, show_flags);
13745 }
13746
13747 DEFUN (show_ip_bgp_flowspec_routes_detailed,
13748 show_ip_bgp_flowspec_routes_detailed_cmd,
13749 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" flowspec] detail [json]",
13750 SHOW_STR
13751 IP_STR
13752 BGP_STR
13753 BGP_INSTANCE_HELP_STR
13754 BGP_AFI_HELP_STR
13755 "SAFI Flowspec\n"
13756 "Detailed information on flowspec entries\n"
13757 JSON_STR)
13758 {
13759 afi_t afi = AFI_IP;
13760 safi_t safi = SAFI_UNICAST;
13761 struct bgp *bgp = NULL;
13762 int idx = 0;
13763 bool uj = use_json(argc, argv);
13764 uint8_t show_flags = 0;
13765
13766 if (uj) {
13767 argc--;
13768 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13769 }
13770
13771 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13772 &bgp, uj);
13773 if (!idx)
13774 return CMD_WARNING;
13775
13776 return bgp_show(vty, bgp, afi, safi, bgp_show_type_detail, NULL,
13777 show_flags);
13778 }
13779
13780 DEFUN (show_ip_bgp_neighbor_routes,
13781 show_ip_bgp_neighbor_routes_cmd,
13782 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] neighbors <A.B.C.D|X:X::X:X|WORD> <flap-statistics|dampened-routes|routes> [json]",
13783 SHOW_STR
13784 IP_STR
13785 BGP_STR
13786 BGP_INSTANCE_HELP_STR
13787 BGP_AFI_HELP_STR
13788 BGP_SAFI_WITH_LABEL_HELP_STR
13789 "Detailed information on TCP and BGP neighbor connections\n"
13790 "Neighbor to display information about\n"
13791 "Neighbor to display information about\n"
13792 "Neighbor on BGP configured interface\n"
13793 "Display flap statistics of the routes learned from neighbor\n"
13794 "Display the dampened routes received from neighbor\n"
13795 "Display routes learned from neighbor\n"
13796 JSON_STR)
13797 {
13798 char *peerstr = NULL;
13799 struct bgp *bgp = NULL;
13800 afi_t afi = AFI_IP6;
13801 safi_t safi = SAFI_UNICAST;
13802 struct peer *peer;
13803 enum bgp_show_type sh_type = bgp_show_type_neighbor;
13804 int idx = 0;
13805 bool uj = use_json(argc, argv);
13806
13807 if (uj)
13808 argc--;
13809
13810 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13811 &bgp, uj);
13812 if (!idx)
13813 return CMD_WARNING;
13814
13815 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13816 argv_find(argv, argc, "neighbors", &idx);
13817 peerstr = argv[++idx]->arg;
13818
13819 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
13820 if (!peer)
13821 return CMD_WARNING;
13822
13823 if (argv_find(argv, argc, "flap-statistics", &idx))
13824 sh_type = bgp_show_type_flap_neighbor;
13825 else if (argv_find(argv, argc, "dampened-routes", &idx))
13826 sh_type = bgp_show_type_damp_neighbor;
13827 else if (argv_find(argv, argc, "routes", &idx))
13828 sh_type = bgp_show_type_neighbor;
13829
13830 return bgp_show_neighbor_route(vty, peer, afi, safi, sh_type, uj);
13831 }
13832
13833 struct bgp_table *bgp_distance_table[AFI_MAX][SAFI_MAX];
13834
13835 struct bgp_distance {
13836 /* Distance value for the IP source prefix. */
13837 uint8_t distance;
13838
13839 /* Name of the access-list to be matched. */
13840 char *access_list;
13841 };
13842
13843 DEFUN (show_bgp_afi_vpn_rd_route,
13844 show_bgp_afi_vpn_rd_route_cmd,
13845 "show bgp "BGP_AFI_CMD_STR" vpn rd ASN:NN_OR_IP-ADDRESS:NN <A.B.C.D/M|X:X::X:X/M> [json]",
13846 SHOW_STR
13847 BGP_STR
13848 BGP_AFI_HELP_STR
13849 "Address Family modifier\n"
13850 "Display information for a route distinguisher\n"
13851 "Route Distinguisher\n"
13852 "Network in the BGP routing table to display\n"
13853 "Network in the BGP routing table to display\n"
13854 JSON_STR)
13855 {
13856 int ret;
13857 struct prefix_rd prd;
13858 afi_t afi = AFI_MAX;
13859 int idx = 0;
13860
13861 if (!argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
13862 vty_out(vty, "%% Malformed Address Family\n");
13863 return CMD_WARNING;
13864 }
13865
13866 ret = str2prefix_rd(argv[5]->arg, &prd);
13867 if (!ret) {
13868 vty_out(vty, "%% Malformed Route Distinguisher\n");
13869 return CMD_WARNING;
13870 }
13871
13872 return bgp_show_route(vty, NULL, argv[6]->arg, afi, SAFI_MPLS_VPN, &prd,
13873 0, BGP_PATH_SHOW_ALL, use_json(argc, argv));
13874 }
13875
13876 static struct bgp_distance *bgp_distance_new(void)
13877 {
13878 return XCALLOC(MTYPE_BGP_DISTANCE, sizeof(struct bgp_distance));
13879 }
13880
13881 static void bgp_distance_free(struct bgp_distance *bdistance)
13882 {
13883 XFREE(MTYPE_BGP_DISTANCE, bdistance);
13884 }
13885
13886 int bgp_distance_set(uint8_t distance, const char *ip_str,
13887 const char *access_list_str, afi_t afi, safi_t safi,
13888 char *errmsg, size_t errmsg_len)
13889 {
13890 int ret;
13891 struct prefix p;
13892 struct bgp_dest *dest;
13893 struct bgp_distance *bdistance;
13894
13895 ret = str2prefix(ip_str, &p);
13896 if (ret == 0) {
13897 snprintf(errmsg, errmsg_len, "Malformed prefix\n");
13898 return CMD_WARNING_CONFIG_FAILED;
13899 }
13900
13901 /* Get BGP distance node. */
13902 dest = bgp_node_get(bgp_distance_table[afi][safi], &p);
13903 bdistance = bgp_dest_get_bgp_distance_info(dest);
13904 if (bdistance)
13905 bgp_dest_unlock_node(dest);
13906 else {
13907 bdistance = bgp_distance_new();
13908 bgp_dest_set_bgp_distance_info(dest, bdistance);
13909 }
13910
13911 /* Set distance value. */
13912 bdistance->distance = distance;
13913
13914 /* Reset access-list configuration. */
13915 XFREE(MTYPE_AS_LIST, bdistance->access_list);
13916 if (access_list_str)
13917 bdistance->access_list =
13918 XSTRDUP(MTYPE_AS_LIST, access_list_str);
13919
13920 return CMD_SUCCESS;
13921 }
13922
13923 int bgp_distance_unset(uint8_t distance, const char *ip_str,
13924 const char *access_list_str, afi_t afi, safi_t safi,
13925 char *errmsg, size_t errmsg_len)
13926 {
13927 int ret;
13928 struct prefix p;
13929 struct bgp_dest *dest;
13930 struct bgp_distance *bdistance;
13931
13932 ret = str2prefix(ip_str, &p);
13933 if (ret == 0) {
13934 snprintf(errmsg, errmsg_len, "Malformed prefix\n");
13935 return CMD_WARNING_CONFIG_FAILED;
13936 }
13937
13938 dest = bgp_node_lookup(bgp_distance_table[afi][safi], &p);
13939 if (!dest) {
13940 snprintf(errmsg, errmsg_len, "Can't find specified prefix\n");
13941 return CMD_WARNING_CONFIG_FAILED;
13942 }
13943
13944 bdistance = bgp_dest_get_bgp_distance_info(dest);
13945
13946 if (bdistance->distance != distance) {
13947 snprintf(errmsg, errmsg_len,
13948 "Distance does not match configured\n");
13949 return CMD_WARNING_CONFIG_FAILED;
13950 }
13951
13952 XFREE(MTYPE_AS_LIST, bdistance->access_list);
13953 bgp_distance_free(bdistance);
13954
13955 bgp_dest_set_bgp_path_info(dest, NULL);
13956 bgp_dest_unlock_node(dest);
13957 bgp_dest_unlock_node(dest);
13958
13959 return CMD_SUCCESS;
13960 }
13961
13962 /* Apply BGP information to distance method. */
13963 uint8_t bgp_distance_apply(const struct prefix *p, struct bgp_path_info *pinfo,
13964 afi_t afi, safi_t safi, struct bgp *bgp)
13965 {
13966 struct bgp_dest *dest;
13967 struct prefix q = {0};
13968 struct peer *peer;
13969 struct bgp_distance *bdistance;
13970 struct access_list *alist;
13971 struct bgp_static *bgp_static;
13972
13973 if (!bgp)
13974 return 0;
13975
13976 peer = pinfo->peer;
13977
13978 if (pinfo->attr->distance)
13979 return pinfo->attr->distance;
13980
13981 /* Check source address.
13982 * Note: for aggregate route, peer can have unspec af type.
13983 */
13984 if (pinfo->sub_type != BGP_ROUTE_AGGREGATE
13985 && !sockunion2hostprefix(&peer->su, &q))
13986 return 0;
13987
13988 dest = bgp_node_match(bgp_distance_table[afi][safi], &q);
13989 if (dest) {
13990 bdistance = bgp_dest_get_bgp_distance_info(dest);
13991 bgp_dest_unlock_node(dest);
13992
13993 if (bdistance->access_list) {
13994 alist = access_list_lookup(afi, bdistance->access_list);
13995 if (alist
13996 && access_list_apply(alist, p) == FILTER_PERMIT)
13997 return bdistance->distance;
13998 } else
13999 return bdistance->distance;
14000 }
14001
14002 /* Backdoor check. */
14003 dest = bgp_node_lookup(bgp->route[afi][safi], p);
14004 if (dest) {
14005 bgp_static = bgp_dest_get_bgp_static_info(dest);
14006 bgp_dest_unlock_node(dest);
14007
14008 if (bgp_static->backdoor) {
14009 if (bgp->distance_local[afi][safi])
14010 return bgp->distance_local[afi][safi];
14011 else
14012 return ZEBRA_IBGP_DISTANCE_DEFAULT;
14013 }
14014 }
14015
14016 if (peer->sort == BGP_PEER_EBGP) {
14017 if (bgp->distance_ebgp[afi][safi])
14018 return bgp->distance_ebgp[afi][safi];
14019 return ZEBRA_EBGP_DISTANCE_DEFAULT;
14020 } else if (peer->sort == BGP_PEER_IBGP) {
14021 if (bgp->distance_ibgp[afi][safi])
14022 return bgp->distance_ibgp[afi][safi];
14023 return ZEBRA_IBGP_DISTANCE_DEFAULT;
14024 } else {
14025 if (bgp->distance_local[afi][safi])
14026 return bgp->distance_local[afi][safi];
14027 return ZEBRA_IBGP_DISTANCE_DEFAULT;
14028 }
14029 }
14030
14031 /* If we enter `distance bgp (1-255) (1-255) (1-255)`,
14032 * we should tell ZEBRA update the routes for a specific
14033 * AFI/SAFI to reflect changes in RIB.
14034 */
14035 void bgp_announce_routes_distance_update(struct bgp *bgp, afi_t update_afi,
14036 safi_t update_safi)
14037 {
14038 afi_t afi;
14039 safi_t safi;
14040
14041 FOREACH_AFI_SAFI (afi, safi) {
14042 if (!bgp_fibupd_safi(safi))
14043 continue;
14044
14045 if (afi != update_afi && safi != update_safi)
14046 continue;
14047
14048 if (BGP_DEBUG(zebra, ZEBRA))
14049 zlog_debug(
14050 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
14051 __func__, afi, safi);
14052 bgp_zebra_announce_table(bgp, afi, safi);
14053 }
14054 }
14055
14056 DEFUN_YANG(bgp_distance, bgp_distance_cmd,
14057 "distance bgp (1-255) (1-255) (1-255)",
14058 "Define an administrative distance\n"
14059 "BGP distance\n"
14060 "Distance for routes external to the AS\n"
14061 "Distance for routes internal to the AS\n"
14062 "Distance for local routes\n")
14063 {
14064 int idx_number = 2;
14065 int idx_number_2 = 3;
14066 int idx_number_3 = 4;
14067 afi_t afi;
14068 safi_t safi;
14069 char xpath[XPATH_MAXLEN];
14070
14071 afi = bgp_node_afi(vty);
14072 safi = bgp_node_safi(vty);
14073
14074 snprintf(
14075 xpath, sizeof(xpath),
14076 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/external",
14077 yang_afi_safi_value2identity(afi, safi),
14078 bgp_afi_safi_get_container_str(afi, safi));
14079 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, argv[idx_number]->arg);
14080 snprintf(
14081 xpath, sizeof(xpath),
14082 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/internal",
14083 yang_afi_safi_value2identity(afi, safi),
14084 bgp_afi_safi_get_container_str(afi, safi));
14085 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY,
14086 argv[idx_number_2]->arg);
14087 snprintf(
14088 xpath, sizeof(xpath),
14089 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/local",
14090 yang_afi_safi_value2identity(afi, safi),
14091 bgp_afi_safi_get_container_str(afi, safi));
14092
14093 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY,
14094 argv[idx_number_3]->arg);
14095
14096 return nb_cli_apply_changes(vty, NULL);
14097 }
14098
14099 DEFUN_YANG(no_bgp_distance, no_bgp_distance_cmd,
14100 "no distance bgp [(1-255) (1-255) (1-255)]",
14101 NO_STR
14102 "Define an administrative distance\n"
14103 "BGP distance\n"
14104 "Distance for routes external to the AS\n"
14105 "Distance for routes internal to the AS\n"
14106 "Distance for local routes\n")
14107 {
14108 afi_t afi;
14109 safi_t safi;
14110 char xpath[XPATH_MAXLEN];
14111
14112 afi = bgp_node_afi(vty);
14113 safi = bgp_node_safi(vty);
14114
14115 snprintf(
14116 xpath, sizeof(xpath),
14117 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/external",
14118 yang_afi_safi_value2identity(afi, safi),
14119 bgp_afi_safi_get_container_str(afi, safi));
14120 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, NULL);
14121 snprintf(
14122 xpath, sizeof(xpath),
14123 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/internal",
14124 yang_afi_safi_value2identity(afi, safi),
14125 bgp_afi_safi_get_container_str(afi, safi));
14126 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, NULL);
14127 snprintf(
14128 xpath, sizeof(xpath),
14129 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/local",
14130 yang_afi_safi_value2identity(afi, safi),
14131 bgp_afi_safi_get_container_str(afi, safi));
14132
14133 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, NULL);
14134
14135 return nb_cli_apply_changes(vty, NULL);
14136 }
14137
14138 void cli_show_bgp_global_afi_safi_admin_distance_config(struct vty *vty,
14139 struct lyd_node *dnode,
14140 bool show_defaults)
14141 {
14142 uint8_t distance_ebgp, distance_ibgp, distance_local;
14143
14144 distance_ebgp = yang_dnode_get_uint8(dnode, "./external");
14145 distance_ibgp = yang_dnode_get_uint8(dnode, "./internal");
14146 distance_local = yang_dnode_get_uint8(dnode, "./local");
14147
14148 vty_out(vty, " distance bgp %d %d %d\n", distance_ebgp, distance_ibgp,
14149 distance_local);
14150 }
14151
14152 DEFPY_YANG(bgp_distance_source,
14153 bgp_distance_source_cmd,
14154 "[no] distance (1-255) <A.B.C.D/M | X:X::X:X/M>$prefix [WORD$acl]",
14155 NO_STR
14156 "Define an administrative distance\n"
14157 "Distance value\n"
14158 "IPv4 source prefix\n"
14159 "IPv6 source prefix\n"
14160 "Access list name\n")
14161 {
14162 afi_t afi;
14163 safi_t safi;
14164 char xpath[XPATH_MAXLEN];
14165
14166 afi = bgp_node_afi(vty);
14167 safi = bgp_node_safi(vty);
14168
14169 if (!no) {
14170 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
14171 nb_cli_enqueue_change(vty, "./distance", NB_OP_MODIFY,
14172 distance_str);
14173 if (acl)
14174 nb_cli_enqueue_change(vty,
14175 "./access-list-policy-export",
14176 NB_OP_CREATE, acl);
14177 else
14178 nb_cli_enqueue_change(vty,
14179 "./access-list-policy-export",
14180 NB_OP_DESTROY, NULL);
14181 } else {
14182 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
14183 }
14184
14185 snprintf(
14186 xpath, sizeof(xpath),
14187 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance-route[prefix='%s']",
14188 yang_afi_safi_value2identity(afi, safi),
14189 bgp_afi_safi_get_container_str(afi, safi), prefix_str);
14190
14191 return nb_cli_apply_changes(vty, xpath);
14192 }
14193
14194 void cli_show_bgp_global_afi_safi_unicast_admin_distance_route(
14195 struct vty *vty, struct lyd_node *dnode, bool show_defaults)
14196 {
14197 vty_out(vty, " distance %d %s %s\n",
14198 yang_dnode_get_uint8(dnode, "./distance"),
14199 yang_dnode_get_string(dnode, "./prefix"),
14200 (yang_dnode_exists(dnode, "./access-list-policy-export"))
14201 ? yang_dnode_get_string(dnode,
14202 "./access-list-policy-export")
14203 : "");
14204 }
14205
14206 DEFPY_YANG(
14207 bgp_dampening, bgp_dampening_cmd,
14208 "[no] bgp dampening [(1-45)$halflife [(1-20000)$reuse (1-20000)$suppress (1-255)$max_suppress]]",
14209 NO_STR
14210 "BGP Specific commands\n"
14211 "Enable route-flap dampening\n"
14212 "Half-life time for the penalty\n"
14213 "Value to start reusing a route\n"
14214 "Value to start suppressing a route\n"
14215 "Maximum duration to suppress a stable route\n")
14216 {
14217 afi_t afi;
14218 safi_t safi;
14219 char xpath[XPATH_MAXLEN];
14220
14221 afi = bgp_node_afi(vty);
14222 safi = bgp_node_safi(vty);
14223
14224 if (!no) {
14225 nb_cli_enqueue_change(vty, "./enable", NB_OP_MODIFY, "true");
14226 if (argc == 6) {
14227 nb_cli_enqueue_change(vty, "./reach-decay",
14228 NB_OP_MODIFY, halflife_str);
14229 nb_cli_enqueue_change(vty, "./reuse-above",
14230 NB_OP_MODIFY, reuse_str);
14231 nb_cli_enqueue_change(vty, "./suppress-above",
14232 NB_OP_MODIFY, suppress_str);
14233 nb_cli_enqueue_change(vty, "./unreach-decay",
14234 NB_OP_MODIFY, max_suppress_str);
14235 } if (argc == 3) {
14236 nb_cli_enqueue_change(vty, "./reach-decay",
14237 NB_OP_MODIFY, halflife_str);
14238 }
14239 } else {
14240 nb_cli_enqueue_change(vty, "./enable", NB_OP_MODIFY, "false");
14241 }
14242
14243 snprintf(
14244 xpath, sizeof(xpath),
14245 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/route-flap-dampening",
14246 yang_afi_safi_value2identity(afi, safi),
14247 bgp_afi_safi_get_container_str(afi, safi));
14248
14249 return nb_cli_apply_changes(vty, xpath);
14250 }
14251
14252 void cli_show_bgp_global_afi_safi_route_flap_dampening(struct vty *vty,
14253 struct lyd_node *dnode,
14254 bool show_defaults)
14255 {
14256 if (!yang_dnode_get_bool(dnode, "./enable"))
14257 return;
14258
14259 int half = DEFAULT_HALF_LIFE * 60;
14260 int reuse = DEFAULT_REUSE;
14261 int suppress = DEFAULT_SUPPRESS;
14262 int max;
14263
14264 half = yang_dnode_get_uint8(dnode, "../reach-decay");
14265 reuse = yang_dnode_get_uint16(dnode, "../reuse-above");
14266 suppress = yang_dnode_get_uint16(dnode, "../suppress-above");
14267 max = yang_dnode_get_uint8(dnode, "../unreach-decay");
14268
14269 if (half == DEFAULT_HALF_LIFE * 60 && reuse == DEFAULT_REUSE
14270 && suppress == DEFAULT_SUPPRESS && max == half * 4)
14271 vty_out(vty, " bgp dampening\n");
14272 else if (half != DEFAULT_HALF_LIFE * 60 && reuse == DEFAULT_REUSE
14273 && suppress == DEFAULT_SUPPRESS && max == half * 4)
14274 vty_out(vty, " bgp dampening %u\n", half);
14275 else
14276 vty_out(vty, " bgp dampening %u %d %d %d\n", half, reuse,
14277 suppress, max);
14278 }
14279
14280 /* Display specified route of BGP table. */
14281 static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
14282 const char *ip_str, afi_t afi, safi_t safi,
14283 struct prefix_rd *prd, int prefix_check)
14284 {
14285 int ret;
14286 struct prefix match;
14287 struct bgp_dest *dest;
14288 struct bgp_dest *rm;
14289 struct bgp_path_info *pi;
14290 struct bgp_path_info *pi_temp;
14291 struct bgp *bgp;
14292 struct bgp_table *table;
14293
14294 /* BGP structure lookup. */
14295 if (view_name) {
14296 bgp = bgp_lookup_by_name(view_name);
14297 if (bgp == NULL) {
14298 vty_out(vty, "%% Can't find BGP instance %s\n",
14299 view_name);
14300 return CMD_WARNING;
14301 }
14302 } else {
14303 bgp = bgp_get_default();
14304 if (bgp == NULL) {
14305 vty_out(vty, "%% No BGP process is configured\n");
14306 return CMD_WARNING;
14307 }
14308 }
14309
14310 /* Check IP address argument. */
14311 ret = str2prefix(ip_str, &match);
14312 if (!ret) {
14313 vty_out(vty, "%% address is malformed\n");
14314 return CMD_WARNING;
14315 }
14316
14317 match.family = afi2family(afi);
14318
14319 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
14320 || (safi == SAFI_EVPN)) {
14321 for (dest = bgp_table_top(bgp->rib[AFI_IP][safi]); dest;
14322 dest = bgp_route_next(dest)) {
14323 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
14324
14325 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
14326 continue;
14327 table = bgp_dest_get_bgp_table_info(dest);
14328 if (!table)
14329 continue;
14330 if ((rm = bgp_node_match(table, &match)) == NULL)
14331 continue;
14332
14333 const struct prefix *rm_p = bgp_dest_get_prefix(dest);
14334
14335 if (!prefix_check
14336 || rm_p->prefixlen == match.prefixlen) {
14337 pi = bgp_dest_get_bgp_path_info(rm);
14338 while (pi) {
14339 if (pi->extra && pi->extra->damp_info) {
14340 pi_temp = pi->next;
14341 bgp_damp_info_free(
14342 &pi->extra->damp_info,
14343 &bgp->damp[afi][safi],
14344 1, afi, safi);
14345 pi = pi_temp;
14346 } else
14347 pi = pi->next;
14348 }
14349 }
14350
14351 bgp_dest_unlock_node(rm);
14352 }
14353 } else {
14354 if ((dest = bgp_node_match(bgp->rib[afi][safi], &match))
14355 != NULL) {
14356 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
14357
14358 if (!prefix_check
14359 || dest_p->prefixlen == match.prefixlen) {
14360 pi = bgp_dest_get_bgp_path_info(dest);
14361 while (pi) {
14362 if (pi->extra && pi->extra->damp_info) {
14363 pi_temp = pi->next;
14364 struct bgp_damp_info *bdi =
14365 pi->extra->damp_info;
14366 if (bdi->lastrecord
14367 == BGP_RECORD_UPDATE) {
14368 bgp_aggregate_increment(
14369 bgp,
14370 &bdi->dest->p,
14371 bdi->path,
14372 bdi->afi,
14373 bdi->safi);
14374 bgp_process(bgp,
14375 bdi->dest,
14376 bdi->afi,
14377 bdi->safi);
14378 }
14379 bgp_damp_info_free(
14380 &pi->extra->damp_info,
14381 &bgp->damp[afi][safi],
14382 1, afi, safi);
14383 pi = pi_temp;
14384 } else
14385 pi = pi->next;
14386 }
14387 }
14388
14389 bgp_dest_unlock_node(dest);
14390 }
14391 }
14392
14393 return CMD_SUCCESS;
14394 }
14395
14396 DEFUN (clear_ip_bgp_dampening,
14397 clear_ip_bgp_dampening_cmd,
14398 "clear ip bgp dampening",
14399 CLEAR_STR
14400 IP_STR
14401 BGP_STR
14402 "Clear route flap dampening information\n")
14403 {
14404 VTY_DECLVAR_CONTEXT(bgp, bgp);
14405 bgp_damp_info_clean(bgp, &bgp->damp[AFI_IP][SAFI_UNICAST], AFI_IP,
14406 SAFI_UNICAST);
14407 return CMD_SUCCESS;
14408 }
14409
14410 DEFUN (clear_ip_bgp_dampening_prefix,
14411 clear_ip_bgp_dampening_prefix_cmd,
14412 "clear ip bgp dampening A.B.C.D/M",
14413 CLEAR_STR
14414 IP_STR
14415 BGP_STR
14416 "Clear route flap dampening information\n"
14417 "IPv4 prefix\n")
14418 {
14419 int idx_ipv4_prefixlen = 4;
14420 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4_prefixlen]->arg,
14421 AFI_IP, SAFI_UNICAST, NULL, 1);
14422 }
14423
14424 DEFUN (clear_ip_bgp_dampening_address,
14425 clear_ip_bgp_dampening_address_cmd,
14426 "clear ip bgp dampening A.B.C.D",
14427 CLEAR_STR
14428 IP_STR
14429 BGP_STR
14430 "Clear route flap dampening information\n"
14431 "Network to clear damping information\n")
14432 {
14433 int idx_ipv4 = 4;
14434 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4]->arg, AFI_IP,
14435 SAFI_UNICAST, NULL, 0);
14436 }
14437
14438 DEFUN (clear_ip_bgp_dampening_address_mask,
14439 clear_ip_bgp_dampening_address_mask_cmd,
14440 "clear ip bgp dampening A.B.C.D A.B.C.D",
14441 CLEAR_STR
14442 IP_STR
14443 BGP_STR
14444 "Clear route flap dampening information\n"
14445 "Network to clear damping information\n"
14446 "Network mask\n")
14447 {
14448 int idx_ipv4 = 4;
14449 int idx_ipv4_2 = 5;
14450 int ret;
14451 char prefix_str[BUFSIZ];
14452
14453 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
14454 prefix_str, sizeof(prefix_str));
14455 if (!ret) {
14456 vty_out(vty, "%% Inconsistent address and mask\n");
14457 return CMD_WARNING;
14458 }
14459
14460 return bgp_clear_damp_route(vty, NULL, prefix_str, AFI_IP, SAFI_UNICAST,
14461 NULL, 0);
14462 }
14463
14464 static void show_bgp_peerhash_entry(struct hash_bucket *bucket, void *arg)
14465 {
14466 struct vty *vty = arg;
14467 struct peer *peer = bucket->data;
14468 char buf[SU_ADDRSTRLEN];
14469
14470 vty_out(vty, "\tPeer: %s %s\n", peer->host,
14471 sockunion2str(&peer->su, buf, sizeof(buf)));
14472 }
14473
14474 DEFUN (show_bgp_listeners,
14475 show_bgp_listeners_cmd,
14476 "show bgp listeners",
14477 SHOW_STR
14478 BGP_STR
14479 "Display Listen Sockets and who created them\n")
14480 {
14481 bgp_dump_listener_info(vty);
14482
14483 return CMD_SUCCESS;
14484 }
14485
14486 DEFUN (show_bgp_peerhash,
14487 show_bgp_peerhash_cmd,
14488 "show bgp peerhash",
14489 SHOW_STR
14490 BGP_STR
14491 "Display information about the BGP peerhash\n")
14492 {
14493 struct list *instances = bm->bgp;
14494 struct listnode *node;
14495 struct bgp *bgp;
14496
14497 for (ALL_LIST_ELEMENTS_RO(instances, node, bgp)) {
14498 vty_out(vty, "BGP: %s\n", bgp->name);
14499 hash_iterate(bgp->peerhash, show_bgp_peerhash_entry,
14500 vty);
14501 }
14502
14503 return CMD_SUCCESS;
14504 }
14505
14506 /* also used for encap safi */
14507 static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
14508 afi_t afi, safi_t safi)
14509 {
14510 struct bgp_dest *pdest;
14511 struct bgp_dest *dest;
14512 struct bgp_table *table;
14513 const struct prefix *p;
14514 const struct prefix_rd *prd;
14515 struct bgp_static *bgp_static;
14516 mpls_label_t label;
14517 char rdbuf[RD_ADDRSTRLEN];
14518
14519 /* Network configuration. */
14520 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
14521 pdest = bgp_route_next(pdest)) {
14522 table = bgp_dest_get_bgp_table_info(pdest);
14523 if (!table)
14524 continue;
14525
14526 for (dest = bgp_table_top(table); dest;
14527 dest = bgp_route_next(dest)) {
14528 bgp_static = bgp_dest_get_bgp_static_info(dest);
14529 if (bgp_static == NULL)
14530 continue;
14531
14532 p = bgp_dest_get_prefix(dest);
14533 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
14534 pdest);
14535
14536 /* "network" configuration display. */
14537 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
14538 label = decode_label(&bgp_static->label);
14539
14540 vty_out(vty, " network %pFX rd %s", p, rdbuf);
14541 if (safi == SAFI_MPLS_VPN)
14542 vty_out(vty, " label %u", label);
14543
14544 if (bgp_static->rmap.name)
14545 vty_out(vty, " route-map %s",
14546 bgp_static->rmap.name);
14547
14548 if (bgp_static->backdoor)
14549 vty_out(vty, " backdoor");
14550
14551 vty_out(vty, "\n");
14552 }
14553 }
14554 }
14555
14556 static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
14557 afi_t afi, safi_t safi)
14558 {
14559 struct bgp_dest *pdest;
14560 struct bgp_dest *dest;
14561 struct bgp_table *table;
14562 const struct prefix *p;
14563 const struct prefix_rd *prd;
14564 struct bgp_static *bgp_static;
14565 char buf[PREFIX_STRLEN * 2];
14566 char buf2[SU_ADDRSTRLEN];
14567 char rdbuf[RD_ADDRSTRLEN];
14568 char esi_buf[ESI_BYTES];
14569
14570 /* Network configuration. */
14571 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
14572 pdest = bgp_route_next(pdest)) {
14573 table = bgp_dest_get_bgp_table_info(pdest);
14574 if (!table)
14575 continue;
14576
14577 for (dest = bgp_table_top(table); dest;
14578 dest = bgp_route_next(dest)) {
14579 bgp_static = bgp_dest_get_bgp_static_info(dest);
14580 if (bgp_static == NULL)
14581 continue;
14582
14583 char *macrouter = NULL;
14584
14585 if (bgp_static->router_mac)
14586 macrouter = prefix_mac2str(
14587 bgp_static->router_mac, NULL, 0);
14588 if (bgp_static->eth_s_id)
14589 esi_to_str(bgp_static->eth_s_id,
14590 esi_buf, sizeof(esi_buf));
14591 p = bgp_dest_get_prefix(dest);
14592 prd = (struct prefix_rd *)bgp_dest_get_prefix(pdest);
14593
14594 /* "network" configuration display. */
14595 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
14596 if (p->u.prefix_evpn.route_type == 5) {
14597 char local_buf[PREFIX_STRLEN];
14598 uint8_t family = is_evpn_prefix_ipaddr_v4((
14599 struct prefix_evpn *)p)
14600 ? AF_INET
14601 : AF_INET6;
14602 inet_ntop(family,
14603 &p->u.prefix_evpn.prefix_addr.ip.ip.addr,
14604 local_buf, PREFIX_STRLEN);
14605 snprintf(buf, sizeof(buf), "%s/%u", local_buf,
14606 p->u.prefix_evpn.prefix_addr
14607 .ip_prefix_length);
14608 } else {
14609 prefix2str(p, buf, sizeof(buf));
14610 }
14611
14612 if (bgp_static->gatewayIp.family == AF_INET
14613 || bgp_static->gatewayIp.family == AF_INET6)
14614 inet_ntop(bgp_static->gatewayIp.family,
14615 &bgp_static->gatewayIp.u.prefix, buf2,
14616 sizeof(buf2));
14617 vty_out(vty,
14618 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
14619 buf, rdbuf,
14620 p->u.prefix_evpn.prefix_addr.eth_tag,
14621 decode_label(&bgp_static->label), esi_buf, buf2,
14622 macrouter);
14623
14624 XFREE(MTYPE_TMP, macrouter);
14625 }
14626 }
14627 }
14628
14629 /* Configuration of static route announcement and aggregate
14630 information. */
14631 void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
14632 safi_t safi)
14633 {
14634 struct bgp_dest *dest;
14635 const struct prefix *p;
14636 struct bgp_static *bgp_static;
14637 struct bgp_aggregate *bgp_aggregate;
14638
14639 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) {
14640 bgp_config_write_network_vpn(vty, bgp, afi, safi);
14641 return;
14642 }
14643
14644 if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
14645 bgp_config_write_network_evpn(vty, bgp, afi, safi);
14646 return;
14647 }
14648
14649 /* Network configuration. */
14650 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
14651 dest = bgp_route_next(dest)) {
14652 bgp_static = bgp_dest_get_bgp_static_info(dest);
14653 if (bgp_static == NULL)
14654 continue;
14655
14656 p = bgp_dest_get_prefix(dest);
14657
14658 vty_out(vty, " network %pFX", p);
14659
14660 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX)
14661 vty_out(vty, " label-index %u",
14662 bgp_static->label_index);
14663
14664 if (bgp_static->rmap.name)
14665 vty_out(vty, " route-map %s", bgp_static->rmap.name);
14666
14667 if (bgp_static->backdoor)
14668 vty_out(vty, " backdoor");
14669
14670 vty_out(vty, "\n");
14671 }
14672
14673 /* Aggregate-address configuration. */
14674 for (dest = bgp_table_top(bgp->aggregate[afi][safi]); dest;
14675 dest = bgp_route_next(dest)) {
14676 bgp_aggregate = bgp_dest_get_bgp_aggregate_info(dest);
14677 if (bgp_aggregate == NULL)
14678 continue;
14679
14680 p = bgp_dest_get_prefix(dest);
14681
14682 vty_out(vty, " aggregate-address %pFX", p);
14683
14684 if (bgp_aggregate->as_set)
14685 vty_out(vty, " as-set");
14686
14687 if (bgp_aggregate->summary_only)
14688 vty_out(vty, " summary-only");
14689
14690 if (bgp_aggregate->rmap.name)
14691 vty_out(vty, " route-map %s", bgp_aggregate->rmap.name);
14692
14693 if (bgp_aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
14694 vty_out(vty, " origin %s",
14695 bgp_origin2str(bgp_aggregate->origin));
14696
14697 if (bgp_aggregate->match_med)
14698 vty_out(vty, " matching-MED-only");
14699
14700 if (bgp_aggregate->suppress_map_name)
14701 vty_out(vty, " suppress-map %s",
14702 bgp_aggregate->suppress_map_name);
14703
14704 vty_out(vty, "\n");
14705 }
14706 }
14707
14708 void bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
14709 safi_t safi)
14710 {
14711 struct bgp_dest *dest;
14712 struct bgp_distance *bdistance;
14713
14714 /* Distance configuration. */
14715 if (bgp->distance_ebgp[afi][safi] && bgp->distance_ibgp[afi][safi]
14716 && bgp->distance_local[afi][safi]
14717 && (bgp->distance_ebgp[afi][safi] != ZEBRA_EBGP_DISTANCE_DEFAULT
14718 || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT
14719 || bgp->distance_local[afi][safi]
14720 != ZEBRA_IBGP_DISTANCE_DEFAULT)) {
14721 vty_out(vty, " distance bgp %d %d %d\n",
14722 bgp->distance_ebgp[afi][safi],
14723 bgp->distance_ibgp[afi][safi],
14724 bgp->distance_local[afi][safi]);
14725 }
14726
14727 for (dest = bgp_table_top(bgp_distance_table[afi][safi]); dest;
14728 dest = bgp_route_next(dest)) {
14729 bdistance = bgp_dest_get_bgp_distance_info(dest);
14730 if (bdistance != NULL)
14731 vty_out(vty, " distance %d %pBD %s\n",
14732 bdistance->distance, dest,
14733 bdistance->access_list ? bdistance->access_list
14734 : "");
14735 }
14736 }
14737
14738 /* Allocate routing table structure and install commands. */
14739 void bgp_route_init(void)
14740 {
14741 afi_t afi;
14742 safi_t safi;
14743
14744 /* Init BGP distance table. */
14745 FOREACH_AFI_SAFI (afi, safi)
14746 bgp_distance_table[afi][safi] = bgp_table_init(NULL, afi, safi);
14747
14748 /* IPv4 BGP commands. */
14749 install_element(BGP_NODE, &bgp_table_map_cmd);
14750 install_element(BGP_NODE, &bgp_network_cmd);
14751 install_element(BGP_NODE, &no_bgp_table_map_cmd);
14752
14753 install_element(BGP_NODE, &aggregate_addressv4_cmd);
14754
14755 /* IPv4 unicast configuration. */
14756 install_element(BGP_IPV4_NODE, &bgp_table_map_cmd);
14757 install_element(BGP_IPV4_NODE, &bgp_network_cmd);
14758 install_element(BGP_IPV4_NODE, &no_bgp_table_map_cmd);
14759
14760 install_element(BGP_IPV4_NODE, &aggregate_addressv4_cmd);
14761
14762 /* IPv4 multicast configuration. */
14763 install_element(BGP_IPV4M_NODE, &bgp_table_map_cmd);
14764 install_element(BGP_IPV4M_NODE, &bgp_network_cmd);
14765 install_element(BGP_IPV4M_NODE, &no_bgp_table_map_cmd);
14766 install_element(BGP_IPV4M_NODE, &aggregate_addressv4_cmd);
14767
14768 /* IPv4 labeled-unicast configuration. */
14769 install_element(BGP_IPV4L_NODE, &bgp_network_cmd);
14770 install_element(BGP_IPV4L_NODE, &aggregate_addressv4_cmd);
14771
14772 install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd);
14773 install_element(VIEW_NODE, &show_ip_bgp_cmd);
14774 install_element(VIEW_NODE, &show_ip_bgp_afi_safi_statistics_cmd);
14775 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_statistics_cmd);
14776 install_element(VIEW_NODE, &show_ip_bgp_json_cmd);
14777 install_element(VIEW_NODE, &show_ip_bgp_route_cmd);
14778 install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd);
14779 install_element(VIEW_NODE, &show_ip_bgp_statistics_all_cmd);
14780
14781 install_element(VIEW_NODE,
14782 &show_ip_bgp_instance_neighbor_advertised_route_cmd);
14783 install_element(VIEW_NODE,
14784 &show_ip_bgp_instance_neighbor_bestpath_route_cmd);
14785 install_element(VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd);
14786 install_element(VIEW_NODE,
14787 &show_ip_bgp_neighbor_received_prefix_filter_cmd);
14788 #ifdef KEEP_OLD_VPN_COMMANDS
14789 install_element(VIEW_NODE, &show_ip_bgp_vpn_all_route_prefix_cmd);
14790 #endif /* KEEP_OLD_VPN_COMMANDS */
14791 install_element(VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd);
14792 install_element(VIEW_NODE,
14793 &show_bgp_l2vpn_evpn_route_prefix_cmd);
14794
14795 /* BGP dampening clear commands */
14796 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
14797 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_prefix_cmd);
14798
14799 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd);
14800 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd);
14801
14802 /* prefix count */
14803 install_element(ENABLE_NODE,
14804 &show_ip_bgp_instance_neighbor_prefix_counts_cmd);
14805 #ifdef KEEP_OLD_VPN_COMMANDS
14806 install_element(ENABLE_NODE,
14807 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd);
14808 #endif /* KEEP_OLD_VPN_COMMANDS */
14809
14810 /* New config IPv6 BGP commands. */
14811 install_element(BGP_IPV6_NODE, &bgp_table_map_cmd);
14812 install_element(BGP_IPV6_NODE, &ipv6_bgp_network_cmd);
14813 install_element(BGP_IPV6_NODE, &no_bgp_table_map_cmd);
14814
14815 install_element(BGP_IPV6_NODE, &aggregate_addressv6_cmd);
14816
14817 install_element(BGP_IPV6M_NODE, &ipv6_bgp_network_cmd);
14818
14819 /* IPv6 labeled unicast address family. */
14820 install_element(BGP_IPV6L_NODE, &ipv6_bgp_network_cmd);
14821 install_element(BGP_IPV6L_NODE, &aggregate_addressv6_cmd);
14822
14823 install_element(BGP_NODE, &bgp_distance_cmd);
14824 install_element(BGP_NODE, &no_bgp_distance_cmd);
14825 install_element(BGP_NODE, &bgp_distance_source_cmd);
14826 install_element(BGP_IPV4_NODE, &bgp_distance_cmd);
14827 install_element(BGP_IPV4_NODE, &no_bgp_distance_cmd);
14828 install_element(BGP_IPV4_NODE, &bgp_distance_source_cmd);
14829 install_element(BGP_IPV4M_NODE, &bgp_distance_cmd);
14830 install_element(BGP_IPV4M_NODE, &no_bgp_distance_cmd);
14831 install_element(BGP_IPV4M_NODE, &bgp_distance_source_cmd);
14832 install_element(BGP_IPV6_NODE, &bgp_distance_cmd);
14833 install_element(BGP_IPV6_NODE, &no_bgp_distance_cmd);
14834 install_element(BGP_IPV6_NODE, &bgp_distance_source_cmd);
14835 install_element(BGP_IPV6M_NODE, &bgp_distance_cmd);
14836 install_element(BGP_IPV6M_NODE, &no_bgp_distance_cmd);
14837 install_element(BGP_IPV6M_NODE, &bgp_distance_source_cmd);
14838
14839 /* BGP dampening */
14840 install_element(BGP_NODE, &bgp_dampening_cmd);
14841 install_element(BGP_IPV4_NODE, &bgp_dampening_cmd);
14842 install_element(BGP_IPV4M_NODE, &bgp_dampening_cmd);
14843 install_element(BGP_IPV4L_NODE, &bgp_dampening_cmd);
14844 install_element(BGP_IPV6_NODE, &bgp_dampening_cmd);
14845 install_element(BGP_IPV6M_NODE, &bgp_dampening_cmd);
14846 install_element(BGP_IPV6L_NODE, &bgp_dampening_cmd);
14847
14848 /* Large Communities */
14849 install_element(VIEW_NODE, &show_ip_bgp_large_community_list_cmd);
14850 install_element(VIEW_NODE, &show_ip_bgp_large_community_cmd);
14851
14852 /* show bgp ipv4 flowspec detailed */
14853 install_element(VIEW_NODE, &show_ip_bgp_flowspec_routes_detailed_cmd);
14854
14855 install_element(VIEW_NODE, &show_bgp_listeners_cmd);
14856 install_element(VIEW_NODE, &show_bgp_peerhash_cmd);
14857 }
14858
14859 void bgp_route_finish(void)
14860 {
14861 afi_t afi;
14862 safi_t safi;
14863
14864 FOREACH_AFI_SAFI (afi, safi) {
14865 bgp_table_unlock(bgp_distance_table[afi][safi]);
14866 bgp_distance_table[afi][safi] = NULL;
14867 }
14868 }