]> git.proxmox.com Git - mirror_frr.git/blob - bgpd/bgp_route.c
Merge pull request #8942 from ton31337/fix/cleanups_2
[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 "frrstr.h"
27 #include "prefix.h"
28 #include "linklist.h"
29 #include "memory.h"
30 #include "command.h"
31 #include "stream.h"
32 #include "filter.h"
33 #include "log.h"
34 #include "routemap.h"
35 #include "buffer.h"
36 #include "sockunion.h"
37 #include "plist.h"
38 #include "thread.h"
39 #include "workqueue.h"
40 #include "queue.h"
41 #include "memory.h"
42 #include "srv6.h"
43 #include "lib/json.h"
44 #include "lib_errors.h"
45 #include "zclient.h"
46 #include "bgpd/bgpd.h"
47 #include "bgpd/bgp_table.h"
48 #include "bgpd/bgp_route.h"
49 #include "bgpd/bgp_attr.h"
50 #include "bgpd/bgp_debug.h"
51 #include "bgpd/bgp_errors.h"
52 #include "bgpd/bgp_aspath.h"
53 #include "bgpd/bgp_regex.h"
54 #include "bgpd/bgp_community.h"
55 #include "bgpd/bgp_community_alias.h"
56 #include "bgpd/bgp_ecommunity.h"
57 #include "bgpd/bgp_lcommunity.h"
58 #include "bgpd/bgp_clist.h"
59 #include "bgpd/bgp_packet.h"
60 #include "bgpd/bgp_filter.h"
61 #include "bgpd/bgp_fsm.h"
62 #include "bgpd/bgp_mplsvpn.h"
63 #include "bgpd/bgp_nexthop.h"
64 #include "bgpd/bgp_damp.h"
65 #include "bgpd/bgp_advertise.h"
66 #include "bgpd/bgp_zebra.h"
67 #include "bgpd/bgp_vty.h"
68 #include "bgpd/bgp_mpath.h"
69 #include "bgpd/bgp_nht.h"
70 #include "bgpd/bgp_updgrp.h"
71 #include "bgpd/bgp_label.h"
72 #include "bgpd/bgp_addpath.h"
73 #include "bgpd/bgp_mac.h"
74 #include "bgpd/bgp_network.h"
75 #include "bgpd/bgp_trace.h"
76 #include "bgpd/bgp_rpki.h"
77
78 #ifdef ENABLE_BGP_VNC
79 #include "bgpd/rfapi/rfapi_backend.h"
80 #include "bgpd/rfapi/vnc_import_bgp.h"
81 #include "bgpd/rfapi/vnc_export_bgp.h"
82 #endif
83 #include "bgpd/bgp_encap_types.h"
84 #include "bgpd/bgp_encap_tlv.h"
85 #include "bgpd/bgp_evpn.h"
86 #include "bgpd/bgp_evpn_mh.h"
87 #include "bgpd/bgp_evpn_vty.h"
88 #include "bgpd/bgp_flowspec.h"
89 #include "bgpd/bgp_flowspec_util.h"
90 #include "bgpd/bgp_pbr.h"
91 #include "northbound.h"
92 #include "northbound_cli.h"
93 #include "bgpd/bgp_nb.h"
94
95 #ifndef VTYSH_EXTRACT_PL
96 #include "bgpd/bgp_route_clippy.c"
97 #endif
98
99 DEFINE_HOOK(bgp_snmp_update_stats,
100 (struct bgp_node *rn, struct bgp_path_info *pi, bool added),
101 (rn, pi, added));
102
103 DEFINE_HOOK(bgp_rpki_prefix_status,
104 (struct peer *peer, struct attr *attr,
105 const struct prefix *prefix),
106 (peer, attr, prefix));
107
108 /* Extern from bgp_dump.c */
109 extern const char *bgp_origin_str[];
110 extern const char *bgp_origin_long_str[];
111
112 /* PMSI strings. */
113 #define PMSI_TNLTYPE_STR_NO_INFO "No info"
114 #define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
115 static const struct message bgp_pmsi_tnltype_str[] = {
116 {PMSI_TNLTYPE_NO_INFO, PMSI_TNLTYPE_STR_NO_INFO},
117 {PMSI_TNLTYPE_RSVP_TE_P2MP, "RSVP-TE P2MP"},
118 {PMSI_TNLTYPE_MLDP_P2MP, "mLDP P2MP"},
119 {PMSI_TNLTYPE_PIM_SSM, "PIM-SSM"},
120 {PMSI_TNLTYPE_PIM_SM, "PIM-SM"},
121 {PMSI_TNLTYPE_PIM_BIDIR, "PIM-BIDIR"},
122 {PMSI_TNLTYPE_INGR_REPL, "Ingress Replication"},
123 {PMSI_TNLTYPE_MLDP_MP2MP, "mLDP MP2MP"},
124 {0}
125 };
126
127 #define VRFID_NONE_STR "-"
128 #define SOFT_RECONFIG_TASK_MAX_PREFIX 25000
129
130 DEFINE_HOOK(bgp_process,
131 (struct bgp * bgp, afi_t afi, safi_t safi, struct bgp_dest *bn,
132 struct peer *peer, bool withdraw),
133 (bgp, afi, safi, bn, peer, withdraw));
134
135 /** Test if path is suppressed. */
136 static bool bgp_path_suppressed(struct bgp_path_info *pi)
137 {
138 if (pi->extra == NULL || pi->extra->aggr_suppressors == NULL)
139 return false;
140
141 return listcount(pi->extra->aggr_suppressors) > 0;
142 }
143
144 struct bgp_dest *bgp_afi_node_get(struct bgp_table *table, afi_t afi,
145 safi_t safi, const struct prefix *p,
146 struct prefix_rd *prd)
147 {
148 struct bgp_dest *dest;
149 struct bgp_dest *pdest = NULL;
150
151 assert(table);
152
153 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
154 || (safi == SAFI_EVPN)) {
155 pdest = bgp_node_get(table, (struct prefix *)prd);
156
157 if (!bgp_dest_has_bgp_path_info_data(pdest))
158 bgp_dest_set_bgp_table_info(
159 pdest, bgp_table_init(table->bgp, afi, safi));
160 else
161 bgp_dest_unlock_node(pdest);
162 table = bgp_dest_get_bgp_table_info(pdest);
163 }
164
165 dest = bgp_node_get(table, p);
166
167 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
168 || (safi == SAFI_EVPN))
169 dest->pdest = pdest;
170
171 return dest;
172 }
173
174 struct bgp_dest *bgp_afi_node_lookup(struct bgp_table *table, afi_t afi,
175 safi_t safi, const struct prefix *p,
176 struct prefix_rd *prd)
177 {
178 struct bgp_dest *dest;
179 struct bgp_dest *pdest = NULL;
180
181 if (!table)
182 return NULL;
183
184 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
185 || (safi == SAFI_EVPN)) {
186 pdest = bgp_node_lookup(table, (struct prefix *)prd);
187 if (!pdest)
188 return NULL;
189
190 if (!bgp_dest_has_bgp_path_info_data(pdest)) {
191 bgp_dest_unlock_node(pdest);
192 return NULL;
193 }
194
195 table = bgp_dest_get_bgp_table_info(pdest);
196 }
197
198 dest = bgp_node_lookup(table, p);
199
200 return dest;
201 }
202
203 /* Allocate bgp_path_info_extra */
204 static struct bgp_path_info_extra *bgp_path_info_extra_new(void)
205 {
206 struct bgp_path_info_extra *new;
207 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA,
208 sizeof(struct bgp_path_info_extra));
209 new->label[0] = MPLS_INVALID_LABEL;
210 new->num_labels = 0;
211 new->bgp_fs_pbr = NULL;
212 new->bgp_fs_iprule = NULL;
213 return new;
214 }
215
216 void bgp_path_info_extra_free(struct bgp_path_info_extra **extra)
217 {
218 struct bgp_path_info_extra *e;
219
220 if (!extra || !*extra)
221 return;
222
223 e = *extra;
224
225 e->damp_info = NULL;
226 if (e->parent) {
227 struct bgp_path_info *bpi = (struct bgp_path_info *)e->parent;
228
229 if (bpi->net) {
230 /* FIXME: since multiple e may have the same e->parent
231 * and e->parent->net is holding a refcount for each
232 * of them, we need to do some fudging here.
233 *
234 * WARNING: if bpi->net->lock drops to 0, bpi may be
235 * freed as well (because bpi->net was holding the
236 * last reference to bpi) => write after free!
237 */
238 unsigned refcount;
239
240 bpi = bgp_path_info_lock(bpi);
241 refcount = bgp_dest_get_lock_count(bpi->net) - 1;
242 bgp_dest_unlock_node((struct bgp_dest *)bpi->net);
243 if (!refcount)
244 bpi->net = NULL;
245 bgp_path_info_unlock(bpi);
246 }
247 bgp_path_info_unlock(e->parent);
248 e->parent = NULL;
249 }
250
251 if (e->bgp_orig)
252 bgp_unlock(e->bgp_orig);
253
254 if (e->aggr_suppressors)
255 list_delete(&e->aggr_suppressors);
256
257 if (e->mh_info)
258 bgp_evpn_path_mh_info_free(e->mh_info);
259
260 if ((*extra)->bgp_fs_iprule)
261 list_delete(&((*extra)->bgp_fs_iprule));
262 if ((*extra)->bgp_fs_pbr)
263 list_delete(&((*extra)->bgp_fs_pbr));
264 XFREE(MTYPE_BGP_ROUTE_EXTRA, *extra);
265 }
266
267 /* Get bgp_path_info extra information for the given bgp_path_info, lazy
268 * allocated if required.
269 */
270 struct bgp_path_info_extra *bgp_path_info_extra_get(struct bgp_path_info *pi)
271 {
272 if (!pi->extra)
273 pi->extra = bgp_path_info_extra_new();
274 return pi->extra;
275 }
276
277 /* Free bgp route information. */
278 static void bgp_path_info_free(struct bgp_path_info *path)
279 {
280 bgp_attr_unintern(&path->attr);
281
282 bgp_unlink_nexthop(path);
283 bgp_path_info_extra_free(&path->extra);
284 bgp_path_info_mpath_free(&path->mpath);
285 if (path->net)
286 bgp_addpath_free_info_data(&path->tx_addpath,
287 &path->net->tx_addpath);
288
289 peer_unlock(path->peer); /* bgp_path_info peer reference */
290
291 XFREE(MTYPE_BGP_ROUTE, path);
292 }
293
294 struct bgp_path_info *bgp_path_info_lock(struct bgp_path_info *path)
295 {
296 path->lock++;
297 return path;
298 }
299
300 struct bgp_path_info *bgp_path_info_unlock(struct bgp_path_info *path)
301 {
302 assert(path && path->lock > 0);
303 path->lock--;
304
305 if (path->lock == 0) {
306 #if 0
307 zlog_debug ("%s: unlocked and freeing", __func__);
308 zlog_backtrace (LOG_DEBUG);
309 #endif
310 bgp_path_info_free(path);
311 return NULL;
312 }
313
314 #if 0
315 if (path->lock == 1)
316 {
317 zlog_debug ("%s: unlocked to 1", __func__);
318 zlog_backtrace (LOG_DEBUG);
319 }
320 #endif
321
322 return path;
323 }
324
325 /* This function sets flag BGP_NODE_SELECT_DEFER based on condition */
326 static int bgp_dest_set_defer_flag(struct bgp_dest *dest, bool delete)
327 {
328 struct peer *peer;
329 struct bgp_path_info *old_pi, *nextpi;
330 bool set_flag = false;
331 struct bgp *bgp = NULL;
332 struct bgp_table *table = NULL;
333 afi_t afi = 0;
334 safi_t safi = 0;
335
336 /* If the flag BGP_NODE_SELECT_DEFER is set and new path is added
337 * then the route selection is deferred
338 */
339 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER) && (!delete))
340 return 0;
341
342 if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED)) {
343 if (BGP_DEBUG(update, UPDATE_OUT))
344 zlog_debug(
345 "Route %pBD is in workqueue and being processed, not deferred.",
346 dest);
347
348 return 0;
349 }
350
351 table = bgp_dest_table(dest);
352 if (table) {
353 bgp = table->bgp;
354 afi = table->afi;
355 safi = table->safi;
356 }
357
358 for (old_pi = bgp_dest_get_bgp_path_info(dest);
359 (old_pi != NULL) && (nextpi = old_pi->next, 1); old_pi = nextpi) {
360 if (CHECK_FLAG(old_pi->flags, BGP_PATH_SELECTED))
361 continue;
362
363 /* Route selection is deferred if there is a stale path which
364 * which indicates peer is in restart mode
365 */
366 if (CHECK_FLAG(old_pi->flags, BGP_PATH_STALE)
367 && (old_pi->sub_type == BGP_ROUTE_NORMAL)) {
368 set_flag = true;
369 } else {
370 /* If the peer is graceful restart capable and peer is
371 * restarting mode, set the flag BGP_NODE_SELECT_DEFER
372 */
373 peer = old_pi->peer;
374 if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer)
375 && BGP_PEER_RESTARTING_MODE(peer)
376 && (old_pi
377 && old_pi->sub_type == BGP_ROUTE_NORMAL)) {
378 set_flag = true;
379 }
380 }
381 if (set_flag)
382 break;
383 }
384
385 /* Set the flag BGP_NODE_SELECT_DEFER if route selection deferral timer
386 * is active
387 */
388 if (set_flag && table) {
389 if (bgp && (bgp->gr_info[afi][safi].t_select_deferral)) {
390 if (!CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER))
391 bgp->gr_info[afi][safi].gr_deferred++;
392 SET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
393 if (BGP_DEBUG(update, UPDATE_OUT))
394 zlog_debug("DEFER route %pBD, dest %p", dest,
395 dest);
396 return 0;
397 }
398 }
399 return -1;
400 }
401
402 void bgp_path_info_add(struct bgp_dest *dest, struct bgp_path_info *pi)
403 {
404 struct bgp_path_info *top;
405
406 top = bgp_dest_get_bgp_path_info(dest);
407
408 pi->next = top;
409 pi->prev = NULL;
410 if (top)
411 top->prev = pi;
412 bgp_dest_set_bgp_path_info(dest, pi);
413
414 bgp_path_info_lock(pi);
415 bgp_dest_lock_node(dest);
416 peer_lock(pi->peer); /* bgp_path_info peer reference */
417 bgp_dest_set_defer_flag(dest, false);
418 hook_call(bgp_snmp_update_stats, dest, pi, true);
419 }
420
421 /* Do the actual removal of info from RIB, for use by bgp_process
422 completion callback *only* */
423 void bgp_path_info_reap(struct bgp_dest *dest, struct bgp_path_info *pi)
424 {
425 if (pi->next)
426 pi->next->prev = pi->prev;
427 if (pi->prev)
428 pi->prev->next = pi->next;
429 else
430 bgp_dest_set_bgp_path_info(dest, pi->next);
431
432 bgp_path_info_mpath_dequeue(pi);
433 bgp_path_info_unlock(pi);
434 hook_call(bgp_snmp_update_stats, dest, pi, false);
435 bgp_dest_unlock_node(dest);
436 }
437
438 void bgp_path_info_delete(struct bgp_dest *dest, struct bgp_path_info *pi)
439 {
440 bgp_path_info_set_flag(dest, pi, BGP_PATH_REMOVED);
441 /* set of previous already took care of pcount */
442 UNSET_FLAG(pi->flags, BGP_PATH_VALID);
443 }
444
445 /* undo the effects of a previous call to bgp_path_info_delete; typically
446 called when a route is deleted and then quickly re-added before the
447 deletion has been processed */
448 void bgp_path_info_restore(struct bgp_dest *dest, struct bgp_path_info *pi)
449 {
450 bgp_path_info_unset_flag(dest, pi, BGP_PATH_REMOVED);
451 /* unset of previous already took care of pcount */
452 SET_FLAG(pi->flags, BGP_PATH_VALID);
453 }
454
455 /* Adjust pcount as required */
456 static void bgp_pcount_adjust(struct bgp_dest *dest, struct bgp_path_info *pi)
457 {
458 struct bgp_table *table;
459
460 assert(dest && bgp_dest_table(dest));
461 assert(pi && pi->peer && pi->peer->bgp);
462
463 table = bgp_dest_table(dest);
464
465 if (pi->peer == pi->peer->bgp->peer_self)
466 return;
467
468 if (!BGP_PATH_COUNTABLE(pi)
469 && CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
470
471 UNSET_FLAG(pi->flags, BGP_PATH_COUNTED);
472
473 /* slight hack, but more robust against errors. */
474 if (pi->peer->pcount[table->afi][table->safi])
475 pi->peer->pcount[table->afi][table->safi]--;
476 else
477 flog_err(EC_LIB_DEVELOPMENT,
478 "Asked to decrement 0 prefix count for peer");
479 } else if (BGP_PATH_COUNTABLE(pi)
480 && !CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
481 SET_FLAG(pi->flags, BGP_PATH_COUNTED);
482 pi->peer->pcount[table->afi][table->safi]++;
483 }
484 }
485
486 static int bgp_label_index_differs(struct bgp_path_info *pi1,
487 struct bgp_path_info *pi2)
488 {
489 return (!(pi1->attr->label_index == pi2->attr->label_index));
490 }
491
492 /* Set/unset bgp_path_info flags, adjusting any other state as needed.
493 * This is here primarily to keep prefix-count in check.
494 */
495 void bgp_path_info_set_flag(struct bgp_dest *dest, struct bgp_path_info *pi,
496 uint32_t flag)
497 {
498 SET_FLAG(pi->flags, flag);
499
500 /* early bath if we know it's not a flag that changes countability state
501 */
502 if (!CHECK_FLAG(flag,
503 BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
504 return;
505
506 bgp_pcount_adjust(dest, pi);
507 }
508
509 void bgp_path_info_unset_flag(struct bgp_dest *dest, struct bgp_path_info *pi,
510 uint32_t flag)
511 {
512 UNSET_FLAG(pi->flags, flag);
513
514 /* early bath if we know it's not a flag that changes countability state
515 */
516 if (!CHECK_FLAG(flag,
517 BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
518 return;
519
520 bgp_pcount_adjust(dest, pi);
521 }
522
523 /* Get MED value. If MED value is missing and "bgp bestpath
524 missing-as-worst" is specified, treat it as the worst value. */
525 static uint32_t bgp_med_value(struct attr *attr, struct bgp *bgp)
526 {
527 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
528 return attr->med;
529 else {
530 if (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_MISSING_AS_WORST))
531 return BGP_MED_MAX;
532 else
533 return 0;
534 }
535 }
536
537 void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info *pi, char *buf,
538 size_t buf_len)
539 {
540 if (pi->addpath_rx_id)
541 snprintf(buf, buf_len, "path %s (addpath rxid %d)",
542 pi->peer->host, pi->addpath_rx_id);
543 else
544 snprintf(buf, buf_len, "path %s", pi->peer->host);
545 }
546
547 /* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
548 */
549 static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
550 struct bgp_path_info *exist, int *paths_eq,
551 struct bgp_maxpaths_cfg *mpath_cfg, int debug,
552 char *pfx_buf, afi_t afi, safi_t safi,
553 enum bgp_path_selection_reason *reason)
554 {
555 const struct prefix *new_p;
556 struct attr *newattr, *existattr;
557 bgp_peer_sort_t new_sort;
558 bgp_peer_sort_t exist_sort;
559 uint32_t new_pref;
560 uint32_t exist_pref;
561 uint32_t new_med;
562 uint32_t exist_med;
563 uint32_t new_weight;
564 uint32_t exist_weight;
565 uint32_t newm, existm;
566 struct in_addr new_id;
567 struct in_addr exist_id;
568 int new_cluster;
569 int exist_cluster;
570 int internal_as_route;
571 int confed_as_route;
572 int ret = 0;
573 int igp_metric_ret = 0;
574 int peer_sort_ret = -1;
575 char new_buf[PATH_ADDPATH_STR_BUFFER];
576 char exist_buf[PATH_ADDPATH_STR_BUFFER];
577 uint32_t new_mm_seq;
578 uint32_t exist_mm_seq;
579 int nh_cmp;
580 esi_t *exist_esi;
581 esi_t *new_esi;
582 bool same_esi;
583 bool old_proxy;
584 bool new_proxy;
585 bool new_origin, exist_origin;
586
587 *paths_eq = 0;
588
589 /* 0. Null check. */
590 if (new == NULL) {
591 *reason = bgp_path_selection_none;
592 if (debug)
593 zlog_debug("%s: new is NULL", pfx_buf);
594 return 0;
595 }
596
597 if (debug)
598 bgp_path_info_path_with_addpath_rx_str(new, new_buf,
599 sizeof(new_buf));
600
601 if (exist == NULL) {
602 *reason = bgp_path_selection_first;
603 if (debug)
604 zlog_debug("%s: %s is the initial bestpath", pfx_buf,
605 new_buf);
606 return 1;
607 }
608
609 if (debug) {
610 bgp_path_info_path_with_addpath_rx_str(exist, exist_buf,
611 sizeof(exist_buf));
612 zlog_debug("%s: Comparing %s flags 0x%x with %s flags 0x%x",
613 pfx_buf, new_buf, new->flags, exist_buf,
614 exist->flags);
615 }
616
617 newattr = new->attr;
618 existattr = exist->attr;
619
620 new_p = bgp_dest_get_prefix(new->net);
621
622 /* For EVPN routes, we cannot just go by local vs remote, we have to
623 * look at the MAC mobility sequence number, if present.
624 */
625 if ((safi == SAFI_EVPN)
626 && (new_p->u.prefix_evpn.route_type == BGP_EVPN_MAC_IP_ROUTE)) {
627 /* This is an error condition described in RFC 7432 Section
628 * 15.2. The RFC
629 * states that in this scenario "the PE MUST alert the operator"
630 * but it
631 * does not state what other action to take. In order to provide
632 * some
633 * consistency in this scenario we are going to prefer the path
634 * with the
635 * sticky flag.
636 */
637 if (newattr->sticky != existattr->sticky) {
638 if (!debug) {
639 prefix2str(new_p, pfx_buf,
640 sizeof(*pfx_buf)
641 * PREFIX2STR_BUFFER);
642 bgp_path_info_path_with_addpath_rx_str(
643 new, new_buf, sizeof(new_buf));
644 bgp_path_info_path_with_addpath_rx_str(
645 exist, exist_buf, sizeof(exist_buf));
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 wins over %s due to sticky MAC flag",
653 pfx_buf, new_buf, exist_buf);
654 return 1;
655 }
656
657 if (!newattr->sticky && existattr->sticky) {
658 *reason = bgp_path_selection_evpn_sticky_mac;
659 if (debug)
660 zlog_debug(
661 "%s: %s loses to %s due to sticky MAC flag",
662 pfx_buf, new_buf, exist_buf);
663 return 0;
664 }
665 }
666
667 new_esi = bgp_evpn_attr_get_esi(newattr);
668 exist_esi = bgp_evpn_attr_get_esi(existattr);
669 if (bgp_evpn_is_esi_valid(new_esi) &&
670 !memcmp(new_esi, exist_esi, sizeof(esi_t))) {
671 same_esi = true;
672 } else {
673 same_esi = false;
674 }
675
676 /* If both paths have the same non-zero ES and
677 * one path is local it wins.
678 * PS: Note the local path wins even if the remote
679 * has the higher MM seq. The local path's
680 * MM seq will be fixed up to match the highest
681 * rem seq, subsequently.
682 */
683 if (same_esi) {
684 char esi_buf[ESI_STR_LEN];
685
686 if (bgp_evpn_is_path_local(bgp, new)) {
687 *reason = bgp_path_selection_evpn_local_path;
688 if (debug)
689 zlog_debug(
690 "%s: %s wins over %s as ES %s is same and local",
691 pfx_buf, new_buf, exist_buf,
692 esi_to_str(new_esi, esi_buf,
693 sizeof(esi_buf)));
694 return 1;
695 }
696 if (bgp_evpn_is_path_local(bgp, exist)) {
697 *reason = bgp_path_selection_evpn_local_path;
698 if (debug)
699 zlog_debug(
700 "%s: %s loses to %s as ES %s is same and local",
701 pfx_buf, new_buf, exist_buf,
702 esi_to_str(new_esi, esi_buf,
703 sizeof(esi_buf)));
704 return 0;
705 }
706 }
707
708 new_mm_seq = mac_mobility_seqnum(newattr);
709 exist_mm_seq = mac_mobility_seqnum(existattr);
710
711 if (new_mm_seq > exist_mm_seq) {
712 *reason = bgp_path_selection_evpn_seq;
713 if (debug)
714 zlog_debug(
715 "%s: %s wins over %s due to MM seq %u > %u",
716 pfx_buf, new_buf, exist_buf, new_mm_seq,
717 exist_mm_seq);
718 return 1;
719 }
720
721 if (new_mm_seq < exist_mm_seq) {
722 *reason = bgp_path_selection_evpn_seq;
723 if (debug)
724 zlog_debug(
725 "%s: %s loses to %s due to MM seq %u < %u",
726 pfx_buf, new_buf, exist_buf, new_mm_seq,
727 exist_mm_seq);
728 return 0;
729 }
730
731 /* if the sequence numbers and ESI are the same and one path
732 * is non-proxy it wins (over proxy)
733 */
734 new_proxy = bgp_evpn_attr_is_proxy(newattr);
735 old_proxy = bgp_evpn_attr_is_proxy(existattr);
736 if (same_esi && bgp_evpn_attr_is_local_es(newattr) &&
737 old_proxy != new_proxy) {
738 if (!new_proxy) {
739 *reason = bgp_path_selection_evpn_non_proxy;
740 if (debug)
741 zlog_debug(
742 "%s: %s wins over %s, same seq/es and non-proxy",
743 pfx_buf, new_buf, exist_buf);
744 return 1;
745 }
746
747 *reason = bgp_path_selection_evpn_non_proxy;
748 if (debug)
749 zlog_debug(
750 "%s: %s loses to %s, same seq/es and non-proxy",
751 pfx_buf, new_buf, exist_buf);
752 return 0;
753 }
754
755 /*
756 * if sequence numbers are the same path with the lowest IP
757 * wins
758 */
759 nh_cmp = bgp_path_info_nexthop_cmp(new, exist);
760 if (nh_cmp < 0) {
761 *reason = bgp_path_selection_evpn_lower_ip;
762 if (debug)
763 zlog_debug(
764 "%s: %s wins over %s due to same MM seq %u and lower IP %pI4",
765 pfx_buf, new_buf, exist_buf, new_mm_seq,
766 &new->attr->nexthop);
767 return 1;
768 }
769 if (nh_cmp > 0) {
770 *reason = bgp_path_selection_evpn_lower_ip;
771 if (debug)
772 zlog_debug(
773 "%s: %s loses to %s due to same MM seq %u and higher IP %pI4",
774 pfx_buf, new_buf, exist_buf, new_mm_seq,
775 &new->attr->nexthop);
776 return 0;
777 }
778 }
779
780 /* 1. Weight check. */
781 new_weight = newattr->weight;
782 exist_weight = existattr->weight;
783
784 if (new_weight > exist_weight) {
785 *reason = bgp_path_selection_weight;
786 if (debug)
787 zlog_debug("%s: %s wins over %s due to weight %d > %d",
788 pfx_buf, new_buf, exist_buf, new_weight,
789 exist_weight);
790 return 1;
791 }
792
793 if (new_weight < exist_weight) {
794 *reason = bgp_path_selection_weight;
795 if (debug)
796 zlog_debug("%s: %s loses to %s due to weight %d < %d",
797 pfx_buf, new_buf, exist_buf, new_weight,
798 exist_weight);
799 return 0;
800 }
801
802 /* 2. Local preference check. */
803 new_pref = exist_pref = bgp->default_local_pref;
804
805 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
806 new_pref = newattr->local_pref;
807 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
808 exist_pref = existattr->local_pref;
809
810 if (new_pref > exist_pref) {
811 *reason = bgp_path_selection_local_pref;
812 if (debug)
813 zlog_debug(
814 "%s: %s wins over %s due to localpref %d > %d",
815 pfx_buf, new_buf, exist_buf, new_pref,
816 exist_pref);
817 return 1;
818 }
819
820 if (new_pref < exist_pref) {
821 *reason = bgp_path_selection_local_pref;
822 if (debug)
823 zlog_debug(
824 "%s: %s loses to %s due to localpref %d < %d",
825 pfx_buf, new_buf, exist_buf, new_pref,
826 exist_pref);
827 return 0;
828 }
829
830 /* 3. Local route check. We prefer:
831 * - BGP_ROUTE_STATIC
832 * - BGP_ROUTE_AGGREGATE
833 * - BGP_ROUTE_REDISTRIBUTE
834 */
835 new_origin = !(new->sub_type == BGP_ROUTE_NORMAL ||
836 new->sub_type == BGP_ROUTE_IMPORTED);
837 exist_origin = !(exist->sub_type == BGP_ROUTE_NORMAL ||
838 exist->sub_type == BGP_ROUTE_IMPORTED);
839
840 if (new_origin && !exist_origin) {
841 *reason = bgp_path_selection_local_route;
842 if (debug)
843 zlog_debug(
844 "%s: %s wins over %s due to preferred BGP_ROUTE type",
845 pfx_buf, new_buf, exist_buf);
846 return 1;
847 }
848
849 if (!new_origin && exist_origin) {
850 *reason = bgp_path_selection_local_route;
851 if (debug)
852 zlog_debug(
853 "%s: %s loses to %s due to preferred BGP_ROUTE type",
854 pfx_buf, new_buf, exist_buf);
855 return 0;
856 }
857
858 /* 4. AS path length check. */
859 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_IGNORE)) {
860 int exist_hops = aspath_count_hops(existattr->aspath);
861 int exist_confeds = aspath_count_confeds(existattr->aspath);
862
863 if (CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_CONFED)) {
864 int aspath_hops;
865
866 aspath_hops = aspath_count_hops(newattr->aspath);
867 aspath_hops += aspath_count_confeds(newattr->aspath);
868
869 if (aspath_hops < (exist_hops + exist_confeds)) {
870 *reason = bgp_path_selection_confed_as_path;
871 if (debug)
872 zlog_debug(
873 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
874 pfx_buf, new_buf, exist_buf,
875 aspath_hops,
876 (exist_hops + exist_confeds));
877 return 1;
878 }
879
880 if (aspath_hops > (exist_hops + exist_confeds)) {
881 *reason = bgp_path_selection_confed_as_path;
882 if (debug)
883 zlog_debug(
884 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
885 pfx_buf, new_buf, exist_buf,
886 aspath_hops,
887 (exist_hops + exist_confeds));
888 return 0;
889 }
890 } else {
891 int newhops = aspath_count_hops(newattr->aspath);
892
893 if (newhops < exist_hops) {
894 *reason = bgp_path_selection_as_path;
895 if (debug)
896 zlog_debug(
897 "%s: %s wins over %s due to aspath hopcount %d < %d",
898 pfx_buf, new_buf, exist_buf,
899 newhops, exist_hops);
900 return 1;
901 }
902
903 if (newhops > exist_hops) {
904 *reason = bgp_path_selection_as_path;
905 if (debug)
906 zlog_debug(
907 "%s: %s loses to %s due to aspath hopcount %d > %d",
908 pfx_buf, new_buf, exist_buf,
909 newhops, exist_hops);
910 return 0;
911 }
912 }
913 }
914
915 /* 5. Origin check. */
916 if (newattr->origin < existattr->origin) {
917 *reason = bgp_path_selection_origin;
918 if (debug)
919 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
920 pfx_buf, new_buf, exist_buf,
921 bgp_origin_long_str[newattr->origin],
922 bgp_origin_long_str[existattr->origin]);
923 return 1;
924 }
925
926 if (newattr->origin > existattr->origin) {
927 *reason = bgp_path_selection_origin;
928 if (debug)
929 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
930 pfx_buf, new_buf, exist_buf,
931 bgp_origin_long_str[newattr->origin],
932 bgp_origin_long_str[existattr->origin]);
933 return 0;
934 }
935
936 /* 6. MED check. */
937 internal_as_route = (aspath_count_hops(newattr->aspath) == 0
938 && aspath_count_hops(existattr->aspath) == 0);
939 confed_as_route = (aspath_count_confeds(newattr->aspath) > 0
940 && aspath_count_confeds(existattr->aspath) > 0
941 && aspath_count_hops(newattr->aspath) == 0
942 && aspath_count_hops(existattr->aspath) == 0);
943
944 if (CHECK_FLAG(bgp->flags, BGP_FLAG_ALWAYS_COMPARE_MED)
945 || (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_CONFED) && confed_as_route)
946 || aspath_cmp_left(newattr->aspath, existattr->aspath)
947 || aspath_cmp_left_confed(newattr->aspath, existattr->aspath)
948 || internal_as_route) {
949 new_med = bgp_med_value(new->attr, bgp);
950 exist_med = bgp_med_value(exist->attr, bgp);
951
952 if (new_med < exist_med) {
953 *reason = bgp_path_selection_med;
954 if (debug)
955 zlog_debug(
956 "%s: %s wins over %s due to MED %d < %d",
957 pfx_buf, new_buf, exist_buf, new_med,
958 exist_med);
959 return 1;
960 }
961
962 if (new_med > exist_med) {
963 *reason = bgp_path_selection_med;
964 if (debug)
965 zlog_debug(
966 "%s: %s loses to %s due to MED %d > %d",
967 pfx_buf, new_buf, exist_buf, new_med,
968 exist_med);
969 return 0;
970 }
971 }
972
973 /* 7. Peer type check. */
974 new_sort = new->peer->sort;
975 exist_sort = exist->peer->sort;
976
977 if (new_sort == BGP_PEER_EBGP
978 && (exist_sort == BGP_PEER_IBGP || exist_sort == BGP_PEER_CONFED)) {
979 *reason = bgp_path_selection_peer;
980 if (debug)
981 zlog_debug(
982 "%s: %s wins over %s due to eBGP peer > iBGP peer",
983 pfx_buf, new_buf, exist_buf);
984 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
985 return 1;
986 peer_sort_ret = 1;
987 }
988
989 if (exist_sort == BGP_PEER_EBGP
990 && (new_sort == BGP_PEER_IBGP || new_sort == BGP_PEER_CONFED)) {
991 *reason = bgp_path_selection_peer;
992 if (debug)
993 zlog_debug(
994 "%s: %s loses to %s due to iBGP peer < eBGP peer",
995 pfx_buf, new_buf, exist_buf);
996 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
997 return 0;
998 peer_sort_ret = 0;
999 }
1000
1001 /* 8. IGP metric check. */
1002 newm = existm = 0;
1003
1004 if (new->extra)
1005 newm = new->extra->igpmetric;
1006 if (exist->extra)
1007 existm = exist->extra->igpmetric;
1008
1009 if (newm < existm) {
1010 if (debug && peer_sort_ret < 0)
1011 zlog_debug(
1012 "%s: %s wins over %s due to IGP metric %u < %u",
1013 pfx_buf, new_buf, exist_buf, newm, existm);
1014 igp_metric_ret = 1;
1015 }
1016
1017 if (newm > existm) {
1018 if (debug && peer_sort_ret < 0)
1019 zlog_debug(
1020 "%s: %s loses to %s due to IGP metric %u > %u",
1021 pfx_buf, new_buf, exist_buf, newm, existm);
1022 igp_metric_ret = 0;
1023 }
1024
1025 /* 9. Same IGP metric. Compare the cluster list length as
1026 representative of IGP hops metric. Rewrite the metric value
1027 pair (newm, existm) with the cluster list length. Prefer the
1028 path with smaller cluster list length. */
1029 if (newm == existm) {
1030 if (peer_sort_lookup(new->peer) == BGP_PEER_IBGP
1031 && peer_sort_lookup(exist->peer) == BGP_PEER_IBGP
1032 && (mpath_cfg == NULL
1033 || CHECK_FLAG(
1034 mpath_cfg->ibgp_flags,
1035 BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN))) {
1036 newm = BGP_CLUSTER_LIST_LENGTH(new->attr);
1037 existm = BGP_CLUSTER_LIST_LENGTH(exist->attr);
1038
1039 if (newm < existm) {
1040 if (debug && peer_sort_ret < 0)
1041 zlog_debug(
1042 "%s: %s wins over %s due to CLUSTER_LIST length %u < %u",
1043 pfx_buf, new_buf, exist_buf,
1044 newm, existm);
1045 igp_metric_ret = 1;
1046 }
1047
1048 if (newm > existm) {
1049 if (debug && peer_sort_ret < 0)
1050 zlog_debug(
1051 "%s: %s loses to %s due to CLUSTER_LIST length %u > %u",
1052 pfx_buf, new_buf, exist_buf,
1053 newm, existm);
1054 igp_metric_ret = 0;
1055 }
1056 }
1057 }
1058
1059 /* 10. confed-external vs. confed-internal */
1060 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
1061 if (new_sort == BGP_PEER_CONFED
1062 && exist_sort == BGP_PEER_IBGP) {
1063 *reason = bgp_path_selection_confed;
1064 if (debug)
1065 zlog_debug(
1066 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
1067 pfx_buf, new_buf, exist_buf);
1068 if (!CHECK_FLAG(bgp->flags,
1069 BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1070 return 1;
1071 peer_sort_ret = 1;
1072 }
1073
1074 if (exist_sort == BGP_PEER_CONFED
1075 && new_sort == BGP_PEER_IBGP) {
1076 *reason = bgp_path_selection_confed;
1077 if (debug)
1078 zlog_debug(
1079 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
1080 pfx_buf, new_buf, exist_buf);
1081 if (!CHECK_FLAG(bgp->flags,
1082 BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1083 return 0;
1084 peer_sort_ret = 0;
1085 }
1086 }
1087
1088 /* 11. Maximum path check. */
1089 if (newm == existm) {
1090 /* If one path has a label but the other does not, do not treat
1091 * them as equals for multipath
1092 */
1093 if ((new->extra &&bgp_is_valid_label(&new->extra->label[0]))
1094 != (exist->extra
1095 && bgp_is_valid_label(&exist->extra->label[0]))) {
1096 if (debug)
1097 zlog_debug(
1098 "%s: %s and %s cannot be multipath, one has a label while the other does not",
1099 pfx_buf, new_buf, exist_buf);
1100 } else if (CHECK_FLAG(bgp->flags,
1101 BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
1102
1103 /*
1104 * For the two paths, all comparison steps till IGP
1105 * metric
1106 * have succeeded - including AS_PATH hop count. Since
1107 * 'bgp
1108 * bestpath as-path multipath-relax' knob is on, we
1109 * don't need
1110 * an exact match of AS_PATH. Thus, mark the paths are
1111 * equal.
1112 * That will trigger both these paths to get into the
1113 * multipath
1114 * array.
1115 */
1116 *paths_eq = 1;
1117
1118 if (debug)
1119 zlog_debug(
1120 "%s: %s and %s are equal via multipath-relax",
1121 pfx_buf, new_buf, exist_buf);
1122 } else if (new->peer->sort == BGP_PEER_IBGP) {
1123 if (aspath_cmp(new->attr->aspath,
1124 exist->attr->aspath)) {
1125 *paths_eq = 1;
1126
1127 if (debug)
1128 zlog_debug(
1129 "%s: %s and %s are equal via matching aspaths",
1130 pfx_buf, new_buf, exist_buf);
1131 }
1132 } else if (new->peer->as == exist->peer->as) {
1133 *paths_eq = 1;
1134
1135 if (debug)
1136 zlog_debug(
1137 "%s: %s and %s are equal via same remote-as",
1138 pfx_buf, new_buf, exist_buf);
1139 }
1140 } else {
1141 /*
1142 * TODO: If unequal cost ibgp multipath is enabled we can
1143 * mark the paths as equal here instead of returning
1144 */
1145
1146 /* Prior to the addition of BGP_FLAG_PEERTYPE_MULTIPATH_RELAX,
1147 * if either step 7 or 10 (peer type checks) yielded a winner,
1148 * that result was returned immediately. Returning from step 10
1149 * ignored the return value computed in steps 8 and 9 (IGP
1150 * metric checks). In order to preserve that behavior, if
1151 * peer_sort_ret is set, return that rather than igp_metric_ret.
1152 */
1153 ret = peer_sort_ret;
1154 if (peer_sort_ret < 0) {
1155 ret = igp_metric_ret;
1156 if (debug) {
1157 if (ret == 1)
1158 zlog_debug(
1159 "%s: %s wins over %s after IGP metric comparison",
1160 pfx_buf, new_buf, exist_buf);
1161 else
1162 zlog_debug(
1163 "%s: %s loses to %s after IGP metric comparison",
1164 pfx_buf, new_buf, exist_buf);
1165 }
1166 *reason = bgp_path_selection_igp_metric;
1167 }
1168 return ret;
1169 }
1170
1171 /*
1172 * At this point, the decision whether to set *paths_eq = 1 has been
1173 * completed. If we deferred returning because of bestpath peer-type
1174 * relax configuration, return now.
1175 */
1176 if (peer_sort_ret >= 0)
1177 return peer_sort_ret;
1178
1179 /* 12. If both paths are external, prefer the path that was received
1180 first (the oldest one). This step minimizes route-flap, since a
1181 newer path won't displace an older one, even if it was the
1182 preferred route based on the additional decision criteria below. */
1183 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_COMPARE_ROUTER_ID)
1184 && new_sort == BGP_PEER_EBGP && exist_sort == BGP_PEER_EBGP) {
1185 if (CHECK_FLAG(new->flags, BGP_PATH_SELECTED)) {
1186 *reason = bgp_path_selection_older;
1187 if (debug)
1188 zlog_debug(
1189 "%s: %s wins over %s due to oldest external",
1190 pfx_buf, new_buf, exist_buf);
1191 return 1;
1192 }
1193
1194 if (CHECK_FLAG(exist->flags, BGP_PATH_SELECTED)) {
1195 *reason = bgp_path_selection_older;
1196 if (debug)
1197 zlog_debug(
1198 "%s: %s loses to %s due to oldest external",
1199 pfx_buf, new_buf, exist_buf);
1200 return 0;
1201 }
1202 }
1203
1204 /* 13. Router-ID comparision. */
1205 /* If one of the paths is "stale", the corresponding peer router-id will
1206 * be 0 and would always win over the other path. If originator id is
1207 * used for the comparision, it will decide which path is better.
1208 */
1209 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1210 new_id.s_addr = newattr->originator_id.s_addr;
1211 else
1212 new_id.s_addr = new->peer->remote_id.s_addr;
1213 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1214 exist_id.s_addr = existattr->originator_id.s_addr;
1215 else
1216 exist_id.s_addr = exist->peer->remote_id.s_addr;
1217
1218 if (ntohl(new_id.s_addr) < ntohl(exist_id.s_addr)) {
1219 *reason = bgp_path_selection_router_id;
1220 if (debug)
1221 zlog_debug(
1222 "%s: %s wins over %s due to Router-ID comparison",
1223 pfx_buf, new_buf, exist_buf);
1224 return 1;
1225 }
1226
1227 if (ntohl(new_id.s_addr) > ntohl(exist_id.s_addr)) {
1228 *reason = bgp_path_selection_router_id;
1229 if (debug)
1230 zlog_debug(
1231 "%s: %s loses to %s due to Router-ID comparison",
1232 pfx_buf, new_buf, exist_buf);
1233 return 0;
1234 }
1235
1236 /* 14. Cluster length comparision. */
1237 new_cluster = BGP_CLUSTER_LIST_LENGTH(new->attr);
1238 exist_cluster = BGP_CLUSTER_LIST_LENGTH(exist->attr);
1239
1240 if (new_cluster < exist_cluster) {
1241 *reason = bgp_path_selection_cluster_length;
1242 if (debug)
1243 zlog_debug(
1244 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1245 pfx_buf, new_buf, exist_buf, new_cluster,
1246 exist_cluster);
1247 return 1;
1248 }
1249
1250 if (new_cluster > exist_cluster) {
1251 *reason = bgp_path_selection_cluster_length;
1252 if (debug)
1253 zlog_debug(
1254 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1255 pfx_buf, new_buf, exist_buf, new_cluster,
1256 exist_cluster);
1257 return 0;
1258 }
1259
1260 /* 15. Neighbor address comparision. */
1261 /* Do this only if neither path is "stale" as stale paths do not have
1262 * valid peer information (as the connection may or may not be up).
1263 */
1264 if (CHECK_FLAG(exist->flags, BGP_PATH_STALE)) {
1265 *reason = bgp_path_selection_stale;
1266 if (debug)
1267 zlog_debug(
1268 "%s: %s wins over %s due to latter path being STALE",
1269 pfx_buf, new_buf, exist_buf);
1270 return 1;
1271 }
1272
1273 if (CHECK_FLAG(new->flags, BGP_PATH_STALE)) {
1274 *reason = bgp_path_selection_stale;
1275 if (debug)
1276 zlog_debug(
1277 "%s: %s loses to %s due to former path being STALE",
1278 pfx_buf, new_buf, exist_buf);
1279 return 0;
1280 }
1281
1282 /* locally configured routes to advertise do not have su_remote */
1283 if (new->peer->su_remote == NULL) {
1284 *reason = bgp_path_selection_local_configured;
1285 return 0;
1286 }
1287 if (exist->peer->su_remote == NULL) {
1288 *reason = bgp_path_selection_local_configured;
1289 return 1;
1290 }
1291
1292 ret = sockunion_cmp(new->peer->su_remote, exist->peer->su_remote);
1293
1294 if (ret == 1) {
1295 *reason = bgp_path_selection_neighbor_ip;
1296 if (debug)
1297 zlog_debug(
1298 "%s: %s loses to %s due to Neighor IP comparison",
1299 pfx_buf, new_buf, exist_buf);
1300 return 0;
1301 }
1302
1303 if (ret == -1) {
1304 *reason = bgp_path_selection_neighbor_ip;
1305 if (debug)
1306 zlog_debug(
1307 "%s: %s wins over %s due to Neighor IP comparison",
1308 pfx_buf, new_buf, exist_buf);
1309 return 1;
1310 }
1311
1312 *reason = bgp_path_selection_default;
1313 if (debug)
1314 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1315 pfx_buf, new_buf, exist_buf);
1316
1317 return 1;
1318 }
1319
1320
1321 int bgp_evpn_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
1322 struct bgp_path_info *exist, int *paths_eq)
1323 {
1324 enum bgp_path_selection_reason reason;
1325 char pfx_buf[PREFIX2STR_BUFFER];
1326
1327 return bgp_path_info_cmp(bgp, new, exist, paths_eq, NULL, 0, pfx_buf,
1328 AFI_L2VPN, SAFI_EVPN, &reason);
1329 }
1330
1331 /* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1332 * is preferred, or 0 if they are the same (usually will only occur if
1333 * multipath is enabled
1334 * This version is compatible with */
1335 int bgp_path_info_cmp_compatible(struct bgp *bgp, struct bgp_path_info *new,
1336 struct bgp_path_info *exist, char *pfx_buf,
1337 afi_t afi, safi_t safi,
1338 enum bgp_path_selection_reason *reason)
1339 {
1340 int paths_eq;
1341 int ret;
1342 ret = bgp_path_info_cmp(bgp, new, exist, &paths_eq, NULL, 0, pfx_buf,
1343 afi, safi, reason);
1344
1345 if (paths_eq)
1346 ret = 0;
1347 else {
1348 if (ret == 1)
1349 ret = -1;
1350 else
1351 ret = 1;
1352 }
1353 return ret;
1354 }
1355
1356 static enum filter_type bgp_input_filter(struct peer *peer,
1357 const struct prefix *p,
1358 struct attr *attr, afi_t afi,
1359 safi_t safi)
1360 {
1361 struct bgp_filter *filter;
1362 enum filter_type ret = FILTER_PERMIT;
1363
1364 filter = &peer->filter[afi][safi];
1365
1366 #define FILTER_EXIST_WARN(F, f, filter) \
1367 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
1368 zlog_debug("%s: Could not find configured input %s-list %s!", \
1369 peer->host, #f, F##_IN_NAME(filter));
1370
1371 if (DISTRIBUTE_IN_NAME(filter)) {
1372 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
1373
1374 if (access_list_apply(DISTRIBUTE_IN(filter), p)
1375 == FILTER_DENY) {
1376 ret = FILTER_DENY;
1377 goto done;
1378 }
1379 }
1380
1381 if (PREFIX_LIST_IN_NAME(filter)) {
1382 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
1383
1384 if (prefix_list_apply(PREFIX_LIST_IN(filter), p)
1385 == PREFIX_DENY) {
1386 ret = FILTER_DENY;
1387 goto done;
1388 }
1389 }
1390
1391 if (FILTER_LIST_IN_NAME(filter)) {
1392 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
1393
1394 if (as_list_apply(FILTER_LIST_IN(filter), attr->aspath)
1395 == AS_FILTER_DENY) {
1396 ret = FILTER_DENY;
1397 goto done;
1398 }
1399 }
1400
1401 done:
1402 if (frrtrace_enabled(frr_bgp, input_filter)) {
1403 char pfxprint[PREFIX2STR_BUFFER];
1404
1405 prefix2str(p, pfxprint, sizeof(pfxprint));
1406 frrtrace(5, frr_bgp, input_filter, peer, pfxprint, afi, safi,
1407 ret == FILTER_PERMIT ? "permit" : "deny");
1408 }
1409
1410 return ret;
1411 #undef FILTER_EXIST_WARN
1412 }
1413
1414 static enum filter_type bgp_output_filter(struct peer *peer,
1415 const struct prefix *p,
1416 struct attr *attr, afi_t afi,
1417 safi_t safi)
1418 {
1419 struct bgp_filter *filter;
1420 enum filter_type ret = FILTER_PERMIT;
1421
1422 filter = &peer->filter[afi][safi];
1423
1424 #define FILTER_EXIST_WARN(F, f, filter) \
1425 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
1426 zlog_debug("%s: Could not find configured output %s-list %s!", \
1427 peer->host, #f, F##_OUT_NAME(filter));
1428
1429 if (DISTRIBUTE_OUT_NAME(filter)) {
1430 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
1431
1432 if (access_list_apply(DISTRIBUTE_OUT(filter), p)
1433 == FILTER_DENY) {
1434 ret = FILTER_DENY;
1435 goto done;
1436 }
1437 }
1438
1439 if (PREFIX_LIST_OUT_NAME(filter)) {
1440 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
1441
1442 if (prefix_list_apply(PREFIX_LIST_OUT(filter), p)
1443 == PREFIX_DENY) {
1444 ret = FILTER_DENY;
1445 goto done;
1446 }
1447 }
1448
1449 if (FILTER_LIST_OUT_NAME(filter)) {
1450 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
1451
1452 if (as_list_apply(FILTER_LIST_OUT(filter), attr->aspath)
1453 == AS_FILTER_DENY) {
1454 ret = FILTER_DENY;
1455 goto done;
1456 }
1457 }
1458
1459 if (frrtrace_enabled(frr_bgp, output_filter)) {
1460 char pfxprint[PREFIX2STR_BUFFER];
1461
1462 prefix2str(p, pfxprint, sizeof(pfxprint));
1463 frrtrace(5, frr_bgp, output_filter, peer, pfxprint, afi, safi,
1464 ret == FILTER_PERMIT ? "permit" : "deny");
1465 }
1466
1467 done:
1468 return ret;
1469 #undef FILTER_EXIST_WARN
1470 }
1471
1472 /* If community attribute includes no_export then return 1. */
1473 static bool bgp_community_filter(struct peer *peer, struct attr *attr)
1474 {
1475 if (attr->community) {
1476 /* NO_ADVERTISE check. */
1477 if (community_include(attr->community, COMMUNITY_NO_ADVERTISE))
1478 return true;
1479
1480 /* NO_EXPORT check. */
1481 if (peer->sort == BGP_PEER_EBGP
1482 && community_include(attr->community, COMMUNITY_NO_EXPORT))
1483 return true;
1484
1485 /* NO_EXPORT_SUBCONFED check. */
1486 if (peer->sort == BGP_PEER_EBGP
1487 || peer->sort == BGP_PEER_CONFED)
1488 if (community_include(attr->community,
1489 COMMUNITY_NO_EXPORT_SUBCONFED))
1490 return true;
1491 }
1492 return false;
1493 }
1494
1495 /* Route reflection loop check. */
1496 static bool bgp_cluster_filter(struct peer *peer, struct attr *attr)
1497 {
1498 struct in_addr cluster_id;
1499 struct cluster_list *cluster = bgp_attr_get_cluster(attr);
1500
1501 if (cluster) {
1502 if (peer->bgp->config & BGP_CONFIG_CLUSTER_ID)
1503 cluster_id = peer->bgp->cluster_id;
1504 else
1505 cluster_id = peer->bgp->router_id;
1506
1507 if (cluster_loop_check(cluster, cluster_id))
1508 return true;
1509 }
1510 return false;
1511 }
1512
1513 static int bgp_input_modifier(struct peer *peer, const struct prefix *p,
1514 struct attr *attr, afi_t afi, safi_t safi,
1515 const char *rmap_name, mpls_label_t *label,
1516 uint32_t num_labels, struct bgp_dest *dest)
1517 {
1518 struct bgp_filter *filter;
1519 struct bgp_path_info rmap_path = { 0 };
1520 struct bgp_path_info_extra extra = { 0 };
1521 route_map_result_t ret;
1522 struct route_map *rmap = NULL;
1523
1524 filter = &peer->filter[afi][safi];
1525
1526 /* Apply default weight value. */
1527 if (peer->weight[afi][safi])
1528 attr->weight = peer->weight[afi][safi];
1529
1530 if (rmap_name) {
1531 rmap = route_map_lookup_by_name(rmap_name);
1532
1533 if (rmap == NULL)
1534 return RMAP_DENY;
1535 } else {
1536 if (ROUTE_MAP_IN_NAME(filter)) {
1537 rmap = ROUTE_MAP_IN(filter);
1538
1539 if (rmap == NULL)
1540 return RMAP_DENY;
1541 }
1542 }
1543
1544 /* Route map apply. */
1545 if (rmap) {
1546 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
1547 /* Duplicate current value to new strucutre for modification. */
1548 rmap_path.peer = peer;
1549 rmap_path.attr = attr;
1550 rmap_path.extra = &extra;
1551 rmap_path.net = dest;
1552
1553 extra.num_labels = num_labels;
1554 if (label && num_labels && num_labels <= BGP_MAX_LABELS)
1555 memcpy(extra.label, label,
1556 num_labels * sizeof(mpls_label_t));
1557
1558 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN);
1559
1560 /* Apply BGP route map to the attribute. */
1561 ret = route_map_apply(rmap, p, &rmap_path);
1562
1563 peer->rmap_type = 0;
1564
1565 if (ret == RMAP_DENYMATCH)
1566 return RMAP_DENY;
1567 }
1568 return RMAP_PERMIT;
1569 }
1570
1571 static int bgp_output_modifier(struct peer *peer, const struct prefix *p,
1572 struct attr *attr, afi_t afi, safi_t safi,
1573 const char *rmap_name)
1574 {
1575 struct bgp_path_info rmap_path;
1576 route_map_result_t ret;
1577 struct route_map *rmap = NULL;
1578 uint8_t rmap_type;
1579
1580 /*
1581 * So if we get to this point and have no rmap_name
1582 * we want to just show the output as it currently
1583 * exists.
1584 */
1585 if (!rmap_name)
1586 return RMAP_PERMIT;
1587
1588 /* Apply default weight value. */
1589 if (peer->weight[afi][safi])
1590 attr->weight = peer->weight[afi][safi];
1591
1592 rmap = route_map_lookup_by_name(rmap_name);
1593
1594 /*
1595 * If we have a route map name and we do not find
1596 * the routemap that means we have an implicit
1597 * deny.
1598 */
1599 if (rmap == NULL)
1600 return RMAP_DENY;
1601
1602 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
1603 /* Route map apply. */
1604 /* Duplicate current value to new strucutre for modification. */
1605 rmap_path.peer = peer;
1606 rmap_path.attr = attr;
1607
1608 rmap_type = peer->rmap_type;
1609 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
1610
1611 /* Apply BGP route map to the attribute. */
1612 ret = route_map_apply(rmap, p, &rmap_path);
1613
1614 peer->rmap_type = rmap_type;
1615
1616 if (ret == RMAP_DENYMATCH)
1617 /*
1618 * caller has multiple error paths with bgp_attr_flush()
1619 */
1620 return RMAP_DENY;
1621
1622 return RMAP_PERMIT;
1623 }
1624
1625 /* If this is an EBGP peer with remove-private-AS */
1626 static void bgp_peer_remove_private_as(struct bgp *bgp, afi_t afi, safi_t safi,
1627 struct peer *peer, struct attr *attr)
1628 {
1629 if (peer->sort == BGP_PEER_EBGP
1630 && (peer_af_flag_check(peer, afi, safi,
1631 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1632 || peer_af_flag_check(peer, afi, safi,
1633 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)
1634 || peer_af_flag_check(peer, afi, safi,
1635 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)
1636 || peer_af_flag_check(peer, afi, safi,
1637 PEER_FLAG_REMOVE_PRIVATE_AS))) {
1638 // Take action on the entire aspath
1639 if (peer_af_flag_check(peer, afi, safi,
1640 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1641 || peer_af_flag_check(peer, afi, safi,
1642 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)) {
1643 if (peer_af_flag_check(
1644 peer, afi, safi,
1645 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE))
1646 attr->aspath = aspath_replace_private_asns(
1647 attr->aspath, bgp->as, peer->as);
1648
1649 // The entire aspath consists of private ASNs so create
1650 // an empty aspath
1651 else if (aspath_private_as_check(attr->aspath))
1652 attr->aspath = aspath_empty_get();
1653
1654 // There are some public and some private ASNs, remove
1655 // the private ASNs
1656 else
1657 attr->aspath = aspath_remove_private_asns(
1658 attr->aspath, peer->as);
1659 }
1660
1661 // 'all' was not specified so the entire aspath must be private
1662 // ASNs
1663 // for us to do anything
1664 else if (aspath_private_as_check(attr->aspath)) {
1665 if (peer_af_flag_check(
1666 peer, afi, safi,
1667 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE))
1668 attr->aspath = aspath_replace_private_asns(
1669 attr->aspath, bgp->as, peer->as);
1670 else
1671 attr->aspath = aspath_empty_get();
1672 }
1673 }
1674 }
1675
1676 /* If this is an EBGP peer with as-override */
1677 static void bgp_peer_as_override(struct bgp *bgp, afi_t afi, safi_t safi,
1678 struct peer *peer, struct attr *attr)
1679 {
1680 if (peer->sort == BGP_PEER_EBGP
1681 && peer_af_flag_check(peer, afi, safi, PEER_FLAG_AS_OVERRIDE)) {
1682 if (aspath_single_asn_check(attr->aspath, peer->as))
1683 attr->aspath = aspath_replace_specific_asn(
1684 attr->aspath, peer->as, bgp->as);
1685 }
1686 }
1687
1688 void bgp_attr_add_gshut_community(struct attr *attr)
1689 {
1690 struct community *old;
1691 struct community *new;
1692 struct community *merge;
1693 struct community *gshut;
1694
1695 old = attr->community;
1696 gshut = community_str2com("graceful-shutdown");
1697
1698 assert(gshut);
1699
1700 if (old) {
1701 merge = community_merge(community_dup(old), gshut);
1702
1703 if (old->refcnt == 0)
1704 community_free(&old);
1705
1706 new = community_uniq_sort(merge);
1707 community_free(&merge);
1708 } else {
1709 new = community_dup(gshut);
1710 }
1711
1712 community_free(&gshut);
1713 attr->community = new;
1714 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
1715
1716 /* When we add the graceful-shutdown community we must also
1717 * lower the local-preference */
1718 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1719 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
1720 }
1721
1722
1723 /* Notify BGP Conditional advertisement scanner process. */
1724 void bgp_notify_conditional_adv_scanner(struct update_subgroup *subgrp)
1725 {
1726 struct peer *temp_peer;
1727 struct peer *peer = SUBGRP_PEER(subgrp);
1728 struct listnode *temp_node, *temp_nnode = NULL;
1729 afi_t afi = SUBGRP_AFI(subgrp);
1730 safi_t safi = SUBGRP_SAFI(subgrp);
1731 struct bgp *bgp = SUBGRP_INST(subgrp);
1732 struct bgp_filter *filter = &peer->filter[afi][safi];
1733
1734 if (!ADVERTISE_MAP_NAME(filter))
1735 return;
1736
1737 for (ALL_LIST_ELEMENTS(bgp->peer, temp_node, temp_nnode, temp_peer)) {
1738 if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
1739 continue;
1740
1741 if (peer != temp_peer)
1742 continue;
1743
1744 temp_peer->advmap_table_change = true;
1745 break;
1746 }
1747 }
1748
1749
1750 void subgroup_announce_reset_nhop(uint8_t family, struct attr *attr)
1751 {
1752 if (family == AF_INET) {
1753 attr->nexthop.s_addr = INADDR_ANY;
1754 attr->mp_nexthop_global_in.s_addr = INADDR_ANY;
1755 }
1756 if (family == AF_INET6)
1757 memset(&attr->mp_nexthop_global, 0, IPV6_MAX_BYTELEN);
1758 if (family == AF_EVPN)
1759 memset(&attr->mp_nexthop_global_in, 0, BGP_ATTR_NHLEN_IPV4);
1760 }
1761
1762 bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
1763 struct update_subgroup *subgrp,
1764 const struct prefix *p, struct attr *attr,
1765 bool skip_rmap_check)
1766 {
1767 struct bgp_filter *filter;
1768 struct peer *from;
1769 struct peer *peer;
1770 struct peer *onlypeer;
1771 struct bgp *bgp;
1772 struct attr *piattr;
1773 route_map_result_t ret;
1774 int transparent;
1775 int reflect;
1776 afi_t afi;
1777 safi_t safi;
1778 int samepeer_safe = 0; /* for synthetic mplsvpns routes */
1779 bool nh_reset = false;
1780 uint64_t cum_bw;
1781
1782 if (DISABLE_BGP_ANNOUNCE)
1783 return false;
1784
1785 afi = SUBGRP_AFI(subgrp);
1786 safi = SUBGRP_SAFI(subgrp);
1787 peer = SUBGRP_PEER(subgrp);
1788 onlypeer = NULL;
1789 if (CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL))
1790 onlypeer = SUBGRP_PFIRST(subgrp)->peer;
1791
1792 from = pi->peer;
1793 filter = &peer->filter[afi][safi];
1794 bgp = SUBGRP_INST(subgrp);
1795 piattr = bgp_path_info_mpath_count(pi) ? bgp_path_info_mpath_attr(pi)
1796 : pi->attr;
1797
1798 #ifdef ENABLE_BGP_VNC
1799 if (((afi == AFI_IP) || (afi == AFI_IP6)) && (safi == SAFI_MPLS_VPN)
1800 && ((pi->type == ZEBRA_ROUTE_BGP_DIRECT)
1801 || (pi->type == ZEBRA_ROUTE_BGP_DIRECT_EXT))) {
1802
1803 /*
1804 * direct and direct_ext type routes originate internally even
1805 * though they can have peer pointers that reference other
1806 * systems
1807 */
1808 zlog_debug("%s: pfx %pFX bgp_direct->vpn route peer safe",
1809 __func__, p);
1810 samepeer_safe = 1;
1811 }
1812 #endif
1813
1814 if (((afi == AFI_IP) || (afi == AFI_IP6))
1815 && ((safi == SAFI_MPLS_VPN) || (safi == SAFI_UNICAST))
1816 && (pi->type == ZEBRA_ROUTE_BGP)
1817 && (pi->sub_type == BGP_ROUTE_IMPORTED)) {
1818
1819 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1820
1821 samepeer_safe = 1;
1822 }
1823
1824 /* With addpath we may be asked to TX all kinds of paths so make sure
1825 * pi is valid */
1826 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID)
1827 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)
1828 || CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
1829 return false;
1830 }
1831
1832 /* If this is not the bestpath then check to see if there is an enabled
1833 * addpath
1834 * feature that requires us to advertise it */
1835 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
1836 if (!bgp_addpath_tx_path(peer->addpath_type[afi][safi], pi)) {
1837 return false;
1838 }
1839 }
1840
1841 /* Aggregate-address suppress check. */
1842 if (bgp_path_suppressed(pi) && !UNSUPPRESS_MAP_NAME(filter))
1843 return false;
1844
1845 /*
1846 * If we are doing VRF 2 VRF leaking via the import
1847 * statement, we want to prevent the route going
1848 * off box as that the RT and RD created are localy
1849 * significant and globaly useless.
1850 */
1851 if (safi == SAFI_MPLS_VPN && pi->extra && pi->extra->num_labels
1852 && pi->extra->label[0] == BGP_PREVENT_VRF_2_VRF_LEAK)
1853 return false;
1854
1855 /* If it's labeled safi, make sure the route has a valid label. */
1856 if (safi == SAFI_LABELED_UNICAST) {
1857 mpls_label_t label = bgp_adv_label(dest, pi, peer, afi, safi);
1858 if (!bgp_is_valid_label(&label)) {
1859 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1860 zlog_debug("u%" PRIu64 ":s%" PRIu64
1861 " %pFX is filtered - no label (%p)",
1862 subgrp->update_group->id, subgrp->id,
1863 p, &label);
1864 return false;
1865 }
1866 }
1867
1868 /* Do not send back route to sender. */
1869 if (onlypeer && from == onlypeer) {
1870 return false;
1871 }
1872
1873 /* Do not send the default route in the BGP table if the neighbor is
1874 * configured for default-originate */
1875 if (CHECK_FLAG(peer->af_flags[afi][safi],
1876 PEER_FLAG_DEFAULT_ORIGINATE)) {
1877 if (p->family == AF_INET && p->u.prefix4.s_addr == INADDR_ANY)
1878 return false;
1879 else if (p->family == AF_INET6 && p->prefixlen == 0)
1880 return false;
1881 }
1882
1883 /* Transparency check. */
1884 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1885 && CHECK_FLAG(from->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1886 transparent = 1;
1887 else
1888 transparent = 0;
1889
1890 /* If community is not disabled check the no-export and local. */
1891 if (!transparent && bgp_community_filter(peer, piattr)) {
1892 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1893 zlog_debug("%s: community filter check fail for %pFX",
1894 __func__, p);
1895 return false;
1896 }
1897
1898 /* If the attribute has originator-id and it is same as remote
1899 peer's id. */
1900 if (onlypeer && piattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
1901 && (IPV4_ADDR_SAME(&onlypeer->remote_id, &piattr->originator_id))) {
1902 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1903 zlog_debug(
1904 "%s [Update:SEND] %pFX originator-id is same as remote router-id",
1905 onlypeer->host, p);
1906 return false;
1907 }
1908
1909 /* ORF prefix-list filter check */
1910 if (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV)
1911 && (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)
1912 || CHECK_FLAG(peer->af_cap[afi][safi],
1913 PEER_CAP_ORF_PREFIX_SM_OLD_RCV)))
1914 if (peer->orf_plist[afi][safi]) {
1915 if (prefix_list_apply(peer->orf_plist[afi][safi], p)
1916 == PREFIX_DENY) {
1917 if (bgp_debug_update(NULL, p,
1918 subgrp->update_group, 0))
1919 zlog_debug(
1920 "%s [Update:SEND] %pFX is filtered via ORF",
1921 peer->host, p);
1922 return false;
1923 }
1924 }
1925
1926 /* Output filter check. */
1927 if (bgp_output_filter(peer, p, piattr, afi, safi) == FILTER_DENY) {
1928 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1929 zlog_debug("%s [Update:SEND] %pFX is filtered",
1930 peer->host, p);
1931 return false;
1932 }
1933
1934 /* AS path loop check. */
1935 if (onlypeer && onlypeer->as_path_loop_detection
1936 && aspath_loop_check(piattr->aspath, onlypeer->as)) {
1937 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1938 zlog_debug(
1939 "%s [Update:SEND] suppress announcement to peer AS %u that is part of AS path.",
1940 onlypeer->host, onlypeer->as);
1941 return false;
1942 }
1943
1944 /* If we're a CONFED we need to loop check the CONFED ID too */
1945 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
1946 if (aspath_loop_check(piattr->aspath, bgp->confed_id)) {
1947 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1948 zlog_debug(
1949 "%s [Update:SEND] suppress announcement to peer AS %u is AS path.",
1950 peer->host, bgp->confed_id);
1951 return false;
1952 }
1953 }
1954
1955 /* Route-Reflect check. */
1956 if (from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
1957 reflect = 1;
1958 else
1959 reflect = 0;
1960
1961 /* IBGP reflection check. */
1962 if (reflect && !samepeer_safe) {
1963 /* A route from a Client peer. */
1964 if (CHECK_FLAG(from->af_flags[afi][safi],
1965 PEER_FLAG_REFLECTOR_CLIENT)) {
1966 /* Reflect to all the Non-Client peers and also to the
1967 Client peers other than the originator. Originator
1968 check
1969 is already done. So there is noting to do. */
1970 /* no bgp client-to-client reflection check. */
1971 if (CHECK_FLAG(bgp->flags,
1972 BGP_FLAG_NO_CLIENT_TO_CLIENT))
1973 if (CHECK_FLAG(peer->af_flags[afi][safi],
1974 PEER_FLAG_REFLECTOR_CLIENT))
1975 return false;
1976 } else {
1977 /* A route from a Non-client peer. Reflect to all other
1978 clients. */
1979 if (!CHECK_FLAG(peer->af_flags[afi][safi],
1980 PEER_FLAG_REFLECTOR_CLIENT))
1981 return false;
1982 }
1983 }
1984
1985 /* For modify attribute, copy it to temporary structure. */
1986 *attr = *piattr;
1987
1988 /* If local-preference is not set. */
1989 if ((peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED)
1990 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)))) {
1991 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1992 attr->local_pref = bgp->default_local_pref;
1993 }
1994
1995 /* If originator-id is not set and the route is to be reflected,
1996 set the originator id */
1997 if (reflect
1998 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)))) {
1999 IPV4_ADDR_COPY(&(attr->originator_id), &(from->remote_id));
2000 SET_FLAG(attr->flag, BGP_ATTR_ORIGINATOR_ID);
2001 }
2002
2003 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
2004 */
2005 if (peer->sort == BGP_PEER_EBGP
2006 && attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
2007 if (from != bgp->peer_self && !transparent
2008 && !CHECK_FLAG(peer->af_flags[afi][safi],
2009 PEER_FLAG_MED_UNCHANGED))
2010 attr->flag &=
2011 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC));
2012 }
2013
2014 /* Since the nexthop attribute can vary per peer, it is not explicitly
2015 * set
2016 * in announce check, only certain flags and length (or number of
2017 * nexthops
2018 * -- for IPv6/MP_REACH) are set here in order to guide the update
2019 * formation
2020 * code in setting the nexthop(s) on a per peer basis in
2021 * reformat_peer().
2022 * Typically, the source nexthop in the attribute is preserved but in
2023 * the
2024 * scenarios where we know it will always be overwritten, we reset the
2025 * nexthop to "0" in an attempt to achieve better Update packing. An
2026 * example of this is when a prefix from each of 2 IBGP peers needs to
2027 * be
2028 * announced to an EBGP peer (and they have the same attributes barring
2029 * their nexthop).
2030 */
2031 if (reflect)
2032 SET_FLAG(attr->rmap_change_flags, BATTR_REFLECTED);
2033
2034 #define NEXTHOP_IS_V6 \
2035 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
2036 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
2037 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
2038 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
2039
2040 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
2041 * if
2042 * the peer (group) is configured to receive link-local nexthop
2043 * unchanged
2044 * and it is available in the prefix OR we're not reflecting the route,
2045 * link-local nexthop address is valid and
2046 * the peer (group) to whom we're going to announce is on a shared
2047 * network
2048 * and this is either a self-originated route or the peer is EBGP.
2049 * By checking if nexthop LL address is valid we are sure that
2050 * we do not announce LL address as `::`.
2051 */
2052 if (NEXTHOP_IS_V6) {
2053 attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
2054 if ((CHECK_FLAG(peer->af_flags[afi][safi],
2055 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
2056 && IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_local))
2057 || (!reflect
2058 && IN6_IS_ADDR_LINKLOCAL(&peer->nexthop.v6_local)
2059 && peer->shared_network
2060 && (from == bgp->peer_self
2061 || peer->sort == BGP_PEER_EBGP))) {
2062 attr->mp_nexthop_len =
2063 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
2064 }
2065
2066 /* Clear off link-local nexthop in source, whenever it is not
2067 * needed to
2068 * ensure more prefixes share the same attribute for
2069 * announcement.
2070 */
2071 if (!(CHECK_FLAG(peer->af_flags[afi][safi],
2072 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)))
2073 memset(&attr->mp_nexthop_local, 0, IPV6_MAX_BYTELEN);
2074 }
2075
2076 bgp_peer_remove_private_as(bgp, afi, safi, peer, attr);
2077 bgp_peer_as_override(bgp, afi, safi, peer, attr);
2078
2079 /* Route map & unsuppress-map apply. */
2080 if (!skip_rmap_check
2081 && (ROUTE_MAP_OUT_NAME(filter) || bgp_path_suppressed(pi))) {
2082 struct bgp_path_info rmap_path = {0};
2083 struct bgp_path_info_extra dummy_rmap_path_extra = {0};
2084 struct attr dummy_attr = {0};
2085
2086 /* Fill temp path_info */
2087 prep_for_rmap_apply(&rmap_path, &dummy_rmap_path_extra, dest,
2088 pi, peer, attr);
2089
2090 /* don't confuse inbound and outbound setting */
2091 RESET_FLAG(attr->rmap_change_flags);
2092
2093 /*
2094 * The route reflector is not allowed to modify the attributes
2095 * of the reflected IBGP routes unless explicitly allowed.
2096 */
2097 if ((from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
2098 && !CHECK_FLAG(bgp->flags,
2099 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) {
2100 dummy_attr = *attr;
2101 rmap_path.attr = &dummy_attr;
2102 }
2103
2104 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
2105
2106 if (bgp_path_suppressed(pi))
2107 ret = route_map_apply(UNSUPPRESS_MAP(filter), p,
2108 &rmap_path);
2109 else
2110 ret = route_map_apply(ROUTE_MAP_OUT(filter), p,
2111 &rmap_path);
2112
2113 peer->rmap_type = 0;
2114
2115 if (ret == RMAP_DENYMATCH) {
2116 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2117 zlog_debug(
2118 "%s [Update:SEND] %pFX is filtered by route-map",
2119 peer->host, p);
2120
2121 bgp_attr_flush(attr);
2122 return false;
2123 }
2124 }
2125
2126 /* RFC 8212 to prevent route leaks.
2127 * This specification intends to improve this situation by requiring the
2128 * explicit configuration of both BGP Import and Export Policies for any
2129 * External BGP (EBGP) session such as customers, peers, or
2130 * confederation boundaries for all enabled address families. Through
2131 * codification of the aforementioned requirement, operators will
2132 * benefit from consistent behavior across different BGP
2133 * implementations.
2134 */
2135 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
2136 if (!bgp_outbound_policy_exists(peer, filter))
2137 return false;
2138
2139 /* draft-ietf-idr-deprecate-as-set-confed-set
2140 * Filter routes having AS_SET or AS_CONFED_SET in the path.
2141 * Eventually, This document (if approved) updates RFC 4271
2142 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
2143 * and obsoletes RFC 6472.
2144 */
2145 if (peer->bgp->reject_as_sets)
2146 if (aspath_check_as_sets(attr->aspath))
2147 return false;
2148
2149 /* Codification of AS 0 Processing */
2150 if (aspath_check_as_zero(attr->aspath))
2151 return false;
2152
2153 if (bgp_in_graceful_shutdown(bgp)) {
2154 if (peer->sort == BGP_PEER_IBGP
2155 || peer->sort == BGP_PEER_CONFED) {
2156 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
2157 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
2158 } else {
2159 bgp_attr_add_gshut_community(attr);
2160 }
2161 }
2162
2163 /* After route-map has been applied, we check to see if the nexthop to
2164 * be carried in the attribute (that is used for the announcement) can
2165 * be cleared off or not. We do this in all cases where we would be
2166 * setting the nexthop to "ourselves". For IPv6, we only need to
2167 * consider
2168 * the global nexthop here; the link-local nexthop would have been
2169 * cleared
2170 * already, and if not, it is required by the update formation code.
2171 * Also see earlier comments in this function.
2172 */
2173 /*
2174 * If route-map has performed some operation on the nexthop or the peer
2175 * configuration says to pass it unchanged, we cannot reset the nexthop
2176 * here, so only attempt to do it if these aren't true. Note that the
2177 * route-map handler itself might have cleared the nexthop, if for
2178 * example,
2179 * it is configured as 'peer-address'.
2180 */
2181 if (!bgp_rmap_nhop_changed(attr->rmap_change_flags,
2182 piattr->rmap_change_flags)
2183 && !transparent
2184 && !CHECK_FLAG(peer->af_flags[afi][safi],
2185 PEER_FLAG_NEXTHOP_UNCHANGED)) {
2186 /* We can reset the nexthop, if setting (or forcing) it to
2187 * 'self' */
2188 if (CHECK_FLAG(peer->af_flags[afi][safi],
2189 PEER_FLAG_NEXTHOP_SELF)
2190 || CHECK_FLAG(peer->af_flags[afi][safi],
2191 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
2192 if (!reflect
2193 || CHECK_FLAG(peer->af_flags[afi][safi],
2194 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
2195 subgroup_announce_reset_nhop(
2196 (peer_cap_enhe(peer, afi, safi)
2197 ? AF_INET6
2198 : p->family),
2199 attr);
2200 nh_reset = true;
2201 }
2202 } else if (peer->sort == BGP_PEER_EBGP) {
2203 /* Can also reset the nexthop if announcing to EBGP, but
2204 * only if
2205 * no peer in the subgroup is on a shared subnet.
2206 * Note: 3rd party nexthop currently implemented for
2207 * IPv4 only.
2208 */
2209 if ((p->family == AF_INET) &&
2210 (!bgp_subgrp_multiaccess_check_v4(
2211 piattr->nexthop,
2212 subgrp, from))) {
2213 subgroup_announce_reset_nhop(
2214 (peer_cap_enhe(peer, afi, safi)
2215 ? AF_INET6
2216 : p->family),
2217 attr);
2218 nh_reset = true;
2219 }
2220
2221 if ((p->family == AF_INET6) &&
2222 (!bgp_subgrp_multiaccess_check_v6(
2223 piattr->mp_nexthop_global,
2224 subgrp, from))) {
2225 subgroup_announce_reset_nhop(
2226 (peer_cap_enhe(peer, afi, safi)
2227 ? AF_INET6
2228 : p->family),
2229 attr);
2230 nh_reset = true;
2231 }
2232
2233
2234
2235 } else if (CHECK_FLAG(pi->flags, BGP_PATH_ANNC_NH_SELF)) {
2236 /*
2237 * This flag is used for leaked vpn-vrf routes
2238 */
2239 int family = p->family;
2240
2241 if (peer_cap_enhe(peer, afi, safi))
2242 family = AF_INET6;
2243
2244 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2245 zlog_debug(
2246 "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
2247 __func__, family2str(family));
2248 subgroup_announce_reset_nhop(family, attr);
2249 nh_reset = true;
2250 }
2251 }
2252
2253 /* If IPv6/MP and nexthop does not have any override and happens
2254 * to
2255 * be a link-local address, reset it so that we don't pass along
2256 * the
2257 * source's link-local IPv6 address to recipients who may not be
2258 * on
2259 * the same interface.
2260 */
2261 if (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi)) {
2262 if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global)) {
2263 subgroup_announce_reset_nhop(AF_INET6, attr);
2264 nh_reset = true;
2265 }
2266 }
2267
2268 /*
2269 * When the next hop is set to ourselves, if all multipaths have
2270 * link-bandwidth announce the cumulative bandwidth as that makes
2271 * the most sense. However, don't modify if the link-bandwidth has
2272 * been explicitly set by user policy.
2273 */
2274 if (nh_reset &&
2275 bgp_path_info_mpath_chkwtd(bgp, pi) &&
2276 (cum_bw = bgp_path_info_mpath_cumbw(pi)) != 0 &&
2277 !CHECK_FLAG(attr->rmap_change_flags, BATTR_RMAP_LINK_BW_SET))
2278 attr->ecommunity = ecommunity_replace_linkbw(
2279 bgp->as, attr->ecommunity, cum_bw);
2280
2281 return true;
2282 }
2283
2284 static int bgp_route_select_timer_expire(struct thread *thread)
2285 {
2286 struct afi_safi_info *info;
2287 afi_t afi;
2288 safi_t safi;
2289 struct bgp *bgp;
2290
2291 info = THREAD_ARG(thread);
2292 afi = info->afi;
2293 safi = info->safi;
2294 bgp = info->bgp;
2295
2296 if (BGP_DEBUG(update, UPDATE_OUT))
2297 zlog_debug("afi %d, safi %d : route select timer expired", afi,
2298 safi);
2299
2300 bgp->gr_info[afi][safi].t_route_select = NULL;
2301
2302 XFREE(MTYPE_TMP, info);
2303
2304 /* Best path selection */
2305 return bgp_best_path_select_defer(bgp, afi, safi);
2306 }
2307
2308 void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
2309 struct bgp_maxpaths_cfg *mpath_cfg,
2310 struct bgp_path_info_pair *result, afi_t afi,
2311 safi_t safi)
2312 {
2313 struct bgp_path_info *new_select;
2314 struct bgp_path_info *old_select;
2315 struct bgp_path_info *pi;
2316 struct bgp_path_info *pi1;
2317 struct bgp_path_info *pi2;
2318 struct bgp_path_info *nextpi = NULL;
2319 int paths_eq, do_mpath, debug;
2320 struct list mp_list;
2321 char pfx_buf[PREFIX2STR_BUFFER];
2322 char path_buf[PATH_ADDPATH_STR_BUFFER];
2323
2324 bgp_mp_list_init(&mp_list);
2325 do_mpath =
2326 (mpath_cfg->maxpaths_ebgp > 1 || mpath_cfg->maxpaths_ibgp > 1);
2327
2328 debug = bgp_debug_bestpath(dest);
2329
2330 if (debug)
2331 prefix2str(bgp_dest_get_prefix(dest), pfx_buf, sizeof(pfx_buf));
2332
2333 dest->reason = bgp_path_selection_none;
2334 /* bgp deterministic-med */
2335 new_select = NULL;
2336 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)) {
2337
2338 /* Clear BGP_PATH_DMED_SELECTED for all paths */
2339 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
2340 pi1 = pi1->next)
2341 bgp_path_info_unset_flag(dest, pi1,
2342 BGP_PATH_DMED_SELECTED);
2343
2344 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
2345 pi1 = pi1->next) {
2346 if (CHECK_FLAG(pi1->flags, BGP_PATH_DMED_CHECK))
2347 continue;
2348 if (BGP_PATH_HOLDDOWN(pi1))
2349 continue;
2350 if (pi1->peer != bgp->peer_self)
2351 if (!peer_established(pi1->peer))
2352 continue;
2353
2354 new_select = pi1;
2355 if (pi1->next) {
2356 for (pi2 = pi1->next; pi2; pi2 = pi2->next) {
2357 if (CHECK_FLAG(pi2->flags,
2358 BGP_PATH_DMED_CHECK))
2359 continue;
2360 if (BGP_PATH_HOLDDOWN(pi2))
2361 continue;
2362 if (pi2->peer != bgp->peer_self
2363 && !CHECK_FLAG(
2364 pi2->peer->sflags,
2365 PEER_STATUS_NSF_WAIT))
2366 if (pi2->peer->status
2367 != Established)
2368 continue;
2369
2370 if (!aspath_cmp_left(pi1->attr->aspath,
2371 pi2->attr->aspath)
2372 && !aspath_cmp_left_confed(
2373 pi1->attr->aspath,
2374 pi2->attr->aspath))
2375 continue;
2376
2377 if (bgp_path_info_cmp(
2378 bgp, pi2, new_select,
2379 &paths_eq, mpath_cfg, debug,
2380 pfx_buf, afi, safi,
2381 &dest->reason)) {
2382 bgp_path_info_unset_flag(
2383 dest, new_select,
2384 BGP_PATH_DMED_SELECTED);
2385 new_select = pi2;
2386 }
2387
2388 bgp_path_info_set_flag(
2389 dest, pi2, BGP_PATH_DMED_CHECK);
2390 }
2391 }
2392 bgp_path_info_set_flag(dest, new_select,
2393 BGP_PATH_DMED_CHECK);
2394 bgp_path_info_set_flag(dest, new_select,
2395 BGP_PATH_DMED_SELECTED);
2396
2397 if (debug) {
2398 bgp_path_info_path_with_addpath_rx_str(
2399 new_select, path_buf, sizeof(path_buf));
2400 zlog_debug(
2401 "%pBD: %s is the bestpath from AS %u",
2402 dest, path_buf,
2403 aspath_get_first_as(
2404 new_select->attr->aspath));
2405 }
2406 }
2407 }
2408
2409 /* Check old selected route and new selected route. */
2410 old_select = NULL;
2411 new_select = NULL;
2412 for (pi = bgp_dest_get_bgp_path_info(dest);
2413 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
2414 enum bgp_path_selection_reason reason;
2415
2416 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
2417 old_select = pi;
2418
2419 if (BGP_PATH_HOLDDOWN(pi)) {
2420 /* reap REMOVED routes, if needs be
2421 * selected route must stay for a while longer though
2422 */
2423 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
2424 && (pi != old_select))
2425 bgp_path_info_reap(dest, pi);
2426
2427 if (debug)
2428 zlog_debug("%s: pi %p in holddown", __func__,
2429 pi);
2430
2431 continue;
2432 }
2433
2434 if (pi->peer && pi->peer != bgp->peer_self
2435 && !CHECK_FLAG(pi->peer->sflags, PEER_STATUS_NSF_WAIT))
2436 if (!peer_established(pi->peer)) {
2437
2438 if (debug)
2439 zlog_debug(
2440 "%s: pi %p non self peer %s not estab state",
2441 __func__, pi, pi->peer->host);
2442
2443 continue;
2444 }
2445
2446 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)
2447 && (!CHECK_FLAG(pi->flags, BGP_PATH_DMED_SELECTED))) {
2448 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
2449 if (debug)
2450 zlog_debug("%s: pi %p dmed", __func__, pi);
2451 continue;
2452 }
2453
2454 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
2455
2456 reason = dest->reason;
2457 if (bgp_path_info_cmp(bgp, pi, new_select, &paths_eq, mpath_cfg,
2458 debug, pfx_buf, afi, safi,
2459 &dest->reason)) {
2460 if (new_select == NULL &&
2461 reason != bgp_path_selection_none)
2462 dest->reason = reason;
2463 new_select = pi;
2464 }
2465 }
2466
2467 /* Now that we know which path is the bestpath see if any of the other
2468 * paths
2469 * qualify as multipaths
2470 */
2471 if (debug) {
2472 if (new_select)
2473 bgp_path_info_path_with_addpath_rx_str(
2474 new_select, path_buf, sizeof(path_buf));
2475 else
2476 snprintf(path_buf, sizeof(path_buf), "NONE");
2477 zlog_debug(
2478 "%pBD: After path selection, newbest is %s oldbest was %s",
2479 dest, path_buf,
2480 old_select ? old_select->peer->host : "NONE");
2481 }
2482
2483 if (do_mpath && new_select) {
2484 for (pi = bgp_dest_get_bgp_path_info(dest);
2485 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
2486
2487 if (debug)
2488 bgp_path_info_path_with_addpath_rx_str(
2489 pi, path_buf, sizeof(path_buf));
2490
2491 if (pi == new_select) {
2492 if (debug)
2493 zlog_debug(
2494 "%pBD: %s is the bestpath, add to the multipath list",
2495 dest, path_buf);
2496 bgp_mp_list_add(&mp_list, pi);
2497 continue;
2498 }
2499
2500 if (BGP_PATH_HOLDDOWN(pi))
2501 continue;
2502
2503 if (pi->peer && pi->peer != bgp->peer_self
2504 && !CHECK_FLAG(pi->peer->sflags,
2505 PEER_STATUS_NSF_WAIT))
2506 if (!peer_established(pi->peer))
2507 continue;
2508
2509 if (!bgp_path_info_nexthop_cmp(pi, new_select)) {
2510 if (debug)
2511 zlog_debug(
2512 "%pBD: %s has the same nexthop as the bestpath, skip it",
2513 dest, path_buf);
2514 continue;
2515 }
2516
2517 bgp_path_info_cmp(bgp, pi, new_select, &paths_eq,
2518 mpath_cfg, debug, pfx_buf, afi, safi,
2519 &dest->reason);
2520
2521 if (paths_eq) {
2522 if (debug)
2523 zlog_debug(
2524 "%pBD: %s is equivalent to the bestpath, add to the multipath list",
2525 dest, path_buf);
2526 bgp_mp_list_add(&mp_list, pi);
2527 }
2528 }
2529 }
2530
2531 bgp_path_info_mpath_update(dest, new_select, old_select, &mp_list,
2532 mpath_cfg);
2533 bgp_path_info_mpath_aggregate_update(new_select, old_select);
2534 bgp_mp_list_clear(&mp_list);
2535
2536 bgp_addpath_update_ids(bgp, dest, afi, safi);
2537
2538 result->old = old_select;
2539 result->new = new_select;
2540
2541 return;
2542 }
2543
2544 /*
2545 * A new route/change in bestpath of an existing route. Evaluate the path
2546 * for advertisement to the subgroup.
2547 */
2548 void subgroup_process_announce_selected(struct update_subgroup *subgrp,
2549 struct bgp_path_info *selected,
2550 struct bgp_dest *dest,
2551 uint32_t addpath_tx_id)
2552 {
2553 const struct prefix *p;
2554 struct peer *onlypeer;
2555 struct attr attr;
2556 afi_t afi;
2557 safi_t safi;
2558 struct bgp *bgp;
2559 bool advertise;
2560
2561 p = bgp_dest_get_prefix(dest);
2562 afi = SUBGRP_AFI(subgrp);
2563 safi = SUBGRP_SAFI(subgrp);
2564 bgp = SUBGRP_INST(subgrp);
2565 onlypeer = ((SUBGRP_PCOUNT(subgrp) == 1) ? (SUBGRP_PFIRST(subgrp))->peer
2566 : NULL);
2567
2568 if (BGP_DEBUG(update, UPDATE_OUT))
2569 zlog_debug("%s: p=%pFX, selected=%p", __func__, p, selected);
2570
2571 /* First update is deferred until ORF or ROUTE-REFRESH is received */
2572 if (onlypeer && CHECK_FLAG(onlypeer->af_sflags[afi][safi],
2573 PEER_STATUS_ORF_WAIT_REFRESH))
2574 return;
2575
2576 memset(&attr, 0, sizeof(struct attr));
2577 /* It's initialized in bgp_announce_check() */
2578
2579 /* Announcement to the subgroup. If the route is filtered withdraw it.
2580 * If BGP_NODE_FIB_INSTALL_PENDING is set and data plane install status
2581 * is pending (BGP_NODE_FIB_INSTALL_PENDING), do not advertise the
2582 * route
2583 */
2584 advertise = bgp_check_advertise(bgp, dest);
2585
2586 if (selected) {
2587 if (subgroup_announce_check(dest, selected, subgrp, p, &attr,
2588 false)) {
2589 /* Route is selected, if the route is already installed
2590 * in FIB, then it is advertised
2591 */
2592 if (advertise)
2593 bgp_adj_out_set_subgroup(dest, subgrp, &attr,
2594 selected);
2595 } else
2596 bgp_adj_out_unset_subgroup(dest, subgrp, 1,
2597 addpath_tx_id);
2598 }
2599
2600 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2601 else {
2602 bgp_adj_out_unset_subgroup(dest, subgrp, 1, addpath_tx_id);
2603 }
2604 }
2605
2606 /*
2607 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2608 * This is called at the end of route processing.
2609 */
2610 void bgp_zebra_clear_route_change_flags(struct bgp_dest *dest)
2611 {
2612 struct bgp_path_info *pi;
2613
2614 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
2615 if (BGP_PATH_HOLDDOWN(pi))
2616 continue;
2617 UNSET_FLAG(pi->flags, BGP_PATH_IGP_CHANGED);
2618 UNSET_FLAG(pi->flags, BGP_PATH_ATTR_CHANGED);
2619 }
2620 }
2621
2622 /*
2623 * Has the route changed from the RIB's perspective? This is invoked only
2624 * if the route selection returns the same best route as earlier - to
2625 * determine if we need to update zebra or not.
2626 */
2627 bool bgp_zebra_has_route_changed(struct bgp_path_info *selected)
2628 {
2629 struct bgp_path_info *mpinfo;
2630
2631 /* If this is multipath, check all selected paths for any nexthop
2632 * change or attribute change. Some attribute changes (e.g., community)
2633 * aren't of relevance to the RIB, but we'll update zebra to ensure
2634 * we handle the case of BGP nexthop change. This is the behavior
2635 * when the best path has an attribute change anyway.
2636 */
2637 if (CHECK_FLAG(selected->flags, BGP_PATH_IGP_CHANGED)
2638 || CHECK_FLAG(selected->flags, BGP_PATH_MULTIPATH_CHG)
2639 || CHECK_FLAG(selected->flags, BGP_PATH_LINK_BW_CHG))
2640 return true;
2641
2642 /*
2643 * If this is multipath, check all selected paths for any nexthop change
2644 */
2645 for (mpinfo = bgp_path_info_mpath_first(selected); mpinfo;
2646 mpinfo = bgp_path_info_mpath_next(mpinfo)) {
2647 if (CHECK_FLAG(mpinfo->flags, BGP_PATH_IGP_CHANGED)
2648 || CHECK_FLAG(mpinfo->flags, BGP_PATH_ATTR_CHANGED))
2649 return true;
2650 }
2651
2652 /* Nothing has changed from the RIB's perspective. */
2653 return false;
2654 }
2655
2656 struct bgp_process_queue {
2657 struct bgp *bgp;
2658 STAILQ_HEAD(, bgp_dest) pqueue;
2659 #define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2660 unsigned int flags;
2661 unsigned int queued;
2662 };
2663
2664 static void bgp_process_evpn_route_injection(struct bgp *bgp, afi_t afi,
2665 safi_t safi, struct bgp_dest *dest,
2666 struct bgp_path_info *new_select,
2667 struct bgp_path_info *old_select)
2668 {
2669 const struct prefix *p = bgp_dest_get_prefix(dest);
2670
2671 if ((afi != AFI_IP && afi != AFI_IP6) || (safi != SAFI_UNICAST))
2672 return;
2673
2674 if (advertise_type5_routes(bgp, afi) && new_select
2675 && is_route_injectable_into_evpn(new_select)) {
2676
2677 /* apply the route-map */
2678 if (bgp->adv_cmd_rmap[afi][safi].map) {
2679 route_map_result_t ret;
2680 struct bgp_path_info rmap_path;
2681 struct bgp_path_info_extra rmap_path_extra;
2682 struct attr dummy_attr;
2683
2684 dummy_attr = *new_select->attr;
2685
2686 /* Fill temp path_info */
2687 prep_for_rmap_apply(&rmap_path, &rmap_path_extra, dest,
2688 new_select, new_select->peer,
2689 &dummy_attr);
2690
2691 RESET_FLAG(dummy_attr.rmap_change_flags);
2692
2693 ret = route_map_apply(bgp->adv_cmd_rmap[afi][safi].map,
2694 p, &rmap_path);
2695
2696 if (ret == RMAP_DENYMATCH) {
2697 bgp_attr_flush(&dummy_attr);
2698 bgp_evpn_withdraw_type5_route(bgp, p, afi,
2699 safi);
2700 } else
2701 bgp_evpn_advertise_type5_route(
2702 bgp, p, &dummy_attr, afi, safi);
2703 } else {
2704 bgp_evpn_advertise_type5_route(bgp, p, new_select->attr,
2705 afi, safi);
2706 }
2707 } else if (advertise_type5_routes(bgp, afi) && old_select
2708 && is_route_injectable_into_evpn(old_select))
2709 bgp_evpn_withdraw_type5_route(bgp, p, afi, safi);
2710 }
2711
2712 /*
2713 * old_select = The old best path
2714 * new_select = the new best path
2715 *
2716 * if (!old_select && new_select)
2717 * We are sending new information on.
2718 *
2719 * if (old_select && new_select) {
2720 * if (new_select != old_select)
2721 * We have a new best path send a change
2722 * else
2723 * We've received a update with new attributes that needs
2724 * to be passed on.
2725 * }
2726 *
2727 * if (old_select && !new_select)
2728 * We have no eligible route that we can announce or the rn
2729 * is being removed.
2730 */
2731 static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
2732 afi_t afi, safi_t safi)
2733 {
2734 struct bgp_path_info *new_select;
2735 struct bgp_path_info *old_select;
2736 struct bgp_path_info_pair old_and_new;
2737 int debug = 0;
2738
2739 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)) {
2740 if (dest)
2741 debug = bgp_debug_bestpath(dest);
2742 if (debug)
2743 zlog_debug(
2744 "%s: bgp delete in progress, ignoring event, p=%pBD",
2745 __func__, dest);
2746 return;
2747 }
2748 /* Is it end of initial update? (after startup) */
2749 if (!dest) {
2750 quagga_timestamp(3, bgp->update_delay_zebra_resume_time,
2751 sizeof(bgp->update_delay_zebra_resume_time));
2752
2753 bgp->main_zebra_update_hold = 0;
2754 FOREACH_AFI_SAFI (afi, safi) {
2755 if (bgp_fibupd_safi(safi))
2756 bgp_zebra_announce_table(bgp, afi, safi);
2757 }
2758 bgp->main_peers_update_hold = 0;
2759
2760 bgp_start_routeadv(bgp);
2761 return;
2762 }
2763
2764 const struct prefix *p = bgp_dest_get_prefix(dest);
2765
2766 debug = bgp_debug_bestpath(dest);
2767 if (debug)
2768 zlog_debug("%s: p=%pBD afi=%s, safi=%s start", __func__, dest,
2769 afi2str(afi), safi2str(safi));
2770
2771 /* The best path calculation for the route is deferred if
2772 * BGP_NODE_SELECT_DEFER is set
2773 */
2774 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
2775 if (BGP_DEBUG(update, UPDATE_OUT))
2776 zlog_debug("SELECT_DEFER flag set for route %p", dest);
2777 return;
2778 }
2779
2780 /* Best path selection. */
2781 bgp_best_selection(bgp, dest, &bgp->maxpaths[afi][safi], &old_and_new,
2782 afi, safi);
2783 old_select = old_and_new.old;
2784 new_select = old_and_new.new;
2785
2786 /* Do we need to allocate or free labels?
2787 * Right now, since we only deal with per-prefix labels, it is not
2788 * necessary to do this upon changes to best path. Exceptions:
2789 * - label index has changed -> recalculate resulting label
2790 * - path_info sub_type changed -> switch to/from implicit-null
2791 * - no valid label (due to removed static label binding) -> get new one
2792 */
2793 if (bgp->allocate_mpls_labels[afi][safi]) {
2794 if (new_select) {
2795 if (!old_select
2796 || bgp_label_index_differs(new_select, old_select)
2797 || new_select->sub_type != old_select->sub_type
2798 || !bgp_is_valid_label(&dest->local_label)) {
2799 /* Enforced penultimate hop popping:
2800 * implicit-null for local routes, aggregate
2801 * and redistributed routes
2802 */
2803 if (new_select->sub_type == BGP_ROUTE_STATIC
2804 || new_select->sub_type
2805 == BGP_ROUTE_AGGREGATE
2806 || new_select->sub_type
2807 == BGP_ROUTE_REDISTRIBUTE) {
2808 if (CHECK_FLAG(
2809 dest->flags,
2810 BGP_NODE_REGISTERED_FOR_LABEL)
2811 || CHECK_FLAG(
2812 dest->flags,
2813 BGP_NODE_LABEL_REQUESTED))
2814 bgp_unregister_for_label(dest);
2815 label_ntop(MPLS_LABEL_IMPLICIT_NULL, 1,
2816 &dest->local_label);
2817 bgp_set_valid_label(&dest->local_label);
2818 } else
2819 bgp_register_for_label(dest,
2820 new_select);
2821 }
2822 } else if (CHECK_FLAG(dest->flags,
2823 BGP_NODE_REGISTERED_FOR_LABEL)
2824 || CHECK_FLAG(dest->flags,
2825 BGP_NODE_LABEL_REQUESTED)) {
2826 bgp_unregister_for_label(dest);
2827 }
2828 } else if (CHECK_FLAG(dest->flags, BGP_NODE_REGISTERED_FOR_LABEL)
2829 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_REQUESTED)) {
2830 bgp_unregister_for_label(dest);
2831 }
2832
2833 if (debug)
2834 zlog_debug(
2835 "%s: p=%pBD afi=%s, safi=%s, old_select=%p, new_select=%p",
2836 __func__, dest, afi2str(afi), safi2str(safi),
2837 old_select, new_select);
2838
2839 /* If best route remains the same and this is not due to user-initiated
2840 * clear, see exactly what needs to be done.
2841 */
2842 if (old_select && old_select == new_select
2843 && !CHECK_FLAG(dest->flags, BGP_NODE_USER_CLEAR)
2844 && !CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
2845 && !bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
2846 if (bgp_zebra_has_route_changed(old_select)) {
2847 #ifdef ENABLE_BGP_VNC
2848 vnc_import_bgp_add_route(bgp, p, old_select);
2849 vnc_import_bgp_exterior_add_route(bgp, p, old_select);
2850 #endif
2851 if (bgp_fibupd_safi(safi)
2852 && !bgp_option_check(BGP_OPT_NO_FIB)) {
2853
2854 if (new_select->type == ZEBRA_ROUTE_BGP
2855 && (new_select->sub_type == BGP_ROUTE_NORMAL
2856 || new_select->sub_type
2857 == BGP_ROUTE_IMPORTED))
2858
2859 bgp_zebra_announce(dest, p, old_select,
2860 bgp, afi, safi);
2861 }
2862 }
2863
2864 /* If there is a change of interest to peers, reannounce the
2865 * route. */
2866 if (CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
2867 || CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
2868 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED)) {
2869 group_announce_route(bgp, afi, safi, dest, new_select);
2870
2871 /* unicast routes must also be annouced to
2872 * labeled-unicast update-groups */
2873 if (safi == SAFI_UNICAST)
2874 group_announce_route(bgp, afi,
2875 SAFI_LABELED_UNICAST, dest,
2876 new_select);
2877
2878 UNSET_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED);
2879 UNSET_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED);
2880 }
2881
2882 /* advertise/withdraw type-5 routes */
2883 if (CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
2884 || CHECK_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG))
2885 bgp_process_evpn_route_injection(
2886 bgp, afi, safi, dest, old_select, old_select);
2887
2888 UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG);
2889 UNSET_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG);
2890 bgp_zebra_clear_route_change_flags(dest);
2891 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
2892 return;
2893 }
2894
2895 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2896 */
2897 UNSET_FLAG(dest->flags, BGP_NODE_USER_CLEAR);
2898
2899 /* bestpath has changed; bump version */
2900 if (old_select || new_select) {
2901 bgp_bump_version(dest);
2902
2903 if (!bgp->t_rmap_def_originate_eval) {
2904 bgp_lock(bgp);
2905 thread_add_timer(
2906 bm->master,
2907 update_group_refresh_default_originate_route_map,
2908 bgp, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER,
2909 &bgp->t_rmap_def_originate_eval);
2910 }
2911 }
2912
2913 if (old_select)
2914 bgp_path_info_unset_flag(dest, old_select, BGP_PATH_SELECTED);
2915 if (new_select) {
2916 if (debug)
2917 zlog_debug("%s: setting SELECTED flag", __func__);
2918 bgp_path_info_set_flag(dest, new_select, BGP_PATH_SELECTED);
2919 bgp_path_info_unset_flag(dest, new_select,
2920 BGP_PATH_ATTR_CHANGED);
2921 UNSET_FLAG(new_select->flags, BGP_PATH_MULTIPATH_CHG);
2922 UNSET_FLAG(new_select->flags, BGP_PATH_LINK_BW_CHG);
2923 }
2924
2925 #ifdef ENABLE_BGP_VNC
2926 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
2927 if (old_select != new_select) {
2928 if (old_select) {
2929 vnc_import_bgp_exterior_del_route(bgp, p,
2930 old_select);
2931 vnc_import_bgp_del_route(bgp, p, old_select);
2932 }
2933 if (new_select) {
2934 vnc_import_bgp_exterior_add_route(bgp, p,
2935 new_select);
2936 vnc_import_bgp_add_route(bgp, p, new_select);
2937 }
2938 }
2939 }
2940 #endif
2941
2942 group_announce_route(bgp, afi, safi, dest, new_select);
2943
2944 /* unicast routes must also be annouced to labeled-unicast update-groups
2945 */
2946 if (safi == SAFI_UNICAST)
2947 group_announce_route(bgp, afi, SAFI_LABELED_UNICAST, dest,
2948 new_select);
2949
2950 /* FIB update. */
2951 if (bgp_fibupd_safi(safi) && (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW)
2952 && !bgp_option_check(BGP_OPT_NO_FIB)) {
2953 if (new_select && new_select->type == ZEBRA_ROUTE_BGP
2954 && (new_select->sub_type == BGP_ROUTE_NORMAL
2955 || new_select->sub_type == BGP_ROUTE_AGGREGATE
2956 || new_select->sub_type == BGP_ROUTE_IMPORTED)) {
2957
2958 /* if this is an evpn imported type-5 prefix,
2959 * we need to withdraw the route first to clear
2960 * the nh neigh and the RMAC entry.
2961 */
2962 if (old_select &&
2963 is_route_parent_evpn(old_select))
2964 bgp_zebra_withdraw(p, old_select, bgp, safi);
2965
2966 bgp_zebra_announce(dest, p, new_select, bgp, afi, safi);
2967 } else {
2968 /* Withdraw the route from the kernel. */
2969 if (old_select && old_select->type == ZEBRA_ROUTE_BGP
2970 && (old_select->sub_type == BGP_ROUTE_NORMAL
2971 || old_select->sub_type == BGP_ROUTE_AGGREGATE
2972 || old_select->sub_type == BGP_ROUTE_IMPORTED))
2973
2974 bgp_zebra_withdraw(p, old_select, bgp, safi);
2975 }
2976 }
2977
2978 bgp_process_evpn_route_injection(bgp, afi, safi, dest, new_select,
2979 old_select);
2980
2981 /* Clear any route change flags. */
2982 bgp_zebra_clear_route_change_flags(dest);
2983
2984 /* Reap old select bgp_path_info, if it has been removed */
2985 if (old_select && CHECK_FLAG(old_select->flags, BGP_PATH_REMOVED))
2986 bgp_path_info_reap(dest, old_select);
2987
2988 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
2989 return;
2990 }
2991
2992 /* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
2993 int bgp_best_path_select_defer(struct bgp *bgp, afi_t afi, safi_t safi)
2994 {
2995 struct bgp_dest *dest;
2996 int cnt = 0;
2997 struct afi_safi_info *thread_info;
2998
2999 if (bgp->gr_info[afi][safi].t_route_select) {
3000 struct thread *t = bgp->gr_info[afi][safi].t_route_select;
3001
3002 thread_info = THREAD_ARG(t);
3003 XFREE(MTYPE_TMP, thread_info);
3004 BGP_TIMER_OFF(bgp->gr_info[afi][safi].t_route_select);
3005 }
3006
3007 if (BGP_DEBUG(update, UPDATE_OUT)) {
3008 zlog_debug("%s: processing route for %s : cnt %d", __func__,
3009 get_afi_safi_str(afi, safi, false),
3010 bgp->gr_info[afi][safi].gr_deferred);
3011 }
3012
3013 /* Process the route list */
3014 for (dest = bgp_table_top(bgp->rib[afi][safi]);
3015 dest && bgp->gr_info[afi][safi].gr_deferred != 0;
3016 dest = bgp_route_next(dest)) {
3017 if (!CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER))
3018 continue;
3019
3020 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
3021 bgp->gr_info[afi][safi].gr_deferred--;
3022 bgp_process_main_one(bgp, dest, afi, safi);
3023 cnt++;
3024 if (cnt >= BGP_MAX_BEST_ROUTE_SELECT) {
3025 bgp_dest_unlock_node(dest);
3026 break;
3027 }
3028 }
3029
3030 /* Send EOR message when all routes are processed */
3031 if (!bgp->gr_info[afi][safi].gr_deferred) {
3032 bgp_send_delayed_eor(bgp);
3033 /* Send route processing complete message to RIB */
3034 bgp_zebra_update(afi, safi, bgp->vrf_id,
3035 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE);
3036 return 0;
3037 }
3038
3039 thread_info = XMALLOC(MTYPE_TMP, sizeof(struct afi_safi_info));
3040
3041 thread_info->afi = afi;
3042 thread_info->safi = safi;
3043 thread_info->bgp = bgp;
3044
3045 /* If there are more routes to be processed, start the
3046 * selection timer
3047 */
3048 thread_add_timer(bm->master, bgp_route_select_timer_expire, thread_info,
3049 BGP_ROUTE_SELECT_DELAY,
3050 &bgp->gr_info[afi][safi].t_route_select);
3051 return 0;
3052 }
3053
3054 static wq_item_status bgp_process_wq(struct work_queue *wq, void *data)
3055 {
3056 struct bgp_process_queue *pqnode = data;
3057 struct bgp *bgp = pqnode->bgp;
3058 struct bgp_table *table;
3059 struct bgp_dest *dest;
3060
3061 /* eoiu marker */
3062 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)) {
3063 bgp_process_main_one(bgp, NULL, 0, 0);
3064 /* should always have dedicated wq call */
3065 assert(STAILQ_FIRST(&pqnode->pqueue) == NULL);
3066 return WQ_SUCCESS;
3067 }
3068
3069 while (!STAILQ_EMPTY(&pqnode->pqueue)) {
3070 dest = STAILQ_FIRST(&pqnode->pqueue);
3071 STAILQ_REMOVE_HEAD(&pqnode->pqueue, pq);
3072 STAILQ_NEXT(dest, pq) = NULL; /* complete unlink */
3073 table = bgp_dest_table(dest);
3074 /* note, new DESTs may be added as part of processing */
3075 bgp_process_main_one(bgp, dest, table->afi, table->safi);
3076
3077 bgp_dest_unlock_node(dest);
3078 bgp_table_unlock(table);
3079 }
3080
3081 return WQ_SUCCESS;
3082 }
3083
3084 static void bgp_processq_del(struct work_queue *wq, void *data)
3085 {
3086 struct bgp_process_queue *pqnode = data;
3087
3088 bgp_unlock(pqnode->bgp);
3089
3090 XFREE(MTYPE_BGP_PROCESS_QUEUE, pqnode);
3091 }
3092
3093 void bgp_process_queue_init(struct bgp *bgp)
3094 {
3095 if (!bgp->process_queue) {
3096 char name[BUFSIZ];
3097
3098 snprintf(name, BUFSIZ, "process_queue %s", bgp->name_pretty);
3099 bgp->process_queue = work_queue_new(bm->master, name);
3100 }
3101
3102 bgp->process_queue->spec.workfunc = &bgp_process_wq;
3103 bgp->process_queue->spec.del_item_data = &bgp_processq_del;
3104 bgp->process_queue->spec.max_retries = 0;
3105 bgp->process_queue->spec.hold = 50;
3106 /* Use a higher yield value of 50ms for main queue processing */
3107 bgp->process_queue->spec.yield = 50 * 1000L;
3108 }
3109
3110 static struct bgp_process_queue *bgp_processq_alloc(struct bgp *bgp)
3111 {
3112 struct bgp_process_queue *pqnode;
3113
3114 pqnode = XCALLOC(MTYPE_BGP_PROCESS_QUEUE,
3115 sizeof(struct bgp_process_queue));
3116
3117 /* unlocked in bgp_processq_del */
3118 pqnode->bgp = bgp_lock(bgp);
3119 STAILQ_INIT(&pqnode->pqueue);
3120
3121 return pqnode;
3122 }
3123
3124 void bgp_process(struct bgp *bgp, struct bgp_dest *dest, afi_t afi, safi_t safi)
3125 {
3126 #define ARBITRARY_PROCESS_QLEN 10000
3127 struct work_queue *wq = bgp->process_queue;
3128 struct bgp_process_queue *pqnode;
3129 int pqnode_reuse = 0;
3130
3131 /* already scheduled for processing? */
3132 if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED))
3133 return;
3134
3135 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
3136 * the workqueue
3137 */
3138 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
3139 if (BGP_DEBUG(update, UPDATE_OUT))
3140 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
3141 dest);
3142 return;
3143 }
3144
3145 if (CHECK_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG)) {
3146 if (BGP_DEBUG(update, UPDATE_OUT))
3147 zlog_debug(
3148 "Soft reconfigure table in progress for route %p",
3149 dest);
3150 return;
3151 }
3152
3153 if (wq == NULL)
3154 return;
3155
3156 /* Add route nodes to an existing work queue item until reaching the
3157 limit only if is from the same BGP view and it's not an EOIU marker
3158 */
3159 if (work_queue_item_count(wq)) {
3160 struct work_queue_item *item = work_queue_last_item(wq);
3161 pqnode = item->data;
3162
3163 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)
3164 || pqnode->bgp != bgp
3165 || pqnode->queued >= ARBITRARY_PROCESS_QLEN)
3166 pqnode = bgp_processq_alloc(bgp);
3167 else
3168 pqnode_reuse = 1;
3169 } else
3170 pqnode = bgp_processq_alloc(bgp);
3171 /* all unlocked in bgp_process_wq */
3172 bgp_table_lock(bgp_dest_table(dest));
3173
3174 SET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
3175 bgp_dest_lock_node(dest);
3176
3177 /* can't be enqueued twice */
3178 assert(STAILQ_NEXT(dest, pq) == NULL);
3179 STAILQ_INSERT_TAIL(&pqnode->pqueue, dest, pq);
3180 pqnode->queued++;
3181
3182 if (!pqnode_reuse)
3183 work_queue_add(wq, pqnode);
3184
3185 return;
3186 }
3187
3188 void bgp_add_eoiu_mark(struct bgp *bgp)
3189 {
3190 struct bgp_process_queue *pqnode;
3191
3192 if (bgp->process_queue == NULL)
3193 return;
3194
3195 pqnode = bgp_processq_alloc(bgp);
3196
3197 SET_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER);
3198 work_queue_add(bgp->process_queue, pqnode);
3199 }
3200
3201 static int bgp_maximum_prefix_restart_timer(struct thread *thread)
3202 {
3203 struct peer *peer;
3204
3205 peer = THREAD_ARG(thread);
3206 peer->t_pmax_restart = NULL;
3207
3208 if (bgp_debug_neighbor_events(peer))
3209 zlog_debug(
3210 "%s Maximum-prefix restart timer expired, restore peering",
3211 peer->host);
3212
3213 if ((peer_clear(peer, NULL) < 0) && bgp_debug_neighbor_events(peer))
3214 zlog_debug("%s: %s peer_clear failed", __func__, peer->host);
3215
3216 return 0;
3217 }
3218
3219 static uint32_t bgp_filtered_routes_count(struct peer *peer, afi_t afi,
3220 safi_t safi)
3221 {
3222 uint32_t count = 0;
3223 bool filtered = false;
3224 struct bgp_dest *dest;
3225 struct bgp_adj_in *ain;
3226 struct attr attr = {};
3227 struct bgp_table *table = peer->bgp->rib[afi][safi];
3228
3229 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
3230 for (ain = dest->adj_in; ain; ain = ain->next) {
3231 const struct prefix *rn_p = bgp_dest_get_prefix(dest);
3232
3233 attr = *ain->attr;
3234
3235 if (bgp_input_filter(peer, rn_p, &attr, afi, safi)
3236 == FILTER_DENY)
3237 filtered = true;
3238
3239 if (bgp_input_modifier(
3240 peer, rn_p, &attr, afi, safi,
3241 ROUTE_MAP_IN_NAME(&peer->filter[afi][safi]),
3242 NULL, 0, NULL)
3243 == RMAP_DENY)
3244 filtered = true;
3245
3246 if (filtered)
3247 count++;
3248
3249 bgp_attr_undup(&attr, ain->attr);
3250 }
3251 }
3252
3253 return count;
3254 }
3255
3256 bool bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi,
3257 int always)
3258 {
3259 iana_afi_t pkt_afi;
3260 iana_safi_t pkt_safi;
3261 uint32_t pcount = (CHECK_FLAG(peer->af_flags[afi][safi],
3262 PEER_FLAG_MAX_PREFIX_FORCE))
3263 ? bgp_filtered_routes_count(peer, afi, safi)
3264 + peer->pcount[afi][safi]
3265 : peer->pcount[afi][safi];
3266
3267 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
3268 return false;
3269
3270 if (pcount > peer->pmax[afi][safi]) {
3271 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3272 PEER_STATUS_PREFIX_LIMIT)
3273 && !always)
3274 return false;
3275
3276 zlog_info(
3277 "%%MAXPFXEXCEED: No. of %s prefix received from %s %u exceed, limit %u",
3278 get_afi_safi_str(afi, safi, false), peer->host, pcount,
3279 peer->pmax[afi][safi]);
3280 SET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT);
3281
3282 if (CHECK_FLAG(peer->af_flags[afi][safi],
3283 PEER_FLAG_MAX_PREFIX_WARNING))
3284 return false;
3285
3286 /* Convert AFI, SAFI to values for packet. */
3287 pkt_afi = afi_int2iana(afi);
3288 pkt_safi = safi_int2iana(safi);
3289 {
3290 uint8_t ndata[7];
3291
3292 ndata[0] = (pkt_afi >> 8);
3293 ndata[1] = pkt_afi;
3294 ndata[2] = pkt_safi;
3295 ndata[3] = (peer->pmax[afi][safi] >> 24);
3296 ndata[4] = (peer->pmax[afi][safi] >> 16);
3297 ndata[5] = (peer->pmax[afi][safi] >> 8);
3298 ndata[6] = (peer->pmax[afi][safi]);
3299
3300 SET_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
3301 bgp_notify_send_with_data(peer, BGP_NOTIFY_CEASE,
3302 BGP_NOTIFY_CEASE_MAX_PREFIX,
3303 ndata, 7);
3304 }
3305
3306 /* Dynamic peers will just close their connection. */
3307 if (peer_dynamic_neighbor(peer))
3308 return true;
3309
3310 /* restart timer start */
3311 if (peer->pmax_restart[afi][safi]) {
3312 peer->v_pmax_restart =
3313 peer->pmax_restart[afi][safi] * 60;
3314
3315 if (bgp_debug_neighbor_events(peer))
3316 zlog_debug(
3317 "%s Maximum-prefix restart timer started for %d secs",
3318 peer->host, peer->v_pmax_restart);
3319
3320 BGP_TIMER_ON(peer->t_pmax_restart,
3321 bgp_maximum_prefix_restart_timer,
3322 peer->v_pmax_restart);
3323 }
3324
3325 return true;
3326 } else
3327 UNSET_FLAG(peer->af_sflags[afi][safi],
3328 PEER_STATUS_PREFIX_LIMIT);
3329
3330 if (pcount
3331 > (peer->pmax[afi][safi] * peer->pmax_threshold[afi][safi] / 100)) {
3332 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3333 PEER_STATUS_PREFIX_THRESHOLD)
3334 && !always)
3335 return false;
3336
3337 zlog_info(
3338 "%%MAXPFX: No. of %s prefix received from %s reaches %u, max %u",
3339 get_afi_safi_str(afi, safi, false), peer->host, pcount,
3340 peer->pmax[afi][safi]);
3341 SET_FLAG(peer->af_sflags[afi][safi],
3342 PEER_STATUS_PREFIX_THRESHOLD);
3343 } else
3344 UNSET_FLAG(peer->af_sflags[afi][safi],
3345 PEER_STATUS_PREFIX_THRESHOLD);
3346 return false;
3347 }
3348
3349 /* Unconditionally remove the route from the RIB, without taking
3350 * damping into consideration (eg, because the session went down)
3351 */
3352 void bgp_rib_remove(struct bgp_dest *dest, struct bgp_path_info *pi,
3353 struct peer *peer, afi_t afi, safi_t safi)
3354 {
3355
3356 struct bgp *bgp = NULL;
3357 bool delete_route = false;
3358
3359 bgp_aggregate_decrement(peer->bgp, bgp_dest_get_prefix(dest), pi, afi,
3360 safi);
3361
3362 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
3363 bgp_path_info_delete(dest, pi); /* keep historical info */
3364
3365 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3366 * flag
3367 */
3368 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3369 delete_route = true;
3370 else if (bgp_dest_set_defer_flag(dest, true) < 0)
3371 delete_route = true;
3372 if (delete_route) {
3373 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
3374 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
3375 bgp = pi->peer->bgp;
3376 bgp->gr_info[afi][safi].gr_deferred--;
3377 }
3378 }
3379 }
3380
3381 hook_call(bgp_process, peer->bgp, afi, safi, dest, peer, true);
3382 bgp_process(peer->bgp, dest, afi, safi);
3383 }
3384
3385 static void bgp_rib_withdraw(struct bgp_dest *dest, struct bgp_path_info *pi,
3386 struct peer *peer, afi_t afi, safi_t safi,
3387 struct prefix_rd *prd)
3388 {
3389 const struct prefix *p = bgp_dest_get_prefix(dest);
3390
3391 /* apply dampening, if result is suppressed, we'll be retaining
3392 * the bgp_path_info in the RIB for historical reference.
3393 */
3394 if (peer->sort == BGP_PEER_EBGP) {
3395 if (get_active_bdc_from_pi(pi, afi, safi)) {
3396 if (bgp_damp_withdraw(pi, dest, afi, safi, 0)
3397 == BGP_DAMP_SUPPRESSED) {
3398 bgp_aggregate_decrement(peer->bgp, p, pi, afi,
3399 safi);
3400 return;
3401 }
3402 }
3403 }
3404
3405 #ifdef ENABLE_BGP_VNC
3406 if (safi == SAFI_MPLS_VPN) {
3407 struct bgp_dest *pdest = NULL;
3408 struct bgp_table *table = NULL;
3409
3410 pdest = bgp_node_get(peer->bgp->rib[afi][safi],
3411 (struct prefix *)prd);
3412 if (bgp_dest_has_bgp_path_info_data(pdest)) {
3413 table = bgp_dest_get_bgp_table_info(pdest);
3414
3415 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3416 peer->bgp, prd, table, p, pi);
3417 }
3418 bgp_dest_unlock_node(pdest);
3419 }
3420 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
3421 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
3422
3423 vnc_import_bgp_del_route(peer->bgp, p, pi);
3424 vnc_import_bgp_exterior_del_route(peer->bgp, p, pi);
3425 }
3426 }
3427 #endif
3428
3429 /* If this is an EVPN route, process for un-import. */
3430 if (safi == SAFI_EVPN)
3431 bgp_evpn_unimport_route(peer->bgp, afi, safi, p, pi);
3432
3433 bgp_rib_remove(dest, pi, peer, afi, safi);
3434 }
3435
3436 struct bgp_path_info *info_make(int type, int sub_type, unsigned short instance,
3437 struct peer *peer, struct attr *attr,
3438 struct bgp_dest *dest)
3439 {
3440 struct bgp_path_info *new;
3441
3442 /* Make new BGP info. */
3443 new = XCALLOC(MTYPE_BGP_ROUTE, sizeof(struct bgp_path_info));
3444 new->type = type;
3445 new->instance = instance;
3446 new->sub_type = sub_type;
3447 new->peer = peer;
3448 new->attr = attr;
3449 new->uptime = bgp_clock();
3450 new->net = dest;
3451 return new;
3452 }
3453
3454 static bool overlay_index_equal(afi_t afi, struct bgp_path_info *path,
3455 union gw_addr *gw_ip)
3456 {
3457 const struct bgp_route_evpn *eo = bgp_attr_get_evpn_overlay(path->attr);
3458 union gw_addr path_gw_ip, *path_gw_ip_remote;
3459 union {
3460 esi_t esi;
3461 union gw_addr ip;
3462 } temp;
3463
3464 if (afi != AFI_L2VPN)
3465 return true;
3466
3467 path_gw_ip = eo->gw_ip;
3468
3469 if (gw_ip == NULL) {
3470 memset(&temp, 0, sizeof(temp));
3471 path_gw_ip_remote = &temp.ip;
3472 } else
3473 path_gw_ip_remote = gw_ip;
3474
3475 return !!memcmp(&path_gw_ip, path_gw_ip_remote, sizeof(union gw_addr));
3476 }
3477
3478 /* Check if received nexthop is valid or not. */
3479 bool bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
3480 uint8_t type, uint8_t stype, struct attr *attr,
3481 struct bgp_dest *dest)
3482 {
3483 bool ret = false;
3484 bool is_bgp_static_route =
3485 (type == ZEBRA_ROUTE_BGP && stype == BGP_ROUTE_STATIC) ? true
3486 : false;
3487
3488 /*
3489 * Only validated for unicast and multicast currently.
3490 * Also valid for EVPN where the nexthop is an IP address.
3491 * If we are a bgp static route being checked then there is
3492 * no need to check to see if the nexthop is martian as
3493 * that it should be ok.
3494 */
3495 if (is_bgp_static_route ||
3496 (safi != SAFI_UNICAST && safi != SAFI_MULTICAST && safi != SAFI_EVPN))
3497 return false;
3498
3499 /* If NEXT_HOP is present, validate it. */
3500 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
3501 if (attr->nexthop.s_addr == INADDR_ANY
3502 || IPV4_CLASS_DE(ntohl(attr->nexthop.s_addr))
3503 || bgp_nexthop_self(bgp, afi, type, stype, attr, dest))
3504 return true;
3505 }
3506
3507 /* If MP_NEXTHOP is present, validate it. */
3508 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3509 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3510 * it is not an IPv6 link-local address.
3511 *
3512 * If we receive an UPDATE with nexthop length set to 32 bytes
3513 * we shouldn't discard an UPDATE if it's set to (::).
3514 * The link-local (2st) is validated along the code path later.
3515 */
3516 if (attr->mp_nexthop_len) {
3517 switch (attr->mp_nexthop_len) {
3518 case BGP_ATTR_NHLEN_IPV4:
3519 case BGP_ATTR_NHLEN_VPNV4:
3520 ret = (attr->mp_nexthop_global_in.s_addr == INADDR_ANY
3521 || IPV4_CLASS_DE(
3522 ntohl(attr->mp_nexthop_global_in.s_addr))
3523 || bgp_nexthop_self(bgp, afi, type, stype, attr,
3524 dest));
3525 break;
3526
3527 case BGP_ATTR_NHLEN_IPV6_GLOBAL:
3528 case BGP_ATTR_NHLEN_VPNV6_GLOBAL:
3529 ret = (IN6_IS_ADDR_UNSPECIFIED(
3530 &attr->mp_nexthop_global)
3531 || IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3532 || IN6_IS_ADDR_MULTICAST(
3533 &attr->mp_nexthop_global)
3534 || bgp_nexthop_self(bgp, afi, type, stype, attr,
3535 dest));
3536 break;
3537 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
3538 ret = (IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3539 || IN6_IS_ADDR_MULTICAST(
3540 &attr->mp_nexthop_global)
3541 || bgp_nexthop_self(bgp, afi, type, stype, attr,
3542 dest));
3543 break;
3544
3545 default:
3546 ret = true;
3547 break;
3548 }
3549 }
3550
3551 return ret;
3552 }
3553
3554 static void bgp_attr_add_no_export_community(struct attr *attr)
3555 {
3556 struct community *old;
3557 struct community *new;
3558 struct community *merge;
3559 struct community *no_export;
3560
3561 old = attr->community;
3562 no_export = community_str2com("no-export");
3563
3564 assert(no_export);
3565
3566 if (old) {
3567 merge = community_merge(community_dup(old), no_export);
3568
3569 if (!old->refcnt)
3570 community_free(&old);
3571
3572 new = community_uniq_sort(merge);
3573 community_free(&merge);
3574 } else {
3575 new = community_dup(no_export);
3576 }
3577
3578 community_free(&no_export);
3579
3580 attr->community = new;
3581 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
3582 }
3583
3584 int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
3585 struct attr *attr, afi_t afi, safi_t safi, int type,
3586 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
3587 uint32_t num_labels, int soft_reconfig,
3588 struct bgp_route_evpn *evpn)
3589 {
3590 int ret;
3591 int aspath_loop_count = 0;
3592 struct bgp_dest *dest;
3593 struct bgp *bgp;
3594 struct attr new_attr;
3595 struct attr *attr_new;
3596 struct bgp_path_info *pi;
3597 struct bgp_path_info *new;
3598 struct bgp_path_info_extra *extra;
3599 const char *reason;
3600 char pfx_buf[BGP_PRD_PATH_STRLEN];
3601 int connected = 0;
3602 int do_loop_check = 1;
3603 int has_valid_label = 0;
3604 afi_t nh_afi;
3605 uint8_t pi_type = 0;
3606 uint8_t pi_sub_type = 0;
3607
3608 if (frrtrace_enabled(frr_bgp, process_update)) {
3609 char pfxprint[PREFIX2STR_BUFFER];
3610
3611 prefix2str(p, pfxprint, sizeof(pfxprint));
3612 frrtrace(6, frr_bgp, process_update, peer, pfxprint, addpath_id,
3613 afi, safi, attr);
3614 }
3615
3616 #ifdef ENABLE_BGP_VNC
3617 int vnc_implicit_withdraw = 0;
3618 #endif
3619 int same_attr = 0;
3620
3621 memset(&new_attr, 0, sizeof(struct attr));
3622 new_attr.label_index = BGP_INVALID_LABEL_INDEX;
3623 new_attr.label = MPLS_INVALID_LABEL;
3624
3625 bgp = peer->bgp;
3626 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
3627 /* TODO: Check to see if we can get rid of "is_valid_label" */
3628 if (afi == AFI_L2VPN && safi == SAFI_EVPN)
3629 has_valid_label = (num_labels > 0) ? 1 : 0;
3630 else
3631 has_valid_label = bgp_is_valid_label(label);
3632
3633 if (has_valid_label)
3634 assert(label != NULL);
3635
3636 /* Update overlay index of the attribute */
3637 if (afi == AFI_L2VPN && evpn)
3638 memcpy(&attr->evpn_overlay, evpn,
3639 sizeof(struct bgp_route_evpn));
3640
3641 /* When peer's soft reconfiguration enabled. Record input packet in
3642 Adj-RIBs-In. */
3643 if (!soft_reconfig
3644 && CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
3645 && peer != bgp->peer_self)
3646 bgp_adj_in_set(dest, peer, attr, addpath_id);
3647
3648 /* Check previously received route. */
3649 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
3650 if (pi->peer == peer && pi->type == type
3651 && pi->sub_type == sub_type
3652 && pi->addpath_rx_id == addpath_id)
3653 break;
3654
3655 /* AS path local-as loop check. */
3656 if (peer->change_local_as) {
3657 if (peer->allowas_in[afi][safi])
3658 aspath_loop_count = peer->allowas_in[afi][safi];
3659 else if (!CHECK_FLAG(peer->flags,
3660 PEER_FLAG_LOCAL_AS_NO_PREPEND))
3661 aspath_loop_count = 1;
3662
3663 if (aspath_loop_check(attr->aspath, peer->change_local_as)
3664 > aspath_loop_count) {
3665 peer->stat_pfx_aspath_loop++;
3666 reason = "as-path contains our own AS A;";
3667 goto filtered;
3668 }
3669 }
3670
3671 /* If the peer is configured for "allowas-in origin" and the last ASN in
3672 * the
3673 * as-path is our ASN then we do not need to call aspath_loop_check
3674 */
3675 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN))
3676 if (aspath_get_last_as(attr->aspath) == bgp->as)
3677 do_loop_check = 0;
3678
3679 /* AS path loop check. */
3680 if (do_loop_check) {
3681 if (aspath_loop_check(attr->aspath, bgp->as)
3682 > peer->allowas_in[afi][safi]
3683 || (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)
3684 && aspath_loop_check(attr->aspath, bgp->confed_id)
3685 > peer->allowas_in[afi][safi])) {
3686 peer->stat_pfx_aspath_loop++;
3687 reason = "as-path contains our own AS;";
3688 goto filtered;
3689 }
3690 }
3691
3692 /* Route reflector originator ID check. */
3693 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
3694 && IPV4_ADDR_SAME(&bgp->router_id, &attr->originator_id)) {
3695 peer->stat_pfx_originator_loop++;
3696 reason = "originator is us;";
3697 goto filtered;
3698 }
3699
3700 /* Route reflector cluster ID check. */
3701 if (bgp_cluster_filter(peer, attr)) {
3702 peer->stat_pfx_cluster_loop++;
3703 reason = "reflected from the same cluster;";
3704 goto filtered;
3705 }
3706
3707 /* Apply incoming filter. */
3708 if (bgp_input_filter(peer, p, attr, afi, safi) == FILTER_DENY) {
3709 peer->stat_pfx_filter++;
3710 reason = "filter;";
3711 goto filtered;
3712 }
3713
3714 /* RFC 8212 to prevent route leaks.
3715 * This specification intends to improve this situation by requiring the
3716 * explicit configuration of both BGP Import and Export Policies for any
3717 * External BGP (EBGP) session such as customers, peers, or
3718 * confederation boundaries for all enabled address families. Through
3719 * codification of the aforementioned requirement, operators will
3720 * benefit from consistent behavior across different BGP
3721 * implementations.
3722 */
3723 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
3724 if (!bgp_inbound_policy_exists(peer,
3725 &peer->filter[afi][safi])) {
3726 reason = "inbound policy missing";
3727 goto filtered;
3728 }
3729
3730 /* draft-ietf-idr-deprecate-as-set-confed-set
3731 * Filter routes having AS_SET or AS_CONFED_SET in the path.
3732 * Eventually, This document (if approved) updates RFC 4271
3733 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
3734 * and obsoletes RFC 6472.
3735 */
3736 if (peer->bgp->reject_as_sets)
3737 if (aspath_check_as_sets(attr->aspath)) {
3738 reason =
3739 "as-path contains AS_SET or AS_CONFED_SET type;";
3740 goto filtered;
3741 }
3742
3743 new_attr = *attr;
3744
3745 /* Apply incoming route-map.
3746 * NB: new_attr may now contain newly allocated values from route-map
3747 * "set"
3748 * commands, so we need bgp_attr_flush in the error paths, until we
3749 * intern
3750 * the attr (which takes over the memory references) */
3751 if (bgp_input_modifier(peer, p, &new_attr, afi, safi, NULL, label,
3752 num_labels, dest)
3753 == RMAP_DENY) {
3754 peer->stat_pfx_filter++;
3755 reason = "route-map;";
3756 bgp_attr_flush(&new_attr);
3757 goto filtered;
3758 }
3759
3760 if (pi && pi->attr->rmap_table_id != new_attr.rmap_table_id) {
3761 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3762 /* remove from RIB previous entry */
3763 bgp_zebra_withdraw(p, pi, bgp, safi);
3764 }
3765
3766 if (peer->sort == BGP_PEER_EBGP) {
3767
3768 /* rfc7999:
3769 * A BGP speaker receiving an announcement tagged with the
3770 * BLACKHOLE community SHOULD add the NO_ADVERTISE or
3771 * NO_EXPORT community as defined in RFC1997, or a
3772 * similar community, to prevent propagation of the
3773 * prefix outside the local AS. The community to prevent
3774 * propagation SHOULD be chosen according to the operator's
3775 * routing policy.
3776 */
3777 if (new_attr.community
3778 && community_include(new_attr.community,
3779 COMMUNITY_BLACKHOLE))
3780 bgp_attr_add_no_export_community(&new_attr);
3781
3782 /* If we receive the graceful-shutdown community from an eBGP
3783 * peer we must lower local-preference */
3784 if (new_attr.community
3785 && community_include(new_attr.community, COMMUNITY_GSHUT)) {
3786 new_attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
3787 new_attr.local_pref = BGP_GSHUT_LOCAL_PREF;
3788
3789 /* If graceful-shutdown is configured then add the GSHUT
3790 * community to all paths received from eBGP peers */
3791 } else if (bgp_in_graceful_shutdown(peer->bgp))
3792 bgp_attr_add_gshut_community(&new_attr);
3793 }
3794
3795 if (pi) {
3796 pi_type = pi->type;
3797 pi_sub_type = pi->sub_type;
3798 }
3799
3800 /* next hop check. */
3801 if (!CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD)
3802 && bgp_update_martian_nexthop(bgp, afi, safi, pi_type, pi_sub_type,
3803 &new_attr, dest)) {
3804 peer->stat_pfx_nh_invalid++;
3805 reason = "martian or self next-hop;";
3806 bgp_attr_flush(&new_attr);
3807 goto filtered;
3808 }
3809
3810 if (bgp_mac_entry_exists(p) || bgp_mac_exist(&attr->rmac)) {
3811 peer->stat_pfx_nh_invalid++;
3812 reason = "self mac;";
3813 goto filtered;
3814 }
3815
3816 /* The flag BGP_NODE_FIB_INSTALL_PENDING is for the following
3817 * condition :
3818 * Suppress fib is enabled
3819 * BGP_OPT_NO_FIB is not enabled
3820 * Route type is BGP_ROUTE_NORMAL (peer learnt routes)
3821 * Route is being installed first time (BGP_NODE_FIB_INSTALLED not set)
3822 */
3823 if (bgp_fibupd_safi(safi) && BGP_SUPPRESS_FIB_ENABLED(bgp)
3824 && (sub_type == BGP_ROUTE_NORMAL)
3825 && (!bgp_option_check(BGP_OPT_NO_FIB))
3826 && (!CHECK_FLAG(dest->flags, BGP_NODE_FIB_INSTALLED)))
3827 SET_FLAG(dest->flags, BGP_NODE_FIB_INSTALL_PENDING);
3828
3829 attr_new = bgp_attr_intern(&new_attr);
3830
3831 /* If maximum prefix count is configured and current prefix
3832 * count exeed it.
3833 */
3834 if (bgp_maximum_prefix_overflow(peer, afi, safi, 0))
3835 return -1;
3836
3837 /* If the update is implicit withdraw. */
3838 if (pi) {
3839 pi->uptime = bgp_clock();
3840 same_attr = attrhash_cmp(pi->attr, attr_new);
3841
3842 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
3843
3844 /* Same attribute comes in. */
3845 if (!CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
3846 && same_attr
3847 && (!has_valid_label
3848 || memcmp(&(bgp_path_info_extra_get(pi))->label, label,
3849 num_labels * sizeof(mpls_label_t))
3850 == 0)) {
3851 if (get_active_bdc_from_pi(pi, afi, safi)
3852 && peer->sort == BGP_PEER_EBGP
3853 && CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
3854 if (bgp_debug_update(peer, p, NULL, 1)) {
3855 bgp_debug_rdpfxpath2str(
3856 afi, safi, prd, p, label,
3857 num_labels, addpath_id ? 1 : 0,
3858 addpath_id, evpn, pfx_buf,
3859 sizeof(pfx_buf));
3860 zlog_debug("%s rcvd %s", peer->host,
3861 pfx_buf);
3862 }
3863
3864 if (bgp_damp_update(pi, dest, afi, safi)
3865 != BGP_DAMP_SUPPRESSED) {
3866 bgp_aggregate_increment(bgp, p, pi, afi,
3867 safi);
3868 bgp_process(bgp, dest, afi, safi);
3869 }
3870 } else /* Duplicate - odd */
3871 {
3872 if (bgp_debug_update(peer, p, NULL, 1)) {
3873 if (!peer->rcvd_attr_printed) {
3874 zlog_debug(
3875 "%s rcvd UPDATE w/ attr: %s",
3876 peer->host,
3877 peer->rcvd_attr_str);
3878 peer->rcvd_attr_printed = 1;
3879 }
3880
3881 bgp_debug_rdpfxpath2str(
3882 afi, safi, prd, p, label,
3883 num_labels, addpath_id ? 1 : 0,
3884 addpath_id, evpn, pfx_buf,
3885 sizeof(pfx_buf));
3886 zlog_debug(
3887 "%s rcvd %s...duplicate ignored",
3888 peer->host, pfx_buf);
3889 }
3890
3891 /* graceful restart STALE flag unset. */
3892 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
3893 bgp_path_info_unset_flag(
3894 dest, pi, BGP_PATH_STALE);
3895 bgp_dest_set_defer_flag(dest, false);
3896 bgp_process(bgp, dest, afi, safi);
3897 }
3898 }
3899
3900 bgp_dest_unlock_node(dest);
3901 bgp_attr_unintern(&attr_new);
3902
3903 return 0;
3904 }
3905
3906 /* Withdraw/Announce before we fully processed the withdraw */
3907 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
3908 if (bgp_debug_update(peer, p, NULL, 1)) {
3909 bgp_debug_rdpfxpath2str(
3910 afi, safi, prd, p, label, num_labels,
3911 addpath_id ? 1 : 0, addpath_id, evpn,
3912 pfx_buf, sizeof(pfx_buf));
3913 zlog_debug(
3914 "%s rcvd %s, flapped quicker than processing",
3915 peer->host, pfx_buf);
3916 }
3917
3918 bgp_path_info_restore(dest, pi);
3919 }
3920
3921 /* Received Logging. */
3922 if (bgp_debug_update(peer, p, NULL, 1)) {
3923 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label,
3924 num_labels, addpath_id ? 1 : 0,
3925 addpath_id, evpn, pfx_buf,
3926 sizeof(pfx_buf));
3927 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
3928 }
3929
3930 /* graceful restart STALE flag unset. */
3931 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
3932 bgp_path_info_unset_flag(dest, pi, BGP_PATH_STALE);
3933 bgp_dest_set_defer_flag(dest, false);
3934 }
3935
3936 /* The attribute is changed. */
3937 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
3938
3939 /* implicit withdraw, decrement aggregate and pcount here.
3940 * only if update is accepted, they'll increment below.
3941 */
3942 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
3943
3944 /* Update bgp route dampening information. */
3945 if (get_active_bdc_from_pi(pi, afi, safi)
3946 && peer->sort == BGP_PEER_EBGP) {
3947 /* This is implicit withdraw so we should update
3948 * dampening information.
3949 */
3950 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
3951 bgp_damp_withdraw(pi, dest, afi, safi, 1);
3952 }
3953 #ifdef ENABLE_BGP_VNC
3954 if (safi == SAFI_MPLS_VPN) {
3955 struct bgp_dest *pdest = NULL;
3956 struct bgp_table *table = NULL;
3957
3958 pdest = bgp_node_get(bgp->rib[afi][safi],
3959 (struct prefix *)prd);
3960 if (bgp_dest_has_bgp_path_info_data(pdest)) {
3961 table = bgp_dest_get_bgp_table_info(pdest);
3962
3963 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3964 bgp, prd, table, p, pi);
3965 }
3966 bgp_dest_unlock_node(pdest);
3967 }
3968 if ((afi == AFI_IP || afi == AFI_IP6)
3969 && (safi == SAFI_UNICAST)) {
3970 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
3971 /*
3972 * Implicit withdraw case.
3973 */
3974 ++vnc_implicit_withdraw;
3975 vnc_import_bgp_del_route(bgp, p, pi);
3976 vnc_import_bgp_exterior_del_route(bgp, p, pi);
3977 }
3978 }
3979 #endif
3980
3981 /* Special handling for EVPN update of an existing route. If the
3982 * extended community attribute has changed, we need to
3983 * un-import
3984 * the route using its existing extended community. It will be
3985 * subsequently processed for import with the new extended
3986 * community.
3987 */
3988 if (((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN))
3989 && !same_attr) {
3990 if ((pi->attr->flag
3991 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))
3992 && (attr_new->flag
3993 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
3994 int cmp;
3995
3996 cmp = ecommunity_cmp(pi->attr->ecommunity,
3997 attr_new->ecommunity);
3998 if (!cmp) {
3999 if (bgp_debug_update(peer, p, NULL, 1))
4000 zlog_debug(
4001 "Change in EXT-COMM, existing %s new %s",
4002 ecommunity_str(
4003 pi->attr->ecommunity),
4004 ecommunity_str(
4005 attr_new->ecommunity));
4006 if (safi == SAFI_EVPN)
4007 bgp_evpn_unimport_route(
4008 bgp, afi, safi, p, pi);
4009 else /* SAFI_MPLS_VPN */
4010 vpn_leak_to_vrf_withdraw(bgp,
4011 pi);
4012 }
4013 }
4014 }
4015
4016 /* Update to new attribute. */
4017 bgp_attr_unintern(&pi->attr);
4018 pi->attr = attr_new;
4019
4020 /* Update MPLS label */
4021 if (has_valid_label) {
4022 extra = bgp_path_info_extra_get(pi);
4023 if (extra->label != label) {
4024 memcpy(&extra->label, label,
4025 num_labels * sizeof(mpls_label_t));
4026 extra->num_labels = num_labels;
4027 }
4028 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4029 bgp_set_valid_label(&extra->label[0]);
4030 }
4031
4032 /* Update SRv6 SID */
4033 if (attr->srv6_l3vpn) {
4034 extra = bgp_path_info_extra_get(pi);
4035 if (sid_diff(&extra->sid[0], &attr->srv6_l3vpn->sid)) {
4036 sid_copy(&extra->sid[0],
4037 &attr->srv6_l3vpn->sid);
4038 extra->num_sids = 1;
4039 }
4040 } else if (attr->srv6_vpn) {
4041 extra = bgp_path_info_extra_get(pi);
4042 if (sid_diff(&extra->sid[0], &attr->srv6_vpn->sid)) {
4043 sid_copy(&extra->sid[0], &attr->srv6_vpn->sid);
4044 extra->num_sids = 1;
4045 }
4046 }
4047
4048 #ifdef ENABLE_BGP_VNC
4049 if ((afi == AFI_IP || afi == AFI_IP6)
4050 && (safi == SAFI_UNICAST)) {
4051 if (vnc_implicit_withdraw) {
4052 /*
4053 * Add back the route with its new attributes
4054 * (e.g., nexthop).
4055 * The route is still selected, until the route
4056 * selection
4057 * queued by bgp_process actually runs. We have
4058 * to make this
4059 * update to the VNC side immediately to avoid
4060 * racing against
4061 * configuration changes (e.g., route-map
4062 * changes) which
4063 * trigger re-importation of the entire RIB.
4064 */
4065 vnc_import_bgp_add_route(bgp, p, pi);
4066 vnc_import_bgp_exterior_add_route(bgp, p, pi);
4067 }
4068 }
4069 #endif
4070
4071 /* Update bgp route dampening information. */
4072 if (get_active_bdc_from_pi(pi, afi, safi)
4073 && peer->sort == BGP_PEER_EBGP) {
4074 /* Now we do normal update dampening. */
4075 ret = bgp_damp_update(pi, dest, afi, safi);
4076 if (ret == BGP_DAMP_SUPPRESSED) {
4077 bgp_dest_unlock_node(dest);
4078 return 0;
4079 }
4080 }
4081
4082 /* Nexthop reachability check - for unicast and
4083 * labeled-unicast.. */
4084 if (((afi == AFI_IP || afi == AFI_IP6)
4085 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4086 || (safi == SAFI_EVPN &&
4087 bgp_evpn_is_prefix_nht_supported(p))) {
4088 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4089 && peer->ttl == BGP_DEFAULT_TTL
4090 && !CHECK_FLAG(peer->flags,
4091 PEER_FLAG_DISABLE_CONNECTED_CHECK)
4092 && !CHECK_FLAG(bgp->flags,
4093 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
4094 connected = 1;
4095 else
4096 connected = 0;
4097
4098 struct bgp *bgp_nexthop = bgp;
4099
4100 if (pi->extra && pi->extra->bgp_orig)
4101 bgp_nexthop = pi->extra->bgp_orig;
4102
4103 nh_afi = BGP_ATTR_NH_AFI(afi, pi->attr);
4104
4105 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop, nh_afi,
4106 safi, pi, NULL, connected)
4107 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
4108 bgp_path_info_set_flag(dest, pi,
4109 BGP_PATH_VALID);
4110 else {
4111 if (BGP_DEBUG(nht, NHT)) {
4112 zlog_debug("%s(%pI4): NH unresolved",
4113 __func__,
4114 (in_addr_t *)&attr_new->nexthop);
4115 }
4116 bgp_path_info_unset_flag(dest, pi,
4117 BGP_PATH_VALID);
4118 }
4119 } else
4120 bgp_path_info_set_flag(dest, pi, BGP_PATH_VALID);
4121
4122 #ifdef ENABLE_BGP_VNC
4123 if (safi == SAFI_MPLS_VPN) {
4124 struct bgp_dest *pdest = NULL;
4125 struct bgp_table *table = NULL;
4126
4127 pdest = bgp_node_get(bgp->rib[afi][safi],
4128 (struct prefix *)prd);
4129 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4130 table = bgp_dest_get_bgp_table_info(pdest);
4131
4132 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4133 bgp, prd, table, p, pi);
4134 }
4135 bgp_dest_unlock_node(pdest);
4136 }
4137 #endif
4138
4139 /* If this is an EVPN route and some attribute has changed,
4140 * process
4141 * route for import. If the extended community has changed, we
4142 * would
4143 * have done the un-import earlier and the import would result
4144 * in the
4145 * route getting injected into appropriate L2 VNIs. If it is
4146 * just
4147 * some other attribute change, the import will result in
4148 * updating
4149 * the attributes for the route in the VNI(s).
4150 */
4151 if (safi == SAFI_EVPN && !same_attr &&
4152 CHECK_FLAG(pi->flags, BGP_PATH_VALID))
4153 bgp_evpn_import_route(bgp, afi, safi, p, pi);
4154
4155 /* Process change. */
4156 bgp_aggregate_increment(bgp, p, pi, afi, safi);
4157
4158 bgp_process(bgp, dest, afi, safi);
4159 bgp_dest_unlock_node(dest);
4160
4161 if (SAFI_UNICAST == safi
4162 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4163 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4164
4165 vpn_leak_from_vrf_update(bgp_get_default(), bgp, pi);
4166 }
4167 if ((SAFI_MPLS_VPN == safi)
4168 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4169
4170 vpn_leak_to_vrf_update(bgp, pi);
4171 }
4172
4173 #ifdef ENABLE_BGP_VNC
4174 if (SAFI_MPLS_VPN == safi) {
4175 mpls_label_t label_decoded = decode_label(label);
4176
4177 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4178 type, sub_type, &label_decoded);
4179 }
4180 if (SAFI_ENCAP == safi) {
4181 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4182 type, sub_type, NULL);
4183 }
4184 #endif
4185
4186 return 0;
4187 } // End of implicit withdraw
4188
4189 /* Received Logging. */
4190 if (bgp_debug_update(peer, p, NULL, 1)) {
4191 if (!peer->rcvd_attr_printed) {
4192 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
4193 peer->rcvd_attr_str);
4194 peer->rcvd_attr_printed = 1;
4195 }
4196
4197 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
4198 addpath_id ? 1 : 0, addpath_id, evpn,
4199 pfx_buf, sizeof(pfx_buf));
4200 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
4201 }
4202
4203 /* Make new BGP info. */
4204 new = info_make(type, sub_type, 0, peer, attr_new, dest);
4205
4206 /* Update MPLS label */
4207 if (has_valid_label) {
4208 extra = bgp_path_info_extra_get(new);
4209 if (extra->label != label) {
4210 memcpy(&extra->label, label,
4211 num_labels * sizeof(mpls_label_t));
4212 extra->num_labels = num_labels;
4213 }
4214 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4215 bgp_set_valid_label(&extra->label[0]);
4216 }
4217
4218 /* Update SRv6 SID */
4219 if (safi == SAFI_MPLS_VPN) {
4220 extra = bgp_path_info_extra_get(new);
4221 if (attr->srv6_l3vpn) {
4222 sid_copy(&extra->sid[0], &attr->srv6_l3vpn->sid);
4223 extra->num_sids = 1;
4224 } else if (attr->srv6_vpn) {
4225 sid_copy(&extra->sid[0], &attr->srv6_vpn->sid);
4226 extra->num_sids = 1;
4227 }
4228 }
4229
4230 /* Nexthop reachability check. */
4231 if (((afi == AFI_IP || afi == AFI_IP6)
4232 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4233 || (safi == SAFI_EVPN && bgp_evpn_is_prefix_nht_supported(p))) {
4234 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4235 && peer->ttl == BGP_DEFAULT_TTL
4236 && !CHECK_FLAG(peer->flags,
4237 PEER_FLAG_DISABLE_CONNECTED_CHECK)
4238 && !CHECK_FLAG(bgp->flags,
4239 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
4240 connected = 1;
4241 else
4242 connected = 0;
4243
4244 nh_afi = BGP_ATTR_NH_AFI(afi, new->attr);
4245
4246 if (bgp_find_or_add_nexthop(bgp, bgp, nh_afi, safi, new, NULL,
4247 connected)
4248 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
4249 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
4250 else {
4251 if (BGP_DEBUG(nht, NHT)) {
4252 char buf1[INET6_ADDRSTRLEN];
4253 inet_ntop(AF_INET,
4254 (const void *)&attr_new->nexthop,
4255 buf1, INET6_ADDRSTRLEN);
4256 zlog_debug("%s(%s): NH unresolved", __func__,
4257 buf1);
4258 }
4259 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
4260 }
4261 } else
4262 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
4263
4264 /* Addpath ID */
4265 new->addpath_rx_id = addpath_id;
4266
4267 /* Increment prefix */
4268 bgp_aggregate_increment(bgp, p, new, afi, safi);
4269
4270 /* Register new BGP information. */
4271 bgp_path_info_add(dest, new);
4272
4273 /* route_node_get lock */
4274 bgp_dest_unlock_node(dest);
4275
4276 #ifdef ENABLE_BGP_VNC
4277 if (safi == SAFI_MPLS_VPN) {
4278 struct bgp_dest *pdest = NULL;
4279 struct bgp_table *table = NULL;
4280
4281 pdest = bgp_node_get(bgp->rib[afi][safi], (struct prefix *)prd);
4282 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4283 table = bgp_dest_get_bgp_table_info(pdest);
4284
4285 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4286 bgp, prd, table, p, new);
4287 }
4288 bgp_dest_unlock_node(pdest);
4289 }
4290 #endif
4291
4292 /* If this is an EVPN route, process for import. */
4293 if (safi == SAFI_EVPN && CHECK_FLAG(new->flags, BGP_PATH_VALID))
4294 bgp_evpn_import_route(bgp, afi, safi, p, new);
4295
4296 hook_call(bgp_process, bgp, afi, safi, dest, peer, false);
4297
4298 /* Process change. */
4299 bgp_process(bgp, dest, afi, safi);
4300
4301 if (SAFI_UNICAST == safi
4302 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4303 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4304 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
4305 }
4306 if ((SAFI_MPLS_VPN == safi)
4307 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4308
4309 vpn_leak_to_vrf_update(bgp, new);
4310 }
4311 #ifdef ENABLE_BGP_VNC
4312 if (SAFI_MPLS_VPN == safi) {
4313 mpls_label_t label_decoded = decode_label(label);
4314
4315 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4316 sub_type, &label_decoded);
4317 }
4318 if (SAFI_ENCAP == safi) {
4319 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4320 sub_type, NULL);
4321 }
4322 #endif
4323
4324 return 0;
4325
4326 /* This BGP update is filtered. Log the reason then update BGP
4327 entry. */
4328 filtered:
4329 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4330
4331 if (bgp_debug_update(peer, p, NULL, 1)) {
4332 if (!peer->rcvd_attr_printed) {
4333 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
4334 peer->rcvd_attr_str);
4335 peer->rcvd_attr_printed = 1;
4336 }
4337
4338 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
4339 addpath_id ? 1 : 0, addpath_id, evpn,
4340 pfx_buf, sizeof(pfx_buf));
4341 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
4342 peer->host, pfx_buf, reason);
4343 }
4344
4345 if (pi) {
4346 /* If this is an EVPN route, un-import it as it is now filtered.
4347 */
4348 if (safi == SAFI_EVPN)
4349 bgp_evpn_unimport_route(bgp, afi, safi, p, pi);
4350
4351 if (SAFI_UNICAST == safi
4352 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4353 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4354
4355 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
4356 }
4357 if ((SAFI_MPLS_VPN == safi)
4358 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4359
4360 vpn_leak_to_vrf_withdraw(bgp, pi);
4361 }
4362
4363 bgp_rib_remove(dest, pi, peer, afi, safi);
4364 }
4365
4366 bgp_dest_unlock_node(dest);
4367
4368 #ifdef ENABLE_BGP_VNC
4369 /*
4370 * Filtered update is treated as an implicit withdrawal (see
4371 * bgp_rib_remove()
4372 * a few lines above)
4373 */
4374 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4375 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4376 0);
4377 }
4378 #endif
4379
4380 return 0;
4381 }
4382
4383 int bgp_withdraw(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
4384 struct attr *attr, afi_t afi, safi_t safi, int type,
4385 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
4386 uint32_t num_labels, struct bgp_route_evpn *evpn)
4387 {
4388 struct bgp *bgp;
4389 char pfx_buf[BGP_PRD_PATH_STRLEN];
4390 struct bgp_dest *dest;
4391 struct bgp_path_info *pi;
4392
4393 #ifdef ENABLE_BGP_VNC
4394 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4395 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4396 0);
4397 }
4398 #endif
4399
4400 bgp = peer->bgp;
4401
4402 /* Lookup node. */
4403 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
4404
4405 /* If peer is soft reconfiguration enabled. Record input packet for
4406 * further calculation.
4407 *
4408 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4409 * routes that are filtered. This tanks out Quagga RS pretty badly due
4410 * to
4411 * the iteration over all RS clients.
4412 * Since we need to remove the entry from adj_in anyway, do that first
4413 * and
4414 * if there was no entry, we don't need to do anything more.
4415 */
4416 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
4417 && peer != bgp->peer_self)
4418 if (!bgp_adj_in_unset(dest, peer, addpath_id)) {
4419 peer->stat_pfx_dup_withdraw++;
4420
4421 if (bgp_debug_update(peer, p, NULL, 1)) {
4422 bgp_debug_rdpfxpath2str(
4423 afi, safi, prd, p, label, num_labels,
4424 addpath_id ? 1 : 0, addpath_id, NULL,
4425 pfx_buf, sizeof(pfx_buf));
4426 zlog_debug(
4427 "%s withdrawing route %s not in adj-in",
4428 peer->host, pfx_buf);
4429 }
4430 bgp_dest_unlock_node(dest);
4431 return 0;
4432 }
4433
4434 /* Lookup withdrawn route. */
4435 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
4436 if (pi->peer == peer && pi->type == type
4437 && pi->sub_type == sub_type
4438 && pi->addpath_rx_id == addpath_id)
4439 break;
4440
4441 /* Logging. */
4442 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, NULL,
4445 pfx_buf, sizeof(pfx_buf));
4446 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer->host,
4447 pfx_buf);
4448 }
4449
4450 /* Withdraw specified route from routing table. */
4451 if (pi && !CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
4452 bgp_rib_withdraw(dest, pi, peer, afi, safi, prd);
4453 if (SAFI_UNICAST == safi
4454 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4455 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4456 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
4457 }
4458 if ((SAFI_MPLS_VPN == safi)
4459 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4460
4461 vpn_leak_to_vrf_withdraw(bgp, pi);
4462 }
4463 } else if (bgp_debug_update(peer, p, NULL, 1)) {
4464 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
4465 addpath_id ? 1 : 0, addpath_id, NULL,
4466 pfx_buf, sizeof(pfx_buf));
4467 zlog_debug("%s Can't find the route %s", peer->host, pfx_buf);
4468 }
4469
4470 /* Unlock bgp_node_get() lock. */
4471 bgp_dest_unlock_node(dest);
4472
4473 return 0;
4474 }
4475
4476 void bgp_default_originate(struct peer *peer, afi_t afi, safi_t safi,
4477 int withdraw)
4478 {
4479 struct update_subgroup *subgrp;
4480 subgrp = peer_subgroup(peer, afi, safi);
4481 subgroup_default_originate(subgrp, withdraw);
4482 }
4483
4484
4485 /*
4486 * bgp_stop_announce_route_timer
4487 */
4488 void bgp_stop_announce_route_timer(struct peer_af *paf)
4489 {
4490 if (!paf->t_announce_route)
4491 return;
4492
4493 thread_cancel(&paf->t_announce_route);
4494 }
4495
4496 /*
4497 * bgp_announce_route_timer_expired
4498 *
4499 * Callback that is invoked when the route announcement timer for a
4500 * peer_af expires.
4501 */
4502 static int bgp_announce_route_timer_expired(struct thread *t)
4503 {
4504 struct peer_af *paf;
4505 struct peer *peer;
4506
4507 paf = THREAD_ARG(t);
4508 peer = paf->peer;
4509
4510 if (!peer_established(peer))
4511 return 0;
4512
4513 if (!peer->afc_nego[paf->afi][paf->safi])
4514 return 0;
4515
4516 peer_af_announce_route(paf, 1);
4517
4518 /* Notify BGP conditional advertisement scanner percess */
4519 peer->advmap_config_change[paf->afi][paf->safi] = true;
4520
4521 return 0;
4522 }
4523
4524 /*
4525 * bgp_announce_route
4526 *
4527 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
4528 */
4529 void bgp_announce_route(struct peer *peer, afi_t afi, safi_t safi)
4530 {
4531 struct peer_af *paf;
4532 struct update_subgroup *subgrp;
4533
4534 paf = peer_af_find(peer, afi, safi);
4535 if (!paf)
4536 return;
4537 subgrp = PAF_SUBGRP(paf);
4538
4539 /*
4540 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
4541 * or a refresh has already been triggered.
4542 */
4543 if (!subgrp || paf->t_announce_route)
4544 return;
4545
4546 /*
4547 * Start a timer to stagger/delay the announce. This serves
4548 * two purposes - announcement can potentially be combined for
4549 * multiple peers and the announcement doesn't happen in the
4550 * vty context.
4551 */
4552 thread_add_timer_msec(bm->master, bgp_announce_route_timer_expired, paf,
4553 (subgrp->peer_count == 1)
4554 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
4555 : BGP_ANNOUNCE_ROUTE_DELAY_MS,
4556 &paf->t_announce_route);
4557 }
4558
4559 /*
4560 * Announce routes from all AF tables to a peer.
4561 *
4562 * This should ONLY be called when there is a need to refresh the
4563 * routes to the peer based on a policy change for this peer alone
4564 * or a route refresh request received from the peer.
4565 * The operation will result in splitting the peer from its existing
4566 * subgroups and putting it in new subgroups.
4567 */
4568 void bgp_announce_route_all(struct peer *peer)
4569 {
4570 afi_t afi;
4571 safi_t safi;
4572
4573 FOREACH_AFI_SAFI (afi, safi)
4574 bgp_announce_route(peer, afi, safi);
4575 }
4576
4577 /* Flag or unflag bgp_dest to determine whether it should be treated by
4578 * bgp_soft_reconfig_table_task.
4579 * Flag if flag is true. Unflag if flag is false.
4580 */
4581 static void bgp_soft_reconfig_table_flag(struct bgp_table *table, bool flag)
4582 {
4583 struct bgp_dest *dest;
4584 struct bgp_adj_in *ain;
4585
4586 if (!table)
4587 return;
4588
4589 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
4590 for (ain = dest->adj_in; ain; ain = ain->next) {
4591 if (ain->peer != NULL)
4592 break;
4593 }
4594 if (flag && ain != NULL && ain->peer != NULL)
4595 SET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
4596 else
4597 UNSET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
4598 }
4599 }
4600
4601 static int bgp_soft_reconfig_table_update(struct peer *peer,
4602 struct bgp_dest *dest,
4603 struct bgp_adj_in *ain, afi_t afi,
4604 safi_t safi, struct prefix_rd *prd)
4605 {
4606 struct bgp_path_info *pi;
4607 uint32_t num_labels = 0;
4608 mpls_label_t *label_pnt = NULL;
4609 struct bgp_route_evpn evpn;
4610
4611 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
4612 if (pi->peer == peer)
4613 break;
4614
4615 if (pi && pi->extra)
4616 num_labels = pi->extra->num_labels;
4617 if (num_labels)
4618 label_pnt = &pi->extra->label[0];
4619 if (pi)
4620 memcpy(&evpn, bgp_attr_get_evpn_overlay(pi->attr),
4621 sizeof(evpn));
4622 else
4623 memset(&evpn, 0, sizeof(evpn));
4624
4625 return bgp_update(peer, bgp_dest_get_prefix(dest), ain->addpath_rx_id,
4626 ain->attr, afi, safi, ZEBRA_ROUTE_BGP,
4627 BGP_ROUTE_NORMAL, prd, label_pnt, num_labels, 1,
4628 &evpn);
4629 }
4630
4631 static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi,
4632 struct bgp_table *table,
4633 struct prefix_rd *prd)
4634 {
4635 int ret;
4636 struct bgp_dest *dest;
4637 struct bgp_adj_in *ain;
4638
4639 if (!table)
4640 table = peer->bgp->rib[afi][safi];
4641
4642 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
4643 for (ain = dest->adj_in; ain; ain = ain->next) {
4644 if (ain->peer != peer)
4645 continue;
4646
4647 ret = bgp_soft_reconfig_table_update(peer, dest, ain,
4648 afi, safi, prd);
4649
4650 if (ret < 0) {
4651 bgp_dest_unlock_node(dest);
4652 return;
4653 }
4654 }
4655 }
4656
4657 /* Do soft reconfig table per bgp table.
4658 * Walk on SOFT_RECONFIG_TASK_MAX_PREFIX bgp_dest,
4659 * when BGP_NODE_SOFT_RECONFIG is set,
4660 * reconfig bgp_dest for list of table->soft_reconfig_peers peers.
4661 * Schedule a new thread to continue the job.
4662 * Without splitting the full job into several part,
4663 * vtysh waits for the job to finish before responding to a BGP command
4664 */
4665 static int bgp_soft_reconfig_table_task(struct thread *thread)
4666 {
4667 uint32_t iter, max_iter;
4668 int ret;
4669 struct bgp_dest *dest;
4670 struct bgp_adj_in *ain;
4671 struct peer *peer;
4672 struct bgp_table *table;
4673 struct prefix_rd *prd;
4674 struct listnode *node, *nnode;
4675
4676 table = THREAD_ARG(thread);
4677 prd = NULL;
4678
4679 max_iter = SOFT_RECONFIG_TASK_MAX_PREFIX;
4680 if (table->soft_reconfig_init) {
4681 /* first call of the function with a new srta structure.
4682 * Don't do any treatment this time on nodes
4683 * in order vtysh to respond quickly
4684 */
4685 max_iter = 0;
4686 }
4687
4688 for (iter = 0, dest = bgp_table_top(table); (dest && iter < max_iter);
4689 dest = bgp_route_next(dest)) {
4690 if (!CHECK_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG))
4691 continue;
4692
4693 UNSET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
4694
4695 for (ain = dest->adj_in; ain; ain = ain->next) {
4696 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node,
4697 nnode, peer)) {
4698 if (ain->peer != peer)
4699 continue;
4700
4701 ret = bgp_soft_reconfig_table_update(
4702 peer, dest, ain, table->afi,
4703 table->safi, prd);
4704 iter++;
4705
4706 if (ret < 0) {
4707 bgp_dest_unlock_node(dest);
4708 listnode_delete(
4709 table->soft_reconfig_peers,
4710 peer);
4711 bgp_announce_route(peer, table->afi,
4712 table->safi);
4713 if (list_isempty(
4714 table->soft_reconfig_peers)) {
4715 list_delete(
4716 &table->soft_reconfig_peers);
4717 bgp_soft_reconfig_table_flag(
4718 table, false);
4719 return 0;
4720 }
4721 }
4722 }
4723 }
4724 }
4725
4726 /* we're either starting the initial iteration,
4727 * or we're going to continue an ongoing iteration
4728 */
4729 if (dest || table->soft_reconfig_init) {
4730 table->soft_reconfig_init = false;
4731 thread_add_event(bm->master, bgp_soft_reconfig_table_task,
4732 table, 0, &table->soft_reconfig_thread);
4733 return 0;
4734 }
4735 /* we're done, clean up the background iteration context info and
4736 schedule route annoucement
4737 */
4738 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node, nnode, peer)) {
4739 listnode_delete(table->soft_reconfig_peers, peer);
4740 bgp_announce_route(peer, table->afi, table->safi);
4741 }
4742
4743 list_delete(&table->soft_reconfig_peers);
4744
4745 return 0;
4746 }
4747
4748
4749 /* Cancel soft_reconfig_table task matching bgp instance, bgp_table
4750 * and peer.
4751 * - bgp cannot be NULL
4752 * - if table and peer are NULL, cancel all threads within the bgp instance
4753 * - if table is NULL and peer is not,
4754 * remove peer in all threads within the bgp instance
4755 * - if peer is NULL, cancel all threads matching table within the bgp instance
4756 */
4757 void bgp_soft_reconfig_table_task_cancel(const struct bgp *bgp,
4758 const struct bgp_table *table,
4759 const struct peer *peer)
4760 {
4761 struct peer *npeer;
4762 struct listnode *node, *nnode;
4763 int afi, safi;
4764 struct bgp_table *ntable;
4765
4766 if (!bgp)
4767 return;
4768
4769 FOREACH_AFI_SAFI (afi, safi) {
4770 ntable = bgp->rib[afi][safi];
4771 if (!ntable)
4772 continue;
4773 if (table && table != ntable)
4774 continue;
4775
4776 for (ALL_LIST_ELEMENTS(ntable->soft_reconfig_peers, node, nnode,
4777 npeer)) {
4778 if (peer && peer != npeer)
4779 continue;
4780 listnode_delete(ntable->soft_reconfig_peers, npeer);
4781 }
4782
4783 if (!ntable->soft_reconfig_peers
4784 || !list_isempty(ntable->soft_reconfig_peers))
4785 continue;
4786
4787 list_delete(&ntable->soft_reconfig_peers);
4788 bgp_soft_reconfig_table_flag(ntable, false);
4789 BGP_TIMER_OFF(ntable->soft_reconfig_thread);
4790 }
4791 }
4792
4793 void bgp_soft_reconfig_in(struct peer *peer, afi_t afi, safi_t safi)
4794 {
4795 struct bgp_dest *dest;
4796 struct bgp_table *table;
4797 struct listnode *node, *nnode;
4798 struct peer *npeer;
4799 struct peer_af *paf;
4800
4801 if (!peer_established(peer))
4802 return;
4803
4804 if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP)
4805 && (safi != SAFI_EVPN)) {
4806 table = peer->bgp->rib[afi][safi];
4807 if (!table)
4808 return;
4809
4810 table->soft_reconfig_init = true;
4811
4812 if (!table->soft_reconfig_peers)
4813 table->soft_reconfig_peers = list_new();
4814 npeer = NULL;
4815 /* add peer to the table soft_reconfig_peers if not already
4816 * there
4817 */
4818 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node, nnode,
4819 npeer)) {
4820 if (peer == npeer)
4821 break;
4822 }
4823 if (peer != npeer)
4824 listnode_add(table->soft_reconfig_peers, peer);
4825
4826 /* (re)flag all bgp_dest in table. Existing soft_reconfig_in job
4827 * on table would start back at the beginning.
4828 */
4829 bgp_soft_reconfig_table_flag(table, true);
4830
4831 if (!table->soft_reconfig_thread)
4832 thread_add_event(bm->master,
4833 bgp_soft_reconfig_table_task, table, 0,
4834 &table->soft_reconfig_thread);
4835 /* Cancel bgp_announce_route_timer_expired threads.
4836 * bgp_announce_route_timer_expired threads have been scheduled
4837 * to announce routes as soon as the soft_reconfigure process
4838 * finishes.
4839 * In this case, soft_reconfigure is also scheduled by using
4840 * a thread but is planned after the
4841 * bgp_announce_route_timer_expired threads. It means that,
4842 * without cancelling the threads, the route announcement task
4843 * would run before the soft reconfiguration one. That would
4844 * useless and would block vtysh during several seconds. Route
4845 * announcements are rescheduled as soon as the soft_reconfigure
4846 * process finishes.
4847 */
4848 paf = peer_af_find(peer, afi, safi);
4849 if (paf)
4850 bgp_stop_announce_route_timer(paf);
4851 } else
4852 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4853 dest = bgp_route_next(dest)) {
4854 table = bgp_dest_get_bgp_table_info(dest);
4855
4856 if (table == NULL)
4857 continue;
4858
4859 const struct prefix *p = bgp_dest_get_prefix(dest);
4860 struct prefix_rd prd;
4861
4862 prd.family = AF_UNSPEC;
4863 prd.prefixlen = 64;
4864 memcpy(&prd.val, p->u.val, 8);
4865
4866 bgp_soft_reconfig_table(peer, afi, safi, table, &prd);
4867 }
4868 }
4869
4870
4871 struct bgp_clear_node_queue {
4872 struct bgp_dest *dest;
4873 };
4874
4875 static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data)
4876 {
4877 struct bgp_clear_node_queue *cnq = data;
4878 struct bgp_dest *dest = cnq->dest;
4879 struct peer *peer = wq->spec.data;
4880 struct bgp_path_info *pi;
4881 struct bgp *bgp;
4882 afi_t afi = bgp_dest_table(dest)->afi;
4883 safi_t safi = bgp_dest_table(dest)->safi;
4884
4885 assert(dest && peer);
4886 bgp = peer->bgp;
4887
4888 /* It is possible that we have multiple paths for a prefix from a peer
4889 * if that peer is using AddPath.
4890 */
4891 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
4892 if (pi->peer != peer)
4893 continue;
4894
4895 /* graceful restart STALE flag set. */
4896 if (((CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)
4897 && peer->nsf[afi][safi])
4898 || CHECK_FLAG(peer->af_sflags[afi][safi],
4899 PEER_STATUS_ENHANCED_REFRESH))
4900 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
4901 && !CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
4902 bgp_path_info_set_flag(dest, pi, BGP_PATH_STALE);
4903 else {
4904 /* If this is an EVPN route, process for
4905 * un-import. */
4906 if (safi == SAFI_EVPN)
4907 bgp_evpn_unimport_route(
4908 bgp, afi, safi,
4909 bgp_dest_get_prefix(dest), pi);
4910 /* Handle withdraw for VRF route-leaking and L3VPN */
4911 if (SAFI_UNICAST == safi
4912 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF ||
4913 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4914 vpn_leak_from_vrf_withdraw(bgp_get_default(),
4915 bgp, pi);
4916 }
4917 if (SAFI_MPLS_VPN == safi &&
4918 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
4919 vpn_leak_to_vrf_withdraw(bgp, pi);
4920 }
4921
4922 bgp_rib_remove(dest, pi, peer, afi, safi);
4923 }
4924 }
4925 return WQ_SUCCESS;
4926 }
4927
4928 static void bgp_clear_node_queue_del(struct work_queue *wq, void *data)
4929 {
4930 struct bgp_clear_node_queue *cnq = data;
4931 struct bgp_dest *dest = cnq->dest;
4932 struct bgp_table *table = bgp_dest_table(dest);
4933
4934 bgp_dest_unlock_node(dest);
4935 bgp_table_unlock(table);
4936 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE, cnq);
4937 }
4938
4939 static void bgp_clear_node_complete(struct work_queue *wq)
4940 {
4941 struct peer *peer = wq->spec.data;
4942
4943 /* Tickle FSM to start moving again */
4944 BGP_EVENT_ADD(peer, Clearing_Completed);
4945
4946 peer_unlock(peer); /* bgp_clear_route */
4947 }
4948
4949 static void bgp_clear_node_queue_init(struct peer *peer)
4950 {
4951 char wname[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
4952
4953 snprintf(wname, sizeof(wname), "clear %s", peer->host);
4954 #undef CLEAR_QUEUE_NAME_LEN
4955
4956 peer->clear_node_queue = work_queue_new(bm->master, wname);
4957 peer->clear_node_queue->spec.hold = 10;
4958 peer->clear_node_queue->spec.workfunc = &bgp_clear_route_node;
4959 peer->clear_node_queue->spec.del_item_data = &bgp_clear_node_queue_del;
4960 peer->clear_node_queue->spec.completion_func = &bgp_clear_node_complete;
4961 peer->clear_node_queue->spec.max_retries = 0;
4962
4963 /* we only 'lock' this peer reference when the queue is actually active
4964 */
4965 peer->clear_node_queue->spec.data = peer;
4966 }
4967
4968 static void bgp_clear_route_table(struct peer *peer, afi_t afi, safi_t safi,
4969 struct bgp_table *table)
4970 {
4971 struct bgp_dest *dest;
4972 int force = peer->bgp->process_queue ? 0 : 1;
4973
4974 if (!table)
4975 table = peer->bgp->rib[afi][safi];
4976
4977 /* If still no table => afi/safi isn't configured at all or smth. */
4978 if (!table)
4979 return;
4980
4981 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
4982 struct bgp_path_info *pi, *next;
4983 struct bgp_adj_in *ain;
4984 struct bgp_adj_in *ain_next;
4985
4986 /* XXX:TODO: This is suboptimal, every non-empty route_node is
4987 * queued for every clearing peer, regardless of whether it is
4988 * relevant to the peer at hand.
4989 *
4990 * Overview: There are 3 different indices which need to be
4991 * scrubbed, potentially, when a peer is removed:
4992 *
4993 * 1 peer's routes visible via the RIB (ie accepted routes)
4994 * 2 peer's routes visible by the (optional) peer's adj-in index
4995 * 3 other routes visible by the peer's adj-out index
4996 *
4997 * 3 there is no hurry in scrubbing, once the struct peer is
4998 * removed from bgp->peer, we could just GC such deleted peer's
4999 * adj-outs at our leisure.
5000 *
5001 * 1 and 2 must be 'scrubbed' in some way, at least made
5002 * invisible via RIB index before peer session is allowed to be
5003 * brought back up. So one needs to know when such a 'search' is
5004 * complete.
5005 *
5006 * Ideally:
5007 *
5008 * - there'd be a single global queue or a single RIB walker
5009 * - rather than tracking which route_nodes still need to be
5010 * examined on a peer basis, we'd track which peers still
5011 * aren't cleared
5012 *
5013 * Given that our per-peer prefix-counts now should be reliable,
5014 * this may actually be achievable. It doesn't seem to be a huge
5015 * problem at this time,
5016 *
5017 * It is possible that we have multiple paths for a prefix from
5018 * a peer
5019 * if that peer is using AddPath.
5020 */
5021 ain = dest->adj_in;
5022 while (ain) {
5023 ain_next = ain->next;
5024
5025 if (ain->peer == peer)
5026 bgp_adj_in_remove(dest, ain);
5027
5028 ain = ain_next;
5029 }
5030
5031 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
5032 next = pi->next;
5033 if (pi->peer != peer)
5034 continue;
5035
5036 if (force)
5037 bgp_path_info_reap(dest, pi);
5038 else {
5039 struct bgp_clear_node_queue *cnq;
5040
5041 /* both unlocked in bgp_clear_node_queue_del */
5042 bgp_table_lock(bgp_dest_table(dest));
5043 bgp_dest_lock_node(dest);
5044 cnq = XCALLOC(
5045 MTYPE_BGP_CLEAR_NODE_QUEUE,
5046 sizeof(struct bgp_clear_node_queue));
5047 cnq->dest = dest;
5048 work_queue_add(peer->clear_node_queue, cnq);
5049 break;
5050 }
5051 }
5052 }
5053 return;
5054 }
5055
5056 void bgp_clear_route(struct peer *peer, afi_t afi, safi_t safi)
5057 {
5058 struct bgp_dest *dest;
5059 struct bgp_table *table;
5060
5061 if (peer->clear_node_queue == NULL)
5062 bgp_clear_node_queue_init(peer);
5063
5064 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
5065 * Idle until it receives a Clearing_Completed event. This protects
5066 * against peers which flap faster than we can we clear, which could
5067 * lead to:
5068 *
5069 * a) race with routes from the new session being installed before
5070 * clear_route_node visits the node (to delete the route of that
5071 * peer)
5072 * b) resource exhaustion, clear_route_node likely leads to an entry
5073 * on the process_main queue. Fast-flapping could cause that queue
5074 * to grow and grow.
5075 */
5076
5077 /* lock peer in assumption that clear-node-queue will get nodes; if so,
5078 * the unlock will happen upon work-queue completion; other wise, the
5079 * unlock happens at the end of this function.
5080 */
5081 if (!peer->clear_node_queue->thread)
5082 peer_lock(peer);
5083
5084 if (safi != SAFI_MPLS_VPN && safi != SAFI_ENCAP && safi != SAFI_EVPN)
5085 bgp_clear_route_table(peer, afi, safi, NULL);
5086 else
5087 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5088 dest = bgp_route_next(dest)) {
5089 table = bgp_dest_get_bgp_table_info(dest);
5090 if (!table)
5091 continue;
5092
5093 bgp_clear_route_table(peer, afi, safi, table);
5094 }
5095
5096 /* unlock if no nodes got added to the clear-node-queue. */
5097 if (!peer->clear_node_queue->thread)
5098 peer_unlock(peer);
5099 }
5100
5101 void bgp_clear_route_all(struct peer *peer)
5102 {
5103 afi_t afi;
5104 safi_t safi;
5105
5106 FOREACH_AFI_SAFI (afi, safi)
5107 bgp_clear_route(peer, afi, safi);
5108
5109 #ifdef ENABLE_BGP_VNC
5110 rfapiProcessPeerDown(peer);
5111 #endif
5112 }
5113
5114 void bgp_clear_adj_in(struct peer *peer, afi_t afi, safi_t safi)
5115 {
5116 struct bgp_table *table;
5117 struct bgp_dest *dest;
5118 struct bgp_adj_in *ain;
5119 struct bgp_adj_in *ain_next;
5120
5121 table = peer->bgp->rib[afi][safi];
5122
5123 /* It is possible that we have multiple paths for a prefix from a peer
5124 * if that peer is using AddPath.
5125 */
5126 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
5127 ain = dest->adj_in;
5128
5129 while (ain) {
5130 ain_next = ain->next;
5131
5132 if (ain->peer == peer)
5133 bgp_adj_in_remove(dest, ain);
5134
5135 ain = ain_next;
5136 }
5137 }
5138 }
5139
5140 void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
5141 {
5142 struct bgp_dest *dest;
5143 struct bgp_path_info *pi;
5144 struct bgp_table *table;
5145
5146 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
5147 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5148 dest = bgp_route_next(dest)) {
5149 struct bgp_dest *rm;
5150
5151 /* look for neighbor in tables */
5152 table = bgp_dest_get_bgp_table_info(dest);
5153 if (!table)
5154 continue;
5155
5156 for (rm = bgp_table_top(table); rm;
5157 rm = bgp_route_next(rm))
5158 for (pi = bgp_dest_get_bgp_path_info(rm); pi;
5159 pi = pi->next) {
5160 if (pi->peer != peer)
5161 continue;
5162 if (!CHECK_FLAG(pi->flags,
5163 BGP_PATH_STALE))
5164 break;
5165
5166 bgp_rib_remove(rm, pi, peer, afi, safi);
5167 break;
5168 }
5169 }
5170 } else {
5171 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5172 dest = bgp_route_next(dest))
5173 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
5174 pi = pi->next) {
5175 if (pi->peer != peer)
5176 continue;
5177 if (!CHECK_FLAG(pi->flags, BGP_PATH_STALE))
5178 break;
5179 bgp_rib_remove(dest, pi, peer, afi, safi);
5180 break;
5181 }
5182 }
5183 }
5184
5185 void bgp_set_stale_route(struct peer *peer, afi_t afi, safi_t safi)
5186 {
5187 struct bgp_dest *dest, *ndest;
5188 struct bgp_path_info *pi;
5189 struct bgp_table *table;
5190
5191 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
5192 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5193 dest = bgp_route_next(dest)) {
5194 table = bgp_dest_get_bgp_table_info(dest);
5195 if (!table)
5196 continue;
5197
5198 for (ndest = bgp_table_top(table); ndest;
5199 ndest = bgp_route_next(ndest)) {
5200 for (pi = bgp_dest_get_bgp_path_info(ndest); pi;
5201 pi = pi->next) {
5202 if (pi->peer != peer)
5203 continue;
5204
5205 if ((CHECK_FLAG(
5206 peer->af_sflags[afi][safi],
5207 PEER_STATUS_ENHANCED_REFRESH))
5208 && !CHECK_FLAG(pi->flags,
5209 BGP_PATH_STALE)
5210 && !CHECK_FLAG(
5211 pi->flags,
5212 BGP_PATH_UNUSEABLE)) {
5213 if (bgp_debug_neighbor_events(
5214 peer))
5215 zlog_debug(
5216 "%s: route-refresh for %s/%s, marking prefix %pFX as stale",
5217 peer->host,
5218 afi2str(afi),
5219 safi2str(safi),
5220 bgp_dest_get_prefix(
5221 ndest));
5222
5223 bgp_path_info_set_flag(
5224 ndest, pi,
5225 BGP_PATH_STALE);
5226 }
5227 }
5228 }
5229 }
5230 } else {
5231 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5232 dest = bgp_route_next(dest)) {
5233 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
5234 pi = pi->next) {
5235 if (pi->peer != peer)
5236 continue;
5237
5238 if ((CHECK_FLAG(peer->af_sflags[afi][safi],
5239 PEER_STATUS_ENHANCED_REFRESH))
5240 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
5241 && !CHECK_FLAG(pi->flags,
5242 BGP_PATH_UNUSEABLE)) {
5243 if (bgp_debug_neighbor_events(peer))
5244 zlog_debug(
5245 "%s: route-refresh for %s/%s, marking prefix %pFX as stale",
5246 peer->host,
5247 afi2str(afi),
5248 safi2str(safi),
5249 bgp_dest_get_prefix(
5250 dest));
5251
5252 bgp_path_info_set_flag(dest, pi,
5253 BGP_PATH_STALE);
5254 }
5255 }
5256 }
5257 }
5258 }
5259
5260 bool bgp_outbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
5261 {
5262 if (peer->sort == BGP_PEER_IBGP)
5263 return true;
5264
5265 if (peer->sort == BGP_PEER_EBGP
5266 && (ROUTE_MAP_OUT_NAME(filter) || PREFIX_LIST_OUT_NAME(filter)
5267 || FILTER_LIST_OUT_NAME(filter)
5268 || DISTRIBUTE_OUT_NAME(filter)))
5269 return true;
5270 return false;
5271 }
5272
5273 bool bgp_inbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
5274 {
5275 if (peer->sort == BGP_PEER_IBGP)
5276 return true;
5277
5278 if (peer->sort == BGP_PEER_EBGP
5279 && (ROUTE_MAP_IN_NAME(filter) || PREFIX_LIST_IN_NAME(filter)
5280 || FILTER_LIST_IN_NAME(filter)
5281 || DISTRIBUTE_IN_NAME(filter)))
5282 return true;
5283 return false;
5284 }
5285
5286 static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table,
5287 safi_t safi)
5288 {
5289 struct bgp_dest *dest;
5290 struct bgp_path_info *pi;
5291 struct bgp_path_info *next;
5292
5293 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
5294 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
5295 const struct prefix *p = bgp_dest_get_prefix(dest);
5296
5297 next = pi->next;
5298
5299 /* Unimport EVPN routes from VRFs */
5300 if (safi == SAFI_EVPN)
5301 bgp_evpn_unimport_route(bgp, AFI_L2VPN,
5302 SAFI_EVPN, p, pi);
5303
5304 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)
5305 && pi->type == ZEBRA_ROUTE_BGP
5306 && (pi->sub_type == BGP_ROUTE_NORMAL
5307 || pi->sub_type == BGP_ROUTE_AGGREGATE
5308 || pi->sub_type == BGP_ROUTE_IMPORTED)) {
5309
5310 if (bgp_fibupd_safi(safi))
5311 bgp_zebra_withdraw(p, pi, bgp, safi);
5312 }
5313
5314 bgp_path_info_reap(dest, pi);
5315 }
5316 }
5317
5318 /* Delete all kernel routes. */
5319 void bgp_cleanup_routes(struct bgp *bgp)
5320 {
5321 afi_t afi;
5322 struct bgp_dest *dest;
5323 struct bgp_table *table;
5324
5325 for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
5326 if (afi == AFI_L2VPN)
5327 continue;
5328 bgp_cleanup_table(bgp, bgp->rib[afi][SAFI_UNICAST],
5329 SAFI_UNICAST);
5330 /*
5331 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
5332 */
5333 if (afi != AFI_L2VPN) {
5334 safi_t safi;
5335 safi = SAFI_MPLS_VPN;
5336 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
5337 dest = bgp_route_next(dest)) {
5338 table = bgp_dest_get_bgp_table_info(dest);
5339 if (table != NULL) {
5340 bgp_cleanup_table(bgp, table, safi);
5341 bgp_table_finish(&table);
5342 bgp_dest_set_bgp_table_info(dest, NULL);
5343 bgp_dest_unlock_node(dest);
5344 }
5345 }
5346 safi = SAFI_ENCAP;
5347 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
5348 dest = bgp_route_next(dest)) {
5349 table = bgp_dest_get_bgp_table_info(dest);
5350 if (table != NULL) {
5351 bgp_cleanup_table(bgp, table, safi);
5352 bgp_table_finish(&table);
5353 bgp_dest_set_bgp_table_info(dest, NULL);
5354 bgp_dest_unlock_node(dest);
5355 }
5356 }
5357 }
5358 }
5359 for (dest = bgp_table_top(bgp->rib[AFI_L2VPN][SAFI_EVPN]); dest;
5360 dest = bgp_route_next(dest)) {
5361 table = bgp_dest_get_bgp_table_info(dest);
5362 if (table != NULL) {
5363 bgp_cleanup_table(bgp, table, SAFI_EVPN);
5364 bgp_table_finish(&table);
5365 bgp_dest_set_bgp_table_info(dest, NULL);
5366 bgp_dest_unlock_node(dest);
5367 }
5368 }
5369 }
5370
5371 void bgp_reset(void)
5372 {
5373 vty_reset();
5374 bgp_zclient_reset();
5375 access_list_reset();
5376 prefix_list_reset();
5377 }
5378
5379 static int bgp_addpath_encode_rx(struct peer *peer, afi_t afi, safi_t safi)
5380 {
5381 return (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV)
5382 && CHECK_FLAG(peer->af_cap[afi][safi],
5383 PEER_CAP_ADDPATH_AF_TX_RCV));
5384 }
5385
5386 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
5387 value. */
5388 int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
5389 struct bgp_nlri *packet)
5390 {
5391 uint8_t *pnt;
5392 uint8_t *lim;
5393 struct prefix p;
5394 int psize;
5395 int ret;
5396 afi_t afi;
5397 safi_t safi;
5398 int addpath_encoded;
5399 uint32_t addpath_id;
5400
5401 pnt = packet->nlri;
5402 lim = pnt + packet->length;
5403 afi = packet->afi;
5404 safi = packet->safi;
5405 addpath_id = 0;
5406 addpath_encoded = bgp_addpath_encode_rx(peer, afi, safi);
5407
5408 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
5409 syntactic validity. If the field is syntactically incorrect,
5410 then the Error Subcode is set to Invalid Network Field. */
5411 for (; pnt < lim; pnt += psize) {
5412 /* Clear prefix structure. */
5413 memset(&p, 0, sizeof(struct prefix));
5414
5415 if (addpath_encoded) {
5416
5417 /* When packet overflow occurs return immediately. */
5418 if (pnt + BGP_ADDPATH_ID_LEN >= lim)
5419 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
5420
5421 memcpy(&addpath_id, pnt, BGP_ADDPATH_ID_LEN);
5422 addpath_id = ntohl(addpath_id);
5423 pnt += BGP_ADDPATH_ID_LEN;
5424 }
5425
5426 /* Fetch prefix length. */
5427 p.prefixlen = *pnt++;
5428 /* afi/safi validity already verified by caller,
5429 * bgp_update_receive */
5430 p.family = afi2family(afi);
5431
5432 /* Prefix length check. */
5433 if (p.prefixlen > prefix_blen(&p) * 8) {
5434 flog_err(
5435 EC_BGP_UPDATE_RCV,
5436 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
5437 peer->host, p.prefixlen, packet->afi);
5438 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH;
5439 }
5440
5441 /* Packet size overflow check. */
5442 psize = PSIZE(p.prefixlen);
5443
5444 /* When packet overflow occur return immediately. */
5445 if (pnt + psize > lim) {
5446 flog_err(
5447 EC_BGP_UPDATE_RCV,
5448 "%s [Error] Update packet error (prefix length %d overflows packet)",
5449 peer->host, p.prefixlen);
5450 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
5451 }
5452
5453 /* Defensive coding, double-check the psize fits in a struct
5454 * prefix */
5455 if (psize > (ssize_t)sizeof(p.u)) {
5456 flog_err(
5457 EC_BGP_UPDATE_RCV,
5458 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
5459 peer->host, p.prefixlen, sizeof(p.u));
5460 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
5461 }
5462
5463 /* Fetch prefix from NLRI packet. */
5464 memcpy(p.u.val, pnt, psize);
5465
5466 /* Check address. */
5467 if (afi == AFI_IP && safi == SAFI_UNICAST) {
5468 if (IN_CLASSD(ntohl(p.u.prefix4.s_addr))) {
5469 /* From RFC4271 Section 6.3:
5470 *
5471 * If a prefix in the NLRI field is semantically
5472 * incorrect
5473 * (e.g., an unexpected multicast IP address),
5474 * an error SHOULD
5475 * be logged locally, and the prefix SHOULD be
5476 * ignored.
5477 */
5478 flog_err(
5479 EC_BGP_UPDATE_RCV,
5480 "%s: IPv4 unicast NLRI is multicast address %pI4, ignoring",
5481 peer->host, &p.u.prefix4);
5482 continue;
5483 }
5484 }
5485
5486 /* Check address. */
5487 if (afi == AFI_IP6 && safi == SAFI_UNICAST) {
5488 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
5489 flog_err(
5490 EC_BGP_UPDATE_RCV,
5491 "%s: IPv6 unicast NLRI is link-local address %pI6, ignoring",
5492 peer->host, &p.u.prefix6);
5493
5494 continue;
5495 }
5496 if (IN6_IS_ADDR_MULTICAST(&p.u.prefix6)) {
5497 flog_err(
5498 EC_BGP_UPDATE_RCV,
5499 "%s: IPv6 unicast NLRI is multicast address %pI6, ignoring",
5500 peer->host, &p.u.prefix6);
5501
5502 continue;
5503 }
5504 }
5505
5506 /* Normal process. */
5507 if (attr)
5508 ret = bgp_update(peer, &p, addpath_id, attr, afi, safi,
5509 ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
5510 NULL, NULL, 0, 0, NULL);
5511 else
5512 ret = bgp_withdraw(peer, &p, addpath_id, attr, afi,
5513 safi, ZEBRA_ROUTE_BGP,
5514 BGP_ROUTE_NORMAL, NULL, NULL, 0,
5515 NULL);
5516
5517 /* Do not send BGP notification twice when maximum-prefix count
5518 * overflow. */
5519 if (CHECK_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
5520 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW;
5521
5522 /* Address family configuration mismatch. */
5523 if (ret < 0)
5524 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY;
5525 }
5526
5527 /* Packet length consistency check. */
5528 if (pnt != lim) {
5529 flog_err(
5530 EC_BGP_UPDATE_RCV,
5531 "%s [Error] Update packet error (prefix length mismatch with total length)",
5532 peer->host);
5533 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
5534 }
5535
5536 return BGP_NLRI_PARSE_OK;
5537 }
5538
5539 static struct bgp_static *bgp_static_new(void)
5540 {
5541 return XCALLOC(MTYPE_BGP_STATIC, sizeof(struct bgp_static));
5542 }
5543
5544 static void bgp_static_free(struct bgp_static *bgp_static)
5545 {
5546 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
5547 route_map_counter_decrement(bgp_static->rmap.map);
5548
5549 XFREE(MTYPE_ATTR, bgp_static->eth_s_id);
5550 XFREE(MTYPE_BGP_STATIC, bgp_static);
5551 }
5552
5553 void bgp_static_update(struct bgp *bgp, const struct prefix *p,
5554 struct bgp_static *bgp_static, afi_t afi, safi_t safi)
5555 {
5556 struct bgp_dest *dest;
5557 struct bgp_path_info *pi;
5558 struct bgp_path_info *new;
5559 struct bgp_path_info rmap_path;
5560 struct attr attr;
5561 struct attr *attr_new;
5562 route_map_result_t ret;
5563 #ifdef ENABLE_BGP_VNC
5564 int vnc_implicit_withdraw = 0;
5565 #endif
5566
5567 assert(bgp_static);
5568
5569 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
5570
5571 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
5572
5573 attr.nexthop = bgp_static->igpnexthop;
5574 attr.med = bgp_static->igpmetric;
5575 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
5576
5577 if (bgp_static->atomic)
5578 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
5579
5580 /* Store label index, if required. */
5581 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX) {
5582 attr.label_index = bgp_static->label_index;
5583 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
5584 }
5585
5586 /* Apply route-map. */
5587 if (bgp_static->rmap.name) {
5588 struct attr attr_tmp = attr;
5589
5590 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
5591 rmap_path.peer = bgp->peer_self;
5592 rmap_path.attr = &attr_tmp;
5593
5594 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
5595
5596 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
5597
5598 bgp->peer_self->rmap_type = 0;
5599
5600 if (ret == RMAP_DENYMATCH) {
5601 /* Free uninterned attribute. */
5602 bgp_attr_flush(&attr_tmp);
5603
5604 /* Unintern original. */
5605 aspath_unintern(&attr.aspath);
5606 bgp_static_withdraw(bgp, p, afi, safi);
5607 return;
5608 }
5609
5610 if (bgp_in_graceful_shutdown(bgp))
5611 bgp_attr_add_gshut_community(&attr_tmp);
5612
5613 attr_new = bgp_attr_intern(&attr_tmp);
5614 } else {
5615
5616 if (bgp_in_graceful_shutdown(bgp))
5617 bgp_attr_add_gshut_community(&attr);
5618
5619 attr_new = bgp_attr_intern(&attr);
5620 }
5621
5622 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
5623 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5624 && pi->sub_type == BGP_ROUTE_STATIC)
5625 break;
5626
5627 if (pi) {
5628 if (attrhash_cmp(pi->attr, attr_new)
5629 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
5630 && !CHECK_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS)) {
5631 bgp_dest_unlock_node(dest);
5632 bgp_attr_unintern(&attr_new);
5633 aspath_unintern(&attr.aspath);
5634 return;
5635 } else {
5636 /* The attribute is changed. */
5637 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
5638
5639 /* Rewrite BGP route information. */
5640 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
5641 bgp_path_info_restore(dest, pi);
5642 else
5643 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
5644 #ifdef ENABLE_BGP_VNC
5645 if ((afi == AFI_IP || afi == AFI_IP6)
5646 && (safi == SAFI_UNICAST)) {
5647 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
5648 /*
5649 * Implicit withdraw case.
5650 * We have to do this before pi is
5651 * changed
5652 */
5653 ++vnc_implicit_withdraw;
5654 vnc_import_bgp_del_route(bgp, p, pi);
5655 vnc_import_bgp_exterior_del_route(
5656 bgp, p, pi);
5657 }
5658 }
5659 #endif
5660 bgp_attr_unintern(&pi->attr);
5661 pi->attr = attr_new;
5662 pi->uptime = bgp_clock();
5663 #ifdef ENABLE_BGP_VNC
5664 if ((afi == AFI_IP || afi == AFI_IP6)
5665 && (safi == SAFI_UNICAST)) {
5666 if (vnc_implicit_withdraw) {
5667 vnc_import_bgp_add_route(bgp, p, pi);
5668 vnc_import_bgp_exterior_add_route(
5669 bgp, p, pi);
5670 }
5671 }
5672 #endif
5673
5674 /* Nexthop reachability check. */
5675 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
5676 && (safi == SAFI_UNICAST
5677 || safi == SAFI_LABELED_UNICAST)) {
5678
5679 struct bgp *bgp_nexthop = bgp;
5680
5681 if (pi->extra && pi->extra->bgp_orig)
5682 bgp_nexthop = pi->extra->bgp_orig;
5683
5684 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop,
5685 afi, safi, pi, NULL,
5686 0))
5687 bgp_path_info_set_flag(dest, pi,
5688 BGP_PATH_VALID);
5689 else {
5690 if (BGP_DEBUG(nht, NHT)) {
5691 char buf1[INET6_ADDRSTRLEN];
5692 inet_ntop(p->family,
5693 &p->u.prefix, buf1,
5694 INET6_ADDRSTRLEN);
5695 zlog_debug(
5696 "%s(%s): Route not in table, not advertising",
5697 __func__, buf1);
5698 }
5699 bgp_path_info_unset_flag(
5700 dest, pi, BGP_PATH_VALID);
5701 }
5702 } else {
5703 /* Delete the NHT structure if any, if we're
5704 * toggling between
5705 * enabling/disabling import check. We
5706 * deregister the route
5707 * from NHT to avoid overloading NHT and the
5708 * process interaction
5709 */
5710 bgp_unlink_nexthop(pi);
5711 bgp_path_info_set_flag(dest, pi,
5712 BGP_PATH_VALID);
5713 }
5714 /* Process change. */
5715 bgp_aggregate_increment(bgp, p, pi, afi, safi);
5716 bgp_process(bgp, dest, afi, safi);
5717
5718 if (SAFI_UNICAST == safi
5719 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5720 || bgp->inst_type
5721 == BGP_INSTANCE_TYPE_DEFAULT)) {
5722 vpn_leak_from_vrf_update(bgp_get_default(), bgp,
5723 pi);
5724 }
5725
5726 bgp_dest_unlock_node(dest);
5727 aspath_unintern(&attr.aspath);
5728 return;
5729 }
5730 }
5731
5732 /* Make new BGP info. */
5733 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
5734 attr_new, dest);
5735 /* Nexthop reachability check. */
5736 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
5737 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
5738 if (bgp_find_or_add_nexthop(bgp, bgp, afi, safi, new, NULL, 0))
5739 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
5740 else {
5741 if (BGP_DEBUG(nht, NHT)) {
5742 char buf1[INET6_ADDRSTRLEN];
5743 inet_ntop(p->family, &p->u.prefix, buf1,
5744 INET6_ADDRSTRLEN);
5745 zlog_debug(
5746 "%s(%s): Route not in table, not advertising",
5747 __func__, buf1);
5748 }
5749 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
5750 }
5751 } else {
5752 /* Delete the NHT structure if any, if we're toggling between
5753 * enabling/disabling import check. We deregister the route
5754 * from NHT to avoid overloading NHT and the process interaction
5755 */
5756 bgp_unlink_nexthop(new);
5757
5758 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
5759 }
5760
5761 /* Aggregate address increment. */
5762 bgp_aggregate_increment(bgp, p, new, afi, safi);
5763
5764 /* Register new BGP information. */
5765 bgp_path_info_add(dest, new);
5766
5767 /* route_node_get lock */
5768 bgp_dest_unlock_node(dest);
5769
5770 /* Process change. */
5771 bgp_process(bgp, dest, afi, safi);
5772
5773 if (SAFI_UNICAST == safi
5774 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5775 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
5776 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
5777 }
5778
5779 /* Unintern original. */
5780 aspath_unintern(&attr.aspath);
5781 }
5782
5783 void bgp_static_withdraw(struct bgp *bgp, const struct prefix *p, afi_t afi,
5784 safi_t safi)
5785 {
5786 struct bgp_dest *dest;
5787 struct bgp_path_info *pi;
5788
5789 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
5790
5791 /* Check selected route and self inserted route. */
5792 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
5793 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5794 && pi->sub_type == BGP_ROUTE_STATIC)
5795 break;
5796
5797 /* Withdraw static BGP route from routing table. */
5798 if (pi) {
5799 if (SAFI_UNICAST == safi
5800 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5801 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
5802 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
5803 }
5804 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
5805 bgp_unlink_nexthop(pi);
5806 bgp_path_info_delete(dest, pi);
5807 bgp_process(bgp, dest, afi, safi);
5808 }
5809
5810 /* Unlock bgp_node_lookup. */
5811 bgp_dest_unlock_node(dest);
5812 }
5813
5814 /*
5815 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
5816 */
5817 static void bgp_static_withdraw_safi(struct bgp *bgp, const struct prefix *p,
5818 afi_t afi, safi_t safi,
5819 struct prefix_rd *prd)
5820 {
5821 struct bgp_dest *dest;
5822 struct bgp_path_info *pi;
5823
5824 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
5825
5826 /* Check selected route and self inserted route. */
5827 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
5828 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5829 && pi->sub_type == BGP_ROUTE_STATIC)
5830 break;
5831
5832 /* Withdraw static BGP route from routing table. */
5833 if (pi) {
5834 #ifdef ENABLE_BGP_VNC
5835 rfapiProcessWithdraw(
5836 pi->peer, NULL, p, prd, pi->attr, afi, safi, pi->type,
5837 1); /* Kill, since it is an administrative change */
5838 #endif
5839 if (SAFI_MPLS_VPN == safi
5840 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
5841 vpn_leak_to_vrf_withdraw(bgp, pi);
5842 }
5843 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
5844 bgp_path_info_delete(dest, pi);
5845 bgp_process(bgp, dest, afi, safi);
5846 }
5847
5848 /* Unlock bgp_node_lookup. */
5849 bgp_dest_unlock_node(dest);
5850 }
5851
5852 static void bgp_static_update_safi(struct bgp *bgp, const struct prefix *p,
5853 struct bgp_static *bgp_static, afi_t afi,
5854 safi_t safi)
5855 {
5856 struct bgp_dest *dest;
5857 struct bgp_path_info *new;
5858 struct attr *attr_new;
5859 struct attr attr = {0};
5860 struct bgp_path_info *pi;
5861 #ifdef ENABLE_BGP_VNC
5862 mpls_label_t label = 0;
5863 #endif
5864 uint32_t num_labels = 0;
5865 union gw_addr add;
5866
5867 assert(bgp_static);
5868
5869 if (bgp_static->label != MPLS_INVALID_LABEL)
5870 num_labels = 1;
5871 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p,
5872 &bgp_static->prd);
5873
5874 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
5875
5876 attr.nexthop = bgp_static->igpnexthop;
5877 attr.med = bgp_static->igpmetric;
5878 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
5879
5880 if ((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN)
5881 || (safi == SAFI_ENCAP)) {
5882 if (afi == AFI_IP) {
5883 attr.mp_nexthop_global_in = bgp_static->igpnexthop;
5884 attr.mp_nexthop_len = IPV4_MAX_BYTELEN;
5885 }
5886 }
5887 if (afi == AFI_L2VPN) {
5888 if (bgp_static->gatewayIp.family == AF_INET)
5889 add.ipv4.s_addr =
5890 bgp_static->gatewayIp.u.prefix4.s_addr;
5891 else if (bgp_static->gatewayIp.family == AF_INET6)
5892 memcpy(&(add.ipv6), &(bgp_static->gatewayIp.u.prefix6),
5893 sizeof(struct in6_addr));
5894 memcpy(&attr.esi, bgp_static->eth_s_id, sizeof(esi_t));
5895 if (bgp_static->encap_tunneltype == BGP_ENCAP_TYPE_VXLAN) {
5896 struct bgp_encap_type_vxlan bet;
5897 memset(&bet, 0, sizeof(struct bgp_encap_type_vxlan));
5898 bet.vnid = p->u.prefix_evpn.prefix_addr.eth_tag;
5899 bgp_encap_type_vxlan_to_tlv(&bet, &attr);
5900 }
5901 if (bgp_static->router_mac) {
5902 bgp_add_routermac_ecom(&attr, bgp_static->router_mac);
5903 }
5904 }
5905 /* Apply route-map. */
5906 if (bgp_static->rmap.name) {
5907 struct attr attr_tmp = attr;
5908 struct bgp_path_info rmap_path;
5909 route_map_result_t ret;
5910
5911 rmap_path.peer = bgp->peer_self;
5912 rmap_path.attr = &attr_tmp;
5913
5914 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
5915
5916 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
5917
5918 bgp->peer_self->rmap_type = 0;
5919
5920 if (ret == RMAP_DENYMATCH) {
5921 /* Free uninterned attribute. */
5922 bgp_attr_flush(&attr_tmp);
5923
5924 /* Unintern original. */
5925 aspath_unintern(&attr.aspath);
5926 bgp_static_withdraw_safi(bgp, p, afi, safi,
5927 &bgp_static->prd);
5928 return;
5929 }
5930
5931 attr_new = bgp_attr_intern(&attr_tmp);
5932 } else {
5933 attr_new = bgp_attr_intern(&attr);
5934 }
5935
5936 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
5937 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5938 && pi->sub_type == BGP_ROUTE_STATIC)
5939 break;
5940
5941 if (pi) {
5942 memset(&add, 0, sizeof(union gw_addr));
5943 if (attrhash_cmp(pi->attr, attr_new)
5944 && overlay_index_equal(afi, pi, &add)
5945 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
5946 bgp_dest_unlock_node(dest);
5947 bgp_attr_unintern(&attr_new);
5948 aspath_unintern(&attr.aspath);
5949 return;
5950 } else {
5951 /* The attribute is changed. */
5952 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
5953
5954 /* Rewrite BGP route information. */
5955 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
5956 bgp_path_info_restore(dest, pi);
5957 else
5958 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
5959 bgp_attr_unintern(&pi->attr);
5960 pi->attr = attr_new;
5961 pi->uptime = bgp_clock();
5962 #ifdef ENABLE_BGP_VNC
5963 if (pi->extra)
5964 label = decode_label(&pi->extra->label[0]);
5965 #endif
5966
5967 /* Process change. */
5968 bgp_aggregate_increment(bgp, p, pi, afi, safi);
5969 bgp_process(bgp, dest, afi, safi);
5970
5971 if (SAFI_MPLS_VPN == safi
5972 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
5973 vpn_leak_to_vrf_update(bgp, pi);
5974 }
5975 #ifdef ENABLE_BGP_VNC
5976 rfapiProcessUpdate(pi->peer, NULL, p, &bgp_static->prd,
5977 pi->attr, afi, safi, pi->type,
5978 pi->sub_type, &label);
5979 #endif
5980 bgp_dest_unlock_node(dest);
5981 aspath_unintern(&attr.aspath);
5982 return;
5983 }
5984 }
5985
5986
5987 /* Make new BGP info. */
5988 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
5989 attr_new, dest);
5990 SET_FLAG(new->flags, BGP_PATH_VALID);
5991 new->extra = bgp_path_info_extra_new();
5992 if (num_labels) {
5993 new->extra->label[0] = bgp_static->label;
5994 new->extra->num_labels = num_labels;
5995 }
5996 #ifdef ENABLE_BGP_VNC
5997 label = decode_label(&bgp_static->label);
5998 #endif
5999
6000 /* Aggregate address increment. */
6001 bgp_aggregate_increment(bgp, p, new, afi, safi);
6002
6003 /* Register new BGP information. */
6004 bgp_path_info_add(dest, new);
6005 /* route_node_get lock */
6006 bgp_dest_unlock_node(dest);
6007
6008 /* Process change. */
6009 bgp_process(bgp, dest, afi, safi);
6010
6011 if (SAFI_MPLS_VPN == safi
6012 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
6013 vpn_leak_to_vrf_update(bgp, new);
6014 }
6015 #ifdef ENABLE_BGP_VNC
6016 rfapiProcessUpdate(new->peer, NULL, p, &bgp_static->prd, new->attr, afi,
6017 safi, new->type, new->sub_type, &label);
6018 #endif
6019
6020 /* Unintern original. */
6021 aspath_unintern(&attr.aspath);
6022 }
6023
6024 /* Configure static BGP network. When user don't run zebra, static
6025 route should be installed as valid. */
6026 int bgp_static_set(struct bgp *bgp, const char *negate, struct prefix *pfx,
6027 afi_t afi, safi_t safi, const char *rmap, int backdoor,
6028 uint32_t label_index, char *errmsg, size_t errmsg_len)
6029 {
6030 struct prefix p;
6031 struct bgp_static *bgp_static;
6032 struct bgp_dest *dest;
6033 uint8_t need_update = 0;
6034
6035 prefix_copy(&p, pfx);
6036 apply_mask(&p);
6037
6038 if (negate) {
6039
6040 /* Set BGP static route configuration. */
6041 dest = bgp_node_lookup(bgp->route[afi][safi], &p);
6042
6043 if (!dest) {
6044 snprintf(errmsg, errmsg_len,
6045 "Can't find static route specified\n");
6046 return -1;
6047 }
6048
6049 bgp_static = bgp_dest_get_bgp_static_info(dest);
6050
6051 if ((label_index != BGP_INVALID_LABEL_INDEX)
6052 && (label_index != bgp_static->label_index)) {
6053 snprintf(errmsg, errmsg_len,
6054 "label-index doesn't match static route\n");
6055 return -1;
6056 }
6057
6058 if ((rmap && bgp_static->rmap.name)
6059 && strcmp(rmap, bgp_static->rmap.name)) {
6060 snprintf(errmsg, errmsg_len,
6061 "route-map name doesn't match static route\n");
6062 return -1;
6063 }
6064
6065 /* Update BGP RIB. */
6066 if (!bgp_static->backdoor)
6067 bgp_static_withdraw(bgp, &p, afi, safi);
6068
6069 /* Clear configuration. */
6070 bgp_static_free(bgp_static);
6071 bgp_dest_set_bgp_static_info(dest, NULL);
6072 bgp_dest_unlock_node(dest);
6073 bgp_dest_unlock_node(dest);
6074 } else {
6075
6076 /* Set BGP static route configuration. */
6077 dest = bgp_node_get(bgp->route[afi][safi], &p);
6078 bgp_static = bgp_dest_get_bgp_static_info(dest);
6079 if (bgp_static) {
6080 /* Configuration change. */
6081 /* Label index cannot be changed. */
6082 if (bgp_static->label_index != label_index) {
6083 snprintf(errmsg, errmsg_len,
6084 "cannot change label-index\n");
6085 return -1;
6086 }
6087
6088 /* Check previous routes are installed into BGP. */
6089 if (bgp_static->valid
6090 && bgp_static->backdoor != backdoor)
6091 need_update = 1;
6092
6093 bgp_static->backdoor = backdoor;
6094
6095 if (rmap) {
6096 XFREE(MTYPE_ROUTE_MAP_NAME,
6097 bgp_static->rmap.name);
6098 route_map_counter_decrement(
6099 bgp_static->rmap.map);
6100 bgp_static->rmap.name =
6101 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
6102 bgp_static->rmap.map =
6103 route_map_lookup_by_name(rmap);
6104 route_map_counter_increment(
6105 bgp_static->rmap.map);
6106 } else {
6107 XFREE(MTYPE_ROUTE_MAP_NAME,
6108 bgp_static->rmap.name);
6109 route_map_counter_decrement(
6110 bgp_static->rmap.map);
6111 bgp_static->rmap.map = NULL;
6112 bgp_static->valid = 0;
6113 }
6114 bgp_dest_unlock_node(dest);
6115 } else {
6116 /* New configuration. */
6117 bgp_static = bgp_static_new();
6118 bgp_static->backdoor = backdoor;
6119 bgp_static->valid = 0;
6120 bgp_static->igpmetric = 0;
6121 bgp_static->igpnexthop.s_addr = INADDR_ANY;
6122 bgp_static->label_index = label_index;
6123
6124 if (rmap) {
6125 XFREE(MTYPE_ROUTE_MAP_NAME,
6126 bgp_static->rmap.name);
6127 route_map_counter_decrement(
6128 bgp_static->rmap.map);
6129 bgp_static->rmap.name =
6130 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
6131 bgp_static->rmap.map =
6132 route_map_lookup_by_name(rmap);
6133 route_map_counter_increment(
6134 bgp_static->rmap.map);
6135 }
6136 bgp_dest_set_bgp_static_info(dest, bgp_static);
6137 }
6138
6139 bgp_static->valid = 1;
6140 if (need_update)
6141 bgp_static_withdraw(bgp, &p, afi, safi);
6142
6143 if (!bgp_static->backdoor)
6144 bgp_static_update(bgp, &p, bgp_static, afi, safi);
6145 }
6146
6147 return 0;
6148 }
6149
6150 void bgp_static_add(struct bgp *bgp)
6151 {
6152 afi_t afi;
6153 safi_t safi;
6154 struct bgp_dest *dest;
6155 struct bgp_dest *rm;
6156 struct bgp_table *table;
6157 struct bgp_static *bgp_static;
6158
6159 SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
6160 FOREACH_AFI_SAFI (afi, safi)
6161 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6162 dest = bgp_route_next(dest)) {
6163 if (!bgp_dest_has_bgp_path_info_data(dest))
6164 continue;
6165
6166 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6167 || (safi == SAFI_EVPN)) {
6168 table = bgp_dest_get_bgp_table_info(dest);
6169
6170 for (rm = bgp_table_top(table); rm;
6171 rm = bgp_route_next(rm)) {
6172 bgp_static =
6173 bgp_dest_get_bgp_static_info(
6174 rm);
6175 bgp_static_update_safi(
6176 bgp, bgp_dest_get_prefix(rm),
6177 bgp_static, afi, safi);
6178 }
6179 } else {
6180 bgp_static_update(
6181 bgp, bgp_dest_get_prefix(dest),
6182 bgp_dest_get_bgp_static_info(dest), afi,
6183 safi);
6184 }
6185 }
6186 UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
6187 }
6188
6189 /* Called from bgp_delete(). Delete all static routes from the BGP
6190 instance. */
6191 void bgp_static_delete(struct bgp *bgp)
6192 {
6193 afi_t afi;
6194 safi_t safi;
6195 struct bgp_dest *dest;
6196 struct bgp_dest *rm;
6197 struct bgp_table *table;
6198 struct bgp_static *bgp_static;
6199
6200 FOREACH_AFI_SAFI (afi, safi)
6201 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6202 dest = bgp_route_next(dest)) {
6203 if (!bgp_dest_has_bgp_path_info_data(dest))
6204 continue;
6205
6206 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6207 || (safi == SAFI_EVPN)) {
6208 table = bgp_dest_get_bgp_table_info(dest);
6209
6210 for (rm = bgp_table_top(table); rm;
6211 rm = bgp_route_next(rm)) {
6212 bgp_static =
6213 bgp_dest_get_bgp_static_info(
6214 rm);
6215 if (!bgp_static)
6216 continue;
6217
6218 bgp_static_withdraw_safi(
6219 bgp, bgp_dest_get_prefix(rm),
6220 AFI_IP, safi,
6221 (struct prefix_rd *)
6222 bgp_dest_get_prefix(
6223 dest));
6224 bgp_static_free(bgp_static);
6225 bgp_dest_set_bgp_static_info(rm,
6226 NULL);
6227 bgp_dest_unlock_node(rm);
6228 }
6229 } else {
6230 bgp_static = bgp_dest_get_bgp_static_info(dest);
6231 bgp_static_withdraw(bgp,
6232 bgp_dest_get_prefix(dest),
6233 afi, safi);
6234 bgp_static_free(bgp_static);
6235 bgp_dest_set_bgp_static_info(dest, NULL);
6236 bgp_dest_unlock_node(dest);
6237 }
6238 }
6239 }
6240
6241 void bgp_static_redo_import_check(struct bgp *bgp)
6242 {
6243 afi_t afi;
6244 safi_t safi;
6245 struct bgp_dest *dest;
6246 struct bgp_dest *rm;
6247 struct bgp_table *table;
6248 struct bgp_static *bgp_static;
6249
6250 /* Use this flag to force reprocessing of the route */
6251 SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
6252 FOREACH_AFI_SAFI (afi, safi) {
6253 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6254 dest = bgp_route_next(dest)) {
6255 if (!bgp_dest_has_bgp_path_info_data(dest))
6256 continue;
6257
6258 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6259 || (safi == SAFI_EVPN)) {
6260 table = bgp_dest_get_bgp_table_info(dest);
6261
6262 for (rm = bgp_table_top(table); rm;
6263 rm = bgp_route_next(rm)) {
6264 bgp_static =
6265 bgp_dest_get_bgp_static_info(
6266 rm);
6267 bgp_static_update_safi(
6268 bgp, bgp_dest_get_prefix(rm),
6269 bgp_static, afi, safi);
6270 }
6271 } else {
6272 bgp_static = bgp_dest_get_bgp_static_info(dest);
6273 bgp_static_update(bgp,
6274 bgp_dest_get_prefix(dest),
6275 bgp_static, afi, safi);
6276 }
6277 }
6278 }
6279 UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
6280 }
6281
6282 static void bgp_purge_af_static_redist_routes(struct bgp *bgp, afi_t afi,
6283 safi_t safi)
6284 {
6285 struct bgp_table *table;
6286 struct bgp_dest *dest;
6287 struct bgp_path_info *pi;
6288
6289 /* Do not install the aggregate route if BGP is in the
6290 * process of termination.
6291 */
6292 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
6293 || (bgp->peer_self == NULL))
6294 return;
6295
6296 table = bgp->rib[afi][safi];
6297 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6298 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
6299 if (pi->peer == bgp->peer_self
6300 && ((pi->type == ZEBRA_ROUTE_BGP
6301 && pi->sub_type == BGP_ROUTE_STATIC)
6302 || (pi->type != ZEBRA_ROUTE_BGP
6303 && pi->sub_type
6304 == BGP_ROUTE_REDISTRIBUTE))) {
6305 bgp_aggregate_decrement(
6306 bgp, bgp_dest_get_prefix(dest), pi, afi,
6307 safi);
6308 bgp_unlink_nexthop(pi);
6309 bgp_path_info_delete(dest, pi);
6310 bgp_process(bgp, dest, afi, safi);
6311 }
6312 }
6313 }
6314 }
6315
6316 /*
6317 * Purge all networks and redistributed routes from routing table.
6318 * Invoked upon the instance going down.
6319 */
6320 void bgp_purge_static_redist_routes(struct bgp *bgp)
6321 {
6322 afi_t afi;
6323 safi_t safi;
6324
6325 FOREACH_AFI_SAFI (afi, safi)
6326 bgp_purge_af_static_redist_routes(bgp, afi, safi);
6327 }
6328
6329 /*
6330 * gpz 110624
6331 * Currently this is used to set static routes for VPN and ENCAP.
6332 * I think it can probably be factored with bgp_static_set.
6333 */
6334 int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty,
6335 const char *ip_str, const char *rd_str,
6336 const char *label_str, const char *rmap_str,
6337 int evpn_type, const char *esi, const char *gwip,
6338 const char *ethtag, const char *routermac)
6339 {
6340 VTY_DECLVAR_CONTEXT(bgp, bgp);
6341 int ret;
6342 struct prefix p;
6343 struct prefix_rd prd;
6344 struct bgp_dest *pdest;
6345 struct bgp_dest *dest;
6346 struct bgp_table *table;
6347 struct bgp_static *bgp_static;
6348 mpls_label_t label = MPLS_INVALID_LABEL;
6349 struct prefix gw_ip;
6350
6351 /* validate ip prefix */
6352 ret = str2prefix(ip_str, &p);
6353 if (!ret) {
6354 vty_out(vty, "%% Malformed prefix\n");
6355 return CMD_WARNING_CONFIG_FAILED;
6356 }
6357 apply_mask(&p);
6358 if ((afi == AFI_L2VPN)
6359 && (bgp_build_evpn_prefix(evpn_type,
6360 ethtag != NULL ? atol(ethtag) : 0, &p))) {
6361 vty_out(vty, "%% L2VPN prefix could not be forged\n");
6362 return CMD_WARNING_CONFIG_FAILED;
6363 }
6364
6365 ret = str2prefix_rd(rd_str, &prd);
6366 if (!ret) {
6367 vty_out(vty, "%% Malformed rd\n");
6368 return CMD_WARNING_CONFIG_FAILED;
6369 }
6370
6371 if (label_str) {
6372 unsigned long label_val;
6373 label_val = strtoul(label_str, NULL, 10);
6374 encode_label(label_val, &label);
6375 }
6376
6377 if (safi == SAFI_EVPN) {
6378 if (esi && str2esi(esi, NULL) == 0) {
6379 vty_out(vty, "%% Malformed ESI\n");
6380 return CMD_WARNING_CONFIG_FAILED;
6381 }
6382 if (routermac && prefix_str2mac(routermac, NULL) == 0) {
6383 vty_out(vty, "%% Malformed Router MAC\n");
6384 return CMD_WARNING_CONFIG_FAILED;
6385 }
6386 if (gwip) {
6387 memset(&gw_ip, 0, sizeof(struct prefix));
6388 ret = str2prefix(gwip, &gw_ip);
6389 if (!ret) {
6390 vty_out(vty, "%% Malformed GatewayIp\n");
6391 return CMD_WARNING_CONFIG_FAILED;
6392 }
6393 if ((gw_ip.family == AF_INET
6394 && is_evpn_prefix_ipaddr_v6(
6395 (struct prefix_evpn *)&p))
6396 || (gw_ip.family == AF_INET6
6397 && is_evpn_prefix_ipaddr_v4(
6398 (struct prefix_evpn *)&p))) {
6399 vty_out(vty,
6400 "%% GatewayIp family differs with IP prefix\n");
6401 return CMD_WARNING_CONFIG_FAILED;
6402 }
6403 }
6404 }
6405 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
6406 if (!bgp_dest_has_bgp_path_info_data(pdest))
6407 bgp_dest_set_bgp_table_info(pdest,
6408 bgp_table_init(bgp, afi, safi));
6409 table = bgp_dest_get_bgp_table_info(pdest);
6410
6411 dest = bgp_node_get(table, &p);
6412
6413 if (bgp_dest_has_bgp_path_info_data(dest)) {
6414 vty_out(vty, "%% Same network configuration exists\n");
6415 bgp_dest_unlock_node(dest);
6416 } else {
6417 /* New configuration. */
6418 bgp_static = bgp_static_new();
6419 bgp_static->backdoor = 0;
6420 bgp_static->valid = 0;
6421 bgp_static->igpmetric = 0;
6422 bgp_static->igpnexthop.s_addr = INADDR_ANY;
6423 bgp_static->label = label;
6424 bgp_static->prd = prd;
6425
6426 if (rmap_str) {
6427 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
6428 route_map_counter_decrement(bgp_static->rmap.map);
6429 bgp_static->rmap.name =
6430 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_str);
6431 bgp_static->rmap.map =
6432 route_map_lookup_by_name(rmap_str);
6433 route_map_counter_increment(bgp_static->rmap.map);
6434 }
6435
6436 if (safi == SAFI_EVPN) {
6437 if (esi) {
6438 bgp_static->eth_s_id =
6439 XCALLOC(MTYPE_ATTR,
6440 sizeof(esi_t));
6441 str2esi(esi, bgp_static->eth_s_id);
6442 }
6443 if (routermac) {
6444 bgp_static->router_mac =
6445 XCALLOC(MTYPE_ATTR, ETH_ALEN + 1);
6446 (void)prefix_str2mac(routermac,
6447 bgp_static->router_mac);
6448 }
6449 if (gwip)
6450 prefix_copy(&bgp_static->gatewayIp, &gw_ip);
6451 }
6452 bgp_dest_set_bgp_static_info(dest, bgp_static);
6453
6454 bgp_static->valid = 1;
6455 bgp_static_update_safi(bgp, &p, bgp_static, afi, safi);
6456 }
6457
6458 return CMD_SUCCESS;
6459 }
6460
6461 /* Configure static BGP network. */
6462 int bgp_static_unset_safi(afi_t afi, safi_t safi, struct vty *vty,
6463 const char *ip_str, const char *rd_str,
6464 const char *label_str, int evpn_type, const char *esi,
6465 const char *gwip, const char *ethtag)
6466 {
6467 VTY_DECLVAR_CONTEXT(bgp, bgp);
6468 int ret;
6469 struct prefix p;
6470 struct prefix_rd prd;
6471 struct bgp_dest *pdest;
6472 struct bgp_dest *dest;
6473 struct bgp_table *table;
6474 struct bgp_static *bgp_static;
6475 mpls_label_t label = MPLS_INVALID_LABEL;
6476
6477 /* Convert IP prefix string to struct prefix. */
6478 ret = str2prefix(ip_str, &p);
6479 if (!ret) {
6480 vty_out(vty, "%% Malformed prefix\n");
6481 return CMD_WARNING_CONFIG_FAILED;
6482 }
6483 apply_mask(&p);
6484 if ((afi == AFI_L2VPN)
6485 && (bgp_build_evpn_prefix(evpn_type,
6486 ethtag != NULL ? atol(ethtag) : 0, &p))) {
6487 vty_out(vty, "%% L2VPN prefix could not be forged\n");
6488 return CMD_WARNING_CONFIG_FAILED;
6489 }
6490 ret = str2prefix_rd(rd_str, &prd);
6491 if (!ret) {
6492 vty_out(vty, "%% Malformed rd\n");
6493 return CMD_WARNING_CONFIG_FAILED;
6494 }
6495
6496 if (label_str) {
6497 unsigned long label_val;
6498 label_val = strtoul(label_str, NULL, 10);
6499 encode_label(label_val, &label);
6500 }
6501
6502 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
6503 if (!bgp_dest_has_bgp_path_info_data(pdest))
6504 bgp_dest_set_bgp_table_info(pdest,
6505 bgp_table_init(bgp, afi, safi));
6506 else
6507 bgp_dest_unlock_node(pdest);
6508 table = bgp_dest_get_bgp_table_info(pdest);
6509
6510 dest = bgp_node_lookup(table, &p);
6511
6512 if (dest) {
6513 bgp_static_withdraw_safi(bgp, &p, afi, safi, &prd);
6514
6515 bgp_static = bgp_dest_get_bgp_static_info(dest);
6516 bgp_static_free(bgp_static);
6517 bgp_dest_set_bgp_static_info(dest, NULL);
6518 bgp_dest_unlock_node(dest);
6519 bgp_dest_unlock_node(dest);
6520 } else
6521 vty_out(vty, "%% Can't find the route\n");
6522
6523 return CMD_SUCCESS;
6524 }
6525
6526 static int bgp_table_map_set(struct vty *vty, afi_t afi, safi_t safi,
6527 const char *rmap_name)
6528 {
6529 VTY_DECLVAR_CONTEXT(bgp, bgp);
6530 struct bgp_rmap *rmap;
6531
6532 rmap = &bgp->table_map[afi][safi];
6533 if (rmap_name) {
6534 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
6535 route_map_counter_decrement(rmap->map);
6536 rmap->name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name);
6537 rmap->map = route_map_lookup_by_name(rmap_name);
6538 route_map_counter_increment(rmap->map);
6539 } else {
6540 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
6541 route_map_counter_decrement(rmap->map);
6542 rmap->map = NULL;
6543 }
6544
6545 if (bgp_fibupd_safi(safi))
6546 bgp_zebra_announce_table(bgp, afi, safi);
6547
6548 return CMD_SUCCESS;
6549 }
6550
6551 static int bgp_table_map_unset(struct vty *vty, afi_t afi, safi_t safi,
6552 const char *rmap_name)
6553 {
6554 VTY_DECLVAR_CONTEXT(bgp, bgp);
6555 struct bgp_rmap *rmap;
6556
6557 rmap = &bgp->table_map[afi][safi];
6558 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
6559 route_map_counter_decrement(rmap->map);
6560 rmap->map = NULL;
6561
6562 if (bgp_fibupd_safi(safi))
6563 bgp_zebra_announce_table(bgp, afi, safi);
6564
6565 return CMD_SUCCESS;
6566 }
6567
6568 void bgp_config_write_table_map(struct vty *vty, struct bgp *bgp, afi_t afi,
6569 safi_t safi)
6570 {
6571 if (bgp->table_map[afi][safi].name) {
6572 vty_out(vty, " table-map %s\n",
6573 bgp->table_map[afi][safi].name);
6574 }
6575 }
6576
6577 DEFUN (bgp_table_map,
6578 bgp_table_map_cmd,
6579 "table-map WORD",
6580 "BGP table to RIB route download filter\n"
6581 "Name of the route map\n")
6582 {
6583 int idx_word = 1;
6584 return bgp_table_map_set(vty, bgp_node_afi(vty), bgp_node_safi(vty),
6585 argv[idx_word]->arg);
6586 }
6587 DEFUN (no_bgp_table_map,
6588 no_bgp_table_map_cmd,
6589 "no table-map WORD",
6590 NO_STR
6591 "BGP table to RIB route download filter\n"
6592 "Name of the route map\n")
6593 {
6594 int idx_word = 2;
6595 return bgp_table_map_unset(vty, bgp_node_afi(vty), bgp_node_safi(vty),
6596 argv[idx_word]->arg);
6597 }
6598
6599 DEFPY_YANG (bgp_network, bgp_network_cmd,
6600 "[no] network \
6601 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
6602 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
6603 backdoor$backdoor}]",
6604 NO_STR
6605 "Specify a network to announce via BGP\n"
6606 "IPv4 prefix\n"
6607 "Network number\n"
6608 "Network mask\n"
6609 "Network mask\n"
6610 "Route-map to modify the attributes\n"
6611 "Name of the route map\n"
6612 "Label index to associate with the prefix\n"
6613 "Label index value\n"
6614 "Specify a BGP backdoor route\n")
6615 {
6616 char addr_prefix_str[PREFIX_STRLEN];
6617 char base_xpath[XPATH_MAXLEN];
6618 afi_t afi;
6619 safi_t safi;
6620
6621 if (address_str) {
6622 int ret;
6623
6624 ret = netmask_str2prefix_str(address_str, netmask_str,
6625 addr_prefix_str,
6626 sizeof(addr_prefix_str));
6627 if (!ret) {
6628 vty_out(vty, "%% Inconsistent address and mask\n");
6629 return CMD_WARNING_CONFIG_FAILED;
6630 }
6631 }
6632
6633 afi = bgp_node_afi(vty);
6634 safi = bgp_node_safi(vty);
6635
6636 if (no) {
6637 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
6638 } else {
6639 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
6640
6641 if (map_name)
6642 nb_cli_enqueue_change(vty, "./rmap-policy-export",
6643 NB_OP_CREATE, map_name);
6644 else
6645 nb_cli_enqueue_change(vty, "./rmap-policy-export",
6646 NB_OP_DESTROY, NULL);
6647
6648 if (label_index_str)
6649 nb_cli_enqueue_change(vty, "./label-index",
6650 NB_OP_MODIFY, label_index_str);
6651
6652 nb_cli_enqueue_change(vty, "./backdoor", NB_OP_MODIFY,
6653 backdoor ? "true" : "false");
6654 }
6655
6656 snprintf(
6657 base_xpath, sizeof(base_xpath),
6658 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/network-config[prefix='%s']",
6659 yang_afi_safi_value2identity(afi, safi),
6660 bgp_afi_safi_get_container_str(afi, safi),
6661 address_str ? addr_prefix_str : prefix_str);
6662
6663 return nb_cli_apply_changes(vty, base_xpath);
6664 }
6665
6666 DEFPY_YANG (ipv6_bgp_network,
6667 ipv6_bgp_network_cmd,
6668 "[no] network X:X::X:X/M$prefix \
6669 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
6670 NO_STR
6671 "Specify a network to announce via BGP\n"
6672 "IPv6 prefix\n"
6673 "Route-map to modify the attributes\n"
6674 "Name of the route map\n"
6675 "Label index to associate with the prefix\n"
6676 "Label index value\n")
6677 {
6678 char base_xpath[XPATH_MAXLEN];
6679 afi_t afi;
6680 safi_t safi;
6681
6682 afi = bgp_node_afi(vty);
6683 safi = bgp_node_safi(vty);
6684
6685 if (no) {
6686 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
6687 } else {
6688 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
6689
6690 if (map_name)
6691 nb_cli_enqueue_change(vty, "./rmap-policy-export",
6692 NB_OP_MODIFY, map_name);
6693 else
6694 nb_cli_enqueue_change(vty, "./rmap-policy-export",
6695 NB_OP_DESTROY, NULL);
6696
6697 if (label_index_str)
6698 nb_cli_enqueue_change(vty, "./label-index",
6699 NB_OP_MODIFY, label_index_str);
6700 }
6701
6702 snprintf(
6703 base_xpath, sizeof(base_xpath),
6704 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/network-config[prefix='%s']",
6705 yang_afi_safi_value2identity(afi, safi),
6706 bgp_afi_safi_get_container_str(afi, safi), prefix_str);
6707
6708 return nb_cli_apply_changes(vty, base_xpath);
6709 }
6710
6711 void cli_show_bgp_global_afi_safi_network_config(struct vty *vty,
6712 struct lyd_node *dnode,
6713 bool show_defaults)
6714 {
6715 vty_out(vty, " network %s", yang_dnode_get_string(dnode, "./prefix"));
6716
6717 if (yang_dnode_exists(dnode, "./label-index"))
6718 vty_out(vty, " label-index %s",
6719 yang_dnode_get_string(dnode, "./label-index"));
6720
6721 if (yang_dnode_exists(dnode, "./rmap-policy-export"))
6722 vty_out(vty, " route-map %s",
6723 yang_dnode_get_string(dnode, "./rmap-policy-export"));
6724
6725 if (yang_dnode_get_bool(dnode, "./backdoor"))
6726 vty_out(vty, " backdoor");
6727
6728 vty_out(vty, "\n");
6729 }
6730
6731 static struct bgp_aggregate *bgp_aggregate_new(void)
6732 {
6733 return XCALLOC(MTYPE_BGP_AGGREGATE, sizeof(struct bgp_aggregate));
6734 }
6735
6736 static void bgp_aggregate_free(struct bgp_aggregate *aggregate)
6737 {
6738 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
6739 route_map_counter_decrement(aggregate->suppress_map);
6740 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
6741 route_map_counter_decrement(aggregate->rmap.map);
6742 XFREE(MTYPE_BGP_AGGREGATE, aggregate);
6743 }
6744
6745 /**
6746 * Helper function to avoid repeated code: prepare variables for a
6747 * `route_map_apply` call.
6748 *
6749 * \returns `true` on route map match, otherwise `false`.
6750 */
6751 static bool aggr_suppress_map_test(struct bgp *bgp,
6752 struct bgp_aggregate *aggregate,
6753 struct bgp_path_info *pi)
6754 {
6755 const struct prefix *p = bgp_dest_get_prefix(pi->net);
6756 route_map_result_t rmr = RMAP_DENYMATCH;
6757 struct bgp_path_info rmap_path = {};
6758 struct attr attr = {};
6759
6760 /* No route map entries created, just don't match. */
6761 if (aggregate->suppress_map == NULL)
6762 return false;
6763
6764 /* Call route map matching and return result. */
6765 attr.aspath = aspath_empty();
6766 rmap_path.peer = bgp->peer_self;
6767 rmap_path.attr = &attr;
6768
6769 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_AGGREGATE);
6770 rmr = route_map_apply(aggregate->suppress_map, p, &rmap_path);
6771 bgp->peer_self->rmap_type = 0;
6772
6773 bgp_attr_flush(&attr);
6774
6775 return rmr == RMAP_PERMITMATCH;
6776 }
6777
6778 /** Test whether the aggregation has suppressed this path or not. */
6779 static bool aggr_suppress_exists(struct bgp_aggregate *aggregate,
6780 struct bgp_path_info *pi)
6781 {
6782 if (pi->extra == NULL || pi->extra->aggr_suppressors == NULL)
6783 return false;
6784
6785 return listnode_lookup(pi->extra->aggr_suppressors, aggregate) != NULL;
6786 }
6787
6788 /**
6789 * Suppress this path and keep the reference.
6790 *
6791 * \returns `true` if needs processing otherwise `false`.
6792 */
6793 static bool aggr_suppress_path(struct bgp_aggregate *aggregate,
6794 struct bgp_path_info *pi)
6795 {
6796 struct bgp_path_info_extra *pie;
6797
6798 /* Path is already suppressed by this aggregation. */
6799 if (aggr_suppress_exists(aggregate, pi))
6800 return false;
6801
6802 pie = bgp_path_info_extra_get(pi);
6803
6804 /* This is the first suppression, allocate memory and list it. */
6805 if (pie->aggr_suppressors == NULL)
6806 pie->aggr_suppressors = list_new();
6807
6808 listnode_add(pie->aggr_suppressors, aggregate);
6809
6810 /* Only mark for processing if suppressed. */
6811 if (listcount(pie->aggr_suppressors) == 1) {
6812 if (BGP_DEBUG(update, UPDATE_OUT))
6813 zlog_debug("aggregate-address suppressing: %pFX",
6814 bgp_dest_get_prefix(pi->net));
6815
6816 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
6817 return true;
6818 }
6819
6820 return false;
6821 }
6822
6823 /**
6824 * Unsuppress this path and remove the reference.
6825 *
6826 * \returns `true` if needs processing otherwise `false`.
6827 */
6828 static bool aggr_unsuppress_path(struct bgp_aggregate *aggregate,
6829 struct bgp_path_info *pi)
6830 {
6831 /* Path wasn't suppressed. */
6832 if (!aggr_suppress_exists(aggregate, pi))
6833 return false;
6834
6835 listnode_delete(pi->extra->aggr_suppressors, aggregate);
6836
6837 /* Unsuppress and free extra memory if last item. */
6838 if (listcount(pi->extra->aggr_suppressors) == 0) {
6839 if (BGP_DEBUG(update, UPDATE_OUT))
6840 zlog_debug("aggregate-address unsuppressing: %pFX",
6841 bgp_dest_get_prefix(pi->net));
6842
6843 list_delete(&pi->extra->aggr_suppressors);
6844 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
6845 return true;
6846 }
6847
6848 return false;
6849 }
6850
6851 static bool bgp_aggregate_info_same(struct bgp_path_info *pi, uint8_t origin,
6852 struct aspath *aspath,
6853 struct community *comm,
6854 struct ecommunity *ecomm,
6855 struct lcommunity *lcomm)
6856 {
6857 static struct aspath *ae = NULL;
6858
6859 if (!ae)
6860 ae = aspath_empty();
6861
6862 if (!pi)
6863 return false;
6864
6865 if (origin != pi->attr->origin)
6866 return false;
6867
6868 if (!aspath_cmp(pi->attr->aspath, (aspath) ? aspath : ae))
6869 return false;
6870
6871 if (!community_cmp(pi->attr->community, comm))
6872 return false;
6873
6874 if (!ecommunity_cmp(pi->attr->ecommunity, ecomm))
6875 return false;
6876
6877 if (!lcommunity_cmp(pi->attr->lcommunity, lcomm))
6878 return false;
6879
6880 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID))
6881 return false;
6882
6883 return true;
6884 }
6885
6886 static void bgp_aggregate_install(
6887 struct bgp *bgp, afi_t afi, safi_t safi, const struct prefix *p,
6888 uint8_t origin, struct aspath *aspath, struct community *community,
6889 struct ecommunity *ecommunity, struct lcommunity *lcommunity,
6890 uint8_t atomic_aggregate, struct bgp_aggregate *aggregate)
6891 {
6892 struct bgp_dest *dest;
6893 struct bgp_table *table;
6894 struct bgp_path_info *pi, *orig, *new;
6895 struct attr *attr;
6896
6897 table = bgp->rib[afi][safi];
6898
6899 dest = bgp_node_get(table, p);
6900
6901 for (orig = pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
6902 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6903 && pi->sub_type == BGP_ROUTE_AGGREGATE)
6904 break;
6905
6906 /*
6907 * If we have paths with different MEDs, then don't install
6908 * (or uninstall) the aggregate route.
6909 */
6910 if (aggregate->match_med && aggregate->med_mismatched)
6911 goto uninstall_aggregate_route;
6912
6913 if (aggregate->count > 0) {
6914 /*
6915 * If the aggregate information has not changed
6916 * no need to re-install it again.
6917 */
6918 if (bgp_aggregate_info_same(orig, origin, aspath, community,
6919 ecommunity, lcommunity)) {
6920 bgp_dest_unlock_node(dest);
6921
6922 if (aspath)
6923 aspath_free(aspath);
6924 if (community)
6925 community_free(&community);
6926 if (ecommunity)
6927 ecommunity_free(&ecommunity);
6928 if (lcommunity)
6929 lcommunity_free(&lcommunity);
6930
6931 return;
6932 }
6933
6934 /*
6935 * Mark the old as unusable
6936 */
6937 if (pi)
6938 bgp_path_info_delete(dest, pi);
6939
6940 attr = bgp_attr_aggregate_intern(
6941 bgp, origin, aspath, community, ecommunity, lcommunity,
6942 aggregate, atomic_aggregate, p);
6943
6944 if (!attr) {
6945 bgp_aggregate_delete(bgp, p, afi, safi, aggregate);
6946 if (BGP_DEBUG(update_groups, UPDATE_GROUPS))
6947 zlog_debug("%s: %pFX null attribute", __func__,
6948 p);
6949 return;
6950 }
6951
6952 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0,
6953 bgp->peer_self, attr, dest);
6954
6955 SET_FLAG(new->flags, BGP_PATH_VALID);
6956
6957 bgp_path_info_add(dest, new);
6958 bgp_process(bgp, dest, afi, safi);
6959 } else {
6960 uninstall_aggregate_route:
6961 for (pi = orig; pi; pi = pi->next)
6962 if (pi->peer == bgp->peer_self
6963 && pi->type == ZEBRA_ROUTE_BGP
6964 && pi->sub_type == BGP_ROUTE_AGGREGATE)
6965 break;
6966
6967 /* Withdraw static BGP route from routing table. */
6968 if (pi) {
6969 bgp_path_info_delete(dest, pi);
6970 bgp_process(bgp, dest, afi, safi);
6971 }
6972 }
6973
6974 bgp_dest_unlock_node(dest);
6975 }
6976
6977 /**
6978 * Check if the current path has different MED than other known paths.
6979 *
6980 * \returns `true` if the MED matched the others else `false`.
6981 */
6982 static bool bgp_aggregate_med_match(struct bgp_aggregate *aggregate,
6983 struct bgp *bgp, struct bgp_path_info *pi)
6984 {
6985 uint32_t cur_med = bgp_med_value(pi->attr, bgp);
6986
6987 /* This is the first route being analyzed. */
6988 if (!aggregate->med_initialized) {
6989 aggregate->med_initialized = true;
6990 aggregate->med_mismatched = false;
6991 aggregate->med_matched_value = cur_med;
6992 } else {
6993 /* Check if routes with different MED showed up. */
6994 if (cur_med != aggregate->med_matched_value)
6995 aggregate->med_mismatched = true;
6996 }
6997
6998 return !aggregate->med_mismatched;
6999 }
7000
7001 /**
7002 * Initializes and tests all routes in the aggregate address path for MED
7003 * values.
7004 *
7005 * \returns `true` if all MEDs are the same otherwise `false`.
7006 */
7007 static bool bgp_aggregate_test_all_med(struct bgp_aggregate *aggregate,
7008 struct bgp *bgp, const struct prefix *p,
7009 afi_t afi, safi_t safi)
7010 {
7011 struct bgp_table *table = bgp->rib[afi][safi];
7012 const struct prefix *dest_p;
7013 struct bgp_dest *dest, *top;
7014 struct bgp_path_info *pi;
7015 bool med_matched = true;
7016
7017 aggregate->med_initialized = false;
7018
7019 top = bgp_node_get(table, p);
7020 for (dest = bgp_node_get(table, p); dest;
7021 dest = bgp_route_next_until(dest, top)) {
7022 dest_p = bgp_dest_get_prefix(dest);
7023 if (dest_p->prefixlen <= p->prefixlen)
7024 continue;
7025
7026 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
7027 if (BGP_PATH_HOLDDOWN(pi))
7028 continue;
7029 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7030 continue;
7031 if (!bgp_aggregate_med_match(aggregate, bgp, pi)) {
7032 med_matched = false;
7033 break;
7034 }
7035 }
7036 if (!med_matched)
7037 break;
7038 }
7039 bgp_dest_unlock_node(top);
7040
7041 return med_matched;
7042 }
7043
7044 /**
7045 * Toggles the route suppression status for this aggregate address
7046 * configuration.
7047 */
7048 void bgp_aggregate_toggle_suppressed(struct bgp_aggregate *aggregate,
7049 struct bgp *bgp, const struct prefix *p,
7050 afi_t afi, safi_t safi, bool suppress)
7051 {
7052 struct bgp_table *table = bgp->rib[afi][safi];
7053 const struct prefix *dest_p;
7054 struct bgp_dest *dest, *top;
7055 struct bgp_path_info *pi;
7056 bool toggle_suppression;
7057
7058 /* We've found a different MED we must revert any suppressed routes. */
7059 top = bgp_node_get(table, p);
7060 for (dest = bgp_node_get(table, p); dest;
7061 dest = bgp_route_next_until(dest, top)) {
7062 dest_p = bgp_dest_get_prefix(dest);
7063 if (dest_p->prefixlen <= p->prefixlen)
7064 continue;
7065
7066 toggle_suppression = false;
7067 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
7068 if (BGP_PATH_HOLDDOWN(pi))
7069 continue;
7070 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7071 continue;
7072
7073 /* We are toggling suppression back. */
7074 if (suppress) {
7075 /* Suppress route if not suppressed already. */
7076 if (aggr_suppress_path(aggregate, pi))
7077 toggle_suppression = true;
7078 continue;
7079 }
7080
7081 /* Install route if there is no more suppression. */
7082 if (aggr_unsuppress_path(aggregate, pi))
7083 toggle_suppression = true;
7084 }
7085
7086 if (toggle_suppression)
7087 bgp_process(bgp, dest, afi, safi);
7088 }
7089 bgp_dest_unlock_node(top);
7090 }
7091
7092 /**
7093 * Aggregate address MED matching incremental test: this function is called
7094 * when the initial aggregation occurred and we are only testing a single
7095 * new path.
7096 *
7097 * In addition to testing and setting the MED validity it also installs back
7098 * suppressed routes (if summary is configured).
7099 *
7100 * Must not be called in `bgp_aggregate_route`.
7101 */
7102 static void bgp_aggregate_med_update(struct bgp_aggregate *aggregate,
7103 struct bgp *bgp, const struct prefix *p,
7104 afi_t afi, safi_t safi,
7105 struct bgp_path_info *pi, bool is_adding)
7106 {
7107 /* MED matching disabled. */
7108 if (!aggregate->match_med)
7109 return;
7110
7111 /* Aggregation with different MED, nothing to do. */
7112 if (aggregate->med_mismatched)
7113 return;
7114
7115 /*
7116 * Test the current entry:
7117 *
7118 * is_adding == true: if the new entry doesn't match then we must
7119 * install all suppressed routes.
7120 *
7121 * is_adding == false: if the entry being removed was the last
7122 * unmatching entry then we can suppress all routes.
7123 */
7124 if (!is_adding) {
7125 if (bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi)
7126 && aggregate->summary_only)
7127 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi,
7128 safi, true);
7129 } else
7130 bgp_aggregate_med_match(aggregate, bgp, pi);
7131
7132 /* No mismatches, just quit. */
7133 if (!aggregate->med_mismatched)
7134 return;
7135
7136 /* Route summarization is disabled. */
7137 if (!aggregate->summary_only)
7138 return;
7139
7140 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi, safi, false);
7141 }
7142
7143 /* Update an aggregate as routes are added/removed from the BGP table */
7144 void bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi,
7145 safi_t safi, struct bgp_aggregate *aggregate)
7146 {
7147 struct bgp_table *table;
7148 struct bgp_dest *top;
7149 struct bgp_dest *dest;
7150 uint8_t origin;
7151 struct aspath *aspath = NULL;
7152 struct community *community = NULL;
7153 struct ecommunity *ecommunity = NULL;
7154 struct lcommunity *lcommunity = NULL;
7155 struct bgp_path_info *pi;
7156 unsigned long match = 0;
7157 uint8_t atomic_aggregate = 0;
7158
7159 /* If the bgp instance is being deleted or self peer is deleted
7160 * then do not create aggregate route
7161 */
7162 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7163 || (bgp->peer_self == NULL))
7164 return;
7165
7166 /* Initialize and test routes for MED difference. */
7167 if (aggregate->match_med)
7168 bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi);
7169
7170 /*
7171 * Reset aggregate count: we might've been called from route map
7172 * update so in that case we must retest all more specific routes.
7173 *
7174 * \see `bgp_route_map_process_update`.
7175 */
7176 aggregate->count = 0;
7177 aggregate->incomplete_origin_count = 0;
7178 aggregate->incomplete_origin_count = 0;
7179 aggregate->egp_origin_count = 0;
7180
7181 /* ORIGIN attribute: If at least one route among routes that are
7182 aggregated has ORIGIN with the value INCOMPLETE, then the
7183 aggregated route must have the ORIGIN attribute with the value
7184 INCOMPLETE. Otherwise, if at least one route among routes that
7185 are aggregated has ORIGIN with the value EGP, then the aggregated
7186 route must have the origin attribute with the value EGP. In all
7187 other case the value of the ORIGIN attribute of the aggregated
7188 route is INTERNAL. */
7189 origin = BGP_ORIGIN_IGP;
7190
7191 table = bgp->rib[afi][safi];
7192
7193 top = bgp_node_get(table, p);
7194 for (dest = bgp_node_get(table, p); dest;
7195 dest = bgp_route_next_until(dest, top)) {
7196 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
7197
7198 if (dest_p->prefixlen <= p->prefixlen)
7199 continue;
7200
7201 /* If suppress fib is enabled and route not installed
7202 * in FIB, skip the route
7203 */
7204 if (!bgp_check_advertise(bgp, dest))
7205 continue;
7206
7207 match = 0;
7208
7209 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
7210 if (BGP_PATH_HOLDDOWN(pi))
7211 continue;
7212
7213 if (pi->attr->flag
7214 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
7215 atomic_aggregate = 1;
7216
7217 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7218 continue;
7219
7220 /*
7221 * summary-only aggregate route suppress
7222 * aggregated route announcements.
7223 *
7224 * MED matching:
7225 * Don't create summaries if MED didn't match
7226 * otherwise neither the specific routes and the
7227 * aggregation will be announced.
7228 */
7229 if (aggregate->summary_only
7230 && AGGREGATE_MED_VALID(aggregate)) {
7231 if (aggr_suppress_path(aggregate, pi))
7232 match++;
7233 }
7234
7235 /*
7236 * Suppress more specific routes that match the route
7237 * map results.
7238 *
7239 * MED matching:
7240 * Don't suppress routes if MED matching is enabled and
7241 * it mismatched otherwise we might end up with no
7242 * routes for this path.
7243 */
7244 if (aggregate->suppress_map_name
7245 && AGGREGATE_MED_VALID(aggregate)
7246 && aggr_suppress_map_test(bgp, aggregate, pi)) {
7247 if (aggr_suppress_path(aggregate, pi))
7248 match++;
7249 }
7250
7251 aggregate->count++;
7252
7253 /*
7254 * If at least one route among routes that are
7255 * aggregated has ORIGIN with the value INCOMPLETE,
7256 * then the aggregated route MUST have the ORIGIN
7257 * attribute with the value INCOMPLETE. Otherwise, if
7258 * at least one route among routes that are aggregated
7259 * has ORIGIN with the value EGP, then the aggregated
7260 * route MUST have the ORIGIN attribute with the value
7261 * EGP.
7262 */
7263 switch (pi->attr->origin) {
7264 case BGP_ORIGIN_INCOMPLETE:
7265 aggregate->incomplete_origin_count++;
7266 break;
7267 case BGP_ORIGIN_EGP:
7268 aggregate->egp_origin_count++;
7269 break;
7270 default:
7271 /*Do nothing.
7272 */
7273 break;
7274 }
7275
7276 if (!aggregate->as_set)
7277 continue;
7278
7279 /*
7280 * as-set aggregate route generate origin, as path,
7281 * and community aggregation.
7282 */
7283 /* Compute aggregate route's as-path.
7284 */
7285 bgp_compute_aggregate_aspath_hash(aggregate,
7286 pi->attr->aspath);
7287
7288 /* Compute aggregate route's community.
7289 */
7290 if (pi->attr->community)
7291 bgp_compute_aggregate_community_hash(
7292 aggregate,
7293 pi->attr->community);
7294
7295 /* Compute aggregate route's extended community.
7296 */
7297 if (pi->attr->ecommunity)
7298 bgp_compute_aggregate_ecommunity_hash(
7299 aggregate,
7300 pi->attr->ecommunity);
7301
7302 /* Compute aggregate route's large community.
7303 */
7304 if (pi->attr->lcommunity)
7305 bgp_compute_aggregate_lcommunity_hash(
7306 aggregate,
7307 pi->attr->lcommunity);
7308 }
7309 if (match)
7310 bgp_process(bgp, dest, afi, safi);
7311 }
7312 if (aggregate->as_set) {
7313 bgp_compute_aggregate_aspath_val(aggregate);
7314 bgp_compute_aggregate_community_val(aggregate);
7315 bgp_compute_aggregate_ecommunity_val(aggregate);
7316 bgp_compute_aggregate_lcommunity_val(aggregate);
7317 }
7318
7319
7320 bgp_dest_unlock_node(top);
7321
7322
7323 if (aggregate->incomplete_origin_count > 0)
7324 origin = BGP_ORIGIN_INCOMPLETE;
7325 else if (aggregate->egp_origin_count > 0)
7326 origin = BGP_ORIGIN_EGP;
7327
7328 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7329 origin = aggregate->origin;
7330
7331 if (aggregate->as_set) {
7332 if (aggregate->aspath)
7333 /* Retrieve aggregate route's as-path.
7334 */
7335 aspath = aspath_dup(aggregate->aspath);
7336
7337 if (aggregate->community)
7338 /* Retrieve aggregate route's community.
7339 */
7340 community = community_dup(aggregate->community);
7341
7342 if (aggregate->ecommunity)
7343 /* Retrieve aggregate route's ecommunity.
7344 */
7345 ecommunity = ecommunity_dup(aggregate->ecommunity);
7346
7347 if (aggregate->lcommunity)
7348 /* Retrieve aggregate route's lcommunity.
7349 */
7350 lcommunity = lcommunity_dup(aggregate->lcommunity);
7351 }
7352
7353 bgp_aggregate_install(bgp, afi, safi, p, origin, aspath, community,
7354 ecommunity, lcommunity, atomic_aggregate,
7355 aggregate);
7356 }
7357
7358 void bgp_aggregate_delete(struct bgp *bgp, const struct prefix *p, afi_t afi,
7359 safi_t safi, struct bgp_aggregate *aggregate)
7360 {
7361 struct bgp_table *table;
7362 struct bgp_dest *top;
7363 struct bgp_dest *dest;
7364 struct bgp_path_info *pi;
7365 unsigned long match;
7366
7367 table = bgp->rib[afi][safi];
7368
7369 /* If routes exists below this node, generate aggregate routes. */
7370 top = bgp_node_get(table, p);
7371 for (dest = bgp_node_get(table, p); dest;
7372 dest = bgp_route_next_until(dest, top)) {
7373 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
7374
7375 if (dest_p->prefixlen <= p->prefixlen)
7376 continue;
7377 match = 0;
7378
7379 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
7380 if (BGP_PATH_HOLDDOWN(pi))
7381 continue;
7382
7383 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7384 continue;
7385
7386 if (aggregate->summary_only && pi->extra
7387 && AGGREGATE_MED_VALID(aggregate)) {
7388 if (aggr_unsuppress_path(aggregate, pi))
7389 match++;
7390 }
7391
7392 if (aggregate->suppress_map_name
7393 && AGGREGATE_MED_VALID(aggregate)
7394 && aggr_suppress_map_test(bgp, aggregate, pi)) {
7395 if (aggr_unsuppress_path(aggregate, pi))
7396 match++;
7397 }
7398
7399 aggregate->count--;
7400
7401 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
7402 aggregate->incomplete_origin_count--;
7403 else if (pi->attr->origin == BGP_ORIGIN_EGP)
7404 aggregate->egp_origin_count--;
7405
7406 if (aggregate->as_set) {
7407 /* Remove as-path from aggregate.
7408 */
7409 bgp_remove_aspath_from_aggregate_hash(
7410 aggregate,
7411 pi->attr->aspath);
7412
7413 if (pi->attr->community)
7414 /* Remove community from aggregate.
7415 */
7416 bgp_remove_comm_from_aggregate_hash(
7417 aggregate,
7418 pi->attr->community);
7419
7420 if (pi->attr->ecommunity)
7421 /* Remove ecommunity from aggregate.
7422 */
7423 bgp_remove_ecomm_from_aggregate_hash(
7424 aggregate,
7425 pi->attr->ecommunity);
7426
7427 if (pi->attr->lcommunity)
7428 /* Remove lcommunity from aggregate.
7429 */
7430 bgp_remove_lcomm_from_aggregate_hash(
7431 aggregate,
7432 pi->attr->lcommunity);
7433 }
7434 }
7435
7436 /* If this node was suppressed, process the change. */
7437 if (match)
7438 bgp_process(bgp, dest, afi, safi);
7439 }
7440 if (aggregate->as_set) {
7441 aspath_free(aggregate->aspath);
7442 aggregate->aspath = NULL;
7443 if (aggregate->community)
7444 community_free(&aggregate->community);
7445 if (aggregate->ecommunity)
7446 ecommunity_free(&aggregate->ecommunity);
7447 if (aggregate->lcommunity)
7448 lcommunity_free(&aggregate->lcommunity);
7449 }
7450
7451 bgp_dest_unlock_node(top);
7452 }
7453
7454 static void bgp_add_route_to_aggregate(struct bgp *bgp,
7455 const struct prefix *aggr_p,
7456 struct bgp_path_info *pinew, afi_t afi,
7457 safi_t safi,
7458 struct bgp_aggregate *aggregate)
7459 {
7460 uint8_t origin;
7461 struct aspath *aspath = NULL;
7462 uint8_t atomic_aggregate = 0;
7463 struct community *community = NULL;
7464 struct ecommunity *ecommunity = NULL;
7465 struct lcommunity *lcommunity = NULL;
7466
7467 /* If the bgp instance is being deleted or self peer is deleted
7468 * then do not create aggregate route
7469 */
7470 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7471 || (bgp->peer_self == NULL))
7472 return;
7473
7474 /* ORIGIN attribute: If at least one route among routes that are
7475 * aggregated has ORIGIN with the value INCOMPLETE, then the
7476 * aggregated route must have the ORIGIN attribute with the value
7477 * INCOMPLETE. Otherwise, if at least one route among routes that
7478 * are aggregated has ORIGIN with the value EGP, then the aggregated
7479 * route must have the origin attribute with the value EGP. In all
7480 * other case the value of the ORIGIN attribute of the aggregated
7481 * route is INTERNAL.
7482 */
7483 origin = BGP_ORIGIN_IGP;
7484
7485 aggregate->count++;
7486
7487 /*
7488 * This must be called before `summary` check to avoid
7489 * "suppressing" twice.
7490 */
7491 if (aggregate->match_med)
7492 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi,
7493 pinew, true);
7494
7495 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
7496 aggr_suppress_path(aggregate, pinew);
7497
7498 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
7499 && aggr_suppress_map_test(bgp, aggregate, pinew))
7500 aggr_suppress_path(aggregate, pinew);
7501
7502 switch (pinew->attr->origin) {
7503 case BGP_ORIGIN_INCOMPLETE:
7504 aggregate->incomplete_origin_count++;
7505 break;
7506 case BGP_ORIGIN_EGP:
7507 aggregate->egp_origin_count++;
7508 break;
7509 default:
7510 /* Do nothing.
7511 */
7512 break;
7513 }
7514
7515 if (aggregate->incomplete_origin_count > 0)
7516 origin = BGP_ORIGIN_INCOMPLETE;
7517 else if (aggregate->egp_origin_count > 0)
7518 origin = BGP_ORIGIN_EGP;
7519
7520 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7521 origin = aggregate->origin;
7522
7523 if (aggregate->as_set) {
7524 /* Compute aggregate route's as-path.
7525 */
7526 bgp_compute_aggregate_aspath(aggregate,
7527 pinew->attr->aspath);
7528
7529 /* Compute aggregate route's community.
7530 */
7531 if (pinew->attr->community)
7532 bgp_compute_aggregate_community(
7533 aggregate,
7534 pinew->attr->community);
7535
7536 /* Compute aggregate route's extended community.
7537 */
7538 if (pinew->attr->ecommunity)
7539 bgp_compute_aggregate_ecommunity(
7540 aggregate,
7541 pinew->attr->ecommunity);
7542
7543 /* Compute aggregate route's large community.
7544 */
7545 if (pinew->attr->lcommunity)
7546 bgp_compute_aggregate_lcommunity(
7547 aggregate,
7548 pinew->attr->lcommunity);
7549
7550 /* Retrieve aggregate route's as-path.
7551 */
7552 if (aggregate->aspath)
7553 aspath = aspath_dup(aggregate->aspath);
7554
7555 /* Retrieve aggregate route's community.
7556 */
7557 if (aggregate->community)
7558 community = community_dup(aggregate->community);
7559
7560 /* Retrieve aggregate route's ecommunity.
7561 */
7562 if (aggregate->ecommunity)
7563 ecommunity = ecommunity_dup(aggregate->ecommunity);
7564
7565 /* Retrieve aggregate route's lcommunity.
7566 */
7567 if (aggregate->lcommunity)
7568 lcommunity = lcommunity_dup(aggregate->lcommunity);
7569 }
7570
7571 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
7572 aspath, community, ecommunity,
7573 lcommunity, atomic_aggregate, aggregate);
7574 }
7575
7576 static void bgp_remove_route_from_aggregate(struct bgp *bgp, afi_t afi,
7577 safi_t safi,
7578 struct bgp_path_info *pi,
7579 struct bgp_aggregate *aggregate,
7580 const struct prefix *aggr_p)
7581 {
7582 uint8_t origin;
7583 struct aspath *aspath = NULL;
7584 uint8_t atomic_aggregate = 0;
7585 struct community *community = NULL;
7586 struct ecommunity *ecommunity = NULL;
7587 struct lcommunity *lcommunity = NULL;
7588 unsigned long match = 0;
7589
7590 /* If the bgp instance is being deleted or self peer is deleted
7591 * then do not create aggregate route
7592 */
7593 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7594 || (bgp->peer_self == NULL))
7595 return;
7596
7597 if (BGP_PATH_HOLDDOWN(pi))
7598 return;
7599
7600 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7601 return;
7602
7603 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
7604 if (aggr_unsuppress_path(aggregate, pi))
7605 match++;
7606
7607 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
7608 && aggr_suppress_map_test(bgp, aggregate, pi))
7609 if (aggr_unsuppress_path(aggregate, pi))
7610 match++;
7611
7612 /*
7613 * This must be called after `summary`, `suppress-map` check to avoid
7614 * "unsuppressing" twice.
7615 */
7616 if (aggregate->match_med)
7617 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi, pi,
7618 true);
7619
7620 if (aggregate->count > 0)
7621 aggregate->count--;
7622
7623 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
7624 aggregate->incomplete_origin_count--;
7625 else if (pi->attr->origin == BGP_ORIGIN_EGP)
7626 aggregate->egp_origin_count--;
7627
7628 if (aggregate->as_set) {
7629 /* Remove as-path from aggregate.
7630 */
7631 bgp_remove_aspath_from_aggregate(aggregate,
7632 pi->attr->aspath);
7633
7634 if (pi->attr->community)
7635 /* Remove community from aggregate.
7636 */
7637 bgp_remove_community_from_aggregate(
7638 aggregate,
7639 pi->attr->community);
7640
7641 if (pi->attr->ecommunity)
7642 /* Remove ecommunity from aggregate.
7643 */
7644 bgp_remove_ecommunity_from_aggregate(
7645 aggregate,
7646 pi->attr->ecommunity);
7647
7648 if (pi->attr->lcommunity)
7649 /* Remove lcommunity from aggregate.
7650 */
7651 bgp_remove_lcommunity_from_aggregate(
7652 aggregate,
7653 pi->attr->lcommunity);
7654 }
7655
7656 /* If this node was suppressed, process the change. */
7657 if (match)
7658 bgp_process(bgp, pi->net, afi, safi);
7659
7660 origin = BGP_ORIGIN_IGP;
7661 if (aggregate->incomplete_origin_count > 0)
7662 origin = BGP_ORIGIN_INCOMPLETE;
7663 else if (aggregate->egp_origin_count > 0)
7664 origin = BGP_ORIGIN_EGP;
7665
7666 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7667 origin = aggregate->origin;
7668
7669 if (aggregate->as_set) {
7670 /* Retrieve aggregate route's as-path.
7671 */
7672 if (aggregate->aspath)
7673 aspath = aspath_dup(aggregate->aspath);
7674
7675 /* Retrieve aggregate route's community.
7676 */
7677 if (aggregate->community)
7678 community = community_dup(aggregate->community);
7679
7680 /* Retrieve aggregate route's ecommunity.
7681 */
7682 if (aggregate->ecommunity)
7683 ecommunity = ecommunity_dup(aggregate->ecommunity);
7684
7685 /* Retrieve aggregate route's lcommunity.
7686 */
7687 if (aggregate->lcommunity)
7688 lcommunity = lcommunity_dup(aggregate->lcommunity);
7689 }
7690
7691 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
7692 aspath, community, ecommunity,
7693 lcommunity, atomic_aggregate, aggregate);
7694 }
7695
7696 void bgp_aggregate_increment(struct bgp *bgp, const struct prefix *p,
7697 struct bgp_path_info *pi, afi_t afi, safi_t safi)
7698 {
7699 struct bgp_dest *child;
7700 struct bgp_dest *dest;
7701 struct bgp_aggregate *aggregate;
7702 struct bgp_table *table;
7703
7704 table = bgp->aggregate[afi][safi];
7705
7706 /* No aggregates configured. */
7707 if (bgp_table_top_nolock(table) == NULL)
7708 return;
7709
7710 if (p->prefixlen == 0)
7711 return;
7712
7713 if (BGP_PATH_HOLDDOWN(pi))
7714 return;
7715
7716 /* If suppress fib is enabled and route not installed
7717 * in FIB, do not update the aggregate route
7718 */
7719 if (!bgp_check_advertise(bgp, pi->net))
7720 return;
7721
7722 child = bgp_node_get(table, p);
7723
7724 /* Aggregate address configuration check. */
7725 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
7726 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
7727
7728 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
7729 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
7730 bgp_add_route_to_aggregate(bgp, dest_p, pi, afi, safi,
7731 aggregate);
7732 }
7733 }
7734 bgp_dest_unlock_node(child);
7735 }
7736
7737 void bgp_aggregate_decrement(struct bgp *bgp, const struct prefix *p,
7738 struct bgp_path_info *del, afi_t afi, safi_t safi)
7739 {
7740 struct bgp_dest *child;
7741 struct bgp_dest *dest;
7742 struct bgp_aggregate *aggregate;
7743 struct bgp_table *table;
7744
7745 table = bgp->aggregate[afi][safi];
7746
7747 /* No aggregates configured. */
7748 if (bgp_table_top_nolock(table) == NULL)
7749 return;
7750
7751 if (p->prefixlen == 0)
7752 return;
7753
7754 child = bgp_node_get(table, p);
7755
7756 /* Aggregate address configuration check. */
7757 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
7758 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
7759
7760 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
7761 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
7762 bgp_remove_route_from_aggregate(bgp, afi, safi, del,
7763 aggregate, dest_p);
7764 }
7765 }
7766 bgp_dest_unlock_node(child);
7767 }
7768
7769 /* Aggregate route attribute. */
7770 #define AGGREGATE_SUMMARY_ONLY 1
7771 #define AGGREGATE_AS_SET 1
7772 #define AGGREGATE_AS_UNSET 0
7773
7774 static const char *bgp_origin2str(uint8_t origin)
7775 {
7776 switch (origin) {
7777 case BGP_ORIGIN_IGP:
7778 return "igp";
7779 case BGP_ORIGIN_EGP:
7780 return "egp";
7781 case BGP_ORIGIN_INCOMPLETE:
7782 return "incomplete";
7783 }
7784 return "n/a";
7785 }
7786
7787 static const char *bgp_rpki_validation2str(enum rpki_states v_state)
7788 {
7789 switch (v_state) {
7790 case RPKI_NOT_BEING_USED:
7791 return "not used";
7792 case RPKI_VALID:
7793 return "valid";
7794 case RPKI_NOTFOUND:
7795 return "not found";
7796 case RPKI_INVALID:
7797 return "invalid";
7798 }
7799
7800 assert(!"We should never get here this is a dev escape");
7801 return "ERROR";
7802 }
7803
7804 int bgp_aggregate_unset(struct bgp *bgp, struct prefix *prefix, afi_t afi,
7805 safi_t safi, char *errmsg, size_t errmsg_len)
7806 {
7807 struct bgp_dest *dest;
7808 struct bgp_aggregate *aggregate;
7809
7810 /* If the bgp instance is being deleted or self peer is deleted
7811 * then do not create aggregate route
7812 */
7813 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7814 || (bgp->peer_self == NULL))
7815 return 0;
7816
7817 apply_mask(prefix);
7818 /* Old configuration check. */
7819 dest = bgp_node_lookup(bgp->aggregate[afi][safi], prefix);
7820 if (!dest) {
7821 snprintf(errmsg, errmsg_len,
7822 "There is no aggregate-address configuration.\n");
7823 return -1;
7824 }
7825
7826 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
7827 bgp_aggregate_delete(bgp, prefix, afi, safi, aggregate);
7828 bgp_aggregate_install(bgp, afi, safi, prefix, 0, NULL, NULL, NULL, NULL,
7829 0, aggregate);
7830
7831 /* Unlock aggregate address configuration. */
7832 bgp_dest_set_bgp_aggregate_info(dest, NULL);
7833
7834 if (aggregate->community)
7835 community_free(&aggregate->community);
7836
7837 if (aggregate->community_hash) {
7838 /* Delete all communities in the hash.
7839 */
7840 hash_clean(aggregate->community_hash,
7841 bgp_aggr_community_remove);
7842 /* Free up the community_hash.
7843 */
7844 hash_free(aggregate->community_hash);
7845 }
7846
7847 if (aggregate->ecommunity)
7848 ecommunity_free(&aggregate->ecommunity);
7849
7850 if (aggregate->ecommunity_hash) {
7851 /* Delete all ecommunities in the hash.
7852 */
7853 hash_clean(aggregate->ecommunity_hash,
7854 bgp_aggr_ecommunity_remove);
7855 /* Free up the ecommunity_hash.
7856 */
7857 hash_free(aggregate->ecommunity_hash);
7858 }
7859
7860 if (aggregate->lcommunity)
7861 lcommunity_free(&aggregate->lcommunity);
7862
7863 if (aggregate->lcommunity_hash) {
7864 /* Delete all lcommunities in the hash.
7865 */
7866 hash_clean(aggregate->lcommunity_hash,
7867 bgp_aggr_lcommunity_remove);
7868 /* Free up the lcommunity_hash.
7869 */
7870 hash_free(aggregate->lcommunity_hash);
7871 }
7872
7873 if (aggregate->aspath)
7874 aspath_free(aggregate->aspath);
7875
7876 if (aggregate->aspath_hash) {
7877 /* Delete all as-paths in the hash.
7878 */
7879 hash_clean(aggregate->aspath_hash,
7880 bgp_aggr_aspath_remove);
7881 /* Free up the aspath_hash.
7882 */
7883 hash_free(aggregate->aspath_hash);
7884 }
7885
7886 bgp_aggregate_free(aggregate);
7887 bgp_dest_unlock_node(dest);
7888 bgp_dest_unlock_node(dest);
7889
7890 return 0;
7891 }
7892
7893 int bgp_aggregate_set(struct bgp *bgp, struct prefix *prefix, afi_t afi,
7894 safi_t safi, const char *rmap, uint8_t summary_only,
7895 uint8_t as_set, uint8_t origin, bool match_med,
7896 const char *suppress_map,
7897 char *errmsg, size_t errmsg_len)
7898 {
7899 int ret;
7900 struct bgp_dest *dest;
7901 struct bgp_aggregate *aggregate;
7902 uint8_t as_set_new = as_set;
7903 char buf[PREFIX2STR_BUFFER];
7904
7905 if (suppress_map && summary_only) {
7906 snprintf(errmsg, errmsg_len,
7907 "'summary-only' and 'suppress-map' can't be used at the same time\n");
7908 return -1;
7909 }
7910
7911 apply_mask(prefix);
7912
7913 if ((afi == AFI_IP && prefix->prefixlen == IPV4_MAX_BITLEN)
7914 || (afi == AFI_IP6 && prefix->prefixlen == IPV6_MAX_BITLEN)) {
7915 snprintf(
7916 errmsg, errmsg_len,
7917 "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
7918 prefix2str(prefix, buf, PREFIX_STRLEN));
7919 return -1;
7920 }
7921
7922 /* Old configuration check. */
7923 dest = bgp_node_get(bgp->aggregate[afi][safi], prefix);
7924 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
7925
7926 if (aggregate) {
7927 snprintf(errmsg, errmsg_len,
7928 "There is already same aggregate network.\n");
7929 /* try to remove the old entry */
7930 ret = bgp_aggregate_unset(bgp, prefix, afi, safi, errmsg,
7931 errmsg_len);
7932 if (ret) {
7933 snprintf(errmsg, errmsg_len,
7934 "Error deleting aggregate.\n");
7935 bgp_dest_unlock_node(dest);
7936 return -1;
7937 }
7938 }
7939
7940 /* Make aggregate address structure. */
7941 aggregate = bgp_aggregate_new();
7942 aggregate->summary_only = summary_only;
7943 aggregate->match_med = match_med;
7944
7945 /* Network operators MUST NOT locally generate any new
7946 * announcements containing AS_SET or AS_CONFED_SET. If they have
7947 * announced routes with AS_SET or AS_CONFED_SET in them, then they
7948 * SHOULD withdraw those routes and re-announce routes for the
7949 * aggregate or component prefixes (i.e., the more-specific routes
7950 * subsumed by the previously aggregated route) without AS_SET
7951 * or AS_CONFED_SET in the updates.
7952 */
7953 if (bgp->reject_as_sets) {
7954 if (as_set == AGGREGATE_AS_SET) {
7955 as_set_new = AGGREGATE_AS_UNSET;
7956 zlog_warn(
7957 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
7958 __func__);
7959 snprintf(
7960 errmsg, errmsg_len,
7961 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
7962 }
7963 }
7964
7965 aggregate->as_set = as_set_new;
7966 aggregate->safi = safi;
7967 /* Override ORIGIN attribute if defined.
7968 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
7969 * to IGP which is not what rfc4271 says.
7970 * This enables the same behavior, optionally.
7971 */
7972 aggregate->origin = origin;
7973
7974 if (rmap) {
7975 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
7976 route_map_counter_decrement(aggregate->rmap.map);
7977 aggregate->rmap.name =
7978 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
7979 aggregate->rmap.map = route_map_lookup_by_name(rmap);
7980 route_map_counter_increment(aggregate->rmap.map);
7981 }
7982
7983 if (suppress_map) {
7984 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
7985 route_map_counter_decrement(aggregate->suppress_map);
7986
7987 aggregate->suppress_map_name =
7988 XSTRDUP(MTYPE_ROUTE_MAP_NAME, suppress_map);
7989 aggregate->suppress_map =
7990 route_map_lookup_by_name(aggregate->suppress_map_name);
7991 route_map_counter_increment(aggregate->suppress_map);
7992 }
7993
7994 bgp_dest_set_bgp_aggregate_info(dest, aggregate);
7995
7996 /* Aggregate address insert into BGP routing table. */
7997 bgp_aggregate_route(bgp, prefix, afi, safi, aggregate);
7998
7999 return 0;
8000 }
8001
8002 DEFPY_YANG(
8003 aggregate_addressv4, aggregate_addressv4_cmd,
8004 "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> [{"
8005 "as-set$as_set_s"
8006 "|summary-only$summary_only"
8007 "|route-map WORD$rmap_name"
8008 "|origin <egp|igp|incomplete>$origin_s"
8009 "|matching-MED-only$match_med"
8010 "|suppress-map WORD$suppress_map"
8011 "}]",
8012 NO_STR
8013 "Configure BGP aggregate entries\n"
8014 "Aggregate prefix\n"
8015 "Aggregate address\n"
8016 "Aggregate mask\n"
8017 "Generate AS set path information\n"
8018 "Filter more specific routes from updates\n"
8019 "Apply route map to aggregate network\n"
8020 "Route map name\n"
8021 "BGP origin code\n"
8022 "Remote EGP\n"
8023 "Local IGP\n"
8024 "Unknown heritage\n"
8025 "Only aggregate routes with matching MED\n"
8026 "Suppress the selected more specific routes\n"
8027 "Route map with the route selectors\n")
8028 {
8029 char base_xpath[XPATH_MAXLEN];
8030 safi_t safi = bgp_node_safi(vty);
8031 char prefix_buf[PREFIX2STR_BUFFER];
8032
8033 if (addr_str) {
8034 if (netmask_str2prefix_str(addr_str, mask_str, prefix_buf,
8035 sizeof(prefix_buf))
8036 == 0) {
8037 vty_out(vty, "%% Inconsistent address and mask\n");
8038 return CMD_WARNING_CONFIG_FAILED;
8039 }
8040 } else {
8041 strlcpy(prefix_buf, prefix_str, sizeof(prefix_buf));
8042 }
8043
8044 if (!no && origin_s)
8045 nb_cli_enqueue_change(vty, "./origin", NB_OP_MODIFY, origin_s);
8046
8047 if (!no && as_set_s)
8048 nb_cli_enqueue_change(vty, "./as-set", NB_OP_MODIFY, "true");
8049 else
8050 nb_cli_enqueue_change(vty, "./as-set", NB_OP_MODIFY, "false");
8051
8052 if (!no && summary_only)
8053 nb_cli_enqueue_change(vty, "./summary-only", NB_OP_MODIFY,
8054 "true");
8055 else
8056 nb_cli_enqueue_change(vty, "./summary-only", NB_OP_MODIFY,
8057 "false");
8058
8059 if (!no && match_med)
8060 nb_cli_enqueue_change(vty, "./match-med", NB_OP_MODIFY, "true");
8061 else
8062 nb_cli_enqueue_change(vty, "./match-med", NB_OP_MODIFY,
8063 "false");
8064
8065 if (rmap_name)
8066 nb_cli_enqueue_change(vty, "./rmap-policy-export", NB_OP_MODIFY,
8067 rmap_name);
8068 else
8069 nb_cli_enqueue_change(vty, "./rmap-policy-export",
8070 NB_OP_DESTROY, NULL);
8071
8072 if (suppress_map)
8073 nb_cli_enqueue_change(vty, "./suppress-map", NB_OP_MODIFY,
8074 suppress_map);
8075 else
8076 nb_cli_enqueue_change(vty, "./suppress-map", NB_OP_DESTROY,
8077 NULL);
8078
8079 snprintf(
8080 base_xpath, sizeof(base_xpath),
8081 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/aggregate-route[prefix='%s']",
8082 yang_afi_safi_value2identity(AFI_IP, safi),
8083 bgp_afi_safi_get_container_str(AFI_IP, safi), prefix_buf);
8084
8085 if (no)
8086 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
8087 else
8088 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
8089
8090 return nb_cli_apply_changes(vty, base_xpath);
8091 }
8092
8093 DEFPY_YANG(aggregate_addressv6, aggregate_addressv6_cmd,
8094 "[no] aggregate-address X:X::X:X/M$prefix [{"
8095 "as-set$as_set_s"
8096 "|summary-only$summary_only"
8097 "|route-map WORD$rmap_name"
8098 "|origin <egp|igp|incomplete>$origin_s"
8099 "|matching-MED-only$match_med"
8100 "|suppress-map WORD$suppress_map"
8101 "}]",
8102 NO_STR
8103 "Configure BGP aggregate entries\n"
8104 "Aggregate prefix\n"
8105 "Generate AS set path information\n"
8106 "Filter more specific routes from updates\n"
8107 "Apply route map to aggregate network\n"
8108 "Route map name\n"
8109 "BGP origin code\n"
8110 "Remote EGP\n"
8111 "Local IGP\n"
8112 "Unknown heritage\n"
8113 "Only aggregate routes with matching MED\n"
8114 "Suppress the selected more specific routes\n"
8115 "Route map with the route selectors\n")
8116 {
8117 char base_xpath[XPATH_MAXLEN];
8118 safi_t safi = bgp_node_safi(vty);
8119
8120 if (!no && origin_s)
8121 nb_cli_enqueue_change(vty, "./origin", NB_OP_MODIFY, origin_s);
8122
8123 if (!no && as_set_s)
8124 nb_cli_enqueue_change(vty, "./as-set", NB_OP_MODIFY, "true");
8125 else
8126 nb_cli_enqueue_change(vty, "./as-set", NB_OP_MODIFY, "false");
8127
8128 if (!no && summary_only)
8129 nb_cli_enqueue_change(vty, "./summary-only", NB_OP_MODIFY,
8130 "true");
8131 else
8132 nb_cli_enqueue_change(vty, "./summary-only", NB_OP_MODIFY,
8133 "false");
8134
8135 if (!no && match_med)
8136 nb_cli_enqueue_change(vty, "./match-med", NB_OP_MODIFY, "true");
8137 else
8138 nb_cli_enqueue_change(vty, "./match-med", NB_OP_MODIFY,
8139 "false");
8140
8141 if (rmap_name)
8142 nb_cli_enqueue_change(vty, "./rmap-policy-export", NB_OP_MODIFY,
8143 rmap_name);
8144
8145 if (suppress_map)
8146 nb_cli_enqueue_change(vty, "./suppress-map", NB_OP_MODIFY,
8147 suppress_map);
8148 else
8149 nb_cli_enqueue_change(vty, "./suppress-map", NB_OP_DESTROY,
8150 NULL);
8151
8152 snprintf(
8153 base_xpath, sizeof(base_xpath),
8154 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/aggregate-route[prefix='%s']",
8155 yang_afi_safi_value2identity(AFI_IP6, safi),
8156 bgp_afi_safi_get_container_str(AFI_IP6, safi), prefix_str);
8157
8158 if (no)
8159 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
8160 else
8161 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
8162
8163 return nb_cli_apply_changes(vty, base_xpath);
8164 }
8165
8166 void cli_show_bgp_global_afi_safi_unicast_aggregate_route(
8167 struct vty *vty, struct lyd_node *dnode, bool show_defaults)
8168 {
8169 uint8_t origin;
8170
8171 vty_out(vty, " aggregate-address %s",
8172 yang_dnode_get_string(dnode, "./prefix"));
8173
8174 if (yang_dnode_get_bool(dnode, "./as-set"))
8175 vty_out(vty, " as-set");
8176
8177 if (yang_dnode_get_bool(dnode, "./summary-only"))
8178 vty_out(vty, " summary-only");
8179
8180 if (yang_dnode_exists(dnode, "./rmap-policy-export"))
8181 vty_out(vty, " route-map %s",
8182 yang_dnode_get_string(dnode, "./rmap-policy-export"));
8183
8184 origin = yang_dnode_get_enum(dnode, "./origin");
8185 if (origin != BGP_ORIGIN_UNSPECIFIED)
8186 vty_out(vty, " origin %s", bgp_origin2str(origin));
8187
8188 if (yang_dnode_get_bool(dnode, "./match-med"))
8189 vty_out(vty, " matching-MED-only");
8190
8191 vty_out(vty, "\n");
8192 }
8193
8194 /* Redistribute route treatment. */
8195 void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
8196 const union g_addr *nexthop, ifindex_t ifindex,
8197 enum nexthop_types_t nhtype, uint32_t metric,
8198 uint8_t type, unsigned short instance,
8199 route_tag_t tag)
8200 {
8201 struct bgp_path_info *new;
8202 struct bgp_path_info *bpi;
8203 struct bgp_path_info rmap_path;
8204 struct bgp_dest *bn;
8205 struct attr attr;
8206 struct attr *new_attr;
8207 afi_t afi;
8208 route_map_result_t ret;
8209 struct bgp_redist *red;
8210
8211 /* Make default attribute. */
8212 bgp_attr_default_set(&attr, BGP_ORIGIN_INCOMPLETE);
8213 /*
8214 * This must not be NULL to satisfy Coverity SA
8215 */
8216 assert(attr.aspath);
8217
8218 switch (nhtype) {
8219 case NEXTHOP_TYPE_IFINDEX:
8220 break;
8221 case NEXTHOP_TYPE_IPV4:
8222 case NEXTHOP_TYPE_IPV4_IFINDEX:
8223 attr.nexthop = nexthop->ipv4;
8224 break;
8225 case NEXTHOP_TYPE_IPV6:
8226 case NEXTHOP_TYPE_IPV6_IFINDEX:
8227 attr.mp_nexthop_global = nexthop->ipv6;
8228 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
8229 break;
8230 case NEXTHOP_TYPE_BLACKHOLE:
8231 switch (p->family) {
8232 case AF_INET:
8233 attr.nexthop.s_addr = INADDR_ANY;
8234 break;
8235 case AF_INET6:
8236 memset(&attr.mp_nexthop_global, 0,
8237 sizeof(attr.mp_nexthop_global));
8238 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
8239 break;
8240 }
8241 break;
8242 }
8243 attr.nh_ifindex = ifindex;
8244
8245 attr.med = metric;
8246 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
8247 attr.tag = tag;
8248
8249 afi = family2afi(p->family);
8250
8251 red = bgp_redist_lookup(bgp, afi, type, instance);
8252 if (red) {
8253 struct attr attr_new;
8254
8255 /* Copy attribute for modification. */
8256 attr_new = attr;
8257
8258 if (red->redist_metric_flag)
8259 attr_new.med = red->redist_metric;
8260
8261 /* Apply route-map. */
8262 if (red->rmap.name) {
8263 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
8264 rmap_path.peer = bgp->peer_self;
8265 rmap_path.attr = &attr_new;
8266
8267 SET_FLAG(bgp->peer_self->rmap_type,
8268 PEER_RMAP_TYPE_REDISTRIBUTE);
8269
8270 ret = route_map_apply(red->rmap.map, p, &rmap_path);
8271
8272 bgp->peer_self->rmap_type = 0;
8273
8274 if (ret == RMAP_DENYMATCH) {
8275 /* Free uninterned attribute. */
8276 bgp_attr_flush(&attr_new);
8277
8278 /* Unintern original. */
8279 aspath_unintern(&attr.aspath);
8280 bgp_redistribute_delete(bgp, p, type, instance);
8281 return;
8282 }
8283 }
8284
8285 if (bgp_in_graceful_shutdown(bgp))
8286 bgp_attr_add_gshut_community(&attr_new);
8287
8288 bn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8289 SAFI_UNICAST, p, NULL);
8290
8291 new_attr = bgp_attr_intern(&attr_new);
8292
8293 for (bpi = bgp_dest_get_bgp_path_info(bn); bpi; bpi = bpi->next)
8294 if (bpi->peer == bgp->peer_self
8295 && bpi->sub_type == BGP_ROUTE_REDISTRIBUTE)
8296 break;
8297
8298 if (bpi) {
8299 /* Ensure the (source route) type is updated. */
8300 bpi->type = type;
8301 if (attrhash_cmp(bpi->attr, new_attr)
8302 && !CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
8303 bgp_attr_unintern(&new_attr);
8304 aspath_unintern(&attr.aspath);
8305 bgp_dest_unlock_node(bn);
8306 return;
8307 } else {
8308 /* The attribute is changed. */
8309 bgp_path_info_set_flag(bn, bpi,
8310 BGP_PATH_ATTR_CHANGED);
8311
8312 /* Rewrite BGP route information. */
8313 if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
8314 bgp_path_info_restore(bn, bpi);
8315 else
8316 bgp_aggregate_decrement(
8317 bgp, p, bpi, afi, SAFI_UNICAST);
8318 bgp_attr_unintern(&bpi->attr);
8319 bpi->attr = new_attr;
8320 bpi->uptime = bgp_clock();
8321
8322 /* Process change. */
8323 bgp_aggregate_increment(bgp, p, bpi, afi,
8324 SAFI_UNICAST);
8325 bgp_process(bgp, bn, afi, SAFI_UNICAST);
8326 bgp_dest_unlock_node(bn);
8327 aspath_unintern(&attr.aspath);
8328
8329 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8330 || (bgp->inst_type
8331 == BGP_INSTANCE_TYPE_DEFAULT)) {
8332
8333 vpn_leak_from_vrf_update(
8334 bgp_get_default(), bgp, bpi);
8335 }
8336 return;
8337 }
8338 }
8339
8340 new = info_make(type, BGP_ROUTE_REDISTRIBUTE, instance,
8341 bgp->peer_self, new_attr, bn);
8342 SET_FLAG(new->flags, BGP_PATH_VALID);
8343
8344 bgp_aggregate_increment(bgp, p, new, afi, SAFI_UNICAST);
8345 bgp_path_info_add(bn, new);
8346 bgp_dest_unlock_node(bn);
8347 bgp_process(bgp, bn, afi, SAFI_UNICAST);
8348
8349 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8350 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8351
8352 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
8353 }
8354 }
8355
8356 /* Unintern original. */
8357 aspath_unintern(&attr.aspath);
8358 }
8359
8360 void bgp_redistribute_delete(struct bgp *bgp, struct prefix *p, uint8_t type,
8361 unsigned short instance)
8362 {
8363 afi_t afi;
8364 struct bgp_dest *dest;
8365 struct bgp_path_info *pi;
8366 struct bgp_redist *red;
8367
8368 afi = family2afi(p->family);
8369
8370 red = bgp_redist_lookup(bgp, afi, type, instance);
8371 if (red) {
8372 dest = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8373 SAFI_UNICAST, p, NULL);
8374
8375 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
8376 if (pi->peer == bgp->peer_self && pi->type == type)
8377 break;
8378
8379 if (pi) {
8380 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8381 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8382
8383 vpn_leak_from_vrf_withdraw(bgp_get_default(),
8384 bgp, pi);
8385 }
8386 bgp_aggregate_decrement(bgp, p, pi, afi, SAFI_UNICAST);
8387 bgp_path_info_delete(dest, pi);
8388 bgp_process(bgp, dest, afi, SAFI_UNICAST);
8389 }
8390 bgp_dest_unlock_node(dest);
8391 }
8392 }
8393
8394 /* Withdraw specified route type's route. */
8395 void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type,
8396 unsigned short instance)
8397 {
8398 struct bgp_dest *dest;
8399 struct bgp_path_info *pi;
8400 struct bgp_table *table;
8401
8402 table = bgp->rib[afi][SAFI_UNICAST];
8403
8404 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
8405 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
8406 if (pi->peer == bgp->peer_self && pi->type == type
8407 && pi->instance == instance)
8408 break;
8409
8410 if (pi) {
8411 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8412 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8413
8414 vpn_leak_from_vrf_withdraw(bgp_get_default(),
8415 bgp, pi);
8416 }
8417 bgp_aggregate_decrement(bgp, bgp_dest_get_prefix(dest),
8418 pi, afi, SAFI_UNICAST);
8419 bgp_path_info_delete(dest, pi);
8420 bgp_process(bgp, dest, afi, SAFI_UNICAST);
8421 }
8422 }
8423 }
8424
8425 /* Static function to display route. */
8426 static void route_vty_out_route(struct bgp_dest *dest, const struct prefix *p,
8427 struct vty *vty, json_object *json, bool wide)
8428 {
8429 int len = 0;
8430 char buf[BUFSIZ];
8431 char buf2[BUFSIZ];
8432
8433 if (p->family == AF_INET) {
8434 if (!json) {
8435 len = vty_out(vty, "%pFX", p);
8436 } else {
8437 json_object_string_add(json, "prefix",
8438 inet_ntop(p->family,
8439 &p->u.prefix, buf,
8440 BUFSIZ));
8441 json_object_int_add(json, "prefixLen", p->prefixlen);
8442 prefix2str(p, buf2, PREFIX_STRLEN);
8443 json_object_string_add(json, "network", buf2);
8444 json_object_int_add(json, "version", dest->version);
8445 }
8446 } else if (p->family == AF_ETHERNET) {
8447 len = vty_out(vty, "%pFX", p);
8448 } else if (p->family == AF_EVPN) {
8449 if (!json)
8450 len = vty_out(vty, "%pFX", (struct prefix_evpn *)p);
8451 else
8452 bgp_evpn_route2json((struct prefix_evpn *)p, json);
8453 } else if (p->family == AF_FLOWSPEC) {
8454 route_vty_out_flowspec(vty, p, NULL,
8455 json ?
8456 NLRI_STRING_FORMAT_JSON_SIMPLE :
8457 NLRI_STRING_FORMAT_MIN, json);
8458 } else {
8459 if (!json)
8460 len = vty_out(vty, "%pFX", p);
8461 else {
8462 json_object_string_add(json, "prefix",
8463 inet_ntop(p->family,
8464 &p->u.prefix, buf,
8465 BUFSIZ));
8466 json_object_int_add(json, "prefixLen", p->prefixlen);
8467 prefix2str(p, buf2, PREFIX_STRLEN);
8468 json_object_string_add(json, "network", buf2);
8469 json_object_int_add(json, "version", dest->version);
8470 }
8471 }
8472
8473 if (!json) {
8474 len = wide ? (45 - len) : (17 - len);
8475 if (len < 1)
8476 vty_out(vty, "\n%*s", 20, " ");
8477 else
8478 vty_out(vty, "%*s", len, " ");
8479 }
8480 }
8481
8482 enum bgp_display_type {
8483 normal_list,
8484 };
8485
8486 static const char *
8487 bgp_path_selection_reason2str(enum bgp_path_selection_reason reason)
8488 {
8489 switch (reason) {
8490 case bgp_path_selection_none:
8491 return "Nothing to Select";
8492 case bgp_path_selection_first:
8493 return "First path received";
8494 case bgp_path_selection_evpn_sticky_mac:
8495 return "EVPN Sticky Mac";
8496 case bgp_path_selection_evpn_seq:
8497 return "EVPN sequence number";
8498 case bgp_path_selection_evpn_lower_ip:
8499 return "EVPN lower IP";
8500 case bgp_path_selection_evpn_local_path:
8501 return "EVPN local ES path";
8502 case bgp_path_selection_evpn_non_proxy:
8503 return "EVPN non proxy";
8504 case bgp_path_selection_weight:
8505 return "Weight";
8506 case bgp_path_selection_local_pref:
8507 return "Local Pref";
8508 case bgp_path_selection_local_route:
8509 return "Local Route";
8510 case bgp_path_selection_confed_as_path:
8511 return "Confederation based AS Path";
8512 case bgp_path_selection_as_path:
8513 return "AS Path";
8514 case bgp_path_selection_origin:
8515 return "Origin";
8516 case bgp_path_selection_med:
8517 return "MED";
8518 case bgp_path_selection_peer:
8519 return "Peer Type";
8520 case bgp_path_selection_confed:
8521 return "Confed Peer Type";
8522 case bgp_path_selection_igp_metric:
8523 return "IGP Metric";
8524 case bgp_path_selection_older:
8525 return "Older Path";
8526 case bgp_path_selection_router_id:
8527 return "Router ID";
8528 case bgp_path_selection_cluster_length:
8529 return "Cluster length";
8530 case bgp_path_selection_stale:
8531 return "Path Staleness";
8532 case bgp_path_selection_local_configured:
8533 return "Locally configured route";
8534 case bgp_path_selection_neighbor_ip:
8535 return "Neighbor IP";
8536 case bgp_path_selection_default:
8537 return "Nothing left to compare";
8538 }
8539 return "Invalid (internal error)";
8540 }
8541
8542 /* Print the short form route status for a bgp_path_info */
8543 static void route_vty_short_status_out(struct vty *vty,
8544 struct bgp_path_info *path,
8545 const struct prefix *p,
8546 json_object *json_path)
8547 {
8548 enum rpki_states rpki_state = RPKI_NOT_BEING_USED;
8549
8550 if (json_path) {
8551
8552 /* Route status display. */
8553 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
8554 json_object_boolean_true_add(json_path, "removed");
8555
8556 if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
8557 json_object_boolean_true_add(json_path, "stale");
8558
8559 if (path->extra && bgp_path_suppressed(path))
8560 json_object_boolean_true_add(json_path, "suppressed");
8561
8562 if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
8563 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
8564 json_object_boolean_true_add(json_path, "valid");
8565
8566 /* Selected */
8567 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
8568 json_object_boolean_true_add(json_path, "history");
8569
8570 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
8571 json_object_boolean_true_add(json_path, "damped");
8572
8573 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
8574 json_object_boolean_true_add(json_path, "bestpath");
8575 json_object_string_add(json_path, "selectionReason",
8576 bgp_path_selection_reason2str(
8577 path->net->reason));
8578 }
8579
8580 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
8581 json_object_boolean_true_add(json_path, "multipath");
8582
8583 /* Internal route. */
8584 if ((path->peer->as)
8585 && (path->peer->as == path->peer->local_as))
8586 json_object_string_add(json_path, "pathFrom",
8587 "internal");
8588 else
8589 json_object_string_add(json_path, "pathFrom",
8590 "external");
8591
8592 return;
8593 }
8594
8595 /* RPKI validation state */
8596 rpki_state =
8597 hook_call(bgp_rpki_prefix_status, path->peer, path->attr, p);
8598
8599 if (rpki_state == RPKI_VALID)
8600 vty_out(vty, "V");
8601 else if (rpki_state == RPKI_INVALID)
8602 vty_out(vty, "I");
8603 else if (rpki_state == RPKI_NOTFOUND)
8604 vty_out(vty, "N");
8605
8606 /* Route status display. */
8607 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
8608 vty_out(vty, "R");
8609 else if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
8610 vty_out(vty, "S");
8611 else if (bgp_path_suppressed(path))
8612 vty_out(vty, "s");
8613 else if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
8614 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
8615 vty_out(vty, "*");
8616 else
8617 vty_out(vty, " ");
8618
8619 /* Selected */
8620 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
8621 vty_out(vty, "h");
8622 else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
8623 vty_out(vty, "d");
8624 else if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
8625 vty_out(vty, ">");
8626 else if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
8627 vty_out(vty, "=");
8628 else
8629 vty_out(vty, " ");
8630
8631 /* Internal route. */
8632 if (path->peer && (path->peer->as)
8633 && (path->peer->as == path->peer->local_as))
8634 vty_out(vty, "i");
8635 else
8636 vty_out(vty, " ");
8637 }
8638
8639 static char *bgp_nexthop_hostname(struct peer *peer,
8640 struct bgp_nexthop_cache *bnc)
8641 {
8642 if (peer->hostname
8643 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME))
8644 return peer->hostname;
8645 return NULL;
8646 }
8647
8648 /* called from terminal list command */
8649 void route_vty_out(struct vty *vty, const struct prefix *p,
8650 struct bgp_path_info *path, int display, safi_t safi,
8651 json_object *json_paths, bool wide)
8652 {
8653 int len;
8654 struct attr *attr = path->attr;
8655 json_object *json_path = NULL;
8656 json_object *json_nexthops = NULL;
8657 json_object *json_nexthop_global = NULL;
8658 json_object *json_nexthop_ll = NULL;
8659 json_object *json_ext_community = NULL;
8660 char vrf_id_str[VRF_NAMSIZ] = {0};
8661 bool nexthop_self =
8662 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
8663 bool nexthop_othervrf = false;
8664 vrf_id_t nexthop_vrfid = VRF_DEFAULT;
8665 const char *nexthop_vrfname = VRF_DEFAULT_NAME;
8666 char *nexthop_hostname =
8667 bgp_nexthop_hostname(path->peer, path->nexthop);
8668 char esi_buf[ESI_STR_LEN];
8669
8670 if (json_paths)
8671 json_path = json_object_new_object();
8672
8673 /* short status lead text */
8674 route_vty_short_status_out(vty, path, p, json_path);
8675
8676 if (!json_paths) {
8677 /* print prefix and mask */
8678 if (!display)
8679 route_vty_out_route(path->net, p, vty, json_path, wide);
8680 else
8681 vty_out(vty, "%*s", (wide ? 45 : 17), " ");
8682 } else {
8683 route_vty_out_route(path->net, p, vty, json_path, wide);
8684 }
8685
8686 /*
8687 * If vrf id of nexthop is different from that of prefix,
8688 * set up printable string to append
8689 */
8690 if (path->extra && path->extra->bgp_orig) {
8691 const char *self = "";
8692
8693 if (nexthop_self)
8694 self = "<";
8695
8696 nexthop_othervrf = true;
8697 nexthop_vrfid = path->extra->bgp_orig->vrf_id;
8698
8699 if (path->extra->bgp_orig->vrf_id == VRF_UNKNOWN)
8700 snprintf(vrf_id_str, sizeof(vrf_id_str),
8701 "@%s%s", VRFID_NONE_STR, self);
8702 else
8703 snprintf(vrf_id_str, sizeof(vrf_id_str), "@%u%s",
8704 path->extra->bgp_orig->vrf_id, self);
8705
8706 if (path->extra->bgp_orig->inst_type
8707 != BGP_INSTANCE_TYPE_DEFAULT)
8708
8709 nexthop_vrfname = path->extra->bgp_orig->name;
8710 } else {
8711 const char *self = "";
8712
8713 if (nexthop_self)
8714 self = "<";
8715
8716 snprintf(vrf_id_str, sizeof(vrf_id_str), "%s", self);
8717 }
8718
8719 /*
8720 * For ENCAP and EVPN routes, nexthop address family is not
8721 * neccessarily the same as the prefix address family.
8722 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
8723 * EVPN routes are also exchanged with a MP nexthop. Currently,
8724 * this
8725 * is only IPv4, the value will be present in either
8726 * attr->nexthop or
8727 * attr->mp_nexthop_global_in
8728 */
8729 if ((safi == SAFI_ENCAP) || (safi == SAFI_MPLS_VPN)) {
8730 char buf[BUFSIZ];
8731 char nexthop[128];
8732 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
8733
8734 switch (af) {
8735 case AF_INET:
8736 snprintf(nexthop, sizeof(nexthop), "%s",
8737 inet_ntop(af, &attr->mp_nexthop_global_in, buf,
8738 BUFSIZ));
8739 break;
8740 case AF_INET6:
8741 snprintf(nexthop, sizeof(nexthop), "%s",
8742 inet_ntop(af, &attr->mp_nexthop_global, buf,
8743 BUFSIZ));
8744 break;
8745 default:
8746 snprintf(nexthop, sizeof(nexthop), "?");
8747 break;
8748 }
8749
8750 if (json_paths) {
8751 json_nexthop_global = json_object_new_object();
8752
8753 json_object_string_add(json_nexthop_global, "ip",
8754 nexthop);
8755
8756 if (path->peer->hostname)
8757 json_object_string_add(json_nexthop_global,
8758 "hostname",
8759 path->peer->hostname);
8760
8761 json_object_string_add(json_nexthop_global, "afi",
8762 (af == AF_INET) ? "ipv4"
8763 : "ipv6");
8764 json_object_boolean_true_add(json_nexthop_global,
8765 "used");
8766 } else {
8767 if (nexthop_hostname)
8768 len = vty_out(vty, "%s(%s)%s", nexthop,
8769 nexthop_hostname, vrf_id_str);
8770 else
8771 len = vty_out(vty, "%s%s", nexthop, vrf_id_str);
8772
8773 len = wide ? (41 - len) : (16 - len);
8774 if (len < 1)
8775 vty_out(vty, "\n%*s", 36, " ");
8776 else
8777 vty_out(vty, "%*s", len, " ");
8778 }
8779 } else if (safi == SAFI_EVPN) {
8780 if (json_paths) {
8781 char buf[BUFSIZ] = {0};
8782
8783 json_nexthop_global = json_object_new_object();
8784
8785 json_object_string_add(json_nexthop_global, "ip",
8786 inet_ntop(AF_INET,
8787 &attr->nexthop, buf,
8788 sizeof(buf)));
8789
8790 if (path->peer->hostname)
8791 json_object_string_add(json_nexthop_global,
8792 "hostname",
8793 path->peer->hostname);
8794
8795 json_object_string_add(json_nexthop_global, "afi",
8796 "ipv4");
8797 json_object_boolean_true_add(json_nexthop_global,
8798 "used");
8799 } else {
8800 if (nexthop_hostname)
8801 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
8802 nexthop_hostname, vrf_id_str);
8803 else
8804 len = vty_out(vty, "%pI4%s", &attr->nexthop,
8805 vrf_id_str);
8806
8807 len = wide ? (41 - len) : (16 - len);
8808 if (len < 1)
8809 vty_out(vty, "\n%*s", 36, " ");
8810 else
8811 vty_out(vty, "%*s", len, " ");
8812 }
8813 } else if (safi == SAFI_FLOWSPEC) {
8814 if (attr->nexthop.s_addr != INADDR_ANY) {
8815 if (json_paths) {
8816 char buf[BUFSIZ] = {0};
8817
8818 json_nexthop_global = json_object_new_object();
8819
8820 json_object_string_add(json_nexthop_global,
8821 "afi", "ipv4");
8822 json_object_string_add(
8823 json_nexthop_global, "ip",
8824 inet_ntop(AF_INET, &attr->nexthop, buf,
8825 sizeof(buf)));
8826
8827 if (path->peer->hostname)
8828 json_object_string_add(
8829 json_nexthop_global, "hostname",
8830 path->peer->hostname);
8831
8832 json_object_boolean_true_add(
8833 json_nexthop_global,
8834 "used");
8835 } else {
8836 if (nexthop_hostname)
8837 len = vty_out(vty, "%pI4(%s)%s",
8838 &attr->nexthop,
8839 nexthop_hostname,
8840 vrf_id_str);
8841 else
8842 len = vty_out(vty, "%pI4%s",
8843 &attr->nexthop,
8844 vrf_id_str);
8845
8846 len = wide ? (41 - len) : (16 - len);
8847 if (len < 1)
8848 vty_out(vty, "\n%*s", 36, " ");
8849 else
8850 vty_out(vty, "%*s", len, " ");
8851 }
8852 }
8853 } else if (p->family == AF_INET && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
8854 if (json_paths) {
8855 char buf[BUFSIZ] = {0};
8856
8857 json_nexthop_global = json_object_new_object();
8858
8859 json_object_string_add(json_nexthop_global, "ip",
8860 inet_ntop(AF_INET,
8861 &attr->nexthop, buf,
8862 sizeof(buf)));
8863
8864 if (path->peer->hostname)
8865 json_object_string_add(json_nexthop_global,
8866 "hostname",
8867 path->peer->hostname);
8868
8869 json_object_string_add(json_nexthop_global, "afi",
8870 "ipv4");
8871 json_object_boolean_true_add(json_nexthop_global,
8872 "used");
8873 } else {
8874 if (nexthop_hostname)
8875 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
8876 nexthop_hostname, vrf_id_str);
8877 else
8878 len = vty_out(vty, "%pI4%s", &attr->nexthop,
8879 vrf_id_str);
8880
8881 len = wide ? (41 - len) : (16 - len);
8882 if (len < 1)
8883 vty_out(vty, "\n%*s", 36, " ");
8884 else
8885 vty_out(vty, "%*s", len, " ");
8886 }
8887 }
8888
8889 /* IPv6 Next Hop */
8890 else if (p->family == AF_INET6 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
8891 char buf[BUFSIZ];
8892
8893 if (json_paths) {
8894 json_nexthop_global = json_object_new_object();
8895 json_object_string_add(
8896 json_nexthop_global, "ip",
8897 inet_ntop(AF_INET6, &attr->mp_nexthop_global,
8898 buf, BUFSIZ));
8899
8900 if (path->peer->hostname)
8901 json_object_string_add(json_nexthop_global,
8902 "hostname",
8903 path->peer->hostname);
8904
8905 json_object_string_add(json_nexthop_global, "afi",
8906 "ipv6");
8907 json_object_string_add(json_nexthop_global, "scope",
8908 "global");
8909
8910 /* We display both LL & GL if both have been
8911 * received */
8912 if ((attr->mp_nexthop_len
8913 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
8914 || (path->peer->conf_if)) {
8915 json_nexthop_ll = json_object_new_object();
8916 json_object_string_add(
8917 json_nexthop_ll, "ip",
8918 inet_ntop(AF_INET6,
8919 &attr->mp_nexthop_local, buf,
8920 BUFSIZ));
8921
8922 if (path->peer->hostname)
8923 json_object_string_add(
8924 json_nexthop_ll, "hostname",
8925 path->peer->hostname);
8926
8927 json_object_string_add(json_nexthop_ll, "afi",
8928 "ipv6");
8929 json_object_string_add(json_nexthop_ll, "scope",
8930 "link-local");
8931
8932 if ((IPV6_ADDR_CMP(&attr->mp_nexthop_global,
8933 &attr->mp_nexthop_local)
8934 != 0)
8935 && !attr->mp_nexthop_prefer_global)
8936 json_object_boolean_true_add(
8937 json_nexthop_ll, "used");
8938 else
8939 json_object_boolean_true_add(
8940 json_nexthop_global, "used");
8941 } else
8942 json_object_boolean_true_add(
8943 json_nexthop_global, "used");
8944 } else {
8945 /* Display LL if LL/Global both in table unless
8946 * prefer-global is set */
8947 if (((attr->mp_nexthop_len
8948 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
8949 && !attr->mp_nexthop_prefer_global)
8950 || (path->peer->conf_if)) {
8951 if (path->peer->conf_if) {
8952 len = vty_out(vty, "%s",
8953 path->peer->conf_if);
8954 /* len of IPv6 addr + max len of def
8955 * ifname */
8956 len = wide ? (41 - len) : (16 - len);
8957
8958 if (len < 1)
8959 vty_out(vty, "\n%*s", 36, " ");
8960 else
8961 vty_out(vty, "%*s", len, " ");
8962 } else {
8963 if (nexthop_hostname)
8964 len = vty_out(
8965 vty, "%pI6(%s)%s",
8966 &attr->mp_nexthop_local,
8967 nexthop_hostname,
8968 vrf_id_str);
8969 else
8970 len = vty_out(
8971 vty, "%pI6%s",
8972 &attr->mp_nexthop_local,
8973 vrf_id_str);
8974
8975 len = wide ? (41 - len) : (16 - len);
8976
8977 if (len < 1)
8978 vty_out(vty, "\n%*s", 36, " ");
8979 else
8980 vty_out(vty, "%*s", len, " ");
8981 }
8982 } else {
8983 if (nexthop_hostname)
8984 len = vty_out(vty, "%pI6(%s)%s",
8985 &attr->mp_nexthop_global,
8986 nexthop_hostname,
8987 vrf_id_str);
8988 else
8989 len = vty_out(vty, "%pI6%s",
8990 &attr->mp_nexthop_global,
8991 vrf_id_str);
8992
8993 len = wide ? (41 - len) : (16 - len);
8994
8995 if (len < 1)
8996 vty_out(vty, "\n%*s", 36, " ");
8997 else
8998 vty_out(vty, "%*s", len, " ");
8999 }
9000 }
9001 }
9002
9003 /* MED/Metric */
9004 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
9005 if (json_paths)
9006 json_object_int_add(json_path, "metric", attr->med);
9007 else if (wide)
9008 vty_out(vty, "%7u", attr->med);
9009 else
9010 vty_out(vty, "%10u", attr->med);
9011 else if (!json_paths) {
9012 if (wide)
9013 vty_out(vty, "%*s", 7, " ");
9014 else
9015 vty_out(vty, "%*s", 10, " ");
9016 }
9017
9018 /* Local Pref */
9019 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
9020 if (json_paths)
9021 json_object_int_add(json_path, "locPrf",
9022 attr->local_pref);
9023 else
9024 vty_out(vty, "%7u", attr->local_pref);
9025 else if (!json_paths)
9026 vty_out(vty, " ");
9027
9028 if (json_paths)
9029 json_object_int_add(json_path, "weight", attr->weight);
9030 else
9031 vty_out(vty, "%7u ", attr->weight);
9032
9033 if (json_paths) {
9034 char buf[BUFSIZ];
9035 json_object_string_add(
9036 json_path, "peerId",
9037 sockunion2str(&path->peer->su, buf, SU_ADDRSTRLEN));
9038 }
9039
9040 /* Print aspath */
9041 if (attr->aspath) {
9042 if (json_paths)
9043 json_object_string_add(json_path, "path",
9044 attr->aspath->str);
9045 else
9046 aspath_print_vty(vty, "%s", attr->aspath, " ");
9047 }
9048
9049 /* Print origin */
9050 if (json_paths)
9051 json_object_string_add(json_path, "origin",
9052 bgp_origin_long_str[attr->origin]);
9053 else
9054 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9055
9056 if (json_paths) {
9057 if (bgp_evpn_is_esi_valid(&attr->esi)) {
9058 json_object_string_add(json_path, "esi",
9059 esi_to_str(&attr->esi,
9060 esi_buf, sizeof(esi_buf)));
9061 }
9062 if (safi == SAFI_EVPN &&
9063 attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
9064 json_ext_community = json_object_new_object();
9065 json_object_string_add(json_ext_community,
9066 "string",
9067 attr->ecommunity->str);
9068 json_object_object_add(json_path,
9069 "extendedCommunity",
9070 json_ext_community);
9071 }
9072
9073 if (nexthop_self)
9074 json_object_boolean_true_add(json_path,
9075 "announceNexthopSelf");
9076 if (nexthop_othervrf) {
9077 json_object_string_add(json_path, "nhVrfName",
9078 nexthop_vrfname);
9079
9080 json_object_int_add(json_path, "nhVrfId",
9081 ((nexthop_vrfid == VRF_UNKNOWN)
9082 ? -1
9083 : (int)nexthop_vrfid));
9084 }
9085 }
9086
9087 if (json_paths) {
9088 if (json_nexthop_global || json_nexthop_ll) {
9089 json_nexthops = json_object_new_array();
9090
9091 if (json_nexthop_global)
9092 json_object_array_add(json_nexthops,
9093 json_nexthop_global);
9094
9095 if (json_nexthop_ll)
9096 json_object_array_add(json_nexthops,
9097 json_nexthop_ll);
9098
9099 json_object_object_add(json_path, "nexthops",
9100 json_nexthops);
9101 }
9102
9103 json_object_array_add(json_paths, json_path);
9104 } else {
9105 vty_out(vty, "\n");
9106
9107 if (safi == SAFI_EVPN) {
9108 struct bgp_path_es_info *path_es_info = NULL;
9109
9110 if (bgp_evpn_is_esi_valid(&attr->esi)) {
9111 /* XXX - add these params to the json out */
9112 vty_out(vty, "%*s", 20, " ");
9113 vty_out(vty, "ESI:%s",
9114 esi_to_str(&attr->esi, esi_buf,
9115 sizeof(esi_buf)));
9116
9117 if (path->extra && path->extra->mh_info)
9118 path_es_info =
9119 path->extra->mh_info->es_info;
9120
9121 if (path_es_info && path_es_info->es)
9122 vty_out(vty, " VNI: %u",
9123 path_es_info->vni);
9124 vty_out(vty, "\n");
9125 }
9126 if (attr->flag &
9127 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
9128 vty_out(vty, "%*s", 20, " ");
9129 vty_out(vty, "%s\n", attr->ecommunity->str);
9130 }
9131 }
9132
9133 #ifdef ENABLE_BGP_VNC
9134 /* prints an additional line, indented, with VNC info, if
9135 * present */
9136 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
9137 rfapi_vty_out_vncinfo(vty, p, path, safi);
9138 #endif
9139 }
9140 }
9141
9142 /* called from terminal list command */
9143 void route_vty_out_tmp(struct vty *vty, struct bgp_dest *dest,
9144 const struct prefix *p, struct attr *attr, safi_t safi,
9145 bool use_json, json_object *json_ar, bool wide)
9146 {
9147 json_object *json_status = NULL;
9148 json_object *json_net = NULL;
9149 int len;
9150 char buff[BUFSIZ];
9151
9152 /* Route status display. */
9153 if (use_json) {
9154 json_status = json_object_new_object();
9155 json_net = json_object_new_object();
9156 } else {
9157 vty_out(vty, "*");
9158 vty_out(vty, ">");
9159 vty_out(vty, " ");
9160 }
9161
9162 /* print prefix and mask */
9163 if (use_json) {
9164 if (safi == SAFI_EVPN)
9165 bgp_evpn_route2json((struct prefix_evpn *)p, json_net);
9166 else if (p->family == AF_INET || p->family == AF_INET6) {
9167 json_object_string_add(
9168 json_net, "addrPrefix",
9169 inet_ntop(p->family, &p->u.prefix, buff,
9170 BUFSIZ));
9171 json_object_int_add(json_net, "prefixLen",
9172 p->prefixlen);
9173 prefix2str(p, buff, PREFIX_STRLEN);
9174 json_object_string_add(json_net, "network", buff);
9175 }
9176 } else
9177 route_vty_out_route(dest, p, vty, NULL, wide);
9178
9179 /* Print attribute */
9180 if (attr) {
9181 if (use_json) {
9182 char buf[BUFSIZ] = {0};
9183
9184 if (p->family == AF_INET
9185 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9186 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
9187 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
9188 json_object_string_add(
9189 json_net, "nextHop",
9190 inet_ntop(
9191 AF_INET,
9192 &attr->mp_nexthop_global_in,
9193 buf, sizeof(buf)));
9194 else
9195 json_object_string_add(
9196 json_net, "nextHop",
9197 inet_ntop(AF_INET,
9198 &attr->nexthop, buf,
9199 sizeof(buf)));
9200 } else if (p->family == AF_INET6
9201 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
9202 char buf[BUFSIZ];
9203
9204 json_object_string_add(
9205 json_net, "nextHopGlobal",
9206 inet_ntop(AF_INET6,
9207 &attr->mp_nexthop_global, buf,
9208 BUFSIZ));
9209 } else if (p->family == AF_EVPN
9210 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
9211 char buf[BUFSIZ] = {0};
9212
9213 json_object_string_add(
9214 json_net, "nextHop",
9215 inet_ntop(AF_INET,
9216 &attr->mp_nexthop_global_in,
9217 buf, sizeof(buf)));
9218 }
9219
9220 if (attr->flag
9221 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
9222 json_object_int_add(json_net, "metric",
9223 attr->med);
9224
9225 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
9226 json_object_int_add(json_net, "locPrf",
9227 attr->local_pref);
9228
9229 json_object_int_add(json_net, "weight", attr->weight);
9230
9231 /* Print aspath */
9232 if (attr->aspath)
9233 json_object_string_add(json_net, "path",
9234 attr->aspath->str);
9235
9236 /* Print origin */
9237 json_object_string_add(json_net, "bgpOriginCode",
9238 bgp_origin_str[attr->origin]);
9239 } else {
9240 if (p->family == AF_INET
9241 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9242 || safi == SAFI_EVPN
9243 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
9244 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9245 || safi == SAFI_EVPN)
9246 vty_out(vty, "%-16pI4",
9247 &attr->mp_nexthop_global_in);
9248 else if (wide)
9249 vty_out(vty, "%-41pI4", &attr->nexthop);
9250 else
9251 vty_out(vty, "%-16pI4", &attr->nexthop);
9252 } else if (p->family == AF_INET6
9253 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
9254 char buf[BUFSIZ];
9255
9256 len = vty_out(
9257 vty, "%s",
9258 inet_ntop(AF_INET6,
9259 &attr->mp_nexthop_global, buf,
9260 BUFSIZ));
9261 len = wide ? (41 - len) : (16 - len);
9262 if (len < 1)
9263 vty_out(vty, "\n%*s", 36, " ");
9264 else
9265 vty_out(vty, "%*s", len, " ");
9266 }
9267 if (attr->flag
9268 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
9269 if (wide)
9270 vty_out(vty, "%7u", attr->med);
9271 else
9272 vty_out(vty, "%10u", attr->med);
9273 else if (wide)
9274 vty_out(vty, " ");
9275 else
9276 vty_out(vty, " ");
9277
9278 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
9279 vty_out(vty, "%7u", attr->local_pref);
9280 else
9281 vty_out(vty, " ");
9282
9283 vty_out(vty, "%7u ", attr->weight);
9284
9285 /* Print aspath */
9286 if (attr->aspath)
9287 aspath_print_vty(vty, "%s", attr->aspath, " ");
9288
9289 /* Print origin */
9290 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9291 }
9292 }
9293 if (use_json) {
9294 json_object_boolean_true_add(json_status, "*");
9295 json_object_boolean_true_add(json_status, ">");
9296 json_object_object_add(json_net, "appliedStatusSymbols",
9297 json_status);
9298
9299 prefix2str(p, buff, PREFIX_STRLEN);
9300 json_object_object_add(json_ar, buff, json_net);
9301 } else
9302 vty_out(vty, "\n");
9303 }
9304
9305 void route_vty_out_tag(struct vty *vty, const struct prefix *p,
9306 struct bgp_path_info *path, int display, safi_t safi,
9307 json_object *json)
9308 {
9309 json_object *json_out = NULL;
9310 struct attr *attr;
9311 mpls_label_t label = MPLS_INVALID_LABEL;
9312
9313 if (!path->extra)
9314 return;
9315
9316 if (json)
9317 json_out = json_object_new_object();
9318
9319 /* short status lead text */
9320 route_vty_short_status_out(vty, path, p, json_out);
9321
9322 /* print prefix and mask */
9323 if (json == NULL) {
9324 if (!display)
9325 route_vty_out_route(path->net, p, vty, NULL, false);
9326 else
9327 vty_out(vty, "%*s", 17, " ");
9328 }
9329
9330 /* Print attribute */
9331 attr = path->attr;
9332 if (((p->family == AF_INET)
9333 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
9334 || (safi == SAFI_EVPN && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))
9335 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
9336 char buf[BUFSIZ] = {0};
9337
9338 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9339 || safi == SAFI_EVPN) {
9340 if (json)
9341 json_object_string_add(
9342 json_out, "mpNexthopGlobalIn",
9343 inet_ntop(AF_INET,
9344 &attr->mp_nexthop_global_in,
9345 buf, sizeof(buf)));
9346 else
9347 vty_out(vty, "%-16pI4",
9348 &attr->mp_nexthop_global_in);
9349 } else {
9350 if (json)
9351 json_object_string_add(
9352 json_out, "nexthop",
9353 inet_ntop(AF_INET, &attr->nexthop, buf,
9354 sizeof(buf)));
9355 else
9356 vty_out(vty, "%-16pI4", &attr->nexthop);
9357 }
9358 } else if (((p->family == AF_INET6)
9359 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
9360 || (safi == SAFI_EVPN && BGP_ATTR_NEXTHOP_AFI_IP6(attr))
9361 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
9362 char buf_a[512];
9363
9364 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL) {
9365 if (json)
9366 json_object_string_add(
9367 json_out, "mpNexthopGlobalIn",
9368 inet_ntop(AF_INET6,
9369 &attr->mp_nexthop_global,
9370 buf_a, sizeof(buf_a)));
9371 else
9372 vty_out(vty, "%s",
9373 inet_ntop(AF_INET6,
9374 &attr->mp_nexthop_global,
9375 buf_a, sizeof(buf_a)));
9376 } else if (attr->mp_nexthop_len
9377 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
9378 snprintfrr(buf_a, sizeof(buf_a), "%pI6(%pI6)",
9379 &attr->mp_nexthop_global,
9380 &attr->mp_nexthop_local);
9381 if (json)
9382 json_object_string_add(json_out,
9383 "mpNexthopGlobalLocal",
9384 buf_a);
9385 else
9386 vty_out(vty, "%s", buf_a);
9387 }
9388 }
9389
9390 label = decode_label(&path->extra->label[0]);
9391
9392 if (bgp_is_valid_label(&label)) {
9393 if (json) {
9394 json_object_int_add(json_out, "notag", label);
9395 json_object_array_add(json, json_out);
9396 } else {
9397 vty_out(vty, "notag/%d", label);
9398 vty_out(vty, "\n");
9399 }
9400 }
9401 }
9402
9403 void route_vty_out_overlay(struct vty *vty, const struct prefix *p,
9404 struct bgp_path_info *path, int display,
9405 json_object *json_paths)
9406 {
9407 struct attr *attr;
9408 char buf[BUFSIZ] = {0};
9409 json_object *json_path = NULL;
9410 json_object *json_nexthop = NULL;
9411 json_object *json_overlay = NULL;
9412
9413 if (!path->extra)
9414 return;
9415
9416 if (json_paths) {
9417 json_path = json_object_new_object();
9418 json_overlay = json_object_new_object();
9419 json_nexthop = json_object_new_object();
9420 }
9421
9422 /* short status lead text */
9423 route_vty_short_status_out(vty, path, p, json_path);
9424
9425 /* print prefix and mask */
9426 if (!display)
9427 route_vty_out_route(path->net, p, vty, json_path, false);
9428 else
9429 vty_out(vty, "%*s", 17, " ");
9430
9431 /* Print attribute */
9432 attr = path->attr;
9433 char buf1[BUFSIZ];
9434 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
9435
9436 switch (af) {
9437 case AF_INET:
9438 inet_ntop(af, &attr->mp_nexthop_global_in, buf, BUFSIZ);
9439 if (!json_path) {
9440 vty_out(vty, "%-16s", buf);
9441 } else {
9442 json_object_string_add(json_nexthop, "ip", buf);
9443
9444 json_object_string_add(json_nexthop, "afi", "ipv4");
9445
9446 json_object_object_add(json_path, "nexthop",
9447 json_nexthop);
9448 }
9449 break;
9450 case AF_INET6:
9451 inet_ntop(af, &attr->mp_nexthop_global, buf, BUFSIZ);
9452 inet_ntop(af, &attr->mp_nexthop_local, buf1, BUFSIZ);
9453 if (!json_path) {
9454 vty_out(vty, "%s(%s)", buf, buf1);
9455 } else {
9456 json_object_string_add(json_nexthop, "ipv6Global", buf);
9457
9458 json_object_string_add(json_nexthop, "ipv6LinkLocal",
9459 buf1);
9460
9461 json_object_string_add(json_nexthop, "afi", "ipv6");
9462
9463 json_object_object_add(json_path, "nexthop",
9464 json_nexthop);
9465 }
9466 break;
9467 default:
9468 if (!json_path) {
9469 vty_out(vty, "?");
9470 } else {
9471 json_object_string_add(json_nexthop, "Error",
9472 "Unsupported address-family");
9473 }
9474 }
9475
9476 const struct bgp_route_evpn *eo = bgp_attr_get_evpn_overlay(attr);
9477
9478 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn *)p))
9479 inet_ntop(AF_INET, &eo->gw_ip.ipv4, buf, BUFSIZ);
9480 else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn *)p))
9481 inet_ntop(AF_INET6, &eo->gw_ip.ipv6, buf, BUFSIZ);
9482
9483 if (!json_path)
9484 vty_out(vty, "/%s", buf);
9485 else
9486 json_object_string_add(json_overlay, "gw", buf);
9487
9488 if (attr->ecommunity) {
9489 char *mac = NULL;
9490 struct ecommunity_val *routermac = ecommunity_lookup(
9491 attr->ecommunity, ECOMMUNITY_ENCODE_EVPN,
9492 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC);
9493
9494 if (routermac)
9495 mac = ecom_mac2str((char *)routermac->val);
9496 if (mac) {
9497 if (!json_path) {
9498 vty_out(vty, "/%s", mac);
9499 } else {
9500 json_object_string_add(json_overlay, "rmac",
9501 mac);
9502 }
9503 XFREE(MTYPE_TMP, mac);
9504 }
9505 }
9506
9507 if (!json_path) {
9508 vty_out(vty, "\n");
9509 } else {
9510 json_object_object_add(json_path, "overlay", json_overlay);
9511
9512 json_object_array_add(json_paths, json_path);
9513 }
9514 }
9515
9516 /* dampening route */
9517 static void damp_route_vty_out(struct vty *vty, const struct prefix *p,
9518 struct bgp_path_info *path, int display,
9519 afi_t afi, safi_t safi, bool use_json,
9520 json_object *json)
9521 {
9522 struct attr *attr;
9523 int len;
9524 char timebuf[BGP_UPTIME_LEN];
9525
9526 /* short status lead text */
9527 route_vty_short_status_out(vty, path, p, json);
9528
9529 /* print prefix and mask */
9530 if (!use_json) {
9531 if (!display)
9532 route_vty_out_route(path->net, p, vty, NULL, false);
9533 else
9534 vty_out(vty, "%*s", 17, " ");
9535 }
9536
9537 len = vty_out(vty, "%s", path->peer->host);
9538 len = 17 - len;
9539 if (len < 1) {
9540 if (!use_json)
9541 vty_out(vty, "\n%*s", 34, " ");
9542 } else {
9543 if (use_json)
9544 json_object_int_add(json, "peerHost", len);
9545 else
9546 vty_out(vty, "%*s", len, " ");
9547 }
9548
9549 if (use_json)
9550 bgp_damp_reuse_time_vty(vty, path, timebuf, BGP_UPTIME_LEN, afi,
9551 safi, use_json, json);
9552 else
9553 vty_out(vty, "%s ",
9554 bgp_damp_reuse_time_vty(vty, path, timebuf,
9555 BGP_UPTIME_LEN, afi, safi,
9556 use_json, json));
9557
9558 /* Print attribute */
9559 attr = path->attr;
9560
9561 /* Print aspath */
9562 if (attr->aspath) {
9563 if (use_json)
9564 json_object_string_add(json, "asPath",
9565 attr->aspath->str);
9566 else
9567 aspath_print_vty(vty, "%s", attr->aspath, " ");
9568 }
9569
9570 /* Print origin */
9571 if (use_json)
9572 json_object_string_add(json, "origin",
9573 bgp_origin_str[attr->origin]);
9574 else
9575 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9576
9577 if (!use_json)
9578 vty_out(vty, "\n");
9579 }
9580
9581 /* flap route */
9582 static void flap_route_vty_out(struct vty *vty, const struct prefix *p,
9583 struct bgp_path_info *path, int display,
9584 afi_t afi, safi_t safi, bool use_json,
9585 json_object *json)
9586 {
9587 struct attr *attr;
9588 struct bgp_damp_info *bdi;
9589 char timebuf[BGP_UPTIME_LEN];
9590 int len;
9591
9592 if (!path->extra)
9593 return;
9594
9595 bdi = path->extra->damp_info;
9596
9597 /* short status lead text */
9598 route_vty_short_status_out(vty, path, p, json);
9599
9600 /* print prefix and mask */
9601 if (!use_json) {
9602 if (!display)
9603 route_vty_out_route(path->net, p, vty, NULL, false);
9604 else
9605 vty_out(vty, "%*s", 17, " ");
9606 }
9607
9608 len = vty_out(vty, "%s", path->peer->host);
9609 len = 16 - len;
9610 if (len < 1) {
9611 if (!use_json)
9612 vty_out(vty, "\n%*s", 33, " ");
9613 } else {
9614 if (use_json)
9615 json_object_int_add(json, "peerHost", len);
9616 else
9617 vty_out(vty, "%*s", len, " ");
9618 }
9619
9620 len = vty_out(vty, "%d", bdi->flap);
9621 len = 5 - len;
9622 if (len < 1) {
9623 if (!use_json)
9624 vty_out(vty, " ");
9625 } else {
9626 if (use_json)
9627 json_object_int_add(json, "bdiFlap", len);
9628 else
9629 vty_out(vty, "%*s", len, " ");
9630 }
9631
9632 if (use_json)
9633 peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, use_json,
9634 json);
9635 else
9636 vty_out(vty, "%s ", peer_uptime(bdi->start_time, timebuf,
9637 BGP_UPTIME_LEN, 0, NULL));
9638
9639 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
9640 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
9641 if (use_json)
9642 bgp_damp_reuse_time_vty(vty, path, timebuf,
9643 BGP_UPTIME_LEN, afi, safi,
9644 use_json, json);
9645 else
9646 vty_out(vty, "%s ",
9647 bgp_damp_reuse_time_vty(vty, path, timebuf,
9648 BGP_UPTIME_LEN, afi,
9649 safi, use_json, json));
9650 } else {
9651 if (!use_json)
9652 vty_out(vty, "%*s ", 8, " ");
9653 }
9654
9655 /* Print attribute */
9656 attr = path->attr;
9657
9658 /* Print aspath */
9659 if (attr->aspath) {
9660 if (use_json)
9661 json_object_string_add(json, "asPath",
9662 attr->aspath->str);
9663 else
9664 aspath_print_vty(vty, "%s", attr->aspath, " ");
9665 }
9666
9667 /* Print origin */
9668 if (use_json)
9669 json_object_string_add(json, "origin",
9670 bgp_origin_str[attr->origin]);
9671 else
9672 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9673
9674 if (!use_json)
9675 vty_out(vty, "\n");
9676 }
9677
9678 static void route_vty_out_advertised_to(struct vty *vty, struct peer *peer,
9679 int *first, const char *header,
9680 json_object *json_adv_to)
9681 {
9682 char buf1[INET6_ADDRSTRLEN];
9683 json_object *json_peer = NULL;
9684
9685 if (json_adv_to) {
9686 /* 'advertised-to' is a dictionary of peers we have advertised
9687 * this
9688 * prefix too. The key is the peer's IP or swpX, the value is
9689 * the
9690 * hostname if we know it and "" if not.
9691 */
9692 json_peer = json_object_new_object();
9693
9694 if (peer->hostname)
9695 json_object_string_add(json_peer, "hostname",
9696 peer->hostname);
9697
9698 if (peer->conf_if)
9699 json_object_object_add(json_adv_to, peer->conf_if,
9700 json_peer);
9701 else
9702 json_object_object_add(
9703 json_adv_to,
9704 sockunion2str(&peer->su, buf1, SU_ADDRSTRLEN),
9705 json_peer);
9706 } else {
9707 if (*first) {
9708 vty_out(vty, "%s", header);
9709 *first = 0;
9710 }
9711
9712 if (peer->hostname
9713 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
9714 if (peer->conf_if)
9715 vty_out(vty, " %s(%s)", peer->hostname,
9716 peer->conf_if);
9717 else
9718 vty_out(vty, " %s(%s)", peer->hostname,
9719 sockunion2str(&peer->su, buf1,
9720 SU_ADDRSTRLEN));
9721 } else {
9722 if (peer->conf_if)
9723 vty_out(vty, " %s", peer->conf_if);
9724 else
9725 vty_out(vty, " %s",
9726 sockunion2str(&peer->su, buf1,
9727 SU_ADDRSTRLEN));
9728 }
9729 }
9730 }
9731
9732 static void route_vty_out_tx_ids(struct vty *vty,
9733 struct bgp_addpath_info_data *d)
9734 {
9735 int i;
9736
9737 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
9738 vty_out(vty, "TX-%s %u%s", bgp_addpath_names(i)->human_name,
9739 d->addpath_tx_id[i],
9740 i < BGP_ADDPATH_MAX - 1 ? " " : "\n");
9741 }
9742 }
9743
9744 static void route_vty_out_detail_es_info(struct vty *vty,
9745 struct bgp_path_info *pi,
9746 struct attr *attr,
9747 json_object *json_path)
9748 {
9749 char esi_buf[ESI_STR_LEN];
9750 bool es_local = !!CHECK_FLAG(attr->es_flags, ATTR_ES_IS_LOCAL);
9751 bool peer_router = !!CHECK_FLAG(attr->es_flags,
9752 ATTR_ES_PEER_ROUTER);
9753 bool peer_active = !!CHECK_FLAG(attr->es_flags,
9754 ATTR_ES_PEER_ACTIVE);
9755 bool peer_proxy = !!CHECK_FLAG(attr->es_flags,
9756 ATTR_ES_PEER_PROXY);
9757 esi_to_str(&attr->esi, esi_buf, sizeof(esi_buf));
9758 if (json_path) {
9759 json_object *json_es_info = NULL;
9760
9761 json_object_string_add(
9762 json_path, "esi",
9763 esi_buf);
9764 if (es_local || bgp_evpn_attr_is_sync(attr)) {
9765 json_es_info = json_object_new_object();
9766 if (es_local)
9767 json_object_boolean_true_add(
9768 json_es_info, "localEs");
9769 if (peer_active)
9770 json_object_boolean_true_add(
9771 json_es_info, "peerActive");
9772 if (peer_proxy)
9773 json_object_boolean_true_add(
9774 json_es_info, "peerProxy");
9775 if (peer_router)
9776 json_object_boolean_true_add(
9777 json_es_info, "peerRouter");
9778 if (attr->mm_sync_seqnum)
9779 json_object_int_add(
9780 json_es_info, "peerSeq",
9781 attr->mm_sync_seqnum);
9782 json_object_object_add(
9783 json_path, "es_info",
9784 json_es_info);
9785 }
9786 } else {
9787 if (bgp_evpn_attr_is_sync(attr))
9788 vty_out(vty,
9789 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
9790 esi_buf,
9791 es_local ? "local-es":"",
9792 peer_proxy ? "proxy " : "",
9793 peer_active ? "active ":"",
9794 peer_router ? "router ":"",
9795 attr->mm_sync_seqnum);
9796 else
9797 vty_out(vty, " ESI %s %s\n",
9798 esi_buf,
9799 es_local ? "local-es":"");
9800 }
9801 }
9802
9803 void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
9804 struct bgp_path_info *path, afi_t afi, safi_t safi,
9805 enum rpki_states rpki_curr_state,
9806 json_object *json_paths)
9807 {
9808 char buf[INET6_ADDRSTRLEN];
9809 char buf1[BUFSIZ];
9810 struct attr *attr = path->attr;
9811 int sockunion_vty_out(struct vty *, union sockunion *);
9812 time_t tbuf;
9813 json_object *json_bestpath = NULL;
9814 json_object *json_cluster_list = NULL;
9815 json_object *json_cluster_list_list = NULL;
9816 json_object *json_ext_community = NULL;
9817 json_object *json_last_update = NULL;
9818 json_object *json_pmsi = NULL;
9819 json_object *json_nexthop_global = NULL;
9820 json_object *json_nexthop_ll = NULL;
9821 json_object *json_nexthops = NULL;
9822 json_object *json_path = NULL;
9823 json_object *json_peer = NULL;
9824 json_object *json_string = NULL;
9825 json_object *json_adv_to = NULL;
9826 int first = 0;
9827 struct listnode *node, *nnode;
9828 struct peer *peer;
9829 int addpath_capable;
9830 int has_adj;
9831 unsigned int first_as;
9832 bool nexthop_self =
9833 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
9834 int i;
9835 char *nexthop_hostname =
9836 bgp_nexthop_hostname(path->peer, path->nexthop);
9837
9838 if (json_paths) {
9839 json_path = json_object_new_object();
9840 json_peer = json_object_new_object();
9841 json_nexthop_global = json_object_new_object();
9842 }
9843
9844 if (safi == SAFI_EVPN) {
9845 if (!json_paths)
9846 vty_out(vty, " Route %pRN", bn);
9847 }
9848
9849 if (path->extra) {
9850 char tag_buf[30];
9851
9852 tag_buf[0] = '\0';
9853 if (path->extra && path->extra->num_labels) {
9854 bgp_evpn_label2str(path->extra->label,
9855 path->extra->num_labels, tag_buf,
9856 sizeof(tag_buf));
9857 }
9858 if (safi == SAFI_EVPN) {
9859 if (!json_paths) {
9860 if (tag_buf[0] != '\0')
9861 vty_out(vty, " VNI %s", tag_buf);
9862 } else {
9863 if (tag_buf[0])
9864 json_object_string_add(json_path, "VNI",
9865 tag_buf);
9866 }
9867 }
9868
9869 if (path->extra && path->extra->parent && !json_paths) {
9870 struct bgp_path_info *parent_ri;
9871 struct bgp_dest *dest, *pdest;
9872
9873 parent_ri = (struct bgp_path_info *)path->extra->parent;
9874 dest = parent_ri->net;
9875 if (dest && dest->pdest) {
9876 pdest = dest->pdest;
9877 prefix_rd2str(
9878 (struct prefix_rd *)bgp_dest_get_prefix(
9879 pdest),
9880 buf1, sizeof(buf1));
9881 if (is_pi_family_evpn(parent_ri)) {
9882 vty_out(vty,
9883 " Imported from %s:%pFX, VNI %s",
9884 buf1,
9885 (struct prefix_evpn *)
9886 bgp_dest_get_prefix(
9887 dest),
9888 tag_buf);
9889 if (attr->es_flags & ATTR_ES_L3_NHG)
9890 vty_out(vty, ", L3NHG %s",
9891 (attr->es_flags
9892 & ATTR_ES_L3_NHG_ACTIVE)
9893 ? "active"
9894 : "inactive");
9895 vty_out(vty, "\n");
9896
9897 } else
9898 vty_out(vty,
9899 " Imported from %s:%pFX\n",
9900 buf1,
9901 (struct prefix_evpn *)
9902 bgp_dest_get_prefix(
9903 dest));
9904 }
9905 }
9906 }
9907
9908 if (safi == SAFI_EVPN
9909 && attr->evpn_overlay.type == OVERLAY_INDEX_GATEWAY_IP) {
9910 char gwip_buf[INET6_ADDRSTRLEN];
9911
9912 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn *)&bn->p))
9913 inet_ntop(AF_INET, &attr->evpn_overlay.gw_ip.ipv4,
9914 gwip_buf, sizeof(gwip_buf));
9915 else
9916 inet_ntop(AF_INET6, &attr->evpn_overlay.gw_ip.ipv6,
9917 gwip_buf, sizeof(gwip_buf));
9918
9919 if (json_paths)
9920 json_object_string_add(json_path, "gatewayIP",
9921 gwip_buf);
9922 else
9923 vty_out(vty, " Gateway IP %s", gwip_buf);
9924 }
9925
9926 if (safi == SAFI_EVPN)
9927 vty_out(vty, "\n");
9928
9929 /* Line1 display AS-path, Aggregator */
9930 if (attr->aspath) {
9931 if (json_paths) {
9932 if (!attr->aspath->json)
9933 aspath_str_update(attr->aspath, true);
9934 json_object_lock(attr->aspath->json);
9935 json_object_object_add(json_path, "aspath",
9936 attr->aspath->json);
9937 } else {
9938 if (attr->aspath->segments)
9939 aspath_print_vty(vty, " %s", attr->aspath, "");
9940 else
9941 vty_out(vty, " Local");
9942 }
9943 }
9944
9945 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED)) {
9946 if (json_paths)
9947 json_object_boolean_true_add(json_path, "removed");
9948 else
9949 vty_out(vty, ", (removed)");
9950 }
9951
9952 if (CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
9953 if (json_paths)
9954 json_object_boolean_true_add(json_path, "stale");
9955 else
9956 vty_out(vty, ", (stale)");
9957 }
9958
9959 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
9960 if (json_paths) {
9961 char buf[BUFSIZ] = {0};
9962
9963 json_object_int_add(json_path, "aggregatorAs",
9964 attr->aggregator_as);
9965 json_object_string_add(json_path, "aggregatorId",
9966 inet_ntop(AF_INET,
9967 &attr->aggregator_addr,
9968 buf, sizeof(buf)));
9969 } else {
9970 vty_out(vty, ", (aggregated by %u %pI4)",
9971 attr->aggregator_as, &attr->aggregator_addr);
9972 }
9973 }
9974
9975 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
9976 PEER_FLAG_REFLECTOR_CLIENT)) {
9977 if (json_paths)
9978 json_object_boolean_true_add(json_path,
9979 "rxedFromRrClient");
9980 else
9981 vty_out(vty, ", (Received from a RR-client)");
9982 }
9983
9984 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
9985 PEER_FLAG_RSERVER_CLIENT)) {
9986 if (json_paths)
9987 json_object_boolean_true_add(json_path,
9988 "rxedFromRsClient");
9989 else
9990 vty_out(vty, ", (Received from a RS-client)");
9991 }
9992
9993 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
9994 if (json_paths)
9995 json_object_boolean_true_add(json_path,
9996 "dampeningHistoryEntry");
9997 else
9998 vty_out(vty, ", (history entry)");
9999 } else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)) {
10000 if (json_paths)
10001 json_object_boolean_true_add(json_path,
10002 "dampeningSuppressed");
10003 else
10004 vty_out(vty, ", (suppressed due to dampening)");
10005 }
10006
10007 if (!json_paths)
10008 vty_out(vty, "\n");
10009
10010 /* Line2 display Next-hop, Neighbor, Router-id */
10011 /* Display the nexthop */
10012 const struct prefix *bn_p = bgp_dest_get_prefix(bn);
10013
10014 if ((bn_p->family == AF_INET || bn_p->family == AF_ETHERNET
10015 || bn_p->family == AF_EVPN)
10016 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN
10017 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
10018 char buf[BUFSIZ] = {0};
10019
10020 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
10021 || safi == SAFI_EVPN) {
10022 if (json_paths) {
10023 json_object_string_add(
10024 json_nexthop_global, "ip",
10025 inet_ntop(AF_INET,
10026 &attr->mp_nexthop_global_in,
10027 buf, sizeof(buf)));
10028
10029 if (path->peer->hostname)
10030 json_object_string_add(
10031 json_nexthop_global, "hostname",
10032 path->peer->hostname);
10033 } else {
10034 if (nexthop_hostname)
10035 vty_out(vty, " %pI4(%s)",
10036 &attr->mp_nexthop_global_in,
10037 nexthop_hostname);
10038 else
10039 vty_out(vty, " %pI4",
10040 &attr->mp_nexthop_global_in);
10041 }
10042 } else {
10043 if (json_paths) {
10044 json_object_string_add(
10045 json_nexthop_global, "ip",
10046 inet_ntop(AF_INET, &attr->nexthop, buf,
10047 sizeof(buf)));
10048
10049 if (path->peer->hostname)
10050 json_object_string_add(
10051 json_nexthop_global, "hostname",
10052 path->peer->hostname);
10053 } else {
10054 if (nexthop_hostname)
10055 vty_out(vty, " %pI4(%s)",
10056 &attr->nexthop,
10057 nexthop_hostname);
10058 else
10059 vty_out(vty, " %pI4",
10060 &attr->nexthop);
10061 }
10062 }
10063
10064 if (json_paths)
10065 json_object_string_add(json_nexthop_global, "afi",
10066 "ipv4");
10067 } else {
10068 if (json_paths) {
10069 json_object_string_add(
10070 json_nexthop_global, "ip",
10071 inet_ntop(AF_INET6, &attr->mp_nexthop_global,
10072 buf, INET6_ADDRSTRLEN));
10073
10074 if (path->peer->hostname)
10075 json_object_string_add(json_nexthop_global,
10076 "hostname",
10077 path->peer->hostname);
10078
10079 json_object_string_add(json_nexthop_global, "afi",
10080 "ipv6");
10081 json_object_string_add(json_nexthop_global, "scope",
10082 "global");
10083 } else {
10084 if (nexthop_hostname)
10085 vty_out(vty, " %pI6(%s)",
10086 &attr->mp_nexthop_global,
10087 nexthop_hostname);
10088 else
10089 vty_out(vty, " %pI6",
10090 &attr->mp_nexthop_global);
10091 }
10092 }
10093
10094 /* Display the IGP cost or 'inaccessible' */
10095 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
10096 if (json_paths)
10097 json_object_boolean_false_add(json_nexthop_global,
10098 "accessible");
10099 else
10100 vty_out(vty, " (inaccessible)");
10101 } else {
10102 if (path->extra && path->extra->igpmetric) {
10103 if (json_paths)
10104 json_object_int_add(json_nexthop_global,
10105 "metric",
10106 path->extra->igpmetric);
10107 else
10108 vty_out(vty, " (metric %u)",
10109 path->extra->igpmetric);
10110 }
10111
10112 /* IGP cost is 0, display this only for json */
10113 else {
10114 if (json_paths)
10115 json_object_int_add(json_nexthop_global,
10116 "metric", 0);
10117 }
10118
10119 if (json_paths)
10120 json_object_boolean_true_add(json_nexthop_global,
10121 "accessible");
10122 }
10123
10124 /* Display peer "from" output */
10125 /* This path was originated locally */
10126 if (path->peer == bgp->peer_self) {
10127
10128 if (safi == SAFI_EVPN
10129 || (bn_p->family == AF_INET
10130 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
10131 if (json_paths)
10132 json_object_string_add(json_peer, "peerId",
10133 "0.0.0.0");
10134 else
10135 vty_out(vty, " from 0.0.0.0 ");
10136 } else {
10137 if (json_paths)
10138 json_object_string_add(json_peer, "peerId",
10139 "::");
10140 else
10141 vty_out(vty, " from :: ");
10142 }
10143
10144 if (json_paths) {
10145 char buf[BUFSIZ] = {0};
10146
10147 json_object_string_add(json_peer, "routerId",
10148 inet_ntop(AF_INET,
10149 &bgp->router_id, buf,
10150 sizeof(buf)));
10151 } else {
10152 vty_out(vty, "(%pI4)", &bgp->router_id);
10153 }
10154 }
10155
10156 /* We RXed this path from one of our peers */
10157 else {
10158
10159 if (json_paths) {
10160 json_object_string_add(json_peer, "peerId",
10161 sockunion2str(&path->peer->su,
10162 buf,
10163 SU_ADDRSTRLEN));
10164 json_object_string_add(json_peer, "routerId",
10165 inet_ntop(AF_INET,
10166 &path->peer->remote_id,
10167 buf1, sizeof(buf1)));
10168
10169 if (path->peer->hostname)
10170 json_object_string_add(json_peer, "hostname",
10171 path->peer->hostname);
10172
10173 if (path->peer->domainname)
10174 json_object_string_add(json_peer, "domainname",
10175 path->peer->domainname);
10176
10177 if (path->peer->conf_if)
10178 json_object_string_add(json_peer, "interface",
10179 path->peer->conf_if);
10180 } else {
10181 if (path->peer->conf_if) {
10182 if (path->peer->hostname
10183 && CHECK_FLAG(path->peer->bgp->flags,
10184 BGP_FLAG_SHOW_HOSTNAME))
10185 vty_out(vty, " from %s(%s)",
10186 path->peer->hostname,
10187 path->peer->conf_if);
10188 else
10189 vty_out(vty, " from %s",
10190 path->peer->conf_if);
10191 } else {
10192 if (path->peer->hostname
10193 && CHECK_FLAG(path->peer->bgp->flags,
10194 BGP_FLAG_SHOW_HOSTNAME))
10195 vty_out(vty, " from %s(%s)",
10196 path->peer->hostname,
10197 path->peer->host);
10198 else
10199 vty_out(vty, " from %s",
10200 sockunion2str(&path->peer->su,
10201 buf,
10202 SU_ADDRSTRLEN));
10203 }
10204
10205 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
10206 vty_out(vty, " (%pI4)", &attr->originator_id);
10207 else
10208 vty_out(vty, " (%s)",
10209 inet_ntop(AF_INET,
10210 &path->peer->remote_id, buf1,
10211 sizeof(buf1)));
10212 }
10213 }
10214
10215 /*
10216 * Note when vrfid of nexthop is different from that of prefix
10217 */
10218 if (path->extra && path->extra->bgp_orig) {
10219 vrf_id_t nexthop_vrfid = path->extra->bgp_orig->vrf_id;
10220
10221 if (json_paths) {
10222 const char *vn;
10223
10224 if (path->extra->bgp_orig->inst_type
10225 == BGP_INSTANCE_TYPE_DEFAULT)
10226 vn = VRF_DEFAULT_NAME;
10227 else
10228 vn = path->extra->bgp_orig->name;
10229
10230 json_object_string_add(json_path, "nhVrfName", vn);
10231
10232 if (nexthop_vrfid == VRF_UNKNOWN) {
10233 json_object_int_add(json_path, "nhVrfId", -1);
10234 } else {
10235 json_object_int_add(json_path, "nhVrfId",
10236 (int)nexthop_vrfid);
10237 }
10238 } else {
10239 if (nexthop_vrfid == VRF_UNKNOWN)
10240 vty_out(vty, " vrf ?");
10241 else {
10242 struct vrf *vrf;
10243
10244 vrf = vrf_lookup_by_id(nexthop_vrfid);
10245 vty_out(vty, " vrf %s(%u)",
10246 VRF_LOGNAME(vrf), nexthop_vrfid);
10247 }
10248 }
10249 }
10250
10251 if (nexthop_self) {
10252 if (json_paths) {
10253 json_object_boolean_true_add(json_path,
10254 "announceNexthopSelf");
10255 } else {
10256 vty_out(vty, " announce-nh-self");
10257 }
10258 }
10259
10260 if (!json_paths)
10261 vty_out(vty, "\n");
10262
10263 /* display the link-local nexthop */
10264 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
10265 if (json_paths) {
10266 json_nexthop_ll = json_object_new_object();
10267 json_object_string_add(
10268 json_nexthop_ll, "ip",
10269 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
10270 buf, INET6_ADDRSTRLEN));
10271
10272 if (path->peer->hostname)
10273 json_object_string_add(json_nexthop_ll,
10274 "hostname",
10275 path->peer->hostname);
10276
10277 json_object_string_add(json_nexthop_ll, "afi", "ipv6");
10278 json_object_string_add(json_nexthop_ll, "scope",
10279 "link-local");
10280
10281 json_object_boolean_true_add(json_nexthop_ll,
10282 "accessible");
10283
10284 if (!attr->mp_nexthop_prefer_global)
10285 json_object_boolean_true_add(json_nexthop_ll,
10286 "used");
10287 else
10288 json_object_boolean_true_add(
10289 json_nexthop_global, "used");
10290 } else {
10291 vty_out(vty, " (%s) %s\n",
10292 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
10293 buf, INET6_ADDRSTRLEN),
10294 attr->mp_nexthop_prefer_global
10295 ? "(prefer-global)"
10296 : "(used)");
10297 }
10298 }
10299 /* If we do not have a link-local nexthop then we must flag the
10300 global as "used" */
10301 else {
10302 if (json_paths)
10303 json_object_boolean_true_add(json_nexthop_global,
10304 "used");
10305 }
10306
10307 if (safi == SAFI_EVPN &&
10308 bgp_evpn_is_esi_valid(&attr->esi)) {
10309 route_vty_out_detail_es_info(vty, path, attr, json_path);
10310 }
10311
10312 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
10313 * Int/Ext/Local, Atomic, best */
10314 if (json_paths)
10315 json_object_string_add(json_path, "origin",
10316 bgp_origin_long_str[attr->origin]);
10317 else
10318 vty_out(vty, " Origin %s",
10319 bgp_origin_long_str[attr->origin]);
10320
10321 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
10322 if (json_paths)
10323 json_object_int_add(json_path, "metric", attr->med);
10324 else
10325 vty_out(vty, ", metric %u", attr->med);
10326 }
10327
10328 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
10329 if (json_paths)
10330 json_object_int_add(json_path, "locPrf",
10331 attr->local_pref);
10332 else
10333 vty_out(vty, ", localpref %u", attr->local_pref);
10334 }
10335
10336 if (attr->weight != 0) {
10337 if (json_paths)
10338 json_object_int_add(json_path, "weight", attr->weight);
10339 else
10340 vty_out(vty, ", weight %u", attr->weight);
10341 }
10342
10343 if (attr->tag != 0) {
10344 if (json_paths)
10345 json_object_int_add(json_path, "tag", attr->tag);
10346 else
10347 vty_out(vty, ", tag %" ROUTE_TAG_PRI, attr->tag);
10348 }
10349
10350 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
10351 if (json_paths)
10352 json_object_boolean_false_add(json_path, "valid");
10353 else
10354 vty_out(vty, ", invalid");
10355 } else if (!CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
10356 if (json_paths)
10357 json_object_boolean_true_add(json_path, "valid");
10358 else
10359 vty_out(vty, ", valid");
10360 }
10361
10362 if (json_paths)
10363 json_object_int_add(json_path, "version", bn->version);
10364
10365 if (path->peer != bgp->peer_self) {
10366 if (path->peer->as == path->peer->local_as) {
10367 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
10368 if (json_paths)
10369 json_object_string_add(
10370 json_peer, "type",
10371 "confed-internal");
10372 else
10373 vty_out(vty, ", confed-internal");
10374 } else {
10375 if (json_paths)
10376 json_object_string_add(
10377 json_peer, "type", "internal");
10378 else
10379 vty_out(vty, ", internal");
10380 }
10381 } else {
10382 if (bgp_confederation_peers_check(bgp,
10383 path->peer->as)) {
10384 if (json_paths)
10385 json_object_string_add(
10386 json_peer, "type",
10387 "confed-external");
10388 else
10389 vty_out(vty, ", confed-external");
10390 } else {
10391 if (json_paths)
10392 json_object_string_add(
10393 json_peer, "type", "external");
10394 else
10395 vty_out(vty, ", external");
10396 }
10397 }
10398 } else if (path->sub_type == BGP_ROUTE_AGGREGATE) {
10399 if (json_paths) {
10400 json_object_boolean_true_add(json_path, "aggregated");
10401 json_object_boolean_true_add(json_path, "local");
10402 } else {
10403 vty_out(vty, ", aggregated, local");
10404 }
10405 } else if (path->type != ZEBRA_ROUTE_BGP) {
10406 if (json_paths)
10407 json_object_boolean_true_add(json_path, "sourced");
10408 else
10409 vty_out(vty, ", sourced");
10410 } else {
10411 if (json_paths) {
10412 json_object_boolean_true_add(json_path, "sourced");
10413 json_object_boolean_true_add(json_path, "local");
10414 } else {
10415 vty_out(vty, ", sourced, local");
10416 }
10417 }
10418
10419 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
10420 if (json_paths)
10421 json_object_boolean_true_add(json_path,
10422 "atomicAggregate");
10423 else
10424 vty_out(vty, ", atomic-aggregate");
10425 }
10426
10427 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH)
10428 || (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)
10429 && bgp_path_info_mpath_count(path))) {
10430 if (json_paths)
10431 json_object_boolean_true_add(json_path, "multipath");
10432 else
10433 vty_out(vty, ", multipath");
10434 }
10435
10436 // Mark the bestpath(s)
10437 if (CHECK_FLAG(path->flags, BGP_PATH_DMED_SELECTED)) {
10438 first_as = aspath_get_first_as(attr->aspath);
10439
10440 if (json_paths) {
10441 if (!json_bestpath)
10442 json_bestpath = json_object_new_object();
10443 json_object_int_add(json_bestpath, "bestpathFromAs",
10444 first_as);
10445 } else {
10446 if (first_as)
10447 vty_out(vty, ", bestpath-from-AS %u", first_as);
10448 else
10449 vty_out(vty, ", bestpath-from-AS Local");
10450 }
10451 }
10452
10453 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
10454 if (json_paths) {
10455 if (!json_bestpath)
10456 json_bestpath = json_object_new_object();
10457 json_object_boolean_true_add(json_bestpath, "overall");
10458 json_object_string_add(
10459 json_bestpath, "selectionReason",
10460 bgp_path_selection_reason2str(bn->reason));
10461 } else {
10462 vty_out(vty, ", best");
10463 vty_out(vty, " (%s)",
10464 bgp_path_selection_reason2str(bn->reason));
10465 }
10466 }
10467
10468 if (rpki_curr_state != RPKI_NOT_BEING_USED) {
10469 if (json_paths)
10470 json_object_string_add(
10471 json_path, "rpkiValidationState",
10472 bgp_rpki_validation2str(rpki_curr_state));
10473 else
10474 vty_out(vty, ", rpki validation-state: %s",
10475 bgp_rpki_validation2str(rpki_curr_state));
10476 }
10477
10478 if (json_bestpath)
10479 json_object_object_add(json_path, "bestpath", json_bestpath);
10480
10481 if (!json_paths)
10482 vty_out(vty, "\n");
10483
10484 /* Line 4 display Community */
10485 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES)) {
10486 if (json_paths) {
10487 if (!attr->community->json)
10488 community_str(attr->community, true);
10489 json_object_lock(attr->community->json);
10490 json_object_object_add(json_path, "community",
10491 attr->community->json);
10492 } else {
10493 vty_out(vty, " Community: %s\n",
10494 attr->community->str);
10495 }
10496 }
10497
10498 /* Line 5 display Extended-community */
10499 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
10500 if (json_paths) {
10501 json_ext_community = json_object_new_object();
10502 json_object_string_add(json_ext_community, "string",
10503 attr->ecommunity->str);
10504 json_object_object_add(json_path, "extendedCommunity",
10505 json_ext_community);
10506 } else {
10507 vty_out(vty, " Extended Community: %s\n",
10508 attr->ecommunity->str);
10509 }
10510 }
10511
10512 /* Line 6 display Large community */
10513 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
10514 if (json_paths) {
10515 if (!attr->lcommunity->json)
10516 lcommunity_str(attr->lcommunity, true);
10517 json_object_lock(attr->lcommunity->json);
10518 json_object_object_add(json_path, "largeCommunity",
10519 attr->lcommunity->json);
10520 } else {
10521 vty_out(vty, " Large Community: %s\n",
10522 attr->lcommunity->str);
10523 }
10524 }
10525
10526 /* Line 7 display Originator, Cluster-id */
10527 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
10528 || (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) {
10529 char buf[BUFSIZ] = {0};
10530
10531 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) {
10532 if (json_paths)
10533 json_object_string_add(
10534 json_path, "originatorId",
10535 inet_ntop(AF_INET, &attr->originator_id,
10536 buf, sizeof(buf)));
10537 else
10538 vty_out(vty, " Originator: %pI4",
10539 &attr->originator_id);
10540 }
10541
10542 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) {
10543 struct cluster_list *cluster =
10544 bgp_attr_get_cluster(attr);
10545 int i;
10546
10547 if (json_paths) {
10548 json_cluster_list = json_object_new_object();
10549 json_cluster_list_list =
10550 json_object_new_array();
10551
10552 for (i = 0; i < cluster->length / 4; i++) {
10553 json_string = json_object_new_string(
10554 inet_ntop(AF_INET,
10555 &cluster->list[i],
10556 buf, sizeof(buf)));
10557 json_object_array_add(
10558 json_cluster_list_list,
10559 json_string);
10560 }
10561
10562 /*
10563 * struct cluster_list does not have
10564 * "str" variable like aspath and community
10565 * do. Add this someday if someone asks
10566 * for it.
10567 * json_object_string_add(json_cluster_list,
10568 * "string", cluster->str);
10569 */
10570 json_object_object_add(json_cluster_list,
10571 "list",
10572 json_cluster_list_list);
10573 json_object_object_add(json_path, "clusterList",
10574 json_cluster_list);
10575 } else {
10576 vty_out(vty, ", Cluster list: ");
10577
10578 for (i = 0; i < cluster->length / 4; i++) {
10579 vty_out(vty, "%pI4 ",
10580 &cluster->list[i]);
10581 }
10582 }
10583 }
10584
10585 if (!json_paths)
10586 vty_out(vty, "\n");
10587 }
10588
10589 if (path->extra && path->extra->damp_info)
10590 bgp_damp_info_vty(vty, bgp, path, afi, safi, json_path);
10591
10592 /* Remote Label */
10593 if (path->extra && bgp_is_valid_label(&path->extra->label[0])
10594 && (safi != SAFI_EVPN && !is_route_parent_evpn(path))) {
10595 mpls_label_t label = label_pton(&path->extra->label[0]);
10596
10597 if (json_paths)
10598 json_object_int_add(json_path, "remoteLabel", label);
10599 else
10600 vty_out(vty, " Remote label: %d\n", label);
10601 }
10602
10603 /* Remote SID */
10604 if (path->extra && path->extra->num_sids > 0 && safi != SAFI_EVPN) {
10605 inet_ntop(AF_INET6, &path->extra->sid, buf, sizeof(buf));
10606 if (json_paths)
10607 json_object_string_add(json_path, "remoteSid", buf);
10608 else
10609 vty_out(vty, " Remote SID: %s\n", buf);
10610 }
10611
10612 /* Label Index */
10613 if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
10614 if (json_paths)
10615 json_object_int_add(json_path, "labelIndex",
10616 attr->label_index);
10617 else
10618 vty_out(vty, " Label Index: %d\n",
10619 attr->label_index);
10620 }
10621
10622 /* Line 8 display Addpath IDs */
10623 if (path->addpath_rx_id
10624 || bgp_addpath_info_has_ids(&path->tx_addpath)) {
10625 if (json_paths) {
10626 json_object_int_add(json_path, "addpathRxId",
10627 path->addpath_rx_id);
10628
10629 /* Keep backwards compatibility with the old API
10630 * by putting TX All's ID in the old field
10631 */
10632 json_object_int_add(
10633 json_path, "addpathTxId",
10634 path->tx_addpath
10635 .addpath_tx_id[BGP_ADDPATH_ALL]);
10636
10637 /* ... but create a specific field for each
10638 * strategy
10639 */
10640 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
10641 json_object_int_add(
10642 json_path,
10643 bgp_addpath_names(i)->id_json_name,
10644 path->tx_addpath.addpath_tx_id[i]);
10645 }
10646 } else {
10647 vty_out(vty, " AddPath ID: RX %u, ",
10648 path->addpath_rx_id);
10649
10650 route_vty_out_tx_ids(vty, &path->tx_addpath);
10651 }
10652 }
10653
10654 /* If we used addpath to TX a non-bestpath we need to display
10655 * "Advertised to" on a path-by-path basis
10656 */
10657 if (bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
10658 first = 1;
10659
10660 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
10661 addpath_capable =
10662 bgp_addpath_encode_tx(peer, afi, safi);
10663 has_adj = bgp_adj_out_lookup(
10664 peer, path->net,
10665 bgp_addpath_id_for_peer(peer, afi, safi,
10666 &path->tx_addpath));
10667
10668 if ((addpath_capable && has_adj)
10669 || (!addpath_capable && has_adj
10670 && CHECK_FLAG(path->flags,
10671 BGP_PATH_SELECTED))) {
10672 if (json_path && !json_adv_to)
10673 json_adv_to = json_object_new_object();
10674
10675 route_vty_out_advertised_to(
10676 vty, peer, &first,
10677 " Advertised to:", json_adv_to);
10678 }
10679 }
10680
10681 if (json_path) {
10682 if (json_adv_to) {
10683 json_object_object_add(
10684 json_path, "advertisedTo", json_adv_to);
10685 }
10686 } else {
10687 if (!first) {
10688 vty_out(vty, "\n");
10689 }
10690 }
10691 }
10692
10693 /* Line 9 display Uptime */
10694 tbuf = time(NULL) - (bgp_clock() - path->uptime);
10695 if (json_paths) {
10696 json_last_update = json_object_new_object();
10697 json_object_int_add(json_last_update, "epoch", tbuf);
10698 json_object_string_add(json_last_update, "string",
10699 ctime(&tbuf));
10700 json_object_object_add(json_path, "lastUpdate",
10701 json_last_update);
10702 } else
10703 vty_out(vty, " Last update: %s", ctime(&tbuf));
10704
10705 /* Line 10 display PMSI tunnel attribute, if present */
10706 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
10707 const char *str = lookup_msg(bgp_pmsi_tnltype_str,
10708 bgp_attr_get_pmsi_tnl_type(attr),
10709 PMSI_TNLTYPE_STR_DEFAULT);
10710
10711 if (json_paths) {
10712 json_pmsi = json_object_new_object();
10713 json_object_string_add(json_pmsi, "tunnelType", str);
10714 json_object_int_add(json_pmsi, "label",
10715 label2vni(&attr->label));
10716 json_object_object_add(json_path, "pmsi", json_pmsi);
10717 } else
10718 vty_out(vty, " PMSI Tunnel Type: %s, label: %d\n",
10719 str, label2vni(&attr->label));
10720 }
10721
10722 /* Output some debug about internal state of the dest flags */
10723 if (json_paths) {
10724 if (CHECK_FLAG(bn->flags, BGP_NODE_PROCESS_SCHEDULED))
10725 json_object_boolean_true_add(json_path, "processScheduled");
10726 if (CHECK_FLAG(bn->flags, BGP_NODE_USER_CLEAR))
10727 json_object_boolean_true_add(json_path, "userCleared");
10728 if (CHECK_FLAG(bn->flags, BGP_NODE_LABEL_CHANGED))
10729 json_object_boolean_true_add(json_path, "labelChanged");
10730 if (CHECK_FLAG(bn->flags, BGP_NODE_REGISTERED_FOR_LABEL))
10731 json_object_boolean_true_add(json_path, "registeredForLabel");
10732 if (CHECK_FLAG(bn->flags, BGP_NODE_SELECT_DEFER))
10733 json_object_boolean_true_add(json_path, "selectDefered");
10734 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALLED))
10735 json_object_boolean_true_add(json_path, "fibInstalled");
10736 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALL_PENDING))
10737 json_object_boolean_true_add(json_path, "fibPending");
10738 }
10739
10740 /* We've constructed the json object for this path, add it to the json
10741 * array of paths
10742 */
10743 if (json_paths) {
10744 if (json_nexthop_global || json_nexthop_ll) {
10745 json_nexthops = json_object_new_array();
10746
10747 if (json_nexthop_global)
10748 json_object_array_add(json_nexthops,
10749 json_nexthop_global);
10750
10751 if (json_nexthop_ll)
10752 json_object_array_add(json_nexthops,
10753 json_nexthop_ll);
10754
10755 json_object_object_add(json_path, "nexthops",
10756 json_nexthops);
10757 }
10758
10759 json_object_object_add(json_path, "peer", json_peer);
10760 json_object_array_add(json_paths, json_path);
10761 }
10762 }
10763
10764 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
10765 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
10766 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
10767
10768 static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
10769 const char *prefix_list_str, afi_t afi,
10770 safi_t safi, enum bgp_show_type type);
10771 static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
10772 const char *filter, afi_t afi, safi_t safi,
10773 enum bgp_show_type type);
10774 static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
10775 const char *rmap_str, afi_t afi, safi_t safi,
10776 enum bgp_show_type type);
10777 static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
10778 const char *com, int exact, afi_t afi,
10779 safi_t safi);
10780 static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
10781 const char *prefix, afi_t afi, safi_t safi,
10782 enum bgp_show_type type);
10783 static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
10784 afi_t afi, safi_t safi, enum bgp_show_type type,
10785 bool use_json);
10786 static int bgp_show_community(struct vty *vty, struct bgp *bgp,
10787 const char *comstr, int exact, afi_t afi,
10788 safi_t safi, uint16_t show_flags);
10789
10790 static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
10791 struct bgp_table *table, enum bgp_show_type type,
10792 void *output_arg, char *rd, int is_last,
10793 unsigned long *output_cum, unsigned long *total_cum,
10794 unsigned long *json_header_depth, uint16_t show_flags,
10795 enum rpki_states rpki_target_state)
10796 {
10797 struct bgp_path_info *pi;
10798 struct bgp_dest *dest;
10799 int header = 1;
10800 int display;
10801 unsigned long output_count = 0;
10802 unsigned long total_count = 0;
10803 struct prefix *p;
10804 json_object *json_paths = NULL;
10805 int first = 1;
10806 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
10807 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
10808 bool all = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
10809
10810 if (output_cum && *output_cum != 0)
10811 header = 0;
10812
10813 if (use_json && !*json_header_depth) {
10814 if (all)
10815 *json_header_depth = 1;
10816 else {
10817 vty_out(vty, "{\n");
10818 *json_header_depth = 2;
10819 }
10820
10821 vty_out(vty,
10822 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
10823 ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
10824 " \"localAS\": %u,\n \"routes\": { ",
10825 bgp->vrf_id == VRF_UNKNOWN ? -1 : (int)bgp->vrf_id,
10826 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
10827 ? VRF_DEFAULT_NAME
10828 : bgp->name,
10829 table->version, &bgp->router_id,
10830 bgp->default_local_pref, bgp->as);
10831 if (rd) {
10832 vty_out(vty, " \"routeDistinguishers\" : {");
10833 ++*json_header_depth;
10834 }
10835 }
10836
10837 if (use_json && rd) {
10838 vty_out(vty, " \"%s\" : { ", rd);
10839 }
10840
10841 /* Start processing of routes. */
10842 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
10843 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
10844 enum rpki_states rpki_curr_state = RPKI_NOT_BEING_USED;
10845
10846 pi = bgp_dest_get_bgp_path_info(dest);
10847 if (pi == NULL)
10848 continue;
10849
10850 display = 0;
10851 if (use_json)
10852 json_paths = json_object_new_array();
10853 else
10854 json_paths = NULL;
10855
10856 for (; pi; pi = pi->next) {
10857 total_count++;
10858
10859 if (type == bgp_show_type_prefix_version) {
10860 uint32_t version =
10861 strtoul(output_arg, NULL, 10);
10862 if (dest->version < version)
10863 continue;
10864 }
10865
10866 if (type == bgp_show_type_community_alias) {
10867 char *alias = output_arg;
10868 char **communities;
10869 int num;
10870 bool found = false;
10871
10872 if (pi->attr->community) {
10873 frrstr_split(pi->attr->community->str,
10874 " ", &communities, &num);
10875 for (int i = 0; i < num; i++) {
10876 const char *com2alias =
10877 bgp_community2alias(
10878 communities[i]);
10879 if (strncmp(alias, com2alias,
10880 strlen(com2alias))
10881 == 0) {
10882 found = true;
10883 break;
10884 }
10885 }
10886 }
10887
10888 if (!found && pi->attr->lcommunity) {
10889 frrstr_split(pi->attr->lcommunity->str,
10890 " ", &communities, &num);
10891 for (int i = 0; i < num; i++) {
10892 const char *com2alias =
10893 bgp_community2alias(
10894 communities[i]);
10895 if (strncmp(alias, com2alias,
10896 strlen(com2alias))
10897 == 0) {
10898 found = true;
10899 break;
10900 }
10901 }
10902 }
10903
10904 if (!found)
10905 continue;
10906 }
10907
10908 if (type == bgp_show_type_rpki) {
10909 if (dest_p->family == AF_INET
10910 || dest_p->family == AF_INET6)
10911 rpki_curr_state = hook_call(
10912 bgp_rpki_prefix_status,
10913 pi->peer, pi->attr, dest_p);
10914 if (rpki_target_state != RPKI_NOT_BEING_USED
10915 && rpki_curr_state != rpki_target_state)
10916 continue;
10917 }
10918
10919 if (type == bgp_show_type_flap_statistics
10920 || type == bgp_show_type_flap_neighbor
10921 || type == bgp_show_type_dampend_paths
10922 || type == bgp_show_type_damp_neighbor) {
10923 if (!(pi->extra && pi->extra->damp_info))
10924 continue;
10925 }
10926 if (type == bgp_show_type_regexp) {
10927 regex_t *regex = output_arg;
10928
10929 if (bgp_regexec(regex, pi->attr->aspath)
10930 == REG_NOMATCH)
10931 continue;
10932 }
10933 if (type == bgp_show_type_prefix_list) {
10934 struct prefix_list *plist = output_arg;
10935
10936 if (prefix_list_apply(plist, dest_p)
10937 != PREFIX_PERMIT)
10938 continue;
10939 }
10940 if (type == bgp_show_type_filter_list) {
10941 struct as_list *as_list = output_arg;
10942
10943 if (as_list_apply(as_list, pi->attr->aspath)
10944 != AS_FILTER_PERMIT)
10945 continue;
10946 }
10947 if (type == bgp_show_type_route_map) {
10948 struct route_map *rmap = output_arg;
10949 struct bgp_path_info path;
10950 struct attr dummy_attr;
10951 route_map_result_t ret;
10952
10953 dummy_attr = *pi->attr;
10954
10955 path.peer = pi->peer;
10956 path.attr = &dummy_attr;
10957
10958 ret = route_map_apply(rmap, dest_p, &path);
10959 if (ret == RMAP_DENYMATCH)
10960 continue;
10961 }
10962 if (type == bgp_show_type_neighbor
10963 || type == bgp_show_type_flap_neighbor
10964 || type == bgp_show_type_damp_neighbor) {
10965 union sockunion *su = output_arg;
10966
10967 if (pi->peer == NULL
10968 || pi->peer->su_remote == NULL
10969 || !sockunion_same(pi->peer->su_remote, su))
10970 continue;
10971 }
10972 if (type == bgp_show_type_cidr_only) {
10973 uint32_t destination;
10974
10975 destination = ntohl(dest_p->u.prefix4.s_addr);
10976 if (IN_CLASSC(destination)
10977 && dest_p->prefixlen == 24)
10978 continue;
10979 if (IN_CLASSB(destination)
10980 && dest_p->prefixlen == 16)
10981 continue;
10982 if (IN_CLASSA(destination)
10983 && dest_p->prefixlen == 8)
10984 continue;
10985 }
10986 if (type == bgp_show_type_prefix_longer) {
10987 p = output_arg;
10988 if (!prefix_match(p, dest_p))
10989 continue;
10990 }
10991 if (type == bgp_show_type_community_all) {
10992 if (!pi->attr->community)
10993 continue;
10994 }
10995 if (type == bgp_show_type_community) {
10996 struct community *com = output_arg;
10997
10998 if (!pi->attr->community
10999 || !community_match(pi->attr->community,
11000 com))
11001 continue;
11002 }
11003 if (type == bgp_show_type_community_exact) {
11004 struct community *com = output_arg;
11005
11006 if (!pi->attr->community
11007 || !community_cmp(pi->attr->community, com))
11008 continue;
11009 }
11010 if (type == bgp_show_type_community_list) {
11011 struct community_list *list = output_arg;
11012
11013 if (!community_list_match(pi->attr->community,
11014 list))
11015 continue;
11016 }
11017 if (type == bgp_show_type_community_list_exact) {
11018 struct community_list *list = output_arg;
11019
11020 if (!community_list_exact_match(
11021 pi->attr->community, list))
11022 continue;
11023 }
11024 if (type == bgp_show_type_lcommunity) {
11025 struct lcommunity *lcom = output_arg;
11026
11027 if (!pi->attr->lcommunity
11028 || !lcommunity_match(pi->attr->lcommunity,
11029 lcom))
11030 continue;
11031 }
11032
11033 if (type == bgp_show_type_lcommunity_exact) {
11034 struct lcommunity *lcom = output_arg;
11035
11036 if (!pi->attr->lcommunity
11037 || !lcommunity_cmp(pi->attr->lcommunity,
11038 lcom))
11039 continue;
11040 }
11041 if (type == bgp_show_type_lcommunity_list) {
11042 struct community_list *list = output_arg;
11043
11044 if (!lcommunity_list_match(pi->attr->lcommunity,
11045 list))
11046 continue;
11047 }
11048 if (type
11049 == bgp_show_type_lcommunity_list_exact) {
11050 struct community_list *list = output_arg;
11051
11052 if (!lcommunity_list_exact_match(
11053 pi->attr->lcommunity, list))
11054 continue;
11055 }
11056 if (type == bgp_show_type_lcommunity_all) {
11057 if (!pi->attr->lcommunity)
11058 continue;
11059 }
11060 if (type == bgp_show_type_dampend_paths
11061 || type == bgp_show_type_damp_neighbor) {
11062 if (!CHECK_FLAG(pi->flags, BGP_PATH_DAMPED)
11063 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
11064 continue;
11065 }
11066
11067 if (!use_json && header) {
11068 vty_out(vty,
11069 "BGP table version is %" PRIu64
11070 ", local router ID is %pI4, vrf id ",
11071 table->version, &bgp->router_id);
11072 if (bgp->vrf_id == VRF_UNKNOWN)
11073 vty_out(vty, "%s", VRFID_NONE_STR);
11074 else
11075 vty_out(vty, "%u", bgp->vrf_id);
11076 vty_out(vty, "\n");
11077 vty_out(vty, "Default local pref %u, ",
11078 bgp->default_local_pref);
11079 vty_out(vty, "local AS %u\n", bgp->as);
11080 vty_out(vty, BGP_SHOW_SCODE_HEADER);
11081 vty_out(vty, BGP_SHOW_NCODE_HEADER);
11082 vty_out(vty, BGP_SHOW_OCODE_HEADER);
11083 vty_out(vty, BGP_SHOW_RPKI_HEADER);
11084 if (type == bgp_show_type_dampend_paths
11085 || type == bgp_show_type_damp_neighbor)
11086 vty_out(vty, BGP_SHOW_DAMP_HEADER);
11087 else if (type == bgp_show_type_flap_statistics
11088 || type == bgp_show_type_flap_neighbor)
11089 vty_out(vty, BGP_SHOW_FLAP_HEADER);
11090 else
11091 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
11092 : BGP_SHOW_HEADER));
11093 header = 0;
11094 }
11095 if (rd != NULL && !display && !output_count) {
11096 if (!use_json)
11097 vty_out(vty,
11098 "Route Distinguisher: %s\n",
11099 rd);
11100 }
11101 if (type == bgp_show_type_dampend_paths
11102 || type == bgp_show_type_damp_neighbor)
11103 damp_route_vty_out(vty, dest_p, pi, display,
11104 AFI_IP, safi, use_json,
11105 json_paths);
11106 else if (type == bgp_show_type_flap_statistics
11107 || type == bgp_show_type_flap_neighbor)
11108 flap_route_vty_out(vty, dest_p, pi, display,
11109 AFI_IP, safi, use_json,
11110 json_paths);
11111 else {
11112 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_DETAIL))
11113 route_vty_out_detail(
11114 vty, bgp, dest, pi,
11115 family2afi(dest_p->family),
11116 safi, RPKI_NOT_BEING_USED,
11117 json_paths);
11118 else
11119 route_vty_out(vty, dest_p, pi, display,
11120 safi, json_paths, wide);
11121 }
11122 display++;
11123 }
11124
11125 if (display) {
11126 output_count++;
11127 if (!use_json)
11128 continue;
11129
11130 /* encode prefix */
11131 if (dest_p->family == AF_FLOWSPEC) {
11132 char retstr[BGP_FLOWSPEC_STRING_DISPLAY_MAX];
11133
11134
11135 bgp_fs_nlri_get_string(
11136 (unsigned char *)
11137 dest_p->u.prefix_flowspec.ptr,
11138 dest_p->u.prefix_flowspec.prefixlen,
11139 retstr, NLRI_STRING_FORMAT_MIN, NULL,
11140 family2afi(dest_p->u
11141 .prefix_flowspec.family));
11142 if (first)
11143 vty_out(vty, "\"%s/%d\": ", retstr,
11144 dest_p->u.prefix_flowspec
11145 .prefixlen);
11146 else
11147 vty_out(vty, ",\"%s/%d\": ", retstr,
11148 dest_p->u.prefix_flowspec
11149 .prefixlen);
11150 } else {
11151 if (first)
11152 vty_out(vty, "\"%pFX\": ", dest_p);
11153 else
11154 vty_out(vty, ",\"%pFX\": ", dest_p);
11155 }
11156 vty_out(vty, "%s",
11157 json_object_to_json_string_ext(
11158 json_paths, JSON_C_TO_STRING_PRETTY));
11159 json_object_free(json_paths);
11160 json_paths = NULL;
11161 first = 0;
11162 } else
11163 json_object_free(json_paths);
11164 }
11165
11166 if (output_cum) {
11167 output_count += *output_cum;
11168 *output_cum = output_count;
11169 }
11170 if (total_cum) {
11171 total_count += *total_cum;
11172 *total_cum = total_count;
11173 }
11174 if (use_json) {
11175 if (rd) {
11176 vty_out(vty, " }%s ", (is_last ? "" : ","));
11177 }
11178 if (is_last) {
11179 unsigned long i;
11180 for (i = 0; i < *json_header_depth; ++i)
11181 vty_out(vty, " } ");
11182 if (!all)
11183 vty_out(vty, "\n");
11184 }
11185 } else {
11186 if (is_last) {
11187 /* No route is displayed */
11188 if (output_count == 0) {
11189 if (type == bgp_show_type_normal)
11190 vty_out(vty,
11191 "No BGP prefixes displayed, %ld exist\n",
11192 total_count);
11193 } else
11194 vty_out(vty,
11195 "\nDisplayed %ld routes and %ld total paths\n",
11196 output_count, total_count);
11197 }
11198 }
11199
11200 return CMD_SUCCESS;
11201 }
11202
11203 int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi,
11204 struct bgp_table *table, struct prefix_rd *prd_match,
11205 enum bgp_show_type type, void *output_arg, bool use_json)
11206 {
11207 struct bgp_dest *dest, *next;
11208 unsigned long output_cum = 0;
11209 unsigned long total_cum = 0;
11210 unsigned long json_header_depth = 0;
11211 struct bgp_table *itable;
11212 bool show_msg;
11213 uint16_t show_flags = 0;
11214
11215 show_msg = (!use_json && type == bgp_show_type_normal);
11216
11217 if (use_json)
11218 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11219
11220 for (dest = bgp_table_top(table); dest; dest = next) {
11221 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
11222
11223 next = bgp_route_next(dest);
11224 if (prd_match && memcmp(dest_p->u.val, prd_match->val, 8) != 0)
11225 continue;
11226
11227 itable = bgp_dest_get_bgp_table_info(dest);
11228 if (itable != NULL) {
11229 struct prefix_rd prd;
11230 char rd[RD_ADDRSTRLEN];
11231
11232 memcpy(&prd, dest_p, sizeof(struct prefix_rd));
11233 prefix_rd2str(&prd, rd, sizeof(rd));
11234 bgp_show_table(vty, bgp, safi, itable, type, output_arg,
11235 rd, next == NULL, &output_cum,
11236 &total_cum, &json_header_depth,
11237 show_flags, RPKI_NOT_BEING_USED);
11238 if (next == NULL)
11239 show_msg = false;
11240 }
11241 }
11242 if (show_msg) {
11243 if (output_cum == 0)
11244 vty_out(vty, "No BGP prefixes displayed, %ld exist\n",
11245 total_cum);
11246 else
11247 vty_out(vty,
11248 "\nDisplayed %ld routes and %ld total paths\n",
11249 output_cum, total_cum);
11250 }
11251 return CMD_SUCCESS;
11252 }
11253 static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
11254 enum bgp_show_type type, void *output_arg,
11255 uint16_t show_flags, enum rpki_states rpki_target_state)
11256 {
11257 struct bgp_table *table;
11258 unsigned long json_header_depth = 0;
11259 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11260
11261 if (bgp == NULL) {
11262 bgp = bgp_get_default();
11263 }
11264
11265 if (bgp == NULL) {
11266 if (!use_json)
11267 vty_out(vty, "No BGP process is configured\n");
11268 else
11269 vty_out(vty, "{}\n");
11270 return CMD_WARNING;
11271 }
11272
11273 table = bgp->rib[afi][safi];
11274 /* use MPLS and ENCAP specific shows until they are merged */
11275 if (safi == SAFI_MPLS_VPN) {
11276 return bgp_show_table_rd(vty, bgp, safi, table, NULL, type,
11277 output_arg, use_json);
11278 }
11279
11280 if (safi == SAFI_FLOWSPEC && type == bgp_show_type_detail) {
11281 return bgp_show_table_flowspec(vty, bgp, afi, table, type,
11282 output_arg, use_json,
11283 1, NULL, NULL);
11284 }
11285 /* labeled-unicast routes live in the unicast table */
11286 else if (safi == SAFI_LABELED_UNICAST)
11287 safi = SAFI_UNICAST;
11288
11289 return bgp_show_table(vty, bgp, safi, table, type, output_arg, NULL, 1,
11290 NULL, NULL, &json_header_depth, show_flags,
11291 rpki_target_state);
11292 }
11293
11294 static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi,
11295 safi_t safi, uint16_t show_flags)
11296 {
11297 struct listnode *node, *nnode;
11298 struct bgp *bgp;
11299 int is_first = 1;
11300 bool route_output = false;
11301 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11302
11303 if (use_json)
11304 vty_out(vty, "{\n");
11305
11306 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
11307 route_output = true;
11308 if (use_json) {
11309 if (!is_first)
11310 vty_out(vty, ",\n");
11311 else
11312 is_first = 0;
11313
11314 vty_out(vty, "\"%s\":",
11315 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
11316 ? VRF_DEFAULT_NAME
11317 : bgp->name);
11318 } else {
11319 vty_out(vty, "\nInstance %s:\n",
11320 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
11321 ? VRF_DEFAULT_NAME
11322 : bgp->name);
11323 }
11324 bgp_show(vty, bgp, afi, safi, bgp_show_type_normal, NULL,
11325 show_flags, RPKI_NOT_BEING_USED);
11326 }
11327
11328 if (use_json)
11329 vty_out(vty, "}\n");
11330 else if (!route_output)
11331 vty_out(vty, "%% BGP instance not found\n");
11332 }
11333
11334 /* Header of detailed BGP route information */
11335 void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
11336 struct bgp_dest *dest, struct prefix_rd *prd,
11337 afi_t afi, safi_t safi, json_object *json)
11338 {
11339 struct bgp_path_info *pi;
11340 const struct prefix *p;
11341 struct peer *peer;
11342 struct listnode *node, *nnode;
11343 char buf1[RD_ADDRSTRLEN];
11344 char prefix_str[BUFSIZ];
11345 int count = 0;
11346 int best = 0;
11347 int suppress = 0;
11348 int accept_own = 0;
11349 int route_filter_translated_v4 = 0;
11350 int route_filter_v4 = 0;
11351 int route_filter_translated_v6 = 0;
11352 int route_filter_v6 = 0;
11353 int llgr_stale = 0;
11354 int no_llgr = 0;
11355 int accept_own_nexthop = 0;
11356 int blackhole = 0;
11357 int no_export = 0;
11358 int no_advertise = 0;
11359 int local_as = 0;
11360 int no_peer = 0;
11361 int first = 1;
11362 int has_valid_label = 0;
11363 mpls_label_t label = 0;
11364 json_object *json_adv_to = NULL;
11365
11366 p = bgp_dest_get_prefix(dest);
11367 has_valid_label = bgp_is_valid_label(&dest->local_label);
11368
11369 if (has_valid_label)
11370 label = label_pton(&dest->local_label);
11371
11372 if (safi == SAFI_EVPN) {
11373
11374 if (!json) {
11375 vty_out(vty, "BGP routing table entry for %s%s%pFX\n",
11376 prd ? prefix_rd2str(prd, buf1, sizeof(buf1))
11377 : "",
11378 prd ? ":" : "", (struct prefix_evpn *)p);
11379 } else {
11380 json_object_string_add(json, "rd",
11381 prd ? prefix_rd2str(prd, buf1, sizeof(buf1)) :
11382 "");
11383 bgp_evpn_route2json((struct prefix_evpn *)p, json);
11384 }
11385 } else {
11386 if (!json) {
11387 vty_out(vty,
11388 "BGP routing table entry for %s%s%pFX, version %" PRIu64
11389 "\n",
11390 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
11391 ? prefix_rd2str(prd, buf1,
11392 sizeof(buf1))
11393 : ""),
11394 safi == SAFI_MPLS_VPN ? ":" : "", p,
11395 dest->version);
11396
11397 } else {
11398 json_object_string_add(json, "prefix",
11399 prefix2str(p, prefix_str, sizeof(prefix_str)));
11400 json_object_int_add(json, "version", dest->version);
11401
11402 }
11403 }
11404
11405 if (has_valid_label) {
11406 if (json)
11407 json_object_int_add(json, "localLabel", label);
11408 else
11409 vty_out(vty, "Local label: %d\n", label);
11410 }
11411
11412 if (!json)
11413 if (bgp_labeled_safi(safi) && safi != SAFI_EVPN)
11414 vty_out(vty, "not allocated\n");
11415
11416 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
11417 count++;
11418 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
11419 best = count;
11420 if (bgp_path_suppressed(pi))
11421 suppress = 1;
11422
11423 if (pi->attr->community == NULL)
11424 continue;
11425
11426 no_advertise += community_include(
11427 pi->attr->community, COMMUNITY_NO_ADVERTISE);
11428 no_export += community_include(pi->attr->community,
11429 COMMUNITY_NO_EXPORT);
11430 local_as += community_include(pi->attr->community,
11431 COMMUNITY_LOCAL_AS);
11432 accept_own += community_include(pi->attr->community,
11433 COMMUNITY_ACCEPT_OWN);
11434 route_filter_translated_v4 += community_include(
11435 pi->attr->community,
11436 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4);
11437 route_filter_translated_v6 += community_include(
11438 pi->attr->community,
11439 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6);
11440 route_filter_v4 += community_include(
11441 pi->attr->community, COMMUNITY_ROUTE_FILTER_v4);
11442 route_filter_v6 += community_include(
11443 pi->attr->community, COMMUNITY_ROUTE_FILTER_v6);
11444 llgr_stale += community_include(pi->attr->community,
11445 COMMUNITY_LLGR_STALE);
11446 no_llgr += community_include(pi->attr->community,
11447 COMMUNITY_NO_LLGR);
11448 accept_own_nexthop +=
11449 community_include(pi->attr->community,
11450 COMMUNITY_ACCEPT_OWN_NEXTHOP);
11451 blackhole += community_include(pi->attr->community,
11452 COMMUNITY_BLACKHOLE);
11453 no_peer += community_include(pi->attr->community,
11454 COMMUNITY_NO_PEER);
11455 }
11456 }
11457
11458 if (!json) {
11459 vty_out(vty, "Paths: (%d available", count);
11460 if (best) {
11461 vty_out(vty, ", best #%d", best);
11462 if (safi == SAFI_UNICAST) {
11463 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
11464 vty_out(vty, ", table %s",
11465 VRF_DEFAULT_NAME);
11466 else
11467 vty_out(vty, ", vrf %s",
11468 bgp->name);
11469 }
11470 } else
11471 vty_out(vty, ", no best path");
11472
11473 if (accept_own)
11474 vty_out(vty,
11475 ", accept own local route exported and imported in different VRF");
11476 else if (route_filter_translated_v4)
11477 vty_out(vty,
11478 ", mark translated RTs for VPNv4 route filtering");
11479 else if (route_filter_v4)
11480 vty_out(vty,
11481 ", attach RT as-is for VPNv4 route filtering");
11482 else if (route_filter_translated_v6)
11483 vty_out(vty,
11484 ", mark translated RTs for VPNv6 route filtering");
11485 else if (route_filter_v6)
11486 vty_out(vty,
11487 ", attach RT as-is for VPNv6 route filtering");
11488 else if (llgr_stale)
11489 vty_out(vty,
11490 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
11491 else if (no_llgr)
11492 vty_out(vty,
11493 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
11494 else if (accept_own_nexthop)
11495 vty_out(vty,
11496 ", accept local nexthop");
11497 else if (blackhole)
11498 vty_out(vty, ", inform peer to blackhole prefix");
11499 else if (no_export)
11500 vty_out(vty, ", not advertised to EBGP peer");
11501 else if (no_advertise)
11502 vty_out(vty, ", not advertised to any peer");
11503 else if (local_as)
11504 vty_out(vty, ", not advertised outside local AS");
11505 else if (no_peer)
11506 vty_out(vty,
11507 ", inform EBGP peer not to advertise to their EBGP peers");
11508
11509 if (suppress)
11510 vty_out(vty,
11511 ", Advertisements suppressed by an aggregate.");
11512 vty_out(vty, ")\n");
11513 }
11514
11515 /* If we are not using addpath then we can display Advertised to and
11516 * that will
11517 * show what peers we advertised the bestpath to. If we are using
11518 * addpath
11519 * though then we must display Advertised to on a path-by-path basis. */
11520 if (!bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
11521 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
11522 if (bgp_adj_out_lookup(peer, dest, 0)) {
11523 if (json && !json_adv_to)
11524 json_adv_to = json_object_new_object();
11525
11526 route_vty_out_advertised_to(
11527 vty, peer, &first,
11528 " Advertised to non peer-group peers:\n ",
11529 json_adv_to);
11530 }
11531 }
11532
11533 if (json) {
11534 if (json_adv_to) {
11535 json_object_object_add(json, "advertisedTo",
11536 json_adv_to);
11537 }
11538 } else {
11539 if (first)
11540 vty_out(vty, " Not advertised to any peer");
11541 vty_out(vty, "\n");
11542 }
11543 }
11544 }
11545
11546 static void bgp_show_path_info(struct prefix_rd *pfx_rd,
11547 struct bgp_dest *bgp_node, struct vty *vty,
11548 struct bgp *bgp, afi_t afi, safi_t safi,
11549 json_object *json, enum bgp_path_type pathtype,
11550 int *display, enum rpki_states rpki_target_state)
11551 {
11552 struct bgp_path_info *pi;
11553 int header = 1;
11554 char rdbuf[RD_ADDRSTRLEN];
11555 json_object *json_header = NULL;
11556 json_object *json_paths = NULL;
11557 const struct prefix *p = bgp_dest_get_prefix(bgp_node);
11558
11559 for (pi = bgp_dest_get_bgp_path_info(bgp_node); pi; pi = pi->next) {
11560 enum rpki_states rpki_curr_state = RPKI_NOT_BEING_USED;
11561
11562 if (p->family == AF_INET || p->family == AF_INET6)
11563 rpki_curr_state = hook_call(bgp_rpki_prefix_status,
11564 pi->peer, pi->attr, p);
11565
11566 if (rpki_target_state != RPKI_NOT_BEING_USED
11567 && rpki_curr_state != rpki_target_state)
11568 continue;
11569
11570 if (json && !json_paths) {
11571 /* Instantiate json_paths only if path is valid */
11572 json_paths = json_object_new_array();
11573 if (pfx_rd) {
11574 prefix_rd2str(pfx_rd, rdbuf, sizeof(rdbuf));
11575 json_header = json_object_new_object();
11576 } else
11577 json_header = json;
11578 }
11579
11580 if (header) {
11581 route_vty_out_detail_header(
11582 vty, bgp, bgp_node, pfx_rd,
11583 AFI_IP, safi, json_header);
11584 header = 0;
11585 }
11586 (*display)++;
11587
11588 if (pathtype == BGP_PATH_SHOW_ALL
11589 || (pathtype == BGP_PATH_SHOW_BESTPATH
11590 && CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
11591 || (pathtype == BGP_PATH_SHOW_MULTIPATH
11592 && (CHECK_FLAG(pi->flags, BGP_PATH_MULTIPATH)
11593 || CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))))
11594 route_vty_out_detail(vty, bgp, bgp_node, pi, AFI_IP,
11595 safi, rpki_curr_state, json_paths);
11596 }
11597
11598 if (json && json_paths) {
11599 json_object_object_add(json_header, "paths", json_paths);
11600
11601 if (pfx_rd)
11602 json_object_object_add(json, rdbuf, json_header);
11603 }
11604 }
11605
11606 /* Display specified route of BGP table. */
11607 static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
11608 struct bgp_table *rib, const char *ip_str,
11609 afi_t afi, safi_t safi,
11610 enum rpki_states rpki_target_state,
11611 struct prefix_rd *prd, int prefix_check,
11612 enum bgp_path_type pathtype, bool use_json)
11613 {
11614 int ret;
11615 int display = 0;
11616 struct prefix match;
11617 struct bgp_dest *dest;
11618 struct bgp_dest *rm;
11619 struct bgp_table *table;
11620 json_object *json = NULL;
11621 json_object *json_paths = NULL;
11622
11623 /* Check IP address argument. */
11624 ret = str2prefix(ip_str, &match);
11625 if (!ret) {
11626 vty_out(vty, "address is malformed\n");
11627 return CMD_WARNING;
11628 }
11629
11630 match.family = afi2family(afi);
11631
11632 if (use_json)
11633 json = json_object_new_object();
11634
11635 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP) {
11636 for (dest = bgp_table_top(rib); dest;
11637 dest = bgp_route_next(dest)) {
11638 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
11639
11640 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
11641 continue;
11642 table = bgp_dest_get_bgp_table_info(dest);
11643 if (!table)
11644 continue;
11645
11646 rm = bgp_node_match(table, &match);
11647 if (rm == NULL)
11648 continue;
11649
11650 const struct prefix *rm_p = bgp_dest_get_prefix(rm);
11651 if (prefix_check
11652 && rm_p->prefixlen != match.prefixlen) {
11653 bgp_dest_unlock_node(rm);
11654 continue;
11655 }
11656
11657 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
11658 bgp, afi, safi, json, pathtype,
11659 &display, rpki_target_state);
11660
11661 bgp_dest_unlock_node(rm);
11662 }
11663 } else if (safi == SAFI_EVPN) {
11664 struct bgp_dest *longest_pfx;
11665 bool is_exact_pfxlen_match = false;
11666
11667 for (dest = bgp_table_top(rib); dest;
11668 dest = bgp_route_next(dest)) {
11669 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
11670
11671 if (prd && memcmp(&dest_p->u.val, prd->val, 8) != 0)
11672 continue;
11673 table = bgp_dest_get_bgp_table_info(dest);
11674 if (!table)
11675 continue;
11676
11677 longest_pfx = NULL;
11678 is_exact_pfxlen_match = false;
11679 /*
11680 * Search through all the prefixes for a match. The
11681 * pfx's are enumerated in ascending order of pfxlens.
11682 * So, the last pfx match is the longest match. Set
11683 * is_exact_pfxlen_match when we get exact pfxlen match
11684 */
11685 for (rm = bgp_table_top(table); rm;
11686 rm = bgp_route_next(rm)) {
11687 const struct prefix *rm_p =
11688 bgp_dest_get_prefix(rm);
11689 /*
11690 * Get prefixlen of the ip-prefix within type5
11691 * evpn route
11692 */
11693 if (evpn_type5_prefix_match(rm_p, &match)
11694 && rm->info) {
11695 longest_pfx = rm;
11696 int type5_pfxlen =
11697 bgp_evpn_get_type5_prefixlen(
11698 rm_p);
11699 if (type5_pfxlen == match.prefixlen) {
11700 is_exact_pfxlen_match = true;
11701 bgp_dest_unlock_node(rm);
11702 break;
11703 }
11704 }
11705 }
11706
11707 if (!longest_pfx)
11708 continue;
11709
11710 if (prefix_check && !is_exact_pfxlen_match)
11711 continue;
11712
11713 rm = longest_pfx;
11714 bgp_dest_lock_node(rm);
11715
11716 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
11717 bgp, afi, safi, json, pathtype,
11718 &display, rpki_target_state);
11719
11720 bgp_dest_unlock_node(rm);
11721 }
11722 } else if (safi == SAFI_FLOWSPEC) {
11723 if (use_json)
11724 json_paths = json_object_new_array();
11725
11726 display = bgp_flowspec_display_match_per_ip(afi, rib,
11727 &match, prefix_check,
11728 vty,
11729 use_json,
11730 json_paths);
11731 if (use_json) {
11732 if (display)
11733 json_object_object_add(json, "paths",
11734 json_paths);
11735 else
11736 json_object_free(json_paths);
11737 }
11738 } else {
11739 dest = bgp_node_match(rib, &match);
11740 if (dest != NULL) {
11741 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
11742 if (!prefix_check
11743 || dest_p->prefixlen == match.prefixlen) {
11744 bgp_show_path_info(NULL, dest, vty, bgp, afi,
11745 safi, json, pathtype,
11746 &display, rpki_target_state);
11747 }
11748
11749 bgp_dest_unlock_node(dest);
11750 }
11751 }
11752
11753 if (use_json) {
11754 vty_out(vty, "%s\n", json_object_to_json_string_ext(
11755 json, JSON_C_TO_STRING_PRETTY |
11756 JSON_C_TO_STRING_NOSLASHESCAPE));
11757 json_object_free(json);
11758 } else {
11759 if (!display) {
11760 vty_out(vty, "%% Network not in table\n");
11761 return CMD_WARNING;
11762 }
11763 }
11764
11765 return CMD_SUCCESS;
11766 }
11767
11768 /* Display specified route of Main RIB */
11769 static int bgp_show_route(struct vty *vty, struct bgp *bgp, const char *ip_str,
11770 afi_t afi, safi_t safi, struct prefix_rd *prd,
11771 int prefix_check, enum bgp_path_type pathtype,
11772 enum rpki_states rpki_target_state, bool use_json)
11773 {
11774 if (!bgp) {
11775 bgp = bgp_get_default();
11776 if (!bgp) {
11777 if (!use_json)
11778 vty_out(vty, "No BGP process is configured\n");
11779 else
11780 vty_out(vty, "{}\n");
11781 return CMD_WARNING;
11782 }
11783 }
11784
11785 /* labeled-unicast routes live in the unicast table */
11786 if (safi == SAFI_LABELED_UNICAST)
11787 safi = SAFI_UNICAST;
11788
11789 return bgp_show_route_in_table(vty, bgp, bgp->rib[afi][safi], ip_str,
11790 afi, safi, rpki_target_state, prd,
11791 prefix_check, pathtype, use_json);
11792 }
11793
11794 static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc,
11795 struct cmd_token **argv, bool exact, afi_t afi,
11796 safi_t safi, bool uj)
11797 {
11798 struct lcommunity *lcom;
11799 struct buffer *b;
11800 int i;
11801 char *str;
11802 int first = 0;
11803 uint16_t show_flags = 0;
11804 int ret;
11805
11806 if (uj)
11807 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11808
11809 b = buffer_new(1024);
11810 for (i = 0; i < argc; i++) {
11811 if (first)
11812 buffer_putc(b, ' ');
11813 else {
11814 if (strmatch(argv[i]->text, "AA:BB:CC")) {
11815 first = 1;
11816 buffer_putstr(b, argv[i]->arg);
11817 }
11818 }
11819 }
11820 buffer_putc(b, '\0');
11821
11822 str = buffer_getstr(b);
11823 buffer_free(b);
11824
11825 lcom = lcommunity_str2com(str);
11826 XFREE(MTYPE_TMP, str);
11827 if (!lcom) {
11828 vty_out(vty, "%% Large-community malformed\n");
11829 return CMD_WARNING;
11830 }
11831
11832 ret = bgp_show(vty, bgp, afi, safi,
11833 (exact ? bgp_show_type_lcommunity_exact
11834 : bgp_show_type_lcommunity),
11835 lcom, show_flags, RPKI_NOT_BEING_USED);
11836
11837 lcommunity_free(&lcom);
11838 return ret;
11839 }
11840
11841 static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp,
11842 const char *lcom, bool exact, afi_t afi,
11843 safi_t safi, bool uj)
11844 {
11845 struct community_list *list;
11846 uint16_t show_flags = 0;
11847
11848 if (uj)
11849 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11850
11851
11852 list = community_list_lookup(bgp_clist, lcom, 0,
11853 LARGE_COMMUNITY_LIST_MASTER);
11854 if (list == NULL) {
11855 vty_out(vty, "%% %s is not a valid large-community-list name\n",
11856 lcom);
11857 return CMD_WARNING;
11858 }
11859
11860 return bgp_show(vty, bgp, afi, safi,
11861 (exact ? bgp_show_type_lcommunity_list_exact
11862 : bgp_show_type_lcommunity_list),
11863 list, show_flags, RPKI_NOT_BEING_USED);
11864 }
11865
11866 DEFUN (show_ip_bgp_large_community_list,
11867 show_ip_bgp_large_community_list_cmd,
11868 "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]",
11869 SHOW_STR
11870 IP_STR
11871 BGP_STR
11872 BGP_INSTANCE_HELP_STR
11873 BGP_AFI_HELP_STR
11874 BGP_SAFI_WITH_LABEL_HELP_STR
11875 "Display routes matching the large-community-list\n"
11876 "large-community-list number\n"
11877 "large-community-list name\n"
11878 "Exact match of the large-communities\n"
11879 JSON_STR)
11880 {
11881 afi_t afi = AFI_IP6;
11882 safi_t safi = SAFI_UNICAST;
11883 int idx = 0;
11884 bool exact_match = 0;
11885 struct bgp *bgp = NULL;
11886 bool uj = use_json(argc, argv);
11887
11888 if (uj)
11889 argc--;
11890
11891 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11892 &bgp, uj);
11893 if (!idx)
11894 return CMD_WARNING;
11895
11896 argv_find(argv, argc, "large-community-list", &idx);
11897
11898 const char *clist_number_or_name = argv[++idx]->arg;
11899
11900 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
11901 exact_match = 1;
11902
11903 return bgp_show_lcommunity_list(vty, bgp, clist_number_or_name,
11904 exact_match, afi, safi, uj);
11905 }
11906 DEFUN (show_ip_bgp_large_community,
11907 show_ip_bgp_large_community_cmd,
11908 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] large-community [<AA:BB:CC> [exact-match]] [json]",
11909 SHOW_STR
11910 IP_STR
11911 BGP_STR
11912 BGP_INSTANCE_HELP_STR
11913 BGP_AFI_HELP_STR
11914 BGP_SAFI_WITH_LABEL_HELP_STR
11915 "Display routes matching the large-communities\n"
11916 "List of large-community numbers\n"
11917 "Exact match of the large-communities\n"
11918 JSON_STR)
11919 {
11920 afi_t afi = AFI_IP6;
11921 safi_t safi = SAFI_UNICAST;
11922 int idx = 0;
11923 bool exact_match = 0;
11924 struct bgp *bgp = NULL;
11925 bool uj = use_json(argc, argv);
11926 uint16_t show_flags = 0;
11927
11928 if (uj) {
11929 argc--;
11930 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11931 }
11932
11933 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11934 &bgp, uj);
11935 if (!idx)
11936 return CMD_WARNING;
11937
11938 if (argv_find(argv, argc, "AA:BB:CC", &idx)) {
11939 if (argv_find(argv, argc, "exact-match", &idx))
11940 exact_match = 1;
11941 return bgp_show_lcommunity(vty, bgp, argc, argv,
11942 exact_match, afi, safi, uj);
11943 } else
11944 return bgp_show(vty, bgp, afi, safi,
11945 bgp_show_type_lcommunity_all, NULL, show_flags,
11946 RPKI_NOT_BEING_USED);
11947 }
11948
11949 static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
11950 safi_t safi, struct json_object *json_array);
11951 static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
11952 safi_t safi, struct json_object *json);
11953
11954
11955 DEFUN(show_ip_bgp_statistics_all, show_ip_bgp_statistics_all_cmd,
11956 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
11957 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
11958 "Display number of prefixes for all afi/safi\n" JSON_STR)
11959 {
11960 bool uj = use_json(argc, argv);
11961 struct bgp *bgp = NULL;
11962 safi_t safi = SAFI_UNICAST;
11963 afi_t afi = AFI_IP6;
11964 int idx = 0;
11965 struct json_object *json_all = NULL;
11966 struct json_object *json_afi_safi = NULL;
11967
11968 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11969 &bgp, false);
11970 if (!idx)
11971 return CMD_WARNING;
11972
11973 if (uj)
11974 json_all = json_object_new_object();
11975
11976 FOREACH_AFI_SAFI (afi, safi) {
11977 /*
11978 * So limit output to those afi/safi pairs that
11979 * actually have something interesting in them
11980 */
11981 if (strmatch(get_afi_safi_str(afi, safi, true),
11982 "Unknown")) {
11983 continue;
11984 }
11985 if (uj) {
11986 json_afi_safi = json_object_new_array();
11987 json_object_object_add(
11988 json_all,
11989 get_afi_safi_str(afi, safi, true),
11990 json_afi_safi);
11991 } else {
11992 json_afi_safi = NULL;
11993 }
11994
11995 bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
11996 }
11997
11998 if (uj) {
11999 vty_out(vty, "%s",
12000 json_object_to_json_string_ext(
12001 json_all, JSON_C_TO_STRING_PRETTY));
12002 json_object_free(json_all);
12003 }
12004
12005 return CMD_SUCCESS;
12006 }
12007
12008 /* BGP route print out function without JSON */
12009 DEFUN (show_ip_bgp_l2vpn_evpn_statistics,
12010 show_ip_bgp_l2vpn_evpn_statistics_cmd,
12011 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
12012 SHOW_STR
12013 IP_STR
12014 BGP_STR
12015 BGP_INSTANCE_HELP_STR
12016 L2VPN_HELP_STR
12017 EVPN_HELP_STR
12018 "BGP RIB advertisement statistics\n"
12019 JSON_STR)
12020 {
12021 afi_t afi = AFI_IP6;
12022 safi_t safi = SAFI_UNICAST;
12023 struct bgp *bgp = NULL;
12024 int idx = 0, ret;
12025 bool uj = use_json(argc, argv);
12026 struct json_object *json_afi_safi = NULL, *json = NULL;
12027
12028 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12029 &bgp, false);
12030 if (!idx)
12031 return CMD_WARNING;
12032
12033 if (uj)
12034 json_afi_safi = json_object_new_array();
12035 else
12036 json_afi_safi = NULL;
12037
12038 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
12039
12040 if (uj) {
12041 json = json_object_new_object();
12042 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
12043 json_afi_safi);
12044 vty_out(vty, "%s", json_object_to_json_string_ext(
12045 json, JSON_C_TO_STRING_PRETTY));
12046 json_object_free(json);
12047 }
12048 return ret;
12049 }
12050
12051 /* BGP route print out function without JSON */
12052 DEFUN(show_ip_bgp_afi_safi_statistics, show_ip_bgp_afi_safi_statistics_cmd,
12053 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12054 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12055 "]]\
12056 statistics [json]",
12057 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12058 BGP_SAFI_WITH_LABEL_HELP_STR
12059 "BGP RIB advertisement statistics\n" JSON_STR)
12060 {
12061 afi_t afi = AFI_IP6;
12062 safi_t safi = SAFI_UNICAST;
12063 struct bgp *bgp = NULL;
12064 int idx = 0, ret;
12065 bool uj = use_json(argc, argv);
12066 struct json_object *json_afi_safi = NULL, *json = NULL;
12067
12068 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12069 &bgp, false);
12070 if (!idx)
12071 return CMD_WARNING;
12072
12073 if (uj)
12074 json_afi_safi = json_object_new_array();
12075 else
12076 json_afi_safi = NULL;
12077
12078 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
12079
12080 if (uj) {
12081 json = json_object_new_object();
12082 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
12083 json_afi_safi);
12084 vty_out(vty, "%s",
12085 json_object_to_json_string_ext(
12086 json, JSON_C_TO_STRING_PRETTY));
12087 json_object_free(json);
12088 }
12089 return ret;
12090 }
12091
12092 /* BGP route print out function without JSON */
12093 DEFPY(show_ip_bgp, show_ip_bgp_cmd,
12094 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12095 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12096 "]]\
12097 <[all$all] dampening <parameters>\
12098 |route-map WORD\
12099 |prefix-list WORD\
12100 |filter-list WORD\
12101 |community-list <(1-500)|WORD> [exact-match]\
12102 |A.B.C.D/M longer-prefixes\
12103 |X:X::X:X/M longer-prefixes\
12104 >",
12105 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12106 BGP_SAFI_WITH_LABEL_HELP_STR
12107 "Display the entries for all address families\n"
12108 "Display detailed information about dampening\n"
12109 "Display detail of configured dampening parameters\n"
12110 "Display routes matching the route-map\n"
12111 "A route-map to match on\n"
12112 "Display routes conforming to the prefix-list\n"
12113 "Prefix-list name\n"
12114 "Display routes conforming to the filter-list\n"
12115 "Regular expression access list name\n"
12116 "Display routes matching the community-list\n"
12117 "community-list number\n"
12118 "community-list name\n"
12119 "Exact match of the communities\n"
12120 "IPv4 prefix\n"
12121 "Display route and more specific routes\n"
12122 "IPv6 prefix\n"
12123 "Display route and more specific routes\n")
12124 {
12125 afi_t afi = AFI_IP6;
12126 safi_t safi = SAFI_UNICAST;
12127 int exact_match = 0;
12128 struct bgp *bgp = NULL;
12129 int idx = 0;
12130 uint16_t show_flags = 0;
12131
12132 /* [<ipv4|ipv6> [all]] */
12133 if (all) {
12134 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
12135 if (argv_find(argv, argc, "ipv4", &idx))
12136 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
12137
12138 if (argv_find(argv, argc, "ipv6", &idx))
12139 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
12140 }
12141
12142 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12143 &bgp, false);
12144 if (!idx)
12145 return CMD_WARNING;
12146
12147 if (argv_find(argv, argc, "dampening", &idx)) {
12148 if (argv_find(argv, argc, "parameters", &idx))
12149 return bgp_show_dampening_parameters(vty, afi, safi,
12150 show_flags);
12151 }
12152
12153 if (argv_find(argv, argc, "prefix-list", &idx))
12154 return bgp_show_prefix_list(vty, bgp, argv[idx + 1]->arg, afi,
12155 safi, bgp_show_type_prefix_list);
12156
12157 if (argv_find(argv, argc, "filter-list", &idx))
12158 return bgp_show_filter_list(vty, bgp, argv[idx + 1]->arg, afi,
12159 safi, bgp_show_type_filter_list);
12160
12161 if (argv_find(argv, argc, "route-map", &idx))
12162 return bgp_show_route_map(vty, bgp, argv[idx + 1]->arg, afi,
12163 safi, bgp_show_type_route_map);
12164
12165 if (argv_find(argv, argc, "community-list", &idx)) {
12166 const char *clist_number_or_name = argv[++idx]->arg;
12167 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
12168 exact_match = 1;
12169 return bgp_show_community_list(vty, bgp, clist_number_or_name,
12170 exact_match, afi, safi);
12171 }
12172 /* prefix-longer */
12173 if (argv_find(argv, argc, "A.B.C.D/M", &idx)
12174 || argv_find(argv, argc, "X:X::X:X/M", &idx))
12175 return bgp_show_prefix_longer(vty, bgp, argv[idx]->arg, afi,
12176 safi,
12177 bgp_show_type_prefix_longer);
12178
12179 return CMD_WARNING;
12180 }
12181
12182 /* BGP route print out function with JSON */
12183 DEFPY(show_ip_bgp_json, show_ip_bgp_json_cmd,
12184 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12185 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12186 "]]\
12187 [all$all]\
12188 [cidr-only\
12189 |dampening <flap-statistics|dampened-paths>\
12190 |community [AA:NN|local-AS|no-advertise|no-export\
12191 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
12192 |accept-own|accept-own-nexthop|route-filter-v6\
12193 |route-filter-v4|route-filter-translated-v6\
12194 |route-filter-translated-v4] [exact-match]\
12195 |rpki <invalid|valid|notfound>\
12196 |version (1-4294967295)\
12197 |alias WORD\
12198 ] [json$uj [detail$detail] | wide$wide]",
12199 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12200 BGP_SAFI_WITH_LABEL_HELP_STR
12201 "Display the entries for all address families\n"
12202 "Display only routes with non-natural netmasks\n"
12203 "Display detailed information about dampening\n"
12204 "Display flap statistics of routes\n"
12205 "Display paths suppressed due to dampening\n"
12206 "Display routes matching the communities\n" COMMUNITY_AANN_STR
12207 "Do not send outside local AS (well-known community)\n"
12208 "Do not advertise to any peer (well-known community)\n"
12209 "Do not export to next AS (well-known community)\n"
12210 "Graceful shutdown (well-known community)\n"
12211 "Do not export to any peer (well-known community)\n"
12212 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
12213 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
12214 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
12215 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
12216 "Should accept VPN route with local nexthop (well-known community)\n"
12217 "RT VPNv6 route filtering (well-known community)\n"
12218 "RT VPNv4 route filtering (well-known community)\n"
12219 "RT translated VPNv6 route filtering (well-known community)\n"
12220 "RT translated VPNv4 route filtering (well-known community)\n"
12221 "Exact match of the communities\n"
12222 "RPKI route types\n"
12223 "A valid path as determined by rpki\n"
12224 "A invalid path as determined by rpki\n"
12225 "A path that has no rpki data\n"
12226 "Display prefixes with matching version numbers\n"
12227 "Version number and above\n"
12228 "Display prefixes with matching BGP community alias\n"
12229 "BGP community alias\n" JSON_STR
12230 "Display detailed version of JSON output\n"
12231 "Increase table width for longer prefixes\n")
12232 {
12233 afi_t afi = AFI_IP6;
12234 safi_t safi = SAFI_UNICAST;
12235 enum bgp_show_type sh_type = bgp_show_type_normal;
12236 struct bgp *bgp = NULL;
12237 int idx = 0;
12238 int exact_match = 0;
12239 char *community = NULL;
12240 char *prefix_version = NULL;
12241 char *bgp_community_alias = NULL;
12242 bool first = true;
12243 uint16_t show_flags = 0;
12244 enum rpki_states rpki_target_state = RPKI_NOT_BEING_USED;
12245
12246 if (uj) {
12247 argc--;
12248 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12249 }
12250
12251 if (detail)
12252 SET_FLAG(show_flags, BGP_SHOW_OPT_DETAIL);
12253
12254 /* [<ipv4|ipv6> [all]] */
12255 if (all) {
12256 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
12257
12258 if (argv_find(argv, argc, "ipv4", &idx))
12259 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
12260
12261 if (argv_find(argv, argc, "ipv6", &idx))
12262 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
12263 }
12264
12265 if (wide)
12266 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
12267
12268 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12269 &bgp, uj);
12270 if (!idx)
12271 return CMD_WARNING;
12272
12273 if (argv_find(argv, argc, "cidr-only", &idx))
12274 sh_type = bgp_show_type_cidr_only;
12275
12276 if (argv_find(argv, argc, "dampening", &idx)) {
12277 if (argv_find(argv, argc, "dampened-paths", &idx))
12278 sh_type = bgp_show_type_dampend_paths;
12279 else if (argv_find(argv, argc, "flap-statistics", &idx))
12280 sh_type = bgp_show_type_flap_statistics;
12281 }
12282
12283 if (argv_find(argv, argc, "community", &idx)) {
12284 char *maybecomm = NULL;
12285
12286 if (idx + 1 < argc) {
12287 if (argv[idx + 1]->type == VARIABLE_TKN)
12288 maybecomm = argv[idx + 1]->arg;
12289 else
12290 maybecomm = argv[idx + 1]->text;
12291 }
12292
12293 if (maybecomm && !strmatch(maybecomm, "json")
12294 && !strmatch(maybecomm, "exact-match"))
12295 community = maybecomm;
12296
12297 if (argv_find(argv, argc, "exact-match", &idx))
12298 exact_match = 1;
12299
12300 if (!community)
12301 sh_type = bgp_show_type_community_all;
12302 }
12303
12304 if (argv_find(argv, argc, "rpki", &idx)) {
12305 sh_type = bgp_show_type_rpki;
12306 if (argv_find(argv, argc, "valid", &idx))
12307 rpki_target_state = RPKI_VALID;
12308 else if (argv_find(argv, argc, "invalid", &idx))
12309 rpki_target_state = RPKI_INVALID;
12310 }
12311
12312 /* Display prefixes with matching version numbers */
12313 if (argv_find(argv, argc, "version", &idx)) {
12314 sh_type = bgp_show_type_prefix_version;
12315 prefix_version = argv[idx + 1]->arg;
12316 }
12317
12318 /* Display prefixes with matching BGP community alias */
12319 if (argv_find(argv, argc, "alias", &idx)) {
12320 sh_type = bgp_show_type_community_alias;
12321 bgp_community_alias = argv[idx + 1]->arg;
12322 }
12323
12324 if (!all) {
12325 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
12326 if (community)
12327 return bgp_show_community(vty, bgp, community,
12328 exact_match, afi, safi,
12329 show_flags);
12330 else if (prefix_version)
12331 return bgp_show(vty, bgp, afi, safi, sh_type,
12332 prefix_version, show_flags,
12333 rpki_target_state);
12334 else if (bgp_community_alias)
12335 return bgp_show(vty, bgp, afi, safi, sh_type,
12336 bgp_community_alias, show_flags,
12337 rpki_target_state);
12338 else
12339 return bgp_show(vty, bgp, afi, safi, sh_type, NULL,
12340 show_flags, rpki_target_state);
12341 } else {
12342 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
12343 * AFI_IP6 */
12344
12345 if (uj)
12346 vty_out(vty, "{\n");
12347
12348 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
12349 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
12350 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
12351 ? AFI_IP
12352 : AFI_IP6;
12353 FOREACH_SAFI (safi) {
12354 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
12355 continue;
12356
12357 if (uj) {
12358 if (first)
12359 first = false;
12360 else
12361 vty_out(vty, ",\n");
12362 vty_out(vty, "\"%s\":{\n",
12363 get_afi_safi_str(afi, safi,
12364 true));
12365 } else
12366 vty_out(vty,
12367 "\nFor address family: %s\n",
12368 get_afi_safi_str(afi, safi,
12369 false));
12370
12371 if (community)
12372 bgp_show_community(vty, bgp, community,
12373 exact_match, afi,
12374 safi, show_flags);
12375 else if (prefix_version)
12376 return bgp_show(vty, bgp, afi, safi,
12377 sh_type, prefix_version,
12378 show_flags,
12379 rpki_target_state);
12380 else if (bgp_community_alias)
12381 return bgp_show(
12382 vty, bgp, afi, safi, sh_type,
12383 bgp_community_alias, show_flags,
12384 rpki_target_state);
12385 else
12386 bgp_show(vty, bgp, afi, safi, sh_type,
12387 NULL, show_flags,
12388 rpki_target_state);
12389 if (uj)
12390 vty_out(vty, "}\n");
12391 }
12392 } else {
12393 /* show <ip> bgp all: for each AFI and SAFI*/
12394 FOREACH_AFI_SAFI (afi, safi) {
12395 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
12396 continue;
12397
12398 if (uj) {
12399 if (first)
12400 first = false;
12401 else
12402 vty_out(vty, ",\n");
12403
12404 vty_out(vty, "\"%s\":{\n",
12405 get_afi_safi_str(afi, safi,
12406 true));
12407 } else
12408 vty_out(vty,
12409 "\nFor address family: %s\n",
12410 get_afi_safi_str(afi, safi,
12411 false));
12412
12413 if (community)
12414 bgp_show_community(vty, bgp, community,
12415 exact_match, afi,
12416 safi, show_flags);
12417 else if (prefix_version)
12418 return bgp_show(vty, bgp, afi, safi,
12419 sh_type, prefix_version,
12420 show_flags,
12421 rpki_target_state);
12422 else
12423 bgp_show(vty, bgp, afi, safi, sh_type,
12424 NULL, show_flags,
12425 rpki_target_state);
12426 if (uj)
12427 vty_out(vty, "}\n");
12428 }
12429 }
12430 if (uj)
12431 vty_out(vty, "}\n");
12432 }
12433 return CMD_SUCCESS;
12434 }
12435
12436 DEFUN (show_ip_bgp_route,
12437 show_ip_bgp_route_cmd,
12438 "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>] [rpki <valid|invalid|notfound>] [json]",
12439 SHOW_STR
12440 IP_STR
12441 BGP_STR
12442 BGP_INSTANCE_HELP_STR
12443 BGP_AFI_HELP_STR
12444 BGP_SAFI_WITH_LABEL_HELP_STR
12445 "Network in the BGP routing table to display\n"
12446 "IPv4 prefix\n"
12447 "Network in the BGP routing table to display\n"
12448 "IPv6 prefix\n"
12449 "Display only the bestpath\n"
12450 "Display only multipaths\n"
12451 "Display only paths that match the specified rpki state\n"
12452 "A valid path as determined by rpki\n"
12453 "A invalid path as determined by rpki\n"
12454 "A path that has no rpki data\n"
12455 JSON_STR)
12456 {
12457 int prefix_check = 0;
12458
12459 afi_t afi = AFI_IP6;
12460 safi_t safi = SAFI_UNICAST;
12461 char *prefix = NULL;
12462 struct bgp *bgp = NULL;
12463 enum bgp_path_type path_type;
12464 bool uj = use_json(argc, argv);
12465
12466 int idx = 0;
12467
12468 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12469 &bgp, uj);
12470 if (!idx)
12471 return CMD_WARNING;
12472
12473 if (!bgp) {
12474 vty_out(vty,
12475 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
12476 return CMD_WARNING;
12477 }
12478
12479 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
12480 if (argv_find(argv, argc, "A.B.C.D", &idx)
12481 || argv_find(argv, argc, "X:X::X:X", &idx))
12482 prefix_check = 0;
12483 else if (argv_find(argv, argc, "A.B.C.D/M", &idx)
12484 || argv_find(argv, argc, "X:X::X:X/M", &idx))
12485 prefix_check = 1;
12486
12487 if ((argv[idx]->type == IPV6_TKN || argv[idx]->type == IPV6_PREFIX_TKN)
12488 && afi != AFI_IP6) {
12489 vty_out(vty,
12490 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
12491 return CMD_WARNING;
12492 }
12493 if ((argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV4_PREFIX_TKN)
12494 && afi != AFI_IP) {
12495 vty_out(vty,
12496 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
12497 return CMD_WARNING;
12498 }
12499
12500 prefix = argv[idx]->arg;
12501
12502 /* [<bestpath|multipath>] */
12503 if (argv_find(argv, argc, "bestpath", &idx))
12504 path_type = BGP_PATH_SHOW_BESTPATH;
12505 else if (argv_find(argv, argc, "multipath", &idx))
12506 path_type = BGP_PATH_SHOW_MULTIPATH;
12507 else
12508 path_type = BGP_PATH_SHOW_ALL;
12509
12510 return bgp_show_route(vty, bgp, prefix, afi, safi, NULL, prefix_check,
12511 path_type, RPKI_NOT_BEING_USED, uj);
12512 }
12513
12514 DEFUN (show_ip_bgp_regexp,
12515 show_ip_bgp_regexp_cmd,
12516 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] regexp REGEX [json]",
12517 SHOW_STR
12518 IP_STR
12519 BGP_STR
12520 BGP_INSTANCE_HELP_STR
12521 BGP_AFI_HELP_STR
12522 BGP_SAFI_WITH_LABEL_HELP_STR
12523 "Display routes matching the AS path regular expression\n"
12524 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
12525 JSON_STR)
12526 {
12527 afi_t afi = AFI_IP6;
12528 safi_t safi = SAFI_UNICAST;
12529 struct bgp *bgp = NULL;
12530 bool uj = use_json(argc, argv);
12531 char *regstr = NULL;
12532
12533 int idx = 0;
12534 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12535 &bgp, false);
12536 if (!idx)
12537 return CMD_WARNING;
12538
12539 // get index of regex
12540 if (argv_find(argv, argc, "REGEX", &idx))
12541 regstr = argv[idx]->arg;
12542
12543 assert(regstr);
12544 return bgp_show_regexp(vty, bgp, (const char *)regstr, afi, safi,
12545 bgp_show_type_regexp, uj);
12546 }
12547
12548 DEFPY (show_ip_bgp_instance_all,
12549 show_ip_bgp_instance_all_cmd,
12550 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [json$uj | wide$wide]",
12551 SHOW_STR
12552 IP_STR
12553 BGP_STR
12554 BGP_INSTANCE_ALL_HELP_STR
12555 BGP_AFI_HELP_STR
12556 BGP_SAFI_WITH_LABEL_HELP_STR
12557 JSON_STR
12558 "Increase table width for longer prefixes\n")
12559 {
12560 afi_t afi = AFI_IP;
12561 safi_t safi = SAFI_UNICAST;
12562 struct bgp *bgp = NULL;
12563 int idx = 0;
12564 uint16_t show_flags = 0;
12565
12566 if (uj) {
12567 argc--;
12568 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12569 }
12570
12571 if (wide)
12572 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
12573
12574 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12575 &bgp, uj);
12576 if (!idx)
12577 return CMD_WARNING;
12578
12579 bgp_show_all_instances_routes_vty(vty, afi, safi, show_flags);
12580 return CMD_SUCCESS;
12581 }
12582
12583 static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
12584 afi_t afi, safi_t safi, enum bgp_show_type type,
12585 bool use_json)
12586 {
12587 regex_t *regex;
12588 int rc;
12589 uint16_t show_flags = 0;
12590
12591 if (use_json)
12592 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12593
12594 if (!config_bgp_aspath_validate(regstr)) {
12595 vty_out(vty, "Invalid character in REGEX %s\n",
12596 regstr);
12597 return CMD_WARNING_CONFIG_FAILED;
12598 }
12599
12600 regex = bgp_regcomp(regstr);
12601 if (!regex) {
12602 vty_out(vty, "Can't compile regexp %s\n", regstr);
12603 return CMD_WARNING;
12604 }
12605
12606 rc = bgp_show(vty, bgp, afi, safi, type, regex, show_flags,
12607 RPKI_NOT_BEING_USED);
12608 bgp_regex_free(regex);
12609 return rc;
12610 }
12611
12612 static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
12613 const char *prefix_list_str, afi_t afi,
12614 safi_t safi, enum bgp_show_type type)
12615 {
12616 struct prefix_list *plist;
12617 uint16_t show_flags = 0;
12618
12619 plist = prefix_list_lookup(afi, prefix_list_str);
12620 if (plist == NULL) {
12621 vty_out(vty, "%% %s is not a valid prefix-list name\n",
12622 prefix_list_str);
12623 return CMD_WARNING;
12624 }
12625
12626 return bgp_show(vty, bgp, afi, safi, type, plist, show_flags,
12627 RPKI_NOT_BEING_USED);
12628 }
12629
12630 static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
12631 const char *filter, afi_t afi, safi_t safi,
12632 enum bgp_show_type type)
12633 {
12634 struct as_list *as_list;
12635 uint16_t show_flags = 0;
12636
12637 as_list = as_list_lookup(filter);
12638 if (as_list == NULL) {
12639 vty_out(vty, "%% %s is not a valid AS-path access-list name\n",
12640 filter);
12641 return CMD_WARNING;
12642 }
12643
12644 return bgp_show(vty, bgp, afi, safi, type, as_list, show_flags,
12645 RPKI_NOT_BEING_USED);
12646 }
12647
12648 static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
12649 const char *rmap_str, afi_t afi, safi_t safi,
12650 enum bgp_show_type type)
12651 {
12652 struct route_map *rmap;
12653 uint16_t show_flags = 0;
12654
12655 rmap = route_map_lookup_by_name(rmap_str);
12656 if (!rmap) {
12657 vty_out(vty, "%% %s is not a valid route-map name\n", rmap_str);
12658 return CMD_WARNING;
12659 }
12660
12661 return bgp_show(vty, bgp, afi, safi, type, rmap, show_flags,
12662 RPKI_NOT_BEING_USED);
12663 }
12664
12665 static int bgp_show_community(struct vty *vty, struct bgp *bgp,
12666 const char *comstr, int exact, afi_t afi,
12667 safi_t safi, uint16_t show_flags)
12668 {
12669 struct community *com;
12670 int ret = 0;
12671
12672 com = community_str2com(comstr);
12673 if (!com) {
12674 vty_out(vty, "%% Community malformed: %s\n", comstr);
12675 return CMD_WARNING;
12676 }
12677
12678 ret = bgp_show(vty, bgp, afi, safi,
12679 (exact ? bgp_show_type_community_exact
12680 : bgp_show_type_community),
12681 com, show_flags, RPKI_NOT_BEING_USED);
12682 community_free(&com);
12683
12684 return ret;
12685 }
12686
12687 static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
12688 const char *com, int exact, afi_t afi,
12689 safi_t safi)
12690 {
12691 struct community_list *list;
12692 uint16_t show_flags = 0;
12693
12694 list = community_list_lookup(bgp_clist, com, 0, COMMUNITY_LIST_MASTER);
12695 if (list == NULL) {
12696 vty_out(vty, "%% %s is not a valid community-list name\n", com);
12697 return CMD_WARNING;
12698 }
12699
12700 return bgp_show(vty, bgp, afi, safi,
12701 (exact ? bgp_show_type_community_list_exact
12702 : bgp_show_type_community_list),
12703 list, show_flags, RPKI_NOT_BEING_USED);
12704 }
12705
12706 static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
12707 const char *prefix, afi_t afi, safi_t safi,
12708 enum bgp_show_type type)
12709 {
12710 int ret;
12711 struct prefix *p;
12712 uint16_t show_flags = 0;
12713
12714 p = prefix_new();
12715
12716 ret = str2prefix(prefix, p);
12717 if (!ret) {
12718 vty_out(vty, "%% Malformed Prefix\n");
12719 return CMD_WARNING;
12720 }
12721
12722 ret = bgp_show(vty, bgp, afi, safi, type, p, show_flags,
12723 RPKI_NOT_BEING_USED);
12724 prefix_free(&p);
12725 return ret;
12726 }
12727
12728 enum bgp_stats {
12729 BGP_STATS_MAXBITLEN = 0,
12730 BGP_STATS_RIB,
12731 BGP_STATS_PREFIXES,
12732 BGP_STATS_TOTPLEN,
12733 BGP_STATS_UNAGGREGATEABLE,
12734 BGP_STATS_MAX_AGGREGATEABLE,
12735 BGP_STATS_AGGREGATES,
12736 BGP_STATS_SPACE,
12737 BGP_STATS_ASPATH_COUNT,
12738 BGP_STATS_ASPATH_MAXHOPS,
12739 BGP_STATS_ASPATH_TOTHOPS,
12740 BGP_STATS_ASPATH_MAXSIZE,
12741 BGP_STATS_ASPATH_TOTSIZE,
12742 BGP_STATS_ASN_HIGHEST,
12743 BGP_STATS_MAX,
12744 };
12745
12746 #define TABLE_STATS_IDX_VTY 0
12747 #define TABLE_STATS_IDX_JSON 1
12748
12749 static const char *table_stats_strs[][2] = {
12750 [BGP_STATS_PREFIXES] = {"Total Prefixes", "totalPrefixes"},
12751 [BGP_STATS_TOTPLEN] = {"Average prefix length", "averagePrefixLength"},
12752 [BGP_STATS_RIB] = {"Total Advertisements", "totalAdvertisements"},
12753 [BGP_STATS_UNAGGREGATEABLE] = {"Unaggregateable prefixes",
12754 "unaggregateablePrefixes"},
12755 [BGP_STATS_MAX_AGGREGATEABLE] = {"Maximum aggregateable prefixes",
12756 "maximumAggregateablePrefixes"},
12757 [BGP_STATS_AGGREGATES] = {"BGP Aggregate advertisements",
12758 "bgpAggregateAdvertisements"},
12759 [BGP_STATS_SPACE] = {"Address space advertised",
12760 "addressSpaceAdvertised"},
12761 [BGP_STATS_ASPATH_COUNT] = {"Advertisements with paths",
12762 "advertisementsWithPaths"},
12763 [BGP_STATS_ASPATH_MAXHOPS] = {"Longest AS-Path (hops)",
12764 "longestAsPath"},
12765 [BGP_STATS_ASPATH_MAXSIZE] = {"Largest AS-Path (bytes)",
12766 "largestAsPath"},
12767 [BGP_STATS_ASPATH_TOTHOPS] = {"Average AS-Path length (hops)",
12768 "averageAsPathLengthHops"},
12769 [BGP_STATS_ASPATH_TOTSIZE] = {"Average AS-Path size (bytes)",
12770 "averageAsPathSizeBytes"},
12771 [BGP_STATS_ASN_HIGHEST] = {"Highest public ASN", "highestPublicAsn"},
12772 [BGP_STATS_MAX] = {NULL, NULL}
12773 };
12774
12775 struct bgp_table_stats {
12776 struct bgp_table *table;
12777 unsigned long long counts[BGP_STATS_MAX];
12778 double total_space;
12779 };
12780
12781 static void bgp_table_stats_rn(struct bgp_dest *dest, struct bgp_dest *top,
12782 struct bgp_table_stats *ts, unsigned int space)
12783 {
12784 struct bgp_dest *pdest = bgp_dest_parent_nolock(dest);
12785 struct bgp_path_info *pi;
12786 const struct prefix *rn_p;
12787
12788 if (!bgp_dest_has_bgp_path_info_data(dest))
12789 return;
12790
12791 rn_p = bgp_dest_get_prefix(dest);
12792 ts->counts[BGP_STATS_PREFIXES]++;
12793 ts->counts[BGP_STATS_TOTPLEN] += rn_p->prefixlen;
12794
12795 /* check if the prefix is included by any other announcements */
12796 while (pdest && !bgp_dest_has_bgp_path_info_data(pdest))
12797 pdest = bgp_dest_parent_nolock(pdest);
12798
12799 if (pdest == NULL || pdest == top) {
12800 ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
12801 /* announced address space */
12802 if (space)
12803 ts->total_space += pow(2.0, space - rn_p->prefixlen);
12804 } else if (bgp_dest_has_bgp_path_info_data(pdest))
12805 ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
12806
12807
12808 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
12809 ts->counts[BGP_STATS_RIB]++;
12810
12811 if (CHECK_FLAG(pi->attr->flag,
12812 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)))
12813 ts->counts[BGP_STATS_AGGREGATES]++;
12814
12815 /* as-path stats */
12816 if (pi->attr->aspath) {
12817 unsigned int hops = aspath_count_hops(pi->attr->aspath);
12818 unsigned int size = aspath_size(pi->attr->aspath);
12819 as_t highest = aspath_highest(pi->attr->aspath);
12820
12821 ts->counts[BGP_STATS_ASPATH_COUNT]++;
12822
12823 if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS])
12824 ts->counts[BGP_STATS_ASPATH_MAXHOPS] = hops;
12825
12826 if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE])
12827 ts->counts[BGP_STATS_ASPATH_MAXSIZE] = size;
12828
12829 ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
12830 ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
12831 if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
12832 ts->counts[BGP_STATS_ASN_HIGHEST] = highest;
12833 }
12834 }
12835 }
12836
12837 static int bgp_table_stats_walker(struct thread *t)
12838 {
12839 struct bgp_dest *dest, *ndest;
12840 struct bgp_dest *top;
12841 struct bgp_table_stats *ts = THREAD_ARG(t);
12842 unsigned int space = 0;
12843
12844 if (!(top = bgp_table_top(ts->table)))
12845 return 0;
12846
12847 switch (ts->table->afi) {
12848 case AFI_IP:
12849 space = IPV4_MAX_BITLEN;
12850 break;
12851 case AFI_IP6:
12852 space = IPV6_MAX_BITLEN;
12853 break;
12854 case AFI_L2VPN:
12855 space = EVPN_ROUTE_PREFIXLEN;
12856 break;
12857 default:
12858 return 0;
12859 }
12860
12861 ts->counts[BGP_STATS_MAXBITLEN] = space;
12862
12863 for (dest = top; dest; dest = bgp_route_next(dest)) {
12864 if (ts->table->safi == SAFI_MPLS_VPN
12865 || ts->table->safi == SAFI_ENCAP
12866 || ts->table->safi == SAFI_EVPN) {
12867 struct bgp_table *table;
12868
12869 table = bgp_dest_get_bgp_table_info(dest);
12870 if (!table)
12871 continue;
12872
12873 top = bgp_table_top(table);
12874 for (ndest = bgp_table_top(table); ndest;
12875 ndest = bgp_route_next(ndest))
12876 bgp_table_stats_rn(ndest, top, ts, space);
12877 } else {
12878 bgp_table_stats_rn(dest, top, ts, space);
12879 }
12880 }
12881
12882 return 0;
12883 }
12884
12885 static void bgp_table_stats_all(struct vty *vty, afi_t afi, safi_t safi,
12886 struct json_object *json_array)
12887 {
12888 struct listnode *node, *nnode;
12889 struct bgp *bgp;
12890
12891 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
12892 bgp_table_stats_single(vty, bgp, afi, safi, json_array);
12893 }
12894
12895 static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
12896 safi_t safi, struct json_object *json_array)
12897 {
12898 struct bgp_table_stats ts;
12899 unsigned int i;
12900 int ret = CMD_SUCCESS;
12901 char temp_buf[20];
12902 struct json_object *json = NULL;
12903
12904 if (json_array)
12905 json = json_object_new_object();
12906
12907 if (!bgp->rib[afi][safi]) {
12908 char warning_msg[50];
12909
12910 snprintf(warning_msg, sizeof(warning_msg),
12911 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi,
12912 safi);
12913
12914 if (!json)
12915 vty_out(vty, "%s\n", warning_msg);
12916 else
12917 json_object_string_add(json, "warning", warning_msg);
12918
12919 ret = CMD_WARNING;
12920 goto end_table_stats;
12921 }
12922
12923 if (!json)
12924 vty_out(vty, "BGP %s RIB statistics (%s)\n",
12925 get_afi_safi_str(afi, safi, false), bgp->name_pretty);
12926 else
12927 json_object_string_add(json, "instance", bgp->name_pretty);
12928
12929 /* labeled-unicast routes live in the unicast table */
12930 if (safi == SAFI_LABELED_UNICAST)
12931 safi = SAFI_UNICAST;
12932
12933 memset(&ts, 0, sizeof(ts));
12934 ts.table = bgp->rib[afi][safi];
12935 thread_execute(bm->master, bgp_table_stats_walker, &ts, 0);
12936
12937 for (i = 0; i < BGP_STATS_MAX; i++) {
12938 if ((!json && !table_stats_strs[i][TABLE_STATS_IDX_VTY])
12939 || (json && !table_stats_strs[i][TABLE_STATS_IDX_JSON]))
12940 continue;
12941
12942 switch (i) {
12943 case BGP_STATS_ASPATH_TOTHOPS:
12944 case BGP_STATS_ASPATH_TOTSIZE:
12945 if (!json) {
12946 snprintf(
12947 temp_buf, sizeof(temp_buf), "%12.2f",
12948 ts.counts[i]
12949 ? (float)ts.counts[i]
12950 / (float)ts.counts
12951 [BGP_STATS_ASPATH_COUNT]
12952 : 0);
12953 vty_out(vty, "%-30s: %s",
12954 table_stats_strs[i]
12955 [TABLE_STATS_IDX_VTY],
12956 temp_buf);
12957 } else {
12958 json_object_double_add(
12959 json,
12960 table_stats_strs[i]
12961 [TABLE_STATS_IDX_JSON],
12962 ts.counts[i]
12963 ? (double)ts.counts[i]
12964 / (double)ts.counts
12965 [BGP_STATS_ASPATH_COUNT]
12966 : 0);
12967 }
12968 break;
12969 case BGP_STATS_TOTPLEN:
12970 if (!json) {
12971 snprintf(
12972 temp_buf, sizeof(temp_buf), "%12.2f",
12973 ts.counts[i]
12974 ? (float)ts.counts[i]
12975 / (float)ts.counts
12976 [BGP_STATS_PREFIXES]
12977 : 0);
12978 vty_out(vty, "%-30s: %s",
12979 table_stats_strs[i]
12980 [TABLE_STATS_IDX_VTY],
12981 temp_buf);
12982 } else {
12983 json_object_double_add(
12984 json,
12985 table_stats_strs[i]
12986 [TABLE_STATS_IDX_JSON],
12987 ts.counts[i]
12988 ? (double)ts.counts[i]
12989 / (double)ts.counts
12990 [BGP_STATS_PREFIXES]
12991 : 0);
12992 }
12993 break;
12994 case BGP_STATS_SPACE:
12995 if (!json) {
12996 snprintf(temp_buf, sizeof(temp_buf), "%12g",
12997 ts.total_space);
12998 vty_out(vty, "%-30s: %s\n",
12999 table_stats_strs[i]
13000 [TABLE_STATS_IDX_VTY],
13001 temp_buf);
13002 } else {
13003 json_object_double_add(
13004 json,
13005 table_stats_strs[i]
13006 [TABLE_STATS_IDX_JSON],
13007 (double)ts.total_space);
13008 }
13009 if (afi == AFI_IP6) {
13010 if (!json) {
13011 snprintf(temp_buf, sizeof(temp_buf),
13012 "%12g",
13013 ts.total_space
13014 * pow(2.0, -128 + 32));
13015 vty_out(vty, "%30s: %s\n",
13016 "/32 equivalent %s\n",
13017 temp_buf);
13018 } else {
13019 json_object_double_add(
13020 json, "/32equivalent",
13021 (double)(ts.total_space
13022 * pow(2.0,
13023 -128 + 32)));
13024 }
13025 if (!json) {
13026 snprintf(temp_buf, sizeof(temp_buf),
13027 "%12g",
13028 ts.total_space
13029 * pow(2.0, -128 + 48));
13030 vty_out(vty, "%30s: %s\n",
13031 "/48 equivalent %s\n",
13032 temp_buf);
13033 } else {
13034 json_object_double_add(
13035 json, "/48equivalent",
13036 (double)(ts.total_space
13037 * pow(2.0,
13038 -128 + 48)));
13039 }
13040 } else {
13041 if (!json) {
13042 snprintf(temp_buf, sizeof(temp_buf),
13043 "%12.2f",
13044 ts.total_space * 100.
13045 * pow(2.0, -32));
13046 vty_out(vty, "%30s: %s\n",
13047 "% announced ", temp_buf);
13048 } else {
13049 json_object_double_add(
13050 json, "%announced",
13051 (double)(ts.total_space * 100.
13052 * pow(2.0, -32)));
13053 }
13054 if (!json) {
13055 snprintf(temp_buf, sizeof(temp_buf),
13056 "%12.2f",
13057 ts.total_space
13058 * pow(2.0, -32 + 8));
13059 vty_out(vty, "%30s: %s\n",
13060 "/8 equivalent ", temp_buf);
13061 } else {
13062 json_object_double_add(
13063 json, "/8equivalent",
13064 (double)(ts.total_space
13065 * pow(2.0, -32 + 8)));
13066 }
13067 if (!json) {
13068 snprintf(temp_buf, sizeof(temp_buf),
13069 "%12.2f",
13070 ts.total_space
13071 * pow(2.0, -32 + 24));
13072 vty_out(vty, "%30s: %s\n",
13073 "/24 equivalent ", temp_buf);
13074 } else {
13075 json_object_double_add(
13076 json, "/24equivalent",
13077 (double)(ts.total_space
13078 * pow(2.0, -32 + 24)));
13079 }
13080 }
13081 break;
13082 default:
13083 if (!json) {
13084 snprintf(temp_buf, sizeof(temp_buf), "%12llu",
13085 ts.counts[i]);
13086 vty_out(vty, "%-30s: %s",
13087 table_stats_strs[i]
13088 [TABLE_STATS_IDX_VTY],
13089 temp_buf);
13090 } else {
13091 json_object_int_add(
13092 json,
13093 table_stats_strs[i]
13094 [TABLE_STATS_IDX_JSON],
13095 ts.counts[i]);
13096 }
13097 }
13098 if (!json)
13099 vty_out(vty, "\n");
13100 }
13101 end_table_stats:
13102 if (json)
13103 json_object_array_add(json_array, json);
13104 return ret;
13105 }
13106
13107 static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
13108 safi_t safi, struct json_object *json_array)
13109 {
13110 if (!bgp) {
13111 bgp_table_stats_all(vty, afi, safi, json_array);
13112 return CMD_SUCCESS;
13113 }
13114
13115 return bgp_table_stats_single(vty, bgp, afi, safi, json_array);
13116 }
13117
13118 enum bgp_pcounts {
13119 PCOUNT_ADJ_IN = 0,
13120 PCOUNT_DAMPED,
13121 PCOUNT_REMOVED,
13122 PCOUNT_HISTORY,
13123 PCOUNT_STALE,
13124 PCOUNT_VALID,
13125 PCOUNT_ALL,
13126 PCOUNT_COUNTED,
13127 PCOUNT_BPATH_SELECTED,
13128 PCOUNT_PFCNT, /* the figure we display to users */
13129 PCOUNT_MAX,
13130 };
13131
13132 static const char *const pcount_strs[] = {
13133 [PCOUNT_ADJ_IN] = "Adj-in",
13134 [PCOUNT_DAMPED] = "Damped",
13135 [PCOUNT_REMOVED] = "Removed",
13136 [PCOUNT_HISTORY] = "History",
13137 [PCOUNT_STALE] = "Stale",
13138 [PCOUNT_VALID] = "Valid",
13139 [PCOUNT_ALL] = "All RIB",
13140 [PCOUNT_COUNTED] = "PfxCt counted",
13141 [PCOUNT_BPATH_SELECTED] = "PfxCt Best Selected",
13142 [PCOUNT_PFCNT] = "Useable",
13143 [PCOUNT_MAX] = NULL,
13144 };
13145
13146 struct peer_pcounts {
13147 unsigned int count[PCOUNT_MAX];
13148 const struct peer *peer;
13149 const struct bgp_table *table;
13150 safi_t safi;
13151 };
13152
13153 static void bgp_peer_count_proc(struct bgp_dest *rn, struct peer_pcounts *pc)
13154 {
13155 const struct bgp_adj_in *ain;
13156 const struct bgp_path_info *pi;
13157 const struct peer *peer = pc->peer;
13158
13159 for (ain = rn->adj_in; ain; ain = ain->next)
13160 if (ain->peer == peer)
13161 pc->count[PCOUNT_ADJ_IN]++;
13162
13163 for (pi = bgp_dest_get_bgp_path_info(rn); pi; pi = pi->next) {
13164
13165 if (pi->peer != peer)
13166 continue;
13167
13168 pc->count[PCOUNT_ALL]++;
13169
13170 if (CHECK_FLAG(pi->flags, BGP_PATH_DAMPED))
13171 pc->count[PCOUNT_DAMPED]++;
13172 if (CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
13173 pc->count[PCOUNT_HISTORY]++;
13174 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
13175 pc->count[PCOUNT_REMOVED]++;
13176 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE))
13177 pc->count[PCOUNT_STALE]++;
13178 if (CHECK_FLAG(pi->flags, BGP_PATH_VALID))
13179 pc->count[PCOUNT_VALID]++;
13180 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
13181 pc->count[PCOUNT_PFCNT]++;
13182 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
13183 pc->count[PCOUNT_BPATH_SELECTED]++;
13184
13185 if (CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
13186 pc->count[PCOUNT_COUNTED]++;
13187 if (CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
13188 flog_err(
13189 EC_LIB_DEVELOPMENT,
13190 "Attempting to count but flags say it is unusable");
13191 } else {
13192 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
13193 flog_err(
13194 EC_LIB_DEVELOPMENT,
13195 "Not counted but flags say we should");
13196 }
13197 }
13198 }
13199
13200 static int bgp_peer_count_walker(struct thread *t)
13201 {
13202 struct bgp_dest *rn, *rm;
13203 const struct bgp_table *table;
13204 struct peer_pcounts *pc = THREAD_ARG(t);
13205
13206 if (pc->safi == SAFI_MPLS_VPN || pc->safi == SAFI_ENCAP
13207 || pc->safi == SAFI_EVPN) {
13208 /* Special handling for 2-level routing tables. */
13209 for (rn = bgp_table_top(pc->table); rn;
13210 rn = bgp_route_next(rn)) {
13211 table = bgp_dest_get_bgp_table_info(rn);
13212 if (table != NULL)
13213 for (rm = bgp_table_top(table); rm;
13214 rm = bgp_route_next(rm))
13215 bgp_peer_count_proc(rm, pc);
13216 }
13217 } else
13218 for (rn = bgp_table_top(pc->table); rn; rn = bgp_route_next(rn))
13219 bgp_peer_count_proc(rn, pc);
13220
13221 return 0;
13222 }
13223
13224 static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi,
13225 safi_t safi, bool use_json)
13226 {
13227 struct peer_pcounts pcounts = {.peer = peer};
13228 unsigned int i;
13229 json_object *json = NULL;
13230 json_object *json_loop = NULL;
13231
13232 if (use_json) {
13233 json = json_object_new_object();
13234 json_loop = json_object_new_object();
13235 }
13236
13237 if (!peer || !peer->bgp || !peer->afc[afi][safi]
13238 || !peer->bgp->rib[afi][safi]) {
13239 if (use_json) {
13240 json_object_string_add(
13241 json, "warning",
13242 "No such neighbor or address family");
13243 vty_out(vty, "%s\n", json_object_to_json_string(json));
13244 json_object_free(json);
13245 json_object_free(json_loop);
13246 } else
13247 vty_out(vty, "%% No such neighbor or address family\n");
13248
13249 return CMD_WARNING;
13250 }
13251
13252 memset(&pcounts, 0, sizeof(pcounts));
13253 pcounts.peer = peer;
13254 pcounts.table = peer->bgp->rib[afi][safi];
13255 pcounts.safi = safi;
13256
13257 /* in-place call via thread subsystem so as to record execution time
13258 * stats for the thread-walk (i.e. ensure this can't be blamed on
13259 * on just vty_read()).
13260 */
13261 thread_execute(bm->master, bgp_peer_count_walker, &pcounts, 0);
13262
13263 if (use_json) {
13264 json_object_string_add(json, "prefixCountsFor", peer->host);
13265 json_object_string_add(json, "multiProtocol",
13266 get_afi_safi_str(afi, safi, true));
13267 json_object_int_add(json, "pfxCounter",
13268 peer->pcount[afi][safi]);
13269
13270 for (i = 0; i < PCOUNT_MAX; i++)
13271 json_object_int_add(json_loop, pcount_strs[i],
13272 pcounts.count[i]);
13273
13274 json_object_object_add(json, "ribTableWalkCounters", json_loop);
13275
13276 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
13277 json_object_string_add(json, "pfxctDriftFor",
13278 peer->host);
13279 json_object_string_add(
13280 json, "recommended",
13281 "Please report this bug, with the above command output");
13282 }
13283 vty_out(vty, "%s\n", json_object_to_json_string_ext(
13284 json, JSON_C_TO_STRING_PRETTY));
13285 json_object_free(json);
13286 } else {
13287
13288 if (peer->hostname
13289 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
13290 vty_out(vty, "Prefix counts for %s/%s, %s\n",
13291 peer->hostname, peer->host,
13292 get_afi_safi_str(afi, safi, false));
13293 } else {
13294 vty_out(vty, "Prefix counts for %s, %s\n", peer->host,
13295 get_afi_safi_str(afi, safi, false));
13296 }
13297
13298 vty_out(vty, "PfxCt: %u\n", peer->pcount[afi][safi]);
13299 vty_out(vty, "\nCounts from RIB table walk:\n\n");
13300
13301 for (i = 0; i < PCOUNT_MAX; i++)
13302 vty_out(vty, "%20s: %-10d\n", pcount_strs[i],
13303 pcounts.count[i]);
13304
13305 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
13306 vty_out(vty, "%s [pcount] PfxCt drift!\n", peer->host);
13307 vty_out(vty,
13308 "Please report this bug, with the above command output\n");
13309 }
13310 }
13311
13312 return CMD_SUCCESS;
13313 }
13314
13315 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts,
13316 show_ip_bgp_instance_neighbor_prefix_counts_cmd,
13317 "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]",
13318 SHOW_STR
13319 IP_STR
13320 BGP_STR
13321 BGP_INSTANCE_HELP_STR
13322 BGP_AFI_HELP_STR
13323 BGP_SAFI_HELP_STR
13324 "Detailed information on TCP and BGP neighbor connections\n"
13325 "Neighbor to display information about\n"
13326 "Neighbor to display information about\n"
13327 "Neighbor on BGP configured interface\n"
13328 "Display detailed prefix count information\n"
13329 JSON_STR)
13330 {
13331 afi_t afi = AFI_IP6;
13332 safi_t safi = SAFI_UNICAST;
13333 struct peer *peer;
13334 int idx = 0;
13335 struct bgp *bgp = NULL;
13336 bool uj = use_json(argc, argv);
13337
13338 if (uj)
13339 argc--;
13340
13341 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13342 &bgp, uj);
13343 if (!idx)
13344 return CMD_WARNING;
13345
13346 argv_find(argv, argc, "neighbors", &idx);
13347 peer = peer_lookup_in_view(vty, bgp, argv[idx + 1]->arg, uj);
13348 if (!peer)
13349 return CMD_WARNING;
13350
13351 return bgp_peer_counts(vty, peer, afi, safi, uj);
13352 }
13353
13354 #ifdef KEEP_OLD_VPN_COMMANDS
13355 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts,
13356 show_ip_bgp_vpn_neighbor_prefix_counts_cmd,
13357 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
13358 SHOW_STR
13359 IP_STR
13360 BGP_STR
13361 BGP_VPNVX_HELP_STR
13362 "Display information about all VPNv4 NLRIs\n"
13363 "Detailed information on TCP and BGP neighbor connections\n"
13364 "Neighbor to display information about\n"
13365 "Neighbor to display information about\n"
13366 "Neighbor on BGP configured interface\n"
13367 "Display detailed prefix count information\n"
13368 JSON_STR)
13369 {
13370 int idx_peer = 6;
13371 struct peer *peer;
13372 bool uj = use_json(argc, argv);
13373
13374 peer = peer_lookup_in_view(vty, NULL, argv[idx_peer]->arg, uj);
13375 if (!peer)
13376 return CMD_WARNING;
13377
13378 return bgp_peer_counts(vty, peer, AFI_IP, SAFI_MPLS_VPN, uj);
13379 }
13380
13381 DEFUN (show_ip_bgp_vpn_all_route_prefix,
13382 show_ip_bgp_vpn_all_route_prefix_cmd,
13383 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
13384 SHOW_STR
13385 IP_STR
13386 BGP_STR
13387 BGP_VPNVX_HELP_STR
13388 "Display information about all VPNv4 NLRIs\n"
13389 "Network in the BGP routing table to display\n"
13390 "Network in the BGP routing table to display\n"
13391 JSON_STR)
13392 {
13393 int idx = 0;
13394 char *network = NULL;
13395 struct bgp *bgp = bgp_get_default();
13396 if (!bgp) {
13397 vty_out(vty, "Can't find default instance\n");
13398 return CMD_WARNING;
13399 }
13400
13401 if (argv_find(argv, argc, "A.B.C.D", &idx))
13402 network = argv[idx]->arg;
13403 else if (argv_find(argv, argc, "A.B.C.D/M", &idx))
13404 network = argv[idx]->arg;
13405 else {
13406 vty_out(vty, "Unable to figure out Network\n");
13407 return CMD_WARNING;
13408 }
13409
13410 return bgp_show_route(vty, bgp, network, AFI_IP, SAFI_MPLS_VPN, NULL, 0,
13411 BGP_PATH_SHOW_ALL, RPKI_NOT_BEING_USED,
13412 use_json(argc, argv));
13413 }
13414 #endif /* KEEP_OLD_VPN_COMMANDS */
13415
13416 DEFUN (show_bgp_l2vpn_evpn_route_prefix,
13417 show_bgp_l2vpn_evpn_route_prefix_cmd,
13418 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
13419 SHOW_STR
13420 BGP_STR
13421 L2VPN_HELP_STR
13422 EVPN_HELP_STR
13423 "Network in the BGP routing table to display\n"
13424 "Network in the BGP routing table to display\n"
13425 "Network in the BGP routing table to display\n"
13426 "Network in the BGP routing table to display\n"
13427 JSON_STR)
13428 {
13429 int idx = 0;
13430 char *network = NULL;
13431 int prefix_check = 0;
13432
13433 if (argv_find(argv, argc, "A.B.C.D", &idx) ||
13434 argv_find(argv, argc, "X:X::X:X", &idx))
13435 network = argv[idx]->arg;
13436 else if (argv_find(argv, argc, "A.B.C.D/M", &idx) ||
13437 argv_find(argv, argc, "X:X::X:X/M", &idx)) {
13438 network = argv[idx]->arg;
13439 prefix_check = 1;
13440 } else {
13441 vty_out(vty, "Unable to figure out Network\n");
13442 return CMD_WARNING;
13443 }
13444 return bgp_show_route(vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL,
13445 prefix_check, BGP_PATH_SHOW_ALL,
13446 RPKI_NOT_BEING_USED, use_json(argc, argv));
13447 }
13448
13449 static void show_adj_route_header(struct vty *vty, struct bgp *bgp,
13450 struct bgp_table *table, int *header1,
13451 int *header2, json_object *json,
13452 json_object *json_scode,
13453 json_object *json_ocode, bool wide)
13454 {
13455 uint64_t version = table ? table->version : 0;
13456 char buf[BUFSIZ] = {0};
13457
13458 if (*header1) {
13459 if (json) {
13460 json_object_int_add(json, "bgpTableVersion", version);
13461 json_object_string_add(json, "bgpLocalRouterId",
13462 inet_ntop(AF_INET,
13463 &bgp->router_id, buf,
13464 sizeof(buf)));
13465 json_object_int_add(json, "defaultLocPrf",
13466 bgp->default_local_pref);
13467 json_object_int_add(json, "localAS", bgp->as);
13468 json_object_object_add(json, "bgpStatusCodes",
13469 json_scode);
13470 json_object_object_add(json, "bgpOriginCodes",
13471 json_ocode);
13472 } else {
13473 vty_out(vty,
13474 "BGP table version is %" PRIu64
13475 ", local router ID is %pI4, vrf id ",
13476 version, &bgp->router_id);
13477 if (bgp->vrf_id == VRF_UNKNOWN)
13478 vty_out(vty, "%s", VRFID_NONE_STR);
13479 else
13480 vty_out(vty, "%u", bgp->vrf_id);
13481 vty_out(vty, "\n");
13482 vty_out(vty, "Default local pref %u, ",
13483 bgp->default_local_pref);
13484 vty_out(vty, "local AS %u\n", bgp->as);
13485 vty_out(vty, BGP_SHOW_SCODE_HEADER);
13486 vty_out(vty, BGP_SHOW_NCODE_HEADER);
13487 vty_out(vty, BGP_SHOW_OCODE_HEADER);
13488 vty_out(vty, BGP_SHOW_RPKI_HEADER);
13489 }
13490 *header1 = 0;
13491 }
13492 if (*header2) {
13493 if (!json)
13494 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
13495 : BGP_SHOW_HEADER));
13496 *header2 = 0;
13497 }
13498 }
13499
13500 static void
13501 show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
13502 afi_t afi, safi_t safi, enum bgp_show_adj_route_type type,
13503 const char *rmap_name, json_object *json, json_object *json_ar,
13504 json_object *json_scode, json_object *json_ocode,
13505 uint16_t show_flags, int *header1, int *header2, char *rd_str,
13506 unsigned long *output_count, unsigned long *filtered_count)
13507 {
13508 struct bgp_adj_in *ain;
13509 struct bgp_adj_out *adj;
13510 struct bgp_dest *dest;
13511 struct bgp *bgp;
13512 struct attr attr;
13513 int ret;
13514 struct update_subgroup *subgrp;
13515 struct peer_af *paf;
13516 bool route_filtered;
13517 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13518 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
13519 bool show_rd = ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
13520 || (safi == SAFI_EVPN))
13521 ? true
13522 : false;
13523
13524 bgp = peer->bgp;
13525
13526 if (!bgp) {
13527 if (use_json) {
13528 json_object_string_add(json, "alert", "no BGP");
13529 vty_out(vty, "%s\n", json_object_to_json_string(json));
13530 json_object_free(json);
13531 } else
13532 vty_out(vty, "%% No bgp\n");
13533 return;
13534 }
13535
13536 subgrp = peer_subgroup(peer, afi, safi);
13537
13538 if (type == bgp_show_adj_route_advertised && subgrp
13539 && CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) {
13540 char buf[BUFSIZ] = {0};
13541
13542 if (use_json) {
13543 json_object_int_add(json, "bgpTableVersion",
13544 table->version);
13545 json_object_string_add(json, "bgpLocalRouterId",
13546 inet_ntop(AF_INET,
13547 &bgp->router_id, buf,
13548 sizeof(buf)));
13549 json_object_int_add(json, "defaultLocPrf",
13550 bgp->default_local_pref);
13551 json_object_int_add(json, "localAS", bgp->as);
13552 json_object_object_add(json, "bgpStatusCodes",
13553 json_scode);
13554 json_object_object_add(json, "bgpOriginCodes",
13555 json_ocode);
13556 json_object_string_add(
13557 json, "bgpOriginatingDefaultNetwork",
13558 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
13559 } else {
13560 vty_out(vty,
13561 "BGP table version is %" PRIu64
13562 ", local router ID is %pI4, vrf id ",
13563 table->version, &bgp->router_id);
13564 if (bgp->vrf_id == VRF_UNKNOWN)
13565 vty_out(vty, "%s", VRFID_NONE_STR);
13566 else
13567 vty_out(vty, "%u", bgp->vrf_id);
13568 vty_out(vty, "\n");
13569 vty_out(vty, "Default local pref %u, ",
13570 bgp->default_local_pref);
13571 vty_out(vty, "local AS %u\n", bgp->as);
13572 vty_out(vty, BGP_SHOW_SCODE_HEADER);
13573 vty_out(vty, BGP_SHOW_NCODE_HEADER);
13574 vty_out(vty, BGP_SHOW_OCODE_HEADER);
13575 vty_out(vty, BGP_SHOW_RPKI_HEADER);
13576
13577 vty_out(vty, "Originating default network %s\n\n",
13578 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
13579 }
13580 *header1 = 0;
13581 }
13582
13583 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
13584 if (type == bgp_show_adj_route_received
13585 || type == bgp_show_adj_route_filtered) {
13586 for (ain = dest->adj_in; ain; ain = ain->next) {
13587 if (ain->peer != peer)
13588 continue;
13589
13590 show_adj_route_header(vty, bgp, table, header1,
13591 header2, json, json_scode,
13592 json_ocode, wide);
13593
13594 if ((safi == SAFI_MPLS_VPN)
13595 || (safi == SAFI_ENCAP)
13596 || (safi == SAFI_EVPN)) {
13597 if (use_json)
13598 json_object_string_add(
13599 json_ar, "rd", rd_str);
13600 else if (show_rd && rd_str) {
13601 vty_out(vty,
13602 "Route Distinguisher: %s\n",
13603 rd_str);
13604 show_rd = false;
13605 }
13606 }
13607
13608 attr = *ain->attr;
13609 route_filtered = false;
13610
13611 /* Filter prefix using distribute list,
13612 * filter list or prefix list
13613 */
13614 const struct prefix *rn_p =
13615 bgp_dest_get_prefix(dest);
13616 if ((bgp_input_filter(peer, rn_p, &attr, afi,
13617 safi))
13618 == FILTER_DENY)
13619 route_filtered = true;
13620
13621 /* Filter prefix using route-map */
13622 ret = bgp_input_modifier(peer, rn_p, &attr, afi,
13623 safi, rmap_name, NULL,
13624 0, NULL);
13625
13626 if (type == bgp_show_adj_route_filtered &&
13627 !route_filtered && ret != RMAP_DENY) {
13628 bgp_attr_undup(&attr, ain->attr);
13629 continue;
13630 }
13631
13632 if (type == bgp_show_adj_route_received
13633 && (route_filtered || ret == RMAP_DENY))
13634 (*filtered_count)++;
13635
13636 route_vty_out_tmp(vty, dest, rn_p, &attr, safi,
13637 use_json, json_ar, wide);
13638 bgp_attr_undup(&attr, ain->attr);
13639 (*output_count)++;
13640 }
13641 } else if (type == bgp_show_adj_route_advertised) {
13642 RB_FOREACH (adj, bgp_adj_out_rb, &dest->adj_out)
13643 SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
13644 if (paf->peer != peer || !adj->attr)
13645 continue;
13646
13647 show_adj_route_header(vty, bgp, table,
13648 header1, header2,
13649 json, json_scode,
13650 json_ocode, wide);
13651
13652 const struct prefix *rn_p =
13653 bgp_dest_get_prefix(dest);
13654
13655 attr = *adj->attr;
13656 ret = bgp_output_modifier(
13657 peer, rn_p, &attr, afi, safi,
13658 rmap_name);
13659
13660 if (ret != RMAP_DENY) {
13661 if ((safi == SAFI_MPLS_VPN)
13662 || (safi == SAFI_ENCAP)
13663 || (safi == SAFI_EVPN)) {
13664 if (use_json)
13665 json_object_string_add(
13666 json_ar,
13667 "rd",
13668 rd_str);
13669 else if (show_rd
13670 && rd_str) {
13671 vty_out(vty,
13672 "Route Distinguisher: %s\n",
13673 rd_str);
13674 show_rd = false;
13675 }
13676 }
13677 route_vty_out_tmp(
13678 vty, dest, rn_p, &attr,
13679 safi, use_json, json_ar,
13680 wide);
13681 (*output_count)++;
13682 } else {
13683 (*filtered_count)++;
13684 }
13685
13686 bgp_attr_undup(&attr, adj->attr);
13687 }
13688 } else if (type == bgp_show_adj_route_bestpath) {
13689 struct bgp_path_info *pi;
13690
13691 show_adj_route_header(vty, bgp, table, header1, header2,
13692 json, json_scode, json_ocode,
13693 wide);
13694
13695 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
13696 pi = pi->next) {
13697 if (pi->peer != peer)
13698 continue;
13699
13700 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
13701 continue;
13702
13703 route_vty_out_tmp(vty, dest,
13704 bgp_dest_get_prefix(dest),
13705 pi->attr, safi, use_json,
13706 json_ar, wide);
13707 (*output_count)++;
13708 }
13709 }
13710 }
13711 }
13712
13713 static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
13714 safi_t safi, enum bgp_show_adj_route_type type,
13715 const char *rmap_name, uint16_t show_flags)
13716 {
13717 struct bgp *bgp;
13718 struct bgp_table *table;
13719 json_object *json = NULL;
13720 json_object *json_scode = NULL;
13721 json_object *json_ocode = NULL;
13722 json_object *json_ar = NULL;
13723 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13724
13725 /* Init BGP headers here so they're only displayed once
13726 * even if 'table' is 2-tier (MPLS_VPN, ENCAP, EVPN).
13727 */
13728 int header1 = 1;
13729 int header2 = 1;
13730
13731 /*
13732 * Initialize variables for each RD
13733 * All prefixes under an RD is aggregated within "json_routes"
13734 */
13735 char rd_str[BUFSIZ] = {0};
13736 json_object *json_routes = NULL;
13737
13738
13739 /* For 2-tier tables, prefix counts need to be
13740 * maintained across multiple runs of show_adj_route()
13741 */
13742 unsigned long output_count_per_rd;
13743 unsigned long filtered_count_per_rd;
13744 unsigned long output_count = 0;
13745 unsigned long filtered_count = 0;
13746
13747 if (use_json) {
13748 json = json_object_new_object();
13749 json_ar = json_object_new_object();
13750 json_scode = json_object_new_object();
13751 json_ocode = json_object_new_object();
13752
13753 json_object_string_add(json_scode, "suppressed", "s");
13754 json_object_string_add(json_scode, "damped", "d");
13755 json_object_string_add(json_scode, "history", "h");
13756 json_object_string_add(json_scode, "valid", "*");
13757 json_object_string_add(json_scode, "best", ">");
13758 json_object_string_add(json_scode, "multipath", "=");
13759 json_object_string_add(json_scode, "internal", "i");
13760 json_object_string_add(json_scode, "ribFailure", "r");
13761 json_object_string_add(json_scode, "stale", "S");
13762 json_object_string_add(json_scode, "removed", "R");
13763
13764 json_object_string_add(json_ocode, "igp", "i");
13765 json_object_string_add(json_ocode, "egp", "e");
13766 json_object_string_add(json_ocode, "incomplete", "?");
13767 }
13768
13769 if (!peer || !peer->afc[afi][safi]) {
13770 if (use_json) {
13771 json_object_string_add(
13772 json, "warning",
13773 "No such neighbor or address family");
13774 vty_out(vty, "%s\n", json_object_to_json_string(json));
13775 json_object_free(json);
13776 } else
13777 vty_out(vty, "%% No such neighbor or address family\n");
13778
13779 return CMD_WARNING;
13780 }
13781
13782 if ((type == bgp_show_adj_route_received
13783 || type == bgp_show_adj_route_filtered)
13784 && !CHECK_FLAG(peer->af_flags[afi][safi],
13785 PEER_FLAG_SOFT_RECONFIG)) {
13786 if (use_json) {
13787 json_object_string_add(
13788 json, "warning",
13789 "Inbound soft reconfiguration not enabled");
13790 vty_out(vty, "%s\n", json_object_to_json_string(json));
13791 json_object_free(json);
13792 } else
13793 vty_out(vty,
13794 "%% Inbound soft reconfiguration not enabled\n");
13795
13796 return CMD_WARNING;
13797 }
13798
13799 bgp = peer->bgp;
13800
13801 /* labeled-unicast routes live in the unicast table */
13802 if (safi == SAFI_LABELED_UNICAST)
13803 table = bgp->rib[afi][SAFI_UNICAST];
13804 else
13805 table = bgp->rib[afi][safi];
13806
13807 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
13808 || (safi == SAFI_EVPN)) {
13809
13810 struct bgp_dest *dest;
13811
13812 for (dest = bgp_table_top(table); dest;
13813 dest = bgp_route_next(dest)) {
13814 table = bgp_dest_get_bgp_table_info(dest);
13815 if (!table)
13816 continue;
13817
13818 output_count_per_rd = 0;
13819 filtered_count_per_rd = 0;
13820
13821 if (use_json)
13822 json_routes = json_object_new_object();
13823
13824 const struct prefix_rd *prd;
13825 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
13826 dest);
13827
13828 prefix_rd2str(prd, rd_str, sizeof(rd_str));
13829
13830 show_adj_route(vty, peer, table, afi, safi, type,
13831 rmap_name, json, json_routes, json_scode,
13832 json_ocode, show_flags, &header1,
13833 &header2, rd_str, &output_count_per_rd,
13834 &filtered_count_per_rd);
13835
13836 /* Don't include an empty RD in the output! */
13837 if (json_routes && (output_count_per_rd > 0))
13838 json_object_object_add(json_ar, rd_str,
13839 json_routes);
13840
13841 output_count += output_count_per_rd;
13842 filtered_count += filtered_count_per_rd;
13843 }
13844 } else
13845 show_adj_route(vty, peer, table, afi, safi, type, rmap_name,
13846 json, json_ar, json_scode, json_ocode,
13847 show_flags, &header1, &header2, rd_str,
13848 &output_count, &filtered_count);
13849
13850 if (use_json) {
13851 json_object_object_add(json, "advertisedRoutes", json_ar);
13852 json_object_int_add(json, "totalPrefixCounter", output_count);
13853 json_object_int_add(json, "filteredPrefixCounter",
13854 filtered_count);
13855
13856 vty_out(vty, "%s\n",
13857 json_object_to_json_string_ext(
13858 json, JSON_C_TO_STRING_PRETTY));
13859
13860 if (!output_count && !filtered_count) {
13861 json_object_free(json_scode);
13862 json_object_free(json_ocode);
13863 }
13864
13865 if (json)
13866 json_object_free(json);
13867
13868 } else if (output_count > 0) {
13869 if (filtered_count > 0)
13870 vty_out(vty,
13871 "\nTotal number of prefixes %ld (%ld filtered)\n",
13872 output_count, filtered_count);
13873 else
13874 vty_out(vty, "\nTotal number of prefixes %ld\n",
13875 output_count);
13876 }
13877
13878 return CMD_SUCCESS;
13879 }
13880
13881 DEFPY (show_ip_bgp_instance_neighbor_bestpath_route,
13882 show_ip_bgp_instance_neighbor_bestpath_route_cmd,
13883 "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]",
13884 SHOW_STR
13885 IP_STR
13886 BGP_STR
13887 BGP_INSTANCE_HELP_STR
13888 BGP_AFI_HELP_STR
13889 BGP_SAFI_WITH_LABEL_HELP_STR
13890 "Detailed information on TCP and BGP neighbor connections\n"
13891 "Neighbor to display information about\n"
13892 "Neighbor to display information about\n"
13893 "Neighbor on BGP configured interface\n"
13894 "Display the routes selected by best path\n"
13895 JSON_STR
13896 "Increase table width for longer prefixes\n")
13897 {
13898 afi_t afi = AFI_IP6;
13899 safi_t safi = SAFI_UNICAST;
13900 char *rmap_name = NULL;
13901 char *peerstr = NULL;
13902 struct bgp *bgp = NULL;
13903 struct peer *peer;
13904 enum bgp_show_adj_route_type type = bgp_show_adj_route_bestpath;
13905 int idx = 0;
13906 uint16_t show_flags = 0;
13907
13908 if (uj)
13909 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13910
13911 if (wide)
13912 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
13913
13914 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13915 &bgp, uj);
13916
13917 if (!idx)
13918 return CMD_WARNING;
13919
13920 argv_find(argv, argc, "neighbors", &idx);
13921 peerstr = argv[++idx]->arg;
13922
13923 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
13924 if (!peer)
13925 return CMD_WARNING;
13926
13927 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13928 show_flags);
13929 }
13930
13931 DEFPY (show_ip_bgp_instance_neighbor_advertised_route,
13932 show_ip_bgp_instance_neighbor_advertised_route_cmd,
13933 "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]",
13934 SHOW_STR
13935 IP_STR
13936 BGP_STR
13937 BGP_INSTANCE_HELP_STR
13938 BGP_AFI_HELP_STR
13939 BGP_SAFI_WITH_LABEL_HELP_STR
13940 "Display the entries for all address families\n"
13941 "Detailed information on TCP and BGP neighbor connections\n"
13942 "Neighbor to display information about\n"
13943 "Neighbor to display information about\n"
13944 "Neighbor on BGP configured interface\n"
13945 "Display the routes advertised to a BGP neighbor\n"
13946 "Display the received routes from neighbor\n"
13947 "Display the filtered routes received from neighbor\n"
13948 "Route-map to modify the attributes\n"
13949 "Name of the route map\n"
13950 JSON_STR
13951 "Increase table width for longer prefixes\n")
13952 {
13953 afi_t afi = AFI_IP6;
13954 safi_t safi = SAFI_UNICAST;
13955 char *rmap_name = NULL;
13956 char *peerstr = NULL;
13957 struct bgp *bgp = NULL;
13958 struct peer *peer;
13959 enum bgp_show_adj_route_type type = bgp_show_adj_route_advertised;
13960 int idx = 0;
13961 bool first = true;
13962 uint16_t show_flags = 0;
13963
13964 if (uj) {
13965 argc--;
13966 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13967 }
13968
13969 if (all) {
13970 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
13971 if (argv_find(argv, argc, "ipv4", &idx))
13972 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
13973
13974 if (argv_find(argv, argc, "ipv6", &idx))
13975 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
13976 }
13977
13978 if (wide)
13979 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
13980
13981 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13982 &bgp, uj);
13983 if (!idx)
13984 return CMD_WARNING;
13985
13986 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13987 argv_find(argv, argc, "neighbors", &idx);
13988 peerstr = argv[++idx]->arg;
13989
13990 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
13991 if (!peer)
13992 return CMD_WARNING;
13993
13994 if (argv_find(argv, argc, "advertised-routes", &idx))
13995 type = bgp_show_adj_route_advertised;
13996 else if (argv_find(argv, argc, "received-routes", &idx))
13997 type = bgp_show_adj_route_received;
13998 else if (argv_find(argv, argc, "filtered-routes", &idx))
13999 type = bgp_show_adj_route_filtered;
14000
14001 if (argv_find(argv, argc, "route-map", &idx))
14002 rmap_name = argv[++idx]->arg;
14003
14004 if (!all)
14005 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
14006 show_flags);
14007 if (uj)
14008 vty_out(vty, "{\n");
14009
14010 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
14011 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
14012 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP) ? AFI_IP
14013 : AFI_IP6;
14014 FOREACH_SAFI (safi) {
14015 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
14016 continue;
14017
14018 if (uj) {
14019 if (first)
14020 first = false;
14021 else
14022 vty_out(vty, ",\n");
14023 vty_out(vty, "\"%s\":",
14024 get_afi_safi_str(afi, safi, true));
14025 } else
14026 vty_out(vty, "\nFor address family: %s\n",
14027 get_afi_safi_str(afi, safi, false));
14028
14029 peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
14030 show_flags);
14031 }
14032 } else {
14033 FOREACH_AFI_SAFI (afi, safi) {
14034 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
14035 continue;
14036
14037 if (uj) {
14038 if (first)
14039 first = false;
14040 else
14041 vty_out(vty, ",\n");
14042 vty_out(vty, "\"%s\":",
14043 get_afi_safi_str(afi, safi, true));
14044 } else
14045 vty_out(vty, "\nFor address family: %s\n",
14046 get_afi_safi_str(afi, safi, false));
14047
14048 peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
14049 show_flags);
14050 }
14051 }
14052 if (uj)
14053 vty_out(vty, "}\n");
14054
14055 return CMD_SUCCESS;
14056 }
14057
14058 DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
14059 show_ip_bgp_neighbor_received_prefix_filter_cmd,
14060 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
14061 SHOW_STR
14062 IP_STR
14063 BGP_STR
14064 "Address Family\n"
14065 "Address Family\n"
14066 "Address Family modifier\n"
14067 "Detailed information on TCP and BGP neighbor connections\n"
14068 "Neighbor to display information about\n"
14069 "Neighbor to display information about\n"
14070 "Neighbor on BGP configured interface\n"
14071 "Display information received from a BGP neighbor\n"
14072 "Display the prefixlist filter\n"
14073 JSON_STR)
14074 {
14075 afi_t afi = AFI_IP6;
14076 safi_t safi = SAFI_UNICAST;
14077 char *peerstr = NULL;
14078
14079 char name[BUFSIZ];
14080 union sockunion su;
14081 struct peer *peer;
14082 int count, ret;
14083
14084 int idx = 0;
14085
14086 /* show [ip] bgp */
14087 if (argv_find(argv, argc, "ip", &idx))
14088 afi = AFI_IP;
14089 /* [<ipv4|ipv6> [unicast]] */
14090 if (argv_find(argv, argc, "ipv4", &idx))
14091 afi = AFI_IP;
14092 if (argv_find(argv, argc, "ipv6", &idx))
14093 afi = AFI_IP6;
14094 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14095 argv_find(argv, argc, "neighbors", &idx);
14096 peerstr = argv[++idx]->arg;
14097
14098 bool uj = use_json(argc, argv);
14099
14100 ret = str2sockunion(peerstr, &su);
14101 if (ret < 0) {
14102 peer = peer_lookup_by_conf_if(NULL, peerstr);
14103 if (!peer) {
14104 if (uj)
14105 vty_out(vty, "{}\n");
14106 else
14107 vty_out(vty,
14108 "%% Malformed address or name: %s\n",
14109 peerstr);
14110 return CMD_WARNING;
14111 }
14112 } else {
14113 peer = peer_lookup(NULL, &su);
14114 if (!peer) {
14115 if (uj)
14116 vty_out(vty, "{}\n");
14117 else
14118 vty_out(vty, "No peer\n");
14119 return CMD_WARNING;
14120 }
14121 }
14122
14123 snprintf(name, sizeof(name), "%s.%d.%d", peer->host, afi, safi);
14124 count = prefix_bgp_show_prefix_list(NULL, afi, name, uj);
14125 if (count) {
14126 if (!uj)
14127 vty_out(vty, "Address Family: %s\n",
14128 get_afi_safi_str(afi, safi, false));
14129 prefix_bgp_show_prefix_list(vty, afi, name, uj);
14130 } else {
14131 if (uj)
14132 vty_out(vty, "{}\n");
14133 else
14134 vty_out(vty, "No functional output\n");
14135 }
14136
14137 return CMD_SUCCESS;
14138 }
14139
14140 static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer,
14141 afi_t afi, safi_t safi,
14142 enum bgp_show_type type, bool use_json)
14143 {
14144 uint16_t show_flags = 0;
14145
14146 if (use_json)
14147 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14148
14149 if (!peer || !peer->afc[afi][safi]) {
14150 if (use_json) {
14151 json_object *json_no = NULL;
14152 json_no = json_object_new_object();
14153 json_object_string_add(
14154 json_no, "warning",
14155 "No such neighbor or address family");
14156 vty_out(vty, "%s\n",
14157 json_object_to_json_string(json_no));
14158 json_object_free(json_no);
14159 } else
14160 vty_out(vty, "%% No such neighbor or address family\n");
14161 return CMD_WARNING;
14162 }
14163
14164 /* labeled-unicast routes live in the unicast table */
14165 if (safi == SAFI_LABELED_UNICAST)
14166 safi = SAFI_UNICAST;
14167
14168 return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, show_flags,
14169 RPKI_NOT_BEING_USED);
14170 }
14171
14172 DEFUN (show_ip_bgp_flowspec_routes_detailed,
14173 show_ip_bgp_flowspec_routes_detailed_cmd,
14174 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" flowspec] detail [json]",
14175 SHOW_STR
14176 IP_STR
14177 BGP_STR
14178 BGP_INSTANCE_HELP_STR
14179 BGP_AFI_HELP_STR
14180 "SAFI Flowspec\n"
14181 "Detailed information on flowspec entries\n"
14182 JSON_STR)
14183 {
14184 afi_t afi = AFI_IP;
14185 safi_t safi = SAFI_UNICAST;
14186 struct bgp *bgp = NULL;
14187 int idx = 0;
14188 bool uj = use_json(argc, argv);
14189 uint16_t show_flags = 0;
14190
14191 if (uj) {
14192 argc--;
14193 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14194 }
14195
14196 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
14197 &bgp, uj);
14198 if (!idx)
14199 return CMD_WARNING;
14200
14201 return bgp_show(vty, bgp, afi, safi, bgp_show_type_detail, NULL,
14202 show_flags, RPKI_NOT_BEING_USED);
14203 }
14204
14205 DEFUN (show_ip_bgp_neighbor_routes,
14206 show_ip_bgp_neighbor_routes_cmd,
14207 "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]",
14208 SHOW_STR
14209 IP_STR
14210 BGP_STR
14211 BGP_INSTANCE_HELP_STR
14212 BGP_AFI_HELP_STR
14213 BGP_SAFI_WITH_LABEL_HELP_STR
14214 "Detailed information on TCP and BGP neighbor connections\n"
14215 "Neighbor to display information about\n"
14216 "Neighbor to display information about\n"
14217 "Neighbor on BGP configured interface\n"
14218 "Display flap statistics of the routes learned from neighbor\n"
14219 "Display the dampened routes received from neighbor\n"
14220 "Display routes learned from neighbor\n"
14221 JSON_STR)
14222 {
14223 char *peerstr = NULL;
14224 struct bgp *bgp = NULL;
14225 afi_t afi = AFI_IP6;
14226 safi_t safi = SAFI_UNICAST;
14227 struct peer *peer;
14228 enum bgp_show_type sh_type = bgp_show_type_neighbor;
14229 int idx = 0;
14230 bool uj = use_json(argc, argv);
14231
14232 if (uj)
14233 argc--;
14234
14235 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
14236 &bgp, uj);
14237 if (!idx)
14238 return CMD_WARNING;
14239
14240 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14241 argv_find(argv, argc, "neighbors", &idx);
14242 peerstr = argv[++idx]->arg;
14243
14244 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
14245 if (!peer)
14246 return CMD_WARNING;
14247
14248 if (argv_find(argv, argc, "flap-statistics", &idx))
14249 sh_type = bgp_show_type_flap_neighbor;
14250 else if (argv_find(argv, argc, "dampened-routes", &idx))
14251 sh_type = bgp_show_type_damp_neighbor;
14252 else if (argv_find(argv, argc, "routes", &idx))
14253 sh_type = bgp_show_type_neighbor;
14254
14255 return bgp_show_neighbor_route(vty, peer, afi, safi, sh_type, uj);
14256 }
14257
14258 struct bgp_table *bgp_distance_table[AFI_MAX][SAFI_MAX];
14259
14260 struct bgp_distance {
14261 /* Distance value for the IP source prefix. */
14262 uint8_t distance;
14263
14264 /* Name of the access-list to be matched. */
14265 char *access_list;
14266 };
14267
14268 DEFUN (show_bgp_afi_vpn_rd_route,
14269 show_bgp_afi_vpn_rd_route_cmd,
14270 "show bgp "BGP_AFI_CMD_STR" vpn rd <ASN:NN_OR_IP-ADDRESS:NN|all> <A.B.C.D/M|X:X::X:X/M> [json]",
14271 SHOW_STR
14272 BGP_STR
14273 BGP_AFI_HELP_STR
14274 "Address Family modifier\n"
14275 "Display information for a route distinguisher\n"
14276 "Route Distinguisher\n"
14277 "All Route Distinguishers\n"
14278 "Network in the BGP routing table to display\n"
14279 "Network in the BGP routing table to display\n"
14280 JSON_STR)
14281 {
14282 int ret;
14283 struct prefix_rd prd;
14284 afi_t afi = AFI_MAX;
14285 int idx = 0;
14286
14287 if (!argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
14288 vty_out(vty, "%% Malformed Address Family\n");
14289 return CMD_WARNING;
14290 }
14291
14292 if (!strcmp(argv[5]->arg, "all"))
14293 return bgp_show_route(vty, NULL, argv[6]->arg, afi,
14294 SAFI_MPLS_VPN, NULL, 0, BGP_PATH_SHOW_ALL,
14295 RPKI_NOT_BEING_USED,
14296 use_json(argc, argv));
14297
14298 ret = str2prefix_rd(argv[5]->arg, &prd);
14299 if (!ret) {
14300 vty_out(vty, "%% Malformed Route Distinguisher\n");
14301 return CMD_WARNING;
14302 }
14303
14304 return bgp_show_route(vty, NULL, argv[6]->arg, afi, SAFI_MPLS_VPN, &prd,
14305 0, BGP_PATH_SHOW_ALL, RPKI_NOT_BEING_USED,
14306 use_json(argc, argv));
14307 }
14308
14309 static struct bgp_distance *bgp_distance_new(void)
14310 {
14311 return XCALLOC(MTYPE_BGP_DISTANCE, sizeof(struct bgp_distance));
14312 }
14313
14314 static void bgp_distance_free(struct bgp_distance *bdistance)
14315 {
14316 XFREE(MTYPE_BGP_DISTANCE, bdistance);
14317 }
14318
14319 int bgp_distance_set(uint8_t distance, const char *ip_str,
14320 const char *access_list_str, afi_t afi, safi_t safi,
14321 char *errmsg, size_t errmsg_len)
14322 {
14323 int ret;
14324 struct prefix p;
14325 struct bgp_dest *dest;
14326 struct bgp_distance *bdistance;
14327
14328 ret = str2prefix(ip_str, &p);
14329 if (ret == 0) {
14330 snprintf(errmsg, errmsg_len, "Malformed prefix\n");
14331 return CMD_WARNING_CONFIG_FAILED;
14332 }
14333
14334 /* Get BGP distance node. */
14335 dest = bgp_node_get(bgp_distance_table[afi][safi], &p);
14336 bdistance = bgp_dest_get_bgp_distance_info(dest);
14337 if (bdistance)
14338 bgp_dest_unlock_node(dest);
14339 else {
14340 bdistance = bgp_distance_new();
14341 bgp_dest_set_bgp_distance_info(dest, bdistance);
14342 }
14343
14344 /* Set distance value. */
14345 bdistance->distance = distance;
14346
14347 /* Reset access-list configuration. */
14348 XFREE(MTYPE_AS_LIST, bdistance->access_list);
14349 if (access_list_str)
14350 bdistance->access_list =
14351 XSTRDUP(MTYPE_AS_LIST, access_list_str);
14352
14353 return CMD_SUCCESS;
14354 }
14355
14356 int bgp_distance_unset(uint8_t distance, const char *ip_str,
14357 const char *access_list_str, afi_t afi, safi_t safi,
14358 char *errmsg, size_t errmsg_len)
14359 {
14360 int ret;
14361 struct prefix p;
14362 struct bgp_dest *dest;
14363 struct bgp_distance *bdistance;
14364
14365 ret = str2prefix(ip_str, &p);
14366 if (ret == 0) {
14367 snprintf(errmsg, errmsg_len, "Malformed prefix\n");
14368 return CMD_WARNING_CONFIG_FAILED;
14369 }
14370
14371 dest = bgp_node_lookup(bgp_distance_table[afi][safi], &p);
14372 if (!dest) {
14373 snprintf(errmsg, errmsg_len, "Can't find specified prefix\n");
14374 return CMD_WARNING_CONFIG_FAILED;
14375 }
14376
14377 bdistance = bgp_dest_get_bgp_distance_info(dest);
14378
14379 if (bdistance->distance != distance) {
14380 snprintf(errmsg, errmsg_len,
14381 "Distance does not match configured\n");
14382 bgp_dest_unlock_node(dest);
14383 return CMD_WARNING_CONFIG_FAILED;
14384 }
14385
14386 XFREE(MTYPE_AS_LIST, bdistance->access_list);
14387 bgp_distance_free(bdistance);
14388
14389 bgp_dest_set_bgp_path_info(dest, NULL);
14390 bgp_dest_unlock_node(dest);
14391 bgp_dest_unlock_node(dest);
14392
14393 return CMD_SUCCESS;
14394 }
14395
14396 /* Apply BGP information to distance method. */
14397 uint8_t bgp_distance_apply(const struct prefix *p, struct bgp_path_info *pinfo,
14398 afi_t afi, safi_t safi, struct bgp *bgp)
14399 {
14400 struct bgp_dest *dest;
14401 struct prefix q = {0};
14402 struct peer *peer;
14403 struct bgp_distance *bdistance;
14404 struct access_list *alist;
14405 struct bgp_static *bgp_static;
14406
14407 if (!bgp)
14408 return 0;
14409
14410 peer = pinfo->peer;
14411
14412 if (pinfo->attr->distance)
14413 return pinfo->attr->distance;
14414
14415 /* Check source address.
14416 * Note: for aggregate route, peer can have unspec af type.
14417 */
14418 if (pinfo->sub_type != BGP_ROUTE_AGGREGATE
14419 && !sockunion2hostprefix(&peer->su, &q))
14420 return 0;
14421
14422 dest = bgp_node_match(bgp_distance_table[afi][safi], &q);
14423 if (dest) {
14424 bdistance = bgp_dest_get_bgp_distance_info(dest);
14425 bgp_dest_unlock_node(dest);
14426
14427 if (bdistance->access_list) {
14428 alist = access_list_lookup(afi, bdistance->access_list);
14429 if (alist
14430 && access_list_apply(alist, p) == FILTER_PERMIT)
14431 return bdistance->distance;
14432 } else
14433 return bdistance->distance;
14434 }
14435
14436 /* Backdoor check. */
14437 dest = bgp_node_lookup(bgp->route[afi][safi], p);
14438 if (dest) {
14439 bgp_static = bgp_dest_get_bgp_static_info(dest);
14440 bgp_dest_unlock_node(dest);
14441
14442 if (bgp_static->backdoor) {
14443 if (bgp->distance_local[afi][safi])
14444 return bgp->distance_local[afi][safi];
14445 else
14446 return ZEBRA_IBGP_DISTANCE_DEFAULT;
14447 }
14448 }
14449
14450 if (peer->sort == BGP_PEER_EBGP) {
14451 if (bgp->distance_ebgp[afi][safi])
14452 return bgp->distance_ebgp[afi][safi];
14453 return ZEBRA_EBGP_DISTANCE_DEFAULT;
14454 } else if (peer->sort == BGP_PEER_IBGP) {
14455 if (bgp->distance_ibgp[afi][safi])
14456 return bgp->distance_ibgp[afi][safi];
14457 return ZEBRA_IBGP_DISTANCE_DEFAULT;
14458 } else {
14459 if (bgp->distance_local[afi][safi])
14460 return bgp->distance_local[afi][safi];
14461 return ZEBRA_IBGP_DISTANCE_DEFAULT;
14462 }
14463 }
14464
14465 /* If we enter `distance bgp (1-255) (1-255) (1-255)`,
14466 * we should tell ZEBRA update the routes for a specific
14467 * AFI/SAFI to reflect changes in RIB.
14468 */
14469 void bgp_announce_routes_distance_update(struct bgp *bgp, afi_t update_afi,
14470 safi_t update_safi)
14471 {
14472 afi_t afi;
14473 safi_t safi;
14474
14475 FOREACH_AFI_SAFI (afi, safi) {
14476 if (!bgp_fibupd_safi(safi))
14477 continue;
14478
14479 if (afi != update_afi && safi != update_safi)
14480 continue;
14481
14482 if (BGP_DEBUG(zebra, ZEBRA))
14483 zlog_debug(
14484 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
14485 __func__, afi, safi);
14486 bgp_zebra_announce_table(bgp, afi, safi);
14487 }
14488 }
14489
14490 DEFUN_YANG(bgp_distance, bgp_distance_cmd,
14491 "distance bgp (1-255) (1-255) (1-255)",
14492 "Define an administrative distance\n"
14493 "BGP distance\n"
14494 "Distance for routes external to the AS\n"
14495 "Distance for routes internal to the AS\n"
14496 "Distance for local routes\n")
14497 {
14498 int idx_number = 2;
14499 int idx_number_2 = 3;
14500 int idx_number_3 = 4;
14501 afi_t afi;
14502 safi_t safi;
14503 char xpath[XPATH_MAXLEN];
14504
14505 afi = bgp_node_afi(vty);
14506 safi = bgp_node_safi(vty);
14507
14508 snprintf(
14509 xpath, sizeof(xpath),
14510 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/external",
14511 yang_afi_safi_value2identity(afi, safi),
14512 bgp_afi_safi_get_container_str(afi, safi));
14513 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, argv[idx_number]->arg);
14514 snprintf(
14515 xpath, sizeof(xpath),
14516 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/internal",
14517 yang_afi_safi_value2identity(afi, safi),
14518 bgp_afi_safi_get_container_str(afi, safi));
14519 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY,
14520 argv[idx_number_2]->arg);
14521 snprintf(
14522 xpath, sizeof(xpath),
14523 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/local",
14524 yang_afi_safi_value2identity(afi, safi),
14525 bgp_afi_safi_get_container_str(afi, safi));
14526
14527 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY,
14528 argv[idx_number_3]->arg);
14529
14530 return nb_cli_apply_changes(vty, NULL);
14531 }
14532
14533 DEFUN_YANG(no_bgp_distance, no_bgp_distance_cmd,
14534 "no distance bgp [(1-255) (1-255) (1-255)]",
14535 NO_STR
14536 "Define an administrative distance\n"
14537 "BGP distance\n"
14538 "Distance for routes external to the AS\n"
14539 "Distance for routes internal to the AS\n"
14540 "Distance for local routes\n")
14541 {
14542 afi_t afi;
14543 safi_t safi;
14544 char xpath[XPATH_MAXLEN];
14545
14546 afi = bgp_node_afi(vty);
14547 safi = bgp_node_safi(vty);
14548
14549 snprintf(
14550 xpath, sizeof(xpath),
14551 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/external",
14552 yang_afi_safi_value2identity(afi, safi),
14553 bgp_afi_safi_get_container_str(afi, safi));
14554 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, NULL);
14555 snprintf(
14556 xpath, sizeof(xpath),
14557 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/internal",
14558 yang_afi_safi_value2identity(afi, safi),
14559 bgp_afi_safi_get_container_str(afi, safi));
14560 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, NULL);
14561 snprintf(
14562 xpath, sizeof(xpath),
14563 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/local",
14564 yang_afi_safi_value2identity(afi, safi),
14565 bgp_afi_safi_get_container_str(afi, safi));
14566
14567 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, NULL);
14568
14569 return nb_cli_apply_changes(vty, NULL);
14570 }
14571
14572 void cli_show_bgp_global_afi_safi_admin_distance_config(struct vty *vty,
14573 struct lyd_node *dnode,
14574 bool show_defaults)
14575 {
14576 uint8_t distance_ebgp, distance_ibgp, distance_local;
14577
14578 distance_ebgp = yang_dnode_get_uint8(dnode, "./external");
14579 distance_ibgp = yang_dnode_get_uint8(dnode, "./internal");
14580 distance_local = yang_dnode_get_uint8(dnode, "./local");
14581
14582 vty_out(vty, " distance bgp %d %d %d\n", distance_ebgp, distance_ibgp,
14583 distance_local);
14584 }
14585
14586 DEFPY_YANG(bgp_distance_source,
14587 bgp_distance_source_cmd,
14588 "[no] distance (1-255) <A.B.C.D/M | X:X::X:X/M>$prefix [WORD$acl]",
14589 NO_STR
14590 "Define an administrative distance\n"
14591 "Distance value\n"
14592 "IPv4 source prefix\n"
14593 "IPv6 source prefix\n"
14594 "Access list name\n")
14595 {
14596 afi_t afi;
14597 safi_t safi;
14598 char xpath[XPATH_MAXLEN];
14599
14600 afi = bgp_node_afi(vty);
14601 safi = bgp_node_safi(vty);
14602
14603 if (!no) {
14604 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
14605 nb_cli_enqueue_change(vty, "./distance", NB_OP_MODIFY,
14606 distance_str);
14607 if (acl)
14608 nb_cli_enqueue_change(vty,
14609 "./access-list-policy-export",
14610 NB_OP_CREATE, acl);
14611 else
14612 nb_cli_enqueue_change(vty,
14613 "./access-list-policy-export",
14614 NB_OP_DESTROY, NULL);
14615 } else {
14616 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
14617 }
14618
14619 snprintf(
14620 xpath, sizeof(xpath),
14621 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance-route[prefix='%s']",
14622 yang_afi_safi_value2identity(afi, safi),
14623 bgp_afi_safi_get_container_str(afi, safi), prefix_str);
14624
14625 return nb_cli_apply_changes(vty, xpath);
14626 }
14627
14628 void cli_show_bgp_global_afi_safi_unicast_admin_distance_route(
14629 struct vty *vty, struct lyd_node *dnode, bool show_defaults)
14630 {
14631 vty_out(vty, " distance %d %s %s\n",
14632 yang_dnode_get_uint8(dnode, "./distance"),
14633 yang_dnode_get_string(dnode, "./prefix"),
14634 (yang_dnode_exists(dnode, "./access-list-policy-export"))
14635 ? yang_dnode_get_string(dnode,
14636 "./access-list-policy-export")
14637 : "");
14638 }
14639
14640 DEFPY_YANG(
14641 bgp_dampening, bgp_dampening_cmd,
14642 "[no] bgp dampening [(1-45)$halflife [(1-20000)$reuse (1-20000)$suppress (1-255)$max_suppress]]",
14643 NO_STR
14644 "BGP Specific commands\n"
14645 "Enable route-flap dampening\n"
14646 "Half-life time for the penalty\n"
14647 "Value to start reusing a route\n"
14648 "Value to start suppressing a route\n"
14649 "Maximum duration to suppress a stable route\n")
14650 {
14651 afi_t afi;
14652 safi_t safi;
14653 char xpath[XPATH_MAXLEN];
14654
14655 afi = bgp_node_afi(vty);
14656 safi = bgp_node_safi(vty);
14657
14658 if (!no) {
14659 nb_cli_enqueue_change(vty, "./enable", NB_OP_MODIFY, "true");
14660 if (argc == 6) {
14661 nb_cli_enqueue_change(vty, "./reach-decay",
14662 NB_OP_MODIFY, halflife_str);
14663 nb_cli_enqueue_change(vty, "./reuse-above",
14664 NB_OP_MODIFY, reuse_str);
14665 nb_cli_enqueue_change(vty, "./suppress-above",
14666 NB_OP_MODIFY, suppress_str);
14667 nb_cli_enqueue_change(vty, "./unreach-decay",
14668 NB_OP_MODIFY, max_suppress_str);
14669 } if (argc == 3) {
14670 nb_cli_enqueue_change(vty, "./reach-decay",
14671 NB_OP_MODIFY, halflife_str);
14672 }
14673 } else {
14674 nb_cli_enqueue_change(vty, "./enable", NB_OP_MODIFY, "false");
14675 }
14676
14677 snprintf(
14678 xpath, sizeof(xpath),
14679 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/route-flap-dampening",
14680 yang_afi_safi_value2identity(afi, safi),
14681 bgp_afi_safi_get_container_str(afi, safi));
14682
14683 return nb_cli_apply_changes(vty, xpath);
14684 }
14685
14686 void cli_show_bgp_global_afi_safi_route_flap_dampening(struct vty *vty,
14687 struct lyd_node *dnode,
14688 bool show_defaults)
14689 {
14690 if (!yang_dnode_get_bool(dnode, "./enable"))
14691 return;
14692
14693 int half = DEFAULT_HALF_LIFE * 60;
14694 int reuse = DEFAULT_REUSE;
14695 int suppress = DEFAULT_SUPPRESS;
14696 int max;
14697
14698 half = yang_dnode_get_uint8(dnode, "../reach-decay");
14699 reuse = yang_dnode_get_uint16(dnode, "../reuse-above");
14700 suppress = yang_dnode_get_uint16(dnode, "../suppress-above");
14701 max = yang_dnode_get_uint8(dnode, "../unreach-decay");
14702
14703 if (half == DEFAULT_HALF_LIFE * 60 && reuse == DEFAULT_REUSE
14704 && suppress == DEFAULT_SUPPRESS && max == half * 4)
14705 vty_out(vty, " bgp dampening\n");
14706 else if (half != DEFAULT_HALF_LIFE * 60 && reuse == DEFAULT_REUSE
14707 && suppress == DEFAULT_SUPPRESS && max == half * 4)
14708 vty_out(vty, " bgp dampening %u\n", half);
14709 else
14710 vty_out(vty, " bgp dampening %u %d %d %d\n", half, reuse,
14711 suppress, max);
14712 }
14713
14714 /* Display specified route of BGP table. */
14715 static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
14716 const char *ip_str, afi_t afi, safi_t safi,
14717 struct prefix_rd *prd, int prefix_check)
14718 {
14719 int ret;
14720 struct prefix match;
14721 struct bgp_dest *dest;
14722 struct bgp_dest *rm;
14723 struct bgp_path_info *pi;
14724 struct bgp_path_info *pi_temp;
14725 struct bgp *bgp;
14726 struct bgp_table *table;
14727
14728 /* BGP structure lookup. */
14729 if (view_name) {
14730 bgp = bgp_lookup_by_name(view_name);
14731 if (bgp == NULL) {
14732 vty_out(vty, "%% Can't find BGP instance %s\n",
14733 view_name);
14734 return CMD_WARNING;
14735 }
14736 } else {
14737 bgp = bgp_get_default();
14738 if (bgp == NULL) {
14739 vty_out(vty, "%% No BGP process is configured\n");
14740 return CMD_WARNING;
14741 }
14742 }
14743
14744 /* Check IP address argument. */
14745 ret = str2prefix(ip_str, &match);
14746 if (!ret) {
14747 vty_out(vty, "%% address is malformed\n");
14748 return CMD_WARNING;
14749 }
14750
14751 match.family = afi2family(afi);
14752
14753 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
14754 || (safi == SAFI_EVPN)) {
14755 for (dest = bgp_table_top(bgp->rib[AFI_IP][safi]); dest;
14756 dest = bgp_route_next(dest)) {
14757 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
14758
14759 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
14760 continue;
14761 table = bgp_dest_get_bgp_table_info(dest);
14762 if (!table)
14763 continue;
14764 rm = bgp_node_match(table, &match);
14765 if (rm == NULL)
14766 continue;
14767
14768 const struct prefix *rm_p = bgp_dest_get_prefix(dest);
14769
14770 if (!prefix_check
14771 || rm_p->prefixlen == match.prefixlen) {
14772 pi = bgp_dest_get_bgp_path_info(rm);
14773 while (pi) {
14774 if (pi->extra && pi->extra->damp_info) {
14775 pi_temp = pi->next;
14776 bgp_damp_info_free(
14777 &pi->extra->damp_info,
14778 &bgp->damp[afi][safi],
14779 1, afi, safi);
14780 pi = pi_temp;
14781 } else
14782 pi = pi->next;
14783 }
14784 }
14785
14786 bgp_dest_unlock_node(rm);
14787 }
14788 } else {
14789 dest = bgp_node_match(bgp->rib[afi][safi], &match);
14790 if (dest != NULL) {
14791 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
14792
14793 if (!prefix_check
14794 || dest_p->prefixlen == match.prefixlen) {
14795 pi = bgp_dest_get_bgp_path_info(dest);
14796 while (pi) {
14797 if (pi->extra && pi->extra->damp_info) {
14798 pi_temp = pi->next;
14799 struct bgp_damp_info *bdi =
14800 pi->extra->damp_info;
14801 if (bdi->lastrecord
14802 == BGP_RECORD_UPDATE) {
14803 bgp_aggregate_increment(
14804 bgp,
14805 &bdi->dest->p,
14806 bdi->path,
14807 bdi->afi,
14808 bdi->safi);
14809 bgp_process(bgp,
14810 bdi->dest,
14811 bdi->afi,
14812 bdi->safi);
14813 }
14814 bgp_damp_info_free(
14815 &pi->extra->damp_info,
14816 &bgp->damp[afi][safi],
14817 1, afi, safi);
14818 pi = pi_temp;
14819 } else
14820 pi = pi->next;
14821 }
14822 }
14823
14824 bgp_dest_unlock_node(dest);
14825 }
14826 }
14827
14828 return CMD_SUCCESS;
14829 }
14830
14831 DEFUN (clear_ip_bgp_dampening,
14832 clear_ip_bgp_dampening_cmd,
14833 "clear ip bgp dampening",
14834 CLEAR_STR
14835 IP_STR
14836 BGP_STR
14837 "Clear route flap dampening information\n")
14838 {
14839 VTY_DECLVAR_CONTEXT(bgp, bgp);
14840 bgp_damp_info_clean(bgp, &bgp->damp[AFI_IP][SAFI_UNICAST], AFI_IP,
14841 SAFI_UNICAST);
14842 return CMD_SUCCESS;
14843 }
14844
14845 DEFUN (clear_ip_bgp_dampening_prefix,
14846 clear_ip_bgp_dampening_prefix_cmd,
14847 "clear ip bgp dampening A.B.C.D/M",
14848 CLEAR_STR
14849 IP_STR
14850 BGP_STR
14851 "Clear route flap dampening information\n"
14852 "IPv4 prefix\n")
14853 {
14854 int idx_ipv4_prefixlen = 4;
14855 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4_prefixlen]->arg,
14856 AFI_IP, SAFI_UNICAST, NULL, 1);
14857 }
14858
14859 DEFUN (clear_ip_bgp_dampening_address,
14860 clear_ip_bgp_dampening_address_cmd,
14861 "clear ip bgp dampening A.B.C.D",
14862 CLEAR_STR
14863 IP_STR
14864 BGP_STR
14865 "Clear route flap dampening information\n"
14866 "Network to clear damping information\n")
14867 {
14868 int idx_ipv4 = 4;
14869 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4]->arg, AFI_IP,
14870 SAFI_UNICAST, NULL, 0);
14871 }
14872
14873 DEFUN (clear_ip_bgp_dampening_address_mask,
14874 clear_ip_bgp_dampening_address_mask_cmd,
14875 "clear ip bgp dampening A.B.C.D A.B.C.D",
14876 CLEAR_STR
14877 IP_STR
14878 BGP_STR
14879 "Clear route flap dampening information\n"
14880 "Network to clear damping information\n"
14881 "Network mask\n")
14882 {
14883 int idx_ipv4 = 4;
14884 int idx_ipv4_2 = 5;
14885 int ret;
14886 char prefix_str[BUFSIZ];
14887
14888 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
14889 prefix_str, sizeof(prefix_str));
14890 if (!ret) {
14891 vty_out(vty, "%% Inconsistent address and mask\n");
14892 return CMD_WARNING;
14893 }
14894
14895 return bgp_clear_damp_route(vty, NULL, prefix_str, AFI_IP, SAFI_UNICAST,
14896 NULL, 0);
14897 }
14898
14899 static void show_bgp_peerhash_entry(struct hash_bucket *bucket, void *arg)
14900 {
14901 struct vty *vty = arg;
14902 struct peer *peer = bucket->data;
14903 char buf[SU_ADDRSTRLEN];
14904
14905 vty_out(vty, "\tPeer: %s %s\n", peer->host,
14906 sockunion2str(&peer->su, buf, sizeof(buf)));
14907 }
14908
14909 DEFUN (show_bgp_listeners,
14910 show_bgp_listeners_cmd,
14911 "show bgp listeners",
14912 SHOW_STR
14913 BGP_STR
14914 "Display Listen Sockets and who created them\n")
14915 {
14916 bgp_dump_listener_info(vty);
14917
14918 return CMD_SUCCESS;
14919 }
14920
14921 DEFUN (show_bgp_peerhash,
14922 show_bgp_peerhash_cmd,
14923 "show bgp peerhash",
14924 SHOW_STR
14925 BGP_STR
14926 "Display information about the BGP peerhash\n")
14927 {
14928 struct list *instances = bm->bgp;
14929 struct listnode *node;
14930 struct bgp *bgp;
14931
14932 for (ALL_LIST_ELEMENTS_RO(instances, node, bgp)) {
14933 vty_out(vty, "BGP: %s\n", bgp->name);
14934 hash_iterate(bgp->peerhash, show_bgp_peerhash_entry,
14935 vty);
14936 }
14937
14938 return CMD_SUCCESS;
14939 }
14940
14941 /* also used for encap safi */
14942 static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
14943 afi_t afi, safi_t safi)
14944 {
14945 struct bgp_dest *pdest;
14946 struct bgp_dest *dest;
14947 struct bgp_table *table;
14948 const struct prefix *p;
14949 const struct prefix_rd *prd;
14950 struct bgp_static *bgp_static;
14951 mpls_label_t label;
14952 char rdbuf[RD_ADDRSTRLEN];
14953
14954 /* Network configuration. */
14955 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
14956 pdest = bgp_route_next(pdest)) {
14957 table = bgp_dest_get_bgp_table_info(pdest);
14958 if (!table)
14959 continue;
14960
14961 for (dest = bgp_table_top(table); dest;
14962 dest = bgp_route_next(dest)) {
14963 bgp_static = bgp_dest_get_bgp_static_info(dest);
14964 if (bgp_static == NULL)
14965 continue;
14966
14967 p = bgp_dest_get_prefix(dest);
14968 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
14969 pdest);
14970
14971 /* "network" configuration display. */
14972 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
14973 label = decode_label(&bgp_static->label);
14974
14975 vty_out(vty, " network %pFX rd %s", p, rdbuf);
14976 if (safi == SAFI_MPLS_VPN)
14977 vty_out(vty, " label %u", label);
14978
14979 if (bgp_static->rmap.name)
14980 vty_out(vty, " route-map %s",
14981 bgp_static->rmap.name);
14982
14983 if (bgp_static->backdoor)
14984 vty_out(vty, " backdoor");
14985
14986 vty_out(vty, "\n");
14987 }
14988 }
14989 }
14990
14991 static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
14992 afi_t afi, safi_t safi)
14993 {
14994 struct bgp_dest *pdest;
14995 struct bgp_dest *dest;
14996 struct bgp_table *table;
14997 const struct prefix *p;
14998 const struct prefix_rd *prd;
14999 struct bgp_static *bgp_static;
15000 char buf[PREFIX_STRLEN * 2];
15001 char buf2[SU_ADDRSTRLEN];
15002 char rdbuf[RD_ADDRSTRLEN];
15003 char esi_buf[ESI_BYTES];
15004
15005 /* Network configuration. */
15006 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
15007 pdest = bgp_route_next(pdest)) {
15008 table = bgp_dest_get_bgp_table_info(pdest);
15009 if (!table)
15010 continue;
15011
15012 for (dest = bgp_table_top(table); dest;
15013 dest = bgp_route_next(dest)) {
15014 bgp_static = bgp_dest_get_bgp_static_info(dest);
15015 if (bgp_static == NULL)
15016 continue;
15017
15018 char *macrouter = NULL;
15019
15020 if (bgp_static->router_mac)
15021 macrouter = prefix_mac2str(
15022 bgp_static->router_mac, NULL, 0);
15023 if (bgp_static->eth_s_id)
15024 esi_to_str(bgp_static->eth_s_id,
15025 esi_buf, sizeof(esi_buf));
15026 p = bgp_dest_get_prefix(dest);
15027 prd = (struct prefix_rd *)bgp_dest_get_prefix(pdest);
15028
15029 /* "network" configuration display. */
15030 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
15031 if (p->u.prefix_evpn.route_type == 5) {
15032 char local_buf[PREFIX_STRLEN];
15033 uint8_t family = is_evpn_prefix_ipaddr_v4((
15034 struct prefix_evpn *)p)
15035 ? AF_INET
15036 : AF_INET6;
15037 inet_ntop(family,
15038 &p->u.prefix_evpn.prefix_addr.ip.ip.addr,
15039 local_buf, PREFIX_STRLEN);
15040 snprintf(buf, sizeof(buf), "%s/%u", local_buf,
15041 p->u.prefix_evpn.prefix_addr
15042 .ip_prefix_length);
15043 } else {
15044 prefix2str(p, buf, sizeof(buf));
15045 }
15046
15047 if (bgp_static->gatewayIp.family == AF_INET
15048 || bgp_static->gatewayIp.family == AF_INET6)
15049 inet_ntop(bgp_static->gatewayIp.family,
15050 &bgp_static->gatewayIp.u.prefix, buf2,
15051 sizeof(buf2));
15052 vty_out(vty,
15053 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
15054 buf, rdbuf,
15055 p->u.prefix_evpn.prefix_addr.eth_tag,
15056 decode_label(&bgp_static->label), esi_buf, buf2,
15057 macrouter);
15058
15059 XFREE(MTYPE_TMP, macrouter);
15060 }
15061 }
15062 }
15063
15064 /* Configuration of static route announcement and aggregate
15065 information. */
15066 void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
15067 safi_t safi)
15068 {
15069 struct bgp_dest *dest;
15070 const struct prefix *p;
15071 struct bgp_static *bgp_static;
15072 struct bgp_aggregate *bgp_aggregate;
15073
15074 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) {
15075 bgp_config_write_network_vpn(vty, bgp, afi, safi);
15076 return;
15077 }
15078
15079 if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
15080 bgp_config_write_network_evpn(vty, bgp, afi, safi);
15081 return;
15082 }
15083
15084 /* Network configuration. */
15085 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
15086 dest = bgp_route_next(dest)) {
15087 bgp_static = bgp_dest_get_bgp_static_info(dest);
15088 if (bgp_static == NULL)
15089 continue;
15090
15091 p = bgp_dest_get_prefix(dest);
15092
15093 vty_out(vty, " network %pFX", p);
15094
15095 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX)
15096 vty_out(vty, " label-index %u",
15097 bgp_static->label_index);
15098
15099 if (bgp_static->rmap.name)
15100 vty_out(vty, " route-map %s", bgp_static->rmap.name);
15101
15102 if (bgp_static->backdoor)
15103 vty_out(vty, " backdoor");
15104
15105 vty_out(vty, "\n");
15106 }
15107
15108 /* Aggregate-address configuration. */
15109 for (dest = bgp_table_top(bgp->aggregate[afi][safi]); dest;
15110 dest = bgp_route_next(dest)) {
15111 bgp_aggregate = bgp_dest_get_bgp_aggregate_info(dest);
15112 if (bgp_aggregate == NULL)
15113 continue;
15114
15115 p = bgp_dest_get_prefix(dest);
15116
15117 vty_out(vty, " aggregate-address %pFX", p);
15118
15119 if (bgp_aggregate->as_set)
15120 vty_out(vty, " as-set");
15121
15122 if (bgp_aggregate->summary_only)
15123 vty_out(vty, " summary-only");
15124
15125 if (bgp_aggregate->rmap.name)
15126 vty_out(vty, " route-map %s", bgp_aggregate->rmap.name);
15127
15128 if (bgp_aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
15129 vty_out(vty, " origin %s",
15130 bgp_origin2str(bgp_aggregate->origin));
15131
15132 if (bgp_aggregate->match_med)
15133 vty_out(vty, " matching-MED-only");
15134
15135 if (bgp_aggregate->suppress_map_name)
15136 vty_out(vty, " suppress-map %s",
15137 bgp_aggregate->suppress_map_name);
15138
15139 vty_out(vty, "\n");
15140 }
15141 }
15142
15143 void bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
15144 safi_t safi)
15145 {
15146 struct bgp_dest *dest;
15147 struct bgp_distance *bdistance;
15148
15149 /* Distance configuration. */
15150 if (bgp->distance_ebgp[afi][safi] && bgp->distance_ibgp[afi][safi]
15151 && bgp->distance_local[afi][safi]
15152 && (bgp->distance_ebgp[afi][safi] != ZEBRA_EBGP_DISTANCE_DEFAULT
15153 || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT
15154 || bgp->distance_local[afi][safi]
15155 != ZEBRA_IBGP_DISTANCE_DEFAULT)) {
15156 vty_out(vty, " distance bgp %d %d %d\n",
15157 bgp->distance_ebgp[afi][safi],
15158 bgp->distance_ibgp[afi][safi],
15159 bgp->distance_local[afi][safi]);
15160 }
15161
15162 for (dest = bgp_table_top(bgp_distance_table[afi][safi]); dest;
15163 dest = bgp_route_next(dest)) {
15164 bdistance = bgp_dest_get_bgp_distance_info(dest);
15165 if (bdistance != NULL)
15166 vty_out(vty, " distance %d %pBD %s\n",
15167 bdistance->distance, dest,
15168 bdistance->access_list ? bdistance->access_list
15169 : "");
15170 }
15171 }
15172
15173 /* Allocate routing table structure and install commands. */
15174 void bgp_route_init(void)
15175 {
15176 afi_t afi;
15177 safi_t safi;
15178
15179 /* Init BGP distance table. */
15180 FOREACH_AFI_SAFI (afi, safi)
15181 bgp_distance_table[afi][safi] = bgp_table_init(NULL, afi, safi);
15182
15183 /* IPv4 BGP commands. */
15184 install_element(BGP_NODE, &bgp_table_map_cmd);
15185 install_element(BGP_NODE, &bgp_network_cmd);
15186 install_element(BGP_NODE, &no_bgp_table_map_cmd);
15187
15188 install_element(BGP_NODE, &aggregate_addressv4_cmd);
15189
15190 /* IPv4 unicast configuration. */
15191 install_element(BGP_IPV4_NODE, &bgp_table_map_cmd);
15192 install_element(BGP_IPV4_NODE, &bgp_network_cmd);
15193 install_element(BGP_IPV4_NODE, &no_bgp_table_map_cmd);
15194
15195 install_element(BGP_IPV4_NODE, &aggregate_addressv4_cmd);
15196
15197 /* IPv4 multicast configuration. */
15198 install_element(BGP_IPV4M_NODE, &bgp_table_map_cmd);
15199 install_element(BGP_IPV4M_NODE, &bgp_network_cmd);
15200 install_element(BGP_IPV4M_NODE, &no_bgp_table_map_cmd);
15201 install_element(BGP_IPV4M_NODE, &aggregate_addressv4_cmd);
15202
15203 /* IPv4 labeled-unicast configuration. */
15204 install_element(BGP_IPV4L_NODE, &bgp_network_cmd);
15205 install_element(BGP_IPV4L_NODE, &aggregate_addressv4_cmd);
15206
15207 install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd);
15208 install_element(VIEW_NODE, &show_ip_bgp_cmd);
15209 install_element(VIEW_NODE, &show_ip_bgp_afi_safi_statistics_cmd);
15210 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_statistics_cmd);
15211 install_element(VIEW_NODE, &show_ip_bgp_json_cmd);
15212 install_element(VIEW_NODE, &show_ip_bgp_route_cmd);
15213 install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd);
15214 install_element(VIEW_NODE, &show_ip_bgp_statistics_all_cmd);
15215
15216 install_element(VIEW_NODE,
15217 &show_ip_bgp_instance_neighbor_advertised_route_cmd);
15218 install_element(VIEW_NODE,
15219 &show_ip_bgp_instance_neighbor_bestpath_route_cmd);
15220 install_element(VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd);
15221 install_element(VIEW_NODE,
15222 &show_ip_bgp_neighbor_received_prefix_filter_cmd);
15223 #ifdef KEEP_OLD_VPN_COMMANDS
15224 install_element(VIEW_NODE, &show_ip_bgp_vpn_all_route_prefix_cmd);
15225 #endif /* KEEP_OLD_VPN_COMMANDS */
15226 install_element(VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd);
15227 install_element(VIEW_NODE,
15228 &show_bgp_l2vpn_evpn_route_prefix_cmd);
15229
15230 /* BGP dampening clear commands */
15231 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
15232 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_prefix_cmd);
15233
15234 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd);
15235 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd);
15236
15237 /* prefix count */
15238 install_element(ENABLE_NODE,
15239 &show_ip_bgp_instance_neighbor_prefix_counts_cmd);
15240 #ifdef KEEP_OLD_VPN_COMMANDS
15241 install_element(ENABLE_NODE,
15242 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd);
15243 #endif /* KEEP_OLD_VPN_COMMANDS */
15244
15245 /* New config IPv6 BGP commands. */
15246 install_element(BGP_IPV6_NODE, &bgp_table_map_cmd);
15247 install_element(BGP_IPV6_NODE, &ipv6_bgp_network_cmd);
15248 install_element(BGP_IPV6_NODE, &no_bgp_table_map_cmd);
15249
15250 install_element(BGP_IPV6_NODE, &aggregate_addressv6_cmd);
15251
15252 install_element(BGP_IPV6M_NODE, &ipv6_bgp_network_cmd);
15253
15254 /* IPv6 labeled unicast address family. */
15255 install_element(BGP_IPV6L_NODE, &ipv6_bgp_network_cmd);
15256 install_element(BGP_IPV6L_NODE, &aggregate_addressv6_cmd);
15257
15258 install_element(BGP_NODE, &bgp_distance_cmd);
15259 install_element(BGP_NODE, &no_bgp_distance_cmd);
15260 install_element(BGP_NODE, &bgp_distance_source_cmd);
15261 install_element(BGP_IPV4_NODE, &bgp_distance_cmd);
15262 install_element(BGP_IPV4_NODE, &no_bgp_distance_cmd);
15263 install_element(BGP_IPV4_NODE, &bgp_distance_source_cmd);
15264 install_element(BGP_IPV4M_NODE, &bgp_distance_cmd);
15265 install_element(BGP_IPV4M_NODE, &no_bgp_distance_cmd);
15266 install_element(BGP_IPV4M_NODE, &bgp_distance_source_cmd);
15267 install_element(BGP_IPV6_NODE, &bgp_distance_cmd);
15268 install_element(BGP_IPV6_NODE, &no_bgp_distance_cmd);
15269 install_element(BGP_IPV6_NODE, &bgp_distance_source_cmd);
15270 install_element(BGP_IPV6M_NODE, &bgp_distance_cmd);
15271 install_element(BGP_IPV6M_NODE, &no_bgp_distance_cmd);
15272 install_element(BGP_IPV6M_NODE, &bgp_distance_source_cmd);
15273
15274 /* BGP dampening */
15275 install_element(BGP_NODE, &bgp_dampening_cmd);
15276 install_element(BGP_IPV4_NODE, &bgp_dampening_cmd);
15277 install_element(BGP_IPV4M_NODE, &bgp_dampening_cmd);
15278 install_element(BGP_IPV4L_NODE, &bgp_dampening_cmd);
15279 install_element(BGP_IPV6_NODE, &bgp_dampening_cmd);
15280 install_element(BGP_IPV6M_NODE, &bgp_dampening_cmd);
15281 install_element(BGP_IPV6L_NODE, &bgp_dampening_cmd);
15282
15283 /* Large Communities */
15284 install_element(VIEW_NODE, &show_ip_bgp_large_community_list_cmd);
15285 install_element(VIEW_NODE, &show_ip_bgp_large_community_cmd);
15286
15287 /* show bgp ipv4 flowspec detailed */
15288 install_element(VIEW_NODE, &show_ip_bgp_flowspec_routes_detailed_cmd);
15289
15290 install_element(VIEW_NODE, &show_bgp_listeners_cmd);
15291 install_element(VIEW_NODE, &show_bgp_peerhash_cmd);
15292 }
15293
15294 void bgp_route_finish(void)
15295 {
15296 afi_t afi;
15297 safi_t safi;
15298
15299 FOREACH_AFI_SAFI (afi, safi) {
15300 bgp_table_unlock(bgp_distance_table[afi][safi]);
15301 bgp_distance_table[afi][safi] = NULL;
15302 }
15303 }