]> git.proxmox.com Git - mirror_frr.git/blob - bgpd/bgp_route.c
Merge pull request #8196 from ton31337/feature/rfc8654_bgpd
[mirror_frr.git] / bgpd / bgp_route.c
1 /* BGP routing information
2 * Copyright (C) 1996, 97, 98, 99 Kunihiro Ishiguro
3 * Copyright (C) 2016 Job Snijders <job@instituut.net>
4 *
5 * This file is part of GNU Zebra.
6 *
7 * GNU Zebra is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
10 * later version.
11 *
12 * GNU Zebra is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; see the file COPYING; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22 #include <zebra.h>
23 #include <math.h>
24
25 #include "printfrr.h"
26 #include "prefix.h"
27 #include "linklist.h"
28 #include "memory.h"
29 #include "command.h"
30 #include "stream.h"
31 #include "filter.h"
32 #include "log.h"
33 #include "routemap.h"
34 #include "buffer.h"
35 #include "sockunion.h"
36 #include "plist.h"
37 #include "thread.h"
38 #include "workqueue.h"
39 #include "queue.h"
40 #include "memory.h"
41 #include "srv6.h"
42 #include "lib/json.h"
43 #include "lib_errors.h"
44 #include "zclient.h"
45 #include "bgpd/bgpd.h"
46 #include "bgpd/bgp_table.h"
47 #include "bgpd/bgp_route.h"
48 #include "bgpd/bgp_attr.h"
49 #include "bgpd/bgp_debug.h"
50 #include "bgpd/bgp_errors.h"
51 #include "bgpd/bgp_aspath.h"
52 #include "bgpd/bgp_regex.h"
53 #include "bgpd/bgp_community.h"
54 #include "bgpd/bgp_ecommunity.h"
55 #include "bgpd/bgp_lcommunity.h"
56 #include "bgpd/bgp_clist.h"
57 #include "bgpd/bgp_packet.h"
58 #include "bgpd/bgp_filter.h"
59 #include "bgpd/bgp_fsm.h"
60 #include "bgpd/bgp_mplsvpn.h"
61 #include "bgpd/bgp_nexthop.h"
62 #include "bgpd/bgp_damp.h"
63 #include "bgpd/bgp_advertise.h"
64 #include "bgpd/bgp_zebra.h"
65 #include "bgpd/bgp_vty.h"
66 #include "bgpd/bgp_mpath.h"
67 #include "bgpd/bgp_nht.h"
68 #include "bgpd/bgp_updgrp.h"
69 #include "bgpd/bgp_label.h"
70 #include "bgpd/bgp_addpath.h"
71 #include "bgpd/bgp_mac.h"
72 #include "bgpd/bgp_network.h"
73 #include "bgpd/bgp_trace.h"
74
75 #ifdef ENABLE_BGP_VNC
76 #include "bgpd/rfapi/rfapi_backend.h"
77 #include "bgpd/rfapi/vnc_import_bgp.h"
78 #include "bgpd/rfapi/vnc_export_bgp.h"
79 #endif
80 #include "bgpd/bgp_encap_types.h"
81 #include "bgpd/bgp_encap_tlv.h"
82 #include "bgpd/bgp_evpn.h"
83 #include "bgpd/bgp_evpn_mh.h"
84 #include "bgpd/bgp_evpn_vty.h"
85 #include "bgpd/bgp_flowspec.h"
86 #include "bgpd/bgp_flowspec_util.h"
87 #include "bgpd/bgp_pbr.h"
88 #include "northbound.h"
89 #include "northbound_cli.h"
90 #include "bgpd/bgp_nb.h"
91
92 #ifndef VTYSH_EXTRACT_PL
93 #include "bgpd/bgp_route_clippy.c"
94 #endif
95
96 DEFINE_HOOK(bgp_snmp_update_stats,
97 (struct bgp_node *rn, struct bgp_path_info *pi, bool added),
98 (rn, pi, added))
99
100 /* Extern from bgp_dump.c */
101 extern const char *bgp_origin_str[];
102 extern const char *bgp_origin_long_str[];
103
104 /* PMSI strings. */
105 #define PMSI_TNLTYPE_STR_NO_INFO "No info"
106 #define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
107 static const struct message bgp_pmsi_tnltype_str[] = {
108 {PMSI_TNLTYPE_NO_INFO, PMSI_TNLTYPE_STR_NO_INFO},
109 {PMSI_TNLTYPE_RSVP_TE_P2MP, "RSVP-TE P2MP"},
110 {PMSI_TNLTYPE_MLDP_P2MP, "mLDP P2MP"},
111 {PMSI_TNLTYPE_PIM_SSM, "PIM-SSM"},
112 {PMSI_TNLTYPE_PIM_SM, "PIM-SM"},
113 {PMSI_TNLTYPE_PIM_BIDIR, "PIM-BIDIR"},
114 {PMSI_TNLTYPE_INGR_REPL, "Ingress Replication"},
115 {PMSI_TNLTYPE_MLDP_MP2MP, "mLDP MP2MP"},
116 {0}
117 };
118
119 #define VRFID_NONE_STR "-"
120
121 DEFINE_HOOK(bgp_process,
122 (struct bgp * bgp, afi_t afi, safi_t safi, struct bgp_dest *bn,
123 struct peer *peer, bool withdraw),
124 (bgp, afi, safi, bn, peer, withdraw))
125
126 /** Test if path is suppressed. */
127 static bool bgp_path_suppressed(struct bgp_path_info *pi)
128 {
129 if (pi->extra == NULL || pi->extra->aggr_suppressors == NULL)
130 return false;
131
132 return listcount(pi->extra->aggr_suppressors) > 0;
133 }
134
135 struct bgp_dest *bgp_afi_node_get(struct bgp_table *table, afi_t afi,
136 safi_t safi, const struct prefix *p,
137 struct prefix_rd *prd)
138 {
139 struct bgp_dest *dest;
140 struct bgp_dest *pdest = NULL;
141
142 assert(table);
143
144 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
145 || (safi == SAFI_EVPN)) {
146 pdest = bgp_node_get(table, (struct prefix *)prd);
147
148 if (!bgp_dest_has_bgp_path_info_data(pdest))
149 bgp_dest_set_bgp_table_info(
150 pdest, bgp_table_init(table->bgp, afi, safi));
151 else
152 bgp_dest_unlock_node(pdest);
153 table = bgp_dest_get_bgp_table_info(pdest);
154 }
155
156 dest = bgp_node_get(table, p);
157
158 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
159 || (safi == SAFI_EVPN))
160 dest->pdest = pdest;
161
162 return dest;
163 }
164
165 struct bgp_dest *bgp_afi_node_lookup(struct bgp_table *table, afi_t afi,
166 safi_t safi, const struct prefix *p,
167 struct prefix_rd *prd)
168 {
169 struct bgp_dest *dest;
170 struct bgp_dest *pdest = NULL;
171
172 if (!table)
173 return NULL;
174
175 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
176 || (safi == SAFI_EVPN)) {
177 pdest = bgp_node_lookup(table, (struct prefix *)prd);
178 if (!pdest)
179 return NULL;
180
181 if (!bgp_dest_has_bgp_path_info_data(pdest)) {
182 bgp_dest_unlock_node(pdest);
183 return NULL;
184 }
185
186 table = bgp_dest_get_bgp_table_info(pdest);
187 }
188
189 dest = bgp_node_lookup(table, p);
190
191 return dest;
192 }
193
194 /* Allocate bgp_path_info_extra */
195 static struct bgp_path_info_extra *bgp_path_info_extra_new(void)
196 {
197 struct bgp_path_info_extra *new;
198 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA,
199 sizeof(struct bgp_path_info_extra));
200 new->label[0] = MPLS_INVALID_LABEL;
201 new->num_labels = 0;
202 new->bgp_fs_pbr = NULL;
203 new->bgp_fs_iprule = NULL;
204 return new;
205 }
206
207 void bgp_path_info_extra_free(struct bgp_path_info_extra **extra)
208 {
209 struct bgp_path_info_extra *e;
210
211 if (!extra || !*extra)
212 return;
213
214 e = *extra;
215
216 e->damp_info = NULL;
217 if (e->parent) {
218 struct bgp_path_info *bpi = (struct bgp_path_info *)e->parent;
219
220 if (bpi->net) {
221 /* FIXME: since multiple e may have the same e->parent
222 * and e->parent->net is holding a refcount for each
223 * of them, we need to do some fudging here.
224 *
225 * WARNING: if bpi->net->lock drops to 0, bpi may be
226 * freed as well (because bpi->net was holding the
227 * last reference to bpi) => write after free!
228 */
229 unsigned refcount;
230
231 bpi = bgp_path_info_lock(bpi);
232 refcount = bgp_dest_get_lock_count(bpi->net) - 1;
233 bgp_dest_unlock_node((struct bgp_dest *)bpi->net);
234 if (!refcount)
235 bpi->net = NULL;
236 bgp_path_info_unlock(bpi);
237 }
238 bgp_path_info_unlock(e->parent);
239 e->parent = NULL;
240 }
241
242 if (e->bgp_orig)
243 bgp_unlock(e->bgp_orig);
244
245 if (e->aggr_suppressors)
246 list_delete(&e->aggr_suppressors);
247
248 if (e->es_info)
249 bgp_evpn_path_es_info_free(e->es_info);
250
251 if ((*extra)->bgp_fs_iprule)
252 list_delete(&((*extra)->bgp_fs_iprule));
253 if ((*extra)->bgp_fs_pbr)
254 list_delete(&((*extra)->bgp_fs_pbr));
255 XFREE(MTYPE_BGP_ROUTE_EXTRA, *extra);
256 }
257
258 /* Get bgp_path_info extra information for the given bgp_path_info, lazy
259 * allocated if required.
260 */
261 struct bgp_path_info_extra *bgp_path_info_extra_get(struct bgp_path_info *pi)
262 {
263 if (!pi->extra)
264 pi->extra = bgp_path_info_extra_new();
265 return pi->extra;
266 }
267
268 /* Free bgp route information. */
269 static void bgp_path_info_free(struct bgp_path_info *path)
270 {
271 bgp_attr_unintern(&path->attr);
272
273 bgp_unlink_nexthop(path);
274 bgp_path_info_extra_free(&path->extra);
275 bgp_path_info_mpath_free(&path->mpath);
276 if (path->net)
277 bgp_addpath_free_info_data(&path->tx_addpath,
278 &path->net->tx_addpath);
279
280 peer_unlock(path->peer); /* bgp_path_info peer reference */
281
282 XFREE(MTYPE_BGP_ROUTE, path);
283 }
284
285 struct bgp_path_info *bgp_path_info_lock(struct bgp_path_info *path)
286 {
287 path->lock++;
288 return path;
289 }
290
291 struct bgp_path_info *bgp_path_info_unlock(struct bgp_path_info *path)
292 {
293 assert(path && path->lock > 0);
294 path->lock--;
295
296 if (path->lock == 0) {
297 #if 0
298 zlog_debug ("%s: unlocked and freeing", __func__);
299 zlog_backtrace (LOG_DEBUG);
300 #endif
301 bgp_path_info_free(path);
302 return NULL;
303 }
304
305 #if 0
306 if (path->lock == 1)
307 {
308 zlog_debug ("%s: unlocked to 1", __func__);
309 zlog_backtrace (LOG_DEBUG);
310 }
311 #endif
312
313 return path;
314 }
315
316 /* This function sets flag BGP_NODE_SELECT_DEFER based on condition */
317 static int bgp_dest_set_defer_flag(struct bgp_dest *dest, bool delete)
318 {
319 struct peer *peer;
320 struct bgp_path_info *old_pi, *nextpi;
321 bool set_flag = false;
322 struct bgp *bgp = NULL;
323 struct bgp_table *table = NULL;
324 afi_t afi = 0;
325 safi_t safi = 0;
326
327 /* If the flag BGP_NODE_SELECT_DEFER is set and new path is added
328 * then the route selection is deferred
329 */
330 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER) && (!delete))
331 return 0;
332
333 if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED)) {
334 if (BGP_DEBUG(update, UPDATE_OUT))
335 zlog_debug(
336 "Route %pBD is in workqueue and being processed, not deferred.",
337 dest);
338
339 return 0;
340 }
341
342 table = bgp_dest_table(dest);
343 if (table) {
344 bgp = table->bgp;
345 afi = table->afi;
346 safi = table->safi;
347 }
348
349 for (old_pi = bgp_dest_get_bgp_path_info(dest);
350 (old_pi != NULL) && (nextpi = old_pi->next, 1); old_pi = nextpi) {
351 if (CHECK_FLAG(old_pi->flags, BGP_PATH_SELECTED))
352 continue;
353
354 /* Route selection is deferred if there is a stale path which
355 * which indicates peer is in restart mode
356 */
357 if (CHECK_FLAG(old_pi->flags, BGP_PATH_STALE)
358 && (old_pi->sub_type == BGP_ROUTE_NORMAL)) {
359 set_flag = true;
360 } else {
361 /* If the peer is graceful restart capable and peer is
362 * restarting mode, set the flag BGP_NODE_SELECT_DEFER
363 */
364 peer = old_pi->peer;
365 if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer)
366 && BGP_PEER_RESTARTING_MODE(peer)
367 && (old_pi
368 && old_pi->sub_type == BGP_ROUTE_NORMAL)) {
369 set_flag = true;
370 }
371 }
372 if (set_flag)
373 break;
374 }
375
376 /* Set the flag BGP_NODE_SELECT_DEFER if route selection deferral timer
377 * is active
378 */
379 if (set_flag && table) {
380 if (bgp && (bgp->gr_info[afi][safi].t_select_deferral)) {
381 if (!CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER))
382 bgp->gr_info[afi][safi].gr_deferred++;
383 SET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
384 if (BGP_DEBUG(update, UPDATE_OUT))
385 zlog_debug("DEFER route %pBD, dest %p", dest,
386 dest);
387 return 0;
388 }
389 }
390 return -1;
391 }
392
393 void bgp_path_info_add(struct bgp_dest *dest, struct bgp_path_info *pi)
394 {
395 struct bgp_path_info *top;
396
397 top = bgp_dest_get_bgp_path_info(dest);
398
399 pi->next = top;
400 pi->prev = NULL;
401 if (top)
402 top->prev = pi;
403 bgp_dest_set_bgp_path_info(dest, pi);
404
405 bgp_path_info_lock(pi);
406 bgp_dest_lock_node(dest);
407 peer_lock(pi->peer); /* bgp_path_info peer reference */
408 bgp_dest_set_defer_flag(dest, false);
409 hook_call(bgp_snmp_update_stats, dest, pi, true);
410 }
411
412 /* Do the actual removal of info from RIB, for use by bgp_process
413 completion callback *only* */
414 void bgp_path_info_reap(struct bgp_dest *dest, struct bgp_path_info *pi)
415 {
416 if (pi->next)
417 pi->next->prev = pi->prev;
418 if (pi->prev)
419 pi->prev->next = pi->next;
420 else
421 bgp_dest_set_bgp_path_info(dest, pi->next);
422
423 bgp_path_info_mpath_dequeue(pi);
424 bgp_path_info_unlock(pi);
425 hook_call(bgp_snmp_update_stats, dest, pi, false);
426 bgp_dest_unlock_node(dest);
427 }
428
429 void bgp_path_info_delete(struct bgp_dest *dest, struct bgp_path_info *pi)
430 {
431 bgp_path_info_set_flag(dest, pi, BGP_PATH_REMOVED);
432 /* set of previous already took care of pcount */
433 UNSET_FLAG(pi->flags, BGP_PATH_VALID);
434 }
435
436 /* undo the effects of a previous call to bgp_path_info_delete; typically
437 called when a route is deleted and then quickly re-added before the
438 deletion has been processed */
439 void bgp_path_info_restore(struct bgp_dest *dest, struct bgp_path_info *pi)
440 {
441 bgp_path_info_unset_flag(dest, pi, BGP_PATH_REMOVED);
442 /* unset of previous already took care of pcount */
443 SET_FLAG(pi->flags, BGP_PATH_VALID);
444 }
445
446 /* Adjust pcount as required */
447 static void bgp_pcount_adjust(struct bgp_dest *dest, struct bgp_path_info *pi)
448 {
449 struct bgp_table *table;
450
451 assert(dest && bgp_dest_table(dest));
452 assert(pi && pi->peer && pi->peer->bgp);
453
454 table = bgp_dest_table(dest);
455
456 if (pi->peer == pi->peer->bgp->peer_self)
457 return;
458
459 if (!BGP_PATH_COUNTABLE(pi)
460 && CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
461
462 UNSET_FLAG(pi->flags, BGP_PATH_COUNTED);
463
464 /* slight hack, but more robust against errors. */
465 if (pi->peer->pcount[table->afi][table->safi])
466 pi->peer->pcount[table->afi][table->safi]--;
467 else
468 flog_err(EC_LIB_DEVELOPMENT,
469 "Asked to decrement 0 prefix count for peer");
470 } else if (BGP_PATH_COUNTABLE(pi)
471 && !CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
472 SET_FLAG(pi->flags, BGP_PATH_COUNTED);
473 pi->peer->pcount[table->afi][table->safi]++;
474 }
475 }
476
477 static int bgp_label_index_differs(struct bgp_path_info *pi1,
478 struct bgp_path_info *pi2)
479 {
480 return (!(pi1->attr->label_index == pi2->attr->label_index));
481 }
482
483 /* Set/unset bgp_path_info flags, adjusting any other state as needed.
484 * This is here primarily to keep prefix-count in check.
485 */
486 void bgp_path_info_set_flag(struct bgp_dest *dest, struct bgp_path_info *pi,
487 uint32_t flag)
488 {
489 SET_FLAG(pi->flags, flag);
490
491 /* early bath if we know it's not a flag that changes countability state
492 */
493 if (!CHECK_FLAG(flag,
494 BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
495 return;
496
497 bgp_pcount_adjust(dest, pi);
498 }
499
500 void bgp_path_info_unset_flag(struct bgp_dest *dest, struct bgp_path_info *pi,
501 uint32_t flag)
502 {
503 UNSET_FLAG(pi->flags, flag);
504
505 /* early bath if we know it's not a flag that changes countability state
506 */
507 if (!CHECK_FLAG(flag,
508 BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
509 return;
510
511 bgp_pcount_adjust(dest, pi);
512 }
513
514 /* Get MED value. If MED value is missing and "bgp bestpath
515 missing-as-worst" is specified, treat it as the worst value. */
516 static uint32_t bgp_med_value(struct attr *attr, struct bgp *bgp)
517 {
518 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
519 return attr->med;
520 else {
521 if (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_MISSING_AS_WORST))
522 return BGP_MED_MAX;
523 else
524 return 0;
525 }
526 }
527
528 void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info *pi, char *buf,
529 size_t buf_len)
530 {
531 if (pi->addpath_rx_id)
532 snprintf(buf, buf_len, "path %s (addpath rxid %d)",
533 pi->peer->host, pi->addpath_rx_id);
534 else
535 snprintf(buf, buf_len, "path %s", pi->peer->host);
536 }
537
538 /* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
539 */
540 static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
541 struct bgp_path_info *exist, int *paths_eq,
542 struct bgp_maxpaths_cfg *mpath_cfg, int debug,
543 char *pfx_buf, afi_t afi, safi_t safi,
544 enum bgp_path_selection_reason *reason)
545 {
546 struct attr *newattr, *existattr;
547 bgp_peer_sort_t new_sort;
548 bgp_peer_sort_t exist_sort;
549 uint32_t new_pref;
550 uint32_t exist_pref;
551 uint32_t new_med;
552 uint32_t exist_med;
553 uint32_t new_weight;
554 uint32_t exist_weight;
555 uint32_t newm, existm;
556 struct in_addr new_id;
557 struct in_addr exist_id;
558 int new_cluster;
559 int exist_cluster;
560 int internal_as_route;
561 int confed_as_route;
562 int ret = 0;
563 char new_buf[PATH_ADDPATH_STR_BUFFER];
564 char exist_buf[PATH_ADDPATH_STR_BUFFER];
565 uint32_t new_mm_seq;
566 uint32_t exist_mm_seq;
567 int nh_cmp;
568 esi_t *exist_esi;
569 esi_t *new_esi;
570 bool same_esi;
571 bool old_proxy;
572 bool new_proxy;
573 bool new_origin, exist_origin;
574
575 *paths_eq = 0;
576
577 /* 0. Null check. */
578 if (new == NULL) {
579 *reason = bgp_path_selection_none;
580 if (debug)
581 zlog_debug("%s: new is NULL", pfx_buf);
582 return 0;
583 }
584
585 if (debug)
586 bgp_path_info_path_with_addpath_rx_str(new, new_buf,
587 sizeof(new_buf));
588
589 if (exist == NULL) {
590 *reason = bgp_path_selection_first;
591 if (debug)
592 zlog_debug("%s: %s is the initial bestpath", pfx_buf,
593 new_buf);
594 return 1;
595 }
596
597 if (debug) {
598 bgp_path_info_path_with_addpath_rx_str(exist, exist_buf,
599 sizeof(exist_buf));
600 zlog_debug("%s: Comparing %s flags 0x%x with %s flags 0x%x",
601 pfx_buf, new_buf, new->flags, exist_buf,
602 exist->flags);
603 }
604
605 newattr = new->attr;
606 existattr = exist->attr;
607
608 /* For EVPN routes, we cannot just go by local vs remote, we have to
609 * look at the MAC mobility sequence number, if present.
610 */
611 if (safi == SAFI_EVPN) {
612 /* This is an error condition described in RFC 7432 Section
613 * 15.2. The RFC
614 * states that in this scenario "the PE MUST alert the operator"
615 * but it
616 * does not state what other action to take. In order to provide
617 * some
618 * consistency in this scenario we are going to prefer the path
619 * with the
620 * sticky flag.
621 */
622 if (newattr->sticky != existattr->sticky) {
623 if (!debug) {
624 prefix2str(
625 bgp_dest_get_prefix(new->net), pfx_buf,
626 sizeof(*pfx_buf) * PREFIX2STR_BUFFER);
627 bgp_path_info_path_with_addpath_rx_str(
628 new, new_buf, sizeof(new_buf));
629 bgp_path_info_path_with_addpath_rx_str(
630 exist, exist_buf, sizeof(exist_buf));
631 }
632
633 if (newattr->sticky && !existattr->sticky) {
634 *reason = bgp_path_selection_evpn_sticky_mac;
635 if (debug)
636 zlog_debug(
637 "%s: %s wins over %s due to sticky MAC flag",
638 pfx_buf, new_buf, exist_buf);
639 return 1;
640 }
641
642 if (!newattr->sticky && existattr->sticky) {
643 *reason = bgp_path_selection_evpn_sticky_mac;
644 if (debug)
645 zlog_debug(
646 "%s: %s loses to %s due to sticky MAC flag",
647 pfx_buf, new_buf, exist_buf);
648 return 0;
649 }
650 }
651
652 new_esi = bgp_evpn_attr_get_esi(newattr);
653 exist_esi = bgp_evpn_attr_get_esi(existattr);
654 if (bgp_evpn_is_esi_valid(new_esi) &&
655 !memcmp(new_esi, exist_esi, sizeof(esi_t))) {
656 same_esi = true;
657 } else {
658 same_esi = false;
659 }
660
661 /* If both paths have the same non-zero ES and
662 * one path is local it wins.
663 * PS: Note the local path wins even if the remote
664 * has the higher MM seq. The local path's
665 * MM seq will be fixed up to match the highest
666 * rem seq, subsequently.
667 */
668 if (same_esi) {
669 char esi_buf[ESI_STR_LEN];
670
671 if (bgp_evpn_is_path_local(bgp, new)) {
672 *reason = bgp_path_selection_evpn_local_path;
673 if (debug)
674 zlog_debug(
675 "%s: %s wins over %s as ES %s is same and local",
676 pfx_buf, new_buf, exist_buf,
677 esi_to_str(new_esi, esi_buf,
678 sizeof(esi_buf)));
679 return 1;
680 }
681 if (bgp_evpn_is_path_local(bgp, exist)) {
682 *reason = bgp_path_selection_evpn_local_path;
683 if (debug)
684 zlog_debug(
685 "%s: %s loses to %s as ES %s is same and local",
686 pfx_buf, new_buf, exist_buf,
687 esi_to_str(new_esi, esi_buf,
688 sizeof(esi_buf)));
689 return 0;
690 }
691 }
692
693 new_mm_seq = mac_mobility_seqnum(newattr);
694 exist_mm_seq = mac_mobility_seqnum(existattr);
695
696 if (new_mm_seq > exist_mm_seq) {
697 *reason = bgp_path_selection_evpn_seq;
698 if (debug)
699 zlog_debug(
700 "%s: %s wins over %s due to MM seq %u > %u",
701 pfx_buf, new_buf, exist_buf, new_mm_seq,
702 exist_mm_seq);
703 return 1;
704 }
705
706 if (new_mm_seq < exist_mm_seq) {
707 *reason = bgp_path_selection_evpn_seq;
708 if (debug)
709 zlog_debug(
710 "%s: %s loses to %s due to MM seq %u < %u",
711 pfx_buf, new_buf, exist_buf, new_mm_seq,
712 exist_mm_seq);
713 return 0;
714 }
715
716 /* if the sequence numbers and ESI are the same and one path
717 * is non-proxy it wins (over proxy)
718 */
719 new_proxy = bgp_evpn_attr_is_proxy(newattr);
720 old_proxy = bgp_evpn_attr_is_proxy(existattr);
721 if (same_esi && bgp_evpn_attr_is_local_es(newattr) &&
722 old_proxy != new_proxy) {
723 if (!new_proxy) {
724 *reason = bgp_path_selection_evpn_non_proxy;
725 if (debug)
726 zlog_debug(
727 "%s: %s wins over %s, same seq/es and non-proxy",
728 pfx_buf, new_buf, exist_buf);
729 return 1;
730 }
731
732 *reason = bgp_path_selection_evpn_non_proxy;
733 if (debug)
734 zlog_debug(
735 "%s: %s loses to %s, same seq/es and non-proxy",
736 pfx_buf, new_buf, exist_buf);
737 return 0;
738 }
739
740 /*
741 * if sequence numbers are the same path with the lowest IP
742 * wins
743 */
744 nh_cmp = bgp_path_info_nexthop_cmp(new, exist);
745 if (nh_cmp < 0) {
746 *reason = bgp_path_selection_evpn_lower_ip;
747 if (debug)
748 zlog_debug(
749 "%s: %s wins over %s due to same MM seq %u and lower IP %pI4",
750 pfx_buf, new_buf, exist_buf, new_mm_seq,
751 &new->attr->nexthop);
752 return 1;
753 }
754 if (nh_cmp > 0) {
755 *reason = bgp_path_selection_evpn_lower_ip;
756 if (debug)
757 zlog_debug(
758 "%s: %s loses to %s due to same MM seq %u and higher IP %pI4",
759 pfx_buf, new_buf, exist_buf, new_mm_seq,
760 &new->attr->nexthop);
761 return 0;
762 }
763 }
764
765 /* 1. Weight check. */
766 new_weight = newattr->weight;
767 exist_weight = existattr->weight;
768
769 if (new_weight > exist_weight) {
770 *reason = bgp_path_selection_weight;
771 if (debug)
772 zlog_debug("%s: %s wins over %s due to weight %d > %d",
773 pfx_buf, new_buf, exist_buf, new_weight,
774 exist_weight);
775 return 1;
776 }
777
778 if (new_weight < exist_weight) {
779 *reason = bgp_path_selection_weight;
780 if (debug)
781 zlog_debug("%s: %s loses to %s due to weight %d < %d",
782 pfx_buf, new_buf, exist_buf, new_weight,
783 exist_weight);
784 return 0;
785 }
786
787 /* 2. Local preference check. */
788 new_pref = exist_pref = bgp->default_local_pref;
789
790 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
791 new_pref = newattr->local_pref;
792 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
793 exist_pref = existattr->local_pref;
794
795 if (new_pref > exist_pref) {
796 *reason = bgp_path_selection_local_pref;
797 if (debug)
798 zlog_debug(
799 "%s: %s wins over %s due to localpref %d > %d",
800 pfx_buf, new_buf, exist_buf, new_pref,
801 exist_pref);
802 return 1;
803 }
804
805 if (new_pref < exist_pref) {
806 *reason = bgp_path_selection_local_pref;
807 if (debug)
808 zlog_debug(
809 "%s: %s loses to %s due to localpref %d < %d",
810 pfx_buf, new_buf, exist_buf, new_pref,
811 exist_pref);
812 return 0;
813 }
814
815 /* 3. Local route check. We prefer:
816 * - BGP_ROUTE_STATIC
817 * - BGP_ROUTE_AGGREGATE
818 * - BGP_ROUTE_REDISTRIBUTE
819 */
820 new_origin = !(new->sub_type == BGP_ROUTE_NORMAL ||
821 new->sub_type == BGP_ROUTE_IMPORTED);
822 exist_origin = !(exist->sub_type == BGP_ROUTE_NORMAL ||
823 exist->sub_type == BGP_ROUTE_IMPORTED);
824
825 if (new_origin && !exist_origin) {
826 *reason = bgp_path_selection_local_route;
827 if (debug)
828 zlog_debug(
829 "%s: %s wins over %s due to preferred BGP_ROUTE type",
830 pfx_buf, new_buf, exist_buf);
831 return 1;
832 }
833
834 if (!new_origin && exist_origin) {
835 *reason = bgp_path_selection_local_route;
836 if (debug)
837 zlog_debug(
838 "%s: %s loses to %s due to preferred BGP_ROUTE type",
839 pfx_buf, new_buf, exist_buf);
840 return 0;
841 }
842
843 /* 4. AS path length check. */
844 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_IGNORE)) {
845 int exist_hops = aspath_count_hops(existattr->aspath);
846 int exist_confeds = aspath_count_confeds(existattr->aspath);
847
848 if (CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_CONFED)) {
849 int aspath_hops;
850
851 aspath_hops = aspath_count_hops(newattr->aspath);
852 aspath_hops += aspath_count_confeds(newattr->aspath);
853
854 if (aspath_hops < (exist_hops + exist_confeds)) {
855 *reason = bgp_path_selection_confed_as_path;
856 if (debug)
857 zlog_debug(
858 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
859 pfx_buf, new_buf, exist_buf,
860 aspath_hops,
861 (exist_hops + exist_confeds));
862 return 1;
863 }
864
865 if (aspath_hops > (exist_hops + exist_confeds)) {
866 *reason = bgp_path_selection_confed_as_path;
867 if (debug)
868 zlog_debug(
869 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
870 pfx_buf, new_buf, exist_buf,
871 aspath_hops,
872 (exist_hops + exist_confeds));
873 return 0;
874 }
875 } else {
876 int newhops = aspath_count_hops(newattr->aspath);
877
878 if (newhops < exist_hops) {
879 *reason = bgp_path_selection_as_path;
880 if (debug)
881 zlog_debug(
882 "%s: %s wins over %s due to aspath hopcount %d < %d",
883 pfx_buf, new_buf, exist_buf,
884 newhops, exist_hops);
885 return 1;
886 }
887
888 if (newhops > exist_hops) {
889 *reason = bgp_path_selection_as_path;
890 if (debug)
891 zlog_debug(
892 "%s: %s loses to %s due to aspath hopcount %d > %d",
893 pfx_buf, new_buf, exist_buf,
894 newhops, exist_hops);
895 return 0;
896 }
897 }
898 }
899
900 /* 5. Origin check. */
901 if (newattr->origin < existattr->origin) {
902 *reason = bgp_path_selection_origin;
903 if (debug)
904 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
905 pfx_buf, new_buf, exist_buf,
906 bgp_origin_long_str[newattr->origin],
907 bgp_origin_long_str[existattr->origin]);
908 return 1;
909 }
910
911 if (newattr->origin > existattr->origin) {
912 *reason = bgp_path_selection_origin;
913 if (debug)
914 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
915 pfx_buf, new_buf, exist_buf,
916 bgp_origin_long_str[newattr->origin],
917 bgp_origin_long_str[existattr->origin]);
918 return 0;
919 }
920
921 /* 6. MED check. */
922 internal_as_route = (aspath_count_hops(newattr->aspath) == 0
923 && aspath_count_hops(existattr->aspath) == 0);
924 confed_as_route = (aspath_count_confeds(newattr->aspath) > 0
925 && aspath_count_confeds(existattr->aspath) > 0
926 && aspath_count_hops(newattr->aspath) == 0
927 && aspath_count_hops(existattr->aspath) == 0);
928
929 if (CHECK_FLAG(bgp->flags, BGP_FLAG_ALWAYS_COMPARE_MED)
930 || (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_CONFED) && confed_as_route)
931 || aspath_cmp_left(newattr->aspath, existattr->aspath)
932 || aspath_cmp_left_confed(newattr->aspath, existattr->aspath)
933 || internal_as_route) {
934 new_med = bgp_med_value(new->attr, bgp);
935 exist_med = bgp_med_value(exist->attr, bgp);
936
937 if (new_med < exist_med) {
938 *reason = bgp_path_selection_med;
939 if (debug)
940 zlog_debug(
941 "%s: %s wins over %s due to MED %d < %d",
942 pfx_buf, new_buf, exist_buf, new_med,
943 exist_med);
944 return 1;
945 }
946
947 if (new_med > exist_med) {
948 *reason = bgp_path_selection_med;
949 if (debug)
950 zlog_debug(
951 "%s: %s loses to %s due to MED %d > %d",
952 pfx_buf, new_buf, exist_buf, new_med,
953 exist_med);
954 return 0;
955 }
956 }
957
958 /* 7. Peer type check. */
959 new_sort = new->peer->sort;
960 exist_sort = exist->peer->sort;
961
962 if (new_sort == BGP_PEER_EBGP
963 && (exist_sort == BGP_PEER_IBGP || exist_sort == BGP_PEER_CONFED)) {
964 *reason = bgp_path_selection_peer;
965 if (debug)
966 zlog_debug(
967 "%s: %s wins over %s due to eBGP peer > iBGP peer",
968 pfx_buf, new_buf, exist_buf);
969 return 1;
970 }
971
972 if (exist_sort == BGP_PEER_EBGP
973 && (new_sort == BGP_PEER_IBGP || new_sort == BGP_PEER_CONFED)) {
974 *reason = bgp_path_selection_peer;
975 if (debug)
976 zlog_debug(
977 "%s: %s loses to %s due to iBGP peer < eBGP peer",
978 pfx_buf, new_buf, exist_buf);
979 return 0;
980 }
981
982 /* 8. IGP metric check. */
983 newm = existm = 0;
984
985 if (new->extra)
986 newm = new->extra->igpmetric;
987 if (exist->extra)
988 existm = exist->extra->igpmetric;
989
990 if (newm < existm) {
991 if (debug)
992 zlog_debug(
993 "%s: %s wins over %s due to IGP metric %d < %d",
994 pfx_buf, new_buf, exist_buf, newm, existm);
995 ret = 1;
996 }
997
998 if (newm > existm) {
999 if (debug)
1000 zlog_debug(
1001 "%s: %s loses to %s due to IGP metric %d > %d",
1002 pfx_buf, new_buf, exist_buf, newm, existm);
1003 ret = 0;
1004 }
1005
1006 /* 9. Same IGP metric. Compare the cluster list length as
1007 representative of IGP hops metric. Rewrite the metric value
1008 pair (newm, existm) with the cluster list length. Prefer the
1009 path with smaller cluster list length. */
1010 if (newm == existm) {
1011 if (peer_sort_lookup(new->peer) == BGP_PEER_IBGP
1012 && peer_sort_lookup(exist->peer) == BGP_PEER_IBGP
1013 && (mpath_cfg == NULL
1014 || CHECK_FLAG(
1015 mpath_cfg->ibgp_flags,
1016 BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN))) {
1017 newm = BGP_CLUSTER_LIST_LENGTH(new->attr);
1018 existm = BGP_CLUSTER_LIST_LENGTH(exist->attr);
1019
1020 if (newm < existm) {
1021 if (debug)
1022 zlog_debug(
1023 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1024 pfx_buf, new_buf, exist_buf,
1025 newm, existm);
1026 ret = 1;
1027 }
1028
1029 if (newm > existm) {
1030 if (debug)
1031 zlog_debug(
1032 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1033 pfx_buf, new_buf, exist_buf,
1034 newm, existm);
1035 ret = 0;
1036 }
1037 }
1038 }
1039
1040 /* 10. confed-external vs. confed-internal */
1041 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
1042 if (new_sort == BGP_PEER_CONFED
1043 && exist_sort == BGP_PEER_IBGP) {
1044 *reason = bgp_path_selection_confed;
1045 if (debug)
1046 zlog_debug(
1047 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
1048 pfx_buf, new_buf, exist_buf);
1049 return 1;
1050 }
1051
1052 if (exist_sort == BGP_PEER_CONFED
1053 && new_sort == BGP_PEER_IBGP) {
1054 *reason = bgp_path_selection_confed;
1055 if (debug)
1056 zlog_debug(
1057 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
1058 pfx_buf, new_buf, exist_buf);
1059 return 0;
1060 }
1061 }
1062
1063 /* 11. Maximum path check. */
1064 if (newm == existm) {
1065 /* If one path has a label but the other does not, do not treat
1066 * them as equals for multipath
1067 */
1068 if ((new->extra &&bgp_is_valid_label(&new->extra->label[0]))
1069 != (exist->extra
1070 && bgp_is_valid_label(&exist->extra->label[0]))) {
1071 if (debug)
1072 zlog_debug(
1073 "%s: %s and %s cannot be multipath, one has a label while the other does not",
1074 pfx_buf, new_buf, exist_buf);
1075 } else if (CHECK_FLAG(bgp->flags,
1076 BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
1077
1078 /*
1079 * For the two paths, all comparison steps till IGP
1080 * metric
1081 * have succeeded - including AS_PATH hop count. Since
1082 * 'bgp
1083 * bestpath as-path multipath-relax' knob is on, we
1084 * don't need
1085 * an exact match of AS_PATH. Thus, mark the paths are
1086 * equal.
1087 * That will trigger both these paths to get into the
1088 * multipath
1089 * array.
1090 */
1091 *paths_eq = 1;
1092
1093 if (debug)
1094 zlog_debug(
1095 "%s: %s and %s are equal via multipath-relax",
1096 pfx_buf, new_buf, exist_buf);
1097 } else if (new->peer->sort == BGP_PEER_IBGP) {
1098 if (aspath_cmp(new->attr->aspath,
1099 exist->attr->aspath)) {
1100 *paths_eq = 1;
1101
1102 if (debug)
1103 zlog_debug(
1104 "%s: %s and %s are equal via matching aspaths",
1105 pfx_buf, new_buf, exist_buf);
1106 }
1107 } else if (new->peer->as == exist->peer->as) {
1108 *paths_eq = 1;
1109
1110 if (debug)
1111 zlog_debug(
1112 "%s: %s and %s are equal via same remote-as",
1113 pfx_buf, new_buf, exist_buf);
1114 }
1115 } else {
1116 /*
1117 * TODO: If unequal cost ibgp multipath is enabled we can
1118 * mark the paths as equal here instead of returning
1119 */
1120 if (debug) {
1121 if (ret == 1)
1122 zlog_debug(
1123 "%s: %s wins over %s after IGP metric comparison",
1124 pfx_buf, new_buf, exist_buf);
1125 else
1126 zlog_debug(
1127 "%s: %s loses to %s after IGP metric comparison",
1128 pfx_buf, new_buf, exist_buf);
1129 }
1130 *reason = bgp_path_selection_igp_metric;
1131 return ret;
1132 }
1133
1134 /* 12. If both paths are external, prefer the path that was received
1135 first (the oldest one). This step minimizes route-flap, since a
1136 newer path won't displace an older one, even if it was the
1137 preferred route based on the additional decision criteria below. */
1138 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_COMPARE_ROUTER_ID)
1139 && new_sort == BGP_PEER_EBGP && exist_sort == BGP_PEER_EBGP) {
1140 if (CHECK_FLAG(new->flags, BGP_PATH_SELECTED)) {
1141 *reason = bgp_path_selection_older;
1142 if (debug)
1143 zlog_debug(
1144 "%s: %s wins over %s due to oldest external",
1145 pfx_buf, new_buf, exist_buf);
1146 return 1;
1147 }
1148
1149 if (CHECK_FLAG(exist->flags, BGP_PATH_SELECTED)) {
1150 *reason = bgp_path_selection_older;
1151 if (debug)
1152 zlog_debug(
1153 "%s: %s loses to %s due to oldest external",
1154 pfx_buf, new_buf, exist_buf);
1155 return 0;
1156 }
1157 }
1158
1159 /* 13. Router-ID comparision. */
1160 /* If one of the paths is "stale", the corresponding peer router-id will
1161 * be 0 and would always win over the other path. If originator id is
1162 * used for the comparision, it will decide which path is better.
1163 */
1164 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1165 new_id.s_addr = newattr->originator_id.s_addr;
1166 else
1167 new_id.s_addr = new->peer->remote_id.s_addr;
1168 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1169 exist_id.s_addr = existattr->originator_id.s_addr;
1170 else
1171 exist_id.s_addr = exist->peer->remote_id.s_addr;
1172
1173 if (ntohl(new_id.s_addr) < ntohl(exist_id.s_addr)) {
1174 *reason = bgp_path_selection_router_id;
1175 if (debug)
1176 zlog_debug(
1177 "%s: %s wins over %s due to Router-ID comparison",
1178 pfx_buf, new_buf, exist_buf);
1179 return 1;
1180 }
1181
1182 if (ntohl(new_id.s_addr) > ntohl(exist_id.s_addr)) {
1183 *reason = bgp_path_selection_router_id;
1184 if (debug)
1185 zlog_debug(
1186 "%s: %s loses to %s due to Router-ID comparison",
1187 pfx_buf, new_buf, exist_buf);
1188 return 0;
1189 }
1190
1191 /* 14. Cluster length comparision. */
1192 new_cluster = BGP_CLUSTER_LIST_LENGTH(new->attr);
1193 exist_cluster = BGP_CLUSTER_LIST_LENGTH(exist->attr);
1194
1195 if (new_cluster < exist_cluster) {
1196 *reason = bgp_path_selection_cluster_length;
1197 if (debug)
1198 zlog_debug(
1199 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1200 pfx_buf, new_buf, exist_buf, new_cluster,
1201 exist_cluster);
1202 return 1;
1203 }
1204
1205 if (new_cluster > exist_cluster) {
1206 *reason = bgp_path_selection_cluster_length;
1207 if (debug)
1208 zlog_debug(
1209 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1210 pfx_buf, new_buf, exist_buf, new_cluster,
1211 exist_cluster);
1212 return 0;
1213 }
1214
1215 /* 15. Neighbor address comparision. */
1216 /* Do this only if neither path is "stale" as stale paths do not have
1217 * valid peer information (as the connection may or may not be up).
1218 */
1219 if (CHECK_FLAG(exist->flags, BGP_PATH_STALE)) {
1220 *reason = bgp_path_selection_stale;
1221 if (debug)
1222 zlog_debug(
1223 "%s: %s wins over %s due to latter path being STALE",
1224 pfx_buf, new_buf, exist_buf);
1225 return 1;
1226 }
1227
1228 if (CHECK_FLAG(new->flags, BGP_PATH_STALE)) {
1229 *reason = bgp_path_selection_stale;
1230 if (debug)
1231 zlog_debug(
1232 "%s: %s loses to %s due to former path being STALE",
1233 pfx_buf, new_buf, exist_buf);
1234 return 0;
1235 }
1236
1237 /* locally configured routes to advertise do not have su_remote */
1238 if (new->peer->su_remote == NULL) {
1239 *reason = bgp_path_selection_local_configured;
1240 return 0;
1241 }
1242 if (exist->peer->su_remote == NULL) {
1243 *reason = bgp_path_selection_local_configured;
1244 return 1;
1245 }
1246
1247 ret = sockunion_cmp(new->peer->su_remote, exist->peer->su_remote);
1248
1249 if (ret == 1) {
1250 *reason = bgp_path_selection_neighbor_ip;
1251 if (debug)
1252 zlog_debug(
1253 "%s: %s loses to %s due to Neighor IP comparison",
1254 pfx_buf, new_buf, exist_buf);
1255 return 0;
1256 }
1257
1258 if (ret == -1) {
1259 *reason = bgp_path_selection_neighbor_ip;
1260 if (debug)
1261 zlog_debug(
1262 "%s: %s wins over %s due to Neighor IP comparison",
1263 pfx_buf, new_buf, exist_buf);
1264 return 1;
1265 }
1266
1267 *reason = bgp_path_selection_default;
1268 if (debug)
1269 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1270 pfx_buf, new_buf, exist_buf);
1271
1272 return 1;
1273 }
1274
1275
1276 int bgp_evpn_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
1277 struct bgp_path_info *exist, int *paths_eq)
1278 {
1279 enum bgp_path_selection_reason reason;
1280 char pfx_buf[PREFIX2STR_BUFFER];
1281
1282 return bgp_path_info_cmp(bgp, new, exist, paths_eq, NULL, 0, pfx_buf,
1283 AFI_L2VPN, SAFI_EVPN, &reason);
1284 }
1285
1286 /* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1287 * is preferred, or 0 if they are the same (usually will only occur if
1288 * multipath is enabled
1289 * This version is compatible with */
1290 int bgp_path_info_cmp_compatible(struct bgp *bgp, struct bgp_path_info *new,
1291 struct bgp_path_info *exist, char *pfx_buf,
1292 afi_t afi, safi_t safi,
1293 enum bgp_path_selection_reason *reason)
1294 {
1295 int paths_eq;
1296 int ret;
1297 ret = bgp_path_info_cmp(bgp, new, exist, &paths_eq, NULL, 0, pfx_buf,
1298 afi, safi, reason);
1299
1300 if (paths_eq)
1301 ret = 0;
1302 else {
1303 if (ret == 1)
1304 ret = -1;
1305 else
1306 ret = 1;
1307 }
1308 return ret;
1309 }
1310
1311 static enum filter_type bgp_input_filter(struct peer *peer,
1312 const struct prefix *p,
1313 struct attr *attr, afi_t afi,
1314 safi_t safi)
1315 {
1316 struct bgp_filter *filter;
1317 enum filter_type ret = FILTER_PERMIT;
1318
1319 filter = &peer->filter[afi][safi];
1320
1321 #define FILTER_EXIST_WARN(F, f, filter) \
1322 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
1323 zlog_debug("%s: Could not find configured input %s-list %s!", \
1324 peer->host, #f, F##_IN_NAME(filter));
1325
1326 if (DISTRIBUTE_IN_NAME(filter)) {
1327 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
1328
1329 if (access_list_apply(DISTRIBUTE_IN(filter), p)
1330 == FILTER_DENY) {
1331 ret = FILTER_DENY;
1332 goto done;
1333 }
1334 }
1335
1336 if (PREFIX_LIST_IN_NAME(filter)) {
1337 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
1338
1339 if (prefix_list_apply(PREFIX_LIST_IN(filter), p)
1340 == PREFIX_DENY) {
1341 ret = FILTER_DENY;
1342 goto done;
1343 }
1344 }
1345
1346 if (FILTER_LIST_IN_NAME(filter)) {
1347 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
1348
1349 if (as_list_apply(FILTER_LIST_IN(filter), attr->aspath)
1350 == AS_FILTER_DENY) {
1351 ret = FILTER_DENY;
1352 goto done;
1353 }
1354 }
1355
1356 done:
1357 if (frrtrace_enabled(frr_bgp, input_filter)) {
1358 char pfxprint[PREFIX2STR_BUFFER];
1359
1360 prefix2str(p, pfxprint, sizeof(pfxprint));
1361 frrtrace(5, frr_bgp, input_filter, peer, pfxprint, afi, safi,
1362 ret == FILTER_PERMIT ? "permit" : "deny");
1363 }
1364
1365 return ret;
1366 #undef FILTER_EXIST_WARN
1367 }
1368
1369 static enum filter_type bgp_output_filter(struct peer *peer,
1370 const struct prefix *p,
1371 struct attr *attr, afi_t afi,
1372 safi_t safi)
1373 {
1374 struct bgp_filter *filter;
1375 enum filter_type ret = FILTER_PERMIT;
1376
1377 filter = &peer->filter[afi][safi];
1378
1379 #define FILTER_EXIST_WARN(F, f, filter) \
1380 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
1381 zlog_debug("%s: Could not find configured output %s-list %s!", \
1382 peer->host, #f, F##_OUT_NAME(filter));
1383
1384 if (DISTRIBUTE_OUT_NAME(filter)) {
1385 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
1386
1387 if (access_list_apply(DISTRIBUTE_OUT(filter), p)
1388 == FILTER_DENY) {
1389 ret = FILTER_DENY;
1390 goto done;
1391 }
1392 }
1393
1394 if (PREFIX_LIST_OUT_NAME(filter)) {
1395 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
1396
1397 if (prefix_list_apply(PREFIX_LIST_OUT(filter), p)
1398 == PREFIX_DENY) {
1399 ret = FILTER_DENY;
1400 goto done;
1401 }
1402 }
1403
1404 if (FILTER_LIST_OUT_NAME(filter)) {
1405 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
1406
1407 if (as_list_apply(FILTER_LIST_OUT(filter), attr->aspath)
1408 == AS_FILTER_DENY) {
1409 ret = FILTER_DENY;
1410 goto done;
1411 }
1412 }
1413
1414 if (frrtrace_enabled(frr_bgp, output_filter)) {
1415 char pfxprint[PREFIX2STR_BUFFER];
1416
1417 prefix2str(p, pfxprint, sizeof(pfxprint));
1418 frrtrace(5, frr_bgp, output_filter, peer, pfxprint, afi, safi,
1419 ret == FILTER_PERMIT ? "permit" : "deny");
1420 }
1421
1422 done:
1423 return ret;
1424 #undef FILTER_EXIST_WARN
1425 }
1426
1427 /* If community attribute includes no_export then return 1. */
1428 static bool bgp_community_filter(struct peer *peer, struct attr *attr)
1429 {
1430 if (attr->community) {
1431 /* NO_ADVERTISE check. */
1432 if (community_include(attr->community, COMMUNITY_NO_ADVERTISE))
1433 return true;
1434
1435 /* NO_EXPORT check. */
1436 if (peer->sort == BGP_PEER_EBGP
1437 && community_include(attr->community, COMMUNITY_NO_EXPORT))
1438 return true;
1439
1440 /* NO_EXPORT_SUBCONFED check. */
1441 if (peer->sort == BGP_PEER_EBGP
1442 || peer->sort == BGP_PEER_CONFED)
1443 if (community_include(attr->community,
1444 COMMUNITY_NO_EXPORT_SUBCONFED))
1445 return true;
1446 }
1447 return false;
1448 }
1449
1450 /* Route reflection loop check. */
1451 static bool bgp_cluster_filter(struct peer *peer, struct attr *attr)
1452 {
1453 struct in_addr cluster_id;
1454 struct cluster_list *cluster = bgp_attr_get_cluster(attr);
1455
1456 if (cluster) {
1457 if (peer->bgp->config & BGP_CONFIG_CLUSTER_ID)
1458 cluster_id = peer->bgp->cluster_id;
1459 else
1460 cluster_id = peer->bgp->router_id;
1461
1462 if (cluster_loop_check(cluster, cluster_id))
1463 return true;
1464 }
1465 return false;
1466 }
1467
1468 static int bgp_input_modifier(struct peer *peer, const struct prefix *p,
1469 struct attr *attr, afi_t afi, safi_t safi,
1470 const char *rmap_name, mpls_label_t *label,
1471 uint32_t num_labels, struct bgp_dest *dest)
1472 {
1473 struct bgp_filter *filter;
1474 struct bgp_path_info rmap_path = { 0 };
1475 struct bgp_path_info_extra extra = { 0 };
1476 route_map_result_t ret;
1477 struct route_map *rmap = NULL;
1478
1479 filter = &peer->filter[afi][safi];
1480
1481 /* Apply default weight value. */
1482 if (peer->weight[afi][safi])
1483 attr->weight = peer->weight[afi][safi];
1484
1485 if (rmap_name) {
1486 rmap = route_map_lookup_by_name(rmap_name);
1487
1488 if (rmap == NULL)
1489 return RMAP_DENY;
1490 } else {
1491 if (ROUTE_MAP_IN_NAME(filter)) {
1492 rmap = ROUTE_MAP_IN(filter);
1493
1494 if (rmap == NULL)
1495 return RMAP_DENY;
1496 }
1497 }
1498
1499 /* Route map apply. */
1500 if (rmap) {
1501 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
1502 /* Duplicate current value to new strucutre for modification. */
1503 rmap_path.peer = peer;
1504 rmap_path.attr = attr;
1505 rmap_path.extra = &extra;
1506 rmap_path.net = dest;
1507
1508 extra.num_labels = num_labels;
1509 if (label && num_labels && num_labels <= BGP_MAX_LABELS)
1510 memcpy(extra.label, label,
1511 num_labels * sizeof(mpls_label_t));
1512
1513 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN);
1514
1515 /* Apply BGP route map to the attribute. */
1516 ret = route_map_apply(rmap, p, &rmap_path);
1517
1518 peer->rmap_type = 0;
1519
1520 if (ret == RMAP_DENYMATCH)
1521 return RMAP_DENY;
1522 }
1523 return RMAP_PERMIT;
1524 }
1525
1526 static int bgp_output_modifier(struct peer *peer, const struct prefix *p,
1527 struct attr *attr, afi_t afi, safi_t safi,
1528 const char *rmap_name)
1529 {
1530 struct bgp_path_info rmap_path;
1531 route_map_result_t ret;
1532 struct route_map *rmap = NULL;
1533 uint8_t rmap_type;
1534
1535 /*
1536 * So if we get to this point and have no rmap_name
1537 * we want to just show the output as it currently
1538 * exists.
1539 */
1540 if (!rmap_name)
1541 return RMAP_PERMIT;
1542
1543 /* Apply default weight value. */
1544 if (peer->weight[afi][safi])
1545 attr->weight = peer->weight[afi][safi];
1546
1547 rmap = route_map_lookup_by_name(rmap_name);
1548
1549 /*
1550 * If we have a route map name and we do not find
1551 * the routemap that means we have an implicit
1552 * deny.
1553 */
1554 if (rmap == NULL)
1555 return RMAP_DENY;
1556
1557 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
1558 /* Route map apply. */
1559 /* Duplicate current value to new strucutre for modification. */
1560 rmap_path.peer = peer;
1561 rmap_path.attr = attr;
1562
1563 rmap_type = peer->rmap_type;
1564 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
1565
1566 /* Apply BGP route map to the attribute. */
1567 ret = route_map_apply(rmap, p, &rmap_path);
1568
1569 peer->rmap_type = rmap_type;
1570
1571 if (ret == RMAP_DENYMATCH)
1572 /*
1573 * caller has multiple error paths with bgp_attr_flush()
1574 */
1575 return RMAP_DENY;
1576
1577 return RMAP_PERMIT;
1578 }
1579
1580 /* If this is an EBGP peer with remove-private-AS */
1581 static void bgp_peer_remove_private_as(struct bgp *bgp, afi_t afi, safi_t safi,
1582 struct peer *peer, struct attr *attr)
1583 {
1584 if (peer->sort == BGP_PEER_EBGP
1585 && (peer_af_flag_check(peer, afi, safi,
1586 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1587 || peer_af_flag_check(peer, afi, safi,
1588 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)
1589 || peer_af_flag_check(peer, afi, safi,
1590 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)
1591 || peer_af_flag_check(peer, afi, safi,
1592 PEER_FLAG_REMOVE_PRIVATE_AS))) {
1593 // Take action on the entire aspath
1594 if (peer_af_flag_check(peer, afi, safi,
1595 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1596 || peer_af_flag_check(peer, afi, safi,
1597 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)) {
1598 if (peer_af_flag_check(
1599 peer, afi, safi,
1600 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE))
1601 attr->aspath = aspath_replace_private_asns(
1602 attr->aspath, bgp->as, peer->as);
1603
1604 // The entire aspath consists of private ASNs so create
1605 // an empty aspath
1606 else if (aspath_private_as_check(attr->aspath))
1607 attr->aspath = aspath_empty_get();
1608
1609 // There are some public and some private ASNs, remove
1610 // the private ASNs
1611 else
1612 attr->aspath = aspath_remove_private_asns(
1613 attr->aspath, peer->as);
1614 }
1615
1616 // 'all' was not specified so the entire aspath must be private
1617 // ASNs
1618 // for us to do anything
1619 else if (aspath_private_as_check(attr->aspath)) {
1620 if (peer_af_flag_check(
1621 peer, afi, safi,
1622 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE))
1623 attr->aspath = aspath_replace_private_asns(
1624 attr->aspath, bgp->as, peer->as);
1625 else
1626 attr->aspath = aspath_empty_get();
1627 }
1628 }
1629 }
1630
1631 /* If this is an EBGP peer with as-override */
1632 static void bgp_peer_as_override(struct bgp *bgp, afi_t afi, safi_t safi,
1633 struct peer *peer, struct attr *attr)
1634 {
1635 if (peer->sort == BGP_PEER_EBGP
1636 && peer_af_flag_check(peer, afi, safi, PEER_FLAG_AS_OVERRIDE)) {
1637 if (aspath_single_asn_check(attr->aspath, peer->as))
1638 attr->aspath = aspath_replace_specific_asn(
1639 attr->aspath, peer->as, bgp->as);
1640 }
1641 }
1642
1643 void bgp_attr_add_gshut_community(struct attr *attr)
1644 {
1645 struct community *old;
1646 struct community *new;
1647 struct community *merge;
1648 struct community *gshut;
1649
1650 old = attr->community;
1651 gshut = community_str2com("graceful-shutdown");
1652
1653 assert(gshut);
1654
1655 if (old) {
1656 merge = community_merge(community_dup(old), gshut);
1657
1658 if (old->refcnt == 0)
1659 community_free(&old);
1660
1661 new = community_uniq_sort(merge);
1662 community_free(&merge);
1663 } else {
1664 new = community_dup(gshut);
1665 }
1666
1667 community_free(&gshut);
1668 attr->community = new;
1669 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
1670
1671 /* When we add the graceful-shutdown community we must also
1672 * lower the local-preference */
1673 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1674 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
1675 }
1676
1677
1678 /* Notify BGP Conditional advertisement scanner process. */
1679 void bgp_notify_conditional_adv_scanner(struct update_subgroup *subgrp)
1680 {
1681 struct peer *temp_peer;
1682 struct peer *peer = SUBGRP_PEER(subgrp);
1683 struct listnode *temp_node, *temp_nnode = NULL;
1684 afi_t afi = SUBGRP_AFI(subgrp);
1685 safi_t safi = SUBGRP_SAFI(subgrp);
1686 struct bgp *bgp = SUBGRP_INST(subgrp);
1687 struct bgp_filter *filter = &peer->filter[afi][safi];
1688
1689 if (!ADVERTISE_MAP_NAME(filter))
1690 return;
1691
1692 for (ALL_LIST_ELEMENTS(bgp->peer, temp_node, temp_nnode, temp_peer)) {
1693 if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
1694 continue;
1695
1696 if (peer != temp_peer)
1697 continue;
1698
1699 temp_peer->advmap_table_change = true;
1700 break;
1701 }
1702 }
1703
1704
1705 void subgroup_announce_reset_nhop(uint8_t family, struct attr *attr)
1706 {
1707 if (family == AF_INET) {
1708 attr->nexthop.s_addr = INADDR_ANY;
1709 attr->mp_nexthop_global_in.s_addr = INADDR_ANY;
1710 }
1711 if (family == AF_INET6)
1712 memset(&attr->mp_nexthop_global, 0, IPV6_MAX_BYTELEN);
1713 if (family == AF_EVPN)
1714 memset(&attr->mp_nexthop_global_in, 0, BGP_ATTR_NHLEN_IPV4);
1715 }
1716
1717 bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
1718 struct update_subgroup *subgrp,
1719 const struct prefix *p, struct attr *attr,
1720 bool skip_rmap_check)
1721 {
1722 struct bgp_filter *filter;
1723 struct peer *from;
1724 struct peer *peer;
1725 struct peer *onlypeer;
1726 struct bgp *bgp;
1727 struct attr *piattr;
1728 route_map_result_t ret;
1729 int transparent;
1730 int reflect;
1731 afi_t afi;
1732 safi_t safi;
1733 int samepeer_safe = 0; /* for synthetic mplsvpns routes */
1734 bool nh_reset = false;
1735 uint64_t cum_bw;
1736
1737 if (DISABLE_BGP_ANNOUNCE)
1738 return false;
1739
1740 afi = SUBGRP_AFI(subgrp);
1741 safi = SUBGRP_SAFI(subgrp);
1742 peer = SUBGRP_PEER(subgrp);
1743 onlypeer = NULL;
1744 if (CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL))
1745 onlypeer = SUBGRP_PFIRST(subgrp)->peer;
1746
1747 from = pi->peer;
1748 filter = &peer->filter[afi][safi];
1749 bgp = SUBGRP_INST(subgrp);
1750 piattr = bgp_path_info_mpath_count(pi) ? bgp_path_info_mpath_attr(pi)
1751 : pi->attr;
1752
1753 #ifdef ENABLE_BGP_VNC
1754 if (((afi == AFI_IP) || (afi == AFI_IP6)) && (safi == SAFI_MPLS_VPN)
1755 && ((pi->type == ZEBRA_ROUTE_BGP_DIRECT)
1756 || (pi->type == ZEBRA_ROUTE_BGP_DIRECT_EXT))) {
1757
1758 /*
1759 * direct and direct_ext type routes originate internally even
1760 * though they can have peer pointers that reference other
1761 * systems
1762 */
1763 zlog_debug("%s: pfx %pFX bgp_direct->vpn route peer safe",
1764 __func__, p);
1765 samepeer_safe = 1;
1766 }
1767 #endif
1768
1769 if (((afi == AFI_IP) || (afi == AFI_IP6))
1770 && ((safi == SAFI_MPLS_VPN) || (safi == SAFI_UNICAST))
1771 && (pi->type == ZEBRA_ROUTE_BGP)
1772 && (pi->sub_type == BGP_ROUTE_IMPORTED)) {
1773
1774 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1775
1776 samepeer_safe = 1;
1777 }
1778
1779 /* With addpath we may be asked to TX all kinds of paths so make sure
1780 * pi is valid */
1781 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID)
1782 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)
1783 || CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
1784 return false;
1785 }
1786
1787 /* If this is not the bestpath then check to see if there is an enabled
1788 * addpath
1789 * feature that requires us to advertise it */
1790 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
1791 if (!bgp_addpath_tx_path(peer->addpath_type[afi][safi], pi)) {
1792 return false;
1793 }
1794 }
1795
1796 /* Aggregate-address suppress check. */
1797 if (bgp_path_suppressed(pi) && !UNSUPPRESS_MAP_NAME(filter))
1798 return false;
1799
1800 /*
1801 * If we are doing VRF 2 VRF leaking via the import
1802 * statement, we want to prevent the route going
1803 * off box as that the RT and RD created are localy
1804 * significant and globaly useless.
1805 */
1806 if (safi == SAFI_MPLS_VPN && pi->extra && pi->extra->num_labels
1807 && pi->extra->label[0] == BGP_PREVENT_VRF_2_VRF_LEAK)
1808 return false;
1809
1810 /* If it's labeled safi, make sure the route has a valid label. */
1811 if (safi == SAFI_LABELED_UNICAST) {
1812 mpls_label_t label = bgp_adv_label(dest, pi, peer, afi, safi);
1813 if (!bgp_is_valid_label(&label)) {
1814 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1815 zlog_debug("u%" PRIu64 ":s%" PRIu64
1816 " %pFX is filtered - no label (%p)",
1817 subgrp->update_group->id, subgrp->id,
1818 p, &label);
1819 return false;
1820 }
1821 }
1822
1823 /* Do not send back route to sender. */
1824 if (onlypeer && from == onlypeer) {
1825 return false;
1826 }
1827
1828 /* Do not send the default route in the BGP table if the neighbor is
1829 * configured for default-originate */
1830 if (CHECK_FLAG(peer->af_flags[afi][safi],
1831 PEER_FLAG_DEFAULT_ORIGINATE)) {
1832 if (p->family == AF_INET && p->u.prefix4.s_addr == INADDR_ANY)
1833 return false;
1834 else if (p->family == AF_INET6 && p->prefixlen == 0)
1835 return false;
1836 }
1837
1838 /* Transparency check. */
1839 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1840 && CHECK_FLAG(from->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1841 transparent = 1;
1842 else
1843 transparent = 0;
1844
1845 /* If community is not disabled check the no-export and local. */
1846 if (!transparent && bgp_community_filter(peer, piattr)) {
1847 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1848 zlog_debug("%s: community filter check fail for %pFX",
1849 __func__, p);
1850 return false;
1851 }
1852
1853 /* If the attribute has originator-id and it is same as remote
1854 peer's id. */
1855 if (onlypeer && piattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
1856 && (IPV4_ADDR_SAME(&onlypeer->remote_id, &piattr->originator_id))) {
1857 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1858 zlog_debug(
1859 "%s [Update:SEND] %pFX originator-id is same as remote router-id",
1860 onlypeer->host, p);
1861 return false;
1862 }
1863
1864 /* ORF prefix-list filter check */
1865 if (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV)
1866 && (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)
1867 || CHECK_FLAG(peer->af_cap[afi][safi],
1868 PEER_CAP_ORF_PREFIX_SM_OLD_RCV)))
1869 if (peer->orf_plist[afi][safi]) {
1870 if (prefix_list_apply(peer->orf_plist[afi][safi], p)
1871 == PREFIX_DENY) {
1872 if (bgp_debug_update(NULL, p,
1873 subgrp->update_group, 0))
1874 zlog_debug(
1875 "%s [Update:SEND] %pFX is filtered via ORF",
1876 peer->host, p);
1877 return false;
1878 }
1879 }
1880
1881 /* Output filter check. */
1882 if (bgp_output_filter(peer, p, piattr, afi, safi) == FILTER_DENY) {
1883 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1884 zlog_debug("%s [Update:SEND] %pFX is filtered",
1885 peer->host, p);
1886 return false;
1887 }
1888
1889 /* AS path loop check. */
1890 if (onlypeer && onlypeer->as_path_loop_detection
1891 && aspath_loop_check(piattr->aspath, onlypeer->as)) {
1892 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1893 zlog_debug(
1894 "%s [Update:SEND] suppress announcement to peer AS %u that is part of AS path.",
1895 onlypeer->host, onlypeer->as);
1896 return false;
1897 }
1898
1899 /* If we're a CONFED we need to loop check the CONFED ID too */
1900 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
1901 if (aspath_loop_check(piattr->aspath, bgp->confed_id)) {
1902 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1903 zlog_debug(
1904 "%s [Update:SEND] suppress announcement to peer AS %u is AS path.",
1905 peer->host, bgp->confed_id);
1906 return false;
1907 }
1908 }
1909
1910 /* Route-Reflect check. */
1911 if (from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
1912 reflect = 1;
1913 else
1914 reflect = 0;
1915
1916 /* IBGP reflection check. */
1917 if (reflect && !samepeer_safe) {
1918 /* A route from a Client peer. */
1919 if (CHECK_FLAG(from->af_flags[afi][safi],
1920 PEER_FLAG_REFLECTOR_CLIENT)) {
1921 /* Reflect to all the Non-Client peers and also to the
1922 Client peers other than the originator. Originator
1923 check
1924 is already done. So there is noting to do. */
1925 /* no bgp client-to-client reflection check. */
1926 if (CHECK_FLAG(bgp->flags,
1927 BGP_FLAG_NO_CLIENT_TO_CLIENT))
1928 if (CHECK_FLAG(peer->af_flags[afi][safi],
1929 PEER_FLAG_REFLECTOR_CLIENT))
1930 return false;
1931 } else {
1932 /* A route from a Non-client peer. Reflect to all other
1933 clients. */
1934 if (!CHECK_FLAG(peer->af_flags[afi][safi],
1935 PEER_FLAG_REFLECTOR_CLIENT))
1936 return false;
1937 }
1938 }
1939
1940 /* For modify attribute, copy it to temporary structure. */
1941 *attr = *piattr;
1942
1943 /* If local-preference is not set. */
1944 if ((peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED)
1945 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)))) {
1946 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1947 attr->local_pref = bgp->default_local_pref;
1948 }
1949
1950 /* If originator-id is not set and the route is to be reflected,
1951 set the originator id */
1952 if (reflect
1953 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)))) {
1954 IPV4_ADDR_COPY(&(attr->originator_id), &(from->remote_id));
1955 SET_FLAG(attr->flag, BGP_ATTR_ORIGINATOR_ID);
1956 }
1957
1958 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
1959 */
1960 if (peer->sort == BGP_PEER_EBGP
1961 && attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
1962 if (from != bgp->peer_self && !transparent
1963 && !CHECK_FLAG(peer->af_flags[afi][safi],
1964 PEER_FLAG_MED_UNCHANGED))
1965 attr->flag &=
1966 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC));
1967 }
1968
1969 /* Since the nexthop attribute can vary per peer, it is not explicitly
1970 * set
1971 * in announce check, only certain flags and length (or number of
1972 * nexthops
1973 * -- for IPv6/MP_REACH) are set here in order to guide the update
1974 * formation
1975 * code in setting the nexthop(s) on a per peer basis in
1976 * reformat_peer().
1977 * Typically, the source nexthop in the attribute is preserved but in
1978 * the
1979 * scenarios where we know it will always be overwritten, we reset the
1980 * nexthop to "0" in an attempt to achieve better Update packing. An
1981 * example of this is when a prefix from each of 2 IBGP peers needs to
1982 * be
1983 * announced to an EBGP peer (and they have the same attributes barring
1984 * their nexthop).
1985 */
1986 if (reflect)
1987 SET_FLAG(attr->rmap_change_flags, BATTR_REFLECTED);
1988
1989 #define NEXTHOP_IS_V6 \
1990 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
1991 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
1992 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
1993 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
1994
1995 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
1996 * if
1997 * the peer (group) is configured to receive link-local nexthop
1998 * unchanged
1999 * and it is available in the prefix OR we're not reflecting the route,
2000 * link-local nexthop address is valid and
2001 * the peer (group) to whom we're going to announce is on a shared
2002 * network
2003 * and this is either a self-originated route or the peer is EBGP.
2004 * By checking if nexthop LL address is valid we are sure that
2005 * we do not announce LL address as `::`.
2006 */
2007 if (NEXTHOP_IS_V6) {
2008 attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
2009 if ((CHECK_FLAG(peer->af_flags[afi][safi],
2010 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
2011 && IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_local))
2012 || (!reflect
2013 && IN6_IS_ADDR_LINKLOCAL(&peer->nexthop.v6_local)
2014 && peer->shared_network
2015 && (from == bgp->peer_self
2016 || peer->sort == BGP_PEER_EBGP))) {
2017 attr->mp_nexthop_len =
2018 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
2019 }
2020
2021 /* Clear off link-local nexthop in source, whenever it is not
2022 * needed to
2023 * ensure more prefixes share the same attribute for
2024 * announcement.
2025 */
2026 if (!(CHECK_FLAG(peer->af_flags[afi][safi],
2027 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)))
2028 memset(&attr->mp_nexthop_local, 0, IPV6_MAX_BYTELEN);
2029 }
2030
2031 bgp_peer_remove_private_as(bgp, afi, safi, peer, attr);
2032 bgp_peer_as_override(bgp, afi, safi, peer, attr);
2033
2034 /* Route map & unsuppress-map apply. */
2035 if (!skip_rmap_check
2036 && (ROUTE_MAP_OUT_NAME(filter) || bgp_path_suppressed(pi))) {
2037 struct bgp_path_info rmap_path = {0};
2038 struct bgp_path_info_extra dummy_rmap_path_extra = {0};
2039 struct attr dummy_attr = {0};
2040
2041 /* Fill temp path_info */
2042 prep_for_rmap_apply(&rmap_path, &dummy_rmap_path_extra, dest,
2043 pi, peer, attr);
2044
2045 /* don't confuse inbound and outbound setting */
2046 RESET_FLAG(attr->rmap_change_flags);
2047
2048 /*
2049 * The route reflector is not allowed to modify the attributes
2050 * of the reflected IBGP routes unless explicitly allowed.
2051 */
2052 if ((from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
2053 && !CHECK_FLAG(bgp->flags,
2054 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) {
2055 dummy_attr = *attr;
2056 rmap_path.attr = &dummy_attr;
2057 }
2058
2059 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
2060
2061 if (bgp_path_suppressed(pi))
2062 ret = route_map_apply(UNSUPPRESS_MAP(filter), p,
2063 &rmap_path);
2064 else
2065 ret = route_map_apply(ROUTE_MAP_OUT(filter), p,
2066 &rmap_path);
2067
2068 peer->rmap_type = 0;
2069
2070 if (ret == RMAP_DENYMATCH) {
2071 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2072 zlog_debug(
2073 "%s [Update:SEND] %pFX is filtered by route-map",
2074 peer->host, p);
2075
2076 bgp_attr_flush(attr);
2077 return false;
2078 }
2079 }
2080
2081 /* RFC 8212 to prevent route leaks.
2082 * This specification intends to improve this situation by requiring the
2083 * explicit configuration of both BGP Import and Export Policies for any
2084 * External BGP (EBGP) session such as customers, peers, or
2085 * confederation boundaries for all enabled address families. Through
2086 * codification of the aforementioned requirement, operators will
2087 * benefit from consistent behavior across different BGP
2088 * implementations.
2089 */
2090 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
2091 if (!bgp_outbound_policy_exists(peer, filter))
2092 return false;
2093
2094 /* draft-ietf-idr-deprecate-as-set-confed-set
2095 * Filter routes having AS_SET or AS_CONFED_SET in the path.
2096 * Eventually, This document (if approved) updates RFC 4271
2097 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
2098 * and obsoletes RFC 6472.
2099 */
2100 if (peer->bgp->reject_as_sets)
2101 if (aspath_check_as_sets(attr->aspath))
2102 return false;
2103
2104 /* Codification of AS 0 Processing */
2105 if (aspath_check_as_zero(attr->aspath))
2106 return false;
2107
2108 if (bgp_in_graceful_shutdown(bgp)) {
2109 if (peer->sort == BGP_PEER_IBGP
2110 || peer->sort == BGP_PEER_CONFED) {
2111 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
2112 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
2113 } else {
2114 bgp_attr_add_gshut_community(attr);
2115 }
2116 }
2117
2118 /* After route-map has been applied, we check to see if the nexthop to
2119 * be carried in the attribute (that is used for the announcement) can
2120 * be cleared off or not. We do this in all cases where we would be
2121 * setting the nexthop to "ourselves". For IPv6, we only need to
2122 * consider
2123 * the global nexthop here; the link-local nexthop would have been
2124 * cleared
2125 * already, and if not, it is required by the update formation code.
2126 * Also see earlier comments in this function.
2127 */
2128 /*
2129 * If route-map has performed some operation on the nexthop or the peer
2130 * configuration says to pass it unchanged, we cannot reset the nexthop
2131 * here, so only attempt to do it if these aren't true. Note that the
2132 * route-map handler itself might have cleared the nexthop, if for
2133 * example,
2134 * it is configured as 'peer-address'.
2135 */
2136 if (!bgp_rmap_nhop_changed(attr->rmap_change_flags,
2137 piattr->rmap_change_flags)
2138 && !transparent
2139 && !CHECK_FLAG(peer->af_flags[afi][safi],
2140 PEER_FLAG_NEXTHOP_UNCHANGED)) {
2141 /* We can reset the nexthop, if setting (or forcing) it to
2142 * 'self' */
2143 if (CHECK_FLAG(peer->af_flags[afi][safi],
2144 PEER_FLAG_NEXTHOP_SELF)
2145 || CHECK_FLAG(peer->af_flags[afi][safi],
2146 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
2147 if (!reflect
2148 || CHECK_FLAG(peer->af_flags[afi][safi],
2149 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
2150 subgroup_announce_reset_nhop(
2151 (peer_cap_enhe(peer, afi, safi)
2152 ? AF_INET6
2153 : p->family),
2154 attr);
2155 nh_reset = true;
2156 }
2157 } else if (peer->sort == BGP_PEER_EBGP) {
2158 /* Can also reset the nexthop if announcing to EBGP, but
2159 * only if
2160 * no peer in the subgroup is on a shared subnet.
2161 * Note: 3rd party nexthop currently implemented for
2162 * IPv4 only.
2163 */
2164 if ((p->family == AF_INET) &&
2165 (!bgp_subgrp_multiaccess_check_v4(
2166 piattr->nexthop,
2167 subgrp, from))) {
2168 subgroup_announce_reset_nhop(
2169 (peer_cap_enhe(peer, afi, safi)
2170 ? AF_INET6
2171 : p->family),
2172 attr);
2173 nh_reset = true;
2174 }
2175
2176 if ((p->family == AF_INET6) &&
2177 (!bgp_subgrp_multiaccess_check_v6(
2178 piattr->mp_nexthop_global,
2179 subgrp, from))) {
2180 subgroup_announce_reset_nhop(
2181 (peer_cap_enhe(peer, afi, safi)
2182 ? AF_INET6
2183 : p->family),
2184 attr);
2185 nh_reset = true;
2186 }
2187
2188
2189
2190 } else if (CHECK_FLAG(pi->flags, BGP_PATH_ANNC_NH_SELF)) {
2191 /*
2192 * This flag is used for leaked vpn-vrf routes
2193 */
2194 int family = p->family;
2195
2196 if (peer_cap_enhe(peer, afi, safi))
2197 family = AF_INET6;
2198
2199 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2200 zlog_debug(
2201 "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
2202 __func__, family2str(family));
2203 subgroup_announce_reset_nhop(family, attr);
2204 nh_reset = true;
2205 }
2206 }
2207
2208 /* If IPv6/MP and nexthop does not have any override and happens
2209 * to
2210 * be a link-local address, reset it so that we don't pass along
2211 * the
2212 * source's link-local IPv6 address to recipients who may not be
2213 * on
2214 * the same interface.
2215 */
2216 if (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi)) {
2217 if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global)) {
2218 subgroup_announce_reset_nhop(AF_INET6, attr);
2219 nh_reset = true;
2220 }
2221 }
2222
2223 /*
2224 * When the next hop is set to ourselves, if all multipaths have
2225 * link-bandwidth announce the cumulative bandwidth as that makes
2226 * the most sense. However, don't modify if the link-bandwidth has
2227 * been explicitly set by user policy.
2228 */
2229 if (nh_reset &&
2230 bgp_path_info_mpath_chkwtd(bgp, pi) &&
2231 (cum_bw = bgp_path_info_mpath_cumbw(pi)) != 0 &&
2232 !CHECK_FLAG(attr->rmap_change_flags, BATTR_RMAP_LINK_BW_SET))
2233 attr->ecommunity = ecommunity_replace_linkbw(
2234 bgp->as, attr->ecommunity, cum_bw);
2235
2236 return true;
2237 }
2238
2239 static int bgp_route_select_timer_expire(struct thread *thread)
2240 {
2241 struct afi_safi_info *info;
2242 afi_t afi;
2243 safi_t safi;
2244 struct bgp *bgp;
2245
2246 info = THREAD_ARG(thread);
2247 afi = info->afi;
2248 safi = info->safi;
2249 bgp = info->bgp;
2250
2251 if (BGP_DEBUG(update, UPDATE_OUT))
2252 zlog_debug("afi %d, safi %d : route select timer expired", afi,
2253 safi);
2254
2255 bgp->gr_info[afi][safi].t_route_select = NULL;
2256
2257 XFREE(MTYPE_TMP, info);
2258
2259 /* Best path selection */
2260 return bgp_best_path_select_defer(bgp, afi, safi);
2261 }
2262
2263 void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
2264 struct bgp_maxpaths_cfg *mpath_cfg,
2265 struct bgp_path_info_pair *result, afi_t afi,
2266 safi_t safi)
2267 {
2268 struct bgp_path_info *new_select;
2269 struct bgp_path_info *old_select;
2270 struct bgp_path_info *pi;
2271 struct bgp_path_info *pi1;
2272 struct bgp_path_info *pi2;
2273 struct bgp_path_info *nextpi = NULL;
2274 int paths_eq, do_mpath, debug;
2275 struct list mp_list;
2276 char pfx_buf[PREFIX2STR_BUFFER];
2277 char path_buf[PATH_ADDPATH_STR_BUFFER];
2278
2279 bgp_mp_list_init(&mp_list);
2280 do_mpath =
2281 (mpath_cfg->maxpaths_ebgp > 1 || mpath_cfg->maxpaths_ibgp > 1);
2282
2283 debug = bgp_debug_bestpath(dest);
2284
2285 if (debug)
2286 prefix2str(bgp_dest_get_prefix(dest), pfx_buf, sizeof(pfx_buf));
2287
2288 dest->reason = bgp_path_selection_none;
2289 /* bgp deterministic-med */
2290 new_select = NULL;
2291 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)) {
2292
2293 /* Clear BGP_PATH_DMED_SELECTED for all paths */
2294 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
2295 pi1 = pi1->next)
2296 bgp_path_info_unset_flag(dest, pi1,
2297 BGP_PATH_DMED_SELECTED);
2298
2299 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
2300 pi1 = pi1->next) {
2301 if (CHECK_FLAG(pi1->flags, BGP_PATH_DMED_CHECK))
2302 continue;
2303 if (BGP_PATH_HOLDDOWN(pi1))
2304 continue;
2305 if (pi1->peer != bgp->peer_self)
2306 if (pi1->peer->status != Established)
2307 continue;
2308
2309 new_select = pi1;
2310 if (pi1->next) {
2311 for (pi2 = pi1->next; pi2; pi2 = pi2->next) {
2312 if (CHECK_FLAG(pi2->flags,
2313 BGP_PATH_DMED_CHECK))
2314 continue;
2315 if (BGP_PATH_HOLDDOWN(pi2))
2316 continue;
2317 if (pi2->peer != bgp->peer_self
2318 && !CHECK_FLAG(
2319 pi2->peer->sflags,
2320 PEER_STATUS_NSF_WAIT))
2321 if (pi2->peer->status
2322 != Established)
2323 continue;
2324
2325 if (!aspath_cmp_left(pi1->attr->aspath,
2326 pi2->attr->aspath)
2327 && !aspath_cmp_left_confed(
2328 pi1->attr->aspath,
2329 pi2->attr->aspath))
2330 continue;
2331
2332 if (bgp_path_info_cmp(
2333 bgp, pi2, new_select,
2334 &paths_eq, mpath_cfg, debug,
2335 pfx_buf, afi, safi,
2336 &dest->reason)) {
2337 bgp_path_info_unset_flag(
2338 dest, new_select,
2339 BGP_PATH_DMED_SELECTED);
2340 new_select = pi2;
2341 }
2342
2343 bgp_path_info_set_flag(
2344 dest, pi2, BGP_PATH_DMED_CHECK);
2345 }
2346 }
2347 bgp_path_info_set_flag(dest, new_select,
2348 BGP_PATH_DMED_CHECK);
2349 bgp_path_info_set_flag(dest, new_select,
2350 BGP_PATH_DMED_SELECTED);
2351
2352 if (debug) {
2353 bgp_path_info_path_with_addpath_rx_str(
2354 new_select, path_buf, sizeof(path_buf));
2355 zlog_debug(
2356 "%pBD: %s is the bestpath from AS %u",
2357 dest, path_buf,
2358 aspath_get_first_as(
2359 new_select->attr->aspath));
2360 }
2361 }
2362 }
2363
2364 /* Check old selected route and new selected route. */
2365 old_select = NULL;
2366 new_select = NULL;
2367 for (pi = bgp_dest_get_bgp_path_info(dest);
2368 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
2369 enum bgp_path_selection_reason reason;
2370
2371 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
2372 old_select = pi;
2373
2374 if (BGP_PATH_HOLDDOWN(pi)) {
2375 /* reap REMOVED routes, if needs be
2376 * selected route must stay for a while longer though
2377 */
2378 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
2379 && (pi != old_select))
2380 bgp_path_info_reap(dest, pi);
2381
2382 if (debug)
2383 zlog_debug("%s: pi %p in holddown", __func__,
2384 pi);
2385
2386 continue;
2387 }
2388
2389 if (pi->peer && pi->peer != bgp->peer_self
2390 && !CHECK_FLAG(pi->peer->sflags, PEER_STATUS_NSF_WAIT))
2391 if (pi->peer->status != Established) {
2392
2393 if (debug)
2394 zlog_debug(
2395 "%s: pi %p non self peer %s not estab state",
2396 __func__, pi, pi->peer->host);
2397
2398 continue;
2399 }
2400
2401 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)
2402 && (!CHECK_FLAG(pi->flags, BGP_PATH_DMED_SELECTED))) {
2403 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
2404 if (debug)
2405 zlog_debug("%s: pi %p dmed", __func__, pi);
2406 continue;
2407 }
2408
2409 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
2410
2411 reason = dest->reason;
2412 if (bgp_path_info_cmp(bgp, pi, new_select, &paths_eq, mpath_cfg,
2413 debug, pfx_buf, afi, safi,
2414 &dest->reason)) {
2415 if (new_select == NULL &&
2416 reason != bgp_path_selection_none)
2417 dest->reason = reason;
2418 new_select = pi;
2419 }
2420 }
2421
2422 /* Now that we know which path is the bestpath see if any of the other
2423 * paths
2424 * qualify as multipaths
2425 */
2426 if (debug) {
2427 if (new_select)
2428 bgp_path_info_path_with_addpath_rx_str(
2429 new_select, path_buf, sizeof(path_buf));
2430 else
2431 snprintf(path_buf, sizeof(path_buf), "NONE");
2432 zlog_debug(
2433 "%pBD: After path selection, newbest is %s oldbest was %s",
2434 dest, path_buf,
2435 old_select ? old_select->peer->host : "NONE");
2436 }
2437
2438 if (do_mpath && new_select) {
2439 for (pi = bgp_dest_get_bgp_path_info(dest);
2440 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
2441
2442 if (debug)
2443 bgp_path_info_path_with_addpath_rx_str(
2444 pi, path_buf, sizeof(path_buf));
2445
2446 if (pi == new_select) {
2447 if (debug)
2448 zlog_debug(
2449 "%pBD: %s is the bestpath, add to the multipath list",
2450 dest, path_buf);
2451 bgp_mp_list_add(&mp_list, pi);
2452 continue;
2453 }
2454
2455 if (BGP_PATH_HOLDDOWN(pi))
2456 continue;
2457
2458 if (pi->peer && pi->peer != bgp->peer_self
2459 && !CHECK_FLAG(pi->peer->sflags,
2460 PEER_STATUS_NSF_WAIT))
2461 if (pi->peer->status != Established)
2462 continue;
2463
2464 if (!bgp_path_info_nexthop_cmp(pi, new_select)) {
2465 if (debug)
2466 zlog_debug(
2467 "%pBD: %s has the same nexthop as the bestpath, skip it",
2468 dest, path_buf);
2469 continue;
2470 }
2471
2472 bgp_path_info_cmp(bgp, pi, new_select, &paths_eq,
2473 mpath_cfg, debug, pfx_buf, afi, safi,
2474 &dest->reason);
2475
2476 if (paths_eq) {
2477 if (debug)
2478 zlog_debug(
2479 "%pBD: %s is equivalent to the bestpath, add to the multipath list",
2480 dest, path_buf);
2481 bgp_mp_list_add(&mp_list, pi);
2482 }
2483 }
2484 }
2485
2486 bgp_path_info_mpath_update(dest, new_select, old_select, &mp_list,
2487 mpath_cfg);
2488 bgp_path_info_mpath_aggregate_update(new_select, old_select);
2489 bgp_mp_list_clear(&mp_list);
2490
2491 bgp_addpath_update_ids(bgp, dest, afi, safi);
2492
2493 result->old = old_select;
2494 result->new = new_select;
2495
2496 return;
2497 }
2498
2499 /*
2500 * A new route/change in bestpath of an existing route. Evaluate the path
2501 * for advertisement to the subgroup.
2502 */
2503 void subgroup_process_announce_selected(struct update_subgroup *subgrp,
2504 struct bgp_path_info *selected,
2505 struct bgp_dest *dest,
2506 uint32_t addpath_tx_id)
2507 {
2508 const struct prefix *p;
2509 struct peer *onlypeer;
2510 struct attr attr;
2511 afi_t afi;
2512 safi_t safi;
2513 struct bgp *bgp;
2514 bool advertise;
2515
2516 p = bgp_dest_get_prefix(dest);
2517 afi = SUBGRP_AFI(subgrp);
2518 safi = SUBGRP_SAFI(subgrp);
2519 bgp = SUBGRP_INST(subgrp);
2520 onlypeer = ((SUBGRP_PCOUNT(subgrp) == 1) ? (SUBGRP_PFIRST(subgrp))->peer
2521 : NULL);
2522
2523 if (BGP_DEBUG(update, UPDATE_OUT))
2524 zlog_debug("%s: p=%pFX, selected=%p", __func__, p, selected);
2525
2526 /* First update is deferred until ORF or ROUTE-REFRESH is received */
2527 if (onlypeer && CHECK_FLAG(onlypeer->af_sflags[afi][safi],
2528 PEER_STATUS_ORF_WAIT_REFRESH))
2529 return;
2530
2531 memset(&attr, 0, sizeof(struct attr));
2532 /* It's initialized in bgp_announce_check() */
2533
2534 /* Announcement to the subgroup. If the route is filtered withdraw it.
2535 * If BGP_NODE_FIB_INSTALL_PENDING is set and data plane install status
2536 * is pending (BGP_NODE_FIB_INSTALL_PENDING), do not advertise the
2537 * route
2538 */
2539 advertise = bgp_check_advertise(bgp, dest);
2540
2541 if (selected) {
2542 if (subgroup_announce_check(dest, selected, subgrp, p, &attr,
2543 false)) {
2544 /* Route is selected, if the route is already installed
2545 * in FIB, then it is advertised
2546 */
2547 if (advertise)
2548 bgp_adj_out_set_subgroup(dest, subgrp, &attr,
2549 selected);
2550 } else
2551 bgp_adj_out_unset_subgroup(dest, subgrp, 1,
2552 addpath_tx_id);
2553 }
2554
2555 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2556 else {
2557 bgp_adj_out_unset_subgroup(dest, subgrp, 1, addpath_tx_id);
2558 }
2559 }
2560
2561 /*
2562 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2563 * This is called at the end of route processing.
2564 */
2565 void bgp_zebra_clear_route_change_flags(struct bgp_dest *dest)
2566 {
2567 struct bgp_path_info *pi;
2568
2569 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
2570 if (BGP_PATH_HOLDDOWN(pi))
2571 continue;
2572 UNSET_FLAG(pi->flags, BGP_PATH_IGP_CHANGED);
2573 UNSET_FLAG(pi->flags, BGP_PATH_ATTR_CHANGED);
2574 }
2575 }
2576
2577 /*
2578 * Has the route changed from the RIB's perspective? This is invoked only
2579 * if the route selection returns the same best route as earlier - to
2580 * determine if we need to update zebra or not.
2581 */
2582 bool bgp_zebra_has_route_changed(struct bgp_path_info *selected)
2583 {
2584 struct bgp_path_info *mpinfo;
2585
2586 /* If this is multipath, check all selected paths for any nexthop
2587 * change or attribute change. Some attribute changes (e.g., community)
2588 * aren't of relevance to the RIB, but we'll update zebra to ensure
2589 * we handle the case of BGP nexthop change. This is the behavior
2590 * when the best path has an attribute change anyway.
2591 */
2592 if (CHECK_FLAG(selected->flags, BGP_PATH_IGP_CHANGED)
2593 || CHECK_FLAG(selected->flags, BGP_PATH_MULTIPATH_CHG)
2594 || CHECK_FLAG(selected->flags, BGP_PATH_LINK_BW_CHG))
2595 return true;
2596
2597 /*
2598 * If this is multipath, check all selected paths for any nexthop change
2599 */
2600 for (mpinfo = bgp_path_info_mpath_first(selected); mpinfo;
2601 mpinfo = bgp_path_info_mpath_next(mpinfo)) {
2602 if (CHECK_FLAG(mpinfo->flags, BGP_PATH_IGP_CHANGED)
2603 || CHECK_FLAG(mpinfo->flags, BGP_PATH_ATTR_CHANGED))
2604 return true;
2605 }
2606
2607 /* Nothing has changed from the RIB's perspective. */
2608 return false;
2609 }
2610
2611 struct bgp_process_queue {
2612 struct bgp *bgp;
2613 STAILQ_HEAD(, bgp_dest) pqueue;
2614 #define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2615 unsigned int flags;
2616 unsigned int queued;
2617 };
2618
2619 static void bgp_process_evpn_route_injection(struct bgp *bgp, afi_t afi,
2620 safi_t safi, struct bgp_dest *dest,
2621 struct bgp_path_info *new_select,
2622 struct bgp_path_info *old_select)
2623 {
2624 const struct prefix *p = bgp_dest_get_prefix(dest);
2625
2626 if ((afi != AFI_IP && afi != AFI_IP6) || (safi != SAFI_UNICAST))
2627 return;
2628
2629 if (advertise_type5_routes(bgp, afi) && new_select
2630 && is_route_injectable_into_evpn(new_select)) {
2631
2632 /* apply the route-map */
2633 if (bgp->adv_cmd_rmap[afi][safi].map) {
2634 route_map_result_t ret;
2635 struct bgp_path_info rmap_path;
2636 struct bgp_path_info_extra rmap_path_extra;
2637 struct attr dummy_attr;
2638
2639 dummy_attr = *new_select->attr;
2640
2641 /* Fill temp path_info */
2642 prep_for_rmap_apply(&rmap_path, &rmap_path_extra, dest,
2643 new_select, new_select->peer,
2644 &dummy_attr);
2645
2646 RESET_FLAG(dummy_attr.rmap_change_flags);
2647
2648 ret = route_map_apply(bgp->adv_cmd_rmap[afi][safi].map,
2649 p, &rmap_path);
2650
2651 if (ret == RMAP_DENYMATCH) {
2652 bgp_attr_flush(&dummy_attr);
2653 bgp_evpn_withdraw_type5_route(bgp, p, afi,
2654 safi);
2655 } else
2656 bgp_evpn_advertise_type5_route(
2657 bgp, p, &dummy_attr, afi, safi);
2658 } else {
2659 bgp_evpn_advertise_type5_route(bgp, p, new_select->attr,
2660 afi, safi);
2661 }
2662 } else if (advertise_type5_routes(bgp, afi) && old_select
2663 && is_route_injectable_into_evpn(old_select))
2664 bgp_evpn_withdraw_type5_route(bgp, p, afi, safi);
2665 }
2666
2667 /*
2668 * old_select = The old best path
2669 * new_select = the new best path
2670 *
2671 * if (!old_select && new_select)
2672 * We are sending new information on.
2673 *
2674 * if (old_select && new_select) {
2675 * if (new_select != old_select)
2676 * We have a new best path send a change
2677 * else
2678 * We've received a update with new attributes that needs
2679 * to be passed on.
2680 * }
2681 *
2682 * if (old_select && !new_select)
2683 * We have no eligible route that we can announce or the rn
2684 * is being removed.
2685 */
2686 static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
2687 afi_t afi, safi_t safi)
2688 {
2689 struct bgp_path_info *new_select;
2690 struct bgp_path_info *old_select;
2691 struct bgp_path_info_pair old_and_new;
2692 int debug = 0;
2693
2694 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)) {
2695 if (dest)
2696 debug = bgp_debug_bestpath(dest);
2697 if (debug)
2698 zlog_debug(
2699 "%s: bgp delete in progress, ignoring event, p=%pBD",
2700 __func__, dest);
2701 return;
2702 }
2703 /* Is it end of initial update? (after startup) */
2704 if (!dest) {
2705 quagga_timestamp(3, bgp->update_delay_zebra_resume_time,
2706 sizeof(bgp->update_delay_zebra_resume_time));
2707
2708 bgp->main_zebra_update_hold = 0;
2709 FOREACH_AFI_SAFI (afi, safi) {
2710 if (bgp_fibupd_safi(safi))
2711 bgp_zebra_announce_table(bgp, afi, safi);
2712 }
2713 bgp->main_peers_update_hold = 0;
2714
2715 bgp_start_routeadv(bgp);
2716 return;
2717 }
2718
2719 const struct prefix *p = bgp_dest_get_prefix(dest);
2720
2721 debug = bgp_debug_bestpath(dest);
2722 if (debug)
2723 zlog_debug("%s: p=%pBD afi=%s, safi=%s start", __func__, dest,
2724 afi2str(afi), safi2str(safi));
2725
2726 /* The best path calculation for the route is deferred if
2727 * BGP_NODE_SELECT_DEFER is set
2728 */
2729 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
2730 if (BGP_DEBUG(update, UPDATE_OUT))
2731 zlog_debug("SELECT_DEFER flag set for route %p", dest);
2732 return;
2733 }
2734
2735 /* Best path selection. */
2736 bgp_best_selection(bgp, dest, &bgp->maxpaths[afi][safi], &old_and_new,
2737 afi, safi);
2738 old_select = old_and_new.old;
2739 new_select = old_and_new.new;
2740
2741 /* Do we need to allocate or free labels?
2742 * Right now, since we only deal with per-prefix labels, it is not
2743 * necessary to do this upon changes to best path. Exceptions:
2744 * - label index has changed -> recalculate resulting label
2745 * - path_info sub_type changed -> switch to/from implicit-null
2746 * - no valid label (due to removed static label binding) -> get new one
2747 */
2748 if (bgp->allocate_mpls_labels[afi][safi]) {
2749 if (new_select) {
2750 if (!old_select
2751 || bgp_label_index_differs(new_select, old_select)
2752 || new_select->sub_type != old_select->sub_type
2753 || !bgp_is_valid_label(&dest->local_label)) {
2754 /* Enforced penultimate hop popping:
2755 * implicit-null for local routes, aggregate
2756 * and redistributed routes
2757 */
2758 if (new_select->sub_type == BGP_ROUTE_STATIC
2759 || new_select->sub_type
2760 == BGP_ROUTE_AGGREGATE
2761 || new_select->sub_type
2762 == BGP_ROUTE_REDISTRIBUTE) {
2763 if (CHECK_FLAG(
2764 dest->flags,
2765 BGP_NODE_REGISTERED_FOR_LABEL)
2766 || CHECK_FLAG(
2767 dest->flags,
2768 BGP_NODE_LABEL_REQUESTED))
2769 bgp_unregister_for_label(dest);
2770 label_ntop(MPLS_LABEL_IMPLICIT_NULL, 1,
2771 &dest->local_label);
2772 bgp_set_valid_label(&dest->local_label);
2773 } else
2774 bgp_register_for_label(dest,
2775 new_select);
2776 }
2777 } else if (CHECK_FLAG(dest->flags,
2778 BGP_NODE_REGISTERED_FOR_LABEL)
2779 || CHECK_FLAG(dest->flags,
2780 BGP_NODE_LABEL_REQUESTED)) {
2781 bgp_unregister_for_label(dest);
2782 }
2783 } else if (CHECK_FLAG(dest->flags, BGP_NODE_REGISTERED_FOR_LABEL)
2784 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_REQUESTED)) {
2785 bgp_unregister_for_label(dest);
2786 }
2787
2788 if (debug)
2789 zlog_debug(
2790 "%s: p=%pBD afi=%s, safi=%s, old_select=%p, new_select=%p",
2791 __func__, dest, afi2str(afi), safi2str(safi),
2792 old_select, new_select);
2793
2794 /* If best route remains the same and this is not due to user-initiated
2795 * clear, see exactly what needs to be done.
2796 */
2797 if (old_select && old_select == new_select
2798 && !CHECK_FLAG(dest->flags, BGP_NODE_USER_CLEAR)
2799 && !CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
2800 && !bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
2801 if (bgp_zebra_has_route_changed(old_select)) {
2802 #ifdef ENABLE_BGP_VNC
2803 vnc_import_bgp_add_route(bgp, p, old_select);
2804 vnc_import_bgp_exterior_add_route(bgp, p, old_select);
2805 #endif
2806 if (bgp_fibupd_safi(safi)
2807 && !bgp_option_check(BGP_OPT_NO_FIB)) {
2808
2809 if (new_select->type == ZEBRA_ROUTE_BGP
2810 && (new_select->sub_type == BGP_ROUTE_NORMAL
2811 || new_select->sub_type
2812 == BGP_ROUTE_IMPORTED))
2813
2814 bgp_zebra_announce(dest, p, old_select,
2815 bgp, afi, safi);
2816 }
2817 }
2818
2819 /* If there is a change of interest to peers, reannounce the
2820 * route. */
2821 if (CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
2822 || CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
2823 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED)) {
2824 group_announce_route(bgp, afi, safi, dest, new_select);
2825
2826 /* unicast routes must also be annouced to
2827 * labeled-unicast update-groups */
2828 if (safi == SAFI_UNICAST)
2829 group_announce_route(bgp, afi,
2830 SAFI_LABELED_UNICAST, dest,
2831 new_select);
2832
2833 UNSET_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED);
2834 UNSET_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED);
2835 }
2836
2837 /* advertise/withdraw type-5 routes */
2838 if (CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
2839 || CHECK_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG))
2840 bgp_process_evpn_route_injection(
2841 bgp, afi, safi, dest, old_select, old_select);
2842
2843 UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG);
2844 UNSET_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG);
2845 bgp_zebra_clear_route_change_flags(dest);
2846 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
2847 return;
2848 }
2849
2850 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2851 */
2852 UNSET_FLAG(dest->flags, BGP_NODE_USER_CLEAR);
2853
2854 /* bestpath has changed; bump version */
2855 if (old_select || new_select) {
2856 bgp_bump_version(dest);
2857
2858 if (!bgp->t_rmap_def_originate_eval) {
2859 bgp_lock(bgp);
2860 thread_add_timer(
2861 bm->master,
2862 update_group_refresh_default_originate_route_map,
2863 bgp, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER,
2864 &bgp->t_rmap_def_originate_eval);
2865 }
2866 }
2867
2868 if (old_select)
2869 bgp_path_info_unset_flag(dest, old_select, BGP_PATH_SELECTED);
2870 if (new_select) {
2871 if (debug)
2872 zlog_debug("%s: setting SELECTED flag", __func__);
2873 bgp_path_info_set_flag(dest, new_select, BGP_PATH_SELECTED);
2874 bgp_path_info_unset_flag(dest, new_select,
2875 BGP_PATH_ATTR_CHANGED);
2876 UNSET_FLAG(new_select->flags, BGP_PATH_MULTIPATH_CHG);
2877 UNSET_FLAG(new_select->flags, BGP_PATH_LINK_BW_CHG);
2878 }
2879
2880 #ifdef ENABLE_BGP_VNC
2881 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
2882 if (old_select != new_select) {
2883 if (old_select) {
2884 vnc_import_bgp_exterior_del_route(bgp, p,
2885 old_select);
2886 vnc_import_bgp_del_route(bgp, p, old_select);
2887 }
2888 if (new_select) {
2889 vnc_import_bgp_exterior_add_route(bgp, p,
2890 new_select);
2891 vnc_import_bgp_add_route(bgp, p, new_select);
2892 }
2893 }
2894 }
2895 #endif
2896
2897 group_announce_route(bgp, afi, safi, dest, new_select);
2898
2899 /* unicast routes must also be annouced to labeled-unicast update-groups
2900 */
2901 if (safi == SAFI_UNICAST)
2902 group_announce_route(bgp, afi, SAFI_LABELED_UNICAST, dest,
2903 new_select);
2904
2905 /* FIB update. */
2906 if (bgp_fibupd_safi(safi) && (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW)
2907 && !bgp_option_check(BGP_OPT_NO_FIB)) {
2908 if (new_select && new_select->type == ZEBRA_ROUTE_BGP
2909 && (new_select->sub_type == BGP_ROUTE_NORMAL
2910 || new_select->sub_type == BGP_ROUTE_AGGREGATE
2911 || new_select->sub_type == BGP_ROUTE_IMPORTED)) {
2912
2913 /* if this is an evpn imported type-5 prefix,
2914 * we need to withdraw the route first to clear
2915 * the nh neigh and the RMAC entry.
2916 */
2917 if (old_select &&
2918 is_route_parent_evpn(old_select))
2919 bgp_zebra_withdraw(p, old_select, bgp, safi);
2920
2921 bgp_zebra_announce(dest, p, new_select, bgp, afi, safi);
2922 } else {
2923 /* Withdraw the route from the kernel. */
2924 if (old_select && old_select->type == ZEBRA_ROUTE_BGP
2925 && (old_select->sub_type == BGP_ROUTE_NORMAL
2926 || old_select->sub_type == BGP_ROUTE_AGGREGATE
2927 || old_select->sub_type == BGP_ROUTE_IMPORTED))
2928
2929 bgp_zebra_withdraw(p, old_select, bgp, safi);
2930 }
2931 }
2932
2933 bgp_process_evpn_route_injection(bgp, afi, safi, dest, new_select,
2934 old_select);
2935
2936 /* Clear any route change flags. */
2937 bgp_zebra_clear_route_change_flags(dest);
2938
2939 /* Reap old select bgp_path_info, if it has been removed */
2940 if (old_select && CHECK_FLAG(old_select->flags, BGP_PATH_REMOVED))
2941 bgp_path_info_reap(dest, old_select);
2942
2943 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
2944 return;
2945 }
2946
2947 /* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
2948 int bgp_best_path_select_defer(struct bgp *bgp, afi_t afi, safi_t safi)
2949 {
2950 struct bgp_dest *dest;
2951 int cnt = 0;
2952 struct afi_safi_info *thread_info;
2953
2954 if (bgp->gr_info[afi][safi].t_route_select) {
2955 struct thread *t = bgp->gr_info[afi][safi].t_route_select;
2956
2957 thread_info = THREAD_ARG(t);
2958 XFREE(MTYPE_TMP, thread_info);
2959 BGP_TIMER_OFF(bgp->gr_info[afi][safi].t_route_select);
2960 }
2961
2962 if (BGP_DEBUG(update, UPDATE_OUT)) {
2963 zlog_debug("%s: processing route for %s : cnt %d", __func__,
2964 get_afi_safi_str(afi, safi, false),
2965 bgp->gr_info[afi][safi].gr_deferred);
2966 }
2967
2968 /* Process the route list */
2969 for (dest = bgp_table_top(bgp->rib[afi][safi]);
2970 dest && bgp->gr_info[afi][safi].gr_deferred != 0;
2971 dest = bgp_route_next(dest)) {
2972 if (!CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER))
2973 continue;
2974
2975 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
2976 bgp->gr_info[afi][safi].gr_deferred--;
2977 bgp_process_main_one(bgp, dest, afi, safi);
2978 cnt++;
2979 if (cnt >= BGP_MAX_BEST_ROUTE_SELECT) {
2980 bgp_dest_unlock_node(dest);
2981 break;
2982 }
2983 }
2984
2985 /* Send EOR message when all routes are processed */
2986 if (!bgp->gr_info[afi][safi].gr_deferred) {
2987 bgp_send_delayed_eor(bgp);
2988 /* Send route processing complete message to RIB */
2989 bgp_zebra_update(afi, safi, bgp->vrf_id,
2990 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE);
2991 return 0;
2992 }
2993
2994 thread_info = XMALLOC(MTYPE_TMP, sizeof(struct afi_safi_info));
2995
2996 thread_info->afi = afi;
2997 thread_info->safi = safi;
2998 thread_info->bgp = bgp;
2999
3000 /* If there are more routes to be processed, start the
3001 * selection timer
3002 */
3003 thread_add_timer(bm->master, bgp_route_select_timer_expire, thread_info,
3004 BGP_ROUTE_SELECT_DELAY,
3005 &bgp->gr_info[afi][safi].t_route_select);
3006 return 0;
3007 }
3008
3009 static wq_item_status bgp_process_wq(struct work_queue *wq, void *data)
3010 {
3011 struct bgp_process_queue *pqnode = data;
3012 struct bgp *bgp = pqnode->bgp;
3013 struct bgp_table *table;
3014 struct bgp_dest *dest;
3015
3016 /* eoiu marker */
3017 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)) {
3018 bgp_process_main_one(bgp, NULL, 0, 0);
3019 /* should always have dedicated wq call */
3020 assert(STAILQ_FIRST(&pqnode->pqueue) == NULL);
3021 return WQ_SUCCESS;
3022 }
3023
3024 while (!STAILQ_EMPTY(&pqnode->pqueue)) {
3025 dest = STAILQ_FIRST(&pqnode->pqueue);
3026 STAILQ_REMOVE_HEAD(&pqnode->pqueue, pq);
3027 STAILQ_NEXT(dest, pq) = NULL; /* complete unlink */
3028 table = bgp_dest_table(dest);
3029 /* note, new DESTs may be added as part of processing */
3030 bgp_process_main_one(bgp, dest, table->afi, table->safi);
3031
3032 bgp_dest_unlock_node(dest);
3033 bgp_table_unlock(table);
3034 }
3035
3036 return WQ_SUCCESS;
3037 }
3038
3039 static void bgp_processq_del(struct work_queue *wq, void *data)
3040 {
3041 struct bgp_process_queue *pqnode = data;
3042
3043 bgp_unlock(pqnode->bgp);
3044
3045 XFREE(MTYPE_BGP_PROCESS_QUEUE, pqnode);
3046 }
3047
3048 void bgp_process_queue_init(struct bgp *bgp)
3049 {
3050 if (!bgp->process_queue) {
3051 char name[BUFSIZ];
3052
3053 snprintf(name, BUFSIZ, "process_queue %s", bgp->name_pretty);
3054 bgp->process_queue = work_queue_new(bm->master, name);
3055 }
3056
3057 bgp->process_queue->spec.workfunc = &bgp_process_wq;
3058 bgp->process_queue->spec.del_item_data = &bgp_processq_del;
3059 bgp->process_queue->spec.max_retries = 0;
3060 bgp->process_queue->spec.hold = 50;
3061 /* Use a higher yield value of 50ms for main queue processing */
3062 bgp->process_queue->spec.yield = 50 * 1000L;
3063 }
3064
3065 static struct bgp_process_queue *bgp_processq_alloc(struct bgp *bgp)
3066 {
3067 struct bgp_process_queue *pqnode;
3068
3069 pqnode = XCALLOC(MTYPE_BGP_PROCESS_QUEUE,
3070 sizeof(struct bgp_process_queue));
3071
3072 /* unlocked in bgp_processq_del */
3073 pqnode->bgp = bgp_lock(bgp);
3074 STAILQ_INIT(&pqnode->pqueue);
3075
3076 return pqnode;
3077 }
3078
3079 void bgp_process(struct bgp *bgp, struct bgp_dest *dest, afi_t afi, safi_t safi)
3080 {
3081 #define ARBITRARY_PROCESS_QLEN 10000
3082 struct work_queue *wq = bgp->process_queue;
3083 struct bgp_process_queue *pqnode;
3084 int pqnode_reuse = 0;
3085
3086 /* already scheduled for processing? */
3087 if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED))
3088 return;
3089
3090 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
3091 * the workqueue
3092 */
3093 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
3094 if (BGP_DEBUG(update, UPDATE_OUT))
3095 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
3096 dest);
3097 return;
3098 }
3099
3100 if (wq == NULL)
3101 return;
3102
3103 /* Add route nodes to an existing work queue item until reaching the
3104 limit only if is from the same BGP view and it's not an EOIU marker
3105 */
3106 if (work_queue_item_count(wq)) {
3107 struct work_queue_item *item = work_queue_last_item(wq);
3108 pqnode = item->data;
3109
3110 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)
3111 || pqnode->bgp != bgp
3112 || pqnode->queued >= ARBITRARY_PROCESS_QLEN)
3113 pqnode = bgp_processq_alloc(bgp);
3114 else
3115 pqnode_reuse = 1;
3116 } else
3117 pqnode = bgp_processq_alloc(bgp);
3118 /* all unlocked in bgp_process_wq */
3119 bgp_table_lock(bgp_dest_table(dest));
3120
3121 SET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
3122 bgp_dest_lock_node(dest);
3123
3124 /* can't be enqueued twice */
3125 assert(STAILQ_NEXT(dest, pq) == NULL);
3126 STAILQ_INSERT_TAIL(&pqnode->pqueue, dest, pq);
3127 pqnode->queued++;
3128
3129 if (!pqnode_reuse)
3130 work_queue_add(wq, pqnode);
3131
3132 return;
3133 }
3134
3135 void bgp_add_eoiu_mark(struct bgp *bgp)
3136 {
3137 struct bgp_process_queue *pqnode;
3138
3139 if (bgp->process_queue == NULL)
3140 return;
3141
3142 pqnode = bgp_processq_alloc(bgp);
3143
3144 SET_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER);
3145 work_queue_add(bgp->process_queue, pqnode);
3146 }
3147
3148 static int bgp_maximum_prefix_restart_timer(struct thread *thread)
3149 {
3150 struct peer *peer;
3151
3152 peer = THREAD_ARG(thread);
3153 peer->t_pmax_restart = NULL;
3154
3155 if (bgp_debug_neighbor_events(peer))
3156 zlog_debug(
3157 "%s Maximum-prefix restart timer expired, restore peering",
3158 peer->host);
3159
3160 if ((peer_clear(peer, NULL) < 0) && bgp_debug_neighbor_events(peer))
3161 zlog_debug("%s: %s peer_clear failed", __func__, peer->host);
3162
3163 return 0;
3164 }
3165
3166 static uint32_t bgp_filtered_routes_count(struct peer *peer, afi_t afi,
3167 safi_t safi)
3168 {
3169 uint32_t count = 0;
3170 bool filtered = false;
3171 struct bgp_dest *dest;
3172 struct bgp_adj_in *ain;
3173 struct attr attr = {};
3174 struct bgp_table *table = peer->bgp->rib[afi][safi];
3175
3176 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
3177 for (ain = dest->adj_in; ain; ain = ain->next) {
3178 const struct prefix *rn_p = bgp_dest_get_prefix(dest);
3179
3180 attr = *ain->attr;
3181
3182 if (bgp_input_filter(peer, rn_p, &attr, afi, safi)
3183 == FILTER_DENY)
3184 filtered = true;
3185
3186 if (bgp_input_modifier(
3187 peer, rn_p, &attr, afi, safi,
3188 ROUTE_MAP_IN_NAME(&peer->filter[afi][safi]),
3189 NULL, 0, NULL)
3190 == RMAP_DENY)
3191 filtered = true;
3192
3193 if (filtered)
3194 count++;
3195
3196 bgp_attr_undup(&attr, ain->attr);
3197 }
3198 }
3199
3200 return count;
3201 }
3202
3203 bool bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi,
3204 int always)
3205 {
3206 iana_afi_t pkt_afi;
3207 iana_safi_t pkt_safi;
3208 uint32_t pcount = (CHECK_FLAG(peer->af_flags[afi][safi],
3209 PEER_FLAG_MAX_PREFIX_FORCE))
3210 ? bgp_filtered_routes_count(peer, afi, safi)
3211 + peer->pcount[afi][safi]
3212 : peer->pcount[afi][safi];
3213
3214 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
3215 return false;
3216
3217 if (pcount > peer->pmax[afi][safi]) {
3218 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3219 PEER_STATUS_PREFIX_LIMIT)
3220 && !always)
3221 return false;
3222
3223 zlog_info(
3224 "%%MAXPFXEXCEED: No. of %s prefix received from %s %u exceed, limit %u",
3225 get_afi_safi_str(afi, safi, false), peer->host, pcount,
3226 peer->pmax[afi][safi]);
3227 SET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT);
3228
3229 if (CHECK_FLAG(peer->af_flags[afi][safi],
3230 PEER_FLAG_MAX_PREFIX_WARNING))
3231 return false;
3232
3233 /* Convert AFI, SAFI to values for packet. */
3234 pkt_afi = afi_int2iana(afi);
3235 pkt_safi = safi_int2iana(safi);
3236 {
3237 uint8_t ndata[7];
3238
3239 ndata[0] = (pkt_afi >> 8);
3240 ndata[1] = pkt_afi;
3241 ndata[2] = pkt_safi;
3242 ndata[3] = (peer->pmax[afi][safi] >> 24);
3243 ndata[4] = (peer->pmax[afi][safi] >> 16);
3244 ndata[5] = (peer->pmax[afi][safi] >> 8);
3245 ndata[6] = (peer->pmax[afi][safi]);
3246
3247 SET_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
3248 bgp_notify_send_with_data(peer, BGP_NOTIFY_CEASE,
3249 BGP_NOTIFY_CEASE_MAX_PREFIX,
3250 ndata, 7);
3251 }
3252
3253 /* Dynamic peers will just close their connection. */
3254 if (peer_dynamic_neighbor(peer))
3255 return true;
3256
3257 /* restart timer start */
3258 if (peer->pmax_restart[afi][safi]) {
3259 peer->v_pmax_restart =
3260 peer->pmax_restart[afi][safi] * 60;
3261
3262 if (bgp_debug_neighbor_events(peer))
3263 zlog_debug(
3264 "%s Maximum-prefix restart timer started for %d secs",
3265 peer->host, peer->v_pmax_restart);
3266
3267 BGP_TIMER_ON(peer->t_pmax_restart,
3268 bgp_maximum_prefix_restart_timer,
3269 peer->v_pmax_restart);
3270 }
3271
3272 return true;
3273 } else
3274 UNSET_FLAG(peer->af_sflags[afi][safi],
3275 PEER_STATUS_PREFIX_LIMIT);
3276
3277 if (pcount
3278 > (peer->pmax[afi][safi] * peer->pmax_threshold[afi][safi] / 100)) {
3279 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3280 PEER_STATUS_PREFIX_THRESHOLD)
3281 && !always)
3282 return false;
3283
3284 zlog_info(
3285 "%%MAXPFX: No. of %s prefix received from %s reaches %u, max %u",
3286 get_afi_safi_str(afi, safi, false), peer->host, pcount,
3287 peer->pmax[afi][safi]);
3288 SET_FLAG(peer->af_sflags[afi][safi],
3289 PEER_STATUS_PREFIX_THRESHOLD);
3290 } else
3291 UNSET_FLAG(peer->af_sflags[afi][safi],
3292 PEER_STATUS_PREFIX_THRESHOLD);
3293 return false;
3294 }
3295
3296 /* Unconditionally remove the route from the RIB, without taking
3297 * damping into consideration (eg, because the session went down)
3298 */
3299 void bgp_rib_remove(struct bgp_dest *dest, struct bgp_path_info *pi,
3300 struct peer *peer, afi_t afi, safi_t safi)
3301 {
3302
3303 struct bgp *bgp = NULL;
3304 bool delete_route = false;
3305
3306 bgp_aggregate_decrement(peer->bgp, bgp_dest_get_prefix(dest), pi, afi,
3307 safi);
3308
3309 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
3310 bgp_path_info_delete(dest, pi); /* keep historical info */
3311
3312 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3313 * flag
3314 */
3315 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3316 delete_route = true;
3317 else if (bgp_dest_set_defer_flag(dest, true) < 0)
3318 delete_route = true;
3319 if (delete_route) {
3320 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
3321 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
3322 bgp = pi->peer->bgp;
3323 bgp->gr_info[afi][safi].gr_deferred--;
3324 }
3325 }
3326 }
3327
3328 hook_call(bgp_process, peer->bgp, afi, safi, dest, peer, true);
3329 bgp_process(peer->bgp, dest, afi, safi);
3330 }
3331
3332 static void bgp_rib_withdraw(struct bgp_dest *dest, struct bgp_path_info *pi,
3333 struct peer *peer, afi_t afi, safi_t safi,
3334 struct prefix_rd *prd)
3335 {
3336 const struct prefix *p = bgp_dest_get_prefix(dest);
3337
3338 /* apply dampening, if result is suppressed, we'll be retaining
3339 * the bgp_path_info in the RIB for historical reference.
3340 */
3341 if (peer->sort == BGP_PEER_EBGP) {
3342 if (get_active_bdc_from_pi(pi, afi, safi)) {
3343 if (bgp_damp_withdraw(pi, dest, afi, safi, 0)
3344 == BGP_DAMP_SUPPRESSED) {
3345 bgp_aggregate_decrement(peer->bgp, p, pi, afi,
3346 safi);
3347 return;
3348 }
3349 }
3350 }
3351
3352 #ifdef ENABLE_BGP_VNC
3353 if (safi == SAFI_MPLS_VPN) {
3354 struct bgp_dest *pdest = NULL;
3355 struct bgp_table *table = NULL;
3356
3357 pdest = bgp_node_get(peer->bgp->rib[afi][safi],
3358 (struct prefix *)prd);
3359 if (bgp_dest_has_bgp_path_info_data(pdest)) {
3360 table = bgp_dest_get_bgp_table_info(pdest);
3361
3362 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3363 peer->bgp, prd, table, p, pi);
3364 }
3365 bgp_dest_unlock_node(pdest);
3366 }
3367 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
3368 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
3369
3370 vnc_import_bgp_del_route(peer->bgp, p, pi);
3371 vnc_import_bgp_exterior_del_route(peer->bgp, p, pi);
3372 }
3373 }
3374 #endif
3375
3376 /* If this is an EVPN route, process for un-import. */
3377 if (safi == SAFI_EVPN)
3378 bgp_evpn_unimport_route(peer->bgp, afi, safi, p, pi);
3379
3380 bgp_rib_remove(dest, pi, peer, afi, safi);
3381 }
3382
3383 struct bgp_path_info *info_make(int type, int sub_type, unsigned short instance,
3384 struct peer *peer, struct attr *attr,
3385 struct bgp_dest *dest)
3386 {
3387 struct bgp_path_info *new;
3388
3389 /* Make new BGP info. */
3390 new = XCALLOC(MTYPE_BGP_ROUTE, sizeof(struct bgp_path_info));
3391 new->type = type;
3392 new->instance = instance;
3393 new->sub_type = sub_type;
3394 new->peer = peer;
3395 new->attr = attr;
3396 new->uptime = bgp_clock();
3397 new->net = dest;
3398 return new;
3399 }
3400
3401 static void overlay_index_update(struct attr *attr,
3402 union gw_addr *gw_ip)
3403 {
3404 if (!attr)
3405 return;
3406 if (gw_ip == NULL) {
3407 struct bgp_route_evpn eo;
3408
3409 memset(&eo, 0, sizeof(eo));
3410 bgp_attr_set_evpn_overlay(attr, &eo);
3411 } else {
3412 struct bgp_route_evpn eo = {.gw_ip = *gw_ip};
3413
3414 bgp_attr_set_evpn_overlay(attr, &eo);
3415 }
3416 }
3417
3418 static bool overlay_index_equal(afi_t afi, struct bgp_path_info *path,
3419 union gw_addr *gw_ip)
3420 {
3421 const struct bgp_route_evpn *eo = bgp_attr_get_evpn_overlay(path->attr);
3422 union gw_addr path_gw_ip, *path_gw_ip_remote;
3423 union {
3424 esi_t esi;
3425 union gw_addr ip;
3426 } temp;
3427
3428 if (afi != AFI_L2VPN)
3429 return true;
3430
3431 path_gw_ip = eo->gw_ip;
3432
3433 if (gw_ip == NULL) {
3434 memset(&temp, 0, sizeof(temp));
3435 path_gw_ip_remote = &temp.ip;
3436 } else
3437 path_gw_ip_remote = gw_ip;
3438
3439 return !!memcmp(&path_gw_ip, path_gw_ip_remote, sizeof(union gw_addr));
3440 }
3441
3442 /* Check if received nexthop is valid or not. */
3443 bool bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
3444 uint8_t type, uint8_t stype, struct attr *attr,
3445 struct bgp_dest *dest)
3446 {
3447 bool ret = false;
3448 bool is_bgp_static_route =
3449 (type == ZEBRA_ROUTE_BGP && stype == BGP_ROUTE_STATIC) ? true
3450 : false;
3451
3452 /*
3453 * Only validated for unicast and multicast currently.
3454 * Also valid for EVPN where the nexthop is an IP address.
3455 * If we are a bgp static route being checked then there is
3456 * no need to check to see if the nexthop is martian as
3457 * that it should be ok.
3458 */
3459 if (is_bgp_static_route ||
3460 (safi != SAFI_UNICAST && safi != SAFI_MULTICAST && safi != SAFI_EVPN))
3461 return false;
3462
3463 /* If NEXT_HOP is present, validate it. */
3464 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
3465 if (attr->nexthop.s_addr == INADDR_ANY
3466 || IPV4_CLASS_DE(ntohl(attr->nexthop.s_addr))
3467 || bgp_nexthop_self(bgp, afi, type, stype, attr, dest))
3468 return true;
3469 }
3470
3471 /* If MP_NEXTHOP is present, validate it. */
3472 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3473 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3474 * it is not an IPv6 link-local address.
3475 *
3476 * If we receive an UPDATE with nexthop length set to 32 bytes
3477 * we shouldn't discard an UPDATE if it's set to (::).
3478 * The link-local (2st) is validated along the code path later.
3479 */
3480 if (attr->mp_nexthop_len) {
3481 switch (attr->mp_nexthop_len) {
3482 case BGP_ATTR_NHLEN_IPV4:
3483 case BGP_ATTR_NHLEN_VPNV4:
3484 ret = (attr->mp_nexthop_global_in.s_addr == INADDR_ANY
3485 || IPV4_CLASS_DE(
3486 ntohl(attr->mp_nexthop_global_in.s_addr))
3487 || bgp_nexthop_self(bgp, afi, type, stype, attr,
3488 dest));
3489 break;
3490
3491 case BGP_ATTR_NHLEN_IPV6_GLOBAL:
3492 case BGP_ATTR_NHLEN_VPNV6_GLOBAL:
3493 ret = (IN6_IS_ADDR_UNSPECIFIED(
3494 &attr->mp_nexthop_global)
3495 || IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3496 || IN6_IS_ADDR_MULTICAST(
3497 &attr->mp_nexthop_global)
3498 || bgp_nexthop_self(bgp, afi, type, stype, attr,
3499 dest));
3500 break;
3501 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
3502 ret = (IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3503 || IN6_IS_ADDR_MULTICAST(
3504 &attr->mp_nexthop_global)
3505 || bgp_nexthop_self(bgp, afi, type, stype, attr,
3506 dest));
3507 break;
3508
3509 default:
3510 ret = true;
3511 break;
3512 }
3513 }
3514
3515 return ret;
3516 }
3517
3518 static void bgp_attr_add_no_export_community(struct attr *attr)
3519 {
3520 struct community *old;
3521 struct community *new;
3522 struct community *merge;
3523 struct community *no_export;
3524
3525 old = attr->community;
3526 no_export = community_str2com("no-export");
3527
3528 assert(no_export);
3529
3530 if (old) {
3531 merge = community_merge(community_dup(old), no_export);
3532
3533 if (!old->refcnt)
3534 community_free(&old);
3535
3536 new = community_uniq_sort(merge);
3537 community_free(&merge);
3538 } else {
3539 new = community_dup(no_export);
3540 }
3541
3542 community_free(&no_export);
3543
3544 attr->community = new;
3545 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
3546 }
3547
3548 int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
3549 struct attr *attr, afi_t afi, safi_t safi, int type,
3550 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
3551 uint32_t num_labels, int soft_reconfig,
3552 struct bgp_route_evpn *evpn)
3553 {
3554 int ret;
3555 int aspath_loop_count = 0;
3556 struct bgp_dest *dest;
3557 struct bgp *bgp;
3558 struct attr new_attr;
3559 struct attr *attr_new;
3560 struct bgp_path_info *pi;
3561 struct bgp_path_info *new;
3562 struct bgp_path_info_extra *extra;
3563 const char *reason;
3564 char pfx_buf[BGP_PRD_PATH_STRLEN];
3565 int connected = 0;
3566 int do_loop_check = 1;
3567 int has_valid_label = 0;
3568 afi_t nh_afi;
3569 uint8_t pi_type = 0;
3570 uint8_t pi_sub_type = 0;
3571
3572 if (frrtrace_enabled(frr_bgp, process_update)) {
3573 char pfxprint[PREFIX2STR_BUFFER];
3574
3575 prefix2str(p, pfxprint, sizeof(pfxprint));
3576 frrtrace(6, frr_bgp, process_update, peer, pfxprint, addpath_id,
3577 afi, safi, attr);
3578 }
3579
3580 #ifdef ENABLE_BGP_VNC
3581 int vnc_implicit_withdraw = 0;
3582 #endif
3583 int same_attr = 0;
3584
3585 memset(&new_attr, 0, sizeof(struct attr));
3586 new_attr.label_index = BGP_INVALID_LABEL_INDEX;
3587 new_attr.label = MPLS_INVALID_LABEL;
3588
3589 bgp = peer->bgp;
3590 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
3591 /* TODO: Check to see if we can get rid of "is_valid_label" */
3592 if (afi == AFI_L2VPN && safi == SAFI_EVPN)
3593 has_valid_label = (num_labels > 0) ? 1 : 0;
3594 else
3595 has_valid_label = bgp_is_valid_label(label);
3596
3597 if (has_valid_label)
3598 assert(label != NULL);
3599
3600 /* When peer's soft reconfiguration enabled. Record input packet in
3601 Adj-RIBs-In. */
3602 if (!soft_reconfig
3603 && CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
3604 && peer != bgp->peer_self)
3605 bgp_adj_in_set(dest, peer, attr, addpath_id);
3606
3607 /* Check previously received route. */
3608 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
3609 if (pi->peer == peer && pi->type == type
3610 && pi->sub_type == sub_type
3611 && pi->addpath_rx_id == addpath_id)
3612 break;
3613
3614 /* AS path local-as loop check. */
3615 if (peer->change_local_as) {
3616 if (peer->allowas_in[afi][safi])
3617 aspath_loop_count = peer->allowas_in[afi][safi];
3618 else if (!CHECK_FLAG(peer->flags,
3619 PEER_FLAG_LOCAL_AS_NO_PREPEND))
3620 aspath_loop_count = 1;
3621
3622 if (aspath_loop_check(attr->aspath, peer->change_local_as)
3623 > aspath_loop_count) {
3624 peer->stat_pfx_aspath_loop++;
3625 reason = "as-path contains our own AS A;";
3626 goto filtered;
3627 }
3628 }
3629
3630 /* If the peer is configured for "allowas-in origin" and the last ASN in
3631 * the
3632 * as-path is our ASN then we do not need to call aspath_loop_check
3633 */
3634 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN))
3635 if (aspath_get_last_as(attr->aspath) == bgp->as)
3636 do_loop_check = 0;
3637
3638 /* AS path loop check. */
3639 if (do_loop_check) {
3640 if (aspath_loop_check(attr->aspath, bgp->as)
3641 > peer->allowas_in[afi][safi]
3642 || (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)
3643 && aspath_loop_check(attr->aspath, bgp->confed_id)
3644 > peer->allowas_in[afi][safi])) {
3645 peer->stat_pfx_aspath_loop++;
3646 reason = "as-path contains our own AS;";
3647 goto filtered;
3648 }
3649 }
3650
3651 /* Route reflector originator ID check. */
3652 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
3653 && IPV4_ADDR_SAME(&bgp->router_id, &attr->originator_id)) {
3654 peer->stat_pfx_originator_loop++;
3655 reason = "originator is us;";
3656 goto filtered;
3657 }
3658
3659 /* Route reflector cluster ID check. */
3660 if (bgp_cluster_filter(peer, attr)) {
3661 peer->stat_pfx_cluster_loop++;
3662 reason = "reflected from the same cluster;";
3663 goto filtered;
3664 }
3665
3666 /* Apply incoming filter. */
3667 if (bgp_input_filter(peer, p, attr, afi, safi) == FILTER_DENY) {
3668 peer->stat_pfx_filter++;
3669 reason = "filter;";
3670 goto filtered;
3671 }
3672
3673 /* RFC 8212 to prevent route leaks.
3674 * This specification intends to improve this situation by requiring the
3675 * explicit configuration of both BGP Import and Export Policies for any
3676 * External BGP (EBGP) session such as customers, peers, or
3677 * confederation boundaries for all enabled address families. Through
3678 * codification of the aforementioned requirement, operators will
3679 * benefit from consistent behavior across different BGP
3680 * implementations.
3681 */
3682 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
3683 if (!bgp_inbound_policy_exists(peer,
3684 &peer->filter[afi][safi])) {
3685 reason = "inbound policy missing";
3686 goto filtered;
3687 }
3688
3689 /* draft-ietf-idr-deprecate-as-set-confed-set
3690 * Filter routes having AS_SET or AS_CONFED_SET in the path.
3691 * Eventually, This document (if approved) updates RFC 4271
3692 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
3693 * and obsoletes RFC 6472.
3694 */
3695 if (peer->bgp->reject_as_sets)
3696 if (aspath_check_as_sets(attr->aspath)) {
3697 reason =
3698 "as-path contains AS_SET or AS_CONFED_SET type;";
3699 goto filtered;
3700 }
3701
3702 new_attr = *attr;
3703
3704 /* Apply incoming route-map.
3705 * NB: new_attr may now contain newly allocated values from route-map
3706 * "set"
3707 * commands, so we need bgp_attr_flush in the error paths, until we
3708 * intern
3709 * the attr (which takes over the memory references) */
3710 if (bgp_input_modifier(peer, p, &new_attr, afi, safi, NULL, label,
3711 num_labels, dest)
3712 == RMAP_DENY) {
3713 peer->stat_pfx_filter++;
3714 reason = "route-map;";
3715 bgp_attr_flush(&new_attr);
3716 goto filtered;
3717 }
3718
3719 if (pi && pi->attr->rmap_table_id != new_attr.rmap_table_id) {
3720 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3721 /* remove from RIB previous entry */
3722 bgp_zebra_withdraw(p, pi, bgp, safi);
3723 }
3724
3725 if (peer->sort == BGP_PEER_EBGP) {
3726
3727 /* rfc7999:
3728 * A BGP speaker receiving an announcement tagged with the
3729 * BLACKHOLE community SHOULD add the NO_ADVERTISE or
3730 * NO_EXPORT community as defined in RFC1997, or a
3731 * similar community, to prevent propagation of the
3732 * prefix outside the local AS. The community to prevent
3733 * propagation SHOULD be chosen according to the operator's
3734 * routing policy.
3735 */
3736 if (new_attr.community
3737 && community_include(new_attr.community,
3738 COMMUNITY_BLACKHOLE))
3739 bgp_attr_add_no_export_community(&new_attr);
3740
3741 /* If we receive the graceful-shutdown community from an eBGP
3742 * peer we must lower local-preference */
3743 if (new_attr.community
3744 && community_include(new_attr.community, COMMUNITY_GSHUT)) {
3745 new_attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
3746 new_attr.local_pref = BGP_GSHUT_LOCAL_PREF;
3747
3748 /* If graceful-shutdown is configured then add the GSHUT
3749 * community to all paths received from eBGP peers */
3750 } else if (bgp_in_graceful_shutdown(peer->bgp))
3751 bgp_attr_add_gshut_community(&new_attr);
3752 }
3753
3754 if (pi) {
3755 pi_type = pi->type;
3756 pi_sub_type = pi->sub_type;
3757 }
3758
3759 /* next hop check. */
3760 if (!CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD)
3761 && bgp_update_martian_nexthop(bgp, afi, safi, pi_type, pi_sub_type,
3762 &new_attr, dest)) {
3763 peer->stat_pfx_nh_invalid++;
3764 reason = "martian or self next-hop;";
3765 bgp_attr_flush(&new_attr);
3766 goto filtered;
3767 }
3768
3769 if (bgp_mac_entry_exists(p) || bgp_mac_exist(&attr->rmac)) {
3770 peer->stat_pfx_nh_invalid++;
3771 reason = "self mac;";
3772 goto filtered;
3773 }
3774
3775 /* Update Overlay Index */
3776 if (afi == AFI_L2VPN) {
3777 overlay_index_update(&new_attr,
3778 evpn == NULL ? NULL : &evpn->gw_ip);
3779 }
3780
3781 /* The flag BGP_NODE_FIB_INSTALL_PENDING is for the following
3782 * condition :
3783 * Suppress fib is enabled
3784 * BGP_OPT_NO_FIB is not enabled
3785 * Route type is BGP_ROUTE_NORMAL (peer learnt routes)
3786 * Route is being installed first time (BGP_NODE_FIB_INSTALLED not set)
3787 */
3788 if (bgp_fibupd_safi(safi) && BGP_SUPPRESS_FIB_ENABLED(bgp)
3789 && (sub_type == BGP_ROUTE_NORMAL)
3790 && (!bgp_option_check(BGP_OPT_NO_FIB))
3791 && (!CHECK_FLAG(dest->flags, BGP_NODE_FIB_INSTALLED)))
3792 SET_FLAG(dest->flags, BGP_NODE_FIB_INSTALL_PENDING);
3793
3794 attr_new = bgp_attr_intern(&new_attr);
3795
3796 /* If maximum prefix count is configured and current prefix
3797 * count exeed it.
3798 */
3799 if (bgp_maximum_prefix_overflow(peer, afi, safi, 0))
3800 return -1;
3801
3802 /* If the update is implicit withdraw. */
3803 if (pi) {
3804 pi->uptime = bgp_clock();
3805 same_attr = attrhash_cmp(pi->attr, attr_new);
3806
3807 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
3808
3809 /* Same attribute comes in. */
3810 if (!CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
3811 && same_attr
3812 && (!has_valid_label
3813 || memcmp(&(bgp_path_info_extra_get(pi))->label, label,
3814 num_labels * sizeof(mpls_label_t))
3815 == 0)
3816 && (overlay_index_equal(
3817 afi, pi,
3818 evpn == NULL ? NULL : &evpn->gw_ip))) {
3819 if (get_active_bdc_from_pi(pi, afi, safi)
3820 && peer->sort == BGP_PEER_EBGP
3821 && CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
3822 if (bgp_debug_update(peer, p, NULL, 1)) {
3823 bgp_debug_rdpfxpath2str(
3824 afi, safi, prd, p, label,
3825 num_labels, addpath_id ? 1 : 0,
3826 addpath_id, pfx_buf,
3827 sizeof(pfx_buf));
3828 zlog_debug("%s rcvd %s", peer->host,
3829 pfx_buf);
3830 }
3831
3832 if (bgp_damp_update(pi, dest, afi, safi)
3833 != BGP_DAMP_SUPPRESSED) {
3834 bgp_aggregate_increment(bgp, p, pi, afi,
3835 safi);
3836 bgp_process(bgp, dest, afi, safi);
3837 }
3838 } else /* Duplicate - odd */
3839 {
3840 if (bgp_debug_update(peer, p, NULL, 1)) {
3841 if (!peer->rcvd_attr_printed) {
3842 zlog_debug(
3843 "%s rcvd UPDATE w/ attr: %s",
3844 peer->host,
3845 peer->rcvd_attr_str);
3846 peer->rcvd_attr_printed = 1;
3847 }
3848
3849 bgp_debug_rdpfxpath2str(
3850 afi, safi, prd, p, label,
3851 num_labels, addpath_id ? 1 : 0,
3852 addpath_id, pfx_buf,
3853 sizeof(pfx_buf));
3854 zlog_debug(
3855 "%s rcvd %s...duplicate ignored",
3856 peer->host, pfx_buf);
3857 }
3858
3859 /* graceful restart STALE flag unset. */
3860 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
3861 bgp_path_info_unset_flag(
3862 dest, pi, BGP_PATH_STALE);
3863 bgp_dest_set_defer_flag(dest, false);
3864 bgp_process(bgp, dest, afi, safi);
3865 }
3866 }
3867
3868 bgp_dest_unlock_node(dest);
3869 bgp_attr_unintern(&attr_new);
3870
3871 return 0;
3872 }
3873
3874 /* Withdraw/Announce before we fully processed the withdraw */
3875 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
3876 if (bgp_debug_update(peer, p, NULL, 1)) {
3877 bgp_debug_rdpfxpath2str(
3878 afi, safi, prd, p, label, num_labels,
3879 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3880 sizeof(pfx_buf));
3881 zlog_debug(
3882 "%s rcvd %s, flapped quicker than processing",
3883 peer->host, pfx_buf);
3884 }
3885
3886 bgp_path_info_restore(dest, pi);
3887 }
3888
3889 /* Received Logging. */
3890 if (bgp_debug_update(peer, p, NULL, 1)) {
3891 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label,
3892 num_labels, addpath_id ? 1 : 0,
3893 addpath_id, pfx_buf,
3894 sizeof(pfx_buf));
3895 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
3896 }
3897
3898 /* graceful restart STALE flag unset. */
3899 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
3900 bgp_path_info_unset_flag(dest, pi, BGP_PATH_STALE);
3901 bgp_dest_set_defer_flag(dest, false);
3902 }
3903
3904 /* The attribute is changed. */
3905 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
3906
3907 /* implicit withdraw, decrement aggregate and pcount here.
3908 * only if update is accepted, they'll increment below.
3909 */
3910 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
3911
3912 /* Update bgp route dampening information. */
3913 if (get_active_bdc_from_pi(pi, afi, safi)
3914 && peer->sort == BGP_PEER_EBGP) {
3915 /* This is implicit withdraw so we should update
3916 * dampening information.
3917 */
3918 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
3919 bgp_damp_withdraw(pi, dest, afi, safi, 1);
3920 }
3921 #ifdef ENABLE_BGP_VNC
3922 if (safi == SAFI_MPLS_VPN) {
3923 struct bgp_dest *pdest = NULL;
3924 struct bgp_table *table = NULL;
3925
3926 pdest = bgp_node_get(bgp->rib[afi][safi],
3927 (struct prefix *)prd);
3928 if (bgp_dest_has_bgp_path_info_data(pdest)) {
3929 table = bgp_dest_get_bgp_table_info(pdest);
3930
3931 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3932 bgp, prd, table, p, pi);
3933 }
3934 bgp_dest_unlock_node(pdest);
3935 }
3936 if ((afi == AFI_IP || afi == AFI_IP6)
3937 && (safi == SAFI_UNICAST)) {
3938 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
3939 /*
3940 * Implicit withdraw case.
3941 */
3942 ++vnc_implicit_withdraw;
3943 vnc_import_bgp_del_route(bgp, p, pi);
3944 vnc_import_bgp_exterior_del_route(bgp, p, pi);
3945 }
3946 }
3947 #endif
3948
3949 /* Special handling for EVPN update of an existing route. If the
3950 * extended community attribute has changed, we need to
3951 * un-import
3952 * the route using its existing extended community. It will be
3953 * subsequently processed for import with the new extended
3954 * community.
3955 */
3956 if (((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN))
3957 && !same_attr) {
3958 if ((pi->attr->flag
3959 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))
3960 && (attr_new->flag
3961 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
3962 int cmp;
3963
3964 cmp = ecommunity_cmp(pi->attr->ecommunity,
3965 attr_new->ecommunity);
3966 if (!cmp) {
3967 if (bgp_debug_update(peer, p, NULL, 1))
3968 zlog_debug(
3969 "Change in EXT-COMM, existing %s new %s",
3970 ecommunity_str(
3971 pi->attr->ecommunity),
3972 ecommunity_str(
3973 attr_new->ecommunity));
3974 if (safi == SAFI_EVPN)
3975 bgp_evpn_unimport_route(
3976 bgp, afi, safi, p, pi);
3977 else /* SAFI_MPLS_VPN */
3978 vpn_leak_to_vrf_withdraw(bgp,
3979 pi);
3980 }
3981 }
3982 }
3983
3984 /* Update to new attribute. */
3985 bgp_attr_unintern(&pi->attr);
3986 pi->attr = attr_new;
3987
3988 /* Update MPLS label */
3989 if (has_valid_label) {
3990 extra = bgp_path_info_extra_get(pi);
3991 if (extra->label != label) {
3992 memcpy(&extra->label, label,
3993 num_labels * sizeof(mpls_label_t));
3994 extra->num_labels = num_labels;
3995 }
3996 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
3997 bgp_set_valid_label(&extra->label[0]);
3998 }
3999
4000 /* Update SRv6 SID */
4001 if (attr->srv6_l3vpn) {
4002 extra = bgp_path_info_extra_get(pi);
4003 if (sid_diff(&extra->sid[0], &attr->srv6_l3vpn->sid)) {
4004 sid_copy(&extra->sid[0],
4005 &attr->srv6_l3vpn->sid);
4006 extra->num_sids = 1;
4007 }
4008 } else if (attr->srv6_vpn) {
4009 extra = bgp_path_info_extra_get(pi);
4010 if (sid_diff(&extra->sid[0], &attr->srv6_vpn->sid)) {
4011 sid_copy(&extra->sid[0], &attr->srv6_vpn->sid);
4012 extra->num_sids = 1;
4013 }
4014 }
4015
4016 #ifdef ENABLE_BGP_VNC
4017 if ((afi == AFI_IP || afi == AFI_IP6)
4018 && (safi == SAFI_UNICAST)) {
4019 if (vnc_implicit_withdraw) {
4020 /*
4021 * Add back the route with its new attributes
4022 * (e.g., nexthop).
4023 * The route is still selected, until the route
4024 * selection
4025 * queued by bgp_process actually runs. We have
4026 * to make this
4027 * update to the VNC side immediately to avoid
4028 * racing against
4029 * configuration changes (e.g., route-map
4030 * changes) which
4031 * trigger re-importation of the entire RIB.
4032 */
4033 vnc_import_bgp_add_route(bgp, p, pi);
4034 vnc_import_bgp_exterior_add_route(bgp, p, pi);
4035 }
4036 }
4037 #endif
4038
4039 /* Update bgp route dampening information. */
4040 if (get_active_bdc_from_pi(pi, afi, safi)
4041 && peer->sort == BGP_PEER_EBGP) {
4042 /* Now we do normal update dampening. */
4043 ret = bgp_damp_update(pi, dest, afi, safi);
4044 if (ret == BGP_DAMP_SUPPRESSED) {
4045 bgp_dest_unlock_node(dest);
4046 return 0;
4047 }
4048 }
4049
4050 /* Nexthop reachability check - for unicast and
4051 * labeled-unicast.. */
4052 if (((afi == AFI_IP || afi == AFI_IP6)
4053 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4054 || (safi == SAFI_EVPN &&
4055 bgp_evpn_is_prefix_nht_supported(p))) {
4056 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4057 && peer->ttl == BGP_DEFAULT_TTL
4058 && !CHECK_FLAG(peer->flags,
4059 PEER_FLAG_DISABLE_CONNECTED_CHECK)
4060 && !CHECK_FLAG(bgp->flags,
4061 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
4062 connected = 1;
4063 else
4064 connected = 0;
4065
4066 struct bgp *bgp_nexthop = bgp;
4067
4068 if (pi->extra && pi->extra->bgp_orig)
4069 bgp_nexthop = pi->extra->bgp_orig;
4070
4071 nh_afi = BGP_ATTR_NH_AFI(afi, pi->attr);
4072
4073 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop, nh_afi,
4074 safi, pi, NULL, connected)
4075 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
4076 bgp_path_info_set_flag(dest, pi,
4077 BGP_PATH_VALID);
4078 else {
4079 if (BGP_DEBUG(nht, NHT)) {
4080 zlog_debug("%s(%pI4): NH unresolved",
4081 __func__,
4082 (in_addr_t *)&attr_new->nexthop);
4083 }
4084 bgp_path_info_unset_flag(dest, pi,
4085 BGP_PATH_VALID);
4086 }
4087 } else
4088 bgp_path_info_set_flag(dest, pi, BGP_PATH_VALID);
4089
4090 #ifdef ENABLE_BGP_VNC
4091 if (safi == SAFI_MPLS_VPN) {
4092 struct bgp_dest *pdest = NULL;
4093 struct bgp_table *table = NULL;
4094
4095 pdest = bgp_node_get(bgp->rib[afi][safi],
4096 (struct prefix *)prd);
4097 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4098 table = bgp_dest_get_bgp_table_info(pdest);
4099
4100 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4101 bgp, prd, table, p, pi);
4102 }
4103 bgp_dest_unlock_node(pdest);
4104 }
4105 #endif
4106
4107 /* If this is an EVPN route and some attribute has changed,
4108 * process
4109 * route for import. If the extended community has changed, we
4110 * would
4111 * have done the un-import earlier and the import would result
4112 * in the
4113 * route getting injected into appropriate L2 VNIs. If it is
4114 * just
4115 * some other attribute change, the import will result in
4116 * updating
4117 * the attributes for the route in the VNI(s).
4118 */
4119 if (safi == SAFI_EVPN && !same_attr &&
4120 CHECK_FLAG(pi->flags, BGP_PATH_VALID))
4121 bgp_evpn_import_route(bgp, afi, safi, p, pi);
4122
4123 /* Process change. */
4124 bgp_aggregate_increment(bgp, p, pi, afi, safi);
4125
4126 bgp_process(bgp, dest, afi, safi);
4127 bgp_dest_unlock_node(dest);
4128
4129 if (SAFI_UNICAST == safi
4130 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4131 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4132
4133 vpn_leak_from_vrf_update(bgp_get_default(), bgp, pi);
4134 }
4135 if ((SAFI_MPLS_VPN == safi)
4136 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4137
4138 vpn_leak_to_vrf_update(bgp, pi);
4139 }
4140
4141 #ifdef ENABLE_BGP_VNC
4142 if (SAFI_MPLS_VPN == safi) {
4143 mpls_label_t label_decoded = decode_label(label);
4144
4145 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4146 type, sub_type, &label_decoded);
4147 }
4148 if (SAFI_ENCAP == safi) {
4149 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4150 type, sub_type, NULL);
4151 }
4152 #endif
4153
4154 return 0;
4155 } // End of implicit withdraw
4156
4157 /* Received Logging. */
4158 if (bgp_debug_update(peer, p, NULL, 1)) {
4159 if (!peer->rcvd_attr_printed) {
4160 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
4161 peer->rcvd_attr_str);
4162 peer->rcvd_attr_printed = 1;
4163 }
4164
4165 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
4166 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4167 sizeof(pfx_buf));
4168 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
4169 }
4170
4171 /* Make new BGP info. */
4172 new = info_make(type, sub_type, 0, peer, attr_new, dest);
4173
4174 /* Update MPLS label */
4175 if (has_valid_label) {
4176 extra = bgp_path_info_extra_get(new);
4177 if (extra->label != label) {
4178 memcpy(&extra->label, label,
4179 num_labels * sizeof(mpls_label_t));
4180 extra->num_labels = num_labels;
4181 }
4182 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4183 bgp_set_valid_label(&extra->label[0]);
4184 }
4185
4186 /* Update SRv6 SID */
4187 if (safi == SAFI_MPLS_VPN) {
4188 extra = bgp_path_info_extra_get(new);
4189 if (attr->srv6_l3vpn) {
4190 sid_copy(&extra->sid[0], &attr->srv6_l3vpn->sid);
4191 extra->num_sids = 1;
4192 } else if (attr->srv6_vpn) {
4193 sid_copy(&extra->sid[0], &attr->srv6_vpn->sid);
4194 extra->num_sids = 1;
4195 }
4196 }
4197
4198 /* Update Overlay Index */
4199 if (afi == AFI_L2VPN) {
4200 overlay_index_update(new->attr,
4201 evpn == NULL ? NULL : &evpn->gw_ip);
4202 }
4203 /* Nexthop reachability check. */
4204 if (((afi == AFI_IP || afi == AFI_IP6)
4205 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4206 || (safi == SAFI_EVPN && bgp_evpn_is_prefix_nht_supported(p))) {
4207 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4208 && peer->ttl == BGP_DEFAULT_TTL
4209 && !CHECK_FLAG(peer->flags,
4210 PEER_FLAG_DISABLE_CONNECTED_CHECK)
4211 && !CHECK_FLAG(bgp->flags,
4212 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
4213 connected = 1;
4214 else
4215 connected = 0;
4216
4217 nh_afi = BGP_ATTR_NH_AFI(afi, new->attr);
4218
4219 if (bgp_find_or_add_nexthop(bgp, bgp, nh_afi, safi, new, NULL,
4220 connected)
4221 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
4222 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
4223 else {
4224 if (BGP_DEBUG(nht, NHT)) {
4225 char buf1[INET6_ADDRSTRLEN];
4226 inet_ntop(AF_INET,
4227 (const void *)&attr_new->nexthop,
4228 buf1, INET6_ADDRSTRLEN);
4229 zlog_debug("%s(%s): NH unresolved", __func__,
4230 buf1);
4231 }
4232 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
4233 }
4234 } else
4235 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
4236
4237 /* Addpath ID */
4238 new->addpath_rx_id = addpath_id;
4239
4240 /* Increment prefix */
4241 bgp_aggregate_increment(bgp, p, new, afi, safi);
4242
4243 /* Register new BGP information. */
4244 bgp_path_info_add(dest, new);
4245
4246 /* route_node_get lock */
4247 bgp_dest_unlock_node(dest);
4248
4249 #ifdef ENABLE_BGP_VNC
4250 if (safi == SAFI_MPLS_VPN) {
4251 struct bgp_dest *pdest = NULL;
4252 struct bgp_table *table = NULL;
4253
4254 pdest = bgp_node_get(bgp->rib[afi][safi], (struct prefix *)prd);
4255 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4256 table = bgp_dest_get_bgp_table_info(pdest);
4257
4258 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4259 bgp, prd, table, p, new);
4260 }
4261 bgp_dest_unlock_node(pdest);
4262 }
4263 #endif
4264
4265 /* If this is an EVPN route, process for import. */
4266 if (safi == SAFI_EVPN && CHECK_FLAG(new->flags, BGP_PATH_VALID))
4267 bgp_evpn_import_route(bgp, afi, safi, p, new);
4268
4269 hook_call(bgp_process, bgp, afi, safi, dest, peer, false);
4270
4271 /* Process change. */
4272 bgp_process(bgp, dest, afi, safi);
4273
4274 if (SAFI_UNICAST == safi
4275 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4276 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4277 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
4278 }
4279 if ((SAFI_MPLS_VPN == safi)
4280 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4281
4282 vpn_leak_to_vrf_update(bgp, new);
4283 }
4284 #ifdef ENABLE_BGP_VNC
4285 if (SAFI_MPLS_VPN == safi) {
4286 mpls_label_t label_decoded = decode_label(label);
4287
4288 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4289 sub_type, &label_decoded);
4290 }
4291 if (SAFI_ENCAP == safi) {
4292 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4293 sub_type, NULL);
4294 }
4295 #endif
4296
4297 return 0;
4298
4299 /* This BGP update is filtered. Log the reason then update BGP
4300 entry. */
4301 filtered:
4302 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4303
4304 if (bgp_debug_update(peer, p, NULL, 1)) {
4305 if (!peer->rcvd_attr_printed) {
4306 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
4307 peer->rcvd_attr_str);
4308 peer->rcvd_attr_printed = 1;
4309 }
4310
4311 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
4312 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4313 sizeof(pfx_buf));
4314 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
4315 peer->host, pfx_buf, reason);
4316 }
4317
4318 if (pi) {
4319 /* If this is an EVPN route, un-import it as it is now filtered.
4320 */
4321 if (safi == SAFI_EVPN)
4322 bgp_evpn_unimport_route(bgp, afi, safi, p, pi);
4323
4324 if (SAFI_UNICAST == safi
4325 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4326 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4327
4328 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
4329 }
4330 if ((SAFI_MPLS_VPN == safi)
4331 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4332
4333 vpn_leak_to_vrf_withdraw(bgp, pi);
4334 }
4335
4336 bgp_rib_remove(dest, pi, peer, afi, safi);
4337 }
4338
4339 bgp_dest_unlock_node(dest);
4340
4341 #ifdef ENABLE_BGP_VNC
4342 /*
4343 * Filtered update is treated as an implicit withdrawal (see
4344 * bgp_rib_remove()
4345 * a few lines above)
4346 */
4347 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4348 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4349 0);
4350 }
4351 #endif
4352
4353 return 0;
4354 }
4355
4356 int bgp_withdraw(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
4357 struct attr *attr, afi_t afi, safi_t safi, int type,
4358 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
4359 uint32_t num_labels, struct bgp_route_evpn *evpn)
4360 {
4361 struct bgp *bgp;
4362 char pfx_buf[BGP_PRD_PATH_STRLEN];
4363 struct bgp_dest *dest;
4364 struct bgp_path_info *pi;
4365
4366 #ifdef ENABLE_BGP_VNC
4367 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4368 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4369 0);
4370 }
4371 #endif
4372
4373 bgp = peer->bgp;
4374
4375 /* Lookup node. */
4376 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
4377
4378 /* If peer is soft reconfiguration enabled. Record input packet for
4379 * further calculation.
4380 *
4381 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4382 * routes that are filtered. This tanks out Quagga RS pretty badly due
4383 * to
4384 * the iteration over all RS clients.
4385 * Since we need to remove the entry from adj_in anyway, do that first
4386 * and
4387 * if there was no entry, we don't need to do anything more.
4388 */
4389 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
4390 && peer != bgp->peer_self)
4391 if (!bgp_adj_in_unset(dest, peer, addpath_id)) {
4392 peer->stat_pfx_dup_withdraw++;
4393
4394 if (bgp_debug_update(peer, p, NULL, 1)) {
4395 bgp_debug_rdpfxpath2str(
4396 afi, safi, prd, p, label, num_labels,
4397 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4398 sizeof(pfx_buf));
4399 zlog_debug(
4400 "%s withdrawing route %s not in adj-in",
4401 peer->host, pfx_buf);
4402 }
4403 bgp_dest_unlock_node(dest);
4404 return 0;
4405 }
4406
4407 /* Lookup withdrawn route. */
4408 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
4409 if (pi->peer == peer && pi->type == type
4410 && pi->sub_type == sub_type
4411 && pi->addpath_rx_id == addpath_id)
4412 break;
4413
4414 /* Logging. */
4415 if (bgp_debug_update(peer, p, NULL, 1)) {
4416 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
4417 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4418 sizeof(pfx_buf));
4419 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer->host,
4420 pfx_buf);
4421 }
4422
4423 /* Withdraw specified route from routing table. */
4424 if (pi && !CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
4425 bgp_rib_withdraw(dest, pi, peer, afi, safi, prd);
4426 if (SAFI_UNICAST == safi
4427 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4428 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4429 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
4430 }
4431 if ((SAFI_MPLS_VPN == safi)
4432 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4433
4434 vpn_leak_to_vrf_withdraw(bgp, pi);
4435 }
4436 } else if (bgp_debug_update(peer, p, NULL, 1)) {
4437 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
4438 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4439 sizeof(pfx_buf));
4440 zlog_debug("%s Can't find the route %s", peer->host, pfx_buf);
4441 }
4442
4443 /* Unlock bgp_node_get() lock. */
4444 bgp_dest_unlock_node(dest);
4445
4446 return 0;
4447 }
4448
4449 void bgp_default_originate(struct peer *peer, afi_t afi, safi_t safi,
4450 int withdraw)
4451 {
4452 struct update_subgroup *subgrp;
4453 subgrp = peer_subgroup(peer, afi, safi);
4454 subgroup_default_originate(subgrp, withdraw);
4455 }
4456
4457
4458 /*
4459 * bgp_stop_announce_route_timer
4460 */
4461 void bgp_stop_announce_route_timer(struct peer_af *paf)
4462 {
4463 if (!paf->t_announce_route)
4464 return;
4465
4466 thread_cancel(&paf->t_announce_route);
4467 }
4468
4469 /*
4470 * bgp_announce_route_timer_expired
4471 *
4472 * Callback that is invoked when the route announcement timer for a
4473 * peer_af expires.
4474 */
4475 static int bgp_announce_route_timer_expired(struct thread *t)
4476 {
4477 struct peer_af *paf;
4478 struct peer *peer;
4479
4480 paf = THREAD_ARG(t);
4481 peer = paf->peer;
4482
4483 if (peer->status != Established)
4484 return 0;
4485
4486 if (!peer->afc_nego[paf->afi][paf->safi])
4487 return 0;
4488
4489 peer_af_announce_route(paf, 1);
4490
4491 /* Notify BGP conditional advertisement scanner percess */
4492 peer->advmap_config_change[paf->afi][paf->safi] = true;
4493
4494 return 0;
4495 }
4496
4497 /*
4498 * bgp_announce_route
4499 *
4500 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
4501 */
4502 void bgp_announce_route(struct peer *peer, afi_t afi, safi_t safi)
4503 {
4504 struct peer_af *paf;
4505 struct update_subgroup *subgrp;
4506
4507 paf = peer_af_find(peer, afi, safi);
4508 if (!paf)
4509 return;
4510 subgrp = PAF_SUBGRP(paf);
4511
4512 /*
4513 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
4514 * or a refresh has already been triggered.
4515 */
4516 if (!subgrp || paf->t_announce_route)
4517 return;
4518
4519 /*
4520 * Start a timer to stagger/delay the announce. This serves
4521 * two purposes - announcement can potentially be combined for
4522 * multiple peers and the announcement doesn't happen in the
4523 * vty context.
4524 */
4525 thread_add_timer_msec(bm->master, bgp_announce_route_timer_expired, paf,
4526 (subgrp->peer_count == 1)
4527 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
4528 : BGP_ANNOUNCE_ROUTE_DELAY_MS,
4529 &paf->t_announce_route);
4530 }
4531
4532 /*
4533 * Announce routes from all AF tables to a peer.
4534 *
4535 * This should ONLY be called when there is a need to refresh the
4536 * routes to the peer based on a policy change for this peer alone
4537 * or a route refresh request received from the peer.
4538 * The operation will result in splitting the peer from its existing
4539 * subgroups and putting it in new subgroups.
4540 */
4541 void bgp_announce_route_all(struct peer *peer)
4542 {
4543 afi_t afi;
4544 safi_t safi;
4545
4546 FOREACH_AFI_SAFI (afi, safi)
4547 bgp_announce_route(peer, afi, safi);
4548 }
4549
4550 static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi,
4551 struct bgp_table *table,
4552 struct prefix_rd *prd)
4553 {
4554 int ret;
4555 struct bgp_dest *dest;
4556 struct bgp_adj_in *ain;
4557
4558 if (!table)
4559 table = peer->bgp->rib[afi][safi];
4560
4561 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
4562 for (ain = dest->adj_in; ain; ain = ain->next) {
4563 if (ain->peer != peer)
4564 continue;
4565
4566 struct bgp_path_info *pi;
4567 uint32_t num_labels = 0;
4568 mpls_label_t *label_pnt = NULL;
4569 struct bgp_route_evpn evpn;
4570
4571 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
4572 pi = pi->next)
4573 if (pi->peer == peer)
4574 break;
4575
4576 if (pi && pi->extra)
4577 num_labels = pi->extra->num_labels;
4578 if (num_labels)
4579 label_pnt = &pi->extra->label[0];
4580 if (pi)
4581 memcpy(&evpn,
4582 bgp_attr_get_evpn_overlay(pi->attr),
4583 sizeof(evpn));
4584 else
4585 memset(&evpn, 0, sizeof(evpn));
4586
4587 ret = bgp_update(peer, bgp_dest_get_prefix(dest),
4588 ain->addpath_rx_id, ain->attr, afi,
4589 safi, ZEBRA_ROUTE_BGP,
4590 BGP_ROUTE_NORMAL, prd, label_pnt,
4591 num_labels, 1, &evpn);
4592
4593 if (ret < 0) {
4594 bgp_dest_unlock_node(dest);
4595 return;
4596 }
4597 }
4598 }
4599
4600 void bgp_soft_reconfig_in(struct peer *peer, afi_t afi, safi_t safi)
4601 {
4602 struct bgp_dest *dest;
4603 struct bgp_table *table;
4604
4605 if (peer->status != Established)
4606 return;
4607
4608 if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP)
4609 && (safi != SAFI_EVPN))
4610 bgp_soft_reconfig_table(peer, afi, safi, NULL, NULL);
4611 else
4612 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4613 dest = bgp_route_next(dest)) {
4614 table = bgp_dest_get_bgp_table_info(dest);
4615
4616 if (table == NULL)
4617 continue;
4618
4619 const struct prefix *p = bgp_dest_get_prefix(dest);
4620 struct prefix_rd prd;
4621
4622 prd.family = AF_UNSPEC;
4623 prd.prefixlen = 64;
4624 memcpy(&prd.val, p->u.val, 8);
4625
4626 bgp_soft_reconfig_table(peer, afi, safi, table, &prd);
4627 }
4628 }
4629
4630
4631 struct bgp_clear_node_queue {
4632 struct bgp_dest *dest;
4633 };
4634
4635 static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data)
4636 {
4637 struct bgp_clear_node_queue *cnq = data;
4638 struct bgp_dest *dest = cnq->dest;
4639 struct peer *peer = wq->spec.data;
4640 struct bgp_path_info *pi;
4641 struct bgp *bgp;
4642 afi_t afi = bgp_dest_table(dest)->afi;
4643 safi_t safi = bgp_dest_table(dest)->safi;
4644
4645 assert(dest && peer);
4646 bgp = peer->bgp;
4647
4648 /* It is possible that we have multiple paths for a prefix from a peer
4649 * if that peer is using AddPath.
4650 */
4651 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
4652 if (pi->peer != peer)
4653 continue;
4654
4655 /* graceful restart STALE flag set. */
4656 if (((CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)
4657 && peer->nsf[afi][safi])
4658 || CHECK_FLAG(peer->af_sflags[afi][safi],
4659 PEER_STATUS_ENHANCED_REFRESH))
4660 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
4661 && !CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
4662 bgp_path_info_set_flag(dest, pi, BGP_PATH_STALE);
4663 else {
4664 /* If this is an EVPN route, process for
4665 * un-import. */
4666 if (safi == SAFI_EVPN)
4667 bgp_evpn_unimport_route(
4668 bgp, afi, safi,
4669 bgp_dest_get_prefix(dest), pi);
4670 /* Handle withdraw for VRF route-leaking and L3VPN */
4671 if (SAFI_UNICAST == safi
4672 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF ||
4673 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4674 vpn_leak_from_vrf_withdraw(bgp_get_default(),
4675 bgp, pi);
4676 }
4677 if (SAFI_MPLS_VPN == safi &&
4678 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
4679 vpn_leak_to_vrf_withdraw(bgp, pi);
4680 }
4681
4682 bgp_rib_remove(dest, pi, peer, afi, safi);
4683 }
4684 }
4685 return WQ_SUCCESS;
4686 }
4687
4688 static void bgp_clear_node_queue_del(struct work_queue *wq, void *data)
4689 {
4690 struct bgp_clear_node_queue *cnq = data;
4691 struct bgp_dest *dest = cnq->dest;
4692 struct bgp_table *table = bgp_dest_table(dest);
4693
4694 bgp_dest_unlock_node(dest);
4695 bgp_table_unlock(table);
4696 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE, cnq);
4697 }
4698
4699 static void bgp_clear_node_complete(struct work_queue *wq)
4700 {
4701 struct peer *peer = wq->spec.data;
4702
4703 /* Tickle FSM to start moving again */
4704 BGP_EVENT_ADD(peer, Clearing_Completed);
4705
4706 peer_unlock(peer); /* bgp_clear_route */
4707 }
4708
4709 static void bgp_clear_node_queue_init(struct peer *peer)
4710 {
4711 char wname[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
4712
4713 snprintf(wname, sizeof(wname), "clear %s", peer->host);
4714 #undef CLEAR_QUEUE_NAME_LEN
4715
4716 peer->clear_node_queue = work_queue_new(bm->master, wname);
4717 peer->clear_node_queue->spec.hold = 10;
4718 peer->clear_node_queue->spec.workfunc = &bgp_clear_route_node;
4719 peer->clear_node_queue->spec.del_item_data = &bgp_clear_node_queue_del;
4720 peer->clear_node_queue->spec.completion_func = &bgp_clear_node_complete;
4721 peer->clear_node_queue->spec.max_retries = 0;
4722
4723 /* we only 'lock' this peer reference when the queue is actually active
4724 */
4725 peer->clear_node_queue->spec.data = peer;
4726 }
4727
4728 static void bgp_clear_route_table(struct peer *peer, afi_t afi, safi_t safi,
4729 struct bgp_table *table)
4730 {
4731 struct bgp_dest *dest;
4732 int force = peer->bgp->process_queue ? 0 : 1;
4733
4734 if (!table)
4735 table = peer->bgp->rib[afi][safi];
4736
4737 /* If still no table => afi/safi isn't configured at all or smth. */
4738 if (!table)
4739 return;
4740
4741 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
4742 struct bgp_path_info *pi, *next;
4743 struct bgp_adj_in *ain;
4744 struct bgp_adj_in *ain_next;
4745
4746 /* XXX:TODO: This is suboptimal, every non-empty route_node is
4747 * queued for every clearing peer, regardless of whether it is
4748 * relevant to the peer at hand.
4749 *
4750 * Overview: There are 3 different indices which need to be
4751 * scrubbed, potentially, when a peer is removed:
4752 *
4753 * 1 peer's routes visible via the RIB (ie accepted routes)
4754 * 2 peer's routes visible by the (optional) peer's adj-in index
4755 * 3 other routes visible by the peer's adj-out index
4756 *
4757 * 3 there is no hurry in scrubbing, once the struct peer is
4758 * removed from bgp->peer, we could just GC such deleted peer's
4759 * adj-outs at our leisure.
4760 *
4761 * 1 and 2 must be 'scrubbed' in some way, at least made
4762 * invisible via RIB index before peer session is allowed to be
4763 * brought back up. So one needs to know when such a 'search' is
4764 * complete.
4765 *
4766 * Ideally:
4767 *
4768 * - there'd be a single global queue or a single RIB walker
4769 * - rather than tracking which route_nodes still need to be
4770 * examined on a peer basis, we'd track which peers still
4771 * aren't cleared
4772 *
4773 * Given that our per-peer prefix-counts now should be reliable,
4774 * this may actually be achievable. It doesn't seem to be a huge
4775 * problem at this time,
4776 *
4777 * It is possible that we have multiple paths for a prefix from
4778 * a peer
4779 * if that peer is using AddPath.
4780 */
4781 ain = dest->adj_in;
4782 while (ain) {
4783 ain_next = ain->next;
4784
4785 if (ain->peer == peer) {
4786 bgp_adj_in_remove(dest, ain);
4787 bgp_dest_unlock_node(dest);
4788 }
4789
4790 ain = ain_next;
4791 }
4792
4793 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
4794 next = pi->next;
4795 if (pi->peer != peer)
4796 continue;
4797
4798 if (force)
4799 bgp_path_info_reap(dest, pi);
4800 else {
4801 struct bgp_clear_node_queue *cnq;
4802
4803 /* both unlocked in bgp_clear_node_queue_del */
4804 bgp_table_lock(bgp_dest_table(dest));
4805 bgp_dest_lock_node(dest);
4806 cnq = XCALLOC(
4807 MTYPE_BGP_CLEAR_NODE_QUEUE,
4808 sizeof(struct bgp_clear_node_queue));
4809 cnq->dest = dest;
4810 work_queue_add(peer->clear_node_queue, cnq);
4811 break;
4812 }
4813 }
4814 }
4815 return;
4816 }
4817
4818 void bgp_clear_route(struct peer *peer, afi_t afi, safi_t safi)
4819 {
4820 struct bgp_dest *dest;
4821 struct bgp_table *table;
4822
4823 if (peer->clear_node_queue == NULL)
4824 bgp_clear_node_queue_init(peer);
4825
4826 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
4827 * Idle until it receives a Clearing_Completed event. This protects
4828 * against peers which flap faster than we can we clear, which could
4829 * lead to:
4830 *
4831 * a) race with routes from the new session being installed before
4832 * clear_route_node visits the node (to delete the route of that
4833 * peer)
4834 * b) resource exhaustion, clear_route_node likely leads to an entry
4835 * on the process_main queue. Fast-flapping could cause that queue
4836 * to grow and grow.
4837 */
4838
4839 /* lock peer in assumption that clear-node-queue will get nodes; if so,
4840 * the unlock will happen upon work-queue completion; other wise, the
4841 * unlock happens at the end of this function.
4842 */
4843 if (!peer->clear_node_queue->thread)
4844 peer_lock(peer);
4845
4846 if (safi != SAFI_MPLS_VPN && safi != SAFI_ENCAP && safi != SAFI_EVPN)
4847 bgp_clear_route_table(peer, afi, safi, NULL);
4848 else
4849 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4850 dest = bgp_route_next(dest)) {
4851 table = bgp_dest_get_bgp_table_info(dest);
4852 if (!table)
4853 continue;
4854
4855 bgp_clear_route_table(peer, afi, safi, table);
4856 }
4857
4858 /* unlock if no nodes got added to the clear-node-queue. */
4859 if (!peer->clear_node_queue->thread)
4860 peer_unlock(peer);
4861 }
4862
4863 void bgp_clear_route_all(struct peer *peer)
4864 {
4865 afi_t afi;
4866 safi_t safi;
4867
4868 FOREACH_AFI_SAFI (afi, safi)
4869 bgp_clear_route(peer, afi, safi);
4870
4871 #ifdef ENABLE_BGP_VNC
4872 rfapiProcessPeerDown(peer);
4873 #endif
4874 }
4875
4876 void bgp_clear_adj_in(struct peer *peer, afi_t afi, safi_t safi)
4877 {
4878 struct bgp_table *table;
4879 struct bgp_dest *dest;
4880 struct bgp_adj_in *ain;
4881 struct bgp_adj_in *ain_next;
4882
4883 table = peer->bgp->rib[afi][safi];
4884
4885 /* It is possible that we have multiple paths for a prefix from a peer
4886 * if that peer is using AddPath.
4887 */
4888 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
4889 ain = dest->adj_in;
4890
4891 while (ain) {
4892 ain_next = ain->next;
4893
4894 if (ain->peer == peer) {
4895 bgp_adj_in_remove(dest, ain);
4896 bgp_dest_unlock_node(dest);
4897 }
4898
4899 ain = ain_next;
4900 }
4901 }
4902 }
4903
4904 void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
4905 {
4906 struct bgp_dest *dest;
4907 struct bgp_path_info *pi;
4908 struct bgp_table *table;
4909
4910 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
4911 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4912 dest = bgp_route_next(dest)) {
4913 struct bgp_dest *rm;
4914
4915 /* look for neighbor in tables */
4916 table = bgp_dest_get_bgp_table_info(dest);
4917 if (!table)
4918 continue;
4919
4920 for (rm = bgp_table_top(table); rm;
4921 rm = bgp_route_next(rm))
4922 for (pi = bgp_dest_get_bgp_path_info(rm); pi;
4923 pi = pi->next) {
4924 if (pi->peer != peer)
4925 continue;
4926 if (!CHECK_FLAG(pi->flags,
4927 BGP_PATH_STALE))
4928 break;
4929
4930 bgp_rib_remove(rm, pi, peer, afi, safi);
4931 break;
4932 }
4933 }
4934 } else {
4935 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4936 dest = bgp_route_next(dest))
4937 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
4938 pi = pi->next) {
4939 if (pi->peer != peer)
4940 continue;
4941 if (!CHECK_FLAG(pi->flags, BGP_PATH_STALE))
4942 break;
4943 bgp_rib_remove(dest, pi, peer, afi, safi);
4944 break;
4945 }
4946 }
4947 }
4948
4949 void bgp_set_stale_route(struct peer *peer, afi_t afi, safi_t safi)
4950 {
4951 struct bgp_dest *dest, *ndest;
4952 struct bgp_path_info *pi;
4953 struct bgp_table *table;
4954
4955 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
4956 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4957 dest = bgp_route_next(dest)) {
4958 table = bgp_dest_get_bgp_table_info(dest);
4959 if (!table)
4960 continue;
4961
4962 for (ndest = bgp_table_top(table); ndest;
4963 ndest = bgp_route_next(ndest)) {
4964 for (pi = bgp_dest_get_bgp_path_info(ndest); pi;
4965 pi = pi->next) {
4966 if (pi->peer != peer)
4967 continue;
4968
4969 if ((CHECK_FLAG(
4970 peer->af_sflags[afi][safi],
4971 PEER_STATUS_ENHANCED_REFRESH))
4972 && !CHECK_FLAG(pi->flags,
4973 BGP_PATH_STALE)
4974 && !CHECK_FLAG(
4975 pi->flags,
4976 BGP_PATH_UNUSEABLE)) {
4977 if (bgp_debug_neighbor_events(
4978 peer))
4979 zlog_debug(
4980 "%s: route-refresh for %s/%s, marking prefix %pFX as stale",
4981 peer->host,
4982 afi2str(afi),
4983 safi2str(safi),
4984 bgp_dest_get_prefix(
4985 ndest));
4986
4987 bgp_path_info_set_flag(
4988 ndest, pi,
4989 BGP_PATH_STALE);
4990 }
4991 }
4992 }
4993 }
4994 } else {
4995 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4996 dest = bgp_route_next(dest)) {
4997 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
4998 pi = pi->next) {
4999 if (pi->peer != peer)
5000 continue;
5001
5002 if ((CHECK_FLAG(peer->af_sflags[afi][safi],
5003 PEER_STATUS_ENHANCED_REFRESH))
5004 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
5005 && !CHECK_FLAG(pi->flags,
5006 BGP_PATH_UNUSEABLE)) {
5007 if (bgp_debug_neighbor_events(peer))
5008 zlog_debug(
5009 "%s: route-refresh for %s/%s, marking prefix %pFX as stale",
5010 peer->host,
5011 afi2str(afi),
5012 safi2str(safi),
5013 bgp_dest_get_prefix(
5014 dest));
5015
5016 bgp_path_info_set_flag(dest, pi,
5017 BGP_PATH_STALE);
5018 }
5019 }
5020 }
5021 }
5022 }
5023
5024 bool bgp_outbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
5025 {
5026 if (peer->sort == BGP_PEER_IBGP)
5027 return true;
5028
5029 if (peer->sort == BGP_PEER_EBGP
5030 && (ROUTE_MAP_OUT_NAME(filter) || PREFIX_LIST_OUT_NAME(filter)
5031 || FILTER_LIST_OUT_NAME(filter)
5032 || DISTRIBUTE_OUT_NAME(filter)))
5033 return true;
5034 return false;
5035 }
5036
5037 bool bgp_inbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
5038 {
5039 if (peer->sort == BGP_PEER_IBGP)
5040 return true;
5041
5042 if (peer->sort == BGP_PEER_EBGP
5043 && (ROUTE_MAP_IN_NAME(filter) || PREFIX_LIST_IN_NAME(filter)
5044 || FILTER_LIST_IN_NAME(filter)
5045 || DISTRIBUTE_IN_NAME(filter)))
5046 return true;
5047 return false;
5048 }
5049
5050 static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table,
5051 safi_t safi)
5052 {
5053 struct bgp_dest *dest;
5054 struct bgp_path_info *pi;
5055 struct bgp_path_info *next;
5056
5057 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
5058 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
5059 const struct prefix *p = bgp_dest_get_prefix(dest);
5060
5061 next = pi->next;
5062
5063 /* Unimport EVPN routes from VRFs */
5064 if (safi == SAFI_EVPN)
5065 bgp_evpn_unimport_route(bgp, AFI_L2VPN,
5066 SAFI_EVPN, p, pi);
5067
5068 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)
5069 && pi->type == ZEBRA_ROUTE_BGP
5070 && (pi->sub_type == BGP_ROUTE_NORMAL
5071 || pi->sub_type == BGP_ROUTE_AGGREGATE
5072 || pi->sub_type == BGP_ROUTE_IMPORTED)) {
5073
5074 if (bgp_fibupd_safi(safi))
5075 bgp_zebra_withdraw(p, pi, bgp, safi);
5076 }
5077
5078 bgp_path_info_reap(dest, pi);
5079 }
5080 }
5081
5082 /* Delete all kernel routes. */
5083 void bgp_cleanup_routes(struct bgp *bgp)
5084 {
5085 afi_t afi;
5086 struct bgp_dest *dest;
5087 struct bgp_table *table;
5088
5089 for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
5090 if (afi == AFI_L2VPN)
5091 continue;
5092 bgp_cleanup_table(bgp, bgp->rib[afi][SAFI_UNICAST],
5093 SAFI_UNICAST);
5094 /*
5095 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
5096 */
5097 if (afi != AFI_L2VPN) {
5098 safi_t safi;
5099 safi = SAFI_MPLS_VPN;
5100 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
5101 dest = bgp_route_next(dest)) {
5102 table = bgp_dest_get_bgp_table_info(dest);
5103 if (table != NULL) {
5104 bgp_cleanup_table(bgp, table, safi);
5105 bgp_table_finish(&table);
5106 bgp_dest_set_bgp_table_info(dest, NULL);
5107 bgp_dest_unlock_node(dest);
5108 }
5109 }
5110 safi = SAFI_ENCAP;
5111 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
5112 dest = bgp_route_next(dest)) {
5113 table = bgp_dest_get_bgp_table_info(dest);
5114 if (table != NULL) {
5115 bgp_cleanup_table(bgp, table, safi);
5116 bgp_table_finish(&table);
5117 bgp_dest_set_bgp_table_info(dest, NULL);
5118 bgp_dest_unlock_node(dest);
5119 }
5120 }
5121 }
5122 }
5123 for (dest = bgp_table_top(bgp->rib[AFI_L2VPN][SAFI_EVPN]); dest;
5124 dest = bgp_route_next(dest)) {
5125 table = bgp_dest_get_bgp_table_info(dest);
5126 if (table != NULL) {
5127 bgp_cleanup_table(bgp, table, SAFI_EVPN);
5128 bgp_table_finish(&table);
5129 bgp_dest_set_bgp_table_info(dest, NULL);
5130 bgp_dest_unlock_node(dest);
5131 }
5132 }
5133 }
5134
5135 void bgp_reset(void)
5136 {
5137 vty_reset();
5138 bgp_zclient_reset();
5139 access_list_reset();
5140 prefix_list_reset();
5141 }
5142
5143 static int bgp_addpath_encode_rx(struct peer *peer, afi_t afi, safi_t safi)
5144 {
5145 return (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV)
5146 && CHECK_FLAG(peer->af_cap[afi][safi],
5147 PEER_CAP_ADDPATH_AF_TX_RCV));
5148 }
5149
5150 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
5151 value. */
5152 int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
5153 struct bgp_nlri *packet)
5154 {
5155 uint8_t *pnt;
5156 uint8_t *lim;
5157 struct prefix p;
5158 int psize;
5159 int ret;
5160 afi_t afi;
5161 safi_t safi;
5162 int addpath_encoded;
5163 uint32_t addpath_id;
5164
5165 pnt = packet->nlri;
5166 lim = pnt + packet->length;
5167 afi = packet->afi;
5168 safi = packet->safi;
5169 addpath_id = 0;
5170 addpath_encoded = bgp_addpath_encode_rx(peer, afi, safi);
5171
5172 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
5173 syntactic validity. If the field is syntactically incorrect,
5174 then the Error Subcode is set to Invalid Network Field. */
5175 for (; pnt < lim; pnt += psize) {
5176 /* Clear prefix structure. */
5177 memset(&p, 0, sizeof(struct prefix));
5178
5179 if (addpath_encoded) {
5180
5181 /* When packet overflow occurs return immediately. */
5182 if (pnt + BGP_ADDPATH_ID_LEN >= lim)
5183 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
5184
5185 memcpy(&addpath_id, pnt, BGP_ADDPATH_ID_LEN);
5186 addpath_id = ntohl(addpath_id);
5187 pnt += BGP_ADDPATH_ID_LEN;
5188 }
5189
5190 /* Fetch prefix length. */
5191 p.prefixlen = *pnt++;
5192 /* afi/safi validity already verified by caller,
5193 * bgp_update_receive */
5194 p.family = afi2family(afi);
5195
5196 /* Prefix length check. */
5197 if (p.prefixlen > prefix_blen(&p) * 8) {
5198 flog_err(
5199 EC_BGP_UPDATE_RCV,
5200 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
5201 peer->host, p.prefixlen, packet->afi);
5202 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH;
5203 }
5204
5205 /* Packet size overflow check. */
5206 psize = PSIZE(p.prefixlen);
5207
5208 /* When packet overflow occur return immediately. */
5209 if (pnt + psize > lim) {
5210 flog_err(
5211 EC_BGP_UPDATE_RCV,
5212 "%s [Error] Update packet error (prefix length %d overflows packet)",
5213 peer->host, p.prefixlen);
5214 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
5215 }
5216
5217 /* Defensive coding, double-check the psize fits in a struct
5218 * prefix */
5219 if (psize > (ssize_t)sizeof(p.u)) {
5220 flog_err(
5221 EC_BGP_UPDATE_RCV,
5222 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
5223 peer->host, p.prefixlen, sizeof(p.u));
5224 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
5225 }
5226
5227 /* Fetch prefix from NLRI packet. */
5228 memcpy(p.u.val, pnt, psize);
5229
5230 /* Check address. */
5231 if (afi == AFI_IP && safi == SAFI_UNICAST) {
5232 if (IN_CLASSD(ntohl(p.u.prefix4.s_addr))) {
5233 /* From RFC4271 Section 6.3:
5234 *
5235 * If a prefix in the NLRI field is semantically
5236 * incorrect
5237 * (e.g., an unexpected multicast IP address),
5238 * an error SHOULD
5239 * be logged locally, and the prefix SHOULD be
5240 * ignored.
5241 */
5242 flog_err(
5243 EC_BGP_UPDATE_RCV,
5244 "%s: IPv4 unicast NLRI is multicast address %pI4, ignoring",
5245 peer->host, &p.u.prefix4);
5246 continue;
5247 }
5248 }
5249
5250 /* Check address. */
5251 if (afi == AFI_IP6 && safi == SAFI_UNICAST) {
5252 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
5253 char buf[BUFSIZ];
5254
5255 flog_err(
5256 EC_BGP_UPDATE_RCV,
5257 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
5258 peer->host,
5259 inet_ntop(AF_INET6, &p.u.prefix6, buf,
5260 BUFSIZ));
5261
5262 continue;
5263 }
5264 if (IN6_IS_ADDR_MULTICAST(&p.u.prefix6)) {
5265 char buf[BUFSIZ];
5266
5267 flog_err(
5268 EC_BGP_UPDATE_RCV,
5269 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
5270 peer->host,
5271 inet_ntop(AF_INET6, &p.u.prefix6, buf,
5272 BUFSIZ));
5273
5274 continue;
5275 }
5276 }
5277
5278 /* Normal process. */
5279 if (attr)
5280 ret = bgp_update(peer, &p, addpath_id, attr, afi, safi,
5281 ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
5282 NULL, NULL, 0, 0, NULL);
5283 else
5284 ret = bgp_withdraw(peer, &p, addpath_id, attr, afi,
5285 safi, ZEBRA_ROUTE_BGP,
5286 BGP_ROUTE_NORMAL, NULL, NULL, 0,
5287 NULL);
5288
5289 /* Do not send BGP notification twice when maximum-prefix count
5290 * overflow. */
5291 if (CHECK_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
5292 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW;
5293
5294 /* Address family configuration mismatch. */
5295 if (ret < 0)
5296 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY;
5297 }
5298
5299 /* Packet length consistency check. */
5300 if (pnt != lim) {
5301 flog_err(
5302 EC_BGP_UPDATE_RCV,
5303 "%s [Error] Update packet error (prefix length mismatch with total length)",
5304 peer->host);
5305 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
5306 }
5307
5308 return BGP_NLRI_PARSE_OK;
5309 }
5310
5311 static struct bgp_static *bgp_static_new(void)
5312 {
5313 return XCALLOC(MTYPE_BGP_STATIC, sizeof(struct bgp_static));
5314 }
5315
5316 static void bgp_static_free(struct bgp_static *bgp_static)
5317 {
5318 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
5319 route_map_counter_decrement(bgp_static->rmap.map);
5320
5321 XFREE(MTYPE_ATTR, bgp_static->eth_s_id);
5322 XFREE(MTYPE_BGP_STATIC, bgp_static);
5323 }
5324
5325 void bgp_static_update(struct bgp *bgp, const struct prefix *p,
5326 struct bgp_static *bgp_static, afi_t afi, safi_t safi)
5327 {
5328 struct bgp_dest *dest;
5329 struct bgp_path_info *pi;
5330 struct bgp_path_info *new;
5331 struct bgp_path_info rmap_path;
5332 struct attr attr;
5333 struct attr *attr_new;
5334 route_map_result_t ret;
5335 #ifdef ENABLE_BGP_VNC
5336 int vnc_implicit_withdraw = 0;
5337 #endif
5338
5339 assert(bgp_static);
5340
5341 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
5342
5343 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
5344
5345 attr.nexthop = bgp_static->igpnexthop;
5346 attr.med = bgp_static->igpmetric;
5347 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
5348
5349 if (bgp_static->atomic)
5350 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
5351
5352 /* Store label index, if required. */
5353 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX) {
5354 attr.label_index = bgp_static->label_index;
5355 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
5356 }
5357
5358 /* Apply route-map. */
5359 if (bgp_static->rmap.name) {
5360 struct attr attr_tmp = attr;
5361
5362 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
5363 rmap_path.peer = bgp->peer_self;
5364 rmap_path.attr = &attr_tmp;
5365
5366 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
5367
5368 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
5369
5370 bgp->peer_self->rmap_type = 0;
5371
5372 if (ret == RMAP_DENYMATCH) {
5373 /* Free uninterned attribute. */
5374 bgp_attr_flush(&attr_tmp);
5375
5376 /* Unintern original. */
5377 aspath_unintern(&attr.aspath);
5378 bgp_static_withdraw(bgp, p, afi, safi);
5379 return;
5380 }
5381
5382 if (bgp_in_graceful_shutdown(bgp))
5383 bgp_attr_add_gshut_community(&attr_tmp);
5384
5385 attr_new = bgp_attr_intern(&attr_tmp);
5386 } else {
5387
5388 if (bgp_in_graceful_shutdown(bgp))
5389 bgp_attr_add_gshut_community(&attr);
5390
5391 attr_new = bgp_attr_intern(&attr);
5392 }
5393
5394 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
5395 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5396 && pi->sub_type == BGP_ROUTE_STATIC)
5397 break;
5398
5399 if (pi) {
5400 if (attrhash_cmp(pi->attr, attr_new)
5401 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
5402 && !CHECK_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS)) {
5403 bgp_dest_unlock_node(dest);
5404 bgp_attr_unintern(&attr_new);
5405 aspath_unintern(&attr.aspath);
5406 return;
5407 } else {
5408 /* The attribute is changed. */
5409 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
5410
5411 /* Rewrite BGP route information. */
5412 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
5413 bgp_path_info_restore(dest, pi);
5414 else
5415 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
5416 #ifdef ENABLE_BGP_VNC
5417 if ((afi == AFI_IP || afi == AFI_IP6)
5418 && (safi == SAFI_UNICAST)) {
5419 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
5420 /*
5421 * Implicit withdraw case.
5422 * We have to do this before pi is
5423 * changed
5424 */
5425 ++vnc_implicit_withdraw;
5426 vnc_import_bgp_del_route(bgp, p, pi);
5427 vnc_import_bgp_exterior_del_route(
5428 bgp, p, pi);
5429 }
5430 }
5431 #endif
5432 bgp_attr_unintern(&pi->attr);
5433 pi->attr = attr_new;
5434 pi->uptime = bgp_clock();
5435 #ifdef ENABLE_BGP_VNC
5436 if ((afi == AFI_IP || afi == AFI_IP6)
5437 && (safi == SAFI_UNICAST)) {
5438 if (vnc_implicit_withdraw) {
5439 vnc_import_bgp_add_route(bgp, p, pi);
5440 vnc_import_bgp_exterior_add_route(
5441 bgp, p, pi);
5442 }
5443 }
5444 #endif
5445
5446 /* Nexthop reachability check. */
5447 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
5448 && (safi == SAFI_UNICAST
5449 || safi == SAFI_LABELED_UNICAST)) {
5450
5451 struct bgp *bgp_nexthop = bgp;
5452
5453 if (pi->extra && pi->extra->bgp_orig)
5454 bgp_nexthop = pi->extra->bgp_orig;
5455
5456 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop,
5457 afi, safi, pi, NULL,
5458 0))
5459 bgp_path_info_set_flag(dest, pi,
5460 BGP_PATH_VALID);
5461 else {
5462 if (BGP_DEBUG(nht, NHT)) {
5463 char buf1[INET6_ADDRSTRLEN];
5464 inet_ntop(p->family,
5465 &p->u.prefix, buf1,
5466 INET6_ADDRSTRLEN);
5467 zlog_debug(
5468 "%s(%s): Route not in table, not advertising",
5469 __func__, buf1);
5470 }
5471 bgp_path_info_unset_flag(
5472 dest, pi, BGP_PATH_VALID);
5473 }
5474 } else {
5475 /* Delete the NHT structure if any, if we're
5476 * toggling between
5477 * enabling/disabling import check. We
5478 * deregister the route
5479 * from NHT to avoid overloading NHT and the
5480 * process interaction
5481 */
5482 bgp_unlink_nexthop(pi);
5483 bgp_path_info_set_flag(dest, pi,
5484 BGP_PATH_VALID);
5485 }
5486 /* Process change. */
5487 bgp_aggregate_increment(bgp, p, pi, afi, safi);
5488 bgp_process(bgp, dest, afi, safi);
5489
5490 if (SAFI_UNICAST == safi
5491 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5492 || bgp->inst_type
5493 == BGP_INSTANCE_TYPE_DEFAULT)) {
5494 vpn_leak_from_vrf_update(bgp_get_default(), bgp,
5495 pi);
5496 }
5497
5498 bgp_dest_unlock_node(dest);
5499 aspath_unintern(&attr.aspath);
5500 return;
5501 }
5502 }
5503
5504 /* Make new BGP info. */
5505 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
5506 attr_new, dest);
5507 /* Nexthop reachability check. */
5508 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
5509 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
5510 if (bgp_find_or_add_nexthop(bgp, bgp, afi, safi, new, NULL, 0))
5511 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
5512 else {
5513 if (BGP_DEBUG(nht, NHT)) {
5514 char buf1[INET6_ADDRSTRLEN];
5515 inet_ntop(p->family, &p->u.prefix, buf1,
5516 INET6_ADDRSTRLEN);
5517 zlog_debug(
5518 "%s(%s): Route not in table, not advertising",
5519 __func__, buf1);
5520 }
5521 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
5522 }
5523 } else {
5524 /* Delete the NHT structure if any, if we're toggling between
5525 * enabling/disabling import check. We deregister the route
5526 * from NHT to avoid overloading NHT and the process interaction
5527 */
5528 bgp_unlink_nexthop(new);
5529
5530 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
5531 }
5532
5533 /* Aggregate address increment. */
5534 bgp_aggregate_increment(bgp, p, new, afi, safi);
5535
5536 /* Register new BGP information. */
5537 bgp_path_info_add(dest, new);
5538
5539 /* route_node_get lock */
5540 bgp_dest_unlock_node(dest);
5541
5542 /* Process change. */
5543 bgp_process(bgp, dest, afi, safi);
5544
5545 if (SAFI_UNICAST == safi
5546 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5547 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
5548 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
5549 }
5550
5551 /* Unintern original. */
5552 aspath_unintern(&attr.aspath);
5553 }
5554
5555 void bgp_static_withdraw(struct bgp *bgp, const struct prefix *p, afi_t afi,
5556 safi_t safi)
5557 {
5558 struct bgp_dest *dest;
5559 struct bgp_path_info *pi;
5560
5561 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
5562
5563 /* Check selected route and self inserted route. */
5564 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
5565 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5566 && pi->sub_type == BGP_ROUTE_STATIC)
5567 break;
5568
5569 /* Withdraw static BGP route from routing table. */
5570 if (pi) {
5571 if (SAFI_UNICAST == safi
5572 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5573 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
5574 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
5575 }
5576 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
5577 bgp_unlink_nexthop(pi);
5578 bgp_path_info_delete(dest, pi);
5579 bgp_process(bgp, dest, afi, safi);
5580 }
5581
5582 /* Unlock bgp_node_lookup. */
5583 bgp_dest_unlock_node(dest);
5584 }
5585
5586 /*
5587 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
5588 */
5589 static void bgp_static_withdraw_safi(struct bgp *bgp, const struct prefix *p,
5590 afi_t afi, safi_t safi,
5591 struct prefix_rd *prd)
5592 {
5593 struct bgp_dest *dest;
5594 struct bgp_path_info *pi;
5595
5596 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
5597
5598 /* Check selected route and self inserted route. */
5599 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
5600 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5601 && pi->sub_type == BGP_ROUTE_STATIC)
5602 break;
5603
5604 /* Withdraw static BGP route from routing table. */
5605 if (pi) {
5606 #ifdef ENABLE_BGP_VNC
5607 rfapiProcessWithdraw(
5608 pi->peer, NULL, p, prd, pi->attr, afi, safi, pi->type,
5609 1); /* Kill, since it is an administrative change */
5610 #endif
5611 if (SAFI_MPLS_VPN == safi
5612 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
5613 vpn_leak_to_vrf_withdraw(bgp, pi);
5614 }
5615 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
5616 bgp_path_info_delete(dest, pi);
5617 bgp_process(bgp, dest, afi, safi);
5618 }
5619
5620 /* Unlock bgp_node_lookup. */
5621 bgp_dest_unlock_node(dest);
5622 }
5623
5624 static void bgp_static_update_safi(struct bgp *bgp, const struct prefix *p,
5625 struct bgp_static *bgp_static, afi_t afi,
5626 safi_t safi)
5627 {
5628 struct bgp_dest *dest;
5629 struct bgp_path_info *new;
5630 struct attr *attr_new;
5631 struct attr attr = {0};
5632 struct bgp_path_info *pi;
5633 #ifdef ENABLE_BGP_VNC
5634 mpls_label_t label = 0;
5635 #endif
5636 uint32_t num_labels = 0;
5637 union gw_addr add;
5638
5639 assert(bgp_static);
5640
5641 if (bgp_static->label != MPLS_INVALID_LABEL)
5642 num_labels = 1;
5643 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p,
5644 &bgp_static->prd);
5645
5646 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
5647
5648 attr.nexthop = bgp_static->igpnexthop;
5649 attr.med = bgp_static->igpmetric;
5650 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
5651
5652 if ((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN)
5653 || (safi == SAFI_ENCAP)) {
5654 if (afi == AFI_IP) {
5655 attr.mp_nexthop_global_in = bgp_static->igpnexthop;
5656 attr.mp_nexthop_len = IPV4_MAX_BYTELEN;
5657 }
5658 }
5659 if (afi == AFI_L2VPN) {
5660 if (bgp_static->gatewayIp.family == AF_INET)
5661 add.ipv4.s_addr =
5662 bgp_static->gatewayIp.u.prefix4.s_addr;
5663 else if (bgp_static->gatewayIp.family == AF_INET6)
5664 memcpy(&(add.ipv6), &(bgp_static->gatewayIp.u.prefix6),
5665 sizeof(struct in6_addr));
5666 memcpy(&attr.esi, bgp_static->eth_s_id, sizeof(esi_t));
5667 if (bgp_static->encap_tunneltype == BGP_ENCAP_TYPE_VXLAN) {
5668 struct bgp_encap_type_vxlan bet;
5669 memset(&bet, 0, sizeof(struct bgp_encap_type_vxlan));
5670 bet.vnid = p->u.prefix_evpn.prefix_addr.eth_tag;
5671 bgp_encap_type_vxlan_to_tlv(&bet, &attr);
5672 }
5673 if (bgp_static->router_mac) {
5674 bgp_add_routermac_ecom(&attr, bgp_static->router_mac);
5675 }
5676 }
5677 /* Apply route-map. */
5678 if (bgp_static->rmap.name) {
5679 struct attr attr_tmp = attr;
5680 struct bgp_path_info rmap_path;
5681 route_map_result_t ret;
5682
5683 rmap_path.peer = bgp->peer_self;
5684 rmap_path.attr = &attr_tmp;
5685
5686 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
5687
5688 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
5689
5690 bgp->peer_self->rmap_type = 0;
5691
5692 if (ret == RMAP_DENYMATCH) {
5693 /* Free uninterned attribute. */
5694 bgp_attr_flush(&attr_tmp);
5695
5696 /* Unintern original. */
5697 aspath_unintern(&attr.aspath);
5698 bgp_static_withdraw_safi(bgp, p, afi, safi,
5699 &bgp_static->prd);
5700 return;
5701 }
5702
5703 attr_new = bgp_attr_intern(&attr_tmp);
5704 } else {
5705 attr_new = bgp_attr_intern(&attr);
5706 }
5707
5708 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
5709 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5710 && pi->sub_type == BGP_ROUTE_STATIC)
5711 break;
5712
5713 if (pi) {
5714 memset(&add, 0, sizeof(union gw_addr));
5715 if (attrhash_cmp(pi->attr, attr_new)
5716 && overlay_index_equal(afi, pi, &add)
5717 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
5718 bgp_dest_unlock_node(dest);
5719 bgp_attr_unintern(&attr_new);
5720 aspath_unintern(&attr.aspath);
5721 return;
5722 } else {
5723 /* The attribute is changed. */
5724 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
5725
5726 /* Rewrite BGP route information. */
5727 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
5728 bgp_path_info_restore(dest, pi);
5729 else
5730 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
5731 bgp_attr_unintern(&pi->attr);
5732 pi->attr = attr_new;
5733 pi->uptime = bgp_clock();
5734 #ifdef ENABLE_BGP_VNC
5735 if (pi->extra)
5736 label = decode_label(&pi->extra->label[0]);
5737 #endif
5738
5739 /* Process change. */
5740 bgp_aggregate_increment(bgp, p, pi, afi, safi);
5741 bgp_process(bgp, dest, afi, safi);
5742
5743 if (SAFI_MPLS_VPN == safi
5744 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
5745 vpn_leak_to_vrf_update(bgp, pi);
5746 }
5747 #ifdef ENABLE_BGP_VNC
5748 rfapiProcessUpdate(pi->peer, NULL, p, &bgp_static->prd,
5749 pi->attr, afi, safi, pi->type,
5750 pi->sub_type, &label);
5751 #endif
5752 bgp_dest_unlock_node(dest);
5753 aspath_unintern(&attr.aspath);
5754 return;
5755 }
5756 }
5757
5758
5759 /* Make new BGP info. */
5760 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
5761 attr_new, dest);
5762 SET_FLAG(new->flags, BGP_PATH_VALID);
5763 new->extra = bgp_path_info_extra_new();
5764 if (num_labels) {
5765 new->extra->label[0] = bgp_static->label;
5766 new->extra->num_labels = num_labels;
5767 }
5768 #ifdef ENABLE_BGP_VNC
5769 label = decode_label(&bgp_static->label);
5770 #endif
5771
5772 /* Aggregate address increment. */
5773 bgp_aggregate_increment(bgp, p, new, afi, safi);
5774
5775 /* Register new BGP information. */
5776 bgp_path_info_add(dest, new);
5777 /* route_node_get lock */
5778 bgp_dest_unlock_node(dest);
5779
5780 /* Process change. */
5781 bgp_process(bgp, dest, afi, safi);
5782
5783 if (SAFI_MPLS_VPN == safi
5784 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
5785 vpn_leak_to_vrf_update(bgp, new);
5786 }
5787 #ifdef ENABLE_BGP_VNC
5788 rfapiProcessUpdate(new->peer, NULL, p, &bgp_static->prd, new->attr, afi,
5789 safi, new->type, new->sub_type, &label);
5790 #endif
5791
5792 /* Unintern original. */
5793 aspath_unintern(&attr.aspath);
5794 }
5795
5796 /* Configure static BGP network. When user don't run zebra, static
5797 route should be installed as valid. */
5798 int bgp_static_set(struct bgp *bgp, const char *negate, struct prefix *pfx,
5799 afi_t afi, safi_t safi, const char *rmap, int backdoor,
5800 uint32_t label_index, char *errmsg, size_t errmsg_len)
5801 {
5802 struct prefix p;
5803 struct bgp_static *bgp_static;
5804 struct bgp_dest *dest;
5805 uint8_t need_update = 0;
5806
5807 prefix_copy(&p, pfx);
5808 apply_mask(&p);
5809
5810 if (negate) {
5811
5812 /* Set BGP static route configuration. */
5813 dest = bgp_node_lookup(bgp->route[afi][safi], &p);
5814
5815 if (!dest) {
5816 snprintf(errmsg, errmsg_len,
5817 "Can't find static route specified\n");
5818 return -1;
5819 }
5820
5821 bgp_static = bgp_dest_get_bgp_static_info(dest);
5822
5823 if ((label_index != BGP_INVALID_LABEL_INDEX)
5824 && (label_index != bgp_static->label_index)) {
5825 snprintf(errmsg, errmsg_len,
5826 "label-index doesn't match static route\n");
5827 return -1;
5828 }
5829
5830 if ((rmap && bgp_static->rmap.name)
5831 && strcmp(rmap, bgp_static->rmap.name)) {
5832 snprintf(errmsg, errmsg_len,
5833 "route-map name doesn't match static route\n");
5834 return -1;
5835 }
5836
5837 /* Update BGP RIB. */
5838 if (!bgp_static->backdoor)
5839 bgp_static_withdraw(bgp, &p, afi, safi);
5840
5841 /* Clear configuration. */
5842 bgp_static_free(bgp_static);
5843 bgp_dest_set_bgp_static_info(dest, NULL);
5844 bgp_dest_unlock_node(dest);
5845 bgp_dest_unlock_node(dest);
5846 } else {
5847
5848 /* Set BGP static route configuration. */
5849 dest = bgp_node_get(bgp->route[afi][safi], &p);
5850 bgp_static = bgp_dest_get_bgp_static_info(dest);
5851 if (bgp_static) {
5852 /* Configuration change. */
5853 /* Label index cannot be changed. */
5854 if (bgp_static->label_index != label_index) {
5855 snprintf(errmsg, errmsg_len,
5856 "cannot change label-index\n");
5857 return -1;
5858 }
5859
5860 /* Check previous routes are installed into BGP. */
5861 if (bgp_static->valid
5862 && bgp_static->backdoor != backdoor)
5863 need_update = 1;
5864
5865 bgp_static->backdoor = backdoor;
5866
5867 if (rmap) {
5868 XFREE(MTYPE_ROUTE_MAP_NAME,
5869 bgp_static->rmap.name);
5870 route_map_counter_decrement(
5871 bgp_static->rmap.map);
5872 bgp_static->rmap.name =
5873 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
5874 bgp_static->rmap.map =
5875 route_map_lookup_by_name(rmap);
5876 route_map_counter_increment(
5877 bgp_static->rmap.map);
5878 } else {
5879 XFREE(MTYPE_ROUTE_MAP_NAME,
5880 bgp_static->rmap.name);
5881 route_map_counter_decrement(
5882 bgp_static->rmap.map);
5883 bgp_static->rmap.map = NULL;
5884 bgp_static->valid = 0;
5885 }
5886 bgp_dest_unlock_node(dest);
5887 } else {
5888 /* New configuration. */
5889 bgp_static = bgp_static_new();
5890 bgp_static->backdoor = backdoor;
5891 bgp_static->valid = 0;
5892 bgp_static->igpmetric = 0;
5893 bgp_static->igpnexthop.s_addr = INADDR_ANY;
5894 bgp_static->label_index = label_index;
5895
5896 if (rmap) {
5897 XFREE(MTYPE_ROUTE_MAP_NAME,
5898 bgp_static->rmap.name);
5899 route_map_counter_decrement(
5900 bgp_static->rmap.map);
5901 bgp_static->rmap.name =
5902 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
5903 bgp_static->rmap.map =
5904 route_map_lookup_by_name(rmap);
5905 route_map_counter_increment(
5906 bgp_static->rmap.map);
5907 }
5908 bgp_dest_set_bgp_static_info(dest, bgp_static);
5909 }
5910
5911 bgp_static->valid = 1;
5912 if (need_update)
5913 bgp_static_withdraw(bgp, &p, afi, safi);
5914
5915 if (!bgp_static->backdoor)
5916 bgp_static_update(bgp, &p, bgp_static, afi, safi);
5917 }
5918
5919 return 0;
5920 }
5921
5922 void bgp_static_add(struct bgp *bgp)
5923 {
5924 afi_t afi;
5925 safi_t safi;
5926 struct bgp_dest *dest;
5927 struct bgp_dest *rm;
5928 struct bgp_table *table;
5929 struct bgp_static *bgp_static;
5930
5931 FOREACH_AFI_SAFI (afi, safi)
5932 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
5933 dest = bgp_route_next(dest)) {
5934 if (!bgp_dest_has_bgp_path_info_data(dest))
5935 continue;
5936
5937 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
5938 || (safi == SAFI_EVPN)) {
5939 table = bgp_dest_get_bgp_table_info(dest);
5940
5941 for (rm = bgp_table_top(table); rm;
5942 rm = bgp_route_next(rm)) {
5943 bgp_static =
5944 bgp_dest_get_bgp_static_info(
5945 rm);
5946 bgp_static_update_safi(
5947 bgp, bgp_dest_get_prefix(rm),
5948 bgp_static, afi, safi);
5949 }
5950 } else {
5951 bgp_static_update(
5952 bgp, bgp_dest_get_prefix(dest),
5953 bgp_dest_get_bgp_static_info(dest), afi,
5954 safi);
5955 }
5956 }
5957 }
5958
5959 /* Called from bgp_delete(). Delete all static routes from the BGP
5960 instance. */
5961 void bgp_static_delete(struct bgp *bgp)
5962 {
5963 afi_t afi;
5964 safi_t safi;
5965 struct bgp_dest *dest;
5966 struct bgp_dest *rm;
5967 struct bgp_table *table;
5968 struct bgp_static *bgp_static;
5969
5970 FOREACH_AFI_SAFI (afi, safi)
5971 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
5972 dest = bgp_route_next(dest)) {
5973 if (!bgp_dest_has_bgp_path_info_data(dest))
5974 continue;
5975
5976 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
5977 || (safi == SAFI_EVPN)) {
5978 table = bgp_dest_get_bgp_table_info(dest);
5979
5980 for (rm = bgp_table_top(table); rm;
5981 rm = bgp_route_next(rm)) {
5982 bgp_static =
5983 bgp_dest_get_bgp_static_info(
5984 rm);
5985 if (!bgp_static)
5986 continue;
5987
5988 bgp_static_withdraw_safi(
5989 bgp, bgp_dest_get_prefix(rm),
5990 AFI_IP, safi,
5991 (struct prefix_rd *)
5992 bgp_dest_get_prefix(
5993 dest));
5994 bgp_static_free(bgp_static);
5995 bgp_dest_set_bgp_static_info(rm,
5996 NULL);
5997 bgp_dest_unlock_node(rm);
5998 }
5999 } else {
6000 bgp_static = bgp_dest_get_bgp_static_info(dest);
6001 bgp_static_withdraw(bgp,
6002 bgp_dest_get_prefix(dest),
6003 afi, safi);
6004 bgp_static_free(bgp_static);
6005 bgp_dest_set_bgp_static_info(dest, NULL);
6006 bgp_dest_unlock_node(dest);
6007 }
6008 }
6009 }
6010
6011 void bgp_static_redo_import_check(struct bgp *bgp)
6012 {
6013 afi_t afi;
6014 safi_t safi;
6015 struct bgp_dest *dest;
6016 struct bgp_dest *rm;
6017 struct bgp_table *table;
6018 struct bgp_static *bgp_static;
6019
6020 /* Use this flag to force reprocessing of the route */
6021 SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
6022 FOREACH_AFI_SAFI (afi, safi) {
6023 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6024 dest = bgp_route_next(dest)) {
6025 if (!bgp_dest_has_bgp_path_info_data(dest))
6026 continue;
6027
6028 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6029 || (safi == SAFI_EVPN)) {
6030 table = bgp_dest_get_bgp_table_info(dest);
6031
6032 for (rm = bgp_table_top(table); rm;
6033 rm = bgp_route_next(rm)) {
6034 bgp_static =
6035 bgp_dest_get_bgp_static_info(
6036 rm);
6037 bgp_static_update_safi(
6038 bgp, bgp_dest_get_prefix(rm),
6039 bgp_static, afi, safi);
6040 }
6041 } else {
6042 bgp_static = bgp_dest_get_bgp_static_info(dest);
6043 bgp_static_update(bgp,
6044 bgp_dest_get_prefix(dest),
6045 bgp_static, afi, safi);
6046 }
6047 }
6048 }
6049 UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
6050 }
6051
6052 static void bgp_purge_af_static_redist_routes(struct bgp *bgp, afi_t afi,
6053 safi_t safi)
6054 {
6055 struct bgp_table *table;
6056 struct bgp_dest *dest;
6057 struct bgp_path_info *pi;
6058
6059 /* Do not install the aggregate route if BGP is in the
6060 * process of termination.
6061 */
6062 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
6063 || (bgp->peer_self == NULL))
6064 return;
6065
6066 table = bgp->rib[afi][safi];
6067 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6068 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
6069 if (pi->peer == bgp->peer_self
6070 && ((pi->type == ZEBRA_ROUTE_BGP
6071 && pi->sub_type == BGP_ROUTE_STATIC)
6072 || (pi->type != ZEBRA_ROUTE_BGP
6073 && pi->sub_type
6074 == BGP_ROUTE_REDISTRIBUTE))) {
6075 bgp_aggregate_decrement(
6076 bgp, bgp_dest_get_prefix(dest), pi, afi,
6077 safi);
6078 bgp_unlink_nexthop(pi);
6079 bgp_path_info_delete(dest, pi);
6080 bgp_process(bgp, dest, afi, safi);
6081 }
6082 }
6083 }
6084 }
6085
6086 /*
6087 * Purge all networks and redistributed routes from routing table.
6088 * Invoked upon the instance going down.
6089 */
6090 void bgp_purge_static_redist_routes(struct bgp *bgp)
6091 {
6092 afi_t afi;
6093 safi_t safi;
6094
6095 FOREACH_AFI_SAFI (afi, safi)
6096 bgp_purge_af_static_redist_routes(bgp, afi, safi);
6097 }
6098
6099 /*
6100 * gpz 110624
6101 * Currently this is used to set static routes for VPN and ENCAP.
6102 * I think it can probably be factored with bgp_static_set.
6103 */
6104 int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty,
6105 const char *ip_str, const char *rd_str,
6106 const char *label_str, const char *rmap_str,
6107 int evpn_type, const char *esi, const char *gwip,
6108 const char *ethtag, const char *routermac)
6109 {
6110 VTY_DECLVAR_CONTEXT(bgp, bgp);
6111 int ret;
6112 struct prefix p;
6113 struct prefix_rd prd;
6114 struct bgp_dest *pdest;
6115 struct bgp_dest *dest;
6116 struct bgp_table *table;
6117 struct bgp_static *bgp_static;
6118 mpls_label_t label = MPLS_INVALID_LABEL;
6119 struct prefix gw_ip;
6120
6121 /* validate ip prefix */
6122 ret = str2prefix(ip_str, &p);
6123 if (!ret) {
6124 vty_out(vty, "%% Malformed prefix\n");
6125 return CMD_WARNING_CONFIG_FAILED;
6126 }
6127 apply_mask(&p);
6128 if ((afi == AFI_L2VPN)
6129 && (bgp_build_evpn_prefix(evpn_type,
6130 ethtag != NULL ? atol(ethtag) : 0, &p))) {
6131 vty_out(vty, "%% L2VPN prefix could not be forged\n");
6132 return CMD_WARNING_CONFIG_FAILED;
6133 }
6134
6135 ret = str2prefix_rd(rd_str, &prd);
6136 if (!ret) {
6137 vty_out(vty, "%% Malformed rd\n");
6138 return CMD_WARNING_CONFIG_FAILED;
6139 }
6140
6141 if (label_str) {
6142 unsigned long label_val;
6143 label_val = strtoul(label_str, NULL, 10);
6144 encode_label(label_val, &label);
6145 }
6146
6147 if (safi == SAFI_EVPN) {
6148 if (esi && str2esi(esi, NULL) == 0) {
6149 vty_out(vty, "%% Malformed ESI\n");
6150 return CMD_WARNING_CONFIG_FAILED;
6151 }
6152 if (routermac && prefix_str2mac(routermac, NULL) == 0) {
6153 vty_out(vty, "%% Malformed Router MAC\n");
6154 return CMD_WARNING_CONFIG_FAILED;
6155 }
6156 if (gwip) {
6157 memset(&gw_ip, 0, sizeof(struct prefix));
6158 ret = str2prefix(gwip, &gw_ip);
6159 if (!ret) {
6160 vty_out(vty, "%% Malformed GatewayIp\n");
6161 return CMD_WARNING_CONFIG_FAILED;
6162 }
6163 if ((gw_ip.family == AF_INET
6164 && is_evpn_prefix_ipaddr_v6(
6165 (struct prefix_evpn *)&p))
6166 || (gw_ip.family == AF_INET6
6167 && is_evpn_prefix_ipaddr_v4(
6168 (struct prefix_evpn *)&p))) {
6169 vty_out(vty,
6170 "%% GatewayIp family differs with IP prefix\n");
6171 return CMD_WARNING_CONFIG_FAILED;
6172 }
6173 }
6174 }
6175 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
6176 if (!bgp_dest_has_bgp_path_info_data(pdest))
6177 bgp_dest_set_bgp_table_info(pdest,
6178 bgp_table_init(bgp, afi, safi));
6179 table = bgp_dest_get_bgp_table_info(pdest);
6180
6181 dest = bgp_node_get(table, &p);
6182
6183 if (bgp_dest_has_bgp_path_info_data(dest)) {
6184 vty_out(vty, "%% Same network configuration exists\n");
6185 bgp_dest_unlock_node(dest);
6186 } else {
6187 /* New configuration. */
6188 bgp_static = bgp_static_new();
6189 bgp_static->backdoor = 0;
6190 bgp_static->valid = 0;
6191 bgp_static->igpmetric = 0;
6192 bgp_static->igpnexthop.s_addr = INADDR_ANY;
6193 bgp_static->label = label;
6194 bgp_static->prd = prd;
6195
6196 if (rmap_str) {
6197 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
6198 route_map_counter_decrement(bgp_static->rmap.map);
6199 bgp_static->rmap.name =
6200 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_str);
6201 bgp_static->rmap.map =
6202 route_map_lookup_by_name(rmap_str);
6203 route_map_counter_increment(bgp_static->rmap.map);
6204 }
6205
6206 if (safi == SAFI_EVPN) {
6207 if (esi) {
6208 bgp_static->eth_s_id =
6209 XCALLOC(MTYPE_ATTR,
6210 sizeof(esi_t));
6211 str2esi(esi, bgp_static->eth_s_id);
6212 }
6213 if (routermac) {
6214 bgp_static->router_mac =
6215 XCALLOC(MTYPE_ATTR, ETH_ALEN + 1);
6216 (void)prefix_str2mac(routermac,
6217 bgp_static->router_mac);
6218 }
6219 if (gwip)
6220 prefix_copy(&bgp_static->gatewayIp, &gw_ip);
6221 }
6222 bgp_dest_set_bgp_static_info(dest, bgp_static);
6223
6224 bgp_static->valid = 1;
6225 bgp_static_update_safi(bgp, &p, bgp_static, afi, safi);
6226 }
6227
6228 return CMD_SUCCESS;
6229 }
6230
6231 /* Configure static BGP network. */
6232 int bgp_static_unset_safi(afi_t afi, safi_t safi, struct vty *vty,
6233 const char *ip_str, const char *rd_str,
6234 const char *label_str, int evpn_type, const char *esi,
6235 const char *gwip, const char *ethtag)
6236 {
6237 VTY_DECLVAR_CONTEXT(bgp, bgp);
6238 int ret;
6239 struct prefix p;
6240 struct prefix_rd prd;
6241 struct bgp_dest *pdest;
6242 struct bgp_dest *dest;
6243 struct bgp_table *table;
6244 struct bgp_static *bgp_static;
6245 mpls_label_t label = MPLS_INVALID_LABEL;
6246
6247 /* Convert IP prefix string to struct prefix. */
6248 ret = str2prefix(ip_str, &p);
6249 if (!ret) {
6250 vty_out(vty, "%% Malformed prefix\n");
6251 return CMD_WARNING_CONFIG_FAILED;
6252 }
6253 apply_mask(&p);
6254 if ((afi == AFI_L2VPN)
6255 && (bgp_build_evpn_prefix(evpn_type,
6256 ethtag != NULL ? atol(ethtag) : 0, &p))) {
6257 vty_out(vty, "%% L2VPN prefix could not be forged\n");
6258 return CMD_WARNING_CONFIG_FAILED;
6259 }
6260 ret = str2prefix_rd(rd_str, &prd);
6261 if (!ret) {
6262 vty_out(vty, "%% Malformed rd\n");
6263 return CMD_WARNING_CONFIG_FAILED;
6264 }
6265
6266 if (label_str) {
6267 unsigned long label_val;
6268 label_val = strtoul(label_str, NULL, 10);
6269 encode_label(label_val, &label);
6270 }
6271
6272 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
6273 if (!bgp_dest_has_bgp_path_info_data(pdest))
6274 bgp_dest_set_bgp_table_info(pdest,
6275 bgp_table_init(bgp, afi, safi));
6276 else
6277 bgp_dest_unlock_node(pdest);
6278 table = bgp_dest_get_bgp_table_info(pdest);
6279
6280 dest = bgp_node_lookup(table, &p);
6281
6282 if (dest) {
6283 bgp_static_withdraw_safi(bgp, &p, afi, safi, &prd);
6284
6285 bgp_static = bgp_dest_get_bgp_static_info(dest);
6286 bgp_static_free(bgp_static);
6287 bgp_dest_set_bgp_static_info(dest, NULL);
6288 bgp_dest_unlock_node(dest);
6289 bgp_dest_unlock_node(dest);
6290 } else
6291 vty_out(vty, "%% Can't find the route\n");
6292
6293 return CMD_SUCCESS;
6294 }
6295
6296 static int bgp_table_map_set(struct vty *vty, afi_t afi, safi_t safi,
6297 const char *rmap_name)
6298 {
6299 VTY_DECLVAR_CONTEXT(bgp, bgp);
6300 struct bgp_rmap *rmap;
6301
6302 rmap = &bgp->table_map[afi][safi];
6303 if (rmap_name) {
6304 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
6305 route_map_counter_decrement(rmap->map);
6306 rmap->name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name);
6307 rmap->map = route_map_lookup_by_name(rmap_name);
6308 route_map_counter_increment(rmap->map);
6309 } else {
6310 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
6311 route_map_counter_decrement(rmap->map);
6312 rmap->map = NULL;
6313 }
6314
6315 if (bgp_fibupd_safi(safi))
6316 bgp_zebra_announce_table(bgp, afi, safi);
6317
6318 return CMD_SUCCESS;
6319 }
6320
6321 static int bgp_table_map_unset(struct vty *vty, afi_t afi, safi_t safi,
6322 const char *rmap_name)
6323 {
6324 VTY_DECLVAR_CONTEXT(bgp, bgp);
6325 struct bgp_rmap *rmap;
6326
6327 rmap = &bgp->table_map[afi][safi];
6328 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
6329 route_map_counter_decrement(rmap->map);
6330 rmap->map = NULL;
6331
6332 if (bgp_fibupd_safi(safi))
6333 bgp_zebra_announce_table(bgp, afi, safi);
6334
6335 return CMD_SUCCESS;
6336 }
6337
6338 void bgp_config_write_table_map(struct vty *vty, struct bgp *bgp, afi_t afi,
6339 safi_t safi)
6340 {
6341 if (bgp->table_map[afi][safi].name) {
6342 vty_out(vty, " table-map %s\n",
6343 bgp->table_map[afi][safi].name);
6344 }
6345 }
6346
6347 DEFUN (bgp_table_map,
6348 bgp_table_map_cmd,
6349 "table-map WORD",
6350 "BGP table to RIB route download filter\n"
6351 "Name of the route map\n")
6352 {
6353 int idx_word = 1;
6354 return bgp_table_map_set(vty, bgp_node_afi(vty), bgp_node_safi(vty),
6355 argv[idx_word]->arg);
6356 }
6357 DEFUN (no_bgp_table_map,
6358 no_bgp_table_map_cmd,
6359 "no table-map WORD",
6360 NO_STR
6361 "BGP table to RIB route download filter\n"
6362 "Name of the route map\n")
6363 {
6364 int idx_word = 2;
6365 return bgp_table_map_unset(vty, bgp_node_afi(vty), bgp_node_safi(vty),
6366 argv[idx_word]->arg);
6367 }
6368
6369 DEFPY_YANG (bgp_network, bgp_network_cmd,
6370 "[no] network \
6371 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
6372 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
6373 backdoor$backdoor}]",
6374 NO_STR
6375 "Specify a network to announce via BGP\n"
6376 "IPv4 prefix\n"
6377 "Network number\n"
6378 "Network mask\n"
6379 "Network mask\n"
6380 "Route-map to modify the attributes\n"
6381 "Name of the route map\n"
6382 "Label index to associate with the prefix\n"
6383 "Label index value\n"
6384 "Specify a BGP backdoor route\n")
6385 {
6386 char addr_prefix_str[PREFIX_STRLEN];
6387 char base_xpath[XPATH_MAXLEN];
6388 afi_t afi;
6389 safi_t safi;
6390
6391 if (address_str) {
6392 int ret;
6393
6394 ret = netmask_str2prefix_str(address_str, netmask_str,
6395 addr_prefix_str,
6396 sizeof(addr_prefix_str));
6397 if (!ret) {
6398 vty_out(vty, "%% Inconsistent address and mask\n");
6399 return CMD_WARNING_CONFIG_FAILED;
6400 }
6401 }
6402
6403 afi = bgp_node_afi(vty);
6404 safi = bgp_node_safi(vty);
6405
6406 if (no) {
6407 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
6408 } else {
6409 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
6410
6411 if (map_name)
6412 nb_cli_enqueue_change(vty, "./rmap-policy-export",
6413 NB_OP_CREATE, map_name);
6414 else
6415 nb_cli_enqueue_change(vty, "./rmap-policy-export",
6416 NB_OP_DESTROY, NULL);
6417
6418 if (label_index_str)
6419 nb_cli_enqueue_change(vty, "./label-index",
6420 NB_OP_MODIFY, label_index_str);
6421
6422 nb_cli_enqueue_change(vty, "./backdoor", NB_OP_MODIFY,
6423 backdoor ? "true" : "false");
6424 }
6425
6426 snprintf(
6427 base_xpath, sizeof(base_xpath),
6428 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/network-config[prefix='%s']",
6429 yang_afi_safi_value2identity(afi, safi),
6430 bgp_afi_safi_get_container_str(afi, safi),
6431 address_str ? addr_prefix_str : prefix_str);
6432
6433 return nb_cli_apply_changes(vty, base_xpath);
6434 }
6435
6436 DEFPY_YANG (ipv6_bgp_network,
6437 ipv6_bgp_network_cmd,
6438 "[no] network X:X::X:X/M$prefix \
6439 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
6440 NO_STR
6441 "Specify a network to announce via BGP\n"
6442 "IPv6 prefix\n"
6443 "Route-map to modify the attributes\n"
6444 "Name of the route map\n"
6445 "Label index to associate with the prefix\n"
6446 "Label index value\n")
6447 {
6448 char base_xpath[XPATH_MAXLEN];
6449 afi_t afi;
6450 safi_t safi;
6451
6452 afi = bgp_node_afi(vty);
6453 safi = bgp_node_safi(vty);
6454
6455 if (no) {
6456 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
6457 } else {
6458 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
6459
6460 if (map_name)
6461 nb_cli_enqueue_change(vty, "./rmap-policy-export",
6462 NB_OP_MODIFY, map_name);
6463 else
6464 nb_cli_enqueue_change(vty, "./rmap-policy-export",
6465 NB_OP_DESTROY, NULL);
6466
6467 if (label_index_str)
6468 nb_cli_enqueue_change(vty, "./label-index",
6469 NB_OP_MODIFY, label_index_str);
6470 }
6471
6472 snprintf(
6473 base_xpath, sizeof(base_xpath),
6474 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/network-config[prefix='%s']",
6475 yang_afi_safi_value2identity(afi, safi),
6476 bgp_afi_safi_get_container_str(afi, safi), prefix_str);
6477
6478 return nb_cli_apply_changes(vty, base_xpath);
6479 }
6480
6481 void cli_show_bgp_global_afi_safi_network_config(struct vty *vty,
6482 struct lyd_node *dnode,
6483 bool show_defaults)
6484 {
6485 vty_out(vty, " network %s", yang_dnode_get_string(dnode, "./prefix"));
6486
6487 if (yang_dnode_exists(dnode, "./label-index"))
6488 vty_out(vty, " label-index %s",
6489 yang_dnode_get_string(dnode, "./label-index"));
6490
6491 if (yang_dnode_exists(dnode, "./rmap-policy-export"))
6492 vty_out(vty, " route-map %s",
6493 yang_dnode_get_string(dnode, "./rmap-policy-export"));
6494
6495 if (yang_dnode_get_bool(dnode, "./backdoor"))
6496 vty_out(vty, " backdoor");
6497
6498 vty_out(vty, "\n");
6499 }
6500
6501 static struct bgp_aggregate *bgp_aggregate_new(void)
6502 {
6503 return XCALLOC(MTYPE_BGP_AGGREGATE, sizeof(struct bgp_aggregate));
6504 }
6505
6506 static void bgp_aggregate_free(struct bgp_aggregate *aggregate)
6507 {
6508 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
6509 route_map_counter_decrement(aggregate->suppress_map);
6510 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
6511 route_map_counter_decrement(aggregate->rmap.map);
6512 XFREE(MTYPE_BGP_AGGREGATE, aggregate);
6513 }
6514
6515 /**
6516 * Helper function to avoid repeated code: prepare variables for a
6517 * `route_map_apply` call.
6518 *
6519 * \returns `true` on route map match, otherwise `false`.
6520 */
6521 static bool aggr_suppress_map_test(struct bgp *bgp,
6522 struct bgp_aggregate *aggregate,
6523 struct bgp_path_info *pi)
6524 {
6525 const struct prefix *p = bgp_dest_get_prefix(pi->net);
6526 route_map_result_t rmr = RMAP_DENYMATCH;
6527 struct bgp_path_info rmap_path = {};
6528 struct attr attr = {};
6529
6530 /* No route map entries created, just don't match. */
6531 if (aggregate->suppress_map == NULL)
6532 return false;
6533
6534 /* Call route map matching and return result. */
6535 attr.aspath = aspath_empty();
6536 rmap_path.peer = bgp->peer_self;
6537 rmap_path.attr = &attr;
6538
6539 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_AGGREGATE);
6540 rmr = route_map_apply(aggregate->suppress_map, p, &rmap_path);
6541 bgp->peer_self->rmap_type = 0;
6542
6543 bgp_attr_flush(&attr);
6544
6545 return rmr == RMAP_PERMITMATCH;
6546 }
6547
6548 /** Test whether the aggregation has suppressed this path or not. */
6549 static bool aggr_suppress_exists(struct bgp_aggregate *aggregate,
6550 struct bgp_path_info *pi)
6551 {
6552 if (pi->extra == NULL || pi->extra->aggr_suppressors == NULL)
6553 return false;
6554
6555 return listnode_lookup(pi->extra->aggr_suppressors, aggregate) != NULL;
6556 }
6557
6558 /**
6559 * Suppress this path and keep the reference.
6560 *
6561 * \returns `true` if needs processing otherwise `false`.
6562 */
6563 static bool aggr_suppress_path(struct bgp_aggregate *aggregate,
6564 struct bgp_path_info *pi)
6565 {
6566 struct bgp_path_info_extra *pie;
6567
6568 /* Path is already suppressed by this aggregation. */
6569 if (aggr_suppress_exists(aggregate, pi))
6570 return false;
6571
6572 pie = bgp_path_info_extra_get(pi);
6573
6574 /* This is the first suppression, allocate memory and list it. */
6575 if (pie->aggr_suppressors == NULL)
6576 pie->aggr_suppressors = list_new();
6577
6578 listnode_add(pie->aggr_suppressors, aggregate);
6579
6580 /* Only mark for processing if suppressed. */
6581 if (listcount(pie->aggr_suppressors) == 1) {
6582 if (BGP_DEBUG(update, UPDATE_OUT))
6583 zlog_debug("aggregate-address suppressing: %pFX",
6584 bgp_dest_get_prefix(pi->net));
6585
6586 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
6587 return true;
6588 }
6589
6590 return false;
6591 }
6592
6593 /**
6594 * Unsuppress this path and remove the reference.
6595 *
6596 * \returns `true` if needs processing otherwise `false`.
6597 */
6598 static bool aggr_unsuppress_path(struct bgp_aggregate *aggregate,
6599 struct bgp_path_info *pi)
6600 {
6601 /* Path wasn't suppressed. */
6602 if (!aggr_suppress_exists(aggregate, pi))
6603 return false;
6604
6605 listnode_delete(pi->extra->aggr_suppressors, aggregate);
6606
6607 /* Unsuppress and free extra memory if last item. */
6608 if (listcount(pi->extra->aggr_suppressors) == 0) {
6609 if (BGP_DEBUG(update, UPDATE_OUT))
6610 zlog_debug("aggregate-address unsuppressing: %pFX",
6611 bgp_dest_get_prefix(pi->net));
6612
6613 list_delete(&pi->extra->aggr_suppressors);
6614 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
6615 return true;
6616 }
6617
6618 return false;
6619 }
6620
6621 static bool bgp_aggregate_info_same(struct bgp_path_info *pi, uint8_t origin,
6622 struct aspath *aspath,
6623 struct community *comm,
6624 struct ecommunity *ecomm,
6625 struct lcommunity *lcomm)
6626 {
6627 static struct aspath *ae = NULL;
6628
6629 if (!ae)
6630 ae = aspath_empty();
6631
6632 if (!pi)
6633 return false;
6634
6635 if (origin != pi->attr->origin)
6636 return false;
6637
6638 if (!aspath_cmp(pi->attr->aspath, (aspath) ? aspath : ae))
6639 return false;
6640
6641 if (!community_cmp(pi->attr->community, comm))
6642 return false;
6643
6644 if (!ecommunity_cmp(pi->attr->ecommunity, ecomm))
6645 return false;
6646
6647 if (!lcommunity_cmp(pi->attr->lcommunity, lcomm))
6648 return false;
6649
6650 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID))
6651 return false;
6652
6653 return true;
6654 }
6655
6656 static void bgp_aggregate_install(
6657 struct bgp *bgp, afi_t afi, safi_t safi, const struct prefix *p,
6658 uint8_t origin, struct aspath *aspath, struct community *community,
6659 struct ecommunity *ecommunity, struct lcommunity *lcommunity,
6660 uint8_t atomic_aggregate, struct bgp_aggregate *aggregate)
6661 {
6662 struct bgp_dest *dest;
6663 struct bgp_table *table;
6664 struct bgp_path_info *pi, *orig, *new;
6665 struct attr *attr;
6666
6667 table = bgp->rib[afi][safi];
6668
6669 dest = bgp_node_get(table, p);
6670
6671 for (orig = pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
6672 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6673 && pi->sub_type == BGP_ROUTE_AGGREGATE)
6674 break;
6675
6676 /*
6677 * If we have paths with different MEDs, then don't install
6678 * (or uninstall) the aggregate route.
6679 */
6680 if (aggregate->match_med && aggregate->med_mismatched)
6681 goto uninstall_aggregate_route;
6682
6683 if (aggregate->count > 0) {
6684 /*
6685 * If the aggregate information has not changed
6686 * no need to re-install it again.
6687 */
6688 if (bgp_aggregate_info_same(orig, origin, aspath, community,
6689 ecommunity, lcommunity)) {
6690 bgp_dest_unlock_node(dest);
6691
6692 if (aspath)
6693 aspath_free(aspath);
6694 if (community)
6695 community_free(&community);
6696 if (ecommunity)
6697 ecommunity_free(&ecommunity);
6698 if (lcommunity)
6699 lcommunity_free(&lcommunity);
6700
6701 return;
6702 }
6703
6704 /*
6705 * Mark the old as unusable
6706 */
6707 if (pi)
6708 bgp_path_info_delete(dest, pi);
6709
6710 attr = bgp_attr_aggregate_intern(
6711 bgp, origin, aspath, community, ecommunity, lcommunity,
6712 aggregate, atomic_aggregate, p);
6713
6714 if (!attr) {
6715 bgp_aggregate_delete(bgp, p, afi, safi, aggregate);
6716 if (BGP_DEBUG(update_groups, UPDATE_GROUPS))
6717 zlog_debug("%s: %pFX null attribute", __func__,
6718 p);
6719 return;
6720 }
6721
6722 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0,
6723 bgp->peer_self, attr, dest);
6724
6725 SET_FLAG(new->flags, BGP_PATH_VALID);
6726
6727 bgp_path_info_add(dest, new);
6728 bgp_process(bgp, dest, afi, safi);
6729 } else {
6730 uninstall_aggregate_route:
6731 for (pi = orig; pi; pi = pi->next)
6732 if (pi->peer == bgp->peer_self
6733 && pi->type == ZEBRA_ROUTE_BGP
6734 && pi->sub_type == BGP_ROUTE_AGGREGATE)
6735 break;
6736
6737 /* Withdraw static BGP route from routing table. */
6738 if (pi) {
6739 bgp_path_info_delete(dest, pi);
6740 bgp_process(bgp, dest, afi, safi);
6741 }
6742 }
6743
6744 bgp_dest_unlock_node(dest);
6745 }
6746
6747 /**
6748 * Check if the current path has different MED than other known paths.
6749 *
6750 * \returns `true` if the MED matched the others else `false`.
6751 */
6752 static bool bgp_aggregate_med_match(struct bgp_aggregate *aggregate,
6753 struct bgp *bgp, struct bgp_path_info *pi)
6754 {
6755 uint32_t cur_med = bgp_med_value(pi->attr, bgp);
6756
6757 /* This is the first route being analyzed. */
6758 if (!aggregate->med_initialized) {
6759 aggregate->med_initialized = true;
6760 aggregate->med_mismatched = false;
6761 aggregate->med_matched_value = cur_med;
6762 } else {
6763 /* Check if routes with different MED showed up. */
6764 if (cur_med != aggregate->med_matched_value)
6765 aggregate->med_mismatched = true;
6766 }
6767
6768 return !aggregate->med_mismatched;
6769 }
6770
6771 /**
6772 * Initializes and tests all routes in the aggregate address path for MED
6773 * values.
6774 *
6775 * \returns `true` if all MEDs are the same otherwise `false`.
6776 */
6777 static bool bgp_aggregate_test_all_med(struct bgp_aggregate *aggregate,
6778 struct bgp *bgp, const struct prefix *p,
6779 afi_t afi, safi_t safi)
6780 {
6781 struct bgp_table *table = bgp->rib[afi][safi];
6782 const struct prefix *dest_p;
6783 struct bgp_dest *dest, *top;
6784 struct bgp_path_info *pi;
6785 bool med_matched = true;
6786
6787 aggregate->med_initialized = false;
6788
6789 top = bgp_node_get(table, p);
6790 for (dest = bgp_node_get(table, p); dest;
6791 dest = bgp_route_next_until(dest, top)) {
6792 dest_p = bgp_dest_get_prefix(dest);
6793 if (dest_p->prefixlen <= p->prefixlen)
6794 continue;
6795
6796 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
6797 if (BGP_PATH_HOLDDOWN(pi))
6798 continue;
6799 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
6800 continue;
6801 if (!bgp_aggregate_med_match(aggregate, bgp, pi)) {
6802 med_matched = false;
6803 break;
6804 }
6805 }
6806 if (!med_matched)
6807 break;
6808 }
6809 bgp_dest_unlock_node(top);
6810
6811 return med_matched;
6812 }
6813
6814 /**
6815 * Toggles the route suppression status for this aggregate address
6816 * configuration.
6817 */
6818 void bgp_aggregate_toggle_suppressed(struct bgp_aggregate *aggregate,
6819 struct bgp *bgp, const struct prefix *p,
6820 afi_t afi, safi_t safi, bool suppress)
6821 {
6822 struct bgp_table *table = bgp->rib[afi][safi];
6823 const struct prefix *dest_p;
6824 struct bgp_dest *dest, *top;
6825 struct bgp_path_info *pi;
6826 bool toggle_suppression;
6827
6828 /* We've found a different MED we must revert any suppressed routes. */
6829 top = bgp_node_get(table, p);
6830 for (dest = bgp_node_get(table, p); dest;
6831 dest = bgp_route_next_until(dest, top)) {
6832 dest_p = bgp_dest_get_prefix(dest);
6833 if (dest_p->prefixlen <= p->prefixlen)
6834 continue;
6835
6836 toggle_suppression = false;
6837 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
6838 if (BGP_PATH_HOLDDOWN(pi))
6839 continue;
6840 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
6841 continue;
6842
6843 /* We are toggling suppression back. */
6844 if (suppress) {
6845 /* Suppress route if not suppressed already. */
6846 if (aggr_suppress_path(aggregate, pi))
6847 toggle_suppression = true;
6848 continue;
6849 }
6850
6851 /* Install route if there is no more suppression. */
6852 if (aggr_unsuppress_path(aggregate, pi))
6853 toggle_suppression = true;
6854 }
6855
6856 if (toggle_suppression)
6857 bgp_process(bgp, dest, afi, safi);
6858 }
6859 bgp_dest_unlock_node(top);
6860 }
6861
6862 /**
6863 * Aggregate address MED matching incremental test: this function is called
6864 * when the initial aggregation occurred and we are only testing a single
6865 * new path.
6866 *
6867 * In addition to testing and setting the MED validity it also installs back
6868 * suppressed routes (if summary is configured).
6869 *
6870 * Must not be called in `bgp_aggregate_route`.
6871 */
6872 static void bgp_aggregate_med_update(struct bgp_aggregate *aggregate,
6873 struct bgp *bgp, const struct prefix *p,
6874 afi_t afi, safi_t safi,
6875 struct bgp_path_info *pi, bool is_adding)
6876 {
6877 /* MED matching disabled. */
6878 if (!aggregate->match_med)
6879 return;
6880
6881 /* Aggregation with different MED, nothing to do. */
6882 if (aggregate->med_mismatched)
6883 return;
6884
6885 /*
6886 * Test the current entry:
6887 *
6888 * is_adding == true: if the new entry doesn't match then we must
6889 * install all suppressed routes.
6890 *
6891 * is_adding == false: if the entry being removed was the last
6892 * unmatching entry then we can suppress all routes.
6893 */
6894 if (!is_adding) {
6895 if (bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi)
6896 && aggregate->summary_only)
6897 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi,
6898 safi, true);
6899 } else
6900 bgp_aggregate_med_match(aggregate, bgp, pi);
6901
6902 /* No mismatches, just quit. */
6903 if (!aggregate->med_mismatched)
6904 return;
6905
6906 /* Route summarization is disabled. */
6907 if (!aggregate->summary_only)
6908 return;
6909
6910 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi, safi, false);
6911 }
6912
6913 /* Update an aggregate as routes are added/removed from the BGP table */
6914 void bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi,
6915 safi_t safi, struct bgp_aggregate *aggregate)
6916 {
6917 struct bgp_table *table;
6918 struct bgp_dest *top;
6919 struct bgp_dest *dest;
6920 uint8_t origin;
6921 struct aspath *aspath = NULL;
6922 struct community *community = NULL;
6923 struct ecommunity *ecommunity = NULL;
6924 struct lcommunity *lcommunity = NULL;
6925 struct bgp_path_info *pi;
6926 unsigned long match = 0;
6927 uint8_t atomic_aggregate = 0;
6928
6929 /* If the bgp instance is being deleted or self peer is deleted
6930 * then do not create aggregate route
6931 */
6932 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
6933 || (bgp->peer_self == NULL))
6934 return;
6935
6936 /* Initialize and test routes for MED difference. */
6937 if (aggregate->match_med)
6938 bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi);
6939
6940 /*
6941 * Reset aggregate count: we might've been called from route map
6942 * update so in that case we must retest all more specific routes.
6943 *
6944 * \see `bgp_route_map_process_update`.
6945 */
6946 aggregate->count = 0;
6947 aggregate->incomplete_origin_count = 0;
6948 aggregate->incomplete_origin_count = 0;
6949 aggregate->egp_origin_count = 0;
6950
6951 /* ORIGIN attribute: If at least one route among routes that are
6952 aggregated has ORIGIN with the value INCOMPLETE, then the
6953 aggregated route must have the ORIGIN attribute with the value
6954 INCOMPLETE. Otherwise, if at least one route among routes that
6955 are aggregated has ORIGIN with the value EGP, then the aggregated
6956 route must have the origin attribute with the value EGP. In all
6957 other case the value of the ORIGIN attribute of the aggregated
6958 route is INTERNAL. */
6959 origin = BGP_ORIGIN_IGP;
6960
6961 table = bgp->rib[afi][safi];
6962
6963 top = bgp_node_get(table, p);
6964 for (dest = bgp_node_get(table, p); dest;
6965 dest = bgp_route_next_until(dest, top)) {
6966 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
6967
6968 if (dest_p->prefixlen <= p->prefixlen)
6969 continue;
6970
6971 /* If suppress fib is enabled and route not installed
6972 * in FIB, skip the route
6973 */
6974 if (!bgp_check_advertise(bgp, dest))
6975 continue;
6976
6977 match = 0;
6978
6979 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
6980 if (BGP_PATH_HOLDDOWN(pi))
6981 continue;
6982
6983 if (pi->attr->flag
6984 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
6985 atomic_aggregate = 1;
6986
6987 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
6988 continue;
6989
6990 /*
6991 * summary-only aggregate route suppress
6992 * aggregated route announcements.
6993 *
6994 * MED matching:
6995 * Don't create summaries if MED didn't match
6996 * otherwise neither the specific routes and the
6997 * aggregation will be announced.
6998 */
6999 if (aggregate->summary_only
7000 && AGGREGATE_MED_VALID(aggregate)) {
7001 if (aggr_suppress_path(aggregate, pi))
7002 match++;
7003 }
7004
7005 /*
7006 * Suppress more specific routes that match the route
7007 * map results.
7008 *
7009 * MED matching:
7010 * Don't suppress routes if MED matching is enabled and
7011 * it mismatched otherwise we might end up with no
7012 * routes for this path.
7013 */
7014 if (aggregate->suppress_map_name
7015 && AGGREGATE_MED_VALID(aggregate)
7016 && aggr_suppress_map_test(bgp, aggregate, pi)) {
7017 if (aggr_suppress_path(aggregate, pi))
7018 match++;
7019 }
7020
7021 aggregate->count++;
7022
7023 /*
7024 * If at least one route among routes that are
7025 * aggregated has ORIGIN with the value INCOMPLETE,
7026 * then the aggregated route MUST have the ORIGIN
7027 * attribute with the value INCOMPLETE. Otherwise, if
7028 * at least one route among routes that are aggregated
7029 * has ORIGIN with the value EGP, then the aggregated
7030 * route MUST have the ORIGIN attribute with the value
7031 * EGP.
7032 */
7033 switch (pi->attr->origin) {
7034 case BGP_ORIGIN_INCOMPLETE:
7035 aggregate->incomplete_origin_count++;
7036 break;
7037 case BGP_ORIGIN_EGP:
7038 aggregate->egp_origin_count++;
7039 break;
7040 default:
7041 /*Do nothing.
7042 */
7043 break;
7044 }
7045
7046 if (!aggregate->as_set)
7047 continue;
7048
7049 /*
7050 * as-set aggregate route generate origin, as path,
7051 * and community aggregation.
7052 */
7053 /* Compute aggregate route's as-path.
7054 */
7055 bgp_compute_aggregate_aspath_hash(aggregate,
7056 pi->attr->aspath);
7057
7058 /* Compute aggregate route's community.
7059 */
7060 if (pi->attr->community)
7061 bgp_compute_aggregate_community_hash(
7062 aggregate,
7063 pi->attr->community);
7064
7065 /* Compute aggregate route's extended community.
7066 */
7067 if (pi->attr->ecommunity)
7068 bgp_compute_aggregate_ecommunity_hash(
7069 aggregate,
7070 pi->attr->ecommunity);
7071
7072 /* Compute aggregate route's large community.
7073 */
7074 if (pi->attr->lcommunity)
7075 bgp_compute_aggregate_lcommunity_hash(
7076 aggregate,
7077 pi->attr->lcommunity);
7078 }
7079 if (match)
7080 bgp_process(bgp, dest, afi, safi);
7081 }
7082 if (aggregate->as_set) {
7083 bgp_compute_aggregate_aspath_val(aggregate);
7084 bgp_compute_aggregate_community_val(aggregate);
7085 bgp_compute_aggregate_ecommunity_val(aggregate);
7086 bgp_compute_aggregate_lcommunity_val(aggregate);
7087 }
7088
7089
7090 bgp_dest_unlock_node(top);
7091
7092
7093 if (aggregate->incomplete_origin_count > 0)
7094 origin = BGP_ORIGIN_INCOMPLETE;
7095 else if (aggregate->egp_origin_count > 0)
7096 origin = BGP_ORIGIN_EGP;
7097
7098 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7099 origin = aggregate->origin;
7100
7101 if (aggregate->as_set) {
7102 if (aggregate->aspath)
7103 /* Retrieve aggregate route's as-path.
7104 */
7105 aspath = aspath_dup(aggregate->aspath);
7106
7107 if (aggregate->community)
7108 /* Retrieve aggregate route's community.
7109 */
7110 community = community_dup(aggregate->community);
7111
7112 if (aggregate->ecommunity)
7113 /* Retrieve aggregate route's ecommunity.
7114 */
7115 ecommunity = ecommunity_dup(aggregate->ecommunity);
7116
7117 if (aggregate->lcommunity)
7118 /* Retrieve aggregate route's lcommunity.
7119 */
7120 lcommunity = lcommunity_dup(aggregate->lcommunity);
7121 }
7122
7123 bgp_aggregate_install(bgp, afi, safi, p, origin, aspath, community,
7124 ecommunity, lcommunity, atomic_aggregate,
7125 aggregate);
7126 }
7127
7128 void bgp_aggregate_delete(struct bgp *bgp, const struct prefix *p, afi_t afi,
7129 safi_t safi, struct bgp_aggregate *aggregate)
7130 {
7131 struct bgp_table *table;
7132 struct bgp_dest *top;
7133 struct bgp_dest *dest;
7134 struct bgp_path_info *pi;
7135 unsigned long match;
7136
7137 table = bgp->rib[afi][safi];
7138
7139 /* If routes exists below this node, generate aggregate routes. */
7140 top = bgp_node_get(table, p);
7141 for (dest = bgp_node_get(table, p); dest;
7142 dest = bgp_route_next_until(dest, top)) {
7143 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
7144
7145 if (dest_p->prefixlen <= p->prefixlen)
7146 continue;
7147 match = 0;
7148
7149 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
7150 if (BGP_PATH_HOLDDOWN(pi))
7151 continue;
7152
7153 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7154 continue;
7155
7156 if (aggregate->summary_only && pi->extra
7157 && AGGREGATE_MED_VALID(aggregate)) {
7158 if (aggr_unsuppress_path(aggregate, pi))
7159 match++;
7160 }
7161
7162 if (aggregate->suppress_map_name
7163 && AGGREGATE_MED_VALID(aggregate)
7164 && aggr_suppress_map_test(bgp, aggregate, pi)) {
7165 if (aggr_unsuppress_path(aggregate, pi))
7166 match++;
7167 }
7168
7169 aggregate->count--;
7170
7171 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
7172 aggregate->incomplete_origin_count--;
7173 else if (pi->attr->origin == BGP_ORIGIN_EGP)
7174 aggregate->egp_origin_count--;
7175
7176 if (aggregate->as_set) {
7177 /* Remove as-path from aggregate.
7178 */
7179 bgp_remove_aspath_from_aggregate_hash(
7180 aggregate,
7181 pi->attr->aspath);
7182
7183 if (pi->attr->community)
7184 /* Remove community from aggregate.
7185 */
7186 bgp_remove_comm_from_aggregate_hash(
7187 aggregate,
7188 pi->attr->community);
7189
7190 if (pi->attr->ecommunity)
7191 /* Remove ecommunity from aggregate.
7192 */
7193 bgp_remove_ecomm_from_aggregate_hash(
7194 aggregate,
7195 pi->attr->ecommunity);
7196
7197 if (pi->attr->lcommunity)
7198 /* Remove lcommunity from aggregate.
7199 */
7200 bgp_remove_lcomm_from_aggregate_hash(
7201 aggregate,
7202 pi->attr->lcommunity);
7203 }
7204 }
7205
7206 /* If this node was suppressed, process the change. */
7207 if (match)
7208 bgp_process(bgp, dest, afi, safi);
7209 }
7210 if (aggregate->as_set) {
7211 aspath_free(aggregate->aspath);
7212 aggregate->aspath = NULL;
7213 if (aggregate->community)
7214 community_free(&aggregate->community);
7215 if (aggregate->ecommunity)
7216 ecommunity_free(&aggregate->ecommunity);
7217 if (aggregate->lcommunity)
7218 lcommunity_free(&aggregate->lcommunity);
7219 }
7220
7221 bgp_dest_unlock_node(top);
7222 }
7223
7224 static void bgp_add_route_to_aggregate(struct bgp *bgp,
7225 const struct prefix *aggr_p,
7226 struct bgp_path_info *pinew, afi_t afi,
7227 safi_t safi,
7228 struct bgp_aggregate *aggregate)
7229 {
7230 uint8_t origin;
7231 struct aspath *aspath = NULL;
7232 uint8_t atomic_aggregate = 0;
7233 struct community *community = NULL;
7234 struct ecommunity *ecommunity = NULL;
7235 struct lcommunity *lcommunity = NULL;
7236
7237 /* If the bgp instance is being deleted or self peer is deleted
7238 * then do not create aggregate route
7239 */
7240 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7241 || (bgp->peer_self == NULL))
7242 return;
7243
7244 /* ORIGIN attribute: If at least one route among routes that are
7245 * aggregated has ORIGIN with the value INCOMPLETE, then the
7246 * aggregated route must have the ORIGIN attribute with the value
7247 * INCOMPLETE. Otherwise, if at least one route among routes that
7248 * are aggregated has ORIGIN with the value EGP, then the aggregated
7249 * route must have the origin attribute with the value EGP. In all
7250 * other case the value of the ORIGIN attribute of the aggregated
7251 * route is INTERNAL.
7252 */
7253 origin = BGP_ORIGIN_IGP;
7254
7255 aggregate->count++;
7256
7257 /*
7258 * This must be called before `summary` check to avoid
7259 * "suppressing" twice.
7260 */
7261 if (aggregate->match_med)
7262 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi,
7263 pinew, true);
7264
7265 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
7266 aggr_suppress_path(aggregate, pinew);
7267
7268 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
7269 && aggr_suppress_map_test(bgp, aggregate, pinew))
7270 aggr_suppress_path(aggregate, pinew);
7271
7272 switch (pinew->attr->origin) {
7273 case BGP_ORIGIN_INCOMPLETE:
7274 aggregate->incomplete_origin_count++;
7275 break;
7276 case BGP_ORIGIN_EGP:
7277 aggregate->egp_origin_count++;
7278 break;
7279 default:
7280 /* Do nothing.
7281 */
7282 break;
7283 }
7284
7285 if (aggregate->incomplete_origin_count > 0)
7286 origin = BGP_ORIGIN_INCOMPLETE;
7287 else if (aggregate->egp_origin_count > 0)
7288 origin = BGP_ORIGIN_EGP;
7289
7290 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7291 origin = aggregate->origin;
7292
7293 if (aggregate->as_set) {
7294 /* Compute aggregate route's as-path.
7295 */
7296 bgp_compute_aggregate_aspath(aggregate,
7297 pinew->attr->aspath);
7298
7299 /* Compute aggregate route's community.
7300 */
7301 if (pinew->attr->community)
7302 bgp_compute_aggregate_community(
7303 aggregate,
7304 pinew->attr->community);
7305
7306 /* Compute aggregate route's extended community.
7307 */
7308 if (pinew->attr->ecommunity)
7309 bgp_compute_aggregate_ecommunity(
7310 aggregate,
7311 pinew->attr->ecommunity);
7312
7313 /* Compute aggregate route's large community.
7314 */
7315 if (pinew->attr->lcommunity)
7316 bgp_compute_aggregate_lcommunity(
7317 aggregate,
7318 pinew->attr->lcommunity);
7319
7320 /* Retrieve aggregate route's as-path.
7321 */
7322 if (aggregate->aspath)
7323 aspath = aspath_dup(aggregate->aspath);
7324
7325 /* Retrieve aggregate route's community.
7326 */
7327 if (aggregate->community)
7328 community = community_dup(aggregate->community);
7329
7330 /* Retrieve aggregate route's ecommunity.
7331 */
7332 if (aggregate->ecommunity)
7333 ecommunity = ecommunity_dup(aggregate->ecommunity);
7334
7335 /* Retrieve aggregate route's lcommunity.
7336 */
7337 if (aggregate->lcommunity)
7338 lcommunity = lcommunity_dup(aggregate->lcommunity);
7339 }
7340
7341 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
7342 aspath, community, ecommunity,
7343 lcommunity, atomic_aggregate, aggregate);
7344 }
7345
7346 static void bgp_remove_route_from_aggregate(struct bgp *bgp, afi_t afi,
7347 safi_t safi,
7348 struct bgp_path_info *pi,
7349 struct bgp_aggregate *aggregate,
7350 const struct prefix *aggr_p)
7351 {
7352 uint8_t origin;
7353 struct aspath *aspath = NULL;
7354 uint8_t atomic_aggregate = 0;
7355 struct community *community = NULL;
7356 struct ecommunity *ecommunity = NULL;
7357 struct lcommunity *lcommunity = NULL;
7358 unsigned long match = 0;
7359
7360 /* If the bgp instance is being deleted or self peer is deleted
7361 * then do not create aggregate route
7362 */
7363 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7364 || (bgp->peer_self == NULL))
7365 return;
7366
7367 if (BGP_PATH_HOLDDOWN(pi))
7368 return;
7369
7370 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7371 return;
7372
7373 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
7374 if (aggr_unsuppress_path(aggregate, pi))
7375 match++;
7376
7377 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
7378 && aggr_suppress_map_test(bgp, aggregate, pi))
7379 if (aggr_unsuppress_path(aggregate, pi))
7380 match++;
7381
7382 /*
7383 * This must be called after `summary`, `suppress-map` check to avoid
7384 * "unsuppressing" twice.
7385 */
7386 if (aggregate->match_med)
7387 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi, pi,
7388 true);
7389
7390 if (aggregate->count > 0)
7391 aggregate->count--;
7392
7393 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
7394 aggregate->incomplete_origin_count--;
7395 else if (pi->attr->origin == BGP_ORIGIN_EGP)
7396 aggregate->egp_origin_count--;
7397
7398 if (aggregate->as_set) {
7399 /* Remove as-path from aggregate.
7400 */
7401 bgp_remove_aspath_from_aggregate(aggregate,
7402 pi->attr->aspath);
7403
7404 if (pi->attr->community)
7405 /* Remove community from aggregate.
7406 */
7407 bgp_remove_community_from_aggregate(
7408 aggregate,
7409 pi->attr->community);
7410
7411 if (pi->attr->ecommunity)
7412 /* Remove ecommunity from aggregate.
7413 */
7414 bgp_remove_ecommunity_from_aggregate(
7415 aggregate,
7416 pi->attr->ecommunity);
7417
7418 if (pi->attr->lcommunity)
7419 /* Remove lcommunity from aggregate.
7420 */
7421 bgp_remove_lcommunity_from_aggregate(
7422 aggregate,
7423 pi->attr->lcommunity);
7424 }
7425
7426 /* If this node was suppressed, process the change. */
7427 if (match)
7428 bgp_process(bgp, pi->net, afi, safi);
7429
7430 origin = BGP_ORIGIN_IGP;
7431 if (aggregate->incomplete_origin_count > 0)
7432 origin = BGP_ORIGIN_INCOMPLETE;
7433 else if (aggregate->egp_origin_count > 0)
7434 origin = BGP_ORIGIN_EGP;
7435
7436 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7437 origin = aggregate->origin;
7438
7439 if (aggregate->as_set) {
7440 /* Retrieve aggregate route's as-path.
7441 */
7442 if (aggregate->aspath)
7443 aspath = aspath_dup(aggregate->aspath);
7444
7445 /* Retrieve aggregate route's community.
7446 */
7447 if (aggregate->community)
7448 community = community_dup(aggregate->community);
7449
7450 /* Retrieve aggregate route's ecommunity.
7451 */
7452 if (aggregate->ecommunity)
7453 ecommunity = ecommunity_dup(aggregate->ecommunity);
7454
7455 /* Retrieve aggregate route's lcommunity.
7456 */
7457 if (aggregate->lcommunity)
7458 lcommunity = lcommunity_dup(aggregate->lcommunity);
7459 }
7460
7461 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
7462 aspath, community, ecommunity,
7463 lcommunity, atomic_aggregate, aggregate);
7464 }
7465
7466 void bgp_aggregate_increment(struct bgp *bgp, const struct prefix *p,
7467 struct bgp_path_info *pi, afi_t afi, safi_t safi)
7468 {
7469 struct bgp_dest *child;
7470 struct bgp_dest *dest;
7471 struct bgp_aggregate *aggregate;
7472 struct bgp_table *table;
7473
7474 table = bgp->aggregate[afi][safi];
7475
7476 /* No aggregates configured. */
7477 if (bgp_table_top_nolock(table) == NULL)
7478 return;
7479
7480 if (p->prefixlen == 0)
7481 return;
7482
7483 if (BGP_PATH_HOLDDOWN(pi))
7484 return;
7485
7486 /* If suppress fib is enabled and route not installed
7487 * in FIB, do not update the aggregate route
7488 */
7489 if (!bgp_check_advertise(bgp, pi->net))
7490 return;
7491
7492 child = bgp_node_get(table, p);
7493
7494 /* Aggregate address configuration check. */
7495 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
7496 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
7497
7498 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
7499 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
7500 bgp_add_route_to_aggregate(bgp, dest_p, pi, afi, safi,
7501 aggregate);
7502 }
7503 }
7504 bgp_dest_unlock_node(child);
7505 }
7506
7507 void bgp_aggregate_decrement(struct bgp *bgp, const struct prefix *p,
7508 struct bgp_path_info *del, afi_t afi, safi_t safi)
7509 {
7510 struct bgp_dest *child;
7511 struct bgp_dest *dest;
7512 struct bgp_aggregate *aggregate;
7513 struct bgp_table *table;
7514
7515 table = bgp->aggregate[afi][safi];
7516
7517 /* No aggregates configured. */
7518 if (bgp_table_top_nolock(table) == NULL)
7519 return;
7520
7521 if (p->prefixlen == 0)
7522 return;
7523
7524 child = bgp_node_get(table, p);
7525
7526 /* Aggregate address configuration check. */
7527 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
7528 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
7529
7530 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
7531 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
7532 bgp_remove_route_from_aggregate(bgp, afi, safi, del,
7533 aggregate, dest_p);
7534 }
7535 }
7536 bgp_dest_unlock_node(child);
7537 }
7538
7539 /* Aggregate route attribute. */
7540 #define AGGREGATE_SUMMARY_ONLY 1
7541 #define AGGREGATE_AS_SET 1
7542 #define AGGREGATE_AS_UNSET 0
7543
7544 static const char *bgp_origin2str(uint8_t origin)
7545 {
7546 switch (origin) {
7547 case BGP_ORIGIN_IGP:
7548 return "igp";
7549 case BGP_ORIGIN_EGP:
7550 return "egp";
7551 case BGP_ORIGIN_INCOMPLETE:
7552 return "incomplete";
7553 }
7554 return "n/a";
7555 }
7556
7557 int bgp_aggregate_unset(struct bgp *bgp, struct prefix *prefix, afi_t afi,
7558 safi_t safi, char *errmsg, size_t errmsg_len)
7559 {
7560 struct bgp_dest *dest;
7561 struct bgp_aggregate *aggregate;
7562
7563 /* If the bgp instance is being deleted or self peer is deleted
7564 * then do not create aggregate route
7565 */
7566 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7567 || (bgp->peer_self == NULL))
7568 return 0;
7569
7570 apply_mask(prefix);
7571 /* Old configuration check. */
7572 dest = bgp_node_lookup(bgp->aggregate[afi][safi], prefix);
7573 if (!dest) {
7574 snprintf(errmsg, errmsg_len,
7575 "There is no aggregate-address configuration.\n");
7576 return -1;
7577 }
7578
7579 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
7580 bgp_aggregate_delete(bgp, prefix, afi, safi, aggregate);
7581 bgp_aggregate_install(bgp, afi, safi, prefix, 0, NULL, NULL, NULL, NULL,
7582 0, aggregate);
7583
7584 /* Unlock aggregate address configuration. */
7585 bgp_dest_set_bgp_aggregate_info(dest, NULL);
7586
7587 if (aggregate->community)
7588 community_free(&aggregate->community);
7589
7590 if (aggregate->community_hash) {
7591 /* Delete all communities in the hash.
7592 */
7593 hash_clean(aggregate->community_hash,
7594 bgp_aggr_community_remove);
7595 /* Free up the community_hash.
7596 */
7597 hash_free(aggregate->community_hash);
7598 }
7599
7600 if (aggregate->ecommunity)
7601 ecommunity_free(&aggregate->ecommunity);
7602
7603 if (aggregate->ecommunity_hash) {
7604 /* Delete all ecommunities in the hash.
7605 */
7606 hash_clean(aggregate->ecommunity_hash,
7607 bgp_aggr_ecommunity_remove);
7608 /* Free up the ecommunity_hash.
7609 */
7610 hash_free(aggregate->ecommunity_hash);
7611 }
7612
7613 if (aggregate->lcommunity)
7614 lcommunity_free(&aggregate->lcommunity);
7615
7616 if (aggregate->lcommunity_hash) {
7617 /* Delete all lcommunities in the hash.
7618 */
7619 hash_clean(aggregate->lcommunity_hash,
7620 bgp_aggr_lcommunity_remove);
7621 /* Free up the lcommunity_hash.
7622 */
7623 hash_free(aggregate->lcommunity_hash);
7624 }
7625
7626 if (aggregate->aspath)
7627 aspath_free(aggregate->aspath);
7628
7629 if (aggregate->aspath_hash) {
7630 /* Delete all as-paths in the hash.
7631 */
7632 hash_clean(aggregate->aspath_hash,
7633 bgp_aggr_aspath_remove);
7634 /* Free up the aspath_hash.
7635 */
7636 hash_free(aggregate->aspath_hash);
7637 }
7638
7639 bgp_aggregate_free(aggregate);
7640 bgp_dest_unlock_node(dest);
7641 bgp_dest_unlock_node(dest);
7642
7643 return 0;
7644 }
7645
7646 int bgp_aggregate_set(struct bgp *bgp, struct prefix *prefix, afi_t afi,
7647 safi_t safi, const char *rmap, uint8_t summary_only,
7648 uint8_t as_set, uint8_t origin, bool match_med,
7649 const char *suppress_map,
7650 char *errmsg, size_t errmsg_len)
7651 {
7652 int ret;
7653 struct bgp_dest *dest;
7654 struct bgp_aggregate *aggregate;
7655 uint8_t as_set_new = as_set;
7656 char buf[PREFIX2STR_BUFFER];
7657
7658 if (suppress_map && summary_only) {
7659 snprintf(errmsg, errmsg_len,
7660 "'summary-only' and 'suppress-map' can't be used at the same time\n");
7661 return -1;
7662 }
7663
7664 apply_mask(prefix);
7665
7666 if ((afi == AFI_IP && prefix->prefixlen == IPV4_MAX_BITLEN)
7667 || (afi == AFI_IP6 && prefix->prefixlen == IPV6_MAX_BITLEN)) {
7668 snprintf(
7669 errmsg, errmsg_len,
7670 "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
7671 prefix2str(prefix, buf, PREFIX_STRLEN));
7672 return -1;
7673 }
7674
7675 /* Old configuration check. */
7676 dest = bgp_node_get(bgp->aggregate[afi][safi], prefix);
7677 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
7678
7679 if (aggregate) {
7680 snprintf(errmsg, errmsg_len,
7681 "There is already same aggregate network.\n");
7682 /* try to remove the old entry */
7683 ret = bgp_aggregate_unset(bgp, prefix, afi, safi, errmsg,
7684 errmsg_len);
7685 if (ret) {
7686 snprintf(errmsg, errmsg_len,
7687 "Error deleting aggregate.\n");
7688 bgp_dest_unlock_node(dest);
7689 return -1;
7690 }
7691 }
7692
7693 /* Make aggregate address structure. */
7694 aggregate = bgp_aggregate_new();
7695 aggregate->summary_only = summary_only;
7696 aggregate->match_med = match_med;
7697
7698 /* Network operators MUST NOT locally generate any new
7699 * announcements containing AS_SET or AS_CONFED_SET. If they have
7700 * announced routes with AS_SET or AS_CONFED_SET in them, then they
7701 * SHOULD withdraw those routes and re-announce routes for the
7702 * aggregate or component prefixes (i.e., the more-specific routes
7703 * subsumed by the previously aggregated route) without AS_SET
7704 * or AS_CONFED_SET in the updates.
7705 */
7706 if (bgp->reject_as_sets) {
7707 if (as_set == AGGREGATE_AS_SET) {
7708 as_set_new = AGGREGATE_AS_UNSET;
7709 zlog_warn(
7710 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
7711 __func__);
7712 snprintf(
7713 errmsg, errmsg_len,
7714 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
7715 }
7716 }
7717
7718 aggregate->as_set = as_set_new;
7719 aggregate->safi = safi;
7720 /* Override ORIGIN attribute if defined.
7721 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
7722 * to IGP which is not what rfc4271 says.
7723 * This enables the same behavior, optionally.
7724 */
7725 aggregate->origin = origin;
7726
7727 if (rmap) {
7728 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
7729 route_map_counter_decrement(aggregate->rmap.map);
7730 aggregate->rmap.name =
7731 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
7732 aggregate->rmap.map = route_map_lookup_by_name(rmap);
7733 route_map_counter_increment(aggregate->rmap.map);
7734 }
7735
7736 if (suppress_map) {
7737 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
7738 route_map_counter_decrement(aggregate->suppress_map);
7739
7740 aggregate->suppress_map_name =
7741 XSTRDUP(MTYPE_ROUTE_MAP_NAME, suppress_map);
7742 aggregate->suppress_map =
7743 route_map_lookup_by_name(aggregate->suppress_map_name);
7744 route_map_counter_increment(aggregate->suppress_map);
7745 }
7746
7747 bgp_dest_set_bgp_aggregate_info(dest, aggregate);
7748
7749 /* Aggregate address insert into BGP routing table. */
7750 bgp_aggregate_route(bgp, prefix, afi, safi, aggregate);
7751
7752 return 0;
7753 }
7754
7755 DEFPY_YANG(
7756 aggregate_addressv4, aggregate_addressv4_cmd,
7757 "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> {"
7758 "as-set$as_set_s"
7759 "|summary-only$summary_only"
7760 "|route-map WORD$rmap_name"
7761 "|origin <egp|igp|incomplete>$origin_s"
7762 "|matching-MED-only$match_med"
7763 "|suppress-map WORD$suppress_map"
7764 "}",
7765 NO_STR
7766 "Configure BGP aggregate entries\n"
7767 "Aggregate prefix\n"
7768 "Aggregate address\n"
7769 "Aggregate mask\n"
7770 "Generate AS set path information\n"
7771 "Filter more specific routes from updates\n"
7772 "Apply route map to aggregate network\n"
7773 "Route map name\n"
7774 "BGP origin code\n"
7775 "Remote EGP\n"
7776 "Local IGP\n"
7777 "Unknown heritage\n"
7778 "Only aggregate routes with matching MED\n"
7779 "Suppress the selected more specific routes\n"
7780 "Route map with the route selectors\n")
7781 {
7782 char base_xpath[XPATH_MAXLEN];
7783 safi_t safi = bgp_node_safi(vty);
7784 char prefix_buf[PREFIX2STR_BUFFER];
7785
7786 if (addr_str) {
7787 if (netmask_str2prefix_str(addr_str, mask_str, prefix_buf,
7788 sizeof(prefix_buf))
7789 == 0) {
7790 vty_out(vty, "%% Inconsistent address and mask\n");
7791 return CMD_WARNING_CONFIG_FAILED;
7792 }
7793 } else {
7794 strlcpy(prefix_buf, prefix_str, sizeof(prefix_buf));
7795 }
7796
7797 if (!no && origin_s)
7798 nb_cli_enqueue_change(vty, "./origin", NB_OP_MODIFY, origin_s);
7799
7800 if (!no && as_set_s)
7801 nb_cli_enqueue_change(vty, "./as-set", NB_OP_MODIFY, "true");
7802 else
7803 nb_cli_enqueue_change(vty, "./as-set", NB_OP_MODIFY, "false");
7804
7805 if (!no && summary_only)
7806 nb_cli_enqueue_change(vty, "./summary-only", NB_OP_MODIFY,
7807 "true");
7808 else
7809 nb_cli_enqueue_change(vty, "./summary-only", NB_OP_MODIFY,
7810 "false");
7811
7812 if (!no && match_med)
7813 nb_cli_enqueue_change(vty, "./match-med", NB_OP_MODIFY, "true");
7814 else
7815 nb_cli_enqueue_change(vty, "./match-med", NB_OP_MODIFY,
7816 "false");
7817
7818 if (rmap_name)
7819 nb_cli_enqueue_change(vty, "./rmap-policy-export", NB_OP_MODIFY,
7820 rmap_name);
7821 else
7822 nb_cli_enqueue_change(vty, "./rmap-policy-export",
7823 NB_OP_DESTROY, NULL);
7824
7825 if (suppress_map)
7826 nb_cli_enqueue_change(vty, "./suppress-map", NB_OP_MODIFY,
7827 suppress_map);
7828 else
7829 nb_cli_enqueue_change(vty, "./suppress-map", NB_OP_DESTROY,
7830 NULL);
7831
7832 snprintf(
7833 base_xpath, sizeof(base_xpath),
7834 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/aggregate-route[prefix='%s']",
7835 yang_afi_safi_value2identity(AFI_IP, safi),
7836 bgp_afi_safi_get_container_str(AFI_IP, safi), prefix_buf);
7837
7838 if (no)
7839 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
7840 else
7841 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
7842
7843 return nb_cli_apply_changes(vty, base_xpath);
7844 }
7845
7846 DEFPY_YANG(aggregate_addressv6, aggregate_addressv6_cmd,
7847 "[no] aggregate-address X:X::X:X/M$prefix {"
7848 "as-set$as_set_s"
7849 "|summary-only$summary_only"
7850 "|route-map WORD$rmap_name"
7851 "|origin <egp|igp|incomplete>$origin_s"
7852 "|matching-MED-only$match_med"
7853 "|suppress-map WORD$suppress_map"
7854 "}",
7855 NO_STR
7856 "Configure BGP aggregate entries\n"
7857 "Aggregate prefix\n"
7858 "Generate AS set path information\n"
7859 "Filter more specific routes from updates\n"
7860 "Apply route map to aggregate network\n"
7861 "Route map name\n"
7862 "BGP origin code\n"
7863 "Remote EGP\n"
7864 "Local IGP\n"
7865 "Unknown heritage\n"
7866 "Only aggregate routes with matching MED\n"
7867 "Suppress the selected more specific routes\n"
7868 "Route map with the route selectors\n")
7869 {
7870 char base_xpath[XPATH_MAXLEN];
7871 safi_t safi = bgp_node_safi(vty);
7872
7873 if (!no && origin_s)
7874 nb_cli_enqueue_change(vty, "./origin", NB_OP_MODIFY, origin_s);
7875
7876 if (!no && as_set_s)
7877 nb_cli_enqueue_change(vty, "./as-set", NB_OP_MODIFY, "true");
7878 else
7879 nb_cli_enqueue_change(vty, "./as-set", NB_OP_MODIFY, "false");
7880
7881 if (!no && summary_only)
7882 nb_cli_enqueue_change(vty, "./summary-only", NB_OP_MODIFY,
7883 "true");
7884 else
7885 nb_cli_enqueue_change(vty, "./summary-only", NB_OP_MODIFY,
7886 "false");
7887
7888 if (!no && match_med)
7889 nb_cli_enqueue_change(vty, "./match-med", NB_OP_MODIFY, "true");
7890 else
7891 nb_cli_enqueue_change(vty, "./match-med", NB_OP_MODIFY,
7892 "false");
7893
7894 if (rmap_name)
7895 nb_cli_enqueue_change(vty, "./rmap-policy-export", NB_OP_MODIFY,
7896 rmap_name);
7897
7898 if (suppress_map)
7899 nb_cli_enqueue_change(vty, "./suppress-map", NB_OP_MODIFY,
7900 suppress_map);
7901 else
7902 nb_cli_enqueue_change(vty, "./suppress-map", NB_OP_DESTROY,
7903 NULL);
7904
7905 snprintf(
7906 base_xpath, sizeof(base_xpath),
7907 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/aggregate-route[prefix='%s']",
7908 yang_afi_safi_value2identity(AFI_IP6, safi),
7909 bgp_afi_safi_get_container_str(AFI_IP6, safi), prefix_str);
7910
7911 if (no)
7912 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
7913 else
7914 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
7915
7916 return nb_cli_apply_changes(vty, base_xpath);
7917 }
7918
7919 void cli_show_bgp_global_afi_safi_unicast_aggregate_route(
7920 struct vty *vty, struct lyd_node *dnode, bool show_defaults)
7921 {
7922 uint8_t origin;
7923
7924 vty_out(vty, " aggregate-address %s",
7925 yang_dnode_get_string(dnode, "./prefix"));
7926
7927 if (yang_dnode_get_bool(dnode, "./as-set"))
7928 vty_out(vty, " as-set");
7929
7930 if (yang_dnode_get_bool(dnode, "./summary-only"))
7931 vty_out(vty, " summary-only");
7932
7933 if (yang_dnode_exists(dnode, "./rmap-policy-export"))
7934 vty_out(vty, " route-map %s",
7935 yang_dnode_get_string(dnode, "./rmap-policy-export"));
7936
7937 origin = yang_dnode_get_enum(dnode, "./origin");
7938 if (origin != BGP_ORIGIN_UNSPECIFIED)
7939 vty_out(vty, " origin %s", bgp_origin2str(origin));
7940
7941 if (yang_dnode_get_bool(dnode, "./match-med"))
7942 vty_out(vty, " matching-MED-only");
7943
7944 vty_out(vty, "\n");
7945 }
7946
7947 /* Redistribute route treatment. */
7948 void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
7949 const union g_addr *nexthop, ifindex_t ifindex,
7950 enum nexthop_types_t nhtype, uint32_t metric,
7951 uint8_t type, unsigned short instance,
7952 route_tag_t tag)
7953 {
7954 struct bgp_path_info *new;
7955 struct bgp_path_info *bpi;
7956 struct bgp_path_info rmap_path;
7957 struct bgp_dest *bn;
7958 struct attr attr;
7959 struct attr *new_attr;
7960 afi_t afi;
7961 route_map_result_t ret;
7962 struct bgp_redist *red;
7963
7964 /* Make default attribute. */
7965 bgp_attr_default_set(&attr, BGP_ORIGIN_INCOMPLETE);
7966 /*
7967 * This must not be NULL to satisfy Coverity SA
7968 */
7969 assert(attr.aspath);
7970
7971 switch (nhtype) {
7972 case NEXTHOP_TYPE_IFINDEX:
7973 break;
7974 case NEXTHOP_TYPE_IPV4:
7975 case NEXTHOP_TYPE_IPV4_IFINDEX:
7976 attr.nexthop = nexthop->ipv4;
7977 break;
7978 case NEXTHOP_TYPE_IPV6:
7979 case NEXTHOP_TYPE_IPV6_IFINDEX:
7980 attr.mp_nexthop_global = nexthop->ipv6;
7981 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
7982 break;
7983 case NEXTHOP_TYPE_BLACKHOLE:
7984 switch (p->family) {
7985 case AF_INET:
7986 attr.nexthop.s_addr = INADDR_ANY;
7987 break;
7988 case AF_INET6:
7989 memset(&attr.mp_nexthop_global, 0,
7990 sizeof(attr.mp_nexthop_global));
7991 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
7992 break;
7993 }
7994 break;
7995 }
7996 attr.nh_ifindex = ifindex;
7997
7998 attr.med = metric;
7999 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
8000 attr.tag = tag;
8001
8002 afi = family2afi(p->family);
8003
8004 red = bgp_redist_lookup(bgp, afi, type, instance);
8005 if (red) {
8006 struct attr attr_new;
8007
8008 /* Copy attribute for modification. */
8009 attr_new = attr;
8010
8011 if (red->redist_metric_flag)
8012 attr_new.med = red->redist_metric;
8013
8014 /* Apply route-map. */
8015 if (red->rmap.name) {
8016 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
8017 rmap_path.peer = bgp->peer_self;
8018 rmap_path.attr = &attr_new;
8019
8020 SET_FLAG(bgp->peer_self->rmap_type,
8021 PEER_RMAP_TYPE_REDISTRIBUTE);
8022
8023 ret = route_map_apply(red->rmap.map, p, &rmap_path);
8024
8025 bgp->peer_self->rmap_type = 0;
8026
8027 if (ret == RMAP_DENYMATCH) {
8028 /* Free uninterned attribute. */
8029 bgp_attr_flush(&attr_new);
8030
8031 /* Unintern original. */
8032 aspath_unintern(&attr.aspath);
8033 bgp_redistribute_delete(bgp, p, type, instance);
8034 return;
8035 }
8036 }
8037
8038 if (bgp_in_graceful_shutdown(bgp))
8039 bgp_attr_add_gshut_community(&attr_new);
8040
8041 bn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8042 SAFI_UNICAST, p, NULL);
8043
8044 new_attr = bgp_attr_intern(&attr_new);
8045
8046 for (bpi = bgp_dest_get_bgp_path_info(bn); bpi; bpi = bpi->next)
8047 if (bpi->peer == bgp->peer_self
8048 && bpi->sub_type == BGP_ROUTE_REDISTRIBUTE)
8049 break;
8050
8051 if (bpi) {
8052 /* Ensure the (source route) type is updated. */
8053 bpi->type = type;
8054 if (attrhash_cmp(bpi->attr, new_attr)
8055 && !CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
8056 bgp_attr_unintern(&new_attr);
8057 aspath_unintern(&attr.aspath);
8058 bgp_dest_unlock_node(bn);
8059 return;
8060 } else {
8061 /* The attribute is changed. */
8062 bgp_path_info_set_flag(bn, bpi,
8063 BGP_PATH_ATTR_CHANGED);
8064
8065 /* Rewrite BGP route information. */
8066 if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
8067 bgp_path_info_restore(bn, bpi);
8068 else
8069 bgp_aggregate_decrement(
8070 bgp, p, bpi, afi, SAFI_UNICAST);
8071 bgp_attr_unintern(&bpi->attr);
8072 bpi->attr = new_attr;
8073 bpi->uptime = bgp_clock();
8074
8075 /* Process change. */
8076 bgp_aggregate_increment(bgp, p, bpi, afi,
8077 SAFI_UNICAST);
8078 bgp_process(bgp, bn, afi, SAFI_UNICAST);
8079 bgp_dest_unlock_node(bn);
8080 aspath_unintern(&attr.aspath);
8081
8082 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8083 || (bgp->inst_type
8084 == BGP_INSTANCE_TYPE_DEFAULT)) {
8085
8086 vpn_leak_from_vrf_update(
8087 bgp_get_default(), bgp, bpi);
8088 }
8089 return;
8090 }
8091 }
8092
8093 new = info_make(type, BGP_ROUTE_REDISTRIBUTE, instance,
8094 bgp->peer_self, new_attr, bn);
8095 SET_FLAG(new->flags, BGP_PATH_VALID);
8096
8097 bgp_aggregate_increment(bgp, p, new, afi, SAFI_UNICAST);
8098 bgp_path_info_add(bn, new);
8099 bgp_dest_unlock_node(bn);
8100 bgp_process(bgp, bn, afi, SAFI_UNICAST);
8101
8102 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8103 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8104
8105 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
8106 }
8107 }
8108
8109 /* Unintern original. */
8110 aspath_unintern(&attr.aspath);
8111 }
8112
8113 void bgp_redistribute_delete(struct bgp *bgp, struct prefix *p, uint8_t type,
8114 unsigned short instance)
8115 {
8116 afi_t afi;
8117 struct bgp_dest *dest;
8118 struct bgp_path_info *pi;
8119 struct bgp_redist *red;
8120
8121 afi = family2afi(p->family);
8122
8123 red = bgp_redist_lookup(bgp, afi, type, instance);
8124 if (red) {
8125 dest = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8126 SAFI_UNICAST, p, NULL);
8127
8128 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
8129 if (pi->peer == bgp->peer_self && pi->type == type)
8130 break;
8131
8132 if (pi) {
8133 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8134 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8135
8136 vpn_leak_from_vrf_withdraw(bgp_get_default(),
8137 bgp, pi);
8138 }
8139 bgp_aggregate_decrement(bgp, p, pi, afi, SAFI_UNICAST);
8140 bgp_path_info_delete(dest, pi);
8141 bgp_process(bgp, dest, afi, SAFI_UNICAST);
8142 }
8143 bgp_dest_unlock_node(dest);
8144 }
8145 }
8146
8147 /* Withdraw specified route type's route. */
8148 void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type,
8149 unsigned short instance)
8150 {
8151 struct bgp_dest *dest;
8152 struct bgp_path_info *pi;
8153 struct bgp_table *table;
8154
8155 table = bgp->rib[afi][SAFI_UNICAST];
8156
8157 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
8158 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
8159 if (pi->peer == bgp->peer_self && pi->type == type
8160 && pi->instance == instance)
8161 break;
8162
8163 if (pi) {
8164 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8165 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8166
8167 vpn_leak_from_vrf_withdraw(bgp_get_default(),
8168 bgp, pi);
8169 }
8170 bgp_aggregate_decrement(bgp, bgp_dest_get_prefix(dest),
8171 pi, afi, SAFI_UNICAST);
8172 bgp_path_info_delete(dest, pi);
8173 bgp_process(bgp, dest, afi, SAFI_UNICAST);
8174 }
8175 }
8176 }
8177
8178 /* Static function to display route. */
8179 static void route_vty_out_route(const struct prefix *p, struct vty *vty,
8180 json_object *json, bool wide)
8181 {
8182 int len = 0;
8183 char buf[BUFSIZ];
8184 char buf2[BUFSIZ];
8185
8186 if (p->family == AF_INET) {
8187 if (!json) {
8188 len = vty_out(vty, "%pFX", p);
8189 } else {
8190 json_object_string_add(json, "prefix",
8191 inet_ntop(p->family,
8192 &p->u.prefix, buf,
8193 BUFSIZ));
8194 json_object_int_add(json, "prefixLen", p->prefixlen);
8195 prefix2str(p, buf2, PREFIX_STRLEN);
8196 json_object_string_add(json, "network", buf2);
8197 }
8198 } else if (p->family == AF_ETHERNET) {
8199 len = vty_out(vty, "%pFX", p);
8200 } else if (p->family == AF_EVPN) {
8201 if (!json)
8202 len = vty_out(vty, "%pFX", (struct prefix_evpn *)p);
8203 else
8204 bgp_evpn_route2json((struct prefix_evpn *)p, json);
8205 } else if (p->family == AF_FLOWSPEC) {
8206 route_vty_out_flowspec(vty, p, NULL,
8207 json ?
8208 NLRI_STRING_FORMAT_JSON_SIMPLE :
8209 NLRI_STRING_FORMAT_MIN, json);
8210 } else {
8211 if (!json)
8212 len = vty_out(vty, "%pFX", p);
8213 else {
8214 json_object_string_add(json, "prefix",
8215 inet_ntop(p->family,
8216 &p->u.prefix, buf,
8217 BUFSIZ));
8218 json_object_int_add(json, "prefixLen", p->prefixlen);
8219 prefix2str(p, buf2, PREFIX_STRLEN);
8220 json_object_string_add(json, "network", buf2);
8221 }
8222 }
8223
8224 if (!json) {
8225 len = wide ? (45 - len) : (17 - len);
8226 if (len < 1)
8227 vty_out(vty, "\n%*s", 20, " ");
8228 else
8229 vty_out(vty, "%*s", len, " ");
8230 }
8231 }
8232
8233 enum bgp_display_type {
8234 normal_list,
8235 };
8236
8237 static const char *
8238 bgp_path_selection_reason2str(enum bgp_path_selection_reason reason)
8239 {
8240 switch (reason) {
8241 case bgp_path_selection_none:
8242 return "Nothing to Select";
8243 case bgp_path_selection_first:
8244 return "First path received";
8245 case bgp_path_selection_evpn_sticky_mac:
8246 return "EVPN Sticky Mac";
8247 case bgp_path_selection_evpn_seq:
8248 return "EVPN sequence number";
8249 case bgp_path_selection_evpn_lower_ip:
8250 return "EVPN lower IP";
8251 case bgp_path_selection_evpn_local_path:
8252 return "EVPN local ES path";
8253 case bgp_path_selection_evpn_non_proxy:
8254 return "EVPN non proxy";
8255 case bgp_path_selection_weight:
8256 return "Weight";
8257 case bgp_path_selection_local_pref:
8258 return "Local Pref";
8259 case bgp_path_selection_local_route:
8260 return "Local Route";
8261 case bgp_path_selection_confed_as_path:
8262 return "Confederation based AS Path";
8263 case bgp_path_selection_as_path:
8264 return "AS Path";
8265 case bgp_path_selection_origin:
8266 return "Origin";
8267 case bgp_path_selection_med:
8268 return "MED";
8269 case bgp_path_selection_peer:
8270 return "Peer Type";
8271 case bgp_path_selection_confed:
8272 return "Confed Peer Type";
8273 case bgp_path_selection_igp_metric:
8274 return "IGP Metric";
8275 case bgp_path_selection_older:
8276 return "Older Path";
8277 case bgp_path_selection_router_id:
8278 return "Router ID";
8279 case bgp_path_selection_cluster_length:
8280 return "Cluster length";
8281 case bgp_path_selection_stale:
8282 return "Path Staleness";
8283 case bgp_path_selection_local_configured:
8284 return "Locally configured route";
8285 case bgp_path_selection_neighbor_ip:
8286 return "Neighbor IP";
8287 case bgp_path_selection_default:
8288 return "Nothing left to compare";
8289 }
8290 return "Invalid (internal error)";
8291 }
8292
8293 /* Print the short form route status for a bgp_path_info */
8294 static void route_vty_short_status_out(struct vty *vty,
8295 struct bgp_path_info *path,
8296 json_object *json_path)
8297 {
8298 if (json_path) {
8299
8300 /* Route status display. */
8301 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
8302 json_object_boolean_true_add(json_path, "removed");
8303
8304 if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
8305 json_object_boolean_true_add(json_path, "stale");
8306
8307 if (path->extra && bgp_path_suppressed(path))
8308 json_object_boolean_true_add(json_path, "suppressed");
8309
8310 if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
8311 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
8312 json_object_boolean_true_add(json_path, "valid");
8313
8314 /* Selected */
8315 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
8316 json_object_boolean_true_add(json_path, "history");
8317
8318 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
8319 json_object_boolean_true_add(json_path, "damped");
8320
8321 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
8322 json_object_boolean_true_add(json_path, "bestpath");
8323 json_object_string_add(json_path, "selectionReason",
8324 bgp_path_selection_reason2str(
8325 path->net->reason));
8326 }
8327
8328 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
8329 json_object_boolean_true_add(json_path, "multipath");
8330
8331 /* Internal route. */
8332 if ((path->peer->as)
8333 && (path->peer->as == path->peer->local_as))
8334 json_object_string_add(json_path, "pathFrom",
8335 "internal");
8336 else
8337 json_object_string_add(json_path, "pathFrom",
8338 "external");
8339
8340 return;
8341 }
8342
8343 /* Route status display. */
8344 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
8345 vty_out(vty, "R");
8346 else if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
8347 vty_out(vty, "S");
8348 else if (bgp_path_suppressed(path))
8349 vty_out(vty, "s");
8350 else if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
8351 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
8352 vty_out(vty, "*");
8353 else
8354 vty_out(vty, " ");
8355
8356 /* Selected */
8357 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
8358 vty_out(vty, "h");
8359 else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
8360 vty_out(vty, "d");
8361 else if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
8362 vty_out(vty, ">");
8363 else if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
8364 vty_out(vty, "=");
8365 else
8366 vty_out(vty, " ");
8367
8368 /* Internal route. */
8369 if (path->peer && (path->peer->as)
8370 && (path->peer->as == path->peer->local_as))
8371 vty_out(vty, "i");
8372 else
8373 vty_out(vty, " ");
8374 }
8375
8376 static char *bgp_nexthop_hostname(struct peer *peer,
8377 struct bgp_nexthop_cache *bnc)
8378 {
8379 if (peer->hostname
8380 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME))
8381 return peer->hostname;
8382 return NULL;
8383 }
8384
8385 /* called from terminal list command */
8386 void route_vty_out(struct vty *vty, const struct prefix *p,
8387 struct bgp_path_info *path, int display, safi_t safi,
8388 json_object *json_paths, bool wide)
8389 {
8390 int len;
8391 struct attr *attr = path->attr;
8392 json_object *json_path = NULL;
8393 json_object *json_nexthops = NULL;
8394 json_object *json_nexthop_global = NULL;
8395 json_object *json_nexthop_ll = NULL;
8396 json_object *json_ext_community = NULL;
8397 char vrf_id_str[VRF_NAMSIZ] = {0};
8398 bool nexthop_self =
8399 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
8400 bool nexthop_othervrf = false;
8401 vrf_id_t nexthop_vrfid = VRF_DEFAULT;
8402 const char *nexthop_vrfname = VRF_DEFAULT_NAME;
8403 char *nexthop_hostname =
8404 bgp_nexthop_hostname(path->peer, path->nexthop);
8405 char esi_buf[ESI_STR_LEN];
8406
8407 if (json_paths)
8408 json_path = json_object_new_object();
8409
8410 /* short status lead text */
8411 route_vty_short_status_out(vty, path, json_path);
8412
8413 if (!json_paths) {
8414 /* print prefix and mask */
8415 if (!display)
8416 route_vty_out_route(p, vty, json_path, wide);
8417 else
8418 vty_out(vty, "%*s", (wide ? 45 : 17), " ");
8419 } else {
8420 route_vty_out_route(p, vty, json_path, wide);
8421 }
8422
8423 /*
8424 * If vrf id of nexthop is different from that of prefix,
8425 * set up printable string to append
8426 */
8427 if (path->extra && path->extra->bgp_orig) {
8428 const char *self = "";
8429
8430 if (nexthop_self)
8431 self = "<";
8432
8433 nexthop_othervrf = true;
8434 nexthop_vrfid = path->extra->bgp_orig->vrf_id;
8435
8436 if (path->extra->bgp_orig->vrf_id == VRF_UNKNOWN)
8437 snprintf(vrf_id_str, sizeof(vrf_id_str),
8438 "@%s%s", VRFID_NONE_STR, self);
8439 else
8440 snprintf(vrf_id_str, sizeof(vrf_id_str), "@%u%s",
8441 path->extra->bgp_orig->vrf_id, self);
8442
8443 if (path->extra->bgp_orig->inst_type
8444 != BGP_INSTANCE_TYPE_DEFAULT)
8445
8446 nexthop_vrfname = path->extra->bgp_orig->name;
8447 } else {
8448 const char *self = "";
8449
8450 if (nexthop_self)
8451 self = "<";
8452
8453 snprintf(vrf_id_str, sizeof(vrf_id_str), "%s", self);
8454 }
8455
8456 /*
8457 * For ENCAP and EVPN routes, nexthop address family is not
8458 * neccessarily the same as the prefix address family.
8459 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
8460 * EVPN routes are also exchanged with a MP nexthop. Currently,
8461 * this
8462 * is only IPv4, the value will be present in either
8463 * attr->nexthop or
8464 * attr->mp_nexthop_global_in
8465 */
8466 if ((safi == SAFI_ENCAP) || (safi == SAFI_MPLS_VPN)) {
8467 char buf[BUFSIZ];
8468 char nexthop[128];
8469 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
8470
8471 switch (af) {
8472 case AF_INET:
8473 snprintf(nexthop, sizeof(nexthop), "%s",
8474 inet_ntop(af, &attr->mp_nexthop_global_in, buf,
8475 BUFSIZ));
8476 break;
8477 case AF_INET6:
8478 snprintf(nexthop, sizeof(nexthop), "%s",
8479 inet_ntop(af, &attr->mp_nexthop_global, buf,
8480 BUFSIZ));
8481 break;
8482 default:
8483 snprintf(nexthop, sizeof(nexthop), "?");
8484 break;
8485 }
8486
8487 if (json_paths) {
8488 json_nexthop_global = json_object_new_object();
8489
8490 json_object_string_add(json_nexthop_global, "ip",
8491 nexthop);
8492
8493 if (path->peer->hostname)
8494 json_object_string_add(json_nexthop_global,
8495 "hostname",
8496 path->peer->hostname);
8497
8498 json_object_string_add(json_nexthop_global, "afi",
8499 (af == AF_INET) ? "ipv4"
8500 : "ipv6");
8501 json_object_boolean_true_add(json_nexthop_global,
8502 "used");
8503 } else {
8504 if (nexthop_hostname)
8505 len = vty_out(vty, "%s(%s)%s", nexthop,
8506 nexthop_hostname, vrf_id_str);
8507 else
8508 len = vty_out(vty, "%s%s", nexthop, vrf_id_str);
8509
8510 len = wide ? (41 - len) : (16 - len);
8511 if (len < 1)
8512 vty_out(vty, "\n%*s", 36, " ");
8513 else
8514 vty_out(vty, "%*s", len, " ");
8515 }
8516 } else if (safi == SAFI_EVPN) {
8517 if (json_paths) {
8518 char buf[BUFSIZ] = {0};
8519
8520 json_nexthop_global = json_object_new_object();
8521
8522 json_object_string_add(json_nexthop_global, "ip",
8523 inet_ntop(AF_INET,
8524 &attr->nexthop, buf,
8525 sizeof(buf)));
8526
8527 if (path->peer->hostname)
8528 json_object_string_add(json_nexthop_global,
8529 "hostname",
8530 path->peer->hostname);
8531
8532 json_object_string_add(json_nexthop_global, "afi",
8533 "ipv4");
8534 json_object_boolean_true_add(json_nexthop_global,
8535 "used");
8536 } else {
8537 if (nexthop_hostname)
8538 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
8539 nexthop_hostname, vrf_id_str);
8540 else
8541 len = vty_out(vty, "%pI4%s", &attr->nexthop,
8542 vrf_id_str);
8543
8544 len = wide ? (41 - len) : (16 - len);
8545 if (len < 1)
8546 vty_out(vty, "\n%*s", 36, " ");
8547 else
8548 vty_out(vty, "%*s", len, " ");
8549 }
8550 } else if (safi == SAFI_FLOWSPEC) {
8551 if (attr->nexthop.s_addr != INADDR_ANY) {
8552 if (json_paths) {
8553 char buf[BUFSIZ] = {0};
8554
8555 json_nexthop_global = json_object_new_object();
8556
8557 json_object_string_add(json_nexthop_global,
8558 "afi", "ipv4");
8559 json_object_string_add(
8560 json_nexthop_global, "ip",
8561 inet_ntop(AF_INET, &attr->nexthop, buf,
8562 sizeof(buf)));
8563
8564 if (path->peer->hostname)
8565 json_object_string_add(
8566 json_nexthop_global, "hostname",
8567 path->peer->hostname);
8568
8569 json_object_boolean_true_add(
8570 json_nexthop_global,
8571 "used");
8572 } else {
8573 if (nexthop_hostname)
8574 len = vty_out(vty, "%pI4(%s)%s",
8575 &attr->nexthop,
8576 nexthop_hostname,
8577 vrf_id_str);
8578 else
8579 len = vty_out(vty, "%pI4%s",
8580 &attr->nexthop,
8581 vrf_id_str);
8582
8583 len = wide ? (41 - len) : (16 - len);
8584 if (len < 1)
8585 vty_out(vty, "\n%*s", 36, " ");
8586 else
8587 vty_out(vty, "%*s", len, " ");
8588 }
8589 }
8590 } else if (p->family == AF_INET && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
8591 if (json_paths) {
8592 char buf[BUFSIZ] = {0};
8593
8594 json_nexthop_global = json_object_new_object();
8595
8596 json_object_string_add(json_nexthop_global, "ip",
8597 inet_ntop(AF_INET,
8598 &attr->nexthop, buf,
8599 sizeof(buf)));
8600
8601 if (path->peer->hostname)
8602 json_object_string_add(json_nexthop_global,
8603 "hostname",
8604 path->peer->hostname);
8605
8606 json_object_string_add(json_nexthop_global, "afi",
8607 "ipv4");
8608 json_object_boolean_true_add(json_nexthop_global,
8609 "used");
8610 } else {
8611 if (nexthop_hostname)
8612 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
8613 nexthop_hostname, vrf_id_str);
8614 else
8615 len = vty_out(vty, "%pI4%s", &attr->nexthop,
8616 vrf_id_str);
8617
8618 len = wide ? (41 - len) : (16 - len);
8619 if (len < 1)
8620 vty_out(vty, "\n%*s", 36, " ");
8621 else
8622 vty_out(vty, "%*s", len, " ");
8623 }
8624 }
8625
8626 /* IPv6 Next Hop */
8627 else if (p->family == AF_INET6 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
8628 char buf[BUFSIZ];
8629
8630 if (json_paths) {
8631 json_nexthop_global = json_object_new_object();
8632 json_object_string_add(
8633 json_nexthop_global, "ip",
8634 inet_ntop(AF_INET6, &attr->mp_nexthop_global,
8635 buf, BUFSIZ));
8636
8637 if (path->peer->hostname)
8638 json_object_string_add(json_nexthop_global,
8639 "hostname",
8640 path->peer->hostname);
8641
8642 json_object_string_add(json_nexthop_global, "afi",
8643 "ipv6");
8644 json_object_string_add(json_nexthop_global, "scope",
8645 "global");
8646
8647 /* We display both LL & GL if both have been
8648 * received */
8649 if ((attr->mp_nexthop_len
8650 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
8651 || (path->peer->conf_if)) {
8652 json_nexthop_ll = json_object_new_object();
8653 json_object_string_add(
8654 json_nexthop_ll, "ip",
8655 inet_ntop(AF_INET6,
8656 &attr->mp_nexthop_local, buf,
8657 BUFSIZ));
8658
8659 if (path->peer->hostname)
8660 json_object_string_add(
8661 json_nexthop_ll, "hostname",
8662 path->peer->hostname);
8663
8664 json_object_string_add(json_nexthop_ll, "afi",
8665 "ipv6");
8666 json_object_string_add(json_nexthop_ll, "scope",
8667 "link-local");
8668
8669 if ((IPV6_ADDR_CMP(&attr->mp_nexthop_global,
8670 &attr->mp_nexthop_local)
8671 != 0)
8672 && !attr->mp_nexthop_prefer_global)
8673 json_object_boolean_true_add(
8674 json_nexthop_ll, "used");
8675 else
8676 json_object_boolean_true_add(
8677 json_nexthop_global, "used");
8678 } else
8679 json_object_boolean_true_add(
8680 json_nexthop_global, "used");
8681 } else {
8682 /* Display LL if LL/Global both in table unless
8683 * prefer-global is set */
8684 if (((attr->mp_nexthop_len
8685 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
8686 && !attr->mp_nexthop_prefer_global)
8687 || (path->peer->conf_if)) {
8688 if (path->peer->conf_if) {
8689 len = vty_out(vty, "%s",
8690 path->peer->conf_if);
8691 /* len of IPv6 addr + max len of def
8692 * ifname */
8693 len = wide ? (41 - len) : (16 - len);
8694
8695 if (len < 1)
8696 vty_out(vty, "\n%*s", 36, " ");
8697 else
8698 vty_out(vty, "%*s", len, " ");
8699 } else {
8700 if (nexthop_hostname)
8701 len = vty_out(
8702 vty, "%pI6(%s)%s",
8703 &attr->mp_nexthop_local,
8704 nexthop_hostname,
8705 vrf_id_str);
8706 else
8707 len = vty_out(
8708 vty, "%pI6%s",
8709 &attr->mp_nexthop_local,
8710 vrf_id_str);
8711
8712 len = wide ? (41 - len) : (16 - len);
8713
8714 if (len < 1)
8715 vty_out(vty, "\n%*s", 36, " ");
8716 else
8717 vty_out(vty, "%*s", len, " ");
8718 }
8719 } else {
8720 if (nexthop_hostname)
8721 len = vty_out(vty, "%pI6(%s)%s",
8722 &attr->mp_nexthop_global,
8723 nexthop_hostname,
8724 vrf_id_str);
8725 else
8726 len = vty_out(vty, "%pI6%s",
8727 &attr->mp_nexthop_global,
8728 vrf_id_str);
8729
8730 len = wide ? (41 - len) : (16 - len);
8731
8732 if (len < 1)
8733 vty_out(vty, "\n%*s", 36, " ");
8734 else
8735 vty_out(vty, "%*s", len, " ");
8736 }
8737 }
8738 }
8739
8740 /* MED/Metric */
8741 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
8742 if (json_paths)
8743 json_object_int_add(json_path, "metric", attr->med);
8744 else if (wide)
8745 vty_out(vty, "%7u", attr->med);
8746 else
8747 vty_out(vty, "%10u", attr->med);
8748 else if (!json_paths) {
8749 if (wide)
8750 vty_out(vty, "%*s", 7, " ");
8751 else
8752 vty_out(vty, "%*s", 10, " ");
8753 }
8754
8755 /* Local Pref */
8756 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
8757 if (json_paths)
8758 json_object_int_add(json_path, "locPrf",
8759 attr->local_pref);
8760 else
8761 vty_out(vty, "%7u", attr->local_pref);
8762 else if (!json_paths)
8763 vty_out(vty, " ");
8764
8765 if (json_paths)
8766 json_object_int_add(json_path, "weight", attr->weight);
8767 else
8768 vty_out(vty, "%7u ", attr->weight);
8769
8770 if (json_paths) {
8771 char buf[BUFSIZ];
8772 json_object_string_add(
8773 json_path, "peerId",
8774 sockunion2str(&path->peer->su, buf, SU_ADDRSTRLEN));
8775 }
8776
8777 /* Print aspath */
8778 if (attr->aspath) {
8779 if (json_paths)
8780 json_object_string_add(json_path, "path",
8781 attr->aspath->str);
8782 else
8783 aspath_print_vty(vty, "%s", attr->aspath, " ");
8784 }
8785
8786 /* Print origin */
8787 if (json_paths)
8788 json_object_string_add(json_path, "origin",
8789 bgp_origin_long_str[attr->origin]);
8790 else
8791 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
8792
8793 if (json_paths) {
8794 if (bgp_evpn_is_esi_valid(&attr->esi)) {
8795 json_object_string_add(json_path, "esi",
8796 esi_to_str(&attr->esi,
8797 esi_buf, sizeof(esi_buf)));
8798 }
8799 if (safi == SAFI_EVPN &&
8800 attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
8801 json_ext_community = json_object_new_object();
8802 json_object_string_add(json_ext_community,
8803 "string",
8804 attr->ecommunity->str);
8805 json_object_object_add(json_path,
8806 "extendedCommunity",
8807 json_ext_community);
8808 }
8809
8810 if (nexthop_self)
8811 json_object_boolean_true_add(json_path,
8812 "announceNexthopSelf");
8813 if (nexthop_othervrf) {
8814 json_object_string_add(json_path, "nhVrfName",
8815 nexthop_vrfname);
8816
8817 json_object_int_add(json_path, "nhVrfId",
8818 ((nexthop_vrfid == VRF_UNKNOWN)
8819 ? -1
8820 : (int)nexthop_vrfid));
8821 }
8822 }
8823
8824 if (json_paths) {
8825 if (json_nexthop_global || json_nexthop_ll) {
8826 json_nexthops = json_object_new_array();
8827
8828 if (json_nexthop_global)
8829 json_object_array_add(json_nexthops,
8830 json_nexthop_global);
8831
8832 if (json_nexthop_ll)
8833 json_object_array_add(json_nexthops,
8834 json_nexthop_ll);
8835
8836 json_object_object_add(json_path, "nexthops",
8837 json_nexthops);
8838 }
8839
8840 json_object_array_add(json_paths, json_path);
8841 } else {
8842 vty_out(vty, "\n");
8843
8844 if (safi == SAFI_EVPN) {
8845 struct bgp_path_es_info *path_es_info = NULL;
8846
8847 if (path->extra)
8848 path_es_info = path->extra->es_info;
8849
8850 if (bgp_evpn_is_esi_valid(&attr->esi)) {
8851 /* XXX - add these params to the json out */
8852 vty_out(vty, "%*s", 20, " ");
8853 vty_out(vty, "ESI:%s",
8854 esi_to_str(&attr->esi, esi_buf,
8855 sizeof(esi_buf)));
8856 if (path_es_info && path_es_info->es)
8857 vty_out(vty, " VNI: %u",
8858 path_es_info->vni);
8859 vty_out(vty, "\n");
8860 }
8861 if (attr->flag &
8862 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
8863 vty_out(vty, "%*s", 20, " ");
8864 vty_out(vty, "%s\n", attr->ecommunity->str);
8865 }
8866 }
8867
8868 #ifdef ENABLE_BGP_VNC
8869 /* prints an additional line, indented, with VNC info, if
8870 * present */
8871 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
8872 rfapi_vty_out_vncinfo(vty, p, path, safi);
8873 #endif
8874 }
8875 }
8876
8877 /* called from terminal list command */
8878 void route_vty_out_tmp(struct vty *vty, const struct prefix *p,
8879 struct attr *attr, safi_t safi, bool use_json,
8880 json_object *json_ar, bool wide)
8881 {
8882 json_object *json_status = NULL;
8883 json_object *json_net = NULL;
8884 int len;
8885 char buff[BUFSIZ];
8886
8887 /* Route status display. */
8888 if (use_json) {
8889 json_status = json_object_new_object();
8890 json_net = json_object_new_object();
8891 } else {
8892 vty_out(vty, "*");
8893 vty_out(vty, ">");
8894 vty_out(vty, " ");
8895 }
8896
8897 /* print prefix and mask */
8898 if (use_json) {
8899 if (safi == SAFI_EVPN)
8900 bgp_evpn_route2json((struct prefix_evpn *)p, json_net);
8901 else if (p->family == AF_INET || p->family == AF_INET6) {
8902 json_object_string_add(
8903 json_net, "addrPrefix",
8904 inet_ntop(p->family, &p->u.prefix, buff,
8905 BUFSIZ));
8906 json_object_int_add(json_net, "prefixLen",
8907 p->prefixlen);
8908 prefix2str(p, buff, PREFIX_STRLEN);
8909 json_object_string_add(json_net, "network", buff);
8910 }
8911 } else
8912 route_vty_out_route(p, vty, NULL, wide);
8913
8914 /* Print attribute */
8915 if (attr) {
8916 if (use_json) {
8917 char buf[BUFSIZ] = {0};
8918
8919 if (p->family == AF_INET
8920 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
8921 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
8922 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
8923 json_object_string_add(
8924 json_net, "nextHop",
8925 inet_ntop(
8926 AF_INET,
8927 &attr->mp_nexthop_global_in,
8928 buf, sizeof(buf)));
8929 else
8930 json_object_string_add(
8931 json_net, "nextHop",
8932 inet_ntop(AF_INET,
8933 &attr->nexthop, buf,
8934 sizeof(buf)));
8935 } else if (p->family == AF_INET6
8936 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
8937 char buf[BUFSIZ];
8938
8939 json_object_string_add(
8940 json_net, "nextHopGlobal",
8941 inet_ntop(AF_INET6,
8942 &attr->mp_nexthop_global, buf,
8943 BUFSIZ));
8944 } else if (p->family == AF_EVPN
8945 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
8946 char buf[BUFSIZ] = {0};
8947
8948 json_object_string_add(
8949 json_net, "nextHop",
8950 inet_ntop(AF_INET,
8951 &attr->mp_nexthop_global_in,
8952 buf, sizeof(buf)));
8953 }
8954
8955 if (attr->flag
8956 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
8957 json_object_int_add(json_net, "metric",
8958 attr->med);
8959
8960 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
8961 json_object_int_add(json_net, "locPrf",
8962 attr->local_pref);
8963
8964 json_object_int_add(json_net, "weight", attr->weight);
8965
8966 /* Print aspath */
8967 if (attr->aspath)
8968 json_object_string_add(json_net, "path",
8969 attr->aspath->str);
8970
8971 /* Print origin */
8972 json_object_string_add(json_net, "bgpOriginCode",
8973 bgp_origin_str[attr->origin]);
8974 } else {
8975 if (p->family == AF_INET
8976 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
8977 || safi == SAFI_EVPN
8978 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
8979 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
8980 || safi == SAFI_EVPN)
8981 vty_out(vty, "%-16pI4",
8982 &attr->mp_nexthop_global_in);
8983 else if (wide)
8984 vty_out(vty, "%-41pI4", &attr->nexthop);
8985 else
8986 vty_out(vty, "%-16pI4", &attr->nexthop);
8987 } else if (p->family == AF_INET6
8988 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
8989 char buf[BUFSIZ];
8990
8991 len = vty_out(
8992 vty, "%s",
8993 inet_ntop(AF_INET6,
8994 &attr->mp_nexthop_global, buf,
8995 BUFSIZ));
8996 len = wide ? (41 - len) : (16 - len);
8997 if (len < 1)
8998 vty_out(vty, "\n%*s", 36, " ");
8999 else
9000 vty_out(vty, "%*s", len, " ");
9001 }
9002 if (attr->flag
9003 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
9004 if (wide)
9005 vty_out(vty, "%7u", attr->med);
9006 else
9007 vty_out(vty, "%10u", attr->med);
9008 else if (wide)
9009 vty_out(vty, " ");
9010 else
9011 vty_out(vty, " ");
9012
9013 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
9014 vty_out(vty, "%7u", attr->local_pref);
9015 else
9016 vty_out(vty, " ");
9017
9018 vty_out(vty, "%7u ", attr->weight);
9019
9020 /* Print aspath */
9021 if (attr->aspath)
9022 aspath_print_vty(vty, "%s", attr->aspath, " ");
9023
9024 /* Print origin */
9025 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9026 }
9027 }
9028 if (use_json) {
9029 json_object_boolean_true_add(json_status, "*");
9030 json_object_boolean_true_add(json_status, ">");
9031 json_object_object_add(json_net, "appliedStatusSymbols",
9032 json_status);
9033
9034 prefix2str(p, buff, PREFIX_STRLEN);
9035 json_object_object_add(json_ar, buff, json_net);
9036 } else
9037 vty_out(vty, "\n");
9038 }
9039
9040 void route_vty_out_tag(struct vty *vty, const struct prefix *p,
9041 struct bgp_path_info *path, int display, safi_t safi,
9042 json_object *json)
9043 {
9044 json_object *json_out = NULL;
9045 struct attr *attr;
9046 mpls_label_t label = MPLS_INVALID_LABEL;
9047
9048 if (!path->extra)
9049 return;
9050
9051 if (json)
9052 json_out = json_object_new_object();
9053
9054 /* short status lead text */
9055 route_vty_short_status_out(vty, path, json_out);
9056
9057 /* print prefix and mask */
9058 if (json == NULL) {
9059 if (!display)
9060 route_vty_out_route(p, vty, NULL, false);
9061 else
9062 vty_out(vty, "%*s", 17, " ");
9063 }
9064
9065 /* Print attribute */
9066 attr = path->attr;
9067 if (((p->family == AF_INET)
9068 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
9069 || (safi == SAFI_EVPN && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))
9070 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
9071 char buf[BUFSIZ] = {0};
9072
9073 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9074 || safi == SAFI_EVPN) {
9075 if (json)
9076 json_object_string_add(
9077 json_out, "mpNexthopGlobalIn",
9078 inet_ntop(AF_INET,
9079 &attr->mp_nexthop_global_in,
9080 buf, sizeof(buf)));
9081 else
9082 vty_out(vty, "%-16pI4",
9083 &attr->mp_nexthop_global_in);
9084 } else {
9085 if (json)
9086 json_object_string_add(
9087 json_out, "nexthop",
9088 inet_ntop(AF_INET, &attr->nexthop, buf,
9089 sizeof(buf)));
9090 else
9091 vty_out(vty, "%-16pI4", &attr->nexthop);
9092 }
9093 } else if (((p->family == AF_INET6)
9094 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
9095 || (safi == SAFI_EVPN && BGP_ATTR_NEXTHOP_AFI_IP6(attr))
9096 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
9097 char buf_a[512];
9098
9099 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL) {
9100 if (json)
9101 json_object_string_add(
9102 json_out, "mpNexthopGlobalIn",
9103 inet_ntop(AF_INET6,
9104 &attr->mp_nexthop_global,
9105 buf_a, sizeof(buf_a)));
9106 else
9107 vty_out(vty, "%s",
9108 inet_ntop(AF_INET6,
9109 &attr->mp_nexthop_global,
9110 buf_a, sizeof(buf_a)));
9111 } else if (attr->mp_nexthop_len
9112 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
9113 snprintfrr(buf_a, sizeof(buf_a), "%pI6(%pI6)",
9114 &attr->mp_nexthop_global,
9115 &attr->mp_nexthop_local);
9116 if (json)
9117 json_object_string_add(json_out,
9118 "mpNexthopGlobalLocal",
9119 buf_a);
9120 else
9121 vty_out(vty, "%s", buf_a);
9122 }
9123 }
9124
9125 label = decode_label(&path->extra->label[0]);
9126
9127 if (bgp_is_valid_label(&label)) {
9128 if (json) {
9129 json_object_int_add(json_out, "notag", label);
9130 json_object_array_add(json, json_out);
9131 } else {
9132 vty_out(vty, "notag/%d", label);
9133 vty_out(vty, "\n");
9134 }
9135 }
9136 }
9137
9138 void route_vty_out_overlay(struct vty *vty, const struct prefix *p,
9139 struct bgp_path_info *path, int display,
9140 json_object *json_paths)
9141 {
9142 struct attr *attr;
9143 char buf[BUFSIZ] = {0};
9144 json_object *json_path = NULL;
9145 json_object *json_nexthop = NULL;
9146 json_object *json_overlay = NULL;
9147
9148 if (!path->extra)
9149 return;
9150
9151 if (json_paths) {
9152 json_path = json_object_new_object();
9153 json_overlay = json_object_new_object();
9154 json_nexthop = json_object_new_object();
9155 }
9156
9157 /* short status lead text */
9158 route_vty_short_status_out(vty, path, json_path);
9159
9160 /* print prefix and mask */
9161 if (!display)
9162 route_vty_out_route(p, vty, json_path, false);
9163 else
9164 vty_out(vty, "%*s", 17, " ");
9165
9166 /* Print attribute */
9167 attr = path->attr;
9168 char buf1[BUFSIZ];
9169 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
9170
9171 switch (af) {
9172 case AF_INET:
9173 inet_ntop(af, &attr->mp_nexthop_global_in, buf, BUFSIZ);
9174 if (!json_path) {
9175 vty_out(vty, "%-16s", buf);
9176 } else {
9177 json_object_string_add(json_nexthop, "ip", buf);
9178
9179 json_object_string_add(json_nexthop, "afi", "ipv4");
9180
9181 json_object_object_add(json_path, "nexthop",
9182 json_nexthop);
9183 }
9184 break;
9185 case AF_INET6:
9186 inet_ntop(af, &attr->mp_nexthop_global, buf, BUFSIZ);
9187 inet_ntop(af, &attr->mp_nexthop_local, buf1, BUFSIZ);
9188 if (!json_path) {
9189 vty_out(vty, "%s(%s)", buf, buf1);
9190 } else {
9191 json_object_string_add(json_nexthop, "ipv6Global", buf);
9192
9193 json_object_string_add(json_nexthop, "ipv6LinkLocal",
9194 buf1);
9195
9196 json_object_string_add(json_nexthop, "afi", "ipv6");
9197
9198 json_object_object_add(json_path, "nexthop",
9199 json_nexthop);
9200 }
9201 break;
9202 default:
9203 if (!json_path) {
9204 vty_out(vty, "?");
9205 } else {
9206 json_object_string_add(json_nexthop, "Error",
9207 "Unsupported address-family");
9208 }
9209 }
9210
9211 const struct bgp_route_evpn *eo = bgp_attr_get_evpn_overlay(attr);
9212
9213 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn *)p))
9214 inet_ntop(AF_INET, &eo->gw_ip.ipv4, buf, BUFSIZ);
9215 else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn *)p))
9216 inet_ntop(AF_INET6, &eo->gw_ip.ipv6, buf, BUFSIZ);
9217
9218 if (!json_path)
9219 vty_out(vty, "/%s", buf);
9220 else
9221 json_object_string_add(json_overlay, "gw", buf);
9222
9223 if (attr->ecommunity) {
9224 char *mac = NULL;
9225 struct ecommunity_val *routermac = ecommunity_lookup(
9226 attr->ecommunity, ECOMMUNITY_ENCODE_EVPN,
9227 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC);
9228
9229 if (routermac)
9230 mac = ecom_mac2str((char *)routermac->val);
9231 if (mac) {
9232 if (!json_path) {
9233 vty_out(vty, "/%s", mac);
9234 } else {
9235 json_object_string_add(json_overlay, "rmac",
9236 mac);
9237 }
9238 XFREE(MTYPE_TMP, mac);
9239 }
9240 }
9241
9242 if (!json_path) {
9243 vty_out(vty, "\n");
9244 } else {
9245 json_object_object_add(json_path, "overlay", json_overlay);
9246
9247 json_object_array_add(json_paths, json_path);
9248 }
9249 }
9250
9251 /* dampening route */
9252 static void damp_route_vty_out(struct vty *vty, const struct prefix *p,
9253 struct bgp_path_info *path, int display,
9254 afi_t afi, safi_t safi, bool use_json,
9255 json_object *json)
9256 {
9257 struct attr *attr;
9258 int len;
9259 char timebuf[BGP_UPTIME_LEN];
9260
9261 /* short status lead text */
9262 route_vty_short_status_out(vty, path, json);
9263
9264 /* print prefix and mask */
9265 if (!use_json) {
9266 if (!display)
9267 route_vty_out_route(p, vty, NULL, false);
9268 else
9269 vty_out(vty, "%*s", 17, " ");
9270 }
9271
9272 len = vty_out(vty, "%s", path->peer->host);
9273 len = 17 - len;
9274 if (len < 1) {
9275 if (!use_json)
9276 vty_out(vty, "\n%*s", 34, " ");
9277 } else {
9278 if (use_json)
9279 json_object_int_add(json, "peerHost", len);
9280 else
9281 vty_out(vty, "%*s", len, " ");
9282 }
9283
9284 if (use_json)
9285 bgp_damp_reuse_time_vty(vty, path, timebuf, BGP_UPTIME_LEN, afi,
9286 safi, use_json, json);
9287 else
9288 vty_out(vty, "%s ",
9289 bgp_damp_reuse_time_vty(vty, path, timebuf,
9290 BGP_UPTIME_LEN, afi, safi,
9291 use_json, json));
9292
9293 /* Print attribute */
9294 attr = path->attr;
9295
9296 /* Print aspath */
9297 if (attr->aspath) {
9298 if (use_json)
9299 json_object_string_add(json, "asPath",
9300 attr->aspath->str);
9301 else
9302 aspath_print_vty(vty, "%s", attr->aspath, " ");
9303 }
9304
9305 /* Print origin */
9306 if (use_json)
9307 json_object_string_add(json, "origin",
9308 bgp_origin_str[attr->origin]);
9309 else
9310 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9311
9312 if (!use_json)
9313 vty_out(vty, "\n");
9314 }
9315
9316 /* flap route */
9317 static void flap_route_vty_out(struct vty *vty, const struct prefix *p,
9318 struct bgp_path_info *path, int display,
9319 afi_t afi, safi_t safi, bool use_json,
9320 json_object *json)
9321 {
9322 struct attr *attr;
9323 struct bgp_damp_info *bdi;
9324 char timebuf[BGP_UPTIME_LEN];
9325 int len;
9326
9327 if (!path->extra)
9328 return;
9329
9330 bdi = path->extra->damp_info;
9331
9332 /* short status lead text */
9333 route_vty_short_status_out(vty, path, json);
9334
9335 /* print prefix and mask */
9336 if (!use_json) {
9337 if (!display)
9338 route_vty_out_route(p, vty, NULL, false);
9339 else
9340 vty_out(vty, "%*s", 17, " ");
9341 }
9342
9343 len = vty_out(vty, "%s", path->peer->host);
9344 len = 16 - len;
9345 if (len < 1) {
9346 if (!use_json)
9347 vty_out(vty, "\n%*s", 33, " ");
9348 } else {
9349 if (use_json)
9350 json_object_int_add(json, "peerHost", len);
9351 else
9352 vty_out(vty, "%*s", len, " ");
9353 }
9354
9355 len = vty_out(vty, "%d", bdi->flap);
9356 len = 5 - len;
9357 if (len < 1) {
9358 if (!use_json)
9359 vty_out(vty, " ");
9360 } else {
9361 if (use_json)
9362 json_object_int_add(json, "bdiFlap", len);
9363 else
9364 vty_out(vty, "%*s", len, " ");
9365 }
9366
9367 if (use_json)
9368 peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, use_json,
9369 json);
9370 else
9371 vty_out(vty, "%s ", peer_uptime(bdi->start_time, timebuf,
9372 BGP_UPTIME_LEN, 0, NULL));
9373
9374 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
9375 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
9376 if (use_json)
9377 bgp_damp_reuse_time_vty(vty, path, timebuf,
9378 BGP_UPTIME_LEN, afi, safi,
9379 use_json, json);
9380 else
9381 vty_out(vty, "%s ",
9382 bgp_damp_reuse_time_vty(vty, path, timebuf,
9383 BGP_UPTIME_LEN, afi,
9384 safi, use_json, json));
9385 } else {
9386 if (!use_json)
9387 vty_out(vty, "%*s ", 8, " ");
9388 }
9389
9390 /* Print attribute */
9391 attr = path->attr;
9392
9393 /* Print aspath */
9394 if (attr->aspath) {
9395 if (use_json)
9396 json_object_string_add(json, "asPath",
9397 attr->aspath->str);
9398 else
9399 aspath_print_vty(vty, "%s", attr->aspath, " ");
9400 }
9401
9402 /* Print origin */
9403 if (use_json)
9404 json_object_string_add(json, "origin",
9405 bgp_origin_str[attr->origin]);
9406 else
9407 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9408
9409 if (!use_json)
9410 vty_out(vty, "\n");
9411 }
9412
9413 static void route_vty_out_advertised_to(struct vty *vty, struct peer *peer,
9414 int *first, const char *header,
9415 json_object *json_adv_to)
9416 {
9417 char buf1[INET6_ADDRSTRLEN];
9418 json_object *json_peer = NULL;
9419
9420 if (json_adv_to) {
9421 /* 'advertised-to' is a dictionary of peers we have advertised
9422 * this
9423 * prefix too. The key is the peer's IP or swpX, the value is
9424 * the
9425 * hostname if we know it and "" if not.
9426 */
9427 json_peer = json_object_new_object();
9428
9429 if (peer->hostname)
9430 json_object_string_add(json_peer, "hostname",
9431 peer->hostname);
9432
9433 if (peer->conf_if)
9434 json_object_object_add(json_adv_to, peer->conf_if,
9435 json_peer);
9436 else
9437 json_object_object_add(
9438 json_adv_to,
9439 sockunion2str(&peer->su, buf1, SU_ADDRSTRLEN),
9440 json_peer);
9441 } else {
9442 if (*first) {
9443 vty_out(vty, "%s", header);
9444 *first = 0;
9445 }
9446
9447 if (peer->hostname
9448 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
9449 if (peer->conf_if)
9450 vty_out(vty, " %s(%s)", peer->hostname,
9451 peer->conf_if);
9452 else
9453 vty_out(vty, " %s(%s)", peer->hostname,
9454 sockunion2str(&peer->su, buf1,
9455 SU_ADDRSTRLEN));
9456 } else {
9457 if (peer->conf_if)
9458 vty_out(vty, " %s", peer->conf_if);
9459 else
9460 vty_out(vty, " %s",
9461 sockunion2str(&peer->su, buf1,
9462 SU_ADDRSTRLEN));
9463 }
9464 }
9465 }
9466
9467 static void route_vty_out_tx_ids(struct vty *vty,
9468 struct bgp_addpath_info_data *d)
9469 {
9470 int i;
9471
9472 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
9473 vty_out(vty, "TX-%s %u%s", bgp_addpath_names(i)->human_name,
9474 d->addpath_tx_id[i],
9475 i < BGP_ADDPATH_MAX - 1 ? " " : "\n");
9476 }
9477 }
9478
9479 static void route_vty_out_detail_es_info(struct vty *vty,
9480 struct bgp_path_info *pi,
9481 struct attr *attr,
9482 json_object *json_path)
9483 {
9484 char esi_buf[ESI_STR_LEN];
9485 bool es_local = !!CHECK_FLAG(attr->es_flags, ATTR_ES_IS_LOCAL);
9486 bool peer_router = !!CHECK_FLAG(attr->es_flags,
9487 ATTR_ES_PEER_ROUTER);
9488 bool peer_active = !!CHECK_FLAG(attr->es_flags,
9489 ATTR_ES_PEER_ACTIVE);
9490 bool peer_proxy = !!CHECK_FLAG(attr->es_flags,
9491 ATTR_ES_PEER_PROXY);
9492 esi_to_str(&attr->esi, esi_buf, sizeof(esi_buf));
9493 if (json_path) {
9494 json_object *json_es_info = NULL;
9495
9496 json_object_string_add(
9497 json_path, "esi",
9498 esi_buf);
9499 if (es_local || bgp_evpn_attr_is_sync(attr)) {
9500 json_es_info = json_object_new_object();
9501 if (es_local)
9502 json_object_boolean_true_add(
9503 json_es_info, "localEs");
9504 if (peer_active)
9505 json_object_boolean_true_add(
9506 json_es_info, "peerActive");
9507 if (peer_proxy)
9508 json_object_boolean_true_add(
9509 json_es_info, "peerProxy");
9510 if (peer_router)
9511 json_object_boolean_true_add(
9512 json_es_info, "peerRouter");
9513 if (attr->mm_sync_seqnum)
9514 json_object_int_add(
9515 json_es_info, "peerSeq",
9516 attr->mm_sync_seqnum);
9517 json_object_object_add(
9518 json_path, "es_info",
9519 json_es_info);
9520 }
9521 } else {
9522 if (bgp_evpn_attr_is_sync(attr))
9523 vty_out(vty,
9524 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
9525 esi_buf,
9526 es_local ? "local-es":"",
9527 peer_proxy ? "proxy " : "",
9528 peer_active ? "active ":"",
9529 peer_router ? "router ":"",
9530 attr->mm_sync_seqnum);
9531 else
9532 vty_out(vty, " ESI %s %s\n",
9533 esi_buf,
9534 es_local ? "local-es":"");
9535 }
9536 }
9537
9538 void route_vty_out_detail(struct vty *vty, struct bgp *bgp,
9539 struct bgp_dest *bn, struct bgp_path_info *path,
9540 afi_t afi, safi_t safi, json_object *json_paths)
9541 {
9542 char buf[INET6_ADDRSTRLEN];
9543 char buf1[BUFSIZ];
9544 struct attr *attr = path->attr;
9545 int sockunion_vty_out(struct vty *, union sockunion *);
9546 time_t tbuf;
9547 json_object *json_bestpath = NULL;
9548 json_object *json_cluster_list = NULL;
9549 json_object *json_cluster_list_list = NULL;
9550 json_object *json_ext_community = NULL;
9551 json_object *json_last_update = NULL;
9552 json_object *json_pmsi = NULL;
9553 json_object *json_nexthop_global = NULL;
9554 json_object *json_nexthop_ll = NULL;
9555 json_object *json_nexthops = NULL;
9556 json_object *json_path = NULL;
9557 json_object *json_peer = NULL;
9558 json_object *json_string = NULL;
9559 json_object *json_adv_to = NULL;
9560 int first = 0;
9561 struct listnode *node, *nnode;
9562 struct peer *peer;
9563 int addpath_capable;
9564 int has_adj;
9565 unsigned int first_as;
9566 bool nexthop_self =
9567 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
9568 int i;
9569 char *nexthop_hostname =
9570 bgp_nexthop_hostname(path->peer, path->nexthop);
9571
9572 if (json_paths) {
9573 json_path = json_object_new_object();
9574 json_peer = json_object_new_object();
9575 json_nexthop_global = json_object_new_object();
9576 }
9577
9578 if (path->extra) {
9579 char tag_buf[30];
9580
9581 tag_buf[0] = '\0';
9582 if (path->extra && path->extra->num_labels) {
9583 bgp_evpn_label2str(path->extra->label,
9584 path->extra->num_labels, tag_buf,
9585 sizeof(tag_buf));
9586 }
9587 if (safi == SAFI_EVPN) {
9588 if (!json_paths) {
9589 vty_out(vty, " Route %pFX",
9590 (struct prefix_evpn *)
9591 bgp_dest_get_prefix(bn));
9592 if (tag_buf[0] != '\0')
9593 vty_out(vty, " VNI %s", tag_buf);
9594 vty_out(vty, "\n");
9595 } else {
9596 if (tag_buf[0])
9597 json_object_string_add(json_path, "VNI",
9598 tag_buf);
9599 }
9600 }
9601
9602 if (path->extra && path->extra->parent && !json_paths) {
9603 struct bgp_path_info *parent_ri;
9604 struct bgp_dest *dest, *pdest;
9605
9606 parent_ri = (struct bgp_path_info *)path->extra->parent;
9607 dest = parent_ri->net;
9608 if (dest && dest->pdest) {
9609 pdest = dest->pdest;
9610 prefix_rd2str(
9611 (struct prefix_rd *)bgp_dest_get_prefix(
9612 pdest),
9613 buf1, sizeof(buf1));
9614 if (is_pi_family_evpn(parent_ri)) {
9615 vty_out(vty,
9616 " Imported from %s:%pFX, VNI %s\n",
9617 buf1,
9618 (struct prefix_evpn *)
9619 bgp_dest_get_prefix(
9620 dest),
9621 tag_buf);
9622 } else
9623 vty_out(vty,
9624 " Imported from %s:%pFX\n",
9625 buf1,
9626 (struct prefix_evpn *)
9627 bgp_dest_get_prefix(
9628 dest));
9629 }
9630 }
9631 }
9632
9633 /* Line1 display AS-path, Aggregator */
9634 if (attr->aspath) {
9635 if (json_paths) {
9636 if (!attr->aspath->json)
9637 aspath_str_update(attr->aspath, true);
9638 json_object_lock(attr->aspath->json);
9639 json_object_object_add(json_path, "aspath",
9640 attr->aspath->json);
9641 } else {
9642 if (attr->aspath->segments)
9643 aspath_print_vty(vty, " %s", attr->aspath, "");
9644 else
9645 vty_out(vty, " Local");
9646 }
9647 }
9648
9649 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED)) {
9650 if (json_paths)
9651 json_object_boolean_true_add(json_path, "removed");
9652 else
9653 vty_out(vty, ", (removed)");
9654 }
9655
9656 if (CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
9657 if (json_paths)
9658 json_object_boolean_true_add(json_path, "stale");
9659 else
9660 vty_out(vty, ", (stale)");
9661 }
9662
9663 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
9664 if (json_paths) {
9665 char buf[BUFSIZ] = {0};
9666
9667 json_object_int_add(json_path, "aggregatorAs",
9668 attr->aggregator_as);
9669 json_object_string_add(json_path, "aggregatorId",
9670 inet_ntop(AF_INET,
9671 &attr->aggregator_addr,
9672 buf, sizeof(buf)));
9673 } else {
9674 vty_out(vty, ", (aggregated by %u %pI4)",
9675 attr->aggregator_as, &attr->aggregator_addr);
9676 }
9677 }
9678
9679 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
9680 PEER_FLAG_REFLECTOR_CLIENT)) {
9681 if (json_paths)
9682 json_object_boolean_true_add(json_path,
9683 "rxedFromRrClient");
9684 else
9685 vty_out(vty, ", (Received from a RR-client)");
9686 }
9687
9688 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
9689 PEER_FLAG_RSERVER_CLIENT)) {
9690 if (json_paths)
9691 json_object_boolean_true_add(json_path,
9692 "rxedFromRsClient");
9693 else
9694 vty_out(vty, ", (Received from a RS-client)");
9695 }
9696
9697 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
9698 if (json_paths)
9699 json_object_boolean_true_add(json_path,
9700 "dampeningHistoryEntry");
9701 else
9702 vty_out(vty, ", (history entry)");
9703 } else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)) {
9704 if (json_paths)
9705 json_object_boolean_true_add(json_path,
9706 "dampeningSuppressed");
9707 else
9708 vty_out(vty, ", (suppressed due to dampening)");
9709 }
9710
9711 if (!json_paths)
9712 vty_out(vty, "\n");
9713
9714 /* Line2 display Next-hop, Neighbor, Router-id */
9715 /* Display the nexthop */
9716 const struct prefix *bn_p = bgp_dest_get_prefix(bn);
9717
9718 if ((bn_p->family == AF_INET || bn_p->family == AF_ETHERNET
9719 || bn_p->family == AF_EVPN)
9720 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN
9721 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
9722 char buf[BUFSIZ] = {0};
9723
9724 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9725 || safi == SAFI_EVPN) {
9726 if (json_paths) {
9727 json_object_string_add(
9728 json_nexthop_global, "ip",
9729 inet_ntop(AF_INET,
9730 &attr->mp_nexthop_global_in,
9731 buf, sizeof(buf)));
9732
9733 if (path->peer->hostname)
9734 json_object_string_add(
9735 json_nexthop_global, "hostname",
9736 path->peer->hostname);
9737 } else {
9738 if (nexthop_hostname)
9739 vty_out(vty, " %pI4(%s)",
9740 &attr->mp_nexthop_global_in,
9741 nexthop_hostname);
9742 else
9743 vty_out(vty, " %pI4",
9744 &attr->mp_nexthop_global_in);
9745 }
9746 } else {
9747 if (json_paths) {
9748 json_object_string_add(
9749 json_nexthop_global, "ip",
9750 inet_ntop(AF_INET, &attr->nexthop, buf,
9751 sizeof(buf)));
9752
9753 if (path->peer->hostname)
9754 json_object_string_add(
9755 json_nexthop_global, "hostname",
9756 path->peer->hostname);
9757 } else {
9758 if (nexthop_hostname)
9759 vty_out(vty, " %pI4(%s)",
9760 &attr->nexthop,
9761 nexthop_hostname);
9762 else
9763 vty_out(vty, " %pI4",
9764 &attr->nexthop);
9765 }
9766 }
9767
9768 if (json_paths)
9769 json_object_string_add(json_nexthop_global, "afi",
9770 "ipv4");
9771 } else {
9772 if (json_paths) {
9773 json_object_string_add(
9774 json_nexthop_global, "ip",
9775 inet_ntop(AF_INET6, &attr->mp_nexthop_global,
9776 buf, INET6_ADDRSTRLEN));
9777
9778 if (path->peer->hostname)
9779 json_object_string_add(json_nexthop_global,
9780 "hostname",
9781 path->peer->hostname);
9782
9783 json_object_string_add(json_nexthop_global, "afi",
9784 "ipv6");
9785 json_object_string_add(json_nexthop_global, "scope",
9786 "global");
9787 } else {
9788 if (nexthop_hostname)
9789 vty_out(vty, " %pI6(%s)",
9790 &attr->mp_nexthop_global,
9791 nexthop_hostname);
9792 else
9793 vty_out(vty, " %pI6",
9794 &attr->mp_nexthop_global);
9795 }
9796 }
9797
9798 /* Display the IGP cost or 'inaccessible' */
9799 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
9800 if (json_paths)
9801 json_object_boolean_false_add(json_nexthop_global,
9802 "accessible");
9803 else
9804 vty_out(vty, " (inaccessible)");
9805 } else {
9806 if (path->extra && path->extra->igpmetric) {
9807 if (json_paths)
9808 json_object_int_add(json_nexthop_global,
9809 "metric",
9810 path->extra->igpmetric);
9811 else
9812 vty_out(vty, " (metric %u)",
9813 path->extra->igpmetric);
9814 }
9815
9816 /* IGP cost is 0, display this only for json */
9817 else {
9818 if (json_paths)
9819 json_object_int_add(json_nexthop_global,
9820 "metric", 0);
9821 }
9822
9823 if (json_paths)
9824 json_object_boolean_true_add(json_nexthop_global,
9825 "accessible");
9826 }
9827
9828 /* Display peer "from" output */
9829 /* This path was originated locally */
9830 if (path->peer == bgp->peer_self) {
9831
9832 if (safi == SAFI_EVPN
9833 || (bn_p->family == AF_INET
9834 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
9835 if (json_paths)
9836 json_object_string_add(json_peer, "peerId",
9837 "0.0.0.0");
9838 else
9839 vty_out(vty, " from 0.0.0.0 ");
9840 } else {
9841 if (json_paths)
9842 json_object_string_add(json_peer, "peerId",
9843 "::");
9844 else
9845 vty_out(vty, " from :: ");
9846 }
9847
9848 if (json_paths) {
9849 char buf[BUFSIZ] = {0};
9850
9851 json_object_string_add(json_peer, "routerId",
9852 inet_ntop(AF_INET,
9853 &bgp->router_id, buf,
9854 sizeof(buf)));
9855 } else {
9856 vty_out(vty, "(%pI4)", &bgp->router_id);
9857 }
9858 }
9859
9860 /* We RXed this path from one of our peers */
9861 else {
9862
9863 if (json_paths) {
9864 json_object_string_add(json_peer, "peerId",
9865 sockunion2str(&path->peer->su,
9866 buf,
9867 SU_ADDRSTRLEN));
9868 json_object_string_add(json_peer, "routerId",
9869 inet_ntop(AF_INET,
9870 &path->peer->remote_id,
9871 buf1, sizeof(buf1)));
9872
9873 if (path->peer->hostname)
9874 json_object_string_add(json_peer, "hostname",
9875 path->peer->hostname);
9876
9877 if (path->peer->domainname)
9878 json_object_string_add(json_peer, "domainname",
9879 path->peer->domainname);
9880
9881 if (path->peer->conf_if)
9882 json_object_string_add(json_peer, "interface",
9883 path->peer->conf_if);
9884 } else {
9885 if (path->peer->conf_if) {
9886 if (path->peer->hostname
9887 && CHECK_FLAG(path->peer->bgp->flags,
9888 BGP_FLAG_SHOW_HOSTNAME))
9889 vty_out(vty, " from %s(%s)",
9890 path->peer->hostname,
9891 path->peer->conf_if);
9892 else
9893 vty_out(vty, " from %s",
9894 path->peer->conf_if);
9895 } else {
9896 if (path->peer->hostname
9897 && CHECK_FLAG(path->peer->bgp->flags,
9898 BGP_FLAG_SHOW_HOSTNAME))
9899 vty_out(vty, " from %s(%s)",
9900 path->peer->hostname,
9901 path->peer->host);
9902 else
9903 vty_out(vty, " from %s",
9904 sockunion2str(&path->peer->su,
9905 buf,
9906 SU_ADDRSTRLEN));
9907 }
9908
9909 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
9910 vty_out(vty, " (%pI4)", &attr->originator_id);
9911 else
9912 vty_out(vty, " (%s)",
9913 inet_ntop(AF_INET,
9914 &path->peer->remote_id, buf1,
9915 sizeof(buf1)));
9916 }
9917 }
9918
9919 /*
9920 * Note when vrfid of nexthop is different from that of prefix
9921 */
9922 if (path->extra && path->extra->bgp_orig) {
9923 vrf_id_t nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9924
9925 if (json_paths) {
9926 const char *vn;
9927
9928 if (path->extra->bgp_orig->inst_type
9929 == BGP_INSTANCE_TYPE_DEFAULT)
9930 vn = VRF_DEFAULT_NAME;
9931 else
9932 vn = path->extra->bgp_orig->name;
9933
9934 json_object_string_add(json_path, "nhVrfName", vn);
9935
9936 if (nexthop_vrfid == VRF_UNKNOWN) {
9937 json_object_int_add(json_path, "nhVrfId", -1);
9938 } else {
9939 json_object_int_add(json_path, "nhVrfId",
9940 (int)nexthop_vrfid);
9941 }
9942 } else {
9943 if (nexthop_vrfid == VRF_UNKNOWN)
9944 vty_out(vty, " vrf ?");
9945 else {
9946 struct vrf *vrf;
9947
9948 vrf = vrf_lookup_by_id(nexthop_vrfid);
9949 vty_out(vty, " vrf %s(%u)",
9950 VRF_LOGNAME(vrf), nexthop_vrfid);
9951 }
9952 }
9953 }
9954
9955 if (nexthop_self) {
9956 if (json_paths) {
9957 json_object_boolean_true_add(json_path,
9958 "announceNexthopSelf");
9959 } else {
9960 vty_out(vty, " announce-nh-self");
9961 }
9962 }
9963
9964 if (!json_paths)
9965 vty_out(vty, "\n");
9966
9967 /* display the link-local nexthop */
9968 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
9969 if (json_paths) {
9970 json_nexthop_ll = json_object_new_object();
9971 json_object_string_add(
9972 json_nexthop_ll, "ip",
9973 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
9974 buf, INET6_ADDRSTRLEN));
9975
9976 if (path->peer->hostname)
9977 json_object_string_add(json_nexthop_ll,
9978 "hostname",
9979 path->peer->hostname);
9980
9981 json_object_string_add(json_nexthop_ll, "afi", "ipv6");
9982 json_object_string_add(json_nexthop_ll, "scope",
9983 "link-local");
9984
9985 json_object_boolean_true_add(json_nexthop_ll,
9986 "accessible");
9987
9988 if (!attr->mp_nexthop_prefer_global)
9989 json_object_boolean_true_add(json_nexthop_ll,
9990 "used");
9991 else
9992 json_object_boolean_true_add(
9993 json_nexthop_global, "used");
9994 } else {
9995 vty_out(vty, " (%s) %s\n",
9996 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
9997 buf, INET6_ADDRSTRLEN),
9998 attr->mp_nexthop_prefer_global
9999 ? "(prefer-global)"
10000 : "(used)");
10001 }
10002 }
10003 /* If we do not have a link-local nexthop then we must flag the
10004 global as "used" */
10005 else {
10006 if (json_paths)
10007 json_object_boolean_true_add(json_nexthop_global,
10008 "used");
10009 }
10010
10011 if (safi == SAFI_EVPN &&
10012 bgp_evpn_is_esi_valid(&attr->esi)) {
10013 route_vty_out_detail_es_info(vty, path, attr, json_path);
10014 }
10015
10016 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
10017 * Int/Ext/Local, Atomic, best */
10018 if (json_paths)
10019 json_object_string_add(json_path, "origin",
10020 bgp_origin_long_str[attr->origin]);
10021 else
10022 vty_out(vty, " Origin %s",
10023 bgp_origin_long_str[attr->origin]);
10024
10025 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
10026 if (json_paths)
10027 json_object_int_add(json_path, "metric", attr->med);
10028 else
10029 vty_out(vty, ", metric %u", attr->med);
10030 }
10031
10032 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
10033 if (json_paths)
10034 json_object_int_add(json_path, "locPrf",
10035 attr->local_pref);
10036 else
10037 vty_out(vty, ", localpref %u", attr->local_pref);
10038 }
10039
10040 if (attr->weight != 0) {
10041 if (json_paths)
10042 json_object_int_add(json_path, "weight", attr->weight);
10043 else
10044 vty_out(vty, ", weight %u", attr->weight);
10045 }
10046
10047 if (attr->tag != 0) {
10048 if (json_paths)
10049 json_object_int_add(json_path, "tag", attr->tag);
10050 else
10051 vty_out(vty, ", tag %" ROUTE_TAG_PRI, attr->tag);
10052 }
10053
10054 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
10055 if (json_paths)
10056 json_object_boolean_false_add(json_path, "valid");
10057 else
10058 vty_out(vty, ", invalid");
10059 } else if (!CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
10060 if (json_paths)
10061 json_object_boolean_true_add(json_path, "valid");
10062 else
10063 vty_out(vty, ", valid");
10064 }
10065
10066 if (path->peer != bgp->peer_self) {
10067 if (path->peer->as == path->peer->local_as) {
10068 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
10069 if (json_paths)
10070 json_object_string_add(
10071 json_peer, "type",
10072 "confed-internal");
10073 else
10074 vty_out(vty, ", confed-internal");
10075 } else {
10076 if (json_paths)
10077 json_object_string_add(
10078 json_peer, "type", "internal");
10079 else
10080 vty_out(vty, ", internal");
10081 }
10082 } else {
10083 if (bgp_confederation_peers_check(bgp,
10084 path->peer->as)) {
10085 if (json_paths)
10086 json_object_string_add(
10087 json_peer, "type",
10088 "confed-external");
10089 else
10090 vty_out(vty, ", confed-external");
10091 } else {
10092 if (json_paths)
10093 json_object_string_add(
10094 json_peer, "type", "external");
10095 else
10096 vty_out(vty, ", external");
10097 }
10098 }
10099 } else if (path->sub_type == BGP_ROUTE_AGGREGATE) {
10100 if (json_paths) {
10101 json_object_boolean_true_add(json_path, "aggregated");
10102 json_object_boolean_true_add(json_path, "local");
10103 } else {
10104 vty_out(vty, ", aggregated, local");
10105 }
10106 } else if (path->type != ZEBRA_ROUTE_BGP) {
10107 if (json_paths)
10108 json_object_boolean_true_add(json_path, "sourced");
10109 else
10110 vty_out(vty, ", sourced");
10111 } else {
10112 if (json_paths) {
10113 json_object_boolean_true_add(json_path, "sourced");
10114 json_object_boolean_true_add(json_path, "local");
10115 } else {
10116 vty_out(vty, ", sourced, local");
10117 }
10118 }
10119
10120 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
10121 if (json_paths)
10122 json_object_boolean_true_add(json_path,
10123 "atomicAggregate");
10124 else
10125 vty_out(vty, ", atomic-aggregate");
10126 }
10127
10128 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH)
10129 || (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)
10130 && bgp_path_info_mpath_count(path))) {
10131 if (json_paths)
10132 json_object_boolean_true_add(json_path, "multipath");
10133 else
10134 vty_out(vty, ", multipath");
10135 }
10136
10137 // Mark the bestpath(s)
10138 if (CHECK_FLAG(path->flags, BGP_PATH_DMED_SELECTED)) {
10139 first_as = aspath_get_first_as(attr->aspath);
10140
10141 if (json_paths) {
10142 if (!json_bestpath)
10143 json_bestpath = json_object_new_object();
10144 json_object_int_add(json_bestpath, "bestpathFromAs",
10145 first_as);
10146 } else {
10147 if (first_as)
10148 vty_out(vty, ", bestpath-from-AS %u", first_as);
10149 else
10150 vty_out(vty, ", bestpath-from-AS Local");
10151 }
10152 }
10153
10154 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
10155 if (json_paths) {
10156 if (!json_bestpath)
10157 json_bestpath = json_object_new_object();
10158 json_object_boolean_true_add(json_bestpath, "overall");
10159 json_object_string_add(
10160 json_bestpath, "selectionReason",
10161 bgp_path_selection_reason2str(bn->reason));
10162 } else {
10163 vty_out(vty, ", best");
10164 vty_out(vty, " (%s)",
10165 bgp_path_selection_reason2str(bn->reason));
10166 }
10167 }
10168
10169 if (json_bestpath)
10170 json_object_object_add(json_path, "bestpath", json_bestpath);
10171
10172 if (!json_paths)
10173 vty_out(vty, "\n");
10174
10175 /* Line 4 display Community */
10176 if (attr->community) {
10177 if (json_paths) {
10178 if (!attr->community->json)
10179 community_str(attr->community, true);
10180 json_object_lock(attr->community->json);
10181 json_object_object_add(json_path, "community",
10182 attr->community->json);
10183 } else {
10184 vty_out(vty, " Community: %s\n",
10185 attr->community->str);
10186 }
10187 }
10188
10189 /* Line 5 display Extended-community */
10190 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
10191 if (json_paths) {
10192 json_ext_community = json_object_new_object();
10193 json_object_string_add(json_ext_community, "string",
10194 attr->ecommunity->str);
10195 json_object_object_add(json_path, "extendedCommunity",
10196 json_ext_community);
10197 } else {
10198 vty_out(vty, " Extended Community: %s\n",
10199 attr->ecommunity->str);
10200 }
10201 }
10202
10203 /* Line 6 display Large community */
10204 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
10205 if (json_paths) {
10206 if (!attr->lcommunity->json)
10207 lcommunity_str(attr->lcommunity, true);
10208 json_object_lock(attr->lcommunity->json);
10209 json_object_object_add(json_path, "largeCommunity",
10210 attr->lcommunity->json);
10211 } else {
10212 vty_out(vty, " Large Community: %s\n",
10213 attr->lcommunity->str);
10214 }
10215 }
10216
10217 /* Line 7 display Originator, Cluster-id */
10218 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
10219 || (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) {
10220 char buf[BUFSIZ] = {0};
10221
10222 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) {
10223 if (json_paths)
10224 json_object_string_add(
10225 json_path, "originatorId",
10226 inet_ntop(AF_INET, &attr->originator_id,
10227 buf, sizeof(buf)));
10228 else
10229 vty_out(vty, " Originator: %pI4",
10230 &attr->originator_id);
10231 }
10232
10233 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) {
10234 struct cluster_list *cluster =
10235 bgp_attr_get_cluster(attr);
10236 int i;
10237
10238 if (json_paths) {
10239 json_cluster_list = json_object_new_object();
10240 json_cluster_list_list =
10241 json_object_new_array();
10242
10243 for (i = 0; i < cluster->length / 4; i++) {
10244 json_string = json_object_new_string(
10245 inet_ntop(AF_INET,
10246 &cluster->list[i],
10247 buf, sizeof(buf)));
10248 json_object_array_add(
10249 json_cluster_list_list,
10250 json_string);
10251 }
10252
10253 /*
10254 * struct cluster_list does not have
10255 * "str" variable like aspath and community
10256 * do. Add this someday if someone asks
10257 * for it.
10258 * json_object_string_add(json_cluster_list,
10259 * "string", cluster->str);
10260 */
10261 json_object_object_add(json_cluster_list,
10262 "list",
10263 json_cluster_list_list);
10264 json_object_object_add(json_path, "clusterList",
10265 json_cluster_list);
10266 } else {
10267 vty_out(vty, ", Cluster list: ");
10268
10269 for (i = 0; i < cluster->length / 4; i++) {
10270 vty_out(vty, "%pI4 ",
10271 &cluster->list[i]);
10272 }
10273 }
10274 }
10275
10276 if (!json_paths)
10277 vty_out(vty, "\n");
10278 }
10279
10280 if (path->extra && path->extra->damp_info)
10281 bgp_damp_info_vty(vty, bgp, path, afi, safi, json_path);
10282
10283 /* Remote Label */
10284 if (path->extra && bgp_is_valid_label(&path->extra->label[0])
10285 && (safi != SAFI_EVPN && !is_route_parent_evpn(path))) {
10286 mpls_label_t label = label_pton(&path->extra->label[0]);
10287
10288 if (json_paths)
10289 json_object_int_add(json_path, "remoteLabel", label);
10290 else
10291 vty_out(vty, " Remote label: %d\n", label);
10292 }
10293
10294 /* Remote SID */
10295 if (path->extra && path->extra->num_sids > 0 && safi != SAFI_EVPN) {
10296 inet_ntop(AF_INET6, &path->extra->sid, buf, sizeof(buf));
10297 if (json_paths)
10298 json_object_string_add(json_path, "remoteSid", buf);
10299 else
10300 vty_out(vty, " Remote SID: %s\n", buf);
10301 }
10302
10303 /* Label Index */
10304 if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
10305 if (json_paths)
10306 json_object_int_add(json_path, "labelIndex",
10307 attr->label_index);
10308 else
10309 vty_out(vty, " Label Index: %d\n",
10310 attr->label_index);
10311 }
10312
10313 /* Line 8 display Addpath IDs */
10314 if (path->addpath_rx_id
10315 || bgp_addpath_info_has_ids(&path->tx_addpath)) {
10316 if (json_paths) {
10317 json_object_int_add(json_path, "addpathRxId",
10318 path->addpath_rx_id);
10319
10320 /* Keep backwards compatibility with the old API
10321 * by putting TX All's ID in the old field
10322 */
10323 json_object_int_add(
10324 json_path, "addpathTxId",
10325 path->tx_addpath
10326 .addpath_tx_id[BGP_ADDPATH_ALL]);
10327
10328 /* ... but create a specific field for each
10329 * strategy
10330 */
10331 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
10332 json_object_int_add(
10333 json_path,
10334 bgp_addpath_names(i)->id_json_name,
10335 path->tx_addpath.addpath_tx_id[i]);
10336 }
10337 } else {
10338 vty_out(vty, " AddPath ID: RX %u, ",
10339 path->addpath_rx_id);
10340
10341 route_vty_out_tx_ids(vty, &path->tx_addpath);
10342 }
10343 }
10344
10345 /* If we used addpath to TX a non-bestpath we need to display
10346 * "Advertised to" on a path-by-path basis
10347 */
10348 if (bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
10349 first = 1;
10350
10351 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
10352 addpath_capable =
10353 bgp_addpath_encode_tx(peer, afi, safi);
10354 has_adj = bgp_adj_out_lookup(
10355 peer, path->net,
10356 bgp_addpath_id_for_peer(peer, afi, safi,
10357 &path->tx_addpath));
10358
10359 if ((addpath_capable && has_adj)
10360 || (!addpath_capable && has_adj
10361 && CHECK_FLAG(path->flags,
10362 BGP_PATH_SELECTED))) {
10363 if (json_path && !json_adv_to)
10364 json_adv_to = json_object_new_object();
10365
10366 route_vty_out_advertised_to(
10367 vty, peer, &first,
10368 " Advertised to:", json_adv_to);
10369 }
10370 }
10371
10372 if (json_path) {
10373 if (json_adv_to) {
10374 json_object_object_add(
10375 json_path, "advertisedTo", json_adv_to);
10376 }
10377 } else {
10378 if (!first) {
10379 vty_out(vty, "\n");
10380 }
10381 }
10382 }
10383
10384 /* Line 9 display Uptime */
10385 tbuf = time(NULL) - (bgp_clock() - path->uptime);
10386 if (json_paths) {
10387 json_last_update = json_object_new_object();
10388 json_object_int_add(json_last_update, "epoch", tbuf);
10389 json_object_string_add(json_last_update, "string",
10390 ctime(&tbuf));
10391 json_object_object_add(json_path, "lastUpdate",
10392 json_last_update);
10393 } else
10394 vty_out(vty, " Last update: %s", ctime(&tbuf));
10395
10396 /* Line 10 display PMSI tunnel attribute, if present */
10397 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
10398 const char *str = lookup_msg(bgp_pmsi_tnltype_str,
10399 bgp_attr_get_pmsi_tnl_type(attr),
10400 PMSI_TNLTYPE_STR_DEFAULT);
10401
10402 if (json_paths) {
10403 json_pmsi = json_object_new_object();
10404 json_object_string_add(json_pmsi, "tunnelType", str);
10405 json_object_int_add(json_pmsi, "label",
10406 label2vni(&attr->label));
10407 json_object_object_add(json_path, "pmsi", json_pmsi);
10408 } else
10409 vty_out(vty, " PMSI Tunnel Type: %s, label: %d\n",
10410 str, label2vni(&attr->label));
10411 }
10412
10413 /* Output some debug about internal state of the dest flags */
10414 if (json_paths) {
10415 if (CHECK_FLAG(bn->flags, BGP_NODE_PROCESS_SCHEDULED))
10416 json_object_boolean_true_add(json_path, "processScheduled");
10417 if (CHECK_FLAG(bn->flags, BGP_NODE_USER_CLEAR))
10418 json_object_boolean_true_add(json_path, "userCleared");
10419 if (CHECK_FLAG(bn->flags, BGP_NODE_LABEL_CHANGED))
10420 json_object_boolean_true_add(json_path, "labelChanged");
10421 if (CHECK_FLAG(bn->flags, BGP_NODE_REGISTERED_FOR_LABEL))
10422 json_object_boolean_true_add(json_path, "registeredForLabel");
10423 if (CHECK_FLAG(bn->flags, BGP_NODE_SELECT_DEFER))
10424 json_object_boolean_true_add(json_path, "selectDefered");
10425 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALLED))
10426 json_object_boolean_true_add(json_path, "fibInstalled");
10427 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALL_PENDING))
10428 json_object_boolean_true_add(json_path, "fibPending");
10429 }
10430
10431 /* We've constructed the json object for this path, add it to the json
10432 * array of paths
10433 */
10434 if (json_paths) {
10435 if (json_nexthop_global || json_nexthop_ll) {
10436 json_nexthops = json_object_new_array();
10437
10438 if (json_nexthop_global)
10439 json_object_array_add(json_nexthops,
10440 json_nexthop_global);
10441
10442 if (json_nexthop_ll)
10443 json_object_array_add(json_nexthops,
10444 json_nexthop_ll);
10445
10446 json_object_object_add(json_path, "nexthops",
10447 json_nexthops);
10448 }
10449
10450 json_object_object_add(json_path, "peer", json_peer);
10451 json_object_array_add(json_paths, json_path);
10452 }
10453 }
10454
10455 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
10456 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
10457 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
10458
10459 static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
10460 const char *prefix_list_str, afi_t afi,
10461 safi_t safi, enum bgp_show_type type);
10462 static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
10463 const char *filter, afi_t afi, safi_t safi,
10464 enum bgp_show_type type);
10465 static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
10466 const char *rmap_str, afi_t afi, safi_t safi,
10467 enum bgp_show_type type);
10468 static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
10469 const char *com, int exact, afi_t afi,
10470 safi_t safi);
10471 static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
10472 const char *prefix, afi_t afi, safi_t safi,
10473 enum bgp_show_type type);
10474 static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
10475 afi_t afi, safi_t safi, enum bgp_show_type type,
10476 bool use_json);
10477 static int bgp_show_community(struct vty *vty, struct bgp *bgp,
10478 const char *comstr, int exact, afi_t afi,
10479 safi_t safi, uint8_t show_flags);
10480
10481
10482 static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
10483 struct bgp_table *table, enum bgp_show_type type,
10484 void *output_arg, char *rd, int is_last,
10485 unsigned long *output_cum, unsigned long *total_cum,
10486 unsigned long *json_header_depth, uint8_t show_flags)
10487 {
10488 struct bgp_path_info *pi;
10489 struct bgp_dest *dest;
10490 int header = 1;
10491 int display;
10492 unsigned long output_count = 0;
10493 unsigned long total_count = 0;
10494 struct prefix *p;
10495 json_object *json_paths = NULL;
10496 int first = 1;
10497 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
10498 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
10499 bool all = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
10500
10501 if (output_cum && *output_cum != 0)
10502 header = 0;
10503
10504 if (use_json && !*json_header_depth) {
10505 if (all)
10506 *json_header_depth = 1;
10507 else {
10508 vty_out(vty, "{\n");
10509 *json_header_depth = 2;
10510 }
10511
10512 vty_out(vty,
10513 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
10514 ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
10515 " \"localAS\": %u,\n \"routes\": { ",
10516 bgp->vrf_id == VRF_UNKNOWN ? -1 : (int)bgp->vrf_id,
10517 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
10518 ? VRF_DEFAULT_NAME
10519 : bgp->name,
10520 table->version, &bgp->router_id,
10521 bgp->default_local_pref, bgp->as);
10522 if (rd) {
10523 vty_out(vty, " \"routeDistinguishers\" : {");
10524 ++*json_header_depth;
10525 }
10526 }
10527
10528 if (use_json && rd) {
10529 vty_out(vty, " \"%s\" : { ", rd);
10530 }
10531
10532 /* Start processing of routes. */
10533 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
10534 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
10535
10536 pi = bgp_dest_get_bgp_path_info(dest);
10537 if (pi == NULL)
10538 continue;
10539
10540 display = 0;
10541 if (use_json)
10542 json_paths = json_object_new_array();
10543 else
10544 json_paths = NULL;
10545
10546 for (; pi; pi = pi->next) {
10547 total_count++;
10548 if (type == bgp_show_type_flap_statistics
10549 || type == bgp_show_type_flap_neighbor
10550 || type == bgp_show_type_dampend_paths
10551 || type == bgp_show_type_damp_neighbor) {
10552 if (!(pi->extra && pi->extra->damp_info))
10553 continue;
10554 }
10555 if (type == bgp_show_type_regexp) {
10556 regex_t *regex = output_arg;
10557
10558 if (bgp_regexec(regex, pi->attr->aspath)
10559 == REG_NOMATCH)
10560 continue;
10561 }
10562 if (type == bgp_show_type_prefix_list) {
10563 struct prefix_list *plist = output_arg;
10564
10565 if (prefix_list_apply(plist, dest_p)
10566 != PREFIX_PERMIT)
10567 continue;
10568 }
10569 if (type == bgp_show_type_filter_list) {
10570 struct as_list *as_list = output_arg;
10571
10572 if (as_list_apply(as_list, pi->attr->aspath)
10573 != AS_FILTER_PERMIT)
10574 continue;
10575 }
10576 if (type == bgp_show_type_route_map) {
10577 struct route_map *rmap = output_arg;
10578 struct bgp_path_info path;
10579 struct attr dummy_attr;
10580 route_map_result_t ret;
10581
10582 dummy_attr = *pi->attr;
10583
10584 path.peer = pi->peer;
10585 path.attr = &dummy_attr;
10586
10587 ret = route_map_apply(rmap, dest_p, &path);
10588 if (ret == RMAP_DENYMATCH)
10589 continue;
10590 }
10591 if (type == bgp_show_type_neighbor
10592 || type == bgp_show_type_flap_neighbor
10593 || type == bgp_show_type_damp_neighbor) {
10594 union sockunion *su = output_arg;
10595
10596 if (pi->peer == NULL
10597 || pi->peer->su_remote == NULL
10598 || !sockunion_same(pi->peer->su_remote, su))
10599 continue;
10600 }
10601 if (type == bgp_show_type_cidr_only) {
10602 uint32_t destination;
10603
10604 destination = ntohl(dest_p->u.prefix4.s_addr);
10605 if (IN_CLASSC(destination)
10606 && dest_p->prefixlen == 24)
10607 continue;
10608 if (IN_CLASSB(destination)
10609 && dest_p->prefixlen == 16)
10610 continue;
10611 if (IN_CLASSA(destination)
10612 && dest_p->prefixlen == 8)
10613 continue;
10614 }
10615 if (type == bgp_show_type_prefix_longer) {
10616 p = output_arg;
10617 if (!prefix_match(p, dest_p))
10618 continue;
10619 }
10620 if (type == bgp_show_type_community_all) {
10621 if (!pi->attr->community)
10622 continue;
10623 }
10624 if (type == bgp_show_type_community) {
10625 struct community *com = output_arg;
10626
10627 if (!pi->attr->community
10628 || !community_match(pi->attr->community,
10629 com))
10630 continue;
10631 }
10632 if (type == bgp_show_type_community_exact) {
10633 struct community *com = output_arg;
10634
10635 if (!pi->attr->community
10636 || !community_cmp(pi->attr->community, com))
10637 continue;
10638 }
10639 if (type == bgp_show_type_community_list) {
10640 struct community_list *list = output_arg;
10641
10642 if (!community_list_match(pi->attr->community,
10643 list))
10644 continue;
10645 }
10646 if (type == bgp_show_type_community_list_exact) {
10647 struct community_list *list = output_arg;
10648
10649 if (!community_list_exact_match(
10650 pi->attr->community, list))
10651 continue;
10652 }
10653 if (type == bgp_show_type_lcommunity) {
10654 struct lcommunity *lcom = output_arg;
10655
10656 if (!pi->attr->lcommunity
10657 || !lcommunity_match(pi->attr->lcommunity,
10658 lcom))
10659 continue;
10660 }
10661
10662 if (type == bgp_show_type_lcommunity_exact) {
10663 struct lcommunity *lcom = output_arg;
10664
10665 if (!pi->attr->lcommunity
10666 || !lcommunity_cmp(pi->attr->lcommunity,
10667 lcom))
10668 continue;
10669 }
10670 if (type == bgp_show_type_lcommunity_list) {
10671 struct community_list *list = output_arg;
10672
10673 if (!lcommunity_list_match(pi->attr->lcommunity,
10674 list))
10675 continue;
10676 }
10677 if (type
10678 == bgp_show_type_lcommunity_list_exact) {
10679 struct community_list *list = output_arg;
10680
10681 if (!lcommunity_list_exact_match(
10682 pi->attr->lcommunity, list))
10683 continue;
10684 }
10685 if (type == bgp_show_type_lcommunity_all) {
10686 if (!pi->attr->lcommunity)
10687 continue;
10688 }
10689 if (type == bgp_show_type_dampend_paths
10690 || type == bgp_show_type_damp_neighbor) {
10691 if (!CHECK_FLAG(pi->flags, BGP_PATH_DAMPED)
10692 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
10693 continue;
10694 }
10695
10696 if (!use_json && header) {
10697 vty_out(vty,
10698 "BGP table version is %" PRIu64
10699 ", local router ID is %pI4, vrf id ",
10700 table->version, &bgp->router_id);
10701 if (bgp->vrf_id == VRF_UNKNOWN)
10702 vty_out(vty, "%s", VRFID_NONE_STR);
10703 else
10704 vty_out(vty, "%u", bgp->vrf_id);
10705 vty_out(vty, "\n");
10706 vty_out(vty, "Default local pref %u, ",
10707 bgp->default_local_pref);
10708 vty_out(vty, "local AS %u\n", bgp->as);
10709 vty_out(vty, BGP_SHOW_SCODE_HEADER);
10710 vty_out(vty, BGP_SHOW_NCODE_HEADER);
10711 vty_out(vty, BGP_SHOW_OCODE_HEADER);
10712 if (type == bgp_show_type_dampend_paths
10713 || type == bgp_show_type_damp_neighbor)
10714 vty_out(vty, BGP_SHOW_DAMP_HEADER);
10715 else if (type == bgp_show_type_flap_statistics
10716 || type == bgp_show_type_flap_neighbor)
10717 vty_out(vty, BGP_SHOW_FLAP_HEADER);
10718 else
10719 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
10720 : BGP_SHOW_HEADER));
10721 header = 0;
10722 }
10723 if (rd != NULL && !display && !output_count) {
10724 if (!use_json)
10725 vty_out(vty,
10726 "Route Distinguisher: %s\n",
10727 rd);
10728 }
10729 if (type == bgp_show_type_dampend_paths
10730 || type == bgp_show_type_damp_neighbor)
10731 damp_route_vty_out(vty, dest_p, pi, display,
10732 AFI_IP, safi, use_json,
10733 json_paths);
10734 else if (type == bgp_show_type_flap_statistics
10735 || type == bgp_show_type_flap_neighbor)
10736 flap_route_vty_out(vty, dest_p, pi, display,
10737 AFI_IP, safi, use_json,
10738 json_paths);
10739 else
10740 route_vty_out(vty, dest_p, pi, display, safi,
10741 json_paths, wide);
10742 display++;
10743 }
10744
10745 if (display) {
10746 output_count++;
10747 if (!use_json)
10748 continue;
10749
10750 /* encode prefix */
10751 if (dest_p->family == AF_FLOWSPEC) {
10752 char retstr[BGP_FLOWSPEC_STRING_DISPLAY_MAX];
10753
10754
10755 bgp_fs_nlri_get_string(
10756 (unsigned char *)
10757 dest_p->u.prefix_flowspec.ptr,
10758 dest_p->u.prefix_flowspec.prefixlen,
10759 retstr, NLRI_STRING_FORMAT_MIN, NULL,
10760 family2afi(dest_p->u
10761 .prefix_flowspec.family));
10762 if (first)
10763 vty_out(vty, "\"%s/%d\": ", retstr,
10764 dest_p->u.prefix_flowspec
10765 .prefixlen);
10766 else
10767 vty_out(vty, ",\"%s/%d\": ", retstr,
10768 dest_p->u.prefix_flowspec
10769 .prefixlen);
10770 } else {
10771 if (first)
10772 vty_out(vty, "\"%pFX\": ", dest_p);
10773 else
10774 vty_out(vty, ",\"%pFX\": ", dest_p);
10775 }
10776 vty_out(vty, "%s",
10777 json_object_to_json_string_ext(
10778 json_paths, JSON_C_TO_STRING_PRETTY));
10779 json_object_free(json_paths);
10780 json_paths = NULL;
10781 first = 0;
10782 } else
10783 json_object_free(json_paths);
10784 }
10785
10786 if (output_cum) {
10787 output_count += *output_cum;
10788 *output_cum = output_count;
10789 }
10790 if (total_cum) {
10791 total_count += *total_cum;
10792 *total_cum = total_count;
10793 }
10794 if (use_json) {
10795 if (rd) {
10796 vty_out(vty, " }%s ", (is_last ? "" : ","));
10797 }
10798 if (is_last) {
10799 unsigned long i;
10800 for (i = 0; i < *json_header_depth; ++i)
10801 vty_out(vty, " } ");
10802 if (!all)
10803 vty_out(vty, "\n");
10804 }
10805 } else {
10806 if (is_last) {
10807 /* No route is displayed */
10808 if (output_count == 0) {
10809 if (type == bgp_show_type_normal)
10810 vty_out(vty,
10811 "No BGP prefixes displayed, %ld exist\n",
10812 total_count);
10813 } else
10814 vty_out(vty,
10815 "\nDisplayed %ld routes and %ld total paths\n",
10816 output_count, total_count);
10817 }
10818 }
10819
10820 return CMD_SUCCESS;
10821 }
10822
10823 int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi,
10824 struct bgp_table *table, struct prefix_rd *prd_match,
10825 enum bgp_show_type type, void *output_arg, bool use_json)
10826 {
10827 struct bgp_dest *dest, *next;
10828 unsigned long output_cum = 0;
10829 unsigned long total_cum = 0;
10830 unsigned long json_header_depth = 0;
10831 struct bgp_table *itable;
10832 bool show_msg;
10833 uint8_t show_flags = 0;
10834
10835 show_msg = (!use_json && type == bgp_show_type_normal);
10836
10837 if (use_json)
10838 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
10839
10840 for (dest = bgp_table_top(table); dest; dest = next) {
10841 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
10842
10843 next = bgp_route_next(dest);
10844 if (prd_match && memcmp(dest_p->u.val, prd_match->val, 8) != 0)
10845 continue;
10846
10847 itable = bgp_dest_get_bgp_table_info(dest);
10848 if (itable != NULL) {
10849 struct prefix_rd prd;
10850 char rd[RD_ADDRSTRLEN];
10851
10852 memcpy(&prd, dest_p, sizeof(struct prefix_rd));
10853 prefix_rd2str(&prd, rd, sizeof(rd));
10854 bgp_show_table(vty, bgp, safi, itable, type, output_arg,
10855 rd, next == NULL, &output_cum,
10856 &total_cum, &json_header_depth,
10857 show_flags);
10858 if (next == NULL)
10859 show_msg = false;
10860 }
10861 }
10862 if (show_msg) {
10863 if (output_cum == 0)
10864 vty_out(vty, "No BGP prefixes displayed, %ld exist\n",
10865 total_cum);
10866 else
10867 vty_out(vty,
10868 "\nDisplayed %ld routes and %ld total paths\n",
10869 output_cum, total_cum);
10870 }
10871 return CMD_SUCCESS;
10872 }
10873 static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
10874 enum bgp_show_type type, void *output_arg,
10875 uint8_t show_flags)
10876 {
10877 struct bgp_table *table;
10878 unsigned long json_header_depth = 0;
10879 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
10880
10881 if (bgp == NULL) {
10882 bgp = bgp_get_default();
10883 }
10884
10885 if (bgp == NULL) {
10886 if (!use_json)
10887 vty_out(vty, "No BGP process is configured\n");
10888 else
10889 vty_out(vty, "{}\n");
10890 return CMD_WARNING;
10891 }
10892
10893 table = bgp->rib[afi][safi];
10894 /* use MPLS and ENCAP specific shows until they are merged */
10895 if (safi == SAFI_MPLS_VPN) {
10896 return bgp_show_table_rd(vty, bgp, safi, table, NULL, type,
10897 output_arg, use_json);
10898 }
10899
10900 if (safi == SAFI_FLOWSPEC && type == bgp_show_type_detail) {
10901 return bgp_show_table_flowspec(vty, bgp, afi, table, type,
10902 output_arg, use_json,
10903 1, NULL, NULL);
10904 }
10905 /* labeled-unicast routes live in the unicast table */
10906 else if (safi == SAFI_LABELED_UNICAST)
10907 safi = SAFI_UNICAST;
10908
10909 return bgp_show_table(vty, bgp, safi, table, type, output_arg, NULL, 1,
10910 NULL, NULL, &json_header_depth, show_flags);
10911 }
10912
10913 static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi,
10914 safi_t safi, uint8_t show_flags)
10915 {
10916 struct listnode *node, *nnode;
10917 struct bgp *bgp;
10918 int is_first = 1;
10919 bool route_output = false;
10920 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
10921
10922 if (use_json)
10923 vty_out(vty, "{\n");
10924
10925 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
10926 route_output = true;
10927 if (use_json) {
10928 if (!is_first)
10929 vty_out(vty, ",\n");
10930 else
10931 is_first = 0;
10932
10933 vty_out(vty, "\"%s\":",
10934 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
10935 ? VRF_DEFAULT_NAME
10936 : bgp->name);
10937 } else {
10938 vty_out(vty, "\nInstance %s:\n",
10939 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
10940 ? VRF_DEFAULT_NAME
10941 : bgp->name);
10942 }
10943 bgp_show(vty, bgp, afi, safi, bgp_show_type_normal, NULL,
10944 show_flags);
10945 }
10946
10947 if (use_json)
10948 vty_out(vty, "}\n");
10949 else if (!route_output)
10950 vty_out(vty, "%% BGP instance not found\n");
10951 }
10952
10953 /* Header of detailed BGP route information */
10954 void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
10955 struct bgp_dest *dest, struct prefix_rd *prd,
10956 afi_t afi, safi_t safi, json_object *json)
10957 {
10958 struct bgp_path_info *pi;
10959 const struct prefix *p;
10960 struct peer *peer;
10961 struct listnode *node, *nnode;
10962 char buf1[RD_ADDRSTRLEN];
10963 char prefix_str[BUFSIZ];
10964 int count = 0;
10965 int best = 0;
10966 int suppress = 0;
10967 int accept_own = 0;
10968 int route_filter_translated_v4 = 0;
10969 int route_filter_v4 = 0;
10970 int route_filter_translated_v6 = 0;
10971 int route_filter_v6 = 0;
10972 int llgr_stale = 0;
10973 int no_llgr = 0;
10974 int accept_own_nexthop = 0;
10975 int blackhole = 0;
10976 int no_export = 0;
10977 int no_advertise = 0;
10978 int local_as = 0;
10979 int no_peer = 0;
10980 int first = 1;
10981 int has_valid_label = 0;
10982 mpls_label_t label = 0;
10983 json_object *json_adv_to = NULL;
10984
10985 p = bgp_dest_get_prefix(dest);
10986 has_valid_label = bgp_is_valid_label(&dest->local_label);
10987
10988 if (has_valid_label)
10989 label = label_pton(&dest->local_label);
10990
10991 if (safi == SAFI_EVPN) {
10992
10993 if (!json) {
10994 vty_out(vty, "BGP routing table entry for %s%s%pFX\n",
10995 prd ? prefix_rd2str(prd, buf1, sizeof(buf1))
10996 : "",
10997 prd ? ":" : "", (struct prefix_evpn *)p);
10998 } else {
10999 json_object_string_add(json, "rd",
11000 prd ? prefix_rd2str(prd, buf1, sizeof(buf1)) :
11001 "");
11002 bgp_evpn_route2json((struct prefix_evpn *)p, json);
11003 }
11004 } else {
11005 if (!json) {
11006 vty_out(vty, "BGP routing table entry for %s%s%pFX\n",
11007 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
11008 ? prefix_rd2str(prd, buf1,
11009 sizeof(buf1))
11010 : ""),
11011 safi == SAFI_MPLS_VPN ? ":" : "", p);
11012
11013 } else
11014 json_object_string_add(json, "prefix",
11015 prefix2str(p, prefix_str, sizeof(prefix_str)));
11016 }
11017
11018 if (has_valid_label) {
11019 if (json)
11020 json_object_int_add(json, "localLabel", label);
11021 else
11022 vty_out(vty, "Local label: %d\n", label);
11023 }
11024
11025 if (!json)
11026 if (bgp_labeled_safi(safi) && safi != SAFI_EVPN)
11027 vty_out(vty, "not allocated\n");
11028
11029 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
11030 count++;
11031 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
11032 best = count;
11033 if (bgp_path_suppressed(pi))
11034 suppress = 1;
11035
11036 if (pi->attr->community == NULL)
11037 continue;
11038
11039 no_advertise += community_include(
11040 pi->attr->community, COMMUNITY_NO_ADVERTISE);
11041 no_export += community_include(pi->attr->community,
11042 COMMUNITY_NO_EXPORT);
11043 local_as += community_include(pi->attr->community,
11044 COMMUNITY_LOCAL_AS);
11045 accept_own += community_include(pi->attr->community,
11046 COMMUNITY_ACCEPT_OWN);
11047 route_filter_translated_v4 += community_include(
11048 pi->attr->community,
11049 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4);
11050 route_filter_translated_v6 += community_include(
11051 pi->attr->community,
11052 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6);
11053 route_filter_v4 += community_include(
11054 pi->attr->community, COMMUNITY_ROUTE_FILTER_v4);
11055 route_filter_v6 += community_include(
11056 pi->attr->community, COMMUNITY_ROUTE_FILTER_v6);
11057 llgr_stale += community_include(pi->attr->community,
11058 COMMUNITY_LLGR_STALE);
11059 no_llgr += community_include(pi->attr->community,
11060 COMMUNITY_NO_LLGR);
11061 accept_own_nexthop +=
11062 community_include(pi->attr->community,
11063 COMMUNITY_ACCEPT_OWN_NEXTHOP);
11064 blackhole += community_include(pi->attr->community,
11065 COMMUNITY_BLACKHOLE);
11066 no_peer += community_include(pi->attr->community,
11067 COMMUNITY_NO_PEER);
11068 }
11069 }
11070
11071 if (!json) {
11072 vty_out(vty, "Paths: (%d available", count);
11073 if (best) {
11074 vty_out(vty, ", best #%d", best);
11075 if (safi == SAFI_UNICAST) {
11076 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
11077 vty_out(vty, ", table %s",
11078 VRF_DEFAULT_NAME);
11079 else
11080 vty_out(vty, ", vrf %s",
11081 bgp->name);
11082 }
11083 } else
11084 vty_out(vty, ", no best path");
11085
11086 if (accept_own)
11087 vty_out(vty,
11088 ", accept own local route exported and imported in different VRF");
11089 else if (route_filter_translated_v4)
11090 vty_out(vty,
11091 ", mark translated RTs for VPNv4 route filtering");
11092 else if (route_filter_v4)
11093 vty_out(vty,
11094 ", attach RT as-is for VPNv4 route filtering");
11095 else if (route_filter_translated_v6)
11096 vty_out(vty,
11097 ", mark translated RTs for VPNv6 route filtering");
11098 else if (route_filter_v6)
11099 vty_out(vty,
11100 ", attach RT as-is for VPNv6 route filtering");
11101 else if (llgr_stale)
11102 vty_out(vty,
11103 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
11104 else if (no_llgr)
11105 vty_out(vty,
11106 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
11107 else if (accept_own_nexthop)
11108 vty_out(vty,
11109 ", accept local nexthop");
11110 else if (blackhole)
11111 vty_out(vty, ", inform peer to blackhole prefix");
11112 else if (no_export)
11113 vty_out(vty, ", not advertised to EBGP peer");
11114 else if (no_advertise)
11115 vty_out(vty, ", not advertised to any peer");
11116 else if (local_as)
11117 vty_out(vty, ", not advertised outside local AS");
11118 else if (no_peer)
11119 vty_out(vty,
11120 ", inform EBGP peer not to advertise to their EBGP peers");
11121
11122 if (suppress)
11123 vty_out(vty,
11124 ", Advertisements suppressed by an aggregate.");
11125 vty_out(vty, ")\n");
11126 }
11127
11128 /* If we are not using addpath then we can display Advertised to and
11129 * that will
11130 * show what peers we advertised the bestpath to. If we are using
11131 * addpath
11132 * though then we must display Advertised to on a path-by-path basis. */
11133 if (!bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
11134 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
11135 if (bgp_adj_out_lookup(peer, dest, 0)) {
11136 if (json && !json_adv_to)
11137 json_adv_to = json_object_new_object();
11138
11139 route_vty_out_advertised_to(
11140 vty, peer, &first,
11141 " Advertised to non peer-group peers:\n ",
11142 json_adv_to);
11143 }
11144 }
11145
11146 if (json) {
11147 if (json_adv_to) {
11148 json_object_object_add(json, "advertisedTo",
11149 json_adv_to);
11150 }
11151 } else {
11152 if (first)
11153 vty_out(vty, " Not advertised to any peer");
11154 vty_out(vty, "\n");
11155 }
11156 }
11157 }
11158
11159 static void bgp_show_path_info(struct prefix_rd *pfx_rd,
11160 struct bgp_dest *bgp_node, struct vty *vty,
11161 struct bgp *bgp, afi_t afi, safi_t safi,
11162 json_object *json, enum bgp_path_type pathtype,
11163 int *display)
11164 {
11165 struct bgp_path_info *pi;
11166 int header = 1;
11167 char rdbuf[RD_ADDRSTRLEN];
11168 json_object *json_header = NULL;
11169 json_object *json_paths = NULL;
11170
11171 for (pi = bgp_dest_get_bgp_path_info(bgp_node); pi; pi = pi->next) {
11172
11173 if (json && !json_paths) {
11174 /* Instantiate json_paths only if path is valid */
11175 json_paths = json_object_new_array();
11176 if (pfx_rd) {
11177 prefix_rd2str(pfx_rd, rdbuf, sizeof(rdbuf));
11178 json_header = json_object_new_object();
11179 } else
11180 json_header = json;
11181 }
11182
11183 if (header) {
11184 route_vty_out_detail_header(
11185 vty, bgp, bgp_node, pfx_rd,
11186 AFI_IP, safi, json_header);
11187 header = 0;
11188 }
11189 (*display)++;
11190
11191 if (pathtype == BGP_PATH_SHOW_ALL
11192 || (pathtype == BGP_PATH_SHOW_BESTPATH
11193 && CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
11194 || (pathtype == BGP_PATH_SHOW_MULTIPATH
11195 && (CHECK_FLAG(pi->flags, BGP_PATH_MULTIPATH)
11196 || CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))))
11197 route_vty_out_detail(vty, bgp, bgp_node,
11198 pi, AFI_IP, safi,
11199 json_paths);
11200 }
11201
11202 if (json && json_paths) {
11203 json_object_object_add(json_header, "paths", json_paths);
11204
11205 if (pfx_rd)
11206 json_object_object_add(json, rdbuf, json_header);
11207 }
11208 }
11209
11210 /* Display specified route of BGP table. */
11211 static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
11212 struct bgp_table *rib, const char *ip_str,
11213 afi_t afi, safi_t safi,
11214 struct prefix_rd *prd, int prefix_check,
11215 enum bgp_path_type pathtype, bool use_json)
11216 {
11217 int ret;
11218 int display = 0;
11219 struct prefix match;
11220 struct bgp_dest *dest;
11221 struct bgp_dest *rm;
11222 struct bgp_table *table;
11223 json_object *json = NULL;
11224 json_object *json_paths = NULL;
11225
11226 /* Check IP address argument. */
11227 ret = str2prefix(ip_str, &match);
11228 if (!ret) {
11229 vty_out(vty, "address is malformed\n");
11230 return CMD_WARNING;
11231 }
11232
11233 match.family = afi2family(afi);
11234
11235 if (use_json)
11236 json = json_object_new_object();
11237
11238 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP) {
11239 for (dest = bgp_table_top(rib); dest;
11240 dest = bgp_route_next(dest)) {
11241 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
11242
11243 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
11244 continue;
11245 table = bgp_dest_get_bgp_table_info(dest);
11246 if (!table)
11247 continue;
11248
11249 if ((rm = bgp_node_match(table, &match)) == NULL)
11250 continue;
11251
11252 const struct prefix *rm_p = bgp_dest_get_prefix(rm);
11253 if (prefix_check
11254 && rm_p->prefixlen != match.prefixlen) {
11255 bgp_dest_unlock_node(rm);
11256 continue;
11257 }
11258
11259 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
11260 bgp, afi, safi, json, pathtype,
11261 &display);
11262
11263 bgp_dest_unlock_node(rm);
11264 }
11265 } else if (safi == SAFI_EVPN) {
11266 struct bgp_dest *longest_pfx;
11267 bool is_exact_pfxlen_match = false;
11268
11269 for (dest = bgp_table_top(rib); dest;
11270 dest = bgp_route_next(dest)) {
11271 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
11272
11273 if (prd && memcmp(&dest_p->u.val, prd->val, 8) != 0)
11274 continue;
11275 table = bgp_dest_get_bgp_table_info(dest);
11276 if (!table)
11277 continue;
11278
11279 longest_pfx = NULL;
11280 is_exact_pfxlen_match = false;
11281 /*
11282 * Search through all the prefixes for a match. The
11283 * pfx's are enumerated in ascending order of pfxlens.
11284 * So, the last pfx match is the longest match. Set
11285 * is_exact_pfxlen_match when we get exact pfxlen match
11286 */
11287 for (rm = bgp_table_top(table); rm;
11288 rm = bgp_route_next(rm)) {
11289 const struct prefix *rm_p =
11290 bgp_dest_get_prefix(rm);
11291 /*
11292 * Get prefixlen of the ip-prefix within type5
11293 * evpn route
11294 */
11295 if (evpn_type5_prefix_match(rm_p, &match)
11296 && rm->info) {
11297 longest_pfx = rm;
11298 int type5_pfxlen =
11299 bgp_evpn_get_type5_prefixlen(
11300 rm_p);
11301 if (type5_pfxlen == match.prefixlen) {
11302 is_exact_pfxlen_match = true;
11303 bgp_dest_unlock_node(rm);
11304 break;
11305 }
11306 }
11307 }
11308
11309 if (!longest_pfx)
11310 continue;
11311
11312 if (prefix_check && !is_exact_pfxlen_match)
11313 continue;
11314
11315 rm = longest_pfx;
11316 bgp_dest_lock_node(rm);
11317
11318 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
11319 bgp, afi, safi, json, pathtype,
11320 &display);
11321
11322 bgp_dest_unlock_node(rm);
11323 }
11324 } else if (safi == SAFI_FLOWSPEC) {
11325 if (use_json)
11326 json_paths = json_object_new_array();
11327
11328 display = bgp_flowspec_display_match_per_ip(afi, rib,
11329 &match, prefix_check,
11330 vty,
11331 use_json,
11332 json_paths);
11333 if (use_json) {
11334 if (display)
11335 json_object_object_add(json, "paths",
11336 json_paths);
11337 else
11338 json_object_free(json_paths);
11339 }
11340 } else {
11341 if ((dest = bgp_node_match(rib, &match)) != NULL) {
11342 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
11343 if (!prefix_check
11344 || dest_p->prefixlen == match.prefixlen) {
11345 bgp_show_path_info(NULL, dest, vty, bgp, afi,
11346 safi, json, pathtype,
11347 &display);
11348 }
11349
11350 bgp_dest_unlock_node(dest);
11351 }
11352 }
11353
11354 if (use_json) {
11355 vty_out(vty, "%s\n", json_object_to_json_string_ext(
11356 json, JSON_C_TO_STRING_PRETTY |
11357 JSON_C_TO_STRING_NOSLASHESCAPE));
11358 json_object_free(json);
11359 } else {
11360 if (!display) {
11361 vty_out(vty, "%% Network not in table\n");
11362 return CMD_WARNING;
11363 }
11364 }
11365
11366 return CMD_SUCCESS;
11367 }
11368
11369 /* Display specified route of Main RIB */
11370 static int bgp_show_route(struct vty *vty, struct bgp *bgp, const char *ip_str,
11371 afi_t afi, safi_t safi, struct prefix_rd *prd,
11372 int prefix_check, enum bgp_path_type pathtype,
11373 bool use_json)
11374 {
11375 if (!bgp) {
11376 bgp = bgp_get_default();
11377 if (!bgp) {
11378 if (!use_json)
11379 vty_out(vty, "No BGP process is configured\n");
11380 else
11381 vty_out(vty, "{}\n");
11382 return CMD_WARNING;
11383 }
11384 }
11385
11386 /* labeled-unicast routes live in the unicast table */
11387 if (safi == SAFI_LABELED_UNICAST)
11388 safi = SAFI_UNICAST;
11389
11390 return bgp_show_route_in_table(vty, bgp, bgp->rib[afi][safi], ip_str,
11391 afi, safi, prd, prefix_check, pathtype,
11392 use_json);
11393 }
11394
11395 static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc,
11396 struct cmd_token **argv, bool exact, afi_t afi,
11397 safi_t safi, bool uj)
11398 {
11399 struct lcommunity *lcom;
11400 struct buffer *b;
11401 int i;
11402 char *str;
11403 int first = 0;
11404 uint8_t show_flags = 0;
11405 int ret;
11406
11407 if (uj)
11408 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11409
11410 b = buffer_new(1024);
11411 for (i = 0; i < argc; i++) {
11412 if (first)
11413 buffer_putc(b, ' ');
11414 else {
11415 if (strmatch(argv[i]->text, "AA:BB:CC")) {
11416 first = 1;
11417 buffer_putstr(b, argv[i]->arg);
11418 }
11419 }
11420 }
11421 buffer_putc(b, '\0');
11422
11423 str = buffer_getstr(b);
11424 buffer_free(b);
11425
11426 lcom = lcommunity_str2com(str);
11427 XFREE(MTYPE_TMP, str);
11428 if (!lcom) {
11429 vty_out(vty, "%% Large-community malformed\n");
11430 return CMD_WARNING;
11431 }
11432
11433 ret = bgp_show(vty, bgp, afi, safi,
11434 (exact ? bgp_show_type_lcommunity_exact
11435 : bgp_show_type_lcommunity),
11436 lcom, show_flags);
11437
11438 lcommunity_free(&lcom);
11439 return ret;
11440 }
11441
11442 static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp,
11443 const char *lcom, bool exact, afi_t afi,
11444 safi_t safi, bool uj)
11445 {
11446 struct community_list *list;
11447 uint8_t show_flags = 0;
11448
11449 if (uj)
11450 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11451
11452
11453 list = community_list_lookup(bgp_clist, lcom, 0,
11454 LARGE_COMMUNITY_LIST_MASTER);
11455 if (list == NULL) {
11456 vty_out(vty, "%% %s is not a valid large-community-list name\n",
11457 lcom);
11458 return CMD_WARNING;
11459 }
11460
11461 return bgp_show(vty, bgp, afi, safi,
11462 (exact ? bgp_show_type_lcommunity_list_exact
11463 : bgp_show_type_lcommunity_list),
11464 list, show_flags);
11465 }
11466
11467 DEFUN (show_ip_bgp_large_community_list,
11468 show_ip_bgp_large_community_list_cmd,
11469 "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]",
11470 SHOW_STR
11471 IP_STR
11472 BGP_STR
11473 BGP_INSTANCE_HELP_STR
11474 BGP_AFI_HELP_STR
11475 BGP_SAFI_WITH_LABEL_HELP_STR
11476 "Display routes matching the large-community-list\n"
11477 "large-community-list number\n"
11478 "large-community-list name\n"
11479 "Exact match of the large-communities\n"
11480 JSON_STR)
11481 {
11482 afi_t afi = AFI_IP6;
11483 safi_t safi = SAFI_UNICAST;
11484 int idx = 0;
11485 bool exact_match = 0;
11486 struct bgp *bgp = NULL;
11487 bool uj = use_json(argc, argv);
11488
11489 if (uj)
11490 argc--;
11491
11492 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11493 &bgp, uj);
11494 if (!idx)
11495 return CMD_WARNING;
11496
11497 argv_find(argv, argc, "large-community-list", &idx);
11498
11499 const char *clist_number_or_name = argv[++idx]->arg;
11500
11501 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
11502 exact_match = 1;
11503
11504 return bgp_show_lcommunity_list(vty, bgp, clist_number_or_name,
11505 exact_match, afi, safi, uj);
11506 }
11507 DEFUN (show_ip_bgp_large_community,
11508 show_ip_bgp_large_community_cmd,
11509 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] large-community [<AA:BB:CC> [exact-match]] [json]",
11510 SHOW_STR
11511 IP_STR
11512 BGP_STR
11513 BGP_INSTANCE_HELP_STR
11514 BGP_AFI_HELP_STR
11515 BGP_SAFI_WITH_LABEL_HELP_STR
11516 "Display routes matching the large-communities\n"
11517 "List of large-community numbers\n"
11518 "Exact match of the large-communities\n"
11519 JSON_STR)
11520 {
11521 afi_t afi = AFI_IP6;
11522 safi_t safi = SAFI_UNICAST;
11523 int idx = 0;
11524 bool exact_match = 0;
11525 struct bgp *bgp = NULL;
11526 bool uj = use_json(argc, argv);
11527 uint8_t show_flags = 0;
11528
11529 if (uj) {
11530 argc--;
11531 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11532 }
11533
11534 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11535 &bgp, uj);
11536 if (!idx)
11537 return CMD_WARNING;
11538
11539 if (argv_find(argv, argc, "AA:BB:CC", &idx)) {
11540 if (argv_find(argv, argc, "exact-match", &idx))
11541 exact_match = 1;
11542 return bgp_show_lcommunity(vty, bgp, argc, argv,
11543 exact_match, afi, safi, uj);
11544 } else
11545 return bgp_show(vty, bgp, afi, safi,
11546 bgp_show_type_lcommunity_all, NULL, show_flags);
11547 }
11548
11549 static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
11550 safi_t safi, struct json_object *json_array);
11551 static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
11552 safi_t safi, struct json_object *json);
11553
11554
11555 DEFUN(show_ip_bgp_statistics_all, show_ip_bgp_statistics_all_cmd,
11556 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
11557 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
11558 "Display number of prefixes for all afi/safi\n" JSON_STR)
11559 {
11560 bool uj = use_json(argc, argv);
11561 struct bgp *bgp = NULL;
11562 safi_t safi = SAFI_UNICAST;
11563 afi_t afi = AFI_IP6;
11564 int idx = 0;
11565 struct json_object *json_all = NULL;
11566 struct json_object *json_afi_safi = NULL;
11567
11568 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11569 &bgp, false);
11570 if (!idx)
11571 return CMD_WARNING;
11572
11573 if (uj)
11574 json_all = json_object_new_object();
11575
11576 FOREACH_AFI_SAFI (afi, safi) {
11577 /*
11578 * So limit output to those afi/safi pairs that
11579 * actually have something interesting in them
11580 */
11581 if (strmatch(get_afi_safi_str(afi, safi, true),
11582 "Unknown")) {
11583 continue;
11584 }
11585 if (uj) {
11586 json_afi_safi = json_object_new_array();
11587 json_object_object_add(
11588 json_all,
11589 get_afi_safi_str(afi, safi, true),
11590 json_afi_safi);
11591 } else {
11592 json_afi_safi = NULL;
11593 }
11594
11595 bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
11596 }
11597
11598 if (uj) {
11599 vty_out(vty, "%s",
11600 json_object_to_json_string_ext(
11601 json_all, JSON_C_TO_STRING_PRETTY));
11602 json_object_free(json_all);
11603 }
11604
11605 return CMD_SUCCESS;
11606 }
11607
11608 /* BGP route print out function without JSON */
11609 DEFUN (show_ip_bgp_l2vpn_evpn_statistics,
11610 show_ip_bgp_l2vpn_evpn_statistics_cmd,
11611 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
11612 SHOW_STR
11613 IP_STR
11614 BGP_STR
11615 BGP_INSTANCE_HELP_STR
11616 L2VPN_HELP_STR
11617 EVPN_HELP_STR
11618 "BGP RIB advertisement statistics\n"
11619 JSON_STR)
11620 {
11621 afi_t afi = AFI_IP6;
11622 safi_t safi = SAFI_UNICAST;
11623 struct bgp *bgp = NULL;
11624 int idx = 0, ret;
11625 bool uj = use_json(argc, argv);
11626 struct json_object *json_afi_safi = NULL, *json = NULL;
11627
11628 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11629 &bgp, false);
11630 if (!idx)
11631 return CMD_WARNING;
11632
11633 if (uj)
11634 json_afi_safi = json_object_new_array();
11635 else
11636 json_afi_safi = NULL;
11637
11638 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
11639
11640 if (uj) {
11641 json = json_object_new_object();
11642 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
11643 json_afi_safi);
11644 vty_out(vty, "%s", json_object_to_json_string_ext(
11645 json, JSON_C_TO_STRING_PRETTY));
11646 json_object_free(json);
11647 }
11648 return ret;
11649 }
11650
11651 /* BGP route print out function without JSON */
11652 DEFUN(show_ip_bgp_afi_safi_statistics, show_ip_bgp_afi_safi_statistics_cmd,
11653 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
11654 " [" BGP_SAFI_WITH_LABEL_CMD_STR
11655 "]]\
11656 statistics [json]",
11657 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
11658 BGP_SAFI_WITH_LABEL_HELP_STR
11659 "BGP RIB advertisement statistics\n" JSON_STR)
11660 {
11661 afi_t afi = AFI_IP6;
11662 safi_t safi = SAFI_UNICAST;
11663 struct bgp *bgp = NULL;
11664 int idx = 0, ret;
11665 bool uj = use_json(argc, argv);
11666 struct json_object *json_afi_safi = NULL, *json = NULL;
11667
11668 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11669 &bgp, false);
11670 if (!idx)
11671 return CMD_WARNING;
11672
11673 if (uj)
11674 json_afi_safi = json_object_new_array();
11675 else
11676 json_afi_safi = NULL;
11677
11678 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
11679
11680 if (uj) {
11681 json = json_object_new_object();
11682 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
11683 json_afi_safi);
11684 vty_out(vty, "%s",
11685 json_object_to_json_string_ext(
11686 json, JSON_C_TO_STRING_PRETTY));
11687 json_object_free(json);
11688 }
11689 return ret;
11690 }
11691
11692 /* BGP route print out function without JSON */
11693 DEFPY(show_ip_bgp, show_ip_bgp_cmd,
11694 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
11695 " [" BGP_SAFI_WITH_LABEL_CMD_STR
11696 "]]\
11697 <[all$all] dampening <parameters>\
11698 |route-map WORD\
11699 |prefix-list WORD\
11700 |filter-list WORD\
11701 |community-list <(1-500)|WORD> [exact-match]\
11702 |A.B.C.D/M longer-prefixes\
11703 |X:X::X:X/M longer-prefixes\
11704 >",
11705 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
11706 BGP_SAFI_WITH_LABEL_HELP_STR
11707 "Display the entries for all address families\n"
11708 "Display detailed information about dampening\n"
11709 "Display detail of configured dampening parameters\n"
11710 "Display routes matching the route-map\n"
11711 "A route-map to match on\n"
11712 "Display routes conforming to the prefix-list\n"
11713 "Prefix-list name\n"
11714 "Display routes conforming to the filter-list\n"
11715 "Regular expression access list name\n"
11716 "Display routes matching the community-list\n"
11717 "community-list number\n"
11718 "community-list name\n"
11719 "Exact match of the communities\n"
11720 "IPv4 prefix\n"
11721 "Display route and more specific routes\n"
11722 "IPv6 prefix\n"
11723 "Display route and more specific routes\n")
11724 {
11725 afi_t afi = AFI_IP6;
11726 safi_t safi = SAFI_UNICAST;
11727 int exact_match = 0;
11728 struct bgp *bgp = NULL;
11729 int idx = 0;
11730 uint8_t show_flags = 0;
11731
11732 /* [<ipv4|ipv6> [all]] */
11733 if (all) {
11734 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
11735 if (argv_find(argv, argc, "ipv4", &idx))
11736 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
11737
11738 if (argv_find(argv, argc, "ipv6", &idx))
11739 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
11740 }
11741
11742 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11743 &bgp, false);
11744 if (!idx)
11745 return CMD_WARNING;
11746
11747 if (argv_find(argv, argc, "dampening", &idx)) {
11748 if (argv_find(argv, argc, "parameters", &idx))
11749 return bgp_show_dampening_parameters(vty, afi, safi,
11750 show_flags);
11751 }
11752
11753 if (argv_find(argv, argc, "prefix-list", &idx))
11754 return bgp_show_prefix_list(vty, bgp, argv[idx + 1]->arg, afi,
11755 safi, bgp_show_type_prefix_list);
11756
11757 if (argv_find(argv, argc, "filter-list", &idx))
11758 return bgp_show_filter_list(vty, bgp, argv[idx + 1]->arg, afi,
11759 safi, bgp_show_type_filter_list);
11760
11761 if (argv_find(argv, argc, "route-map", &idx))
11762 return bgp_show_route_map(vty, bgp, argv[idx + 1]->arg, afi,
11763 safi, bgp_show_type_route_map);
11764
11765 if (argv_find(argv, argc, "community-list", &idx)) {
11766 const char *clist_number_or_name = argv[++idx]->arg;
11767 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
11768 exact_match = 1;
11769 return bgp_show_community_list(vty, bgp, clist_number_or_name,
11770 exact_match, afi, safi);
11771 }
11772 /* prefix-longer */
11773 if (argv_find(argv, argc, "A.B.C.D/M", &idx)
11774 || argv_find(argv, argc, "X:X::X:X/M", &idx))
11775 return bgp_show_prefix_longer(vty, bgp, argv[idx]->arg, afi,
11776 safi,
11777 bgp_show_type_prefix_longer);
11778
11779 return CMD_WARNING;
11780 }
11781
11782 /* BGP route print out function with JSON */
11783 DEFPY (show_ip_bgp_json,
11784 show_ip_bgp_json_cmd,
11785 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]\
11786 [all$all]\
11787 [cidr-only\
11788 |dampening <flap-statistics|dampened-paths>\
11789 |community [AA:NN|local-AS|no-advertise|no-export\
11790 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
11791 |accept-own|accept-own-nexthop|route-filter-v6\
11792 |route-filter-v4|route-filter-translated-v6\
11793 |route-filter-translated-v4] [exact-match]\
11794 ] [json$uj | wide$wide]",
11795 SHOW_STR
11796 IP_STR
11797 BGP_STR
11798 BGP_INSTANCE_HELP_STR
11799 BGP_AFI_HELP_STR
11800 BGP_SAFI_WITH_LABEL_HELP_STR
11801 "Display the entries for all address families\n"
11802 "Display only routes with non-natural netmasks\n"
11803 "Display detailed information about dampening\n"
11804 "Display flap statistics of routes\n"
11805 "Display paths suppressed due to dampening\n"
11806 "Display routes matching the communities\n"
11807 COMMUNITY_AANN_STR
11808 "Do not send outside local AS (well-known community)\n"
11809 "Do not advertise to any peer (well-known community)\n"
11810 "Do not export to next AS (well-known community)\n"
11811 "Graceful shutdown (well-known community)\n"
11812 "Do not export to any peer (well-known community)\n"
11813 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
11814 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
11815 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
11816 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
11817 "Should accept VPN route with local nexthop (well-known community)\n"
11818 "RT VPNv6 route filtering (well-known community)\n"
11819 "RT VPNv4 route filtering (well-known community)\n"
11820 "RT translated VPNv6 route filtering (well-known community)\n"
11821 "RT translated VPNv4 route filtering (well-known community)\n"
11822 "Exact match of the communities\n"
11823 JSON_STR
11824 "Increase table width for longer prefixes\n")
11825 {
11826 afi_t afi = AFI_IP6;
11827 safi_t safi = SAFI_UNICAST;
11828 enum bgp_show_type sh_type = bgp_show_type_normal;
11829 struct bgp *bgp = NULL;
11830 int idx = 0;
11831 int exact_match = 0;
11832 char *community = NULL;
11833 bool first = true;
11834 uint8_t show_flags = 0;
11835
11836
11837 if (uj) {
11838 argc--;
11839 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11840 }
11841
11842 /* [<ipv4|ipv6> [all]] */
11843 if (all) {
11844 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
11845
11846 if (argv_find(argv, argc, "ipv4", &idx))
11847 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
11848
11849 if (argv_find(argv, argc, "ipv6", &idx))
11850 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
11851 }
11852
11853 if (wide)
11854 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
11855
11856 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11857 &bgp, uj);
11858 if (!idx)
11859 return CMD_WARNING;
11860
11861 if (argv_find(argv, argc, "cidr-only", &idx))
11862 sh_type = bgp_show_type_cidr_only;
11863
11864 if (argv_find(argv, argc, "dampening", &idx)) {
11865 if (argv_find(argv, argc, "dampened-paths", &idx))
11866 sh_type = bgp_show_type_dampend_paths;
11867 else if (argv_find(argv, argc, "flap-statistics", &idx))
11868 sh_type = bgp_show_type_flap_statistics;
11869 }
11870
11871 if (argv_find(argv, argc, "community", &idx)) {
11872 char *maybecomm = NULL;
11873
11874 if (idx + 1 < argc) {
11875 if (argv[idx + 1]->type == VARIABLE_TKN)
11876 maybecomm = argv[idx + 1]->arg;
11877 else
11878 maybecomm = argv[idx + 1]->text;
11879 }
11880
11881 if (maybecomm && !strmatch(maybecomm, "json")
11882 && !strmatch(maybecomm, "exact-match"))
11883 community = maybecomm;
11884
11885 if (argv_find(argv, argc, "exact-match", &idx))
11886 exact_match = 1;
11887
11888 if (!community)
11889 sh_type = bgp_show_type_community_all;
11890 }
11891
11892 if (!all) {
11893 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
11894 if (community)
11895 return bgp_show_community(vty, bgp, community,
11896 exact_match, afi, safi,
11897 show_flags);
11898 else
11899 return bgp_show(vty, bgp, afi, safi, sh_type, NULL,
11900 show_flags);
11901 } else {
11902 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
11903 * AFI_IP6 */
11904
11905 if (uj)
11906 vty_out(vty, "{\n");
11907
11908 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
11909 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
11910 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
11911 ? AFI_IP
11912 : AFI_IP6;
11913 FOREACH_SAFI (safi) {
11914 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
11915 continue;
11916
11917 if (uj) {
11918 if (first)
11919 first = false;
11920 else
11921 vty_out(vty, ",\n");
11922 vty_out(vty, "\"%s\":{\n",
11923 get_afi_safi_str(afi, safi,
11924 true));
11925 } else
11926 vty_out(vty,
11927 "\nFor address family: %s\n",
11928 get_afi_safi_str(afi, safi,
11929 false));
11930
11931 if (community)
11932 bgp_show_community(vty, bgp, community,
11933 exact_match, afi,
11934 safi, show_flags);
11935 else
11936 bgp_show(vty, bgp, afi, safi, sh_type,
11937 NULL, show_flags);
11938 if (uj)
11939 vty_out(vty, "}\n");
11940 }
11941 } else {
11942 /* show <ip> bgp all: for each AFI and SAFI*/
11943 FOREACH_AFI_SAFI (afi, safi) {
11944 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
11945 continue;
11946
11947 if (uj) {
11948 if (first)
11949 first = false;
11950 else
11951 vty_out(vty, ",\n");
11952
11953 vty_out(vty, "\"%s\":{\n",
11954 get_afi_safi_str(afi, safi,
11955 true));
11956 } else
11957 vty_out(vty,
11958 "\nFor address family: %s\n",
11959 get_afi_safi_str(afi, safi,
11960 false));
11961
11962 if (community)
11963 bgp_show_community(vty, bgp, community,
11964 exact_match, afi,
11965 safi, show_flags);
11966 else
11967 bgp_show(vty, bgp, afi, safi, sh_type,
11968 NULL, show_flags);
11969 if (uj)
11970 vty_out(vty, "}\n");
11971 }
11972 }
11973 if (uj)
11974 vty_out(vty, "}\n");
11975 }
11976 return CMD_SUCCESS;
11977 }
11978
11979 DEFUN (show_ip_bgp_route,
11980 show_ip_bgp_route_cmd,
11981 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [json]",
11982 SHOW_STR
11983 IP_STR
11984 BGP_STR
11985 BGP_INSTANCE_HELP_STR
11986 BGP_AFI_HELP_STR
11987 BGP_SAFI_WITH_LABEL_HELP_STR
11988 "Network in the BGP routing table to display\n"
11989 "IPv4 prefix\n"
11990 "Network in the BGP routing table to display\n"
11991 "IPv6 prefix\n"
11992 "Display only the bestpath\n"
11993 "Display only multipaths\n"
11994 JSON_STR)
11995 {
11996 int prefix_check = 0;
11997
11998 afi_t afi = AFI_IP6;
11999 safi_t safi = SAFI_UNICAST;
12000 char *prefix = NULL;
12001 struct bgp *bgp = NULL;
12002 enum bgp_path_type path_type;
12003 bool uj = use_json(argc, argv);
12004
12005 int idx = 0;
12006
12007 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12008 &bgp, uj);
12009 if (!idx)
12010 return CMD_WARNING;
12011
12012 if (!bgp) {
12013 vty_out(vty,
12014 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
12015 return CMD_WARNING;
12016 }
12017
12018 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
12019 if (argv_find(argv, argc, "A.B.C.D", &idx)
12020 || argv_find(argv, argc, "X:X::X:X", &idx))
12021 prefix_check = 0;
12022 else if (argv_find(argv, argc, "A.B.C.D/M", &idx)
12023 || argv_find(argv, argc, "X:X::X:X/M", &idx))
12024 prefix_check = 1;
12025
12026 if ((argv[idx]->type == IPV6_TKN || argv[idx]->type == IPV6_PREFIX_TKN)
12027 && afi != AFI_IP6) {
12028 vty_out(vty,
12029 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
12030 return CMD_WARNING;
12031 }
12032 if ((argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV4_PREFIX_TKN)
12033 && afi != AFI_IP) {
12034 vty_out(vty,
12035 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
12036 return CMD_WARNING;
12037 }
12038
12039 prefix = argv[idx]->arg;
12040
12041 /* [<bestpath|multipath>] */
12042 if (argv_find(argv, argc, "bestpath", &idx))
12043 path_type = BGP_PATH_SHOW_BESTPATH;
12044 else if (argv_find(argv, argc, "multipath", &idx))
12045 path_type = BGP_PATH_SHOW_MULTIPATH;
12046 else
12047 path_type = BGP_PATH_SHOW_ALL;
12048
12049 return bgp_show_route(vty, bgp, prefix, afi, safi, NULL, prefix_check,
12050 path_type, uj);
12051 }
12052
12053 DEFUN (show_ip_bgp_regexp,
12054 show_ip_bgp_regexp_cmd,
12055 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] regexp REGEX [json]",
12056 SHOW_STR
12057 IP_STR
12058 BGP_STR
12059 BGP_INSTANCE_HELP_STR
12060 BGP_AFI_HELP_STR
12061 BGP_SAFI_WITH_LABEL_HELP_STR
12062 "Display routes matching the AS path regular expression\n"
12063 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
12064 JSON_STR)
12065 {
12066 afi_t afi = AFI_IP6;
12067 safi_t safi = SAFI_UNICAST;
12068 struct bgp *bgp = NULL;
12069 bool uj = use_json(argc, argv);
12070 char *regstr = NULL;
12071
12072 int idx = 0;
12073 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12074 &bgp, false);
12075 if (!idx)
12076 return CMD_WARNING;
12077
12078 // get index of regex
12079 if (argv_find(argv, argc, "REGEX", &idx))
12080 regstr = argv[idx]->arg;
12081
12082 assert(regstr);
12083 return bgp_show_regexp(vty, bgp, (const char *)regstr, afi, safi,
12084 bgp_show_type_regexp, uj);
12085 }
12086
12087 DEFPY (show_ip_bgp_instance_all,
12088 show_ip_bgp_instance_all_cmd,
12089 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [json$uj | wide$wide]",
12090 SHOW_STR
12091 IP_STR
12092 BGP_STR
12093 BGP_INSTANCE_ALL_HELP_STR
12094 BGP_AFI_HELP_STR
12095 BGP_SAFI_WITH_LABEL_HELP_STR
12096 JSON_STR
12097 "Increase table width for longer prefixes\n")
12098 {
12099 afi_t afi = AFI_IP;
12100 safi_t safi = SAFI_UNICAST;
12101 struct bgp *bgp = NULL;
12102 int idx = 0;
12103 uint8_t show_flags = 0;
12104
12105 if (uj) {
12106 argc--;
12107 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12108 }
12109
12110 if (wide)
12111 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
12112
12113 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12114 &bgp, uj);
12115 if (!idx)
12116 return CMD_WARNING;
12117
12118 bgp_show_all_instances_routes_vty(vty, afi, safi, show_flags);
12119 return CMD_SUCCESS;
12120 }
12121
12122 static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
12123 afi_t afi, safi_t safi, enum bgp_show_type type,
12124 bool use_json)
12125 {
12126 regex_t *regex;
12127 int rc;
12128 uint8_t show_flags = 0;
12129
12130 if (use_json)
12131 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12132
12133 if (!config_bgp_aspath_validate(regstr)) {
12134 vty_out(vty, "Invalid character in REGEX %s\n",
12135 regstr);
12136 return CMD_WARNING_CONFIG_FAILED;
12137 }
12138
12139 regex = bgp_regcomp(regstr);
12140 if (!regex) {
12141 vty_out(vty, "Can't compile regexp %s\n", regstr);
12142 return CMD_WARNING;
12143 }
12144
12145 rc = bgp_show(vty, bgp, afi, safi, type, regex, show_flags);
12146 bgp_regex_free(regex);
12147 return rc;
12148 }
12149
12150 static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
12151 const char *prefix_list_str, afi_t afi,
12152 safi_t safi, enum bgp_show_type type)
12153 {
12154 struct prefix_list *plist;
12155 uint8_t show_flags = 0;
12156
12157 plist = prefix_list_lookup(afi, prefix_list_str);
12158 if (plist == NULL) {
12159 vty_out(vty, "%% %s is not a valid prefix-list name\n",
12160 prefix_list_str);
12161 return CMD_WARNING;
12162 }
12163
12164 return bgp_show(vty, bgp, afi, safi, type, plist, show_flags);
12165 }
12166
12167 static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
12168 const char *filter, afi_t afi, safi_t safi,
12169 enum bgp_show_type type)
12170 {
12171 struct as_list *as_list;
12172 uint8_t show_flags = 0;
12173
12174 as_list = as_list_lookup(filter);
12175 if (as_list == NULL) {
12176 vty_out(vty, "%% %s is not a valid AS-path access-list name\n",
12177 filter);
12178 return CMD_WARNING;
12179 }
12180
12181 return bgp_show(vty, bgp, afi, safi, type, as_list, show_flags);
12182 }
12183
12184 static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
12185 const char *rmap_str, afi_t afi, safi_t safi,
12186 enum bgp_show_type type)
12187 {
12188 struct route_map *rmap;
12189 uint8_t show_flags = 0;
12190
12191 rmap = route_map_lookup_by_name(rmap_str);
12192 if (!rmap) {
12193 vty_out(vty, "%% %s is not a valid route-map name\n", rmap_str);
12194 return CMD_WARNING;
12195 }
12196
12197 return bgp_show(vty, bgp, afi, safi, type, rmap, show_flags);
12198 }
12199
12200 static int bgp_show_community(struct vty *vty, struct bgp *bgp,
12201 const char *comstr, int exact, afi_t afi,
12202 safi_t safi, uint8_t show_flags)
12203 {
12204 struct community *com;
12205 int ret = 0;
12206
12207 com = community_str2com(comstr);
12208 if (!com) {
12209 vty_out(vty, "%% Community malformed: %s\n", comstr);
12210 return CMD_WARNING;
12211 }
12212
12213 ret = bgp_show(vty, bgp, afi, safi,
12214 (exact ? bgp_show_type_community_exact
12215 : bgp_show_type_community),
12216 com, show_flags);
12217 community_free(&com);
12218
12219 return ret;
12220 }
12221
12222 static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
12223 const char *com, int exact, afi_t afi,
12224 safi_t safi)
12225 {
12226 struct community_list *list;
12227 uint8_t show_flags = 0;
12228
12229 list = community_list_lookup(bgp_clist, com, 0, COMMUNITY_LIST_MASTER);
12230 if (list == NULL) {
12231 vty_out(vty, "%% %s is not a valid community-list name\n", com);
12232 return CMD_WARNING;
12233 }
12234
12235 return bgp_show(vty, bgp, afi, safi,
12236 (exact ? bgp_show_type_community_list_exact
12237 : bgp_show_type_community_list),
12238 list, show_flags);
12239 }
12240
12241 static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
12242 const char *prefix, afi_t afi, safi_t safi,
12243 enum bgp_show_type type)
12244 {
12245 int ret;
12246 struct prefix *p;
12247 uint8_t show_flags = 0;
12248
12249 p = prefix_new();
12250
12251 ret = str2prefix(prefix, p);
12252 if (!ret) {
12253 vty_out(vty, "%% Malformed Prefix\n");
12254 return CMD_WARNING;
12255 }
12256
12257 ret = bgp_show(vty, bgp, afi, safi, type, p, show_flags);
12258 prefix_free(&p);
12259 return ret;
12260 }
12261
12262 enum bgp_stats {
12263 BGP_STATS_MAXBITLEN = 0,
12264 BGP_STATS_RIB,
12265 BGP_STATS_PREFIXES,
12266 BGP_STATS_TOTPLEN,
12267 BGP_STATS_UNAGGREGATEABLE,
12268 BGP_STATS_MAX_AGGREGATEABLE,
12269 BGP_STATS_AGGREGATES,
12270 BGP_STATS_SPACE,
12271 BGP_STATS_ASPATH_COUNT,
12272 BGP_STATS_ASPATH_MAXHOPS,
12273 BGP_STATS_ASPATH_TOTHOPS,
12274 BGP_STATS_ASPATH_MAXSIZE,
12275 BGP_STATS_ASPATH_TOTSIZE,
12276 BGP_STATS_ASN_HIGHEST,
12277 BGP_STATS_MAX,
12278 };
12279
12280 #define TABLE_STATS_IDX_VTY 0
12281 #define TABLE_STATS_IDX_JSON 1
12282
12283 static const char *table_stats_strs[][2] = {
12284 [BGP_STATS_PREFIXES] = {"Total Prefixes", "totalPrefixes"},
12285 [BGP_STATS_TOTPLEN] = {"Average prefix length", "averagePrefixLength"},
12286 [BGP_STATS_RIB] = {"Total Advertisements", "totalAdvertisements"},
12287 [BGP_STATS_UNAGGREGATEABLE] = {"Unaggregateable prefixes",
12288 "unaggregateablePrefixes"},
12289 [BGP_STATS_MAX_AGGREGATEABLE] = {"Maximum aggregateable prefixes",
12290 "maximumAggregateablePrefixes"},
12291 [BGP_STATS_AGGREGATES] = {"BGP Aggregate advertisements",
12292 "bgpAggregateAdvertisements"},
12293 [BGP_STATS_SPACE] = {"Address space advertised",
12294 "addressSpaceAdvertised"},
12295 [BGP_STATS_ASPATH_COUNT] = {"Advertisements with paths",
12296 "advertisementsWithPaths"},
12297 [BGP_STATS_ASPATH_MAXHOPS] = {"Longest AS-Path (hops)",
12298 "longestAsPath"},
12299 [BGP_STATS_ASPATH_MAXSIZE] = {"Largest AS-Path (bytes)",
12300 "largestAsPath"},
12301 [BGP_STATS_ASPATH_TOTHOPS] = {"Average AS-Path length (hops)",
12302 "averageAsPathLengthHops"},
12303 [BGP_STATS_ASPATH_TOTSIZE] = {"Average AS-Path size (bytes)",
12304 "averageAsPathSizeBytes"},
12305 [BGP_STATS_ASN_HIGHEST] = {"Highest public ASN", "highestPublicAsn"},
12306 [BGP_STATS_MAX] = {NULL, NULL}
12307 };
12308
12309 struct bgp_table_stats {
12310 struct bgp_table *table;
12311 unsigned long long counts[BGP_STATS_MAX];
12312 double total_space;
12313 };
12314
12315 static void bgp_table_stats_rn(struct bgp_dest *dest, struct bgp_dest *top,
12316 struct bgp_table_stats *ts, unsigned int space)
12317 {
12318 struct bgp_dest *pdest = bgp_dest_parent_nolock(dest);
12319 struct bgp_path_info *pi;
12320 const struct prefix *rn_p;
12321
12322 if (!bgp_dest_has_bgp_path_info_data(dest))
12323 return;
12324
12325 rn_p = bgp_dest_get_prefix(dest);
12326 ts->counts[BGP_STATS_PREFIXES]++;
12327 ts->counts[BGP_STATS_TOTPLEN] += rn_p->prefixlen;
12328
12329 /* check if the prefix is included by any other announcements */
12330 while (pdest && !bgp_dest_has_bgp_path_info_data(pdest))
12331 pdest = bgp_dest_parent_nolock(pdest);
12332
12333 if (pdest == NULL || pdest == top) {
12334 ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
12335 /* announced address space */
12336 if (space)
12337 ts->total_space += pow(2.0, space - rn_p->prefixlen);
12338 } else if (bgp_dest_has_bgp_path_info_data(pdest))
12339 ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
12340
12341
12342 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
12343 ts->counts[BGP_STATS_RIB]++;
12344
12345 if (CHECK_FLAG(pi->attr->flag,
12346 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)))
12347 ts->counts[BGP_STATS_AGGREGATES]++;
12348
12349 /* as-path stats */
12350 if (pi->attr->aspath) {
12351 unsigned int hops = aspath_count_hops(pi->attr->aspath);
12352 unsigned int size = aspath_size(pi->attr->aspath);
12353 as_t highest = aspath_highest(pi->attr->aspath);
12354
12355 ts->counts[BGP_STATS_ASPATH_COUNT]++;
12356
12357 if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS])
12358 ts->counts[BGP_STATS_ASPATH_MAXHOPS] = hops;
12359
12360 if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE])
12361 ts->counts[BGP_STATS_ASPATH_MAXSIZE] = size;
12362
12363 ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
12364 ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
12365 if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
12366 ts->counts[BGP_STATS_ASN_HIGHEST] = highest;
12367 }
12368 }
12369 }
12370
12371 static int bgp_table_stats_walker(struct thread *t)
12372 {
12373 struct bgp_dest *dest, *ndest;
12374 struct bgp_dest *top;
12375 struct bgp_table_stats *ts = THREAD_ARG(t);
12376 unsigned int space = 0;
12377
12378 if (!(top = bgp_table_top(ts->table)))
12379 return 0;
12380
12381 switch (ts->table->afi) {
12382 case AFI_IP:
12383 space = IPV4_MAX_BITLEN;
12384 break;
12385 case AFI_IP6:
12386 space = IPV6_MAX_BITLEN;
12387 break;
12388 case AFI_L2VPN:
12389 space = EVPN_ROUTE_PREFIXLEN;
12390 break;
12391 default:
12392 return 0;
12393 }
12394
12395 ts->counts[BGP_STATS_MAXBITLEN] = space;
12396
12397 for (dest = top; dest; dest = bgp_route_next(dest)) {
12398 if (ts->table->safi == SAFI_MPLS_VPN
12399 || ts->table->safi == SAFI_ENCAP
12400 || ts->table->safi == SAFI_EVPN) {
12401 struct bgp_table *table;
12402
12403 table = bgp_dest_get_bgp_table_info(dest);
12404 if (!table)
12405 continue;
12406
12407 top = bgp_table_top(table);
12408 for (ndest = bgp_table_top(table); ndest;
12409 ndest = bgp_route_next(ndest))
12410 bgp_table_stats_rn(ndest, top, ts, space);
12411 } else {
12412 bgp_table_stats_rn(dest, top, ts, space);
12413 }
12414 }
12415
12416 return 0;
12417 }
12418
12419 static void bgp_table_stats_all(struct vty *vty, afi_t afi, safi_t safi,
12420 struct json_object *json_array)
12421 {
12422 struct listnode *node, *nnode;
12423 struct bgp *bgp;
12424
12425 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
12426 bgp_table_stats_single(vty, bgp, afi, safi, json_array);
12427 }
12428
12429 static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
12430 safi_t safi, struct json_object *json_array)
12431 {
12432 struct bgp_table_stats ts;
12433 unsigned int i;
12434 int ret = CMD_SUCCESS;
12435 char temp_buf[20];
12436 struct json_object *json = NULL;
12437
12438 if (json_array)
12439 json = json_object_new_object();
12440
12441 if (!bgp->rib[afi][safi]) {
12442 char warning_msg[50];
12443
12444 snprintf(warning_msg, sizeof(warning_msg),
12445 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi,
12446 safi);
12447
12448 if (!json)
12449 vty_out(vty, "%s\n", warning_msg);
12450 else
12451 json_object_string_add(json, "warning", warning_msg);
12452
12453 ret = CMD_WARNING;
12454 goto end_table_stats;
12455 }
12456
12457 if (!json)
12458 vty_out(vty, "BGP %s RIB statistics (%s)\n",
12459 get_afi_safi_str(afi, safi, false), bgp->name_pretty);
12460 else
12461 json_object_string_add(json, "instance", bgp->name_pretty);
12462
12463 /* labeled-unicast routes live in the unicast table */
12464 if (safi == SAFI_LABELED_UNICAST)
12465 safi = SAFI_UNICAST;
12466
12467 memset(&ts, 0, sizeof(ts));
12468 ts.table = bgp->rib[afi][safi];
12469 thread_execute(bm->master, bgp_table_stats_walker, &ts, 0);
12470
12471 for (i = 0; i < BGP_STATS_MAX; i++) {
12472 if ((!json && !table_stats_strs[i][TABLE_STATS_IDX_VTY])
12473 || (json && !table_stats_strs[i][TABLE_STATS_IDX_JSON]))
12474 continue;
12475
12476 switch (i) {
12477 case BGP_STATS_ASPATH_TOTHOPS:
12478 case BGP_STATS_ASPATH_TOTSIZE:
12479 if (!json) {
12480 snprintf(
12481 temp_buf, sizeof(temp_buf), "%12.2f",
12482 ts.counts[i]
12483 ? (float)ts.counts[i]
12484 / (float)ts.counts
12485 [BGP_STATS_ASPATH_COUNT]
12486 : 0);
12487 vty_out(vty, "%-30s: %s",
12488 table_stats_strs[i]
12489 [TABLE_STATS_IDX_VTY],
12490 temp_buf);
12491 } else {
12492 json_object_double_add(
12493 json,
12494 table_stats_strs[i]
12495 [TABLE_STATS_IDX_JSON],
12496 ts.counts[i]
12497 ? (double)ts.counts[i]
12498 / (double)ts.counts
12499 [BGP_STATS_ASPATH_COUNT]
12500 : 0);
12501 }
12502 break;
12503 case BGP_STATS_TOTPLEN:
12504 if (!json) {
12505 snprintf(
12506 temp_buf, sizeof(temp_buf), "%12.2f",
12507 ts.counts[i]
12508 ? (float)ts.counts[i]
12509 / (float)ts.counts
12510 [BGP_STATS_PREFIXES]
12511 : 0);
12512 vty_out(vty, "%-30s: %s",
12513 table_stats_strs[i]
12514 [TABLE_STATS_IDX_VTY],
12515 temp_buf);
12516 } else {
12517 json_object_double_add(
12518 json,
12519 table_stats_strs[i]
12520 [TABLE_STATS_IDX_JSON],
12521 ts.counts[i]
12522 ? (double)ts.counts[i]
12523 / (double)ts.counts
12524 [BGP_STATS_PREFIXES]
12525 : 0);
12526 }
12527 break;
12528 case BGP_STATS_SPACE:
12529 if (!json) {
12530 snprintf(temp_buf, sizeof(temp_buf), "%12g",
12531 ts.total_space);
12532 vty_out(vty, "%-30s: %s\n",
12533 table_stats_strs[i]
12534 [TABLE_STATS_IDX_VTY],
12535 temp_buf);
12536 } else {
12537 json_object_double_add(
12538 json,
12539 table_stats_strs[i]
12540 [TABLE_STATS_IDX_JSON],
12541 (double)ts.total_space);
12542 }
12543 if (afi == AFI_IP6) {
12544 if (!json) {
12545 snprintf(temp_buf, sizeof(temp_buf),
12546 "%12g",
12547 ts.total_space
12548 * pow(2.0, -128 + 32));
12549 vty_out(vty, "%30s: %s\n",
12550 "/32 equivalent %s\n",
12551 temp_buf);
12552 } else {
12553 json_object_double_add(
12554 json, "/32equivalent",
12555 (double)(ts.total_space
12556 * pow(2.0,
12557 -128 + 32)));
12558 }
12559 if (!json) {
12560 snprintf(temp_buf, sizeof(temp_buf),
12561 "%12g",
12562 ts.total_space
12563 * pow(2.0, -128 + 48));
12564 vty_out(vty, "%30s: %s\n",
12565 "/48 equivalent %s\n",
12566 temp_buf);
12567 } else {
12568 json_object_double_add(
12569 json, "/48equivalent",
12570 (double)(ts.total_space
12571 * pow(2.0,
12572 -128 + 48)));
12573 }
12574 } else {
12575 if (!json) {
12576 snprintf(temp_buf, sizeof(temp_buf),
12577 "%12.2f",
12578 ts.total_space * 100.
12579 * pow(2.0, -32));
12580 vty_out(vty, "%30s: %s\n",
12581 "% announced ", temp_buf);
12582 } else {
12583 json_object_double_add(
12584 json, "%announced",
12585 (double)(ts.total_space * 100.
12586 * pow(2.0, -32)));
12587 }
12588 if (!json) {
12589 snprintf(temp_buf, sizeof(temp_buf),
12590 "%12.2f",
12591 ts.total_space
12592 * pow(2.0, -32 + 8));
12593 vty_out(vty, "%30s: %s\n",
12594 "/8 equivalent ", temp_buf);
12595 } else {
12596 json_object_double_add(
12597 json, "/8equivalent",
12598 (double)(ts.total_space
12599 * pow(2.0, -32 + 8)));
12600 }
12601 if (!json) {
12602 snprintf(temp_buf, sizeof(temp_buf),
12603 "%12.2f",
12604 ts.total_space
12605 * pow(2.0, -32 + 24));
12606 vty_out(vty, "%30s: %s\n",
12607 "/24 equivalent ", temp_buf);
12608 } else {
12609 json_object_double_add(
12610 json, "/24equivalent",
12611 (double)(ts.total_space
12612 * pow(2.0, -32 + 24)));
12613 }
12614 }
12615 break;
12616 default:
12617 if (!json) {
12618 snprintf(temp_buf, sizeof(temp_buf), "%12llu",
12619 ts.counts[i]);
12620 vty_out(vty, "%-30s: %s",
12621 table_stats_strs[i]
12622 [TABLE_STATS_IDX_VTY],
12623 temp_buf);
12624 } else {
12625 json_object_int_add(
12626 json,
12627 table_stats_strs[i]
12628 [TABLE_STATS_IDX_JSON],
12629 ts.counts[i]);
12630 }
12631 }
12632 if (!json)
12633 vty_out(vty, "\n");
12634 }
12635 end_table_stats:
12636 if (json)
12637 json_object_array_add(json_array, json);
12638 return ret;
12639 }
12640
12641 static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
12642 safi_t safi, struct json_object *json_array)
12643 {
12644 if (!bgp) {
12645 bgp_table_stats_all(vty, afi, safi, json_array);
12646 return CMD_SUCCESS;
12647 }
12648
12649 return bgp_table_stats_single(vty, bgp, afi, safi, json_array);
12650 }
12651
12652 enum bgp_pcounts {
12653 PCOUNT_ADJ_IN = 0,
12654 PCOUNT_DAMPED,
12655 PCOUNT_REMOVED,
12656 PCOUNT_HISTORY,
12657 PCOUNT_STALE,
12658 PCOUNT_VALID,
12659 PCOUNT_ALL,
12660 PCOUNT_COUNTED,
12661 PCOUNT_BPATH_SELECTED,
12662 PCOUNT_PFCNT, /* the figure we display to users */
12663 PCOUNT_MAX,
12664 };
12665
12666 static const char *const pcount_strs[] = {
12667 [PCOUNT_ADJ_IN] = "Adj-in",
12668 [PCOUNT_DAMPED] = "Damped",
12669 [PCOUNT_REMOVED] = "Removed",
12670 [PCOUNT_HISTORY] = "History",
12671 [PCOUNT_STALE] = "Stale",
12672 [PCOUNT_VALID] = "Valid",
12673 [PCOUNT_ALL] = "All RIB",
12674 [PCOUNT_COUNTED] = "PfxCt counted",
12675 [PCOUNT_BPATH_SELECTED] = "PfxCt Best Selected",
12676 [PCOUNT_PFCNT] = "Useable",
12677 [PCOUNT_MAX] = NULL,
12678 };
12679
12680 struct peer_pcounts {
12681 unsigned int count[PCOUNT_MAX];
12682 const struct peer *peer;
12683 const struct bgp_table *table;
12684 safi_t safi;
12685 };
12686
12687 static void bgp_peer_count_proc(struct bgp_dest *rn, struct peer_pcounts *pc)
12688 {
12689 const struct bgp_adj_in *ain;
12690 const struct bgp_path_info *pi;
12691 const struct peer *peer = pc->peer;
12692
12693 for (ain = rn->adj_in; ain; ain = ain->next)
12694 if (ain->peer == peer)
12695 pc->count[PCOUNT_ADJ_IN]++;
12696
12697 for (pi = bgp_dest_get_bgp_path_info(rn); pi; pi = pi->next) {
12698
12699 if (pi->peer != peer)
12700 continue;
12701
12702 pc->count[PCOUNT_ALL]++;
12703
12704 if (CHECK_FLAG(pi->flags, BGP_PATH_DAMPED))
12705 pc->count[PCOUNT_DAMPED]++;
12706 if (CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
12707 pc->count[PCOUNT_HISTORY]++;
12708 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
12709 pc->count[PCOUNT_REMOVED]++;
12710 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE))
12711 pc->count[PCOUNT_STALE]++;
12712 if (CHECK_FLAG(pi->flags, BGP_PATH_VALID))
12713 pc->count[PCOUNT_VALID]++;
12714 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
12715 pc->count[PCOUNT_PFCNT]++;
12716 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
12717 pc->count[PCOUNT_BPATH_SELECTED]++;
12718
12719 if (CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
12720 pc->count[PCOUNT_COUNTED]++;
12721 if (CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
12722 flog_err(
12723 EC_LIB_DEVELOPMENT,
12724 "Attempting to count but flags say it is unusable");
12725 } else {
12726 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
12727 flog_err(
12728 EC_LIB_DEVELOPMENT,
12729 "Not counted but flags say we should");
12730 }
12731 }
12732 }
12733
12734 static int bgp_peer_count_walker(struct thread *t)
12735 {
12736 struct bgp_dest *rn, *rm;
12737 const struct bgp_table *table;
12738 struct peer_pcounts *pc = THREAD_ARG(t);
12739
12740 if (pc->safi == SAFI_MPLS_VPN || pc->safi == SAFI_ENCAP
12741 || pc->safi == SAFI_EVPN) {
12742 /* Special handling for 2-level routing tables. */
12743 for (rn = bgp_table_top(pc->table); rn;
12744 rn = bgp_route_next(rn)) {
12745 table = bgp_dest_get_bgp_table_info(rn);
12746 if (table != NULL)
12747 for (rm = bgp_table_top(table); rm;
12748 rm = bgp_route_next(rm))
12749 bgp_peer_count_proc(rm, pc);
12750 }
12751 } else
12752 for (rn = bgp_table_top(pc->table); rn; rn = bgp_route_next(rn))
12753 bgp_peer_count_proc(rn, pc);
12754
12755 return 0;
12756 }
12757
12758 static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi,
12759 safi_t safi, bool use_json)
12760 {
12761 struct peer_pcounts pcounts = {.peer = peer};
12762 unsigned int i;
12763 json_object *json = NULL;
12764 json_object *json_loop = NULL;
12765
12766 if (use_json) {
12767 json = json_object_new_object();
12768 json_loop = json_object_new_object();
12769 }
12770
12771 if (!peer || !peer->bgp || !peer->afc[afi][safi]
12772 || !peer->bgp->rib[afi][safi]) {
12773 if (use_json) {
12774 json_object_string_add(
12775 json, "warning",
12776 "No such neighbor or address family");
12777 vty_out(vty, "%s\n", json_object_to_json_string(json));
12778 json_object_free(json);
12779 json_object_free(json_loop);
12780 } else
12781 vty_out(vty, "%% No such neighbor or address family\n");
12782
12783 return CMD_WARNING;
12784 }
12785
12786 memset(&pcounts, 0, sizeof(pcounts));
12787 pcounts.peer = peer;
12788 pcounts.table = peer->bgp->rib[afi][safi];
12789 pcounts.safi = safi;
12790
12791 /* in-place call via thread subsystem so as to record execution time
12792 * stats for the thread-walk (i.e. ensure this can't be blamed on
12793 * on just vty_read()).
12794 */
12795 thread_execute(bm->master, bgp_peer_count_walker, &pcounts, 0);
12796
12797 if (use_json) {
12798 json_object_string_add(json, "prefixCountsFor", peer->host);
12799 json_object_string_add(json, "multiProtocol",
12800 get_afi_safi_str(afi, safi, true));
12801 json_object_int_add(json, "pfxCounter",
12802 peer->pcount[afi][safi]);
12803
12804 for (i = 0; i < PCOUNT_MAX; i++)
12805 json_object_int_add(json_loop, pcount_strs[i],
12806 pcounts.count[i]);
12807
12808 json_object_object_add(json, "ribTableWalkCounters", json_loop);
12809
12810 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
12811 json_object_string_add(json, "pfxctDriftFor",
12812 peer->host);
12813 json_object_string_add(
12814 json, "recommended",
12815 "Please report this bug, with the above command output");
12816 }
12817 vty_out(vty, "%s\n", json_object_to_json_string_ext(
12818 json, JSON_C_TO_STRING_PRETTY));
12819 json_object_free(json);
12820 } else {
12821
12822 if (peer->hostname
12823 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
12824 vty_out(vty, "Prefix counts for %s/%s, %s\n",
12825 peer->hostname, peer->host,
12826 get_afi_safi_str(afi, safi, false));
12827 } else {
12828 vty_out(vty, "Prefix counts for %s, %s\n", peer->host,
12829 get_afi_safi_str(afi, safi, false));
12830 }
12831
12832 vty_out(vty, "PfxCt: %u\n", peer->pcount[afi][safi]);
12833 vty_out(vty, "\nCounts from RIB table walk:\n\n");
12834
12835 for (i = 0; i < PCOUNT_MAX; i++)
12836 vty_out(vty, "%20s: %-10d\n", pcount_strs[i],
12837 pcounts.count[i]);
12838
12839 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
12840 vty_out(vty, "%s [pcount] PfxCt drift!\n", peer->host);
12841 vty_out(vty,
12842 "Please report this bug, with the above command output\n");
12843 }
12844 }
12845
12846 return CMD_SUCCESS;
12847 }
12848
12849 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts,
12850 show_ip_bgp_instance_neighbor_prefix_counts_cmd,
12851 "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]",
12852 SHOW_STR
12853 IP_STR
12854 BGP_STR
12855 BGP_INSTANCE_HELP_STR
12856 BGP_AFI_HELP_STR
12857 BGP_SAFI_HELP_STR
12858 "Detailed information on TCP and BGP neighbor connections\n"
12859 "Neighbor to display information about\n"
12860 "Neighbor to display information about\n"
12861 "Neighbor on BGP configured interface\n"
12862 "Display detailed prefix count information\n"
12863 JSON_STR)
12864 {
12865 afi_t afi = AFI_IP6;
12866 safi_t safi = SAFI_UNICAST;
12867 struct peer *peer;
12868 int idx = 0;
12869 struct bgp *bgp = NULL;
12870 bool uj = use_json(argc, argv);
12871
12872 if (uj)
12873 argc--;
12874
12875 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12876 &bgp, uj);
12877 if (!idx)
12878 return CMD_WARNING;
12879
12880 argv_find(argv, argc, "neighbors", &idx);
12881 peer = peer_lookup_in_view(vty, bgp, argv[idx + 1]->arg, uj);
12882 if (!peer)
12883 return CMD_WARNING;
12884
12885 return bgp_peer_counts(vty, peer, afi, safi, uj);
12886 }
12887
12888 #ifdef KEEP_OLD_VPN_COMMANDS
12889 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts,
12890 show_ip_bgp_vpn_neighbor_prefix_counts_cmd,
12891 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
12892 SHOW_STR
12893 IP_STR
12894 BGP_STR
12895 BGP_VPNVX_HELP_STR
12896 "Display information about all VPNv4 NLRIs\n"
12897 "Detailed information on TCP and BGP neighbor connections\n"
12898 "Neighbor to display information about\n"
12899 "Neighbor to display information about\n"
12900 "Neighbor on BGP configured interface\n"
12901 "Display detailed prefix count information\n"
12902 JSON_STR)
12903 {
12904 int idx_peer = 6;
12905 struct peer *peer;
12906 bool uj = use_json(argc, argv);
12907
12908 peer = peer_lookup_in_view(vty, NULL, argv[idx_peer]->arg, uj);
12909 if (!peer)
12910 return CMD_WARNING;
12911
12912 return bgp_peer_counts(vty, peer, AFI_IP, SAFI_MPLS_VPN, uj);
12913 }
12914
12915 DEFUN (show_ip_bgp_vpn_all_route_prefix,
12916 show_ip_bgp_vpn_all_route_prefix_cmd,
12917 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
12918 SHOW_STR
12919 IP_STR
12920 BGP_STR
12921 BGP_VPNVX_HELP_STR
12922 "Display information about all VPNv4 NLRIs\n"
12923 "Network in the BGP routing table to display\n"
12924 "Network in the BGP routing table to display\n"
12925 JSON_STR)
12926 {
12927 int idx = 0;
12928 char *network = NULL;
12929 struct bgp *bgp = bgp_get_default();
12930 if (!bgp) {
12931 vty_out(vty, "Can't find default instance\n");
12932 return CMD_WARNING;
12933 }
12934
12935 if (argv_find(argv, argc, "A.B.C.D", &idx))
12936 network = argv[idx]->arg;
12937 else if (argv_find(argv, argc, "A.B.C.D/M", &idx))
12938 network = argv[idx]->arg;
12939 else {
12940 vty_out(vty, "Unable to figure out Network\n");
12941 return CMD_WARNING;
12942 }
12943
12944 return bgp_show_route(vty, bgp, network, AFI_IP, SAFI_MPLS_VPN, NULL, 0,
12945 BGP_PATH_SHOW_ALL, use_json(argc, argv));
12946 }
12947 #endif /* KEEP_OLD_VPN_COMMANDS */
12948
12949 DEFUN (show_bgp_l2vpn_evpn_route_prefix,
12950 show_bgp_l2vpn_evpn_route_prefix_cmd,
12951 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
12952 SHOW_STR
12953 BGP_STR
12954 L2VPN_HELP_STR
12955 EVPN_HELP_STR
12956 "Network in the BGP routing table to display\n"
12957 "Network in the BGP routing table to display\n"
12958 "Network in the BGP routing table to display\n"
12959 "Network in the BGP routing table to display\n"
12960 JSON_STR)
12961 {
12962 int idx = 0;
12963 char *network = NULL;
12964 int prefix_check = 0;
12965
12966 if (argv_find(argv, argc, "A.B.C.D", &idx) ||
12967 argv_find(argv, argc, "X:X::X:X", &idx))
12968 network = argv[idx]->arg;
12969 else if (argv_find(argv, argc, "A.B.C.D/M", &idx) ||
12970 argv_find(argv, argc, "X:X::X:X/M", &idx)) {
12971 network = argv[idx]->arg;
12972 prefix_check = 1;
12973 } else {
12974 vty_out(vty, "Unable to figure out Network\n");
12975 return CMD_WARNING;
12976 }
12977 return bgp_show_route(vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL,
12978 prefix_check, BGP_PATH_SHOW_ALL,
12979 use_json(argc, argv));
12980 }
12981
12982 static void show_adj_route_header(struct vty *vty, struct bgp *bgp,
12983 struct bgp_table *table, int *header1,
12984 int *header2, json_object *json,
12985 json_object *json_scode,
12986 json_object *json_ocode, bool wide)
12987 {
12988 uint64_t version = table ? table->version : 0;
12989 char buf[BUFSIZ] = {0};
12990
12991 if (*header1) {
12992 if (json) {
12993 json_object_int_add(json, "bgpTableVersion", version);
12994 json_object_string_add(json, "bgpLocalRouterId",
12995 inet_ntop(AF_INET,
12996 &bgp->router_id, buf,
12997 sizeof(buf)));
12998 json_object_int_add(json, "defaultLocPrf",
12999 bgp->default_local_pref);
13000 json_object_int_add(json, "localAS", bgp->as);
13001 json_object_object_add(json, "bgpStatusCodes",
13002 json_scode);
13003 json_object_object_add(json, "bgpOriginCodes",
13004 json_ocode);
13005 } else {
13006 vty_out(vty,
13007 "BGP table version is %" PRIu64
13008 ", local router ID is %pI4, vrf id ",
13009 version, &bgp->router_id);
13010 if (bgp->vrf_id == VRF_UNKNOWN)
13011 vty_out(vty, "%s", VRFID_NONE_STR);
13012 else
13013 vty_out(vty, "%u", bgp->vrf_id);
13014 vty_out(vty, "\n");
13015 vty_out(vty, "Default local pref %u, ",
13016 bgp->default_local_pref);
13017 vty_out(vty, "local AS %u\n", bgp->as);
13018 vty_out(vty, BGP_SHOW_SCODE_HEADER);
13019 vty_out(vty, BGP_SHOW_NCODE_HEADER);
13020 vty_out(vty, BGP_SHOW_OCODE_HEADER);
13021 }
13022 *header1 = 0;
13023 }
13024 if (*header2) {
13025 if (!json)
13026 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
13027 : BGP_SHOW_HEADER));
13028 *header2 = 0;
13029 }
13030 }
13031
13032 static void
13033 show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
13034 afi_t afi, safi_t safi, enum bgp_show_adj_route_type type,
13035 const char *rmap_name, json_object *json, json_object *json_ar,
13036 json_object *json_scode, json_object *json_ocode,
13037 uint8_t show_flags, int *header1, int *header2, char *rd_str,
13038 unsigned long *output_count, unsigned long *filtered_count)
13039 {
13040 struct bgp_adj_in *ain;
13041 struct bgp_adj_out *adj;
13042 struct bgp_dest *dest;
13043 struct bgp *bgp;
13044 struct attr attr;
13045 int ret;
13046 struct update_subgroup *subgrp;
13047 struct peer_af *paf;
13048 bool route_filtered;
13049 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13050 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
13051 bool show_rd = ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
13052 || (safi == SAFI_EVPN))
13053 ? true
13054 : false;
13055
13056 bgp = peer->bgp;
13057
13058 if (!bgp) {
13059 if (use_json) {
13060 json_object_string_add(json, "alert", "no BGP");
13061 vty_out(vty, "%s\n", json_object_to_json_string(json));
13062 json_object_free(json);
13063 } else
13064 vty_out(vty, "%% No bgp\n");
13065 return;
13066 }
13067
13068 subgrp = peer_subgroup(peer, afi, safi);
13069
13070 if (type == bgp_show_adj_route_advertised && subgrp
13071 && CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) {
13072 char buf[BUFSIZ] = {0};
13073
13074 if (use_json) {
13075 json_object_int_add(json, "bgpTableVersion",
13076 table->version);
13077 json_object_string_add(json, "bgpLocalRouterId",
13078 inet_ntop(AF_INET,
13079 &bgp->router_id, buf,
13080 sizeof(buf)));
13081 json_object_int_add(json, "defaultLocPrf",
13082 bgp->default_local_pref);
13083 json_object_int_add(json, "localAS", bgp->as);
13084 json_object_object_add(json, "bgpStatusCodes",
13085 json_scode);
13086 json_object_object_add(json, "bgpOriginCodes",
13087 json_ocode);
13088 json_object_string_add(
13089 json, "bgpOriginatingDefaultNetwork",
13090 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
13091 } else {
13092 vty_out(vty,
13093 "BGP table version is %" PRIu64
13094 ", local router ID is %pI4, vrf id ",
13095 table->version, &bgp->router_id);
13096 if (bgp->vrf_id == VRF_UNKNOWN)
13097 vty_out(vty, "%s", VRFID_NONE_STR);
13098 else
13099 vty_out(vty, "%u", bgp->vrf_id);
13100 vty_out(vty, "\n");
13101 vty_out(vty, "Default local pref %u, ",
13102 bgp->default_local_pref);
13103 vty_out(vty, "local AS %u\n", bgp->as);
13104 vty_out(vty, BGP_SHOW_SCODE_HEADER);
13105 vty_out(vty, BGP_SHOW_NCODE_HEADER);
13106 vty_out(vty, BGP_SHOW_OCODE_HEADER);
13107
13108 vty_out(vty, "Originating default network %s\n\n",
13109 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
13110 }
13111 *header1 = 0;
13112 }
13113
13114 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
13115 if (type == bgp_show_adj_route_received
13116 || type == bgp_show_adj_route_filtered) {
13117 for (ain = dest->adj_in; ain; ain = ain->next) {
13118 if (ain->peer != peer)
13119 continue;
13120
13121 show_adj_route_header(vty, bgp, table, header1,
13122 header2, json, json_scode,
13123 json_ocode, wide);
13124
13125 if ((safi == SAFI_MPLS_VPN)
13126 || (safi == SAFI_ENCAP)
13127 || (safi == SAFI_EVPN)) {
13128 if (use_json)
13129 json_object_string_add(
13130 json_ar, "rd", rd_str);
13131 else if (show_rd && rd_str) {
13132 vty_out(vty,
13133 "Route Distinguisher: %s\n",
13134 rd_str);
13135 show_rd = false;
13136 }
13137 }
13138
13139 attr = *ain->attr;
13140 route_filtered = false;
13141
13142 /* Filter prefix using distribute list,
13143 * filter list or prefix list
13144 */
13145 const struct prefix *rn_p =
13146 bgp_dest_get_prefix(dest);
13147 if ((bgp_input_filter(peer, rn_p, &attr, afi,
13148 safi))
13149 == FILTER_DENY)
13150 route_filtered = true;
13151
13152 /* Filter prefix using route-map */
13153 ret = bgp_input_modifier(peer, rn_p, &attr, afi,
13154 safi, rmap_name, NULL,
13155 0, NULL);
13156
13157 if (type == bgp_show_adj_route_filtered &&
13158 !route_filtered && ret != RMAP_DENY) {
13159 bgp_attr_undup(&attr, ain->attr);
13160 continue;
13161 }
13162
13163 if (type == bgp_show_adj_route_received
13164 && (route_filtered || ret == RMAP_DENY))
13165 (*filtered_count)++;
13166
13167 route_vty_out_tmp(vty, rn_p, &attr, safi,
13168 use_json, json_ar, wide);
13169 bgp_attr_undup(&attr, ain->attr);
13170 (*output_count)++;
13171 }
13172 } else if (type == bgp_show_adj_route_advertised) {
13173 RB_FOREACH (adj, bgp_adj_out_rb, &dest->adj_out)
13174 SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
13175 if (paf->peer != peer || !adj->attr)
13176 continue;
13177
13178 show_adj_route_header(vty, bgp, table,
13179 header1, header2,
13180 json, json_scode,
13181 json_ocode, wide);
13182
13183 const struct prefix *rn_p =
13184 bgp_dest_get_prefix(dest);
13185
13186 attr = *adj->attr;
13187 ret = bgp_output_modifier(
13188 peer, rn_p, &attr, afi, safi,
13189 rmap_name);
13190
13191 if (ret != RMAP_DENY) {
13192 if ((safi == SAFI_MPLS_VPN)
13193 || (safi == SAFI_ENCAP)
13194 || (safi == SAFI_EVPN)) {
13195 if (use_json)
13196 json_object_string_add(
13197 json_ar,
13198 "rd",
13199 rd_str);
13200 else if (show_rd
13201 && rd_str) {
13202 vty_out(vty,
13203 "Route Distinguisher: %s\n",
13204 rd_str);
13205 show_rd = false;
13206 }
13207 }
13208 route_vty_out_tmp(
13209 vty, rn_p, &attr, safi,
13210 use_json, json_ar,
13211 wide);
13212 (*output_count)++;
13213 } else {
13214 (*filtered_count)++;
13215 }
13216
13217 bgp_attr_undup(&attr, adj->attr);
13218 }
13219 } else if (type == bgp_show_adj_route_bestpath) {
13220 struct bgp_path_info *pi;
13221
13222 show_adj_route_header(vty, bgp, table, header1, header2,
13223 json, json_scode, json_ocode,
13224 wide);
13225
13226 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
13227 pi = pi->next) {
13228 if (pi->peer != peer)
13229 continue;
13230
13231 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
13232 continue;
13233
13234 route_vty_out_tmp(vty,
13235 bgp_dest_get_prefix(dest),
13236 pi->attr, safi, use_json,
13237 json_ar, wide);
13238 (*output_count)++;
13239 }
13240 }
13241 }
13242 }
13243
13244 static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
13245 safi_t safi, enum bgp_show_adj_route_type type,
13246 const char *rmap_name, uint8_t show_flags)
13247 {
13248 struct bgp *bgp;
13249 struct bgp_table *table;
13250 json_object *json = NULL;
13251 json_object *json_scode = NULL;
13252 json_object *json_ocode = NULL;
13253 json_object *json_ar = NULL;
13254 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13255
13256 /* Init BGP headers here so they're only displayed once
13257 * even if 'table' is 2-tier (MPLS_VPN, ENCAP, EVPN).
13258 */
13259 int header1 = 1;
13260 int header2 = 1;
13261
13262 /*
13263 * Initialize variables for each RD
13264 * All prefixes under an RD is aggregated within "json_routes"
13265 */
13266 char rd_str[BUFSIZ] = {0};
13267 json_object *json_routes = NULL;
13268
13269
13270 /* For 2-tier tables, prefix counts need to be
13271 * maintained across multiple runs of show_adj_route()
13272 */
13273 unsigned long output_count_per_rd;
13274 unsigned long filtered_count_per_rd;
13275 unsigned long output_count = 0;
13276 unsigned long filtered_count = 0;
13277
13278 if (use_json) {
13279 json = json_object_new_object();
13280 json_ar = json_object_new_object();
13281 json_scode = json_object_new_object();
13282 json_ocode = json_object_new_object();
13283
13284 json_object_string_add(json_scode, "suppressed", "s");
13285 json_object_string_add(json_scode, "damped", "d");
13286 json_object_string_add(json_scode, "history", "h");
13287 json_object_string_add(json_scode, "valid", "*");
13288 json_object_string_add(json_scode, "best", ">");
13289 json_object_string_add(json_scode, "multipath", "=");
13290 json_object_string_add(json_scode, "internal", "i");
13291 json_object_string_add(json_scode, "ribFailure", "r");
13292 json_object_string_add(json_scode, "stale", "S");
13293 json_object_string_add(json_scode, "removed", "R");
13294
13295 json_object_string_add(json_ocode, "igp", "i");
13296 json_object_string_add(json_ocode, "egp", "e");
13297 json_object_string_add(json_ocode, "incomplete", "?");
13298 }
13299
13300 if (!peer || !peer->afc[afi][safi]) {
13301 if (use_json) {
13302 json_object_string_add(
13303 json, "warning",
13304 "No such neighbor or address family");
13305 vty_out(vty, "%s\n", json_object_to_json_string(json));
13306 json_object_free(json);
13307 } else
13308 vty_out(vty, "%% No such neighbor or address family\n");
13309
13310 return CMD_WARNING;
13311 }
13312
13313 if ((type == bgp_show_adj_route_received
13314 || type == bgp_show_adj_route_filtered)
13315 && !CHECK_FLAG(peer->af_flags[afi][safi],
13316 PEER_FLAG_SOFT_RECONFIG)) {
13317 if (use_json) {
13318 json_object_string_add(
13319 json, "warning",
13320 "Inbound soft reconfiguration not enabled");
13321 vty_out(vty, "%s\n", json_object_to_json_string(json));
13322 json_object_free(json);
13323 } else
13324 vty_out(vty,
13325 "%% Inbound soft reconfiguration not enabled\n");
13326
13327 return CMD_WARNING;
13328 }
13329
13330 bgp = peer->bgp;
13331
13332 /* labeled-unicast routes live in the unicast table */
13333 if (safi == SAFI_LABELED_UNICAST)
13334 table = bgp->rib[afi][SAFI_UNICAST];
13335 else
13336 table = bgp->rib[afi][safi];
13337
13338 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
13339 || (safi == SAFI_EVPN)) {
13340
13341 struct bgp_dest *dest;
13342
13343 for (dest = bgp_table_top(table); dest;
13344 dest = bgp_route_next(dest)) {
13345 table = bgp_dest_get_bgp_table_info(dest);
13346 if (!table)
13347 continue;
13348
13349 output_count_per_rd = 0;
13350 filtered_count_per_rd = 0;
13351
13352 if (use_json)
13353 json_routes = json_object_new_object();
13354
13355 const struct prefix_rd *prd;
13356 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
13357 dest);
13358
13359 prefix_rd2str(prd, rd_str, sizeof(rd_str));
13360
13361 show_adj_route(vty, peer, table, afi, safi, type,
13362 rmap_name, json, json_routes, json_scode,
13363 json_ocode, show_flags, &header1,
13364 &header2, rd_str, &output_count_per_rd,
13365 &filtered_count_per_rd);
13366
13367 /* Don't include an empty RD in the output! */
13368 if (json_routes && (output_count_per_rd > 0))
13369 json_object_object_add(json_ar, rd_str,
13370 json_routes);
13371
13372 output_count += output_count_per_rd;
13373 filtered_count += filtered_count_per_rd;
13374 }
13375 } else
13376 show_adj_route(vty, peer, table, afi, safi, type, rmap_name,
13377 json, json_ar, json_scode, json_ocode,
13378 show_flags, &header1, &header2, rd_str,
13379 &output_count, &filtered_count);
13380
13381 if (use_json) {
13382 json_object_object_add(json, "advertisedRoutes", json_ar);
13383 json_object_int_add(json, "totalPrefixCounter", output_count);
13384 json_object_int_add(json, "filteredPrefixCounter",
13385 filtered_count);
13386
13387 vty_out(vty, "%s\n",
13388 json_object_to_json_string_ext(
13389 json, JSON_C_TO_STRING_PRETTY));
13390
13391 if (!output_count && !filtered_count) {
13392 json_object_free(json_scode);
13393 json_object_free(json_ocode);
13394 }
13395
13396 if (json)
13397 json_object_free(json);
13398
13399 } else if (output_count > 0) {
13400 if (filtered_count > 0)
13401 vty_out(vty,
13402 "\nTotal number of prefixes %ld (%ld filtered)\n",
13403 output_count, filtered_count);
13404 else
13405 vty_out(vty, "\nTotal number of prefixes %ld\n",
13406 output_count);
13407 }
13408
13409 return CMD_SUCCESS;
13410 }
13411
13412 DEFPY (show_ip_bgp_instance_neighbor_bestpath_route,
13413 show_ip_bgp_instance_neighbor_bestpath_route_cmd,
13414 "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]",
13415 SHOW_STR
13416 IP_STR
13417 BGP_STR
13418 BGP_INSTANCE_HELP_STR
13419 BGP_AFI_HELP_STR
13420 BGP_SAFI_WITH_LABEL_HELP_STR
13421 "Detailed information on TCP and BGP neighbor connections\n"
13422 "Neighbor to display information about\n"
13423 "Neighbor to display information about\n"
13424 "Neighbor on BGP configured interface\n"
13425 "Display the routes selected by best path\n"
13426 JSON_STR
13427 "Increase table width for longer prefixes\n")
13428 {
13429 afi_t afi = AFI_IP6;
13430 safi_t safi = SAFI_UNICAST;
13431 char *rmap_name = NULL;
13432 char *peerstr = NULL;
13433 struct bgp *bgp = NULL;
13434 struct peer *peer;
13435 enum bgp_show_adj_route_type type = bgp_show_adj_route_bestpath;
13436 int idx = 0;
13437 uint8_t show_flags = 0;
13438
13439 if (uj)
13440 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13441
13442 if (wide)
13443 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
13444
13445 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13446 &bgp, uj);
13447
13448 if (!idx)
13449 return CMD_WARNING;
13450
13451 argv_find(argv, argc, "neighbors", &idx);
13452 peerstr = argv[++idx]->arg;
13453
13454 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
13455 if (!peer)
13456 return CMD_WARNING;
13457
13458 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13459 show_flags);
13460 }
13461
13462 DEFPY (show_ip_bgp_instance_neighbor_advertised_route,
13463 show_ip_bgp_instance_neighbor_advertised_route_cmd,
13464 "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]",
13465 SHOW_STR
13466 IP_STR
13467 BGP_STR
13468 BGP_INSTANCE_HELP_STR
13469 BGP_AFI_HELP_STR
13470 BGP_SAFI_WITH_LABEL_HELP_STR
13471 "Display the entries for all address families\n"
13472 "Detailed information on TCP and BGP neighbor connections\n"
13473 "Neighbor to display information about\n"
13474 "Neighbor to display information about\n"
13475 "Neighbor on BGP configured interface\n"
13476 "Display the routes advertised to a BGP neighbor\n"
13477 "Display the received routes from neighbor\n"
13478 "Display the filtered routes received from neighbor\n"
13479 "Route-map to modify the attributes\n"
13480 "Name of the route map\n"
13481 JSON_STR
13482 "Increase table width for longer prefixes\n")
13483 {
13484 afi_t afi = AFI_IP6;
13485 safi_t safi = SAFI_UNICAST;
13486 char *rmap_name = NULL;
13487 char *peerstr = NULL;
13488 struct bgp *bgp = NULL;
13489 struct peer *peer;
13490 enum bgp_show_adj_route_type type = bgp_show_adj_route_advertised;
13491 int idx = 0;
13492 bool first = true;
13493 uint8_t show_flags = 0;
13494
13495 if (uj) {
13496 argc--;
13497 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13498 }
13499
13500 if (all) {
13501 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
13502 if (argv_find(argv, argc, "ipv4", &idx))
13503 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
13504
13505 if (argv_find(argv, argc, "ipv6", &idx))
13506 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
13507 }
13508
13509 if (wide)
13510 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
13511
13512 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13513 &bgp, uj);
13514 if (!idx)
13515 return CMD_WARNING;
13516
13517 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13518 argv_find(argv, argc, "neighbors", &idx);
13519 peerstr = argv[++idx]->arg;
13520
13521 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
13522 if (!peer)
13523 return CMD_WARNING;
13524
13525 if (argv_find(argv, argc, "advertised-routes", &idx))
13526 type = bgp_show_adj_route_advertised;
13527 else if (argv_find(argv, argc, "received-routes", &idx))
13528 type = bgp_show_adj_route_received;
13529 else if (argv_find(argv, argc, "filtered-routes", &idx))
13530 type = bgp_show_adj_route_filtered;
13531
13532 if (argv_find(argv, argc, "route-map", &idx))
13533 rmap_name = argv[++idx]->arg;
13534
13535 if (!all)
13536 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13537 show_flags);
13538 if (uj)
13539 vty_out(vty, "{\n");
13540
13541 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
13542 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
13543 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP) ? AFI_IP
13544 : AFI_IP6;
13545 FOREACH_SAFI (safi) {
13546 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
13547 continue;
13548
13549 if (uj) {
13550 if (first)
13551 first = false;
13552 else
13553 vty_out(vty, ",\n");
13554 vty_out(vty, "\"%s\":",
13555 get_afi_safi_str(afi, safi, true));
13556 } else
13557 vty_out(vty, "\nFor address family: %s\n",
13558 get_afi_safi_str(afi, safi, false));
13559
13560 peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13561 show_flags);
13562 }
13563 } else {
13564 FOREACH_AFI_SAFI (afi, safi) {
13565 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
13566 continue;
13567
13568 if (uj) {
13569 if (first)
13570 first = false;
13571 else
13572 vty_out(vty, ",\n");
13573 vty_out(vty, "\"%s\":",
13574 get_afi_safi_str(afi, safi, true));
13575 } else
13576 vty_out(vty, "\nFor address family: %s\n",
13577 get_afi_safi_str(afi, safi, false));
13578
13579 peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13580 show_flags);
13581 }
13582 }
13583 if (uj)
13584 vty_out(vty, "}\n");
13585
13586 return CMD_SUCCESS;
13587 }
13588
13589 DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
13590 show_ip_bgp_neighbor_received_prefix_filter_cmd,
13591 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
13592 SHOW_STR
13593 IP_STR
13594 BGP_STR
13595 "Address Family\n"
13596 "Address Family\n"
13597 "Address Family modifier\n"
13598 "Detailed information on TCP and BGP neighbor connections\n"
13599 "Neighbor to display information about\n"
13600 "Neighbor to display information about\n"
13601 "Neighbor on BGP configured interface\n"
13602 "Display information received from a BGP neighbor\n"
13603 "Display the prefixlist filter\n"
13604 JSON_STR)
13605 {
13606 afi_t afi = AFI_IP6;
13607 safi_t safi = SAFI_UNICAST;
13608 char *peerstr = NULL;
13609
13610 char name[BUFSIZ];
13611 union sockunion su;
13612 struct peer *peer;
13613 int count, ret;
13614
13615 int idx = 0;
13616
13617 /* show [ip] bgp */
13618 if (argv_find(argv, argc, "ip", &idx))
13619 afi = AFI_IP;
13620 /* [<ipv4|ipv6> [unicast]] */
13621 if (argv_find(argv, argc, "ipv4", &idx))
13622 afi = AFI_IP;
13623 if (argv_find(argv, argc, "ipv6", &idx))
13624 afi = AFI_IP6;
13625 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13626 argv_find(argv, argc, "neighbors", &idx);
13627 peerstr = argv[++idx]->arg;
13628
13629 bool uj = use_json(argc, argv);
13630
13631 ret = str2sockunion(peerstr, &su);
13632 if (ret < 0) {
13633 peer = peer_lookup_by_conf_if(NULL, peerstr);
13634 if (!peer) {
13635 if (uj)
13636 vty_out(vty, "{}\n");
13637 else
13638 vty_out(vty,
13639 "%% Malformed address or name: %s\n",
13640 peerstr);
13641 return CMD_WARNING;
13642 }
13643 } else {
13644 peer = peer_lookup(NULL, &su);
13645 if (!peer) {
13646 if (uj)
13647 vty_out(vty, "{}\n");
13648 else
13649 vty_out(vty, "No peer\n");
13650 return CMD_WARNING;
13651 }
13652 }
13653
13654 snprintf(name, sizeof(name), "%s.%d.%d", peer->host, afi, safi);
13655 count = prefix_bgp_show_prefix_list(NULL, afi, name, uj);
13656 if (count) {
13657 if (!uj)
13658 vty_out(vty, "Address Family: %s\n",
13659 get_afi_safi_str(afi, safi, false));
13660 prefix_bgp_show_prefix_list(vty, afi, name, uj);
13661 } else {
13662 if (uj)
13663 vty_out(vty, "{}\n");
13664 else
13665 vty_out(vty, "No functional output\n");
13666 }
13667
13668 return CMD_SUCCESS;
13669 }
13670
13671 static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer,
13672 afi_t afi, safi_t safi,
13673 enum bgp_show_type type, bool use_json)
13674 {
13675 uint8_t show_flags = 0;
13676
13677 if (use_json)
13678 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13679
13680 if (!peer || !peer->afc[afi][safi]) {
13681 if (use_json) {
13682 json_object *json_no = NULL;
13683 json_no = json_object_new_object();
13684 json_object_string_add(
13685 json_no, "warning",
13686 "No such neighbor or address family");
13687 vty_out(vty, "%s\n",
13688 json_object_to_json_string(json_no));
13689 json_object_free(json_no);
13690 } else
13691 vty_out(vty, "%% No such neighbor or address family\n");
13692 return CMD_WARNING;
13693 }
13694
13695 /* labeled-unicast routes live in the unicast table */
13696 if (safi == SAFI_LABELED_UNICAST)
13697 safi = SAFI_UNICAST;
13698
13699 return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, show_flags);
13700 }
13701
13702 DEFUN (show_ip_bgp_flowspec_routes_detailed,
13703 show_ip_bgp_flowspec_routes_detailed_cmd,
13704 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" flowspec] detail [json]",
13705 SHOW_STR
13706 IP_STR
13707 BGP_STR
13708 BGP_INSTANCE_HELP_STR
13709 BGP_AFI_HELP_STR
13710 "SAFI Flowspec\n"
13711 "Detailed information on flowspec entries\n"
13712 JSON_STR)
13713 {
13714 afi_t afi = AFI_IP;
13715 safi_t safi = SAFI_UNICAST;
13716 struct bgp *bgp = NULL;
13717 int idx = 0;
13718 bool uj = use_json(argc, argv);
13719 uint8_t show_flags = 0;
13720
13721 if (uj) {
13722 argc--;
13723 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13724 }
13725
13726 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13727 &bgp, uj);
13728 if (!idx)
13729 return CMD_WARNING;
13730
13731 return bgp_show(vty, bgp, afi, safi, bgp_show_type_detail, NULL,
13732 show_flags);
13733 }
13734
13735 DEFUN (show_ip_bgp_neighbor_routes,
13736 show_ip_bgp_neighbor_routes_cmd,
13737 "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]",
13738 SHOW_STR
13739 IP_STR
13740 BGP_STR
13741 BGP_INSTANCE_HELP_STR
13742 BGP_AFI_HELP_STR
13743 BGP_SAFI_WITH_LABEL_HELP_STR
13744 "Detailed information on TCP and BGP neighbor connections\n"
13745 "Neighbor to display information about\n"
13746 "Neighbor to display information about\n"
13747 "Neighbor on BGP configured interface\n"
13748 "Display flap statistics of the routes learned from neighbor\n"
13749 "Display the dampened routes received from neighbor\n"
13750 "Display routes learned from neighbor\n"
13751 JSON_STR)
13752 {
13753 char *peerstr = NULL;
13754 struct bgp *bgp = NULL;
13755 afi_t afi = AFI_IP6;
13756 safi_t safi = SAFI_UNICAST;
13757 struct peer *peer;
13758 enum bgp_show_type sh_type = bgp_show_type_neighbor;
13759 int idx = 0;
13760 bool uj = use_json(argc, argv);
13761
13762 if (uj)
13763 argc--;
13764
13765 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13766 &bgp, uj);
13767 if (!idx)
13768 return CMD_WARNING;
13769
13770 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13771 argv_find(argv, argc, "neighbors", &idx);
13772 peerstr = argv[++idx]->arg;
13773
13774 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
13775 if (!peer)
13776 return CMD_WARNING;
13777
13778 if (argv_find(argv, argc, "flap-statistics", &idx))
13779 sh_type = bgp_show_type_flap_neighbor;
13780 else if (argv_find(argv, argc, "dampened-routes", &idx))
13781 sh_type = bgp_show_type_damp_neighbor;
13782 else if (argv_find(argv, argc, "routes", &idx))
13783 sh_type = bgp_show_type_neighbor;
13784
13785 return bgp_show_neighbor_route(vty, peer, afi, safi, sh_type, uj);
13786 }
13787
13788 struct bgp_table *bgp_distance_table[AFI_MAX][SAFI_MAX];
13789
13790 struct bgp_distance {
13791 /* Distance value for the IP source prefix. */
13792 uint8_t distance;
13793
13794 /* Name of the access-list to be matched. */
13795 char *access_list;
13796 };
13797
13798 DEFUN (show_bgp_afi_vpn_rd_route,
13799 show_bgp_afi_vpn_rd_route_cmd,
13800 "show bgp "BGP_AFI_CMD_STR" vpn rd ASN:NN_OR_IP-ADDRESS:NN <A.B.C.D/M|X:X::X:X/M> [json]",
13801 SHOW_STR
13802 BGP_STR
13803 BGP_AFI_HELP_STR
13804 "Address Family modifier\n"
13805 "Display information for a route distinguisher\n"
13806 "Route Distinguisher\n"
13807 "Network in the BGP routing table to display\n"
13808 "Network in the BGP routing table to display\n"
13809 JSON_STR)
13810 {
13811 int ret;
13812 struct prefix_rd prd;
13813 afi_t afi = AFI_MAX;
13814 int idx = 0;
13815
13816 if (!argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
13817 vty_out(vty, "%% Malformed Address Family\n");
13818 return CMD_WARNING;
13819 }
13820
13821 ret = str2prefix_rd(argv[5]->arg, &prd);
13822 if (!ret) {
13823 vty_out(vty, "%% Malformed Route Distinguisher\n");
13824 return CMD_WARNING;
13825 }
13826
13827 return bgp_show_route(vty, NULL, argv[6]->arg, afi, SAFI_MPLS_VPN, &prd,
13828 0, BGP_PATH_SHOW_ALL, use_json(argc, argv));
13829 }
13830
13831 static struct bgp_distance *bgp_distance_new(void)
13832 {
13833 return XCALLOC(MTYPE_BGP_DISTANCE, sizeof(struct bgp_distance));
13834 }
13835
13836 static void bgp_distance_free(struct bgp_distance *bdistance)
13837 {
13838 XFREE(MTYPE_BGP_DISTANCE, bdistance);
13839 }
13840
13841 int bgp_distance_set(uint8_t distance, const char *ip_str,
13842 const char *access_list_str, afi_t afi, safi_t safi,
13843 char *errmsg, size_t errmsg_len)
13844 {
13845 int ret;
13846 struct prefix p;
13847 struct bgp_dest *dest;
13848 struct bgp_distance *bdistance;
13849
13850 ret = str2prefix(ip_str, &p);
13851 if (ret == 0) {
13852 snprintf(errmsg, errmsg_len, "Malformed prefix\n");
13853 return CMD_WARNING_CONFIG_FAILED;
13854 }
13855
13856 /* Get BGP distance node. */
13857 dest = bgp_node_get(bgp_distance_table[afi][safi], &p);
13858 bdistance = bgp_dest_get_bgp_distance_info(dest);
13859 if (bdistance)
13860 bgp_dest_unlock_node(dest);
13861 else {
13862 bdistance = bgp_distance_new();
13863 bgp_dest_set_bgp_distance_info(dest, bdistance);
13864 }
13865
13866 /* Set distance value. */
13867 bdistance->distance = distance;
13868
13869 /* Reset access-list configuration. */
13870 XFREE(MTYPE_AS_LIST, bdistance->access_list);
13871 if (access_list_str)
13872 bdistance->access_list =
13873 XSTRDUP(MTYPE_AS_LIST, access_list_str);
13874
13875 return CMD_SUCCESS;
13876 }
13877
13878 int bgp_distance_unset(uint8_t distance, const char *ip_str,
13879 const char *access_list_str, afi_t afi, safi_t safi,
13880 char *errmsg, size_t errmsg_len)
13881 {
13882 int ret;
13883 struct prefix p;
13884 struct bgp_dest *dest;
13885 struct bgp_distance *bdistance;
13886
13887 ret = str2prefix(ip_str, &p);
13888 if (ret == 0) {
13889 snprintf(errmsg, errmsg_len, "Malformed prefix\n");
13890 return CMD_WARNING_CONFIG_FAILED;
13891 }
13892
13893 dest = bgp_node_lookup(bgp_distance_table[afi][safi], &p);
13894 if (!dest) {
13895 snprintf(errmsg, errmsg_len, "Can't find specified prefix\n");
13896 return CMD_WARNING_CONFIG_FAILED;
13897 }
13898
13899 bdistance = bgp_dest_get_bgp_distance_info(dest);
13900
13901 if (bdistance->distance != distance) {
13902 snprintf(errmsg, errmsg_len,
13903 "Distance does not match configured\n");
13904 return CMD_WARNING_CONFIG_FAILED;
13905 }
13906
13907 XFREE(MTYPE_AS_LIST, bdistance->access_list);
13908 bgp_distance_free(bdistance);
13909
13910 bgp_dest_set_bgp_path_info(dest, NULL);
13911 bgp_dest_unlock_node(dest);
13912 bgp_dest_unlock_node(dest);
13913
13914 return CMD_SUCCESS;
13915 }
13916
13917 /* Apply BGP information to distance method. */
13918 uint8_t bgp_distance_apply(const struct prefix *p, struct bgp_path_info *pinfo,
13919 afi_t afi, safi_t safi, struct bgp *bgp)
13920 {
13921 struct bgp_dest *dest;
13922 struct prefix q = {0};
13923 struct peer *peer;
13924 struct bgp_distance *bdistance;
13925 struct access_list *alist;
13926 struct bgp_static *bgp_static;
13927
13928 if (!bgp)
13929 return 0;
13930
13931 peer = pinfo->peer;
13932
13933 if (pinfo->attr->distance)
13934 return pinfo->attr->distance;
13935
13936 /* Check source address.
13937 * Note: for aggregate route, peer can have unspec af type.
13938 */
13939 if (pinfo->sub_type != BGP_ROUTE_AGGREGATE
13940 && !sockunion2hostprefix(&peer->su, &q))
13941 return 0;
13942
13943 dest = bgp_node_match(bgp_distance_table[afi][safi], &q);
13944 if (dest) {
13945 bdistance = bgp_dest_get_bgp_distance_info(dest);
13946 bgp_dest_unlock_node(dest);
13947
13948 if (bdistance->access_list) {
13949 alist = access_list_lookup(afi, bdistance->access_list);
13950 if (alist
13951 && access_list_apply(alist, p) == FILTER_PERMIT)
13952 return bdistance->distance;
13953 } else
13954 return bdistance->distance;
13955 }
13956
13957 /* Backdoor check. */
13958 dest = bgp_node_lookup(bgp->route[afi][safi], p);
13959 if (dest) {
13960 bgp_static = bgp_dest_get_bgp_static_info(dest);
13961 bgp_dest_unlock_node(dest);
13962
13963 if (bgp_static->backdoor) {
13964 if (bgp->distance_local[afi][safi])
13965 return bgp->distance_local[afi][safi];
13966 else
13967 return ZEBRA_IBGP_DISTANCE_DEFAULT;
13968 }
13969 }
13970
13971 if (peer->sort == BGP_PEER_EBGP) {
13972 if (bgp->distance_ebgp[afi][safi])
13973 return bgp->distance_ebgp[afi][safi];
13974 return ZEBRA_EBGP_DISTANCE_DEFAULT;
13975 } else if (peer->sort == BGP_PEER_IBGP) {
13976 if (bgp->distance_ibgp[afi][safi])
13977 return bgp->distance_ibgp[afi][safi];
13978 return ZEBRA_IBGP_DISTANCE_DEFAULT;
13979 } else {
13980 if (bgp->distance_local[afi][safi])
13981 return bgp->distance_local[afi][safi];
13982 return ZEBRA_IBGP_DISTANCE_DEFAULT;
13983 }
13984 }
13985
13986 /* If we enter `distance bgp (1-255) (1-255) (1-255)`,
13987 * we should tell ZEBRA update the routes for a specific
13988 * AFI/SAFI to reflect changes in RIB.
13989 */
13990 void bgp_announce_routes_distance_update(struct bgp *bgp, afi_t update_afi,
13991 safi_t update_safi)
13992 {
13993 afi_t afi;
13994 safi_t safi;
13995
13996 FOREACH_AFI_SAFI (afi, safi) {
13997 if (!bgp_fibupd_safi(safi))
13998 continue;
13999
14000 if (afi != update_afi && safi != update_safi)
14001 continue;
14002
14003 if (BGP_DEBUG(zebra, ZEBRA))
14004 zlog_debug(
14005 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
14006 __func__, afi, safi);
14007 bgp_zebra_announce_table(bgp, afi, safi);
14008 }
14009 }
14010
14011 DEFUN_YANG(bgp_distance, bgp_distance_cmd,
14012 "distance bgp (1-255) (1-255) (1-255)",
14013 "Define an administrative distance\n"
14014 "BGP distance\n"
14015 "Distance for routes external to the AS\n"
14016 "Distance for routes internal to the AS\n"
14017 "Distance for local routes\n")
14018 {
14019 int idx_number = 2;
14020 int idx_number_2 = 3;
14021 int idx_number_3 = 4;
14022 afi_t afi;
14023 safi_t safi;
14024 char xpath[XPATH_MAXLEN];
14025
14026 afi = bgp_node_afi(vty);
14027 safi = bgp_node_safi(vty);
14028
14029 snprintf(
14030 xpath, sizeof(xpath),
14031 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/external",
14032 yang_afi_safi_value2identity(afi, safi),
14033 bgp_afi_safi_get_container_str(afi, safi));
14034 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, argv[idx_number]->arg);
14035 snprintf(
14036 xpath, sizeof(xpath),
14037 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/internal",
14038 yang_afi_safi_value2identity(afi, safi),
14039 bgp_afi_safi_get_container_str(afi, safi));
14040 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY,
14041 argv[idx_number_2]->arg);
14042 snprintf(
14043 xpath, sizeof(xpath),
14044 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/local",
14045 yang_afi_safi_value2identity(afi, safi),
14046 bgp_afi_safi_get_container_str(afi, safi));
14047
14048 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY,
14049 argv[idx_number_3]->arg);
14050
14051 return nb_cli_apply_changes(vty, NULL);
14052 }
14053
14054 DEFUN_YANG(no_bgp_distance, no_bgp_distance_cmd,
14055 "no distance bgp [(1-255) (1-255) (1-255)]",
14056 NO_STR
14057 "Define an administrative distance\n"
14058 "BGP distance\n"
14059 "Distance for routes external to the AS\n"
14060 "Distance for routes internal to the AS\n"
14061 "Distance for local routes\n")
14062 {
14063 afi_t afi;
14064 safi_t safi;
14065 char xpath[XPATH_MAXLEN];
14066
14067 afi = bgp_node_afi(vty);
14068 safi = bgp_node_safi(vty);
14069
14070 snprintf(
14071 xpath, sizeof(xpath),
14072 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/external",
14073 yang_afi_safi_value2identity(afi, safi),
14074 bgp_afi_safi_get_container_str(afi, safi));
14075 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, NULL);
14076 snprintf(
14077 xpath, sizeof(xpath),
14078 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/internal",
14079 yang_afi_safi_value2identity(afi, safi),
14080 bgp_afi_safi_get_container_str(afi, safi));
14081 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, NULL);
14082 snprintf(
14083 xpath, sizeof(xpath),
14084 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/local",
14085 yang_afi_safi_value2identity(afi, safi),
14086 bgp_afi_safi_get_container_str(afi, safi));
14087
14088 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, NULL);
14089
14090 return nb_cli_apply_changes(vty, NULL);
14091 }
14092
14093 void cli_show_bgp_global_afi_safi_admin_distance_config(struct vty *vty,
14094 struct lyd_node *dnode,
14095 bool show_defaults)
14096 {
14097 uint8_t distance_ebgp, distance_ibgp, distance_local;
14098
14099 distance_ebgp = yang_dnode_get_uint8(dnode, "./external");
14100 distance_ibgp = yang_dnode_get_uint8(dnode, "./internal");
14101 distance_local = yang_dnode_get_uint8(dnode, "./local");
14102
14103 vty_out(vty, " distance bgp %d %d %d\n", distance_ebgp, distance_ibgp,
14104 distance_local);
14105 }
14106
14107 DEFPY_YANG(bgp_distance_source,
14108 bgp_distance_source_cmd,
14109 "[no] distance (1-255) <A.B.C.D/M | X:X::X:X/M>$prefix [WORD$acl]",
14110 NO_STR
14111 "Define an administrative distance\n"
14112 "Distance value\n"
14113 "IPv4 source prefix\n"
14114 "IPv6 source prefix\n"
14115 "Access list name\n")
14116 {
14117 afi_t afi;
14118 safi_t safi;
14119 char xpath[XPATH_MAXLEN];
14120
14121 afi = bgp_node_afi(vty);
14122 safi = bgp_node_safi(vty);
14123
14124 if (!no) {
14125 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
14126 nb_cli_enqueue_change(vty, "./distance", NB_OP_MODIFY,
14127 distance_str);
14128 if (acl)
14129 nb_cli_enqueue_change(vty,
14130 "./access-list-policy-export",
14131 NB_OP_CREATE, acl);
14132 else
14133 nb_cli_enqueue_change(vty,
14134 "./access-list-policy-export",
14135 NB_OP_DESTROY, NULL);
14136 } else {
14137 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
14138 }
14139
14140 snprintf(
14141 xpath, sizeof(xpath),
14142 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance-route[prefix='%s']",
14143 yang_afi_safi_value2identity(afi, safi),
14144 bgp_afi_safi_get_container_str(afi, safi), prefix_str);
14145
14146 return nb_cli_apply_changes(vty, xpath);
14147 }
14148
14149 void cli_show_bgp_global_afi_safi_unicast_admin_distance_route(
14150 struct vty *vty, struct lyd_node *dnode, bool show_defaults)
14151 {
14152 vty_out(vty, " distance %d %s %s\n",
14153 yang_dnode_get_uint8(dnode, "./distance"),
14154 yang_dnode_get_string(dnode, "./prefix"),
14155 (yang_dnode_exists(dnode, "./access-list-policy-export"))
14156 ? yang_dnode_get_string(dnode,
14157 "./access-list-policy-export")
14158 : "");
14159 }
14160
14161 DEFPY_YANG(
14162 bgp_dampening, bgp_dampening_cmd,
14163 "[no] bgp dampening [(1-45)$halflife [(1-20000)$reuse (1-20000)$suppress (1-255)$max_suppress]]",
14164 NO_STR
14165 "BGP Specific commands\n"
14166 "Enable route-flap dampening\n"
14167 "Half-life time for the penalty\n"
14168 "Value to start reusing a route\n"
14169 "Value to start suppressing a route\n"
14170 "Maximum duration to suppress a stable route\n")
14171 {
14172 afi_t afi;
14173 safi_t safi;
14174 char xpath[XPATH_MAXLEN];
14175
14176 afi = bgp_node_afi(vty);
14177 safi = bgp_node_safi(vty);
14178
14179 if (!no) {
14180 nb_cli_enqueue_change(vty, "./enable", NB_OP_MODIFY, "true");
14181 if (argc == 6) {
14182 nb_cli_enqueue_change(vty, "./reach-decay",
14183 NB_OP_MODIFY, halflife_str);
14184 nb_cli_enqueue_change(vty, "./reuse-above",
14185 NB_OP_MODIFY, reuse_str);
14186 nb_cli_enqueue_change(vty, "./suppress-above",
14187 NB_OP_MODIFY, suppress_str);
14188 nb_cli_enqueue_change(vty, "./unreach-decay",
14189 NB_OP_MODIFY, max_suppress_str);
14190 } if (argc == 3) {
14191 nb_cli_enqueue_change(vty, "./reach-decay",
14192 NB_OP_MODIFY, halflife_str);
14193 }
14194 } else {
14195 nb_cli_enqueue_change(vty, "./enable", NB_OP_MODIFY, "false");
14196 }
14197
14198 snprintf(
14199 xpath, sizeof(xpath),
14200 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/route-flap-dampening",
14201 yang_afi_safi_value2identity(afi, safi),
14202 bgp_afi_safi_get_container_str(afi, safi));
14203
14204 return nb_cli_apply_changes(vty, xpath);
14205 }
14206
14207 void cli_show_bgp_global_afi_safi_route_flap_dampening(struct vty *vty,
14208 struct lyd_node *dnode,
14209 bool show_defaults)
14210 {
14211 if (!yang_dnode_get_bool(dnode, "./enable"))
14212 return;
14213
14214 int half = DEFAULT_HALF_LIFE * 60;
14215 int reuse = DEFAULT_REUSE;
14216 int suppress = DEFAULT_SUPPRESS;
14217 int max;
14218
14219 half = yang_dnode_get_uint8(dnode, "../reach-decay");
14220 reuse = yang_dnode_get_uint16(dnode, "../reuse-above");
14221 suppress = yang_dnode_get_uint16(dnode, "../suppress-above");
14222 max = yang_dnode_get_uint8(dnode, "../unreach-decay");
14223
14224 if (half == DEFAULT_HALF_LIFE * 60 && reuse == DEFAULT_REUSE
14225 && suppress == DEFAULT_SUPPRESS && max == half * 4)
14226 vty_out(vty, " bgp dampening\n");
14227 else if (half != DEFAULT_HALF_LIFE * 60 && reuse == DEFAULT_REUSE
14228 && suppress == DEFAULT_SUPPRESS && max == half * 4)
14229 vty_out(vty, " bgp dampening %u\n", half);
14230 else
14231 vty_out(vty, " bgp dampening %u %d %d %d\n", half, reuse,
14232 suppress, max);
14233 }
14234
14235 /* Display specified route of BGP table. */
14236 static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
14237 const char *ip_str, afi_t afi, safi_t safi,
14238 struct prefix_rd *prd, int prefix_check)
14239 {
14240 int ret;
14241 struct prefix match;
14242 struct bgp_dest *dest;
14243 struct bgp_dest *rm;
14244 struct bgp_path_info *pi;
14245 struct bgp_path_info *pi_temp;
14246 struct bgp *bgp;
14247 struct bgp_table *table;
14248
14249 /* BGP structure lookup. */
14250 if (view_name) {
14251 bgp = bgp_lookup_by_name(view_name);
14252 if (bgp == NULL) {
14253 vty_out(vty, "%% Can't find BGP instance %s\n",
14254 view_name);
14255 return CMD_WARNING;
14256 }
14257 } else {
14258 bgp = bgp_get_default();
14259 if (bgp == NULL) {
14260 vty_out(vty, "%% No BGP process is configured\n");
14261 return CMD_WARNING;
14262 }
14263 }
14264
14265 /* Check IP address argument. */
14266 ret = str2prefix(ip_str, &match);
14267 if (!ret) {
14268 vty_out(vty, "%% address is malformed\n");
14269 return CMD_WARNING;
14270 }
14271
14272 match.family = afi2family(afi);
14273
14274 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
14275 || (safi == SAFI_EVPN)) {
14276 for (dest = bgp_table_top(bgp->rib[AFI_IP][safi]); dest;
14277 dest = bgp_route_next(dest)) {
14278 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
14279
14280 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
14281 continue;
14282 table = bgp_dest_get_bgp_table_info(dest);
14283 if (!table)
14284 continue;
14285 if ((rm = bgp_node_match(table, &match)) == NULL)
14286 continue;
14287
14288 const struct prefix *rm_p = bgp_dest_get_prefix(dest);
14289
14290 if (!prefix_check
14291 || rm_p->prefixlen == match.prefixlen) {
14292 pi = bgp_dest_get_bgp_path_info(rm);
14293 while (pi) {
14294 if (pi->extra && pi->extra->damp_info) {
14295 pi_temp = pi->next;
14296 bgp_damp_info_free(
14297 &pi->extra->damp_info,
14298 &bgp->damp[afi][safi],
14299 1, afi, safi);
14300 pi = pi_temp;
14301 } else
14302 pi = pi->next;
14303 }
14304 }
14305
14306 bgp_dest_unlock_node(rm);
14307 }
14308 } else {
14309 if ((dest = bgp_node_match(bgp->rib[afi][safi], &match))
14310 != NULL) {
14311 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
14312
14313 if (!prefix_check
14314 || dest_p->prefixlen == match.prefixlen) {
14315 pi = bgp_dest_get_bgp_path_info(dest);
14316 while (pi) {
14317 if (pi->extra && pi->extra->damp_info) {
14318 pi_temp = pi->next;
14319 struct bgp_damp_info *bdi =
14320 pi->extra->damp_info;
14321 if (bdi->lastrecord
14322 == BGP_RECORD_UPDATE) {
14323 bgp_aggregate_increment(
14324 bgp,
14325 &bdi->dest->p,
14326 bdi->path,
14327 bdi->afi,
14328 bdi->safi);
14329 bgp_process(bgp,
14330 bdi->dest,
14331 bdi->afi,
14332 bdi->safi);
14333 }
14334 bgp_damp_info_free(
14335 &pi->extra->damp_info,
14336 &bgp->damp[afi][safi],
14337 1, afi, safi);
14338 pi = pi_temp;
14339 } else
14340 pi = pi->next;
14341 }
14342 }
14343
14344 bgp_dest_unlock_node(dest);
14345 }
14346 }
14347
14348 return CMD_SUCCESS;
14349 }
14350
14351 DEFUN (clear_ip_bgp_dampening,
14352 clear_ip_bgp_dampening_cmd,
14353 "clear ip bgp dampening",
14354 CLEAR_STR
14355 IP_STR
14356 BGP_STR
14357 "Clear route flap dampening information\n")
14358 {
14359 VTY_DECLVAR_CONTEXT(bgp, bgp);
14360 bgp_damp_info_clean(bgp, &bgp->damp[AFI_IP][SAFI_UNICAST], AFI_IP,
14361 SAFI_UNICAST);
14362 return CMD_SUCCESS;
14363 }
14364
14365 DEFUN (clear_ip_bgp_dampening_prefix,
14366 clear_ip_bgp_dampening_prefix_cmd,
14367 "clear ip bgp dampening A.B.C.D/M",
14368 CLEAR_STR
14369 IP_STR
14370 BGP_STR
14371 "Clear route flap dampening information\n"
14372 "IPv4 prefix\n")
14373 {
14374 int idx_ipv4_prefixlen = 4;
14375 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4_prefixlen]->arg,
14376 AFI_IP, SAFI_UNICAST, NULL, 1);
14377 }
14378
14379 DEFUN (clear_ip_bgp_dampening_address,
14380 clear_ip_bgp_dampening_address_cmd,
14381 "clear ip bgp dampening A.B.C.D",
14382 CLEAR_STR
14383 IP_STR
14384 BGP_STR
14385 "Clear route flap dampening information\n"
14386 "Network to clear damping information\n")
14387 {
14388 int idx_ipv4 = 4;
14389 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4]->arg, AFI_IP,
14390 SAFI_UNICAST, NULL, 0);
14391 }
14392
14393 DEFUN (clear_ip_bgp_dampening_address_mask,
14394 clear_ip_bgp_dampening_address_mask_cmd,
14395 "clear ip bgp dampening A.B.C.D A.B.C.D",
14396 CLEAR_STR
14397 IP_STR
14398 BGP_STR
14399 "Clear route flap dampening information\n"
14400 "Network to clear damping information\n"
14401 "Network mask\n")
14402 {
14403 int idx_ipv4 = 4;
14404 int idx_ipv4_2 = 5;
14405 int ret;
14406 char prefix_str[BUFSIZ];
14407
14408 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
14409 prefix_str, sizeof(prefix_str));
14410 if (!ret) {
14411 vty_out(vty, "%% Inconsistent address and mask\n");
14412 return CMD_WARNING;
14413 }
14414
14415 return bgp_clear_damp_route(vty, NULL, prefix_str, AFI_IP, SAFI_UNICAST,
14416 NULL, 0);
14417 }
14418
14419 static void show_bgp_peerhash_entry(struct hash_bucket *bucket, void *arg)
14420 {
14421 struct vty *vty = arg;
14422 struct peer *peer = bucket->data;
14423 char buf[SU_ADDRSTRLEN];
14424
14425 vty_out(vty, "\tPeer: %s %s\n", peer->host,
14426 sockunion2str(&peer->su, buf, sizeof(buf)));
14427 }
14428
14429 DEFUN (show_bgp_listeners,
14430 show_bgp_listeners_cmd,
14431 "show bgp listeners",
14432 SHOW_STR
14433 BGP_STR
14434 "Display Listen Sockets and who created them\n")
14435 {
14436 bgp_dump_listener_info(vty);
14437
14438 return CMD_SUCCESS;
14439 }
14440
14441 DEFUN (show_bgp_peerhash,
14442 show_bgp_peerhash_cmd,
14443 "show bgp peerhash",
14444 SHOW_STR
14445 BGP_STR
14446 "Display information about the BGP peerhash\n")
14447 {
14448 struct list *instances = bm->bgp;
14449 struct listnode *node;
14450 struct bgp *bgp;
14451
14452 for (ALL_LIST_ELEMENTS_RO(instances, node, bgp)) {
14453 vty_out(vty, "BGP: %s\n", bgp->name);
14454 hash_iterate(bgp->peerhash, show_bgp_peerhash_entry,
14455 vty);
14456 }
14457
14458 return CMD_SUCCESS;
14459 }
14460
14461 /* also used for encap safi */
14462 static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
14463 afi_t afi, safi_t safi)
14464 {
14465 struct bgp_dest *pdest;
14466 struct bgp_dest *dest;
14467 struct bgp_table *table;
14468 const struct prefix *p;
14469 const struct prefix_rd *prd;
14470 struct bgp_static *bgp_static;
14471 mpls_label_t label;
14472 char rdbuf[RD_ADDRSTRLEN];
14473
14474 /* Network configuration. */
14475 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
14476 pdest = bgp_route_next(pdest)) {
14477 table = bgp_dest_get_bgp_table_info(pdest);
14478 if (!table)
14479 continue;
14480
14481 for (dest = bgp_table_top(table); dest;
14482 dest = bgp_route_next(dest)) {
14483 bgp_static = bgp_dest_get_bgp_static_info(dest);
14484 if (bgp_static == NULL)
14485 continue;
14486
14487 p = bgp_dest_get_prefix(dest);
14488 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
14489 pdest);
14490
14491 /* "network" configuration display. */
14492 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
14493 label = decode_label(&bgp_static->label);
14494
14495 vty_out(vty, " network %pFX rd %s", p, rdbuf);
14496 if (safi == SAFI_MPLS_VPN)
14497 vty_out(vty, " label %u", label);
14498
14499 if (bgp_static->rmap.name)
14500 vty_out(vty, " route-map %s",
14501 bgp_static->rmap.name);
14502
14503 if (bgp_static->backdoor)
14504 vty_out(vty, " backdoor");
14505
14506 vty_out(vty, "\n");
14507 }
14508 }
14509 }
14510
14511 static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
14512 afi_t afi, safi_t safi)
14513 {
14514 struct bgp_dest *pdest;
14515 struct bgp_dest *dest;
14516 struct bgp_table *table;
14517 const struct prefix *p;
14518 const struct prefix_rd *prd;
14519 struct bgp_static *bgp_static;
14520 char buf[PREFIX_STRLEN * 2];
14521 char buf2[SU_ADDRSTRLEN];
14522 char rdbuf[RD_ADDRSTRLEN];
14523 char esi_buf[ESI_BYTES];
14524
14525 /* Network configuration. */
14526 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
14527 pdest = bgp_route_next(pdest)) {
14528 table = bgp_dest_get_bgp_table_info(pdest);
14529 if (!table)
14530 continue;
14531
14532 for (dest = bgp_table_top(table); dest;
14533 dest = bgp_route_next(dest)) {
14534 bgp_static = bgp_dest_get_bgp_static_info(dest);
14535 if (bgp_static == NULL)
14536 continue;
14537
14538 char *macrouter = NULL;
14539
14540 if (bgp_static->router_mac)
14541 macrouter = prefix_mac2str(
14542 bgp_static->router_mac, NULL, 0);
14543 if (bgp_static->eth_s_id)
14544 esi_to_str(bgp_static->eth_s_id,
14545 esi_buf, sizeof(esi_buf));
14546 p = bgp_dest_get_prefix(dest);
14547 prd = (struct prefix_rd *)bgp_dest_get_prefix(pdest);
14548
14549 /* "network" configuration display. */
14550 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
14551 if (p->u.prefix_evpn.route_type == 5) {
14552 char local_buf[PREFIX_STRLEN];
14553 uint8_t family = is_evpn_prefix_ipaddr_v4((
14554 struct prefix_evpn *)p)
14555 ? AF_INET
14556 : AF_INET6;
14557 inet_ntop(family,
14558 &p->u.prefix_evpn.prefix_addr.ip.ip.addr,
14559 local_buf, PREFIX_STRLEN);
14560 snprintf(buf, sizeof(buf), "%s/%u", local_buf,
14561 p->u.prefix_evpn.prefix_addr
14562 .ip_prefix_length);
14563 } else {
14564 prefix2str(p, buf, sizeof(buf));
14565 }
14566
14567 if (bgp_static->gatewayIp.family == AF_INET
14568 || bgp_static->gatewayIp.family == AF_INET6)
14569 inet_ntop(bgp_static->gatewayIp.family,
14570 &bgp_static->gatewayIp.u.prefix, buf2,
14571 sizeof(buf2));
14572 vty_out(vty,
14573 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
14574 buf, rdbuf,
14575 p->u.prefix_evpn.prefix_addr.eth_tag,
14576 decode_label(&bgp_static->label), esi_buf, buf2,
14577 macrouter);
14578
14579 XFREE(MTYPE_TMP, macrouter);
14580 }
14581 }
14582 }
14583
14584 /* Configuration of static route announcement and aggregate
14585 information. */
14586 void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
14587 safi_t safi)
14588 {
14589 struct bgp_dest *dest;
14590 const struct prefix *p;
14591 struct bgp_static *bgp_static;
14592 struct bgp_aggregate *bgp_aggregate;
14593
14594 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) {
14595 bgp_config_write_network_vpn(vty, bgp, afi, safi);
14596 return;
14597 }
14598
14599 if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
14600 bgp_config_write_network_evpn(vty, bgp, afi, safi);
14601 return;
14602 }
14603
14604 /* Network configuration. */
14605 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
14606 dest = bgp_route_next(dest)) {
14607 bgp_static = bgp_dest_get_bgp_static_info(dest);
14608 if (bgp_static == NULL)
14609 continue;
14610
14611 p = bgp_dest_get_prefix(dest);
14612
14613 vty_out(vty, " network %pFX", p);
14614
14615 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX)
14616 vty_out(vty, " label-index %u",
14617 bgp_static->label_index);
14618
14619 if (bgp_static->rmap.name)
14620 vty_out(vty, " route-map %s", bgp_static->rmap.name);
14621
14622 if (bgp_static->backdoor)
14623 vty_out(vty, " backdoor");
14624
14625 vty_out(vty, "\n");
14626 }
14627
14628 /* Aggregate-address configuration. */
14629 for (dest = bgp_table_top(bgp->aggregate[afi][safi]); dest;
14630 dest = bgp_route_next(dest)) {
14631 bgp_aggregate = bgp_dest_get_bgp_aggregate_info(dest);
14632 if (bgp_aggregate == NULL)
14633 continue;
14634
14635 p = bgp_dest_get_prefix(dest);
14636
14637 vty_out(vty, " aggregate-address %pFX", p);
14638
14639 if (bgp_aggregate->as_set)
14640 vty_out(vty, " as-set");
14641
14642 if (bgp_aggregate->summary_only)
14643 vty_out(vty, " summary-only");
14644
14645 if (bgp_aggregate->rmap.name)
14646 vty_out(vty, " route-map %s", bgp_aggregate->rmap.name);
14647
14648 if (bgp_aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
14649 vty_out(vty, " origin %s",
14650 bgp_origin2str(bgp_aggregate->origin));
14651
14652 if (bgp_aggregate->match_med)
14653 vty_out(vty, " matching-MED-only");
14654
14655 if (bgp_aggregate->suppress_map_name)
14656 vty_out(vty, " suppress-map %s",
14657 bgp_aggregate->suppress_map_name);
14658
14659 vty_out(vty, "\n");
14660 }
14661 }
14662
14663 void bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
14664 safi_t safi)
14665 {
14666 struct bgp_dest *dest;
14667 struct bgp_distance *bdistance;
14668
14669 /* Distance configuration. */
14670 if (bgp->distance_ebgp[afi][safi] && bgp->distance_ibgp[afi][safi]
14671 && bgp->distance_local[afi][safi]
14672 && (bgp->distance_ebgp[afi][safi] != ZEBRA_EBGP_DISTANCE_DEFAULT
14673 || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT
14674 || bgp->distance_local[afi][safi]
14675 != ZEBRA_IBGP_DISTANCE_DEFAULT)) {
14676 vty_out(vty, " distance bgp %d %d %d\n",
14677 bgp->distance_ebgp[afi][safi],
14678 bgp->distance_ibgp[afi][safi],
14679 bgp->distance_local[afi][safi]);
14680 }
14681
14682 for (dest = bgp_table_top(bgp_distance_table[afi][safi]); dest;
14683 dest = bgp_route_next(dest)) {
14684 bdistance = bgp_dest_get_bgp_distance_info(dest);
14685 if (bdistance != NULL)
14686 vty_out(vty, " distance %d %pBD %s\n",
14687 bdistance->distance, dest,
14688 bdistance->access_list ? bdistance->access_list
14689 : "");
14690 }
14691 }
14692
14693 /* Allocate routing table structure and install commands. */
14694 void bgp_route_init(void)
14695 {
14696 afi_t afi;
14697 safi_t safi;
14698
14699 /* Init BGP distance table. */
14700 FOREACH_AFI_SAFI (afi, safi)
14701 bgp_distance_table[afi][safi] = bgp_table_init(NULL, afi, safi);
14702
14703 /* IPv4 BGP commands. */
14704 install_element(BGP_NODE, &bgp_table_map_cmd);
14705 install_element(BGP_NODE, &bgp_network_cmd);
14706 install_element(BGP_NODE, &no_bgp_table_map_cmd);
14707
14708 install_element(BGP_NODE, &aggregate_addressv4_cmd);
14709
14710 /* IPv4 unicast configuration. */
14711 install_element(BGP_IPV4_NODE, &bgp_table_map_cmd);
14712 install_element(BGP_IPV4_NODE, &bgp_network_cmd);
14713 install_element(BGP_IPV4_NODE, &no_bgp_table_map_cmd);
14714
14715 install_element(BGP_IPV4_NODE, &aggregate_addressv4_cmd);
14716
14717 /* IPv4 multicast configuration. */
14718 install_element(BGP_IPV4M_NODE, &bgp_table_map_cmd);
14719 install_element(BGP_IPV4M_NODE, &bgp_network_cmd);
14720 install_element(BGP_IPV4M_NODE, &no_bgp_table_map_cmd);
14721 install_element(BGP_IPV4M_NODE, &aggregate_addressv4_cmd);
14722
14723 /* IPv4 labeled-unicast configuration. */
14724 install_element(BGP_IPV4L_NODE, &bgp_network_cmd);
14725 install_element(BGP_IPV4L_NODE, &aggregate_addressv4_cmd);
14726
14727 install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd);
14728 install_element(VIEW_NODE, &show_ip_bgp_cmd);
14729 install_element(VIEW_NODE, &show_ip_bgp_afi_safi_statistics_cmd);
14730 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_statistics_cmd);
14731 install_element(VIEW_NODE, &show_ip_bgp_json_cmd);
14732 install_element(VIEW_NODE, &show_ip_bgp_route_cmd);
14733 install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd);
14734 install_element(VIEW_NODE, &show_ip_bgp_statistics_all_cmd);
14735
14736 install_element(VIEW_NODE,
14737 &show_ip_bgp_instance_neighbor_advertised_route_cmd);
14738 install_element(VIEW_NODE,
14739 &show_ip_bgp_instance_neighbor_bestpath_route_cmd);
14740 install_element(VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd);
14741 install_element(VIEW_NODE,
14742 &show_ip_bgp_neighbor_received_prefix_filter_cmd);
14743 #ifdef KEEP_OLD_VPN_COMMANDS
14744 install_element(VIEW_NODE, &show_ip_bgp_vpn_all_route_prefix_cmd);
14745 #endif /* KEEP_OLD_VPN_COMMANDS */
14746 install_element(VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd);
14747 install_element(VIEW_NODE,
14748 &show_bgp_l2vpn_evpn_route_prefix_cmd);
14749
14750 /* BGP dampening clear commands */
14751 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
14752 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_prefix_cmd);
14753
14754 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd);
14755 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd);
14756
14757 /* prefix count */
14758 install_element(ENABLE_NODE,
14759 &show_ip_bgp_instance_neighbor_prefix_counts_cmd);
14760 #ifdef KEEP_OLD_VPN_COMMANDS
14761 install_element(ENABLE_NODE,
14762 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd);
14763 #endif /* KEEP_OLD_VPN_COMMANDS */
14764
14765 /* New config IPv6 BGP commands. */
14766 install_element(BGP_IPV6_NODE, &bgp_table_map_cmd);
14767 install_element(BGP_IPV6_NODE, &ipv6_bgp_network_cmd);
14768 install_element(BGP_IPV6_NODE, &no_bgp_table_map_cmd);
14769
14770 install_element(BGP_IPV6_NODE, &aggregate_addressv6_cmd);
14771
14772 install_element(BGP_IPV6M_NODE, &ipv6_bgp_network_cmd);
14773
14774 /* IPv6 labeled unicast address family. */
14775 install_element(BGP_IPV6L_NODE, &ipv6_bgp_network_cmd);
14776 install_element(BGP_IPV6L_NODE, &aggregate_addressv6_cmd);
14777
14778 install_element(BGP_NODE, &bgp_distance_cmd);
14779 install_element(BGP_NODE, &no_bgp_distance_cmd);
14780 install_element(BGP_NODE, &bgp_distance_source_cmd);
14781 install_element(BGP_IPV4_NODE, &bgp_distance_cmd);
14782 install_element(BGP_IPV4_NODE, &no_bgp_distance_cmd);
14783 install_element(BGP_IPV4_NODE, &bgp_distance_source_cmd);
14784 install_element(BGP_IPV4M_NODE, &bgp_distance_cmd);
14785 install_element(BGP_IPV4M_NODE, &no_bgp_distance_cmd);
14786 install_element(BGP_IPV4M_NODE, &bgp_distance_source_cmd);
14787 install_element(BGP_IPV6_NODE, &bgp_distance_cmd);
14788 install_element(BGP_IPV6_NODE, &no_bgp_distance_cmd);
14789 install_element(BGP_IPV6_NODE, &bgp_distance_source_cmd);
14790 install_element(BGP_IPV6M_NODE, &bgp_distance_cmd);
14791 install_element(BGP_IPV6M_NODE, &no_bgp_distance_cmd);
14792 install_element(BGP_IPV6M_NODE, &bgp_distance_source_cmd);
14793
14794 /* BGP dampening */
14795 install_element(BGP_NODE, &bgp_dampening_cmd);
14796 install_element(BGP_IPV4_NODE, &bgp_dampening_cmd);
14797 install_element(BGP_IPV4M_NODE, &bgp_dampening_cmd);
14798 install_element(BGP_IPV4L_NODE, &bgp_dampening_cmd);
14799 install_element(BGP_IPV6_NODE, &bgp_dampening_cmd);
14800 install_element(BGP_IPV6M_NODE, &bgp_dampening_cmd);
14801 install_element(BGP_IPV6L_NODE, &bgp_dampening_cmd);
14802
14803 /* Large Communities */
14804 install_element(VIEW_NODE, &show_ip_bgp_large_community_list_cmd);
14805 install_element(VIEW_NODE, &show_ip_bgp_large_community_cmd);
14806
14807 /* show bgp ipv4 flowspec detailed */
14808 install_element(VIEW_NODE, &show_ip_bgp_flowspec_routes_detailed_cmd);
14809
14810 install_element(VIEW_NODE, &show_bgp_listeners_cmd);
14811 install_element(VIEW_NODE, &show_bgp_peerhash_cmd);
14812 }
14813
14814 void bgp_route_finish(void)
14815 {
14816 afi_t afi;
14817 safi_t safi;
14818
14819 FOREACH_AFI_SAFI (afi, safi) {
14820 bgp_table_unlock(bgp_distance_table[afi][safi]);
14821 bgp_distance_table[afi][safi] = NULL;
14822 }
14823 }