]> git.proxmox.com Git - mirror_frr.git/blob - bgpd/bgp_route.c
Merge pull request #8099 from donaldsharp/more_ignore_revs
[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 {
530 if (pi->addpath_rx_id)
531 sprintf(buf, "path %s (addpath rxid %d)", pi->peer->host,
532 pi->addpath_rx_id);
533 else
534 sprintf(buf, "path %s", pi->peer->host);
535 }
536
537 /* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
538 */
539 static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
540 struct bgp_path_info *exist, int *paths_eq,
541 struct bgp_maxpaths_cfg *mpath_cfg, int debug,
542 char *pfx_buf, afi_t afi, safi_t safi,
543 enum bgp_path_selection_reason *reason)
544 {
545 struct attr *newattr, *existattr;
546 bgp_peer_sort_t new_sort;
547 bgp_peer_sort_t exist_sort;
548 uint32_t new_pref;
549 uint32_t exist_pref;
550 uint32_t new_med;
551 uint32_t exist_med;
552 uint32_t new_weight;
553 uint32_t exist_weight;
554 uint32_t newm, existm;
555 struct in_addr new_id;
556 struct in_addr exist_id;
557 int new_cluster;
558 int exist_cluster;
559 int internal_as_route;
560 int confed_as_route;
561 int ret = 0;
562 char new_buf[PATH_ADDPATH_STR_BUFFER];
563 char exist_buf[PATH_ADDPATH_STR_BUFFER];
564 uint32_t new_mm_seq;
565 uint32_t exist_mm_seq;
566 int nh_cmp;
567 esi_t *exist_esi;
568 esi_t *new_esi;
569 bool same_esi;
570 bool old_proxy;
571 bool new_proxy;
572 bool new_origin, exist_origin;
573
574 *paths_eq = 0;
575
576 /* 0. Null check. */
577 if (new == NULL) {
578 *reason = bgp_path_selection_none;
579 if (debug)
580 zlog_debug("%s: new is NULL", pfx_buf);
581 return 0;
582 }
583
584 if (debug)
585 bgp_path_info_path_with_addpath_rx_str(new, new_buf);
586
587 if (exist == NULL) {
588 *reason = bgp_path_selection_first;
589 if (debug)
590 zlog_debug("%s: %s is the initial bestpath", pfx_buf,
591 new_buf);
592 return 1;
593 }
594
595 if (debug) {
596 bgp_path_info_path_with_addpath_rx_str(exist, exist_buf);
597 zlog_debug("%s: Comparing %s flags 0x%x with %s flags 0x%x",
598 pfx_buf, new_buf, new->flags, exist_buf,
599 exist->flags);
600 }
601
602 newattr = new->attr;
603 existattr = exist->attr;
604
605 /* For EVPN routes, we cannot just go by local vs remote, we have to
606 * look at the MAC mobility sequence number, if present.
607 */
608 if (safi == SAFI_EVPN) {
609 /* This is an error condition described in RFC 7432 Section
610 * 15.2. The RFC
611 * states that in this scenario "the PE MUST alert the operator"
612 * but it
613 * does not state what other action to take. In order to provide
614 * some
615 * consistency in this scenario we are going to prefer the path
616 * with the
617 * sticky flag.
618 */
619 if (newattr->sticky != existattr->sticky) {
620 if (!debug) {
621 prefix2str(
622 bgp_dest_get_prefix(new->net), pfx_buf,
623 sizeof(*pfx_buf) * PREFIX2STR_BUFFER);
624 bgp_path_info_path_with_addpath_rx_str(new,
625 new_buf);
626 bgp_path_info_path_with_addpath_rx_str(
627 exist, exist_buf);
628 }
629
630 if (newattr->sticky && !existattr->sticky) {
631 *reason = bgp_path_selection_evpn_sticky_mac;
632 if (debug)
633 zlog_debug(
634 "%s: %s wins over %s due to sticky MAC flag",
635 pfx_buf, new_buf, exist_buf);
636 return 1;
637 }
638
639 if (!newattr->sticky && existattr->sticky) {
640 *reason = bgp_path_selection_evpn_sticky_mac;
641 if (debug)
642 zlog_debug(
643 "%s: %s loses to %s due to sticky MAC flag",
644 pfx_buf, new_buf, exist_buf);
645 return 0;
646 }
647 }
648
649 new_esi = bgp_evpn_attr_get_esi(newattr);
650 exist_esi = bgp_evpn_attr_get_esi(existattr);
651 if (bgp_evpn_is_esi_valid(new_esi) &&
652 !memcmp(new_esi, exist_esi, sizeof(esi_t))) {
653 same_esi = true;
654 } else {
655 same_esi = false;
656 }
657
658 /* If both paths have the same non-zero ES and
659 * one path is local it wins.
660 * PS: Note the local path wins even if the remote
661 * has the higher MM seq. The local path's
662 * MM seq will be fixed up to match the highest
663 * rem seq, subsequently.
664 */
665 if (same_esi) {
666 char esi_buf[ESI_STR_LEN];
667
668 if (bgp_evpn_is_path_local(bgp, new)) {
669 *reason = bgp_path_selection_evpn_local_path;
670 if (debug)
671 zlog_debug(
672 "%s: %s wins over %s as ES %s is same and local",
673 pfx_buf, new_buf, exist_buf,
674 esi_to_str(new_esi, esi_buf,
675 sizeof(esi_buf)));
676 return 1;
677 }
678 if (bgp_evpn_is_path_local(bgp, exist)) {
679 *reason = bgp_path_selection_evpn_local_path;
680 if (debug)
681 zlog_debug(
682 "%s: %s loses to %s as ES %s is same and local",
683 pfx_buf, new_buf, exist_buf,
684 esi_to_str(new_esi, esi_buf,
685 sizeof(esi_buf)));
686 return 0;
687 }
688 }
689
690 new_mm_seq = mac_mobility_seqnum(newattr);
691 exist_mm_seq = mac_mobility_seqnum(existattr);
692
693 if (new_mm_seq > exist_mm_seq) {
694 *reason = bgp_path_selection_evpn_seq;
695 if (debug)
696 zlog_debug(
697 "%s: %s wins over %s due to MM seq %u > %u",
698 pfx_buf, new_buf, exist_buf, new_mm_seq,
699 exist_mm_seq);
700 return 1;
701 }
702
703 if (new_mm_seq < exist_mm_seq) {
704 *reason = bgp_path_selection_evpn_seq;
705 if (debug)
706 zlog_debug(
707 "%s: %s loses to %s due to MM seq %u < %u",
708 pfx_buf, new_buf, exist_buf, new_mm_seq,
709 exist_mm_seq);
710 return 0;
711 }
712
713 /* if the sequence numbers and ESI are the same and one path
714 * is non-proxy it wins (over proxy)
715 */
716 new_proxy = bgp_evpn_attr_is_proxy(newattr);
717 old_proxy = bgp_evpn_attr_is_proxy(existattr);
718 if (same_esi && bgp_evpn_attr_is_local_es(newattr) &&
719 old_proxy != new_proxy) {
720 if (!new_proxy) {
721 *reason = bgp_path_selection_evpn_non_proxy;
722 if (debug)
723 zlog_debug(
724 "%s: %s wins over %s, same seq/es and non-proxy",
725 pfx_buf, new_buf, exist_buf);
726 return 1;
727 }
728
729 *reason = bgp_path_selection_evpn_non_proxy;
730 if (debug)
731 zlog_debug(
732 "%s: %s loses to %s, same seq/es and non-proxy",
733 pfx_buf, new_buf, exist_buf);
734 return 0;
735 }
736
737 /*
738 * if sequence numbers are the same path with the lowest IP
739 * wins
740 */
741 nh_cmp = bgp_path_info_nexthop_cmp(new, exist);
742 if (nh_cmp < 0) {
743 *reason = bgp_path_selection_evpn_lower_ip;
744 if (debug)
745 zlog_debug(
746 "%s: %s wins over %s due to same MM seq %u and lower IP %pI4",
747 pfx_buf, new_buf, exist_buf, new_mm_seq,
748 &new->attr->nexthop);
749 return 1;
750 }
751 if (nh_cmp > 0) {
752 *reason = bgp_path_selection_evpn_lower_ip;
753 if (debug)
754 zlog_debug(
755 "%s: %s loses to %s due to same MM seq %u and higher IP %pI4",
756 pfx_buf, new_buf, exist_buf, new_mm_seq,
757 &new->attr->nexthop);
758 return 0;
759 }
760 }
761
762 /* 1. Weight check. */
763 new_weight = newattr->weight;
764 exist_weight = existattr->weight;
765
766 if (new_weight > exist_weight) {
767 *reason = bgp_path_selection_weight;
768 if (debug)
769 zlog_debug("%s: %s wins over %s due to weight %d > %d",
770 pfx_buf, new_buf, exist_buf, new_weight,
771 exist_weight);
772 return 1;
773 }
774
775 if (new_weight < exist_weight) {
776 *reason = bgp_path_selection_weight;
777 if (debug)
778 zlog_debug("%s: %s loses to %s due to weight %d < %d",
779 pfx_buf, new_buf, exist_buf, new_weight,
780 exist_weight);
781 return 0;
782 }
783
784 /* 2. Local preference check. */
785 new_pref = exist_pref = bgp->default_local_pref;
786
787 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
788 new_pref = newattr->local_pref;
789 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
790 exist_pref = existattr->local_pref;
791
792 if (new_pref > exist_pref) {
793 *reason = bgp_path_selection_local_pref;
794 if (debug)
795 zlog_debug(
796 "%s: %s wins over %s due to localpref %d > %d",
797 pfx_buf, new_buf, exist_buf, new_pref,
798 exist_pref);
799 return 1;
800 }
801
802 if (new_pref < exist_pref) {
803 *reason = bgp_path_selection_local_pref;
804 if (debug)
805 zlog_debug(
806 "%s: %s loses to %s due to localpref %d < %d",
807 pfx_buf, new_buf, exist_buf, new_pref,
808 exist_pref);
809 return 0;
810 }
811
812 /* 3. Local route check. We prefer:
813 * - BGP_ROUTE_STATIC
814 * - BGP_ROUTE_AGGREGATE
815 * - BGP_ROUTE_REDISTRIBUTE
816 */
817 new_origin = !(new->sub_type == BGP_ROUTE_NORMAL ||
818 new->sub_type == BGP_ROUTE_IMPORTED);
819 exist_origin = !(exist->sub_type == BGP_ROUTE_NORMAL ||
820 exist->sub_type == BGP_ROUTE_IMPORTED);
821
822 if (new_origin && !exist_origin) {
823 *reason = bgp_path_selection_local_route;
824 if (debug)
825 zlog_debug(
826 "%s: %s wins over %s due to preferred BGP_ROUTE type",
827 pfx_buf, new_buf, exist_buf);
828 return 1;
829 }
830
831 if (!new_origin && exist_origin) {
832 *reason = bgp_path_selection_local_route;
833 if (debug)
834 zlog_debug(
835 "%s: %s loses to %s due to preferred BGP_ROUTE type",
836 pfx_buf, new_buf, exist_buf);
837 return 0;
838 }
839
840 /* 4. AS path length check. */
841 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_IGNORE)) {
842 int exist_hops = aspath_count_hops(existattr->aspath);
843 int exist_confeds = aspath_count_confeds(existattr->aspath);
844
845 if (CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_CONFED)) {
846 int aspath_hops;
847
848 aspath_hops = aspath_count_hops(newattr->aspath);
849 aspath_hops += aspath_count_confeds(newattr->aspath);
850
851 if (aspath_hops < (exist_hops + exist_confeds)) {
852 *reason = bgp_path_selection_confed_as_path;
853 if (debug)
854 zlog_debug(
855 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
856 pfx_buf, new_buf, exist_buf,
857 aspath_hops,
858 (exist_hops + exist_confeds));
859 return 1;
860 }
861
862 if (aspath_hops > (exist_hops + exist_confeds)) {
863 *reason = bgp_path_selection_confed_as_path;
864 if (debug)
865 zlog_debug(
866 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
867 pfx_buf, new_buf, exist_buf,
868 aspath_hops,
869 (exist_hops + exist_confeds));
870 return 0;
871 }
872 } else {
873 int newhops = aspath_count_hops(newattr->aspath);
874
875 if (newhops < exist_hops) {
876 *reason = bgp_path_selection_as_path;
877 if (debug)
878 zlog_debug(
879 "%s: %s wins over %s due to aspath hopcount %d < %d",
880 pfx_buf, new_buf, exist_buf,
881 newhops, exist_hops);
882 return 1;
883 }
884
885 if (newhops > exist_hops) {
886 *reason = bgp_path_selection_as_path;
887 if (debug)
888 zlog_debug(
889 "%s: %s loses to %s due to aspath hopcount %d > %d",
890 pfx_buf, new_buf, exist_buf,
891 newhops, exist_hops);
892 return 0;
893 }
894 }
895 }
896
897 /* 5. Origin check. */
898 if (newattr->origin < existattr->origin) {
899 *reason = bgp_path_selection_origin;
900 if (debug)
901 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
902 pfx_buf, new_buf, exist_buf,
903 bgp_origin_long_str[newattr->origin],
904 bgp_origin_long_str[existattr->origin]);
905 return 1;
906 }
907
908 if (newattr->origin > existattr->origin) {
909 *reason = bgp_path_selection_origin;
910 if (debug)
911 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
912 pfx_buf, new_buf, exist_buf,
913 bgp_origin_long_str[newattr->origin],
914 bgp_origin_long_str[existattr->origin]);
915 return 0;
916 }
917
918 /* 6. MED check. */
919 internal_as_route = (aspath_count_hops(newattr->aspath) == 0
920 && aspath_count_hops(existattr->aspath) == 0);
921 confed_as_route = (aspath_count_confeds(newattr->aspath) > 0
922 && aspath_count_confeds(existattr->aspath) > 0
923 && aspath_count_hops(newattr->aspath) == 0
924 && aspath_count_hops(existattr->aspath) == 0);
925
926 if (CHECK_FLAG(bgp->flags, BGP_FLAG_ALWAYS_COMPARE_MED)
927 || (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_CONFED) && confed_as_route)
928 || aspath_cmp_left(newattr->aspath, existattr->aspath)
929 || aspath_cmp_left_confed(newattr->aspath, existattr->aspath)
930 || internal_as_route) {
931 new_med = bgp_med_value(new->attr, bgp);
932 exist_med = bgp_med_value(exist->attr, bgp);
933
934 if (new_med < exist_med) {
935 *reason = bgp_path_selection_med;
936 if (debug)
937 zlog_debug(
938 "%s: %s wins over %s due to MED %d < %d",
939 pfx_buf, new_buf, exist_buf, new_med,
940 exist_med);
941 return 1;
942 }
943
944 if (new_med > exist_med) {
945 *reason = bgp_path_selection_med;
946 if (debug)
947 zlog_debug(
948 "%s: %s loses to %s due to MED %d > %d",
949 pfx_buf, new_buf, exist_buf, new_med,
950 exist_med);
951 return 0;
952 }
953 }
954
955 /* 7. Peer type check. */
956 new_sort = new->peer->sort;
957 exist_sort = exist->peer->sort;
958
959 if (new_sort == BGP_PEER_EBGP
960 && (exist_sort == BGP_PEER_IBGP || exist_sort == BGP_PEER_CONFED)) {
961 *reason = bgp_path_selection_peer;
962 if (debug)
963 zlog_debug(
964 "%s: %s wins over %s due to eBGP peer > iBGP peer",
965 pfx_buf, new_buf, exist_buf);
966 return 1;
967 }
968
969 if (exist_sort == BGP_PEER_EBGP
970 && (new_sort == BGP_PEER_IBGP || new_sort == BGP_PEER_CONFED)) {
971 *reason = bgp_path_selection_peer;
972 if (debug)
973 zlog_debug(
974 "%s: %s loses to %s due to iBGP peer < eBGP peer",
975 pfx_buf, new_buf, exist_buf);
976 return 0;
977 }
978
979 /* 8. IGP metric check. */
980 newm = existm = 0;
981
982 if (new->extra)
983 newm = new->extra->igpmetric;
984 if (exist->extra)
985 existm = exist->extra->igpmetric;
986
987 if (newm < existm) {
988 if (debug)
989 zlog_debug(
990 "%s: %s wins over %s due to IGP metric %d < %d",
991 pfx_buf, new_buf, exist_buf, newm, existm);
992 ret = 1;
993 }
994
995 if (newm > existm) {
996 if (debug)
997 zlog_debug(
998 "%s: %s loses to %s due to IGP metric %d > %d",
999 pfx_buf, new_buf, exist_buf, newm, existm);
1000 ret = 0;
1001 }
1002
1003 /* 9. Same IGP metric. Compare the cluster list length as
1004 representative of IGP hops metric. Rewrite the metric value
1005 pair (newm, existm) with the cluster list length. Prefer the
1006 path with smaller cluster list length. */
1007 if (newm == existm) {
1008 if (peer_sort_lookup(new->peer) == BGP_PEER_IBGP
1009 && peer_sort_lookup(exist->peer) == BGP_PEER_IBGP
1010 && (mpath_cfg == NULL
1011 || CHECK_FLAG(
1012 mpath_cfg->ibgp_flags,
1013 BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN))) {
1014 newm = BGP_CLUSTER_LIST_LENGTH(new->attr);
1015 existm = BGP_CLUSTER_LIST_LENGTH(exist->attr);
1016
1017 if (newm < existm) {
1018 if (debug)
1019 zlog_debug(
1020 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1021 pfx_buf, new_buf, exist_buf,
1022 newm, existm);
1023 ret = 1;
1024 }
1025
1026 if (newm > existm) {
1027 if (debug)
1028 zlog_debug(
1029 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1030 pfx_buf, new_buf, exist_buf,
1031 newm, existm);
1032 ret = 0;
1033 }
1034 }
1035 }
1036
1037 /* 10. confed-external vs. confed-internal */
1038 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
1039 if (new_sort == BGP_PEER_CONFED
1040 && exist_sort == BGP_PEER_IBGP) {
1041 *reason = bgp_path_selection_confed;
1042 if (debug)
1043 zlog_debug(
1044 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
1045 pfx_buf, new_buf, exist_buf);
1046 return 1;
1047 }
1048
1049 if (exist_sort == BGP_PEER_CONFED
1050 && new_sort == BGP_PEER_IBGP) {
1051 *reason = bgp_path_selection_confed;
1052 if (debug)
1053 zlog_debug(
1054 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
1055 pfx_buf, new_buf, exist_buf);
1056 return 0;
1057 }
1058 }
1059
1060 /* 11. Maximum path check. */
1061 if (newm == existm) {
1062 /* If one path has a label but the other does not, do not treat
1063 * them as equals for multipath
1064 */
1065 if ((new->extra &&bgp_is_valid_label(&new->extra->label[0]))
1066 != (exist->extra
1067 && bgp_is_valid_label(&exist->extra->label[0]))) {
1068 if (debug)
1069 zlog_debug(
1070 "%s: %s and %s cannot be multipath, one has a label while the other does not",
1071 pfx_buf, new_buf, exist_buf);
1072 } else if (CHECK_FLAG(bgp->flags,
1073 BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
1074
1075 /*
1076 * For the two paths, all comparison steps till IGP
1077 * metric
1078 * have succeeded - including AS_PATH hop count. Since
1079 * 'bgp
1080 * bestpath as-path multipath-relax' knob is on, we
1081 * don't need
1082 * an exact match of AS_PATH. Thus, mark the paths are
1083 * equal.
1084 * That will trigger both these paths to get into the
1085 * multipath
1086 * array.
1087 */
1088 *paths_eq = 1;
1089
1090 if (debug)
1091 zlog_debug(
1092 "%s: %s and %s are equal via multipath-relax",
1093 pfx_buf, new_buf, exist_buf);
1094 } else if (new->peer->sort == BGP_PEER_IBGP) {
1095 if (aspath_cmp(new->attr->aspath,
1096 exist->attr->aspath)) {
1097 *paths_eq = 1;
1098
1099 if (debug)
1100 zlog_debug(
1101 "%s: %s and %s are equal via matching aspaths",
1102 pfx_buf, new_buf, exist_buf);
1103 }
1104 } else if (new->peer->as == exist->peer->as) {
1105 *paths_eq = 1;
1106
1107 if (debug)
1108 zlog_debug(
1109 "%s: %s and %s are equal via same remote-as",
1110 pfx_buf, new_buf, exist_buf);
1111 }
1112 } else {
1113 /*
1114 * TODO: If unequal cost ibgp multipath is enabled we can
1115 * mark the paths as equal here instead of returning
1116 */
1117 if (debug) {
1118 if (ret == 1)
1119 zlog_debug(
1120 "%s: %s wins over %s after IGP metric comparison",
1121 pfx_buf, new_buf, exist_buf);
1122 else
1123 zlog_debug(
1124 "%s: %s loses to %s after IGP metric comparison",
1125 pfx_buf, new_buf, exist_buf);
1126 }
1127 *reason = bgp_path_selection_igp_metric;
1128 return ret;
1129 }
1130
1131 /* 12. If both paths are external, prefer the path that was received
1132 first (the oldest one). This step minimizes route-flap, since a
1133 newer path won't displace an older one, even if it was the
1134 preferred route based on the additional decision criteria below. */
1135 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_COMPARE_ROUTER_ID)
1136 && new_sort == BGP_PEER_EBGP && exist_sort == BGP_PEER_EBGP) {
1137 if (CHECK_FLAG(new->flags, BGP_PATH_SELECTED)) {
1138 *reason = bgp_path_selection_older;
1139 if (debug)
1140 zlog_debug(
1141 "%s: %s wins over %s due to oldest external",
1142 pfx_buf, new_buf, exist_buf);
1143 return 1;
1144 }
1145
1146 if (CHECK_FLAG(exist->flags, BGP_PATH_SELECTED)) {
1147 *reason = bgp_path_selection_older;
1148 if (debug)
1149 zlog_debug(
1150 "%s: %s loses to %s due to oldest external",
1151 pfx_buf, new_buf, exist_buf);
1152 return 0;
1153 }
1154 }
1155
1156 /* 13. Router-ID comparision. */
1157 /* If one of the paths is "stale", the corresponding peer router-id will
1158 * be 0 and would always win over the other path. If originator id is
1159 * used for the comparision, it will decide which path is better.
1160 */
1161 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1162 new_id.s_addr = newattr->originator_id.s_addr;
1163 else
1164 new_id.s_addr = new->peer->remote_id.s_addr;
1165 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1166 exist_id.s_addr = existattr->originator_id.s_addr;
1167 else
1168 exist_id.s_addr = exist->peer->remote_id.s_addr;
1169
1170 if (ntohl(new_id.s_addr) < ntohl(exist_id.s_addr)) {
1171 *reason = bgp_path_selection_router_id;
1172 if (debug)
1173 zlog_debug(
1174 "%s: %s wins over %s due to Router-ID comparison",
1175 pfx_buf, new_buf, exist_buf);
1176 return 1;
1177 }
1178
1179 if (ntohl(new_id.s_addr) > ntohl(exist_id.s_addr)) {
1180 *reason = bgp_path_selection_router_id;
1181 if (debug)
1182 zlog_debug(
1183 "%s: %s loses to %s due to Router-ID comparison",
1184 pfx_buf, new_buf, exist_buf);
1185 return 0;
1186 }
1187
1188 /* 14. Cluster length comparision. */
1189 new_cluster = BGP_CLUSTER_LIST_LENGTH(new->attr);
1190 exist_cluster = BGP_CLUSTER_LIST_LENGTH(exist->attr);
1191
1192 if (new_cluster < exist_cluster) {
1193 *reason = bgp_path_selection_cluster_length;
1194 if (debug)
1195 zlog_debug(
1196 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1197 pfx_buf, new_buf, exist_buf, new_cluster,
1198 exist_cluster);
1199 return 1;
1200 }
1201
1202 if (new_cluster > exist_cluster) {
1203 *reason = bgp_path_selection_cluster_length;
1204 if (debug)
1205 zlog_debug(
1206 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1207 pfx_buf, new_buf, exist_buf, new_cluster,
1208 exist_cluster);
1209 return 0;
1210 }
1211
1212 /* 15. Neighbor address comparision. */
1213 /* Do this only if neither path is "stale" as stale paths do not have
1214 * valid peer information (as the connection may or may not be up).
1215 */
1216 if (CHECK_FLAG(exist->flags, BGP_PATH_STALE)) {
1217 *reason = bgp_path_selection_stale;
1218 if (debug)
1219 zlog_debug(
1220 "%s: %s wins over %s due to latter path being STALE",
1221 pfx_buf, new_buf, exist_buf);
1222 return 1;
1223 }
1224
1225 if (CHECK_FLAG(new->flags, BGP_PATH_STALE)) {
1226 *reason = bgp_path_selection_stale;
1227 if (debug)
1228 zlog_debug(
1229 "%s: %s loses to %s due to former path being STALE",
1230 pfx_buf, new_buf, exist_buf);
1231 return 0;
1232 }
1233
1234 /* locally configured routes to advertise do not have su_remote */
1235 if (new->peer->su_remote == NULL) {
1236 *reason = bgp_path_selection_local_configured;
1237 return 0;
1238 }
1239 if (exist->peer->su_remote == NULL) {
1240 *reason = bgp_path_selection_local_configured;
1241 return 1;
1242 }
1243
1244 ret = sockunion_cmp(new->peer->su_remote, exist->peer->su_remote);
1245
1246 if (ret == 1) {
1247 *reason = bgp_path_selection_neighbor_ip;
1248 if (debug)
1249 zlog_debug(
1250 "%s: %s loses to %s due to Neighor IP comparison",
1251 pfx_buf, new_buf, exist_buf);
1252 return 0;
1253 }
1254
1255 if (ret == -1) {
1256 *reason = bgp_path_selection_neighbor_ip;
1257 if (debug)
1258 zlog_debug(
1259 "%s: %s wins over %s due to Neighor IP comparison",
1260 pfx_buf, new_buf, exist_buf);
1261 return 1;
1262 }
1263
1264 *reason = bgp_path_selection_default;
1265 if (debug)
1266 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1267 pfx_buf, new_buf, exist_buf);
1268
1269 return 1;
1270 }
1271
1272
1273 int bgp_evpn_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
1274 struct bgp_path_info *exist, int *paths_eq)
1275 {
1276 enum bgp_path_selection_reason reason;
1277 char pfx_buf[PREFIX2STR_BUFFER];
1278
1279 return bgp_path_info_cmp(bgp, new, exist, paths_eq, NULL, 0, pfx_buf,
1280 AFI_L2VPN, SAFI_EVPN, &reason);
1281 }
1282
1283 /* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1284 * is preferred, or 0 if they are the same (usually will only occur if
1285 * multipath is enabled
1286 * This version is compatible with */
1287 int bgp_path_info_cmp_compatible(struct bgp *bgp, struct bgp_path_info *new,
1288 struct bgp_path_info *exist, char *pfx_buf,
1289 afi_t afi, safi_t safi,
1290 enum bgp_path_selection_reason *reason)
1291 {
1292 int paths_eq;
1293 int ret;
1294 ret = bgp_path_info_cmp(bgp, new, exist, &paths_eq, NULL, 0, pfx_buf,
1295 afi, safi, reason);
1296
1297 if (paths_eq)
1298 ret = 0;
1299 else {
1300 if (ret == 1)
1301 ret = -1;
1302 else
1303 ret = 1;
1304 }
1305 return ret;
1306 }
1307
1308 static enum filter_type bgp_input_filter(struct peer *peer,
1309 const struct prefix *p,
1310 struct attr *attr, afi_t afi,
1311 safi_t safi)
1312 {
1313 struct bgp_filter *filter;
1314 enum filter_type ret = FILTER_PERMIT;
1315
1316 filter = &peer->filter[afi][safi];
1317
1318 #define FILTER_EXIST_WARN(F, f, filter) \
1319 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
1320 zlog_debug("%s: Could not find configured input %s-list %s!", \
1321 peer->host, #f, F##_IN_NAME(filter));
1322
1323 if (DISTRIBUTE_IN_NAME(filter)) {
1324 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
1325
1326 if (access_list_apply(DISTRIBUTE_IN(filter), p)
1327 == FILTER_DENY) {
1328 ret = FILTER_DENY;
1329 goto done;
1330 }
1331 }
1332
1333 if (PREFIX_LIST_IN_NAME(filter)) {
1334 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
1335
1336 if (prefix_list_apply(PREFIX_LIST_IN(filter), p)
1337 == PREFIX_DENY) {
1338 ret = FILTER_DENY;
1339 goto done;
1340 }
1341 }
1342
1343 if (FILTER_LIST_IN_NAME(filter)) {
1344 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
1345
1346 if (as_list_apply(FILTER_LIST_IN(filter), attr->aspath)
1347 == AS_FILTER_DENY) {
1348 ret = FILTER_DENY;
1349 goto done;
1350 }
1351 }
1352
1353 done:
1354 if (frrtrace_enabled(frr_bgp, input_filter)) {
1355 char pfxprint[PREFIX2STR_BUFFER];
1356
1357 prefix2str(p, pfxprint, sizeof(pfxprint));
1358 frrtrace(5, frr_bgp, input_filter, peer, pfxprint, afi, safi,
1359 ret == FILTER_PERMIT ? "permit" : "deny");
1360 }
1361
1362 return ret;
1363 #undef FILTER_EXIST_WARN
1364 }
1365
1366 static enum filter_type bgp_output_filter(struct peer *peer,
1367 const struct prefix *p,
1368 struct attr *attr, afi_t afi,
1369 safi_t safi)
1370 {
1371 struct bgp_filter *filter;
1372 enum filter_type ret = FILTER_PERMIT;
1373
1374 filter = &peer->filter[afi][safi];
1375
1376 #define FILTER_EXIST_WARN(F, f, filter) \
1377 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
1378 zlog_debug("%s: Could not find configured output %s-list %s!", \
1379 peer->host, #f, F##_OUT_NAME(filter));
1380
1381 if (DISTRIBUTE_OUT_NAME(filter)) {
1382 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
1383
1384 if (access_list_apply(DISTRIBUTE_OUT(filter), p)
1385 == FILTER_DENY) {
1386 ret = FILTER_DENY;
1387 goto done;
1388 }
1389 }
1390
1391 if (PREFIX_LIST_OUT_NAME(filter)) {
1392 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
1393
1394 if (prefix_list_apply(PREFIX_LIST_OUT(filter), p)
1395 == PREFIX_DENY) {
1396 ret = FILTER_DENY;
1397 goto done;
1398 }
1399 }
1400
1401 if (FILTER_LIST_OUT_NAME(filter)) {
1402 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
1403
1404 if (as_list_apply(FILTER_LIST_OUT(filter), attr->aspath)
1405 == AS_FILTER_DENY) {
1406 ret = FILTER_DENY;
1407 goto done;
1408 }
1409 }
1410
1411 if (frrtrace_enabled(frr_bgp, output_filter)) {
1412 char pfxprint[PREFIX2STR_BUFFER];
1413
1414 prefix2str(p, pfxprint, sizeof(pfxprint));
1415 frrtrace(5, frr_bgp, output_filter, peer, pfxprint, afi, safi,
1416 ret == FILTER_PERMIT ? "permit" : "deny");
1417 }
1418
1419 done:
1420 return ret;
1421 #undef FILTER_EXIST_WARN
1422 }
1423
1424 /* If community attribute includes no_export then return 1. */
1425 static bool bgp_community_filter(struct peer *peer, struct attr *attr)
1426 {
1427 if (attr->community) {
1428 /* NO_ADVERTISE check. */
1429 if (community_include(attr->community, COMMUNITY_NO_ADVERTISE))
1430 return true;
1431
1432 /* NO_EXPORT check. */
1433 if (peer->sort == BGP_PEER_EBGP
1434 && community_include(attr->community, COMMUNITY_NO_EXPORT))
1435 return true;
1436
1437 /* NO_EXPORT_SUBCONFED check. */
1438 if (peer->sort == BGP_PEER_EBGP
1439 || peer->sort == BGP_PEER_CONFED)
1440 if (community_include(attr->community,
1441 COMMUNITY_NO_EXPORT_SUBCONFED))
1442 return true;
1443 }
1444 return false;
1445 }
1446
1447 /* Route reflection loop check. */
1448 static bool bgp_cluster_filter(struct peer *peer, struct attr *attr)
1449 {
1450 struct in_addr cluster_id;
1451 struct cluster_list *cluster = bgp_attr_get_cluster(attr);
1452
1453 if (cluster) {
1454 if (peer->bgp->config & BGP_CONFIG_CLUSTER_ID)
1455 cluster_id = peer->bgp->cluster_id;
1456 else
1457 cluster_id = peer->bgp->router_id;
1458
1459 if (cluster_loop_check(cluster, cluster_id))
1460 return true;
1461 }
1462 return false;
1463 }
1464
1465 static int bgp_input_modifier(struct peer *peer, const struct prefix *p,
1466 struct attr *attr, afi_t afi, safi_t safi,
1467 const char *rmap_name, mpls_label_t *label,
1468 uint32_t num_labels, struct bgp_dest *dest)
1469 {
1470 struct bgp_filter *filter;
1471 struct bgp_path_info rmap_path = { 0 };
1472 struct bgp_path_info_extra extra = { 0 };
1473 route_map_result_t ret;
1474 struct route_map *rmap = NULL;
1475
1476 filter = &peer->filter[afi][safi];
1477
1478 /* Apply default weight value. */
1479 if (peer->weight[afi][safi])
1480 attr->weight = peer->weight[afi][safi];
1481
1482 if (rmap_name) {
1483 rmap = route_map_lookup_by_name(rmap_name);
1484
1485 if (rmap == NULL)
1486 return RMAP_DENY;
1487 } else {
1488 if (ROUTE_MAP_IN_NAME(filter)) {
1489 rmap = ROUTE_MAP_IN(filter);
1490
1491 if (rmap == NULL)
1492 return RMAP_DENY;
1493 }
1494 }
1495
1496 /* Route map apply. */
1497 if (rmap) {
1498 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
1499 /* Duplicate current value to new strucutre for modification. */
1500 rmap_path.peer = peer;
1501 rmap_path.attr = attr;
1502 rmap_path.extra = &extra;
1503 rmap_path.net = dest;
1504
1505 extra.num_labels = num_labels;
1506 if (label && num_labels && num_labels <= BGP_MAX_LABELS)
1507 memcpy(extra.label, label,
1508 num_labels * sizeof(mpls_label_t));
1509
1510 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN);
1511
1512 /* Apply BGP route map to the attribute. */
1513 ret = route_map_apply(rmap, p, &rmap_path);
1514
1515 peer->rmap_type = 0;
1516
1517 if (ret == RMAP_DENYMATCH)
1518 return RMAP_DENY;
1519 }
1520 return RMAP_PERMIT;
1521 }
1522
1523 static int bgp_output_modifier(struct peer *peer, const struct prefix *p,
1524 struct attr *attr, afi_t afi, safi_t safi,
1525 const char *rmap_name)
1526 {
1527 struct bgp_path_info rmap_path;
1528 route_map_result_t ret;
1529 struct route_map *rmap = NULL;
1530 uint8_t rmap_type;
1531
1532 /*
1533 * So if we get to this point and have no rmap_name
1534 * we want to just show the output as it currently
1535 * exists.
1536 */
1537 if (!rmap_name)
1538 return RMAP_PERMIT;
1539
1540 /* Apply default weight value. */
1541 if (peer->weight[afi][safi])
1542 attr->weight = peer->weight[afi][safi];
1543
1544 rmap = route_map_lookup_by_name(rmap_name);
1545
1546 /*
1547 * If we have a route map name and we do not find
1548 * the routemap that means we have an implicit
1549 * deny.
1550 */
1551 if (rmap == NULL)
1552 return RMAP_DENY;
1553
1554 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
1555 /* Route map apply. */
1556 /* Duplicate current value to new strucutre for modification. */
1557 rmap_path.peer = peer;
1558 rmap_path.attr = attr;
1559
1560 rmap_type = peer->rmap_type;
1561 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
1562
1563 /* Apply BGP route map to the attribute. */
1564 ret = route_map_apply(rmap, p, &rmap_path);
1565
1566 peer->rmap_type = rmap_type;
1567
1568 if (ret == RMAP_DENYMATCH)
1569 /*
1570 * caller has multiple error paths with bgp_attr_flush()
1571 */
1572 return RMAP_DENY;
1573
1574 return RMAP_PERMIT;
1575 }
1576
1577 /* If this is an EBGP peer with remove-private-AS */
1578 static void bgp_peer_remove_private_as(struct bgp *bgp, afi_t afi, safi_t safi,
1579 struct peer *peer, struct attr *attr)
1580 {
1581 if (peer->sort == BGP_PEER_EBGP
1582 && (peer_af_flag_check(peer, afi, safi,
1583 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1584 || peer_af_flag_check(peer, afi, safi,
1585 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)
1586 || peer_af_flag_check(peer, afi, safi,
1587 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)
1588 || peer_af_flag_check(peer, afi, safi,
1589 PEER_FLAG_REMOVE_PRIVATE_AS))) {
1590 // Take action on the entire aspath
1591 if (peer_af_flag_check(peer, afi, safi,
1592 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1593 || peer_af_flag_check(peer, afi, safi,
1594 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)) {
1595 if (peer_af_flag_check(
1596 peer, afi, safi,
1597 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE))
1598 attr->aspath = aspath_replace_private_asns(
1599 attr->aspath, bgp->as, peer->as);
1600
1601 // The entire aspath consists of private ASNs so create
1602 // an empty aspath
1603 else if (aspath_private_as_check(attr->aspath))
1604 attr->aspath = aspath_empty_get();
1605
1606 // There are some public and some private ASNs, remove
1607 // the private ASNs
1608 else
1609 attr->aspath = aspath_remove_private_asns(
1610 attr->aspath, peer->as);
1611 }
1612
1613 // 'all' was not specified so the entire aspath must be private
1614 // ASNs
1615 // for us to do anything
1616 else if (aspath_private_as_check(attr->aspath)) {
1617 if (peer_af_flag_check(
1618 peer, afi, safi,
1619 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE))
1620 attr->aspath = aspath_replace_private_asns(
1621 attr->aspath, bgp->as, peer->as);
1622 else
1623 attr->aspath = aspath_empty_get();
1624 }
1625 }
1626 }
1627
1628 /* If this is an EBGP peer with as-override */
1629 static void bgp_peer_as_override(struct bgp *bgp, afi_t afi, safi_t safi,
1630 struct peer *peer, struct attr *attr)
1631 {
1632 if (peer->sort == BGP_PEER_EBGP
1633 && peer_af_flag_check(peer, afi, safi, PEER_FLAG_AS_OVERRIDE)) {
1634 if (aspath_single_asn_check(attr->aspath, peer->as))
1635 attr->aspath = aspath_replace_specific_asn(
1636 attr->aspath, peer->as, bgp->as);
1637 }
1638 }
1639
1640 void bgp_attr_add_gshut_community(struct attr *attr)
1641 {
1642 struct community *old;
1643 struct community *new;
1644 struct community *merge;
1645 struct community *gshut;
1646
1647 old = attr->community;
1648 gshut = community_str2com("graceful-shutdown");
1649
1650 assert(gshut);
1651
1652 if (old) {
1653 merge = community_merge(community_dup(old), gshut);
1654
1655 if (old->refcnt == 0)
1656 community_free(&old);
1657
1658 new = community_uniq_sort(merge);
1659 community_free(&merge);
1660 } else {
1661 new = community_dup(gshut);
1662 }
1663
1664 community_free(&gshut);
1665 attr->community = new;
1666 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
1667
1668 /* When we add the graceful-shutdown community we must also
1669 * lower the local-preference */
1670 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1671 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
1672 }
1673
1674
1675 /* Notify BGP Conditional advertisement scanner process. */
1676 void bgp_notify_conditional_adv_scanner(struct update_subgroup *subgrp)
1677 {
1678 struct peer *temp_peer;
1679 struct peer *peer = SUBGRP_PEER(subgrp);
1680 struct listnode *temp_node, *temp_nnode = NULL;
1681 afi_t afi = SUBGRP_AFI(subgrp);
1682 safi_t safi = SUBGRP_SAFI(subgrp);
1683 struct bgp *bgp = SUBGRP_INST(subgrp);
1684 struct bgp_filter *filter = &peer->filter[afi][safi];
1685
1686 if (!ADVERTISE_MAP_NAME(filter))
1687 return;
1688
1689 for (ALL_LIST_ELEMENTS(bgp->peer, temp_node, temp_nnode, temp_peer)) {
1690 if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
1691 continue;
1692
1693 if (peer != temp_peer)
1694 continue;
1695
1696 temp_peer->advmap_table_change = true;
1697 break;
1698 }
1699 }
1700
1701
1702 void subgroup_announce_reset_nhop(uint8_t family, struct attr *attr)
1703 {
1704 if (family == AF_INET) {
1705 attr->nexthop.s_addr = INADDR_ANY;
1706 attr->mp_nexthop_global_in.s_addr = INADDR_ANY;
1707 }
1708 if (family == AF_INET6)
1709 memset(&attr->mp_nexthop_global, 0, IPV6_MAX_BYTELEN);
1710 if (family == AF_EVPN)
1711 memset(&attr->mp_nexthop_global_in, 0, BGP_ATTR_NHLEN_IPV4);
1712 }
1713
1714 bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
1715 struct update_subgroup *subgrp,
1716 const struct prefix *p, struct attr *attr,
1717 bool skip_rmap_check)
1718 {
1719 struct bgp_filter *filter;
1720 struct peer *from;
1721 struct peer *peer;
1722 struct peer *onlypeer;
1723 struct bgp *bgp;
1724 struct attr *piattr;
1725 route_map_result_t ret;
1726 int transparent;
1727 int reflect;
1728 afi_t afi;
1729 safi_t safi;
1730 int samepeer_safe = 0; /* for synthetic mplsvpns routes */
1731 bool nh_reset = false;
1732 uint64_t cum_bw;
1733
1734 if (DISABLE_BGP_ANNOUNCE)
1735 return false;
1736
1737 afi = SUBGRP_AFI(subgrp);
1738 safi = SUBGRP_SAFI(subgrp);
1739 peer = SUBGRP_PEER(subgrp);
1740 onlypeer = NULL;
1741 if (CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL))
1742 onlypeer = SUBGRP_PFIRST(subgrp)->peer;
1743
1744 from = pi->peer;
1745 filter = &peer->filter[afi][safi];
1746 bgp = SUBGRP_INST(subgrp);
1747 piattr = bgp_path_info_mpath_count(pi) ? bgp_path_info_mpath_attr(pi)
1748 : pi->attr;
1749
1750 #ifdef ENABLE_BGP_VNC
1751 if (((afi == AFI_IP) || (afi == AFI_IP6)) && (safi == SAFI_MPLS_VPN)
1752 && ((pi->type == ZEBRA_ROUTE_BGP_DIRECT)
1753 || (pi->type == ZEBRA_ROUTE_BGP_DIRECT_EXT))) {
1754
1755 /*
1756 * direct and direct_ext type routes originate internally even
1757 * though they can have peer pointers that reference other
1758 * systems
1759 */
1760 zlog_debug("%s: pfx %pFX bgp_direct->vpn route peer safe",
1761 __func__, p);
1762 samepeer_safe = 1;
1763 }
1764 #endif
1765
1766 if (((afi == AFI_IP) || (afi == AFI_IP6))
1767 && ((safi == SAFI_MPLS_VPN) || (safi == SAFI_UNICAST))
1768 && (pi->type == ZEBRA_ROUTE_BGP)
1769 && (pi->sub_type == BGP_ROUTE_IMPORTED)) {
1770
1771 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1772
1773 samepeer_safe = 1;
1774 }
1775
1776 /* With addpath we may be asked to TX all kinds of paths so make sure
1777 * pi is valid */
1778 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID)
1779 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)
1780 || CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
1781 return false;
1782 }
1783
1784 /* If this is not the bestpath then check to see if there is an enabled
1785 * addpath
1786 * feature that requires us to advertise it */
1787 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
1788 if (!bgp_addpath_tx_path(peer->addpath_type[afi][safi], pi)) {
1789 return false;
1790 }
1791 }
1792
1793 /* Aggregate-address suppress check. */
1794 if (bgp_path_suppressed(pi) && !UNSUPPRESS_MAP_NAME(filter))
1795 return false;
1796
1797 /*
1798 * If we are doing VRF 2 VRF leaking via the import
1799 * statement, we want to prevent the route going
1800 * off box as that the RT and RD created are localy
1801 * significant and globaly useless.
1802 */
1803 if (safi == SAFI_MPLS_VPN && pi->extra && pi->extra->num_labels
1804 && pi->extra->label[0] == BGP_PREVENT_VRF_2_VRF_LEAK)
1805 return false;
1806
1807 /* If it's labeled safi, make sure the route has a valid label. */
1808 if (safi == SAFI_LABELED_UNICAST) {
1809 mpls_label_t label = bgp_adv_label(dest, pi, peer, afi, safi);
1810 if (!bgp_is_valid_label(&label)) {
1811 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1812 zlog_debug("u%" PRIu64 ":s%" PRIu64
1813 " %pFX is filtered - no label (%p)",
1814 subgrp->update_group->id, subgrp->id,
1815 p, &label);
1816 return false;
1817 }
1818 }
1819
1820 /* Do not send back route to sender. */
1821 if (onlypeer && from == onlypeer) {
1822 return false;
1823 }
1824
1825 /* Do not send the default route in the BGP table if the neighbor is
1826 * configured for default-originate */
1827 if (CHECK_FLAG(peer->af_flags[afi][safi],
1828 PEER_FLAG_DEFAULT_ORIGINATE)) {
1829 if (p->family == AF_INET && p->u.prefix4.s_addr == INADDR_ANY)
1830 return false;
1831 else if (p->family == AF_INET6 && p->prefixlen == 0)
1832 return false;
1833 }
1834
1835 /* Transparency check. */
1836 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1837 && CHECK_FLAG(from->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1838 transparent = 1;
1839 else
1840 transparent = 0;
1841
1842 /* If community is not disabled check the no-export and local. */
1843 if (!transparent && bgp_community_filter(peer, piattr)) {
1844 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1845 zlog_debug("%s: community filter check fail for %pFX",
1846 __func__, p);
1847 return false;
1848 }
1849
1850 /* If the attribute has originator-id and it is same as remote
1851 peer's id. */
1852 if (onlypeer && piattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
1853 && (IPV4_ADDR_SAME(&onlypeer->remote_id, &piattr->originator_id))) {
1854 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1855 zlog_debug(
1856 "%s [Update:SEND] %pFX originator-id is same as remote router-id",
1857 onlypeer->host, p);
1858 return false;
1859 }
1860
1861 /* ORF prefix-list filter check */
1862 if (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV)
1863 && (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)
1864 || CHECK_FLAG(peer->af_cap[afi][safi],
1865 PEER_CAP_ORF_PREFIX_SM_OLD_RCV)))
1866 if (peer->orf_plist[afi][safi]) {
1867 if (prefix_list_apply(peer->orf_plist[afi][safi], p)
1868 == PREFIX_DENY) {
1869 if (bgp_debug_update(NULL, p,
1870 subgrp->update_group, 0))
1871 zlog_debug(
1872 "%s [Update:SEND] %pFX is filtered via ORF",
1873 peer->host, p);
1874 return false;
1875 }
1876 }
1877
1878 /* Output filter check. */
1879 if (bgp_output_filter(peer, p, piattr, afi, safi) == FILTER_DENY) {
1880 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1881 zlog_debug("%s [Update:SEND] %pFX is filtered",
1882 peer->host, p);
1883 return false;
1884 }
1885
1886 /* AS path loop check. */
1887 if (onlypeer && onlypeer->as_path_loop_detection
1888 && aspath_loop_check(piattr->aspath, onlypeer->as)) {
1889 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1890 zlog_debug(
1891 "%s [Update:SEND] suppress announcement to peer AS %u that is part of AS path.",
1892 onlypeer->host, onlypeer->as);
1893 return false;
1894 }
1895
1896 /* If we're a CONFED we need to loop check the CONFED ID too */
1897 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
1898 if (aspath_loop_check(piattr->aspath, bgp->confed_id)) {
1899 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1900 zlog_debug(
1901 "%s [Update:SEND] suppress announcement to peer AS %u is AS path.",
1902 peer->host, bgp->confed_id);
1903 return false;
1904 }
1905 }
1906
1907 /* Route-Reflect check. */
1908 if (from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
1909 reflect = 1;
1910 else
1911 reflect = 0;
1912
1913 /* IBGP reflection check. */
1914 if (reflect && !samepeer_safe) {
1915 /* A route from a Client peer. */
1916 if (CHECK_FLAG(from->af_flags[afi][safi],
1917 PEER_FLAG_REFLECTOR_CLIENT)) {
1918 /* Reflect to all the Non-Client peers and also to the
1919 Client peers other than the originator. Originator
1920 check
1921 is already done. So there is noting to do. */
1922 /* no bgp client-to-client reflection check. */
1923 if (CHECK_FLAG(bgp->flags,
1924 BGP_FLAG_NO_CLIENT_TO_CLIENT))
1925 if (CHECK_FLAG(peer->af_flags[afi][safi],
1926 PEER_FLAG_REFLECTOR_CLIENT))
1927 return false;
1928 } else {
1929 /* A route from a Non-client peer. Reflect to all other
1930 clients. */
1931 if (!CHECK_FLAG(peer->af_flags[afi][safi],
1932 PEER_FLAG_REFLECTOR_CLIENT))
1933 return false;
1934 }
1935 }
1936
1937 /* For modify attribute, copy it to temporary structure. */
1938 *attr = *piattr;
1939
1940 /* If local-preference is not set. */
1941 if ((peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED)
1942 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)))) {
1943 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1944 attr->local_pref = bgp->default_local_pref;
1945 }
1946
1947 /* If originator-id is not set and the route is to be reflected,
1948 set the originator id */
1949 if (reflect
1950 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)))) {
1951 IPV4_ADDR_COPY(&(attr->originator_id), &(from->remote_id));
1952 SET_FLAG(attr->flag, BGP_ATTR_ORIGINATOR_ID);
1953 }
1954
1955 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
1956 */
1957 if (peer->sort == BGP_PEER_EBGP
1958 && attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
1959 if (from != bgp->peer_self && !transparent
1960 && !CHECK_FLAG(peer->af_flags[afi][safi],
1961 PEER_FLAG_MED_UNCHANGED))
1962 attr->flag &=
1963 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC));
1964 }
1965
1966 /* Since the nexthop attribute can vary per peer, it is not explicitly
1967 * set
1968 * in announce check, only certain flags and length (or number of
1969 * nexthops
1970 * -- for IPv6/MP_REACH) are set here in order to guide the update
1971 * formation
1972 * code in setting the nexthop(s) on a per peer basis in
1973 * reformat_peer().
1974 * Typically, the source nexthop in the attribute is preserved but in
1975 * the
1976 * scenarios where we know it will always be overwritten, we reset the
1977 * nexthop to "0" in an attempt to achieve better Update packing. An
1978 * example of this is when a prefix from each of 2 IBGP peers needs to
1979 * be
1980 * announced to an EBGP peer (and they have the same attributes barring
1981 * their nexthop).
1982 */
1983 if (reflect)
1984 SET_FLAG(attr->rmap_change_flags, BATTR_REFLECTED);
1985
1986 #define NEXTHOP_IS_V6 \
1987 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
1988 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
1989 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
1990 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
1991
1992 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
1993 * if
1994 * the peer (group) is configured to receive link-local nexthop
1995 * unchanged
1996 * and it is available in the prefix OR we're not reflecting the route,
1997 * link-local nexthop address is valid and
1998 * the peer (group) to whom we're going to announce is on a shared
1999 * network
2000 * and this is either a self-originated route or the peer is EBGP.
2001 * By checking if nexthop LL address is valid we are sure that
2002 * we do not announce LL address as `::`.
2003 */
2004 if (NEXTHOP_IS_V6) {
2005 attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
2006 if ((CHECK_FLAG(peer->af_flags[afi][safi],
2007 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
2008 && IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_local))
2009 || (!reflect
2010 && IN6_IS_ADDR_LINKLOCAL(&peer->nexthop.v6_local)
2011 && peer->shared_network
2012 && (from == bgp->peer_self
2013 || peer->sort == BGP_PEER_EBGP))) {
2014 attr->mp_nexthop_len =
2015 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
2016 }
2017
2018 /* Clear off link-local nexthop in source, whenever it is not
2019 * needed to
2020 * ensure more prefixes share the same attribute for
2021 * announcement.
2022 */
2023 if (!(CHECK_FLAG(peer->af_flags[afi][safi],
2024 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)))
2025 memset(&attr->mp_nexthop_local, 0, IPV6_MAX_BYTELEN);
2026 }
2027
2028 bgp_peer_remove_private_as(bgp, afi, safi, peer, attr);
2029 bgp_peer_as_override(bgp, afi, safi, peer, attr);
2030
2031 /* Route map & unsuppress-map apply. */
2032 if (!skip_rmap_check
2033 && (ROUTE_MAP_OUT_NAME(filter) || bgp_path_suppressed(pi))) {
2034 struct bgp_path_info rmap_path = {0};
2035 struct bgp_path_info_extra dummy_rmap_path_extra = {0};
2036 struct attr dummy_attr = {0};
2037
2038 /* Fill temp path_info */
2039 prep_for_rmap_apply(&rmap_path, &dummy_rmap_path_extra, dest,
2040 pi, peer, attr);
2041
2042 /* don't confuse inbound and outbound setting */
2043 RESET_FLAG(attr->rmap_change_flags);
2044
2045 /*
2046 * The route reflector is not allowed to modify the attributes
2047 * of the reflected IBGP routes unless explicitly allowed.
2048 */
2049 if ((from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
2050 && !CHECK_FLAG(bgp->flags,
2051 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) {
2052 dummy_attr = *attr;
2053 rmap_path.attr = &dummy_attr;
2054 }
2055
2056 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
2057
2058 if (bgp_path_suppressed(pi))
2059 ret = route_map_apply(UNSUPPRESS_MAP(filter), p,
2060 &rmap_path);
2061 else
2062 ret = route_map_apply(ROUTE_MAP_OUT(filter), p,
2063 &rmap_path);
2064
2065 peer->rmap_type = 0;
2066
2067 if (ret == RMAP_DENYMATCH) {
2068 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2069 zlog_debug(
2070 "%s [Update:SEND] %pFX is filtered by route-map",
2071 peer->host, p);
2072
2073 bgp_attr_flush(attr);
2074 return false;
2075 }
2076 }
2077
2078 /* RFC 8212 to prevent route leaks.
2079 * This specification intends to improve this situation by requiring the
2080 * explicit configuration of both BGP Import and Export Policies for any
2081 * External BGP (EBGP) session such as customers, peers, or
2082 * confederation boundaries for all enabled address families. Through
2083 * codification of the aforementioned requirement, operators will
2084 * benefit from consistent behavior across different BGP
2085 * implementations.
2086 */
2087 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
2088 if (!bgp_outbound_policy_exists(peer, filter))
2089 return false;
2090
2091 /* draft-ietf-idr-deprecate-as-set-confed-set
2092 * Filter routes having AS_SET or AS_CONFED_SET in the path.
2093 * Eventually, This document (if approved) updates RFC 4271
2094 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
2095 * and obsoletes RFC 6472.
2096 */
2097 if (peer->bgp->reject_as_sets)
2098 if (aspath_check_as_sets(attr->aspath))
2099 return false;
2100
2101 /* Codification of AS 0 Processing */
2102 if (aspath_check_as_zero(attr->aspath))
2103 return false;
2104
2105 if (bgp_in_graceful_shutdown(bgp)) {
2106 if (peer->sort == BGP_PEER_IBGP
2107 || peer->sort == BGP_PEER_CONFED) {
2108 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
2109 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
2110 } else {
2111 bgp_attr_add_gshut_community(attr);
2112 }
2113 }
2114
2115 /* After route-map has been applied, we check to see if the nexthop to
2116 * be carried in the attribute (that is used for the announcement) can
2117 * be cleared off or not. We do this in all cases where we would be
2118 * setting the nexthop to "ourselves". For IPv6, we only need to
2119 * consider
2120 * the global nexthop here; the link-local nexthop would have been
2121 * cleared
2122 * already, and if not, it is required by the update formation code.
2123 * Also see earlier comments in this function.
2124 */
2125 /*
2126 * If route-map has performed some operation on the nexthop or the peer
2127 * configuration says to pass it unchanged, we cannot reset the nexthop
2128 * here, so only attempt to do it if these aren't true. Note that the
2129 * route-map handler itself might have cleared the nexthop, if for
2130 * example,
2131 * it is configured as 'peer-address'.
2132 */
2133 if (!bgp_rmap_nhop_changed(attr->rmap_change_flags,
2134 piattr->rmap_change_flags)
2135 && !transparent
2136 && !CHECK_FLAG(peer->af_flags[afi][safi],
2137 PEER_FLAG_NEXTHOP_UNCHANGED)) {
2138 /* We can reset the nexthop, if setting (or forcing) it to
2139 * 'self' */
2140 if (CHECK_FLAG(peer->af_flags[afi][safi],
2141 PEER_FLAG_NEXTHOP_SELF)
2142 || CHECK_FLAG(peer->af_flags[afi][safi],
2143 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
2144 if (!reflect
2145 || CHECK_FLAG(peer->af_flags[afi][safi],
2146 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
2147 subgroup_announce_reset_nhop(
2148 (peer_cap_enhe(peer, afi, safi)
2149 ? AF_INET6
2150 : p->family),
2151 attr);
2152 nh_reset = true;
2153 }
2154 } else if (peer->sort == BGP_PEER_EBGP) {
2155 /* Can also reset the nexthop if announcing to EBGP, but
2156 * only if
2157 * no peer in the subgroup is on a shared subnet.
2158 * Note: 3rd party nexthop currently implemented for
2159 * IPv4 only.
2160 */
2161 if ((p->family == AF_INET) &&
2162 (!bgp_subgrp_multiaccess_check_v4(
2163 piattr->nexthop,
2164 subgrp, from))) {
2165 subgroup_announce_reset_nhop(
2166 (peer_cap_enhe(peer, afi, safi)
2167 ? AF_INET6
2168 : p->family),
2169 attr);
2170 nh_reset = true;
2171 }
2172
2173 if ((p->family == AF_INET6) &&
2174 (!bgp_subgrp_multiaccess_check_v6(
2175 piattr->mp_nexthop_global,
2176 subgrp, from))) {
2177 subgroup_announce_reset_nhop(
2178 (peer_cap_enhe(peer, afi, safi)
2179 ? AF_INET6
2180 : p->family),
2181 attr);
2182 nh_reset = true;
2183 }
2184
2185
2186
2187 } else if (CHECK_FLAG(pi->flags, BGP_PATH_ANNC_NH_SELF)) {
2188 /*
2189 * This flag is used for leaked vpn-vrf routes
2190 */
2191 int family = p->family;
2192
2193 if (peer_cap_enhe(peer, afi, safi))
2194 family = AF_INET6;
2195
2196 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2197 zlog_debug(
2198 "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
2199 __func__, family2str(family));
2200 subgroup_announce_reset_nhop(family, attr);
2201 nh_reset = true;
2202 }
2203 }
2204
2205 /* If IPv6/MP and nexthop does not have any override and happens
2206 * to
2207 * be a link-local address, reset it so that we don't pass along
2208 * the
2209 * source's link-local IPv6 address to recipients who may not be
2210 * on
2211 * the same interface.
2212 */
2213 if (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi)) {
2214 if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global)) {
2215 subgroup_announce_reset_nhop(AF_INET6, attr);
2216 nh_reset = true;
2217 }
2218 }
2219
2220 /*
2221 * When the next hop is set to ourselves, if all multipaths have
2222 * link-bandwidth announce the cumulative bandwidth as that makes
2223 * the most sense. However, don't modify if the link-bandwidth has
2224 * been explicitly set by user policy.
2225 */
2226 if (nh_reset &&
2227 bgp_path_info_mpath_chkwtd(bgp, pi) &&
2228 (cum_bw = bgp_path_info_mpath_cumbw(pi)) != 0 &&
2229 !CHECK_FLAG(attr->rmap_change_flags, BATTR_RMAP_LINK_BW_SET))
2230 attr->ecommunity = ecommunity_replace_linkbw(
2231 bgp->as, attr->ecommunity, cum_bw);
2232
2233 return true;
2234 }
2235
2236 static int bgp_route_select_timer_expire(struct thread *thread)
2237 {
2238 struct afi_safi_info *info;
2239 afi_t afi;
2240 safi_t safi;
2241 struct bgp *bgp;
2242
2243 info = THREAD_ARG(thread);
2244 afi = info->afi;
2245 safi = info->safi;
2246 bgp = info->bgp;
2247
2248 if (BGP_DEBUG(update, UPDATE_OUT))
2249 zlog_debug("afi %d, safi %d : route select timer expired", afi,
2250 safi);
2251
2252 bgp->gr_info[afi][safi].t_route_select = NULL;
2253
2254 XFREE(MTYPE_TMP, info);
2255
2256 /* Best path selection */
2257 return bgp_best_path_select_defer(bgp, afi, safi);
2258 }
2259
2260 void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
2261 struct bgp_maxpaths_cfg *mpath_cfg,
2262 struct bgp_path_info_pair *result, afi_t afi,
2263 safi_t safi)
2264 {
2265 struct bgp_path_info *new_select;
2266 struct bgp_path_info *old_select;
2267 struct bgp_path_info *pi;
2268 struct bgp_path_info *pi1;
2269 struct bgp_path_info *pi2;
2270 struct bgp_path_info *nextpi = NULL;
2271 int paths_eq, do_mpath, debug;
2272 struct list mp_list;
2273 char pfx_buf[PREFIX2STR_BUFFER];
2274 char path_buf[PATH_ADDPATH_STR_BUFFER];
2275
2276 bgp_mp_list_init(&mp_list);
2277 do_mpath =
2278 (mpath_cfg->maxpaths_ebgp > 1 || mpath_cfg->maxpaths_ibgp > 1);
2279
2280 debug = bgp_debug_bestpath(dest);
2281
2282 if (debug)
2283 prefix2str(bgp_dest_get_prefix(dest), pfx_buf, sizeof(pfx_buf));
2284
2285 dest->reason = bgp_path_selection_none;
2286 /* bgp deterministic-med */
2287 new_select = NULL;
2288 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)) {
2289
2290 /* Clear BGP_PATH_DMED_SELECTED for all paths */
2291 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
2292 pi1 = pi1->next)
2293 bgp_path_info_unset_flag(dest, pi1,
2294 BGP_PATH_DMED_SELECTED);
2295
2296 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
2297 pi1 = pi1->next) {
2298 if (CHECK_FLAG(pi1->flags, BGP_PATH_DMED_CHECK))
2299 continue;
2300 if (BGP_PATH_HOLDDOWN(pi1))
2301 continue;
2302 if (pi1->peer != bgp->peer_self)
2303 if (pi1->peer->status != Established)
2304 continue;
2305
2306 new_select = pi1;
2307 if (pi1->next) {
2308 for (pi2 = pi1->next; pi2; pi2 = pi2->next) {
2309 if (CHECK_FLAG(pi2->flags,
2310 BGP_PATH_DMED_CHECK))
2311 continue;
2312 if (BGP_PATH_HOLDDOWN(pi2))
2313 continue;
2314 if (pi2->peer != bgp->peer_self
2315 && !CHECK_FLAG(
2316 pi2->peer->sflags,
2317 PEER_STATUS_NSF_WAIT))
2318 if (pi2->peer->status
2319 != Established)
2320 continue;
2321
2322 if (!aspath_cmp_left(pi1->attr->aspath,
2323 pi2->attr->aspath)
2324 && !aspath_cmp_left_confed(
2325 pi1->attr->aspath,
2326 pi2->attr->aspath))
2327 continue;
2328
2329 if (bgp_path_info_cmp(
2330 bgp, pi2, new_select,
2331 &paths_eq, mpath_cfg, debug,
2332 pfx_buf, afi, safi,
2333 &dest->reason)) {
2334 bgp_path_info_unset_flag(
2335 dest, new_select,
2336 BGP_PATH_DMED_SELECTED);
2337 new_select = pi2;
2338 }
2339
2340 bgp_path_info_set_flag(
2341 dest, pi2, BGP_PATH_DMED_CHECK);
2342 }
2343 }
2344 bgp_path_info_set_flag(dest, new_select,
2345 BGP_PATH_DMED_CHECK);
2346 bgp_path_info_set_flag(dest, new_select,
2347 BGP_PATH_DMED_SELECTED);
2348
2349 if (debug) {
2350 bgp_path_info_path_with_addpath_rx_str(
2351 new_select, path_buf);
2352 zlog_debug(
2353 "%pBD: %s is the bestpath from AS %u",
2354 dest, path_buf,
2355 aspath_get_first_as(
2356 new_select->attr->aspath));
2357 }
2358 }
2359 }
2360
2361 /* Check old selected route and new selected route. */
2362 old_select = NULL;
2363 new_select = NULL;
2364 for (pi = bgp_dest_get_bgp_path_info(dest);
2365 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
2366 enum bgp_path_selection_reason reason;
2367
2368 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
2369 old_select = pi;
2370
2371 if (BGP_PATH_HOLDDOWN(pi)) {
2372 /* reap REMOVED routes, if needs be
2373 * selected route must stay for a while longer though
2374 */
2375 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
2376 && (pi != old_select))
2377 bgp_path_info_reap(dest, pi);
2378
2379 if (debug)
2380 zlog_debug("%s: pi %p in holddown", __func__,
2381 pi);
2382
2383 continue;
2384 }
2385
2386 if (pi->peer && pi->peer != bgp->peer_self
2387 && !CHECK_FLAG(pi->peer->sflags, PEER_STATUS_NSF_WAIT))
2388 if (pi->peer->status != Established) {
2389
2390 if (debug)
2391 zlog_debug(
2392 "%s: pi %p non self peer %s not estab state",
2393 __func__, pi, pi->peer->host);
2394
2395 continue;
2396 }
2397
2398 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)
2399 && (!CHECK_FLAG(pi->flags, BGP_PATH_DMED_SELECTED))) {
2400 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
2401 if (debug)
2402 zlog_debug("%s: pi %p dmed", __func__, pi);
2403 continue;
2404 }
2405
2406 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
2407
2408 reason = dest->reason;
2409 if (bgp_path_info_cmp(bgp, pi, new_select, &paths_eq, mpath_cfg,
2410 debug, pfx_buf, afi, safi,
2411 &dest->reason)) {
2412 if (new_select == NULL &&
2413 reason != bgp_path_selection_none)
2414 dest->reason = reason;
2415 new_select = pi;
2416 }
2417 }
2418
2419 /* Now that we know which path is the bestpath see if any of the other
2420 * paths
2421 * qualify as multipaths
2422 */
2423 if (debug) {
2424 if (new_select)
2425 bgp_path_info_path_with_addpath_rx_str(new_select,
2426 path_buf);
2427 else
2428 snprintf(path_buf, sizeof(path_buf), "NONE");
2429 zlog_debug(
2430 "%pBD: After path selection, newbest is %s oldbest was %s",
2431 dest, path_buf,
2432 old_select ? old_select->peer->host : "NONE");
2433 }
2434
2435 if (do_mpath && new_select) {
2436 for (pi = bgp_dest_get_bgp_path_info(dest);
2437 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
2438
2439 if (debug)
2440 bgp_path_info_path_with_addpath_rx_str(
2441 pi, path_buf);
2442
2443 if (pi == new_select) {
2444 if (debug)
2445 zlog_debug(
2446 "%pBD: %s is the bestpath, add to the multipath list",
2447 dest, path_buf);
2448 bgp_mp_list_add(&mp_list, pi);
2449 continue;
2450 }
2451
2452 if (BGP_PATH_HOLDDOWN(pi))
2453 continue;
2454
2455 if (pi->peer && pi->peer != bgp->peer_self
2456 && !CHECK_FLAG(pi->peer->sflags,
2457 PEER_STATUS_NSF_WAIT))
2458 if (pi->peer->status != Established)
2459 continue;
2460
2461 if (!bgp_path_info_nexthop_cmp(pi, new_select)) {
2462 if (debug)
2463 zlog_debug(
2464 "%pBD: %s has the same nexthop as the bestpath, skip it",
2465 dest, path_buf);
2466 continue;
2467 }
2468
2469 bgp_path_info_cmp(bgp, pi, new_select, &paths_eq,
2470 mpath_cfg, debug, pfx_buf, afi, safi,
2471 &dest->reason);
2472
2473 if (paths_eq) {
2474 if (debug)
2475 zlog_debug(
2476 "%pBD: %s is equivalent to the bestpath, add to the multipath list",
2477 dest, path_buf);
2478 bgp_mp_list_add(&mp_list, pi);
2479 }
2480 }
2481 }
2482
2483 bgp_path_info_mpath_update(dest, new_select, old_select, &mp_list,
2484 mpath_cfg);
2485 bgp_path_info_mpath_aggregate_update(new_select, old_select);
2486 bgp_mp_list_clear(&mp_list);
2487
2488 bgp_addpath_update_ids(bgp, dest, afi, safi);
2489
2490 result->old = old_select;
2491 result->new = new_select;
2492
2493 return;
2494 }
2495
2496 /*
2497 * A new route/change in bestpath of an existing route. Evaluate the path
2498 * for advertisement to the subgroup.
2499 */
2500 void subgroup_process_announce_selected(struct update_subgroup *subgrp,
2501 struct bgp_path_info *selected,
2502 struct bgp_dest *dest,
2503 uint32_t addpath_tx_id)
2504 {
2505 const struct prefix *p;
2506 struct peer *onlypeer;
2507 struct attr attr;
2508 afi_t afi;
2509 safi_t safi;
2510 struct bgp *bgp;
2511 bool advertise;
2512
2513 p = bgp_dest_get_prefix(dest);
2514 afi = SUBGRP_AFI(subgrp);
2515 safi = SUBGRP_SAFI(subgrp);
2516 bgp = SUBGRP_INST(subgrp);
2517 onlypeer = ((SUBGRP_PCOUNT(subgrp) == 1) ? (SUBGRP_PFIRST(subgrp))->peer
2518 : NULL);
2519
2520 if (BGP_DEBUG(update, UPDATE_OUT))
2521 zlog_debug("%s: p=%pFX, selected=%p", __func__, p, selected);
2522
2523 /* First update is deferred until ORF or ROUTE-REFRESH is received */
2524 if (onlypeer && CHECK_FLAG(onlypeer->af_sflags[afi][safi],
2525 PEER_STATUS_ORF_WAIT_REFRESH))
2526 return;
2527
2528 memset(&attr, 0, sizeof(struct attr));
2529 /* It's initialized in bgp_announce_check() */
2530
2531 /* Announcement to the subgroup. If the route is filtered withdraw it.
2532 * If BGP_NODE_FIB_INSTALL_PENDING is set and data plane install status
2533 * is pending (BGP_NODE_FIB_INSTALL_PENDING), do not advertise the
2534 * route
2535 */
2536 advertise = bgp_check_advertise(bgp, dest);
2537
2538 if (selected) {
2539 if (subgroup_announce_check(dest, selected, subgrp, p, &attr,
2540 false)) {
2541 /* Route is selected, if the route is already installed
2542 * in FIB, then it is advertised
2543 */
2544 if (advertise)
2545 bgp_adj_out_set_subgroup(dest, subgrp, &attr,
2546 selected);
2547 } else
2548 bgp_adj_out_unset_subgroup(dest, subgrp, 1,
2549 addpath_tx_id);
2550 }
2551
2552 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2553 else {
2554 bgp_adj_out_unset_subgroup(dest, subgrp, 1, addpath_tx_id);
2555 }
2556 }
2557
2558 /*
2559 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2560 * This is called at the end of route processing.
2561 */
2562 void bgp_zebra_clear_route_change_flags(struct bgp_dest *dest)
2563 {
2564 struct bgp_path_info *pi;
2565
2566 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
2567 if (BGP_PATH_HOLDDOWN(pi))
2568 continue;
2569 UNSET_FLAG(pi->flags, BGP_PATH_IGP_CHANGED);
2570 UNSET_FLAG(pi->flags, BGP_PATH_ATTR_CHANGED);
2571 }
2572 }
2573
2574 /*
2575 * Has the route changed from the RIB's perspective? This is invoked only
2576 * if the route selection returns the same best route as earlier - to
2577 * determine if we need to update zebra or not.
2578 */
2579 bool bgp_zebra_has_route_changed(struct bgp_path_info *selected)
2580 {
2581 struct bgp_path_info *mpinfo;
2582
2583 /* If this is multipath, check all selected paths for any nexthop
2584 * change or attribute change. Some attribute changes (e.g., community)
2585 * aren't of relevance to the RIB, but we'll update zebra to ensure
2586 * we handle the case of BGP nexthop change. This is the behavior
2587 * when the best path has an attribute change anyway.
2588 */
2589 if (CHECK_FLAG(selected->flags, BGP_PATH_IGP_CHANGED)
2590 || CHECK_FLAG(selected->flags, BGP_PATH_MULTIPATH_CHG)
2591 || CHECK_FLAG(selected->flags, BGP_PATH_LINK_BW_CHG))
2592 return true;
2593
2594 /*
2595 * If this is multipath, check all selected paths for any nexthop change
2596 */
2597 for (mpinfo = bgp_path_info_mpath_first(selected); mpinfo;
2598 mpinfo = bgp_path_info_mpath_next(mpinfo)) {
2599 if (CHECK_FLAG(mpinfo->flags, BGP_PATH_IGP_CHANGED)
2600 || CHECK_FLAG(mpinfo->flags, BGP_PATH_ATTR_CHANGED))
2601 return true;
2602 }
2603
2604 /* Nothing has changed from the RIB's perspective. */
2605 return false;
2606 }
2607
2608 struct bgp_process_queue {
2609 struct bgp *bgp;
2610 STAILQ_HEAD(, bgp_dest) pqueue;
2611 #define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2612 unsigned int flags;
2613 unsigned int queued;
2614 };
2615
2616 static void bgp_process_evpn_route_injection(struct bgp *bgp, afi_t afi,
2617 safi_t safi, struct bgp_dest *dest,
2618 struct bgp_path_info *new_select,
2619 struct bgp_path_info *old_select)
2620 {
2621 const struct prefix *p = bgp_dest_get_prefix(dest);
2622
2623 if ((afi != AFI_IP && afi != AFI_IP6) || (safi != SAFI_UNICAST))
2624 return;
2625
2626 if (advertise_type5_routes(bgp, afi) && new_select
2627 && is_route_injectable_into_evpn(new_select)) {
2628
2629 /* apply the route-map */
2630 if (bgp->adv_cmd_rmap[afi][safi].map) {
2631 route_map_result_t ret;
2632 struct bgp_path_info rmap_path;
2633 struct bgp_path_info_extra rmap_path_extra;
2634 struct attr dummy_attr;
2635
2636 dummy_attr = *new_select->attr;
2637
2638 /* Fill temp path_info */
2639 prep_for_rmap_apply(&rmap_path, &rmap_path_extra, dest,
2640 new_select, new_select->peer,
2641 &dummy_attr);
2642
2643 RESET_FLAG(dummy_attr.rmap_change_flags);
2644
2645 ret = route_map_apply(bgp->adv_cmd_rmap[afi][safi].map,
2646 p, &rmap_path);
2647
2648 if (ret == RMAP_DENYMATCH) {
2649 bgp_attr_flush(&dummy_attr);
2650 bgp_evpn_withdraw_type5_route(bgp, p, afi,
2651 safi);
2652 } else
2653 bgp_evpn_advertise_type5_route(
2654 bgp, p, &dummy_attr, afi, safi);
2655 } else {
2656 bgp_evpn_advertise_type5_route(bgp, p, new_select->attr,
2657 afi, safi);
2658 }
2659 } else if (advertise_type5_routes(bgp, afi) && old_select
2660 && is_route_injectable_into_evpn(old_select))
2661 bgp_evpn_withdraw_type5_route(bgp, p, afi, safi);
2662 }
2663
2664 /*
2665 * old_select = The old best path
2666 * new_select = the new best path
2667 *
2668 * if (!old_select && new_select)
2669 * We are sending new information on.
2670 *
2671 * if (old_select && new_select) {
2672 * if (new_select != old_select)
2673 * We have a new best path send a change
2674 * else
2675 * We've received a update with new attributes that needs
2676 * to be passed on.
2677 * }
2678 *
2679 * if (old_select && !new_select)
2680 * We have no eligible route that we can announce or the rn
2681 * is being removed.
2682 */
2683 static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
2684 afi_t afi, safi_t safi)
2685 {
2686 struct bgp_path_info *new_select;
2687 struct bgp_path_info *old_select;
2688 struct bgp_path_info_pair old_and_new;
2689 int debug = 0;
2690
2691 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)) {
2692 if (dest)
2693 debug = bgp_debug_bestpath(dest);
2694 if (debug)
2695 zlog_debug(
2696 "%s: bgp delete in progress, ignoring event, p=%pBD",
2697 __func__, dest);
2698 return;
2699 }
2700 /* Is it end of initial update? (after startup) */
2701 if (!dest) {
2702 quagga_timestamp(3, bgp->update_delay_zebra_resume_time,
2703 sizeof(bgp->update_delay_zebra_resume_time));
2704
2705 bgp->main_zebra_update_hold = 0;
2706 FOREACH_AFI_SAFI (afi, safi) {
2707 if (bgp_fibupd_safi(safi))
2708 bgp_zebra_announce_table(bgp, afi, safi);
2709 }
2710 bgp->main_peers_update_hold = 0;
2711
2712 bgp_start_routeadv(bgp);
2713 return;
2714 }
2715
2716 const struct prefix *p = bgp_dest_get_prefix(dest);
2717
2718 debug = bgp_debug_bestpath(dest);
2719 if (debug)
2720 zlog_debug("%s: p=%pBD afi=%s, safi=%s start", __func__, dest,
2721 afi2str(afi), safi2str(safi));
2722
2723 /* The best path calculation for the route is deferred if
2724 * BGP_NODE_SELECT_DEFER is set
2725 */
2726 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
2727 if (BGP_DEBUG(update, UPDATE_OUT))
2728 zlog_debug("SELECT_DEFER flag set for route %p", dest);
2729 return;
2730 }
2731
2732 /* Best path selection. */
2733 bgp_best_selection(bgp, dest, &bgp->maxpaths[afi][safi], &old_and_new,
2734 afi, safi);
2735 old_select = old_and_new.old;
2736 new_select = old_and_new.new;
2737
2738 /* Do we need to allocate or free labels?
2739 * Right now, since we only deal with per-prefix labels, it is not
2740 * necessary to do this upon changes to best path. Exceptions:
2741 * - label index has changed -> recalculate resulting label
2742 * - path_info sub_type changed -> switch to/from implicit-null
2743 * - no valid label (due to removed static label binding) -> get new one
2744 */
2745 if (bgp->allocate_mpls_labels[afi][safi]) {
2746 if (new_select) {
2747 if (!old_select
2748 || bgp_label_index_differs(new_select, old_select)
2749 || new_select->sub_type != old_select->sub_type
2750 || !bgp_is_valid_label(&dest->local_label)) {
2751 /* Enforced penultimate hop popping:
2752 * implicit-null for local routes, aggregate
2753 * and redistributed routes
2754 */
2755 if (new_select->sub_type == BGP_ROUTE_STATIC
2756 || new_select->sub_type
2757 == BGP_ROUTE_AGGREGATE
2758 || new_select->sub_type
2759 == BGP_ROUTE_REDISTRIBUTE) {
2760 if (CHECK_FLAG(
2761 dest->flags,
2762 BGP_NODE_REGISTERED_FOR_LABEL)
2763 || CHECK_FLAG(
2764 dest->flags,
2765 BGP_NODE_LABEL_REQUESTED))
2766 bgp_unregister_for_label(dest);
2767 label_ntop(MPLS_LABEL_IMPLICIT_NULL, 1,
2768 &dest->local_label);
2769 bgp_set_valid_label(&dest->local_label);
2770 } else
2771 bgp_register_for_label(dest,
2772 new_select);
2773 }
2774 } else if (CHECK_FLAG(dest->flags,
2775 BGP_NODE_REGISTERED_FOR_LABEL)
2776 || CHECK_FLAG(dest->flags,
2777 BGP_NODE_LABEL_REQUESTED)) {
2778 bgp_unregister_for_label(dest);
2779 }
2780 } else if (CHECK_FLAG(dest->flags, BGP_NODE_REGISTERED_FOR_LABEL)
2781 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_REQUESTED)) {
2782 bgp_unregister_for_label(dest);
2783 }
2784
2785 if (debug)
2786 zlog_debug(
2787 "%s: p=%pBD afi=%s, safi=%s, old_select=%p, new_select=%p",
2788 __func__, dest, afi2str(afi), safi2str(safi),
2789 old_select, new_select);
2790
2791 /* If best route remains the same and this is not due to user-initiated
2792 * clear, see exactly what needs to be done.
2793 */
2794 if (old_select && old_select == new_select
2795 && !CHECK_FLAG(dest->flags, BGP_NODE_USER_CLEAR)
2796 && !CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
2797 && !bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
2798 if (bgp_zebra_has_route_changed(old_select)) {
2799 #ifdef ENABLE_BGP_VNC
2800 vnc_import_bgp_add_route(bgp, p, old_select);
2801 vnc_import_bgp_exterior_add_route(bgp, p, old_select);
2802 #endif
2803 if (bgp_fibupd_safi(safi)
2804 && !bgp_option_check(BGP_OPT_NO_FIB)) {
2805
2806 if (new_select->type == ZEBRA_ROUTE_BGP
2807 && (new_select->sub_type == BGP_ROUTE_NORMAL
2808 || new_select->sub_type
2809 == BGP_ROUTE_IMPORTED))
2810
2811 bgp_zebra_announce(dest, p, old_select,
2812 bgp, afi, safi);
2813 }
2814 }
2815
2816 /* If there is a change of interest to peers, reannounce the
2817 * route. */
2818 if (CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
2819 || CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
2820 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED)) {
2821 group_announce_route(bgp, afi, safi, dest, new_select);
2822
2823 /* unicast routes must also be annouced to
2824 * labeled-unicast update-groups */
2825 if (safi == SAFI_UNICAST)
2826 group_announce_route(bgp, afi,
2827 SAFI_LABELED_UNICAST, dest,
2828 new_select);
2829
2830 UNSET_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED);
2831 UNSET_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED);
2832 }
2833
2834 /* advertise/withdraw type-5 routes */
2835 if (CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
2836 || CHECK_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG))
2837 bgp_process_evpn_route_injection(
2838 bgp, afi, safi, dest, old_select, old_select);
2839
2840 UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG);
2841 UNSET_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG);
2842 bgp_zebra_clear_route_change_flags(dest);
2843 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
2844 return;
2845 }
2846
2847 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2848 */
2849 UNSET_FLAG(dest->flags, BGP_NODE_USER_CLEAR);
2850
2851 /* bestpath has changed; bump version */
2852 if (old_select || new_select) {
2853 bgp_bump_version(dest);
2854
2855 if (!bgp->t_rmap_def_originate_eval) {
2856 bgp_lock(bgp);
2857 thread_add_timer(
2858 bm->master,
2859 update_group_refresh_default_originate_route_map,
2860 bgp, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER,
2861 &bgp->t_rmap_def_originate_eval);
2862 }
2863 }
2864
2865 if (old_select)
2866 bgp_path_info_unset_flag(dest, old_select, BGP_PATH_SELECTED);
2867 if (new_select) {
2868 if (debug)
2869 zlog_debug("%s: setting SELECTED flag", __func__);
2870 bgp_path_info_set_flag(dest, new_select, BGP_PATH_SELECTED);
2871 bgp_path_info_unset_flag(dest, new_select,
2872 BGP_PATH_ATTR_CHANGED);
2873 UNSET_FLAG(new_select->flags, BGP_PATH_MULTIPATH_CHG);
2874 UNSET_FLAG(new_select->flags, BGP_PATH_LINK_BW_CHG);
2875 }
2876
2877 #ifdef ENABLE_BGP_VNC
2878 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
2879 if (old_select != new_select) {
2880 if (old_select) {
2881 vnc_import_bgp_exterior_del_route(bgp, p,
2882 old_select);
2883 vnc_import_bgp_del_route(bgp, p, old_select);
2884 }
2885 if (new_select) {
2886 vnc_import_bgp_exterior_add_route(bgp, p,
2887 new_select);
2888 vnc_import_bgp_add_route(bgp, p, new_select);
2889 }
2890 }
2891 }
2892 #endif
2893
2894 group_announce_route(bgp, afi, safi, dest, new_select);
2895
2896 /* unicast routes must also be annouced to labeled-unicast update-groups
2897 */
2898 if (safi == SAFI_UNICAST)
2899 group_announce_route(bgp, afi, SAFI_LABELED_UNICAST, dest,
2900 new_select);
2901
2902 /* FIB update. */
2903 if (bgp_fibupd_safi(safi) && (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW)
2904 && !bgp_option_check(BGP_OPT_NO_FIB)) {
2905 if (new_select && new_select->type == ZEBRA_ROUTE_BGP
2906 && (new_select->sub_type == BGP_ROUTE_NORMAL
2907 || new_select->sub_type == BGP_ROUTE_AGGREGATE
2908 || new_select->sub_type == BGP_ROUTE_IMPORTED)) {
2909
2910 /* if this is an evpn imported type-5 prefix,
2911 * we need to withdraw the route first to clear
2912 * the nh neigh and the RMAC entry.
2913 */
2914 if (old_select &&
2915 is_route_parent_evpn(old_select))
2916 bgp_zebra_withdraw(p, old_select, bgp, safi);
2917
2918 bgp_zebra_announce(dest, p, new_select, bgp, afi, safi);
2919 } else {
2920 /* Withdraw the route from the kernel. */
2921 if (old_select && old_select->type == ZEBRA_ROUTE_BGP
2922 && (old_select->sub_type == BGP_ROUTE_NORMAL
2923 || old_select->sub_type == BGP_ROUTE_AGGREGATE
2924 || old_select->sub_type == BGP_ROUTE_IMPORTED))
2925
2926 bgp_zebra_withdraw(p, old_select, bgp, safi);
2927 }
2928 }
2929
2930 bgp_process_evpn_route_injection(bgp, afi, safi, dest, new_select,
2931 old_select);
2932
2933 /* Clear any route change flags. */
2934 bgp_zebra_clear_route_change_flags(dest);
2935
2936 /* Reap old select bgp_path_info, if it has been removed */
2937 if (old_select && CHECK_FLAG(old_select->flags, BGP_PATH_REMOVED))
2938 bgp_path_info_reap(dest, old_select);
2939
2940 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
2941 return;
2942 }
2943
2944 /* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
2945 int bgp_best_path_select_defer(struct bgp *bgp, afi_t afi, safi_t safi)
2946 {
2947 struct bgp_dest *dest;
2948 int cnt = 0;
2949 struct afi_safi_info *thread_info;
2950
2951 if (bgp->gr_info[afi][safi].t_route_select) {
2952 struct thread *t = bgp->gr_info[afi][safi].t_route_select;
2953
2954 thread_info = THREAD_ARG(t);
2955 XFREE(MTYPE_TMP, thread_info);
2956 BGP_TIMER_OFF(bgp->gr_info[afi][safi].t_route_select);
2957 }
2958
2959 if (BGP_DEBUG(update, UPDATE_OUT)) {
2960 zlog_debug("%s: processing route for %s : cnt %d", __func__,
2961 get_afi_safi_str(afi, safi, false),
2962 bgp->gr_info[afi][safi].gr_deferred);
2963 }
2964
2965 /* Process the route list */
2966 for (dest = bgp_table_top(bgp->rib[afi][safi]);
2967 dest && bgp->gr_info[afi][safi].gr_deferred != 0;
2968 dest = bgp_route_next(dest)) {
2969 if (!CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER))
2970 continue;
2971
2972 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
2973 bgp->gr_info[afi][safi].gr_deferred--;
2974 bgp_process_main_one(bgp, dest, afi, safi);
2975 cnt++;
2976 if (cnt >= BGP_MAX_BEST_ROUTE_SELECT) {
2977 bgp_dest_unlock_node(dest);
2978 break;
2979 }
2980 }
2981
2982 /* Send EOR message when all routes are processed */
2983 if (!bgp->gr_info[afi][safi].gr_deferred) {
2984 bgp_send_delayed_eor(bgp);
2985 /* Send route processing complete message to RIB */
2986 bgp_zebra_update(afi, safi, bgp->vrf_id,
2987 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE);
2988 return 0;
2989 }
2990
2991 thread_info = XMALLOC(MTYPE_TMP, sizeof(struct afi_safi_info));
2992
2993 thread_info->afi = afi;
2994 thread_info->safi = safi;
2995 thread_info->bgp = bgp;
2996
2997 /* If there are more routes to be processed, start the
2998 * selection timer
2999 */
3000 thread_add_timer(bm->master, bgp_route_select_timer_expire, thread_info,
3001 BGP_ROUTE_SELECT_DELAY,
3002 &bgp->gr_info[afi][safi].t_route_select);
3003 return 0;
3004 }
3005
3006 static wq_item_status bgp_process_wq(struct work_queue *wq, void *data)
3007 {
3008 struct bgp_process_queue *pqnode = data;
3009 struct bgp *bgp = pqnode->bgp;
3010 struct bgp_table *table;
3011 struct bgp_dest *dest;
3012
3013 /* eoiu marker */
3014 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)) {
3015 bgp_process_main_one(bgp, NULL, 0, 0);
3016 /* should always have dedicated wq call */
3017 assert(STAILQ_FIRST(&pqnode->pqueue) == NULL);
3018 return WQ_SUCCESS;
3019 }
3020
3021 while (!STAILQ_EMPTY(&pqnode->pqueue)) {
3022 dest = STAILQ_FIRST(&pqnode->pqueue);
3023 STAILQ_REMOVE_HEAD(&pqnode->pqueue, pq);
3024 STAILQ_NEXT(dest, pq) = NULL; /* complete unlink */
3025 table = bgp_dest_table(dest);
3026 /* note, new DESTs may be added as part of processing */
3027 bgp_process_main_one(bgp, dest, table->afi, table->safi);
3028
3029 bgp_dest_unlock_node(dest);
3030 bgp_table_unlock(table);
3031 }
3032
3033 return WQ_SUCCESS;
3034 }
3035
3036 static void bgp_processq_del(struct work_queue *wq, void *data)
3037 {
3038 struct bgp_process_queue *pqnode = data;
3039
3040 bgp_unlock(pqnode->bgp);
3041
3042 XFREE(MTYPE_BGP_PROCESS_QUEUE, pqnode);
3043 }
3044
3045 void bgp_process_queue_init(struct bgp *bgp)
3046 {
3047 if (!bgp->process_queue) {
3048 char name[BUFSIZ];
3049
3050 snprintf(name, BUFSIZ, "process_queue %s", bgp->name_pretty);
3051 bgp->process_queue = work_queue_new(bm->master, name);
3052 }
3053
3054 bgp->process_queue->spec.workfunc = &bgp_process_wq;
3055 bgp->process_queue->spec.del_item_data = &bgp_processq_del;
3056 bgp->process_queue->spec.max_retries = 0;
3057 bgp->process_queue->spec.hold = 50;
3058 /* Use a higher yield value of 50ms for main queue processing */
3059 bgp->process_queue->spec.yield = 50 * 1000L;
3060 }
3061
3062 static struct bgp_process_queue *bgp_processq_alloc(struct bgp *bgp)
3063 {
3064 struct bgp_process_queue *pqnode;
3065
3066 pqnode = XCALLOC(MTYPE_BGP_PROCESS_QUEUE,
3067 sizeof(struct bgp_process_queue));
3068
3069 /* unlocked in bgp_processq_del */
3070 pqnode->bgp = bgp_lock(bgp);
3071 STAILQ_INIT(&pqnode->pqueue);
3072
3073 return pqnode;
3074 }
3075
3076 void bgp_process(struct bgp *bgp, struct bgp_dest *dest, afi_t afi, safi_t safi)
3077 {
3078 #define ARBITRARY_PROCESS_QLEN 10000
3079 struct work_queue *wq = bgp->process_queue;
3080 struct bgp_process_queue *pqnode;
3081 int pqnode_reuse = 0;
3082
3083 /* already scheduled for processing? */
3084 if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED))
3085 return;
3086
3087 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
3088 * the workqueue
3089 */
3090 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
3091 if (BGP_DEBUG(update, UPDATE_OUT))
3092 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
3093 dest);
3094 return;
3095 }
3096
3097 if (wq == NULL)
3098 return;
3099
3100 /* Add route nodes to an existing work queue item until reaching the
3101 limit only if is from the same BGP view and it's not an EOIU marker
3102 */
3103 if (work_queue_item_count(wq)) {
3104 struct work_queue_item *item = work_queue_last_item(wq);
3105 pqnode = item->data;
3106
3107 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)
3108 || pqnode->bgp != bgp
3109 || pqnode->queued >= ARBITRARY_PROCESS_QLEN)
3110 pqnode = bgp_processq_alloc(bgp);
3111 else
3112 pqnode_reuse = 1;
3113 } else
3114 pqnode = bgp_processq_alloc(bgp);
3115 /* all unlocked in bgp_process_wq */
3116 bgp_table_lock(bgp_dest_table(dest));
3117
3118 SET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
3119 bgp_dest_lock_node(dest);
3120
3121 /* can't be enqueued twice */
3122 assert(STAILQ_NEXT(dest, pq) == NULL);
3123 STAILQ_INSERT_TAIL(&pqnode->pqueue, dest, pq);
3124 pqnode->queued++;
3125
3126 if (!pqnode_reuse)
3127 work_queue_add(wq, pqnode);
3128
3129 return;
3130 }
3131
3132 void bgp_add_eoiu_mark(struct bgp *bgp)
3133 {
3134 struct bgp_process_queue *pqnode;
3135
3136 if (bgp->process_queue == NULL)
3137 return;
3138
3139 pqnode = bgp_processq_alloc(bgp);
3140
3141 SET_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER);
3142 work_queue_add(bgp->process_queue, pqnode);
3143 }
3144
3145 static int bgp_maximum_prefix_restart_timer(struct thread *thread)
3146 {
3147 struct peer *peer;
3148
3149 peer = THREAD_ARG(thread);
3150 peer->t_pmax_restart = NULL;
3151
3152 if (bgp_debug_neighbor_events(peer))
3153 zlog_debug(
3154 "%s Maximum-prefix restart timer expired, restore peering",
3155 peer->host);
3156
3157 if ((peer_clear(peer, NULL) < 0) && bgp_debug_neighbor_events(peer))
3158 zlog_debug("%s: %s peer_clear failed", __func__, peer->host);
3159
3160 return 0;
3161 }
3162
3163 static uint32_t bgp_filtered_routes_count(struct peer *peer, afi_t afi,
3164 safi_t safi)
3165 {
3166 uint32_t count = 0;
3167 bool filtered = false;
3168 struct bgp_dest *dest;
3169 struct bgp_adj_in *ain;
3170 struct attr attr = {};
3171 struct bgp_table *table = peer->bgp->rib[afi][safi];
3172
3173 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
3174 for (ain = dest->adj_in; ain; ain = ain->next) {
3175 const struct prefix *rn_p = bgp_dest_get_prefix(dest);
3176
3177 attr = *ain->attr;
3178
3179 if (bgp_input_filter(peer, rn_p, &attr, afi, safi)
3180 == FILTER_DENY)
3181 filtered = true;
3182
3183 if (bgp_input_modifier(
3184 peer, rn_p, &attr, afi, safi,
3185 ROUTE_MAP_IN_NAME(&peer->filter[afi][safi]),
3186 NULL, 0, NULL)
3187 == RMAP_DENY)
3188 filtered = true;
3189
3190 if (filtered)
3191 count++;
3192
3193 bgp_attr_undup(&attr, ain->attr);
3194 }
3195 }
3196
3197 return count;
3198 }
3199
3200 bool bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi,
3201 int always)
3202 {
3203 iana_afi_t pkt_afi;
3204 iana_safi_t pkt_safi;
3205 uint32_t pcount = (CHECK_FLAG(peer->af_flags[afi][safi],
3206 PEER_FLAG_MAX_PREFIX_FORCE))
3207 ? bgp_filtered_routes_count(peer, afi, safi)
3208 + peer->pcount[afi][safi]
3209 : peer->pcount[afi][safi];
3210
3211 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
3212 return false;
3213
3214 if (pcount > peer->pmax[afi][safi]) {
3215 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3216 PEER_STATUS_PREFIX_LIMIT)
3217 && !always)
3218 return false;
3219
3220 zlog_info(
3221 "%%MAXPFXEXCEED: No. of %s prefix received from %s %u exceed, limit %u",
3222 get_afi_safi_str(afi, safi, false), peer->host, pcount,
3223 peer->pmax[afi][safi]);
3224 SET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT);
3225
3226 if (CHECK_FLAG(peer->af_flags[afi][safi],
3227 PEER_FLAG_MAX_PREFIX_WARNING))
3228 return false;
3229
3230 /* Convert AFI, SAFI to values for packet. */
3231 pkt_afi = afi_int2iana(afi);
3232 pkt_safi = safi_int2iana(safi);
3233 {
3234 uint8_t ndata[7];
3235
3236 ndata[0] = (pkt_afi >> 8);
3237 ndata[1] = pkt_afi;
3238 ndata[2] = pkt_safi;
3239 ndata[3] = (peer->pmax[afi][safi] >> 24);
3240 ndata[4] = (peer->pmax[afi][safi] >> 16);
3241 ndata[5] = (peer->pmax[afi][safi] >> 8);
3242 ndata[6] = (peer->pmax[afi][safi]);
3243
3244 SET_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
3245 bgp_notify_send_with_data(peer, BGP_NOTIFY_CEASE,
3246 BGP_NOTIFY_CEASE_MAX_PREFIX,
3247 ndata, 7);
3248 }
3249
3250 /* Dynamic peers will just close their connection. */
3251 if (peer_dynamic_neighbor(peer))
3252 return true;
3253
3254 /* restart timer start */
3255 if (peer->pmax_restart[afi][safi]) {
3256 peer->v_pmax_restart =
3257 peer->pmax_restart[afi][safi] * 60;
3258
3259 if (bgp_debug_neighbor_events(peer))
3260 zlog_debug(
3261 "%s Maximum-prefix restart timer started for %d secs",
3262 peer->host, peer->v_pmax_restart);
3263
3264 BGP_TIMER_ON(peer->t_pmax_restart,
3265 bgp_maximum_prefix_restart_timer,
3266 peer->v_pmax_restart);
3267 }
3268
3269 return true;
3270 } else
3271 UNSET_FLAG(peer->af_sflags[afi][safi],
3272 PEER_STATUS_PREFIX_LIMIT);
3273
3274 if (pcount
3275 > (peer->pmax[afi][safi] * peer->pmax_threshold[afi][safi] / 100)) {
3276 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3277 PEER_STATUS_PREFIX_THRESHOLD)
3278 && !always)
3279 return false;
3280
3281 zlog_info(
3282 "%%MAXPFX: No. of %s prefix received from %s reaches %u, max %u",
3283 get_afi_safi_str(afi, safi, false), peer->host, pcount,
3284 peer->pmax[afi][safi]);
3285 SET_FLAG(peer->af_sflags[afi][safi],
3286 PEER_STATUS_PREFIX_THRESHOLD);
3287 } else
3288 UNSET_FLAG(peer->af_sflags[afi][safi],
3289 PEER_STATUS_PREFIX_THRESHOLD);
3290 return false;
3291 }
3292
3293 /* Unconditionally remove the route from the RIB, without taking
3294 * damping into consideration (eg, because the session went down)
3295 */
3296 void bgp_rib_remove(struct bgp_dest *dest, struct bgp_path_info *pi,
3297 struct peer *peer, afi_t afi, safi_t safi)
3298 {
3299
3300 struct bgp *bgp = NULL;
3301 bool delete_route = false;
3302
3303 bgp_aggregate_decrement(peer->bgp, bgp_dest_get_prefix(dest), pi, afi,
3304 safi);
3305
3306 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
3307 bgp_path_info_delete(dest, pi); /* keep historical info */
3308
3309 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3310 * flag
3311 */
3312 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3313 delete_route = true;
3314 else if (bgp_dest_set_defer_flag(dest, true) < 0)
3315 delete_route = true;
3316 if (delete_route) {
3317 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
3318 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
3319 bgp = pi->peer->bgp;
3320 bgp->gr_info[afi][safi].gr_deferred--;
3321 }
3322 }
3323 }
3324
3325 hook_call(bgp_process, peer->bgp, afi, safi, dest, peer, true);
3326 bgp_process(peer->bgp, dest, afi, safi);
3327 }
3328
3329 static void bgp_rib_withdraw(struct bgp_dest *dest, struct bgp_path_info *pi,
3330 struct peer *peer, afi_t afi, safi_t safi,
3331 struct prefix_rd *prd)
3332 {
3333 const struct prefix *p = bgp_dest_get_prefix(dest);
3334
3335 /* apply dampening, if result is suppressed, we'll be retaining
3336 * the bgp_path_info in the RIB for historical reference.
3337 */
3338 if (peer->sort == BGP_PEER_EBGP) {
3339 if (get_active_bdc_from_pi(pi, afi, safi)) {
3340 if (bgp_damp_withdraw(pi, dest, afi, safi, 0)
3341 == BGP_DAMP_SUPPRESSED) {
3342 bgp_aggregate_decrement(peer->bgp, p, pi, afi,
3343 safi);
3344 return;
3345 }
3346 }
3347 }
3348
3349 #ifdef ENABLE_BGP_VNC
3350 if (safi == SAFI_MPLS_VPN) {
3351 struct bgp_dest *pdest = NULL;
3352 struct bgp_table *table = NULL;
3353
3354 pdest = bgp_node_get(peer->bgp->rib[afi][safi],
3355 (struct prefix *)prd);
3356 if (bgp_dest_has_bgp_path_info_data(pdest)) {
3357 table = bgp_dest_get_bgp_table_info(pdest);
3358
3359 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3360 peer->bgp, prd, table, p, pi);
3361 }
3362 bgp_dest_unlock_node(pdest);
3363 }
3364 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
3365 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
3366
3367 vnc_import_bgp_del_route(peer->bgp, p, pi);
3368 vnc_import_bgp_exterior_del_route(peer->bgp, p, pi);
3369 }
3370 }
3371 #endif
3372
3373 /* If this is an EVPN route, process for un-import. */
3374 if (safi == SAFI_EVPN)
3375 bgp_evpn_unimport_route(peer->bgp, afi, safi, p, pi);
3376
3377 bgp_rib_remove(dest, pi, peer, afi, safi);
3378 }
3379
3380 struct bgp_path_info *info_make(int type, int sub_type, unsigned short instance,
3381 struct peer *peer, struct attr *attr,
3382 struct bgp_dest *dest)
3383 {
3384 struct bgp_path_info *new;
3385
3386 /* Make new BGP info. */
3387 new = XCALLOC(MTYPE_BGP_ROUTE, sizeof(struct bgp_path_info));
3388 new->type = type;
3389 new->instance = instance;
3390 new->sub_type = sub_type;
3391 new->peer = peer;
3392 new->attr = attr;
3393 new->uptime = bgp_clock();
3394 new->net = dest;
3395 return new;
3396 }
3397
3398 static void overlay_index_update(struct attr *attr,
3399 union gw_addr *gw_ip)
3400 {
3401 if (!attr)
3402 return;
3403 if (gw_ip == NULL) {
3404 struct bgp_route_evpn eo;
3405
3406 memset(&eo, 0, sizeof(eo));
3407 bgp_attr_set_evpn_overlay(attr, &eo);
3408 } else {
3409 struct bgp_route_evpn eo = {.gw_ip = *gw_ip};
3410
3411 bgp_attr_set_evpn_overlay(attr, &eo);
3412 }
3413 }
3414
3415 static bool overlay_index_equal(afi_t afi, struct bgp_path_info *path,
3416 union gw_addr *gw_ip)
3417 {
3418 const struct bgp_route_evpn *eo = bgp_attr_get_evpn_overlay(path->attr);
3419 union gw_addr path_gw_ip, *path_gw_ip_remote;
3420 union {
3421 esi_t esi;
3422 union gw_addr ip;
3423 } temp;
3424
3425 if (afi != AFI_L2VPN)
3426 return true;
3427
3428 path_gw_ip = eo->gw_ip;
3429
3430 if (gw_ip == NULL) {
3431 memset(&temp, 0, sizeof(temp));
3432 path_gw_ip_remote = &temp.ip;
3433 } else
3434 path_gw_ip_remote = gw_ip;
3435
3436 return !!memcmp(&path_gw_ip, path_gw_ip_remote, sizeof(union gw_addr));
3437 }
3438
3439 /* Check if received nexthop is valid or not. */
3440 bool bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
3441 uint8_t type, uint8_t stype, struct attr *attr,
3442 struct bgp_dest *dest)
3443 {
3444 bool ret = false;
3445 bool is_bgp_static_route =
3446 (type == ZEBRA_ROUTE_BGP && stype == BGP_ROUTE_STATIC) ? true
3447 : false;
3448
3449 /*
3450 * Only validated for unicast and multicast currently.
3451 * Also valid for EVPN where the nexthop is an IP address.
3452 * If we are a bgp static route being checked then there is
3453 * no need to check to see if the nexthop is martian as
3454 * that it should be ok.
3455 */
3456 if (is_bgp_static_route ||
3457 (safi != SAFI_UNICAST && safi != SAFI_MULTICAST && safi != SAFI_EVPN))
3458 return false;
3459
3460 /* If NEXT_HOP is present, validate it. */
3461 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
3462 if (attr->nexthop.s_addr == INADDR_ANY
3463 || IPV4_CLASS_DE(ntohl(attr->nexthop.s_addr))
3464 || bgp_nexthop_self(bgp, afi, type, stype, attr, dest))
3465 return true;
3466 }
3467
3468 /* If MP_NEXTHOP is present, validate it. */
3469 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3470 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3471 * it is not an IPv6 link-local address.
3472 *
3473 * If we receive an UPDATE with nexthop length set to 32 bytes
3474 * we shouldn't discard an UPDATE if it's set to (::).
3475 * The link-local (2st) is validated along the code path later.
3476 */
3477 if (attr->mp_nexthop_len) {
3478 switch (attr->mp_nexthop_len) {
3479 case BGP_ATTR_NHLEN_IPV4:
3480 case BGP_ATTR_NHLEN_VPNV4:
3481 ret = (attr->mp_nexthop_global_in.s_addr == INADDR_ANY
3482 || IPV4_CLASS_DE(
3483 ntohl(attr->mp_nexthop_global_in.s_addr))
3484 || bgp_nexthop_self(bgp, afi, type, stype, attr,
3485 dest));
3486 break;
3487
3488 case BGP_ATTR_NHLEN_IPV6_GLOBAL:
3489 case BGP_ATTR_NHLEN_VPNV6_GLOBAL:
3490 ret = (IN6_IS_ADDR_UNSPECIFIED(
3491 &attr->mp_nexthop_global)
3492 || IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3493 || IN6_IS_ADDR_MULTICAST(
3494 &attr->mp_nexthop_global)
3495 || bgp_nexthop_self(bgp, afi, type, stype, attr,
3496 dest));
3497 break;
3498 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
3499 ret = (IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3500 || IN6_IS_ADDR_MULTICAST(
3501 &attr->mp_nexthop_global)
3502 || bgp_nexthop_self(bgp, afi, type, stype, attr,
3503 dest));
3504 break;
3505
3506 default:
3507 ret = true;
3508 break;
3509 }
3510 }
3511
3512 return ret;
3513 }
3514
3515 static void bgp_attr_add_no_export_community(struct attr *attr)
3516 {
3517 struct community *old;
3518 struct community *new;
3519 struct community *merge;
3520 struct community *no_export;
3521
3522 old = attr->community;
3523 no_export = community_str2com("no-export");
3524
3525 assert(no_export);
3526
3527 if (old) {
3528 merge = community_merge(community_dup(old), no_export);
3529
3530 if (!old->refcnt)
3531 community_free(&old);
3532
3533 new = community_uniq_sort(merge);
3534 community_free(&merge);
3535 } else {
3536 new = community_dup(no_export);
3537 }
3538
3539 community_free(&no_export);
3540
3541 attr->community = new;
3542 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
3543 }
3544
3545 int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
3546 struct attr *attr, afi_t afi, safi_t safi, int type,
3547 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
3548 uint32_t num_labels, int soft_reconfig,
3549 struct bgp_route_evpn *evpn)
3550 {
3551 int ret;
3552 int aspath_loop_count = 0;
3553 struct bgp_dest *dest;
3554 struct bgp *bgp;
3555 struct attr new_attr;
3556 struct attr *attr_new;
3557 struct bgp_path_info *pi;
3558 struct bgp_path_info *new;
3559 struct bgp_path_info_extra *extra;
3560 const char *reason;
3561 char pfx_buf[BGP_PRD_PATH_STRLEN];
3562 int connected = 0;
3563 int do_loop_check = 1;
3564 int has_valid_label = 0;
3565 afi_t nh_afi;
3566 uint8_t pi_type = 0;
3567 uint8_t pi_sub_type = 0;
3568
3569 if (frrtrace_enabled(frr_bgp, process_update)) {
3570 char pfxprint[PREFIX2STR_BUFFER];
3571
3572 prefix2str(p, pfxprint, sizeof(pfxprint));
3573 frrtrace(6, frr_bgp, process_update, peer, pfxprint, addpath_id,
3574 afi, safi, attr);
3575 }
3576
3577 #ifdef ENABLE_BGP_VNC
3578 int vnc_implicit_withdraw = 0;
3579 #endif
3580 int same_attr = 0;
3581
3582 memset(&new_attr, 0, sizeof(struct attr));
3583 new_attr.label_index = BGP_INVALID_LABEL_INDEX;
3584 new_attr.label = MPLS_INVALID_LABEL;
3585
3586 bgp = peer->bgp;
3587 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
3588 /* TODO: Check to see if we can get rid of "is_valid_label" */
3589 if (afi == AFI_L2VPN && safi == SAFI_EVPN)
3590 has_valid_label = (num_labels > 0) ? 1 : 0;
3591 else
3592 has_valid_label = bgp_is_valid_label(label);
3593
3594 if (has_valid_label)
3595 assert(label != NULL);
3596
3597 /* The flag BGP_NODE_FIB_INSTALL_PENDING is for the following
3598 * condition :
3599 * Suppress fib is enabled
3600 * BGP_OPT_NO_FIB is not enabled
3601 * Route type is BGP_ROUTE_NORMAL (peer learnt routes)
3602 * Route is being installed first time (BGP_NODE_FIB_INSTALLED not set)
3603 */
3604 if (BGP_SUPPRESS_FIB_ENABLED(bgp) &&
3605 (sub_type == BGP_ROUTE_NORMAL) &&
3606 (!bgp_option_check(BGP_OPT_NO_FIB)) &&
3607 (!CHECK_FLAG(dest->flags, BGP_NODE_FIB_INSTALLED)))
3608 SET_FLAG(dest->flags, BGP_NODE_FIB_INSTALL_PENDING);
3609
3610 /* When peer's soft reconfiguration enabled. Record input packet in
3611 Adj-RIBs-In. */
3612 if (!soft_reconfig
3613 && CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
3614 && peer != bgp->peer_self)
3615 bgp_adj_in_set(dest, peer, attr, addpath_id);
3616
3617 /* Check previously received route. */
3618 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
3619 if (pi->peer == peer && pi->type == type
3620 && pi->sub_type == sub_type
3621 && pi->addpath_rx_id == addpath_id)
3622 break;
3623
3624 /* AS path local-as loop check. */
3625 if (peer->change_local_as) {
3626 if (peer->allowas_in[afi][safi])
3627 aspath_loop_count = peer->allowas_in[afi][safi];
3628 else if (!CHECK_FLAG(peer->flags,
3629 PEER_FLAG_LOCAL_AS_NO_PREPEND))
3630 aspath_loop_count = 1;
3631
3632 if (aspath_loop_check(attr->aspath, peer->change_local_as)
3633 > aspath_loop_count) {
3634 peer->stat_pfx_aspath_loop++;
3635 reason = "as-path contains our own AS A;";
3636 goto filtered;
3637 }
3638 }
3639
3640 /* If the peer is configured for "allowas-in origin" and the last ASN in
3641 * the
3642 * as-path is our ASN then we do not need to call aspath_loop_check
3643 */
3644 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN))
3645 if (aspath_get_last_as(attr->aspath) == bgp->as)
3646 do_loop_check = 0;
3647
3648 /* AS path loop check. */
3649 if (do_loop_check) {
3650 if (aspath_loop_check(attr->aspath, bgp->as)
3651 > peer->allowas_in[afi][safi]
3652 || (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)
3653 && aspath_loop_check(attr->aspath, bgp->confed_id)
3654 > peer->allowas_in[afi][safi])) {
3655 peer->stat_pfx_aspath_loop++;
3656 reason = "as-path contains our own AS;";
3657 goto filtered;
3658 }
3659 }
3660
3661 /* Route reflector originator ID check. */
3662 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
3663 && IPV4_ADDR_SAME(&bgp->router_id, &attr->originator_id)) {
3664 peer->stat_pfx_originator_loop++;
3665 reason = "originator is us;";
3666 goto filtered;
3667 }
3668
3669 /* Route reflector cluster ID check. */
3670 if (bgp_cluster_filter(peer, attr)) {
3671 peer->stat_pfx_cluster_loop++;
3672 reason = "reflected from the same cluster;";
3673 goto filtered;
3674 }
3675
3676 /* Apply incoming filter. */
3677 if (bgp_input_filter(peer, p, attr, afi, safi) == FILTER_DENY) {
3678 peer->stat_pfx_filter++;
3679 reason = "filter;";
3680 goto filtered;
3681 }
3682
3683 /* RFC 8212 to prevent route leaks.
3684 * This specification intends to improve this situation by requiring the
3685 * explicit configuration of both BGP Import and Export Policies for any
3686 * External BGP (EBGP) session such as customers, peers, or
3687 * confederation boundaries for all enabled address families. Through
3688 * codification of the aforementioned requirement, operators will
3689 * benefit from consistent behavior across different BGP
3690 * implementations.
3691 */
3692 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
3693 if (!bgp_inbound_policy_exists(peer,
3694 &peer->filter[afi][safi])) {
3695 reason = "inbound policy missing";
3696 goto filtered;
3697 }
3698
3699 /* draft-ietf-idr-deprecate-as-set-confed-set
3700 * Filter routes having AS_SET or AS_CONFED_SET in the path.
3701 * Eventually, This document (if approved) updates RFC 4271
3702 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
3703 * and obsoletes RFC 6472.
3704 */
3705 if (peer->bgp->reject_as_sets)
3706 if (aspath_check_as_sets(attr->aspath)) {
3707 reason =
3708 "as-path contains AS_SET or AS_CONFED_SET type;";
3709 goto filtered;
3710 }
3711
3712 new_attr = *attr;
3713
3714 /* Apply incoming route-map.
3715 * NB: new_attr may now contain newly allocated values from route-map
3716 * "set"
3717 * commands, so we need bgp_attr_flush in the error paths, until we
3718 * intern
3719 * the attr (which takes over the memory references) */
3720 if (bgp_input_modifier(peer, p, &new_attr, afi, safi, NULL, label,
3721 num_labels, dest)
3722 == RMAP_DENY) {
3723 peer->stat_pfx_filter++;
3724 reason = "route-map;";
3725 bgp_attr_flush(&new_attr);
3726 goto filtered;
3727 }
3728
3729 if (pi && pi->attr->rmap_table_id != new_attr.rmap_table_id) {
3730 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3731 /* remove from RIB previous entry */
3732 bgp_zebra_withdraw(p, pi, bgp, safi);
3733 }
3734
3735 if (peer->sort == BGP_PEER_EBGP) {
3736
3737 /* rfc7999:
3738 * A BGP speaker receiving an announcement tagged with the
3739 * BLACKHOLE community SHOULD add the NO_ADVERTISE or
3740 * NO_EXPORT community as defined in RFC1997, or a
3741 * similar community, to prevent propagation of the
3742 * prefix outside the local AS. The community to prevent
3743 * propagation SHOULD be chosen according to the operator's
3744 * routing policy.
3745 */
3746 if (new_attr.community
3747 && community_include(new_attr.community,
3748 COMMUNITY_BLACKHOLE))
3749 bgp_attr_add_no_export_community(&new_attr);
3750
3751 /* If we receive the graceful-shutdown community from an eBGP
3752 * peer we must lower local-preference */
3753 if (new_attr.community
3754 && community_include(new_attr.community, COMMUNITY_GSHUT)) {
3755 new_attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
3756 new_attr.local_pref = BGP_GSHUT_LOCAL_PREF;
3757
3758 /* If graceful-shutdown is configured then add the GSHUT
3759 * community to all paths received from eBGP peers */
3760 } else if (bgp_in_graceful_shutdown(peer->bgp))
3761 bgp_attr_add_gshut_community(&new_attr);
3762 }
3763
3764 if (pi) {
3765 pi_type = pi->type;
3766 pi_sub_type = pi->sub_type;
3767 }
3768
3769 /* next hop check. */
3770 if (!CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD)
3771 && bgp_update_martian_nexthop(bgp, afi, safi, pi_type, pi_sub_type,
3772 &new_attr, dest)) {
3773 peer->stat_pfx_nh_invalid++;
3774 reason = "martian or self next-hop;";
3775 bgp_attr_flush(&new_attr);
3776 goto filtered;
3777 }
3778
3779 if (bgp_mac_entry_exists(p) || bgp_mac_exist(&attr->rmac)) {
3780 peer->stat_pfx_nh_invalid++;
3781 reason = "self mac;";
3782 goto filtered;
3783 }
3784
3785 /* Update Overlay Index */
3786 if (afi == AFI_L2VPN) {
3787 overlay_index_update(&new_attr,
3788 evpn == NULL ? NULL : &evpn->gw_ip);
3789 }
3790
3791 attr_new = bgp_attr_intern(&new_attr);
3792
3793 /* If maximum prefix count is configured and current prefix
3794 * count exeed it.
3795 */
3796 if (bgp_maximum_prefix_overflow(peer, afi, safi, 0))
3797 return -1;
3798
3799 /* If the update is implicit withdraw. */
3800 if (pi) {
3801 pi->uptime = bgp_clock();
3802 same_attr = attrhash_cmp(pi->attr, attr_new);
3803
3804 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
3805
3806 /* Same attribute comes in. */
3807 if (!CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
3808 && same_attr
3809 && (!has_valid_label
3810 || memcmp(&(bgp_path_info_extra_get(pi))->label, label,
3811 num_labels * sizeof(mpls_label_t))
3812 == 0)
3813 && (overlay_index_equal(
3814 afi, pi,
3815 evpn == NULL ? NULL : &evpn->gw_ip))) {
3816 if (get_active_bdc_from_pi(pi, afi, safi)
3817 && peer->sort == BGP_PEER_EBGP
3818 && CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
3819 if (bgp_debug_update(peer, p, NULL, 1)) {
3820 bgp_debug_rdpfxpath2str(
3821 afi, safi, prd, p, label,
3822 num_labels, addpath_id ? 1 : 0,
3823 addpath_id, pfx_buf,
3824 sizeof(pfx_buf));
3825 zlog_debug("%s rcvd %s", peer->host,
3826 pfx_buf);
3827 }
3828
3829 if (bgp_damp_update(pi, dest, afi, safi)
3830 != BGP_DAMP_SUPPRESSED) {
3831 bgp_aggregate_increment(bgp, p, pi, afi,
3832 safi);
3833 bgp_process(bgp, dest, afi, safi);
3834 }
3835 } else /* Duplicate - odd */
3836 {
3837 if (bgp_debug_update(peer, p, NULL, 1)) {
3838 if (!peer->rcvd_attr_printed) {
3839 zlog_debug(
3840 "%s rcvd UPDATE w/ attr: %s",
3841 peer->host,
3842 peer->rcvd_attr_str);
3843 peer->rcvd_attr_printed = 1;
3844 }
3845
3846 bgp_debug_rdpfxpath2str(
3847 afi, safi, prd, p, label,
3848 num_labels, addpath_id ? 1 : 0,
3849 addpath_id, pfx_buf,
3850 sizeof(pfx_buf));
3851 zlog_debug(
3852 "%s rcvd %s...duplicate ignored",
3853 peer->host, pfx_buf);
3854 }
3855
3856 /* graceful restart STALE flag unset. */
3857 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
3858 bgp_path_info_unset_flag(
3859 dest, pi, BGP_PATH_STALE);
3860 bgp_dest_set_defer_flag(dest, false);
3861 bgp_process(bgp, dest, afi, safi);
3862 }
3863 }
3864
3865 bgp_dest_unlock_node(dest);
3866 bgp_attr_unintern(&attr_new);
3867
3868 return 0;
3869 }
3870
3871 /* Withdraw/Announce before we fully processed the withdraw */
3872 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
3873 if (bgp_debug_update(peer, p, NULL, 1)) {
3874 bgp_debug_rdpfxpath2str(
3875 afi, safi, prd, p, label, num_labels,
3876 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3877 sizeof(pfx_buf));
3878 zlog_debug(
3879 "%s rcvd %s, flapped quicker than processing",
3880 peer->host, pfx_buf);
3881 }
3882
3883 bgp_path_info_restore(dest, pi);
3884 }
3885
3886 /* Received Logging. */
3887 if (bgp_debug_update(peer, p, NULL, 1)) {
3888 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label,
3889 num_labels, addpath_id ? 1 : 0,
3890 addpath_id, pfx_buf,
3891 sizeof(pfx_buf));
3892 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
3893 }
3894
3895 /* graceful restart STALE flag unset. */
3896 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
3897 bgp_path_info_unset_flag(dest, pi, BGP_PATH_STALE);
3898 bgp_dest_set_defer_flag(dest, false);
3899 }
3900
3901 /* The attribute is changed. */
3902 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
3903
3904 /* implicit withdraw, decrement aggregate and pcount here.
3905 * only if update is accepted, they'll increment below.
3906 */
3907 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
3908
3909 /* Update bgp route dampening information. */
3910 if (get_active_bdc_from_pi(pi, afi, safi)
3911 && peer->sort == BGP_PEER_EBGP) {
3912 /* This is implicit withdraw so we should update
3913 * dampening information.
3914 */
3915 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
3916 bgp_damp_withdraw(pi, dest, afi, safi, 1);
3917 }
3918 #ifdef ENABLE_BGP_VNC
3919 if (safi == SAFI_MPLS_VPN) {
3920 struct bgp_dest *pdest = NULL;
3921 struct bgp_table *table = NULL;
3922
3923 pdest = bgp_node_get(bgp->rib[afi][safi],
3924 (struct prefix *)prd);
3925 if (bgp_dest_has_bgp_path_info_data(pdest)) {
3926 table = bgp_dest_get_bgp_table_info(pdest);
3927
3928 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3929 bgp, prd, table, p, pi);
3930 }
3931 bgp_dest_unlock_node(pdest);
3932 }
3933 if ((afi == AFI_IP || afi == AFI_IP6)
3934 && (safi == SAFI_UNICAST)) {
3935 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
3936 /*
3937 * Implicit withdraw case.
3938 */
3939 ++vnc_implicit_withdraw;
3940 vnc_import_bgp_del_route(bgp, p, pi);
3941 vnc_import_bgp_exterior_del_route(bgp, p, pi);
3942 }
3943 }
3944 #endif
3945
3946 /* Special handling for EVPN update of an existing route. If the
3947 * extended community attribute has changed, we need to
3948 * un-import
3949 * the route using its existing extended community. It will be
3950 * subsequently processed for import with the new extended
3951 * community.
3952 */
3953 if (((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN))
3954 && !same_attr) {
3955 if ((pi->attr->flag
3956 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))
3957 && (attr_new->flag
3958 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
3959 int cmp;
3960
3961 cmp = ecommunity_cmp(pi->attr->ecommunity,
3962 attr_new->ecommunity);
3963 if (!cmp) {
3964 if (bgp_debug_update(peer, p, NULL, 1))
3965 zlog_debug(
3966 "Change in EXT-COMM, existing %s new %s",
3967 ecommunity_str(
3968 pi->attr->ecommunity),
3969 ecommunity_str(
3970 attr_new->ecommunity));
3971 if (safi == SAFI_EVPN)
3972 bgp_evpn_unimport_route(
3973 bgp, afi, safi, p, pi);
3974 else /* SAFI_MPLS_VPN */
3975 vpn_leak_to_vrf_withdraw(bgp,
3976 pi);
3977 }
3978 }
3979 }
3980
3981 /* Update to new attribute. */
3982 bgp_attr_unintern(&pi->attr);
3983 pi->attr = attr_new;
3984
3985 /* Update MPLS label */
3986 if (has_valid_label) {
3987 extra = bgp_path_info_extra_get(pi);
3988 if (extra->label != label) {
3989 memcpy(&extra->label, label,
3990 num_labels * sizeof(mpls_label_t));
3991 extra->num_labels = num_labels;
3992 }
3993 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
3994 bgp_set_valid_label(&extra->label[0]);
3995 }
3996
3997 /* Update SRv6 SID */
3998 if (attr->srv6_l3vpn) {
3999 extra = bgp_path_info_extra_get(pi);
4000 if (sid_diff(&extra->sid[0], &attr->srv6_l3vpn->sid)) {
4001 sid_copy(&extra->sid[0],
4002 &attr->srv6_l3vpn->sid);
4003 extra->num_sids = 1;
4004 }
4005 } else if (attr->srv6_vpn) {
4006 extra = bgp_path_info_extra_get(pi);
4007 if (sid_diff(&extra->sid[0], &attr->srv6_vpn->sid)) {
4008 sid_copy(&extra->sid[0], &attr->srv6_vpn->sid);
4009 extra->num_sids = 1;
4010 }
4011 }
4012
4013 #ifdef ENABLE_BGP_VNC
4014 if ((afi == AFI_IP || afi == AFI_IP6)
4015 && (safi == SAFI_UNICAST)) {
4016 if (vnc_implicit_withdraw) {
4017 /*
4018 * Add back the route with its new attributes
4019 * (e.g., nexthop).
4020 * The route is still selected, until the route
4021 * selection
4022 * queued by bgp_process actually runs. We have
4023 * to make this
4024 * update to the VNC side immediately to avoid
4025 * racing against
4026 * configuration changes (e.g., route-map
4027 * changes) which
4028 * trigger re-importation of the entire RIB.
4029 */
4030 vnc_import_bgp_add_route(bgp, p, pi);
4031 vnc_import_bgp_exterior_add_route(bgp, p, pi);
4032 }
4033 }
4034 #endif
4035
4036 /* Update bgp route dampening information. */
4037 if (get_active_bdc_from_pi(pi, afi, safi)
4038 && peer->sort == BGP_PEER_EBGP) {
4039 /* Now we do normal update dampening. */
4040 ret = bgp_damp_update(pi, dest, afi, safi);
4041 if (ret == BGP_DAMP_SUPPRESSED) {
4042 bgp_dest_unlock_node(dest);
4043 return 0;
4044 }
4045 }
4046
4047 /* Nexthop reachability check - for unicast and
4048 * labeled-unicast.. */
4049 if (((afi == AFI_IP || afi == AFI_IP6)
4050 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4051 || (safi == SAFI_EVPN &&
4052 bgp_evpn_is_prefix_nht_supported(p))) {
4053 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4054 && peer->ttl == BGP_DEFAULT_TTL
4055 && !CHECK_FLAG(peer->flags,
4056 PEER_FLAG_DISABLE_CONNECTED_CHECK)
4057 && !CHECK_FLAG(bgp->flags,
4058 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
4059 connected = 1;
4060 else
4061 connected = 0;
4062
4063 struct bgp *bgp_nexthop = bgp;
4064
4065 if (pi->extra && pi->extra->bgp_orig)
4066 bgp_nexthop = pi->extra->bgp_orig;
4067
4068 nh_afi = BGP_ATTR_NH_AFI(afi, pi->attr);
4069
4070 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop, nh_afi,
4071 safi, pi, NULL, connected)
4072 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
4073 bgp_path_info_set_flag(dest, pi,
4074 BGP_PATH_VALID);
4075 else {
4076 if (BGP_DEBUG(nht, NHT)) {
4077 zlog_debug("%s(%pI4): NH unresolved",
4078 __func__,
4079 (in_addr_t *)&attr_new->nexthop);
4080 }
4081 bgp_path_info_unset_flag(dest, pi,
4082 BGP_PATH_VALID);
4083 }
4084 } else
4085 bgp_path_info_set_flag(dest, pi, BGP_PATH_VALID);
4086
4087 #ifdef ENABLE_BGP_VNC
4088 if (safi == SAFI_MPLS_VPN) {
4089 struct bgp_dest *pdest = NULL;
4090 struct bgp_table *table = NULL;
4091
4092 pdest = bgp_node_get(bgp->rib[afi][safi],
4093 (struct prefix *)prd);
4094 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4095 table = bgp_dest_get_bgp_table_info(pdest);
4096
4097 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4098 bgp, prd, table, p, pi);
4099 }
4100 bgp_dest_unlock_node(pdest);
4101 }
4102 #endif
4103
4104 /* If this is an EVPN route and some attribute has changed,
4105 * process
4106 * route for import. If the extended community has changed, we
4107 * would
4108 * have done the un-import earlier and the import would result
4109 * in the
4110 * route getting injected into appropriate L2 VNIs. If it is
4111 * just
4112 * some other attribute change, the import will result in
4113 * updating
4114 * the attributes for the route in the VNI(s).
4115 */
4116 if (safi == SAFI_EVPN && !same_attr &&
4117 CHECK_FLAG(pi->flags, BGP_PATH_VALID))
4118 bgp_evpn_import_route(bgp, afi, safi, p, pi);
4119
4120 /* Process change. */
4121 bgp_aggregate_increment(bgp, p, pi, afi, safi);
4122
4123 bgp_process(bgp, dest, afi, safi);
4124 bgp_dest_unlock_node(dest);
4125
4126 if (SAFI_UNICAST == safi
4127 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4128 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4129
4130 vpn_leak_from_vrf_update(bgp_get_default(), bgp, pi);
4131 }
4132 if ((SAFI_MPLS_VPN == safi)
4133 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4134
4135 vpn_leak_to_vrf_update(bgp, pi);
4136 }
4137
4138 #ifdef ENABLE_BGP_VNC
4139 if (SAFI_MPLS_VPN == safi) {
4140 mpls_label_t label_decoded = decode_label(label);
4141
4142 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4143 type, sub_type, &label_decoded);
4144 }
4145 if (SAFI_ENCAP == safi) {
4146 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4147 type, sub_type, NULL);
4148 }
4149 #endif
4150
4151 return 0;
4152 } // End of implicit withdraw
4153
4154 /* Received Logging. */
4155 if (bgp_debug_update(peer, p, NULL, 1)) {
4156 if (!peer->rcvd_attr_printed) {
4157 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
4158 peer->rcvd_attr_str);
4159 peer->rcvd_attr_printed = 1;
4160 }
4161
4162 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
4163 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4164 sizeof(pfx_buf));
4165 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
4166 }
4167
4168 /* Make new BGP info. */
4169 new = info_make(type, sub_type, 0, peer, attr_new, dest);
4170
4171 /* Update MPLS label */
4172 if (has_valid_label) {
4173 extra = bgp_path_info_extra_get(new);
4174 if (extra->label != label) {
4175 memcpy(&extra->label, label,
4176 num_labels * sizeof(mpls_label_t));
4177 extra->num_labels = num_labels;
4178 }
4179 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4180 bgp_set_valid_label(&extra->label[0]);
4181 }
4182
4183 /* Update SRv6 SID */
4184 if (safi == SAFI_MPLS_VPN) {
4185 extra = bgp_path_info_extra_get(new);
4186 if (attr->srv6_l3vpn) {
4187 sid_copy(&extra->sid[0], &attr->srv6_l3vpn->sid);
4188 extra->num_sids = 1;
4189 } else if (attr->srv6_vpn) {
4190 sid_copy(&extra->sid[0], &attr->srv6_vpn->sid);
4191 extra->num_sids = 1;
4192 }
4193 }
4194
4195 /* Update Overlay Index */
4196 if (afi == AFI_L2VPN) {
4197 overlay_index_update(new->attr,
4198 evpn == NULL ? NULL : &evpn->gw_ip);
4199 }
4200 /* Nexthop reachability check. */
4201 if (((afi == AFI_IP || afi == AFI_IP6)
4202 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4203 || (safi == SAFI_EVPN && bgp_evpn_is_prefix_nht_supported(p))) {
4204 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4205 && peer->ttl == BGP_DEFAULT_TTL
4206 && !CHECK_FLAG(peer->flags,
4207 PEER_FLAG_DISABLE_CONNECTED_CHECK)
4208 && !CHECK_FLAG(bgp->flags,
4209 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
4210 connected = 1;
4211 else
4212 connected = 0;
4213
4214 nh_afi = BGP_ATTR_NH_AFI(afi, new->attr);
4215
4216 if (bgp_find_or_add_nexthop(bgp, bgp, nh_afi, safi, new, NULL,
4217 connected)
4218 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
4219 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
4220 else {
4221 if (BGP_DEBUG(nht, NHT)) {
4222 char buf1[INET6_ADDRSTRLEN];
4223 inet_ntop(AF_INET,
4224 (const void *)&attr_new->nexthop,
4225 buf1, INET6_ADDRSTRLEN);
4226 zlog_debug("%s(%s): NH unresolved", __func__,
4227 buf1);
4228 }
4229 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
4230 }
4231 } else
4232 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
4233
4234 /* Addpath ID */
4235 new->addpath_rx_id = addpath_id;
4236
4237 /* Increment prefix */
4238 bgp_aggregate_increment(bgp, p, new, afi, safi);
4239
4240 /* Register new BGP information. */
4241 bgp_path_info_add(dest, new);
4242
4243 /* route_node_get lock */
4244 bgp_dest_unlock_node(dest);
4245
4246 #ifdef ENABLE_BGP_VNC
4247 if (safi == SAFI_MPLS_VPN) {
4248 struct bgp_dest *pdest = NULL;
4249 struct bgp_table *table = NULL;
4250
4251 pdest = bgp_node_get(bgp->rib[afi][safi], (struct prefix *)prd);
4252 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4253 table = bgp_dest_get_bgp_table_info(pdest);
4254
4255 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4256 bgp, prd, table, p, new);
4257 }
4258 bgp_dest_unlock_node(pdest);
4259 }
4260 #endif
4261
4262 /* If this is an EVPN route, process for import. */
4263 if (safi == SAFI_EVPN && CHECK_FLAG(new->flags, BGP_PATH_VALID))
4264 bgp_evpn_import_route(bgp, afi, safi, p, new);
4265
4266 hook_call(bgp_process, bgp, afi, safi, dest, peer, false);
4267
4268 /* Process change. */
4269 bgp_process(bgp, dest, afi, safi);
4270
4271 if (SAFI_UNICAST == safi
4272 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4273 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4274 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
4275 }
4276 if ((SAFI_MPLS_VPN == safi)
4277 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4278
4279 vpn_leak_to_vrf_update(bgp, new);
4280 }
4281 #ifdef ENABLE_BGP_VNC
4282 if (SAFI_MPLS_VPN == safi) {
4283 mpls_label_t label_decoded = decode_label(label);
4284
4285 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4286 sub_type, &label_decoded);
4287 }
4288 if (SAFI_ENCAP == safi) {
4289 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4290 sub_type, NULL);
4291 }
4292 #endif
4293
4294 return 0;
4295
4296 /* This BGP update is filtered. Log the reason then update BGP
4297 entry. */
4298 filtered:
4299 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4300
4301 if (bgp_debug_update(peer, p, NULL, 1)) {
4302 if (!peer->rcvd_attr_printed) {
4303 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
4304 peer->rcvd_attr_str);
4305 peer->rcvd_attr_printed = 1;
4306 }
4307
4308 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
4309 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4310 sizeof(pfx_buf));
4311 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
4312 peer->host, pfx_buf, reason);
4313 }
4314
4315 if (pi) {
4316 /* If this is an EVPN route, un-import it as it is now filtered.
4317 */
4318 if (safi == SAFI_EVPN)
4319 bgp_evpn_unimport_route(bgp, afi, safi, p, pi);
4320
4321 if (SAFI_UNICAST == safi
4322 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4323 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4324
4325 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
4326 }
4327 if ((SAFI_MPLS_VPN == safi)
4328 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4329
4330 vpn_leak_to_vrf_withdraw(bgp, pi);
4331 }
4332
4333 bgp_rib_remove(dest, pi, peer, afi, safi);
4334 }
4335
4336 bgp_dest_unlock_node(dest);
4337
4338 #ifdef ENABLE_BGP_VNC
4339 /*
4340 * Filtered update is treated as an implicit withdrawal (see
4341 * bgp_rib_remove()
4342 * a few lines above)
4343 */
4344 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4345 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4346 0);
4347 }
4348 #endif
4349
4350 return 0;
4351 }
4352
4353 int bgp_withdraw(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
4354 struct attr *attr, afi_t afi, safi_t safi, int type,
4355 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
4356 uint32_t num_labels, struct bgp_route_evpn *evpn)
4357 {
4358 struct bgp *bgp;
4359 char pfx_buf[BGP_PRD_PATH_STRLEN];
4360 struct bgp_dest *dest;
4361 struct bgp_path_info *pi;
4362
4363 #ifdef ENABLE_BGP_VNC
4364 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4365 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4366 0);
4367 }
4368 #endif
4369
4370 bgp = peer->bgp;
4371
4372 /* Lookup node. */
4373 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
4374
4375 /* If peer is soft reconfiguration enabled. Record input packet for
4376 * further calculation.
4377 *
4378 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4379 * routes that are filtered. This tanks out Quagga RS pretty badly due
4380 * to
4381 * the iteration over all RS clients.
4382 * Since we need to remove the entry from adj_in anyway, do that first
4383 * and
4384 * if there was no entry, we don't need to do anything more.
4385 */
4386 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
4387 && peer != bgp->peer_self)
4388 if (!bgp_adj_in_unset(dest, peer, addpath_id)) {
4389 peer->stat_pfx_dup_withdraw++;
4390
4391 if (bgp_debug_update(peer, p, NULL, 1)) {
4392 bgp_debug_rdpfxpath2str(
4393 afi, safi, prd, p, label, num_labels,
4394 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4395 sizeof(pfx_buf));
4396 zlog_debug(
4397 "%s withdrawing route %s not in adj-in",
4398 peer->host, pfx_buf);
4399 }
4400 bgp_dest_unlock_node(dest);
4401 return 0;
4402 }
4403
4404 /* Lookup withdrawn route. */
4405 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
4406 if (pi->peer == peer && pi->type == type
4407 && pi->sub_type == sub_type
4408 && pi->addpath_rx_id == addpath_id)
4409 break;
4410
4411 /* Logging. */
4412 if (bgp_debug_update(peer, p, NULL, 1)) {
4413 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
4414 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4415 sizeof(pfx_buf));
4416 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer->host,
4417 pfx_buf);
4418 }
4419
4420 /* Withdraw specified route from routing table. */
4421 if (pi && !CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
4422 bgp_rib_withdraw(dest, pi, peer, afi, safi, prd);
4423 if (SAFI_UNICAST == safi
4424 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4425 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4426 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
4427 }
4428 if ((SAFI_MPLS_VPN == safi)
4429 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4430
4431 vpn_leak_to_vrf_withdraw(bgp, pi);
4432 }
4433 } else if (bgp_debug_update(peer, p, NULL, 1)) {
4434 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
4435 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4436 sizeof(pfx_buf));
4437 zlog_debug("%s Can't find the route %s", peer->host, pfx_buf);
4438 }
4439
4440 /* Unlock bgp_node_get() lock. */
4441 bgp_dest_unlock_node(dest);
4442
4443 return 0;
4444 }
4445
4446 void bgp_default_originate(struct peer *peer, afi_t afi, safi_t safi,
4447 int withdraw)
4448 {
4449 struct update_subgroup *subgrp;
4450 subgrp = peer_subgroup(peer, afi, safi);
4451 subgroup_default_originate(subgrp, withdraw);
4452 }
4453
4454
4455 /*
4456 * bgp_stop_announce_route_timer
4457 */
4458 void bgp_stop_announce_route_timer(struct peer_af *paf)
4459 {
4460 if (!paf->t_announce_route)
4461 return;
4462
4463 thread_cancel(&paf->t_announce_route);
4464 }
4465
4466 /*
4467 * bgp_announce_route_timer_expired
4468 *
4469 * Callback that is invoked when the route announcement timer for a
4470 * peer_af expires.
4471 */
4472 static int bgp_announce_route_timer_expired(struct thread *t)
4473 {
4474 struct peer_af *paf;
4475 struct peer *peer;
4476
4477 paf = THREAD_ARG(t);
4478 peer = paf->peer;
4479
4480 if (peer->status != Established)
4481 return 0;
4482
4483 if (!peer->afc_nego[paf->afi][paf->safi])
4484 return 0;
4485
4486 peer_af_announce_route(paf, 1);
4487
4488 /* Notify BGP conditional advertisement scanner percess */
4489 peer->advmap_config_change[paf->afi][paf->safi] = true;
4490
4491 return 0;
4492 }
4493
4494 /*
4495 * bgp_announce_route
4496 *
4497 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
4498 */
4499 void bgp_announce_route(struct peer *peer, afi_t afi, safi_t safi)
4500 {
4501 struct peer_af *paf;
4502 struct update_subgroup *subgrp;
4503
4504 paf = peer_af_find(peer, afi, safi);
4505 if (!paf)
4506 return;
4507 subgrp = PAF_SUBGRP(paf);
4508
4509 /*
4510 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
4511 * or a refresh has already been triggered.
4512 */
4513 if (!subgrp || paf->t_announce_route)
4514 return;
4515
4516 /*
4517 * Start a timer to stagger/delay the announce. This serves
4518 * two purposes - announcement can potentially be combined for
4519 * multiple peers and the announcement doesn't happen in the
4520 * vty context.
4521 */
4522 thread_add_timer_msec(bm->master, bgp_announce_route_timer_expired, paf,
4523 (subgrp->peer_count == 1)
4524 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
4525 : BGP_ANNOUNCE_ROUTE_DELAY_MS,
4526 &paf->t_announce_route);
4527 }
4528
4529 /*
4530 * Announce routes from all AF tables to a peer.
4531 *
4532 * This should ONLY be called when there is a need to refresh the
4533 * routes to the peer based on a policy change for this peer alone
4534 * or a route refresh request received from the peer.
4535 * The operation will result in splitting the peer from its existing
4536 * subgroups and putting it in new subgroups.
4537 */
4538 void bgp_announce_route_all(struct peer *peer)
4539 {
4540 afi_t afi;
4541 safi_t safi;
4542
4543 FOREACH_AFI_SAFI (afi, safi)
4544 bgp_announce_route(peer, afi, safi);
4545 }
4546
4547 static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi,
4548 struct bgp_table *table,
4549 struct prefix_rd *prd)
4550 {
4551 int ret;
4552 struct bgp_dest *dest;
4553 struct bgp_adj_in *ain;
4554
4555 if (!table)
4556 table = peer->bgp->rib[afi][safi];
4557
4558 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
4559 for (ain = dest->adj_in; ain; ain = ain->next) {
4560 if (ain->peer != peer)
4561 continue;
4562
4563 struct bgp_path_info *pi;
4564 uint32_t num_labels = 0;
4565 mpls_label_t *label_pnt = NULL;
4566 struct bgp_route_evpn evpn;
4567
4568 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
4569 pi = pi->next)
4570 if (pi->peer == peer)
4571 break;
4572
4573 if (pi && pi->extra)
4574 num_labels = pi->extra->num_labels;
4575 if (num_labels)
4576 label_pnt = &pi->extra->label[0];
4577 if (pi)
4578 memcpy(&evpn,
4579 bgp_attr_get_evpn_overlay(pi->attr),
4580 sizeof(evpn));
4581 else
4582 memset(&evpn, 0, sizeof(evpn));
4583
4584 ret = bgp_update(peer, bgp_dest_get_prefix(dest),
4585 ain->addpath_rx_id, ain->attr, afi,
4586 safi, ZEBRA_ROUTE_BGP,
4587 BGP_ROUTE_NORMAL, prd, label_pnt,
4588 num_labels, 1, &evpn);
4589
4590 if (ret < 0) {
4591 bgp_dest_unlock_node(dest);
4592 return;
4593 }
4594 }
4595 }
4596
4597 void bgp_soft_reconfig_in(struct peer *peer, afi_t afi, safi_t safi)
4598 {
4599 struct bgp_dest *dest;
4600 struct bgp_table *table;
4601
4602 if (peer->status != Established)
4603 return;
4604
4605 if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP)
4606 && (safi != SAFI_EVPN))
4607 bgp_soft_reconfig_table(peer, afi, safi, NULL, NULL);
4608 else
4609 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4610 dest = bgp_route_next(dest)) {
4611 table = bgp_dest_get_bgp_table_info(dest);
4612
4613 if (table == NULL)
4614 continue;
4615
4616 const struct prefix *p = bgp_dest_get_prefix(dest);
4617 struct prefix_rd prd;
4618
4619 prd.family = AF_UNSPEC;
4620 prd.prefixlen = 64;
4621 memcpy(&prd.val, p->u.val, 8);
4622
4623 bgp_soft_reconfig_table(peer, afi, safi, table, &prd);
4624 }
4625 }
4626
4627
4628 struct bgp_clear_node_queue {
4629 struct bgp_dest *dest;
4630 };
4631
4632 static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data)
4633 {
4634 struct bgp_clear_node_queue *cnq = data;
4635 struct bgp_dest *dest = cnq->dest;
4636 struct peer *peer = wq->spec.data;
4637 struct bgp_path_info *pi;
4638 struct bgp *bgp;
4639 afi_t afi = bgp_dest_table(dest)->afi;
4640 safi_t safi = bgp_dest_table(dest)->safi;
4641
4642 assert(dest && peer);
4643 bgp = peer->bgp;
4644
4645 /* It is possible that we have multiple paths for a prefix from a peer
4646 * if that peer is using AddPath.
4647 */
4648 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
4649 if (pi->peer != peer)
4650 continue;
4651
4652 /* graceful restart STALE flag set. */
4653 if (((CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)
4654 && peer->nsf[afi][safi])
4655 || CHECK_FLAG(peer->af_sflags[afi][safi],
4656 PEER_STATUS_ENHANCED_REFRESH))
4657 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
4658 && !CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
4659 bgp_path_info_set_flag(dest, pi, BGP_PATH_STALE);
4660 else {
4661 /* If this is an EVPN route, process for
4662 * un-import. */
4663 if (safi == SAFI_EVPN)
4664 bgp_evpn_unimport_route(
4665 bgp, afi, safi,
4666 bgp_dest_get_prefix(dest), pi);
4667 /* Handle withdraw for VRF route-leaking and L3VPN */
4668 if (SAFI_UNICAST == safi
4669 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF ||
4670 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4671 vpn_leak_from_vrf_withdraw(bgp_get_default(),
4672 bgp, pi);
4673 }
4674 if (SAFI_MPLS_VPN == safi &&
4675 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
4676 vpn_leak_to_vrf_withdraw(bgp, pi);
4677 }
4678
4679 bgp_rib_remove(dest, pi, peer, afi, safi);
4680 }
4681 }
4682 return WQ_SUCCESS;
4683 }
4684
4685 static void bgp_clear_node_queue_del(struct work_queue *wq, void *data)
4686 {
4687 struct bgp_clear_node_queue *cnq = data;
4688 struct bgp_dest *dest = cnq->dest;
4689 struct bgp_table *table = bgp_dest_table(dest);
4690
4691 bgp_dest_unlock_node(dest);
4692 bgp_table_unlock(table);
4693 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE, cnq);
4694 }
4695
4696 static void bgp_clear_node_complete(struct work_queue *wq)
4697 {
4698 struct peer *peer = wq->spec.data;
4699
4700 /* Tickle FSM to start moving again */
4701 BGP_EVENT_ADD(peer, Clearing_Completed);
4702
4703 peer_unlock(peer); /* bgp_clear_route */
4704 }
4705
4706 static void bgp_clear_node_queue_init(struct peer *peer)
4707 {
4708 char wname[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
4709
4710 snprintf(wname, sizeof(wname), "clear %s", peer->host);
4711 #undef CLEAR_QUEUE_NAME_LEN
4712
4713 peer->clear_node_queue = work_queue_new(bm->master, wname);
4714 peer->clear_node_queue->spec.hold = 10;
4715 peer->clear_node_queue->spec.workfunc = &bgp_clear_route_node;
4716 peer->clear_node_queue->spec.del_item_data = &bgp_clear_node_queue_del;
4717 peer->clear_node_queue->spec.completion_func = &bgp_clear_node_complete;
4718 peer->clear_node_queue->spec.max_retries = 0;
4719
4720 /* we only 'lock' this peer reference when the queue is actually active
4721 */
4722 peer->clear_node_queue->spec.data = peer;
4723 }
4724
4725 static void bgp_clear_route_table(struct peer *peer, afi_t afi, safi_t safi,
4726 struct bgp_table *table)
4727 {
4728 struct bgp_dest *dest;
4729 int force = peer->bgp->process_queue ? 0 : 1;
4730
4731 if (!table)
4732 table = peer->bgp->rib[afi][safi];
4733
4734 /* If still no table => afi/safi isn't configured at all or smth. */
4735 if (!table)
4736 return;
4737
4738 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
4739 struct bgp_path_info *pi, *next;
4740 struct bgp_adj_in *ain;
4741 struct bgp_adj_in *ain_next;
4742
4743 /* XXX:TODO: This is suboptimal, every non-empty route_node is
4744 * queued for every clearing peer, regardless of whether it is
4745 * relevant to the peer at hand.
4746 *
4747 * Overview: There are 3 different indices which need to be
4748 * scrubbed, potentially, when a peer is removed:
4749 *
4750 * 1 peer's routes visible via the RIB (ie accepted routes)
4751 * 2 peer's routes visible by the (optional) peer's adj-in index
4752 * 3 other routes visible by the peer's adj-out index
4753 *
4754 * 3 there is no hurry in scrubbing, once the struct peer is
4755 * removed from bgp->peer, we could just GC such deleted peer's
4756 * adj-outs at our leisure.
4757 *
4758 * 1 and 2 must be 'scrubbed' in some way, at least made
4759 * invisible via RIB index before peer session is allowed to be
4760 * brought back up. So one needs to know when such a 'search' is
4761 * complete.
4762 *
4763 * Ideally:
4764 *
4765 * - there'd be a single global queue or a single RIB walker
4766 * - rather than tracking which route_nodes still need to be
4767 * examined on a peer basis, we'd track which peers still
4768 * aren't cleared
4769 *
4770 * Given that our per-peer prefix-counts now should be reliable,
4771 * this may actually be achievable. It doesn't seem to be a huge
4772 * problem at this time,
4773 *
4774 * It is possible that we have multiple paths for a prefix from
4775 * a peer
4776 * if that peer is using AddPath.
4777 */
4778 ain = dest->adj_in;
4779 while (ain) {
4780 ain_next = ain->next;
4781
4782 if (ain->peer == peer) {
4783 bgp_adj_in_remove(dest, ain);
4784 bgp_dest_unlock_node(dest);
4785 }
4786
4787 ain = ain_next;
4788 }
4789
4790 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
4791 next = pi->next;
4792 if (pi->peer != peer)
4793 continue;
4794
4795 if (force)
4796 bgp_path_info_reap(dest, pi);
4797 else {
4798 struct bgp_clear_node_queue *cnq;
4799
4800 /* both unlocked in bgp_clear_node_queue_del */
4801 bgp_table_lock(bgp_dest_table(dest));
4802 bgp_dest_lock_node(dest);
4803 cnq = XCALLOC(
4804 MTYPE_BGP_CLEAR_NODE_QUEUE,
4805 sizeof(struct bgp_clear_node_queue));
4806 cnq->dest = dest;
4807 work_queue_add(peer->clear_node_queue, cnq);
4808 break;
4809 }
4810 }
4811 }
4812 return;
4813 }
4814
4815 void bgp_clear_route(struct peer *peer, afi_t afi, safi_t safi)
4816 {
4817 struct bgp_dest *dest;
4818 struct bgp_table *table;
4819
4820 if (peer->clear_node_queue == NULL)
4821 bgp_clear_node_queue_init(peer);
4822
4823 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
4824 * Idle until it receives a Clearing_Completed event. This protects
4825 * against peers which flap faster than we can we clear, which could
4826 * lead to:
4827 *
4828 * a) race with routes from the new session being installed before
4829 * clear_route_node visits the node (to delete the route of that
4830 * peer)
4831 * b) resource exhaustion, clear_route_node likely leads to an entry
4832 * on the process_main queue. Fast-flapping could cause that queue
4833 * to grow and grow.
4834 */
4835
4836 /* lock peer in assumption that clear-node-queue will get nodes; if so,
4837 * the unlock will happen upon work-queue completion; other wise, the
4838 * unlock happens at the end of this function.
4839 */
4840 if (!peer->clear_node_queue->thread)
4841 peer_lock(peer);
4842
4843 if (safi != SAFI_MPLS_VPN && safi != SAFI_ENCAP && safi != SAFI_EVPN)
4844 bgp_clear_route_table(peer, afi, safi, NULL);
4845 else
4846 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4847 dest = bgp_route_next(dest)) {
4848 table = bgp_dest_get_bgp_table_info(dest);
4849 if (!table)
4850 continue;
4851
4852 bgp_clear_route_table(peer, afi, safi, table);
4853 }
4854
4855 /* unlock if no nodes got added to the clear-node-queue. */
4856 if (!peer->clear_node_queue->thread)
4857 peer_unlock(peer);
4858 }
4859
4860 void bgp_clear_route_all(struct peer *peer)
4861 {
4862 afi_t afi;
4863 safi_t safi;
4864
4865 FOREACH_AFI_SAFI (afi, safi)
4866 bgp_clear_route(peer, afi, safi);
4867
4868 #ifdef ENABLE_BGP_VNC
4869 rfapiProcessPeerDown(peer);
4870 #endif
4871 }
4872
4873 void bgp_clear_adj_in(struct peer *peer, afi_t afi, safi_t safi)
4874 {
4875 struct bgp_table *table;
4876 struct bgp_dest *dest;
4877 struct bgp_adj_in *ain;
4878 struct bgp_adj_in *ain_next;
4879
4880 table = peer->bgp->rib[afi][safi];
4881
4882 /* It is possible that we have multiple paths for a prefix from a peer
4883 * if that peer is using AddPath.
4884 */
4885 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
4886 ain = dest->adj_in;
4887
4888 while (ain) {
4889 ain_next = ain->next;
4890
4891 if (ain->peer == peer) {
4892 bgp_adj_in_remove(dest, ain);
4893 bgp_dest_unlock_node(dest);
4894 }
4895
4896 ain = ain_next;
4897 }
4898 }
4899 }
4900
4901 void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
4902 {
4903 struct bgp_dest *dest;
4904 struct bgp_path_info *pi;
4905 struct bgp_table *table;
4906
4907 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
4908 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4909 dest = bgp_route_next(dest)) {
4910 struct bgp_dest *rm;
4911
4912 /* look for neighbor in tables */
4913 table = bgp_dest_get_bgp_table_info(dest);
4914 if (!table)
4915 continue;
4916
4917 for (rm = bgp_table_top(table); rm;
4918 rm = bgp_route_next(rm))
4919 for (pi = bgp_dest_get_bgp_path_info(rm); pi;
4920 pi = pi->next) {
4921 if (pi->peer != peer)
4922 continue;
4923 if (!CHECK_FLAG(pi->flags,
4924 BGP_PATH_STALE))
4925 break;
4926
4927 bgp_rib_remove(rm, pi, peer, afi, safi);
4928 break;
4929 }
4930 }
4931 } else {
4932 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4933 dest = bgp_route_next(dest))
4934 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
4935 pi = pi->next) {
4936 if (pi->peer != peer)
4937 continue;
4938 if (!CHECK_FLAG(pi->flags, BGP_PATH_STALE))
4939 break;
4940 bgp_rib_remove(dest, pi, peer, afi, safi);
4941 break;
4942 }
4943 }
4944 }
4945
4946 void bgp_set_stale_route(struct peer *peer, afi_t afi, safi_t safi)
4947 {
4948 struct bgp_dest *dest, *ndest;
4949 struct bgp_path_info *pi;
4950 struct bgp_table *table;
4951
4952 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
4953 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4954 dest = bgp_route_next(dest)) {
4955 table = bgp_dest_get_bgp_table_info(dest);
4956 if (!table)
4957 continue;
4958
4959 for (ndest = bgp_table_top(table); ndest;
4960 ndest = bgp_route_next(ndest)) {
4961 for (pi = bgp_dest_get_bgp_path_info(ndest); pi;
4962 pi = pi->next) {
4963 if (pi->peer != peer)
4964 continue;
4965
4966 if ((CHECK_FLAG(
4967 peer->af_sflags[afi][safi],
4968 PEER_STATUS_ENHANCED_REFRESH))
4969 && !CHECK_FLAG(pi->flags,
4970 BGP_PATH_STALE)
4971 && !CHECK_FLAG(
4972 pi->flags,
4973 BGP_PATH_UNUSEABLE)) {
4974 if (bgp_debug_neighbor_events(
4975 peer))
4976 zlog_debug(
4977 "%s: route-refresh for %s/%s, marking prefix %pFX as stale",
4978 peer->host,
4979 afi2str(afi),
4980 safi2str(safi),
4981 bgp_dest_get_prefix(
4982 ndest));
4983
4984 bgp_path_info_set_flag(
4985 ndest, pi,
4986 BGP_PATH_STALE);
4987 }
4988 }
4989 }
4990 }
4991 } else {
4992 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4993 dest = bgp_route_next(dest)) {
4994 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
4995 pi = pi->next) {
4996 if (pi->peer != peer)
4997 continue;
4998
4999 if ((CHECK_FLAG(peer->af_sflags[afi][safi],
5000 PEER_STATUS_ENHANCED_REFRESH))
5001 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
5002 && !CHECK_FLAG(pi->flags,
5003 BGP_PATH_UNUSEABLE)) {
5004 if (bgp_debug_neighbor_events(peer))
5005 zlog_debug(
5006 "%s: route-refresh for %s/%s, marking prefix %pFX as stale",
5007 peer->host,
5008 afi2str(afi),
5009 safi2str(safi),
5010 bgp_dest_get_prefix(
5011 dest));
5012
5013 bgp_path_info_set_flag(dest, pi,
5014 BGP_PATH_STALE);
5015 }
5016 }
5017 }
5018 }
5019 }
5020
5021 bool bgp_outbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
5022 {
5023 if (peer->sort == BGP_PEER_IBGP)
5024 return true;
5025
5026 if (peer->sort == BGP_PEER_EBGP
5027 && (ROUTE_MAP_OUT_NAME(filter) || PREFIX_LIST_OUT_NAME(filter)
5028 || FILTER_LIST_OUT_NAME(filter)
5029 || DISTRIBUTE_OUT_NAME(filter)))
5030 return true;
5031 return false;
5032 }
5033
5034 bool bgp_inbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
5035 {
5036 if (peer->sort == BGP_PEER_IBGP)
5037 return true;
5038
5039 if (peer->sort == BGP_PEER_EBGP
5040 && (ROUTE_MAP_IN_NAME(filter) || PREFIX_LIST_IN_NAME(filter)
5041 || FILTER_LIST_IN_NAME(filter)
5042 || DISTRIBUTE_IN_NAME(filter)))
5043 return true;
5044 return false;
5045 }
5046
5047 static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table,
5048 safi_t safi)
5049 {
5050 struct bgp_dest *dest;
5051 struct bgp_path_info *pi;
5052 struct bgp_path_info *next;
5053
5054 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
5055 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
5056 const struct prefix *p = bgp_dest_get_prefix(dest);
5057
5058 next = pi->next;
5059
5060 /* Unimport EVPN routes from VRFs */
5061 if (safi == SAFI_EVPN)
5062 bgp_evpn_unimport_route(bgp, AFI_L2VPN,
5063 SAFI_EVPN, p, pi);
5064
5065 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)
5066 && pi->type == ZEBRA_ROUTE_BGP
5067 && (pi->sub_type == BGP_ROUTE_NORMAL
5068 || pi->sub_type == BGP_ROUTE_AGGREGATE
5069 || pi->sub_type == BGP_ROUTE_IMPORTED)) {
5070
5071 if (bgp_fibupd_safi(safi))
5072 bgp_zebra_withdraw(p, pi, bgp, safi);
5073 }
5074
5075 bgp_path_info_reap(dest, pi);
5076 }
5077 }
5078
5079 /* Delete all kernel routes. */
5080 void bgp_cleanup_routes(struct bgp *bgp)
5081 {
5082 afi_t afi;
5083 struct bgp_dest *dest;
5084 struct bgp_table *table;
5085
5086 for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
5087 if (afi == AFI_L2VPN)
5088 continue;
5089 bgp_cleanup_table(bgp, bgp->rib[afi][SAFI_UNICAST],
5090 SAFI_UNICAST);
5091 /*
5092 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
5093 */
5094 if (afi != AFI_L2VPN) {
5095 safi_t safi;
5096 safi = SAFI_MPLS_VPN;
5097 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
5098 dest = bgp_route_next(dest)) {
5099 table = bgp_dest_get_bgp_table_info(dest);
5100 if (table != NULL) {
5101 bgp_cleanup_table(bgp, table, safi);
5102 bgp_table_finish(&table);
5103 bgp_dest_set_bgp_table_info(dest, NULL);
5104 bgp_dest_unlock_node(dest);
5105 }
5106 }
5107 safi = SAFI_ENCAP;
5108 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
5109 dest = bgp_route_next(dest)) {
5110 table = bgp_dest_get_bgp_table_info(dest);
5111 if (table != NULL) {
5112 bgp_cleanup_table(bgp, table, safi);
5113 bgp_table_finish(&table);
5114 bgp_dest_set_bgp_table_info(dest, NULL);
5115 bgp_dest_unlock_node(dest);
5116 }
5117 }
5118 }
5119 }
5120 for (dest = bgp_table_top(bgp->rib[AFI_L2VPN][SAFI_EVPN]); dest;
5121 dest = bgp_route_next(dest)) {
5122 table = bgp_dest_get_bgp_table_info(dest);
5123 if (table != NULL) {
5124 bgp_cleanup_table(bgp, table, SAFI_EVPN);
5125 bgp_table_finish(&table);
5126 bgp_dest_set_bgp_table_info(dest, NULL);
5127 bgp_dest_unlock_node(dest);
5128 }
5129 }
5130 }
5131
5132 void bgp_reset(void)
5133 {
5134 vty_reset();
5135 bgp_zclient_reset();
5136 access_list_reset();
5137 prefix_list_reset();
5138 }
5139
5140 static int bgp_addpath_encode_rx(struct peer *peer, afi_t afi, safi_t safi)
5141 {
5142 return (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV)
5143 && CHECK_FLAG(peer->af_cap[afi][safi],
5144 PEER_CAP_ADDPATH_AF_TX_RCV));
5145 }
5146
5147 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
5148 value. */
5149 int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
5150 struct bgp_nlri *packet)
5151 {
5152 uint8_t *pnt;
5153 uint8_t *lim;
5154 struct prefix p;
5155 int psize;
5156 int ret;
5157 afi_t afi;
5158 safi_t safi;
5159 int addpath_encoded;
5160 uint32_t addpath_id;
5161
5162 pnt = packet->nlri;
5163 lim = pnt + packet->length;
5164 afi = packet->afi;
5165 safi = packet->safi;
5166 addpath_id = 0;
5167 addpath_encoded = bgp_addpath_encode_rx(peer, afi, safi);
5168
5169 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
5170 syntactic validity. If the field is syntactically incorrect,
5171 then the Error Subcode is set to Invalid Network Field. */
5172 for (; pnt < lim; pnt += psize) {
5173 /* Clear prefix structure. */
5174 memset(&p, 0, sizeof(struct prefix));
5175
5176 if (addpath_encoded) {
5177
5178 /* When packet overflow occurs return immediately. */
5179 if (pnt + BGP_ADDPATH_ID_LEN >= lim)
5180 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
5181
5182 memcpy(&addpath_id, pnt, BGP_ADDPATH_ID_LEN);
5183 addpath_id = ntohl(addpath_id);
5184 pnt += BGP_ADDPATH_ID_LEN;
5185 }
5186
5187 /* Fetch prefix length. */
5188 p.prefixlen = *pnt++;
5189 /* afi/safi validity already verified by caller,
5190 * bgp_update_receive */
5191 p.family = afi2family(afi);
5192
5193 /* Prefix length check. */
5194 if (p.prefixlen > prefix_blen(&p) * 8) {
5195 flog_err(
5196 EC_BGP_UPDATE_RCV,
5197 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
5198 peer->host, p.prefixlen, packet->afi);
5199 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH;
5200 }
5201
5202 /* Packet size overflow check. */
5203 psize = PSIZE(p.prefixlen);
5204
5205 /* When packet overflow occur return immediately. */
5206 if (pnt + psize > lim) {
5207 flog_err(
5208 EC_BGP_UPDATE_RCV,
5209 "%s [Error] Update packet error (prefix length %d overflows packet)",
5210 peer->host, p.prefixlen);
5211 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
5212 }
5213
5214 /* Defensive coding, double-check the psize fits in a struct
5215 * prefix */
5216 if (psize > (ssize_t)sizeof(p.u)) {
5217 flog_err(
5218 EC_BGP_UPDATE_RCV,
5219 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
5220 peer->host, p.prefixlen, sizeof(p.u));
5221 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
5222 }
5223
5224 /* Fetch prefix from NLRI packet. */
5225 memcpy(p.u.val, pnt, psize);
5226
5227 /* Check address. */
5228 if (afi == AFI_IP && safi == SAFI_UNICAST) {
5229 if (IN_CLASSD(ntohl(p.u.prefix4.s_addr))) {
5230 /* From RFC4271 Section 6.3:
5231 *
5232 * If a prefix in the NLRI field is semantically
5233 * incorrect
5234 * (e.g., an unexpected multicast IP address),
5235 * an error SHOULD
5236 * be logged locally, and the prefix SHOULD be
5237 * ignored.
5238 */
5239 flog_err(
5240 EC_BGP_UPDATE_RCV,
5241 "%s: IPv4 unicast NLRI is multicast address %pI4, ignoring",
5242 peer->host, &p.u.prefix4);
5243 continue;
5244 }
5245 }
5246
5247 /* Check address. */
5248 if (afi == AFI_IP6 && safi == SAFI_UNICAST) {
5249 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
5250 char buf[BUFSIZ];
5251
5252 flog_err(
5253 EC_BGP_UPDATE_RCV,
5254 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
5255 peer->host,
5256 inet_ntop(AF_INET6, &p.u.prefix6, buf,
5257 BUFSIZ));
5258
5259 continue;
5260 }
5261 if (IN6_IS_ADDR_MULTICAST(&p.u.prefix6)) {
5262 char buf[BUFSIZ];
5263
5264 flog_err(
5265 EC_BGP_UPDATE_RCV,
5266 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
5267 peer->host,
5268 inet_ntop(AF_INET6, &p.u.prefix6, buf,
5269 BUFSIZ));
5270
5271 continue;
5272 }
5273 }
5274
5275 /* Normal process. */
5276 if (attr)
5277 ret = bgp_update(peer, &p, addpath_id, attr, afi, safi,
5278 ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
5279 NULL, NULL, 0, 0, NULL);
5280 else
5281 ret = bgp_withdraw(peer, &p, addpath_id, attr, afi,
5282 safi, ZEBRA_ROUTE_BGP,
5283 BGP_ROUTE_NORMAL, NULL, NULL, 0,
5284 NULL);
5285
5286 /* Do not send BGP notification twice when maximum-prefix count
5287 * overflow. */
5288 if (CHECK_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
5289 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW;
5290
5291 /* Address family configuration mismatch. */
5292 if (ret < 0)
5293 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY;
5294 }
5295
5296 /* Packet length consistency check. */
5297 if (pnt != lim) {
5298 flog_err(
5299 EC_BGP_UPDATE_RCV,
5300 "%s [Error] Update packet error (prefix length mismatch with total length)",
5301 peer->host);
5302 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
5303 }
5304
5305 return BGP_NLRI_PARSE_OK;
5306 }
5307
5308 static struct bgp_static *bgp_static_new(void)
5309 {
5310 return XCALLOC(MTYPE_BGP_STATIC, sizeof(struct bgp_static));
5311 }
5312
5313 static void bgp_static_free(struct bgp_static *bgp_static)
5314 {
5315 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
5316 route_map_counter_decrement(bgp_static->rmap.map);
5317
5318 XFREE(MTYPE_ATTR, bgp_static->eth_s_id);
5319 XFREE(MTYPE_BGP_STATIC, bgp_static);
5320 }
5321
5322 void bgp_static_update(struct bgp *bgp, const struct prefix *p,
5323 struct bgp_static *bgp_static, afi_t afi, safi_t safi)
5324 {
5325 struct bgp_dest *dest;
5326 struct bgp_path_info *pi;
5327 struct bgp_path_info *new;
5328 struct bgp_path_info rmap_path;
5329 struct attr attr;
5330 struct attr *attr_new;
5331 route_map_result_t ret;
5332 #ifdef ENABLE_BGP_VNC
5333 int vnc_implicit_withdraw = 0;
5334 #endif
5335
5336 assert(bgp_static);
5337
5338 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
5339
5340 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
5341
5342 attr.nexthop = bgp_static->igpnexthop;
5343 attr.med = bgp_static->igpmetric;
5344 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
5345
5346 if (bgp_static->atomic)
5347 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
5348
5349 /* Store label index, if required. */
5350 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX) {
5351 attr.label_index = bgp_static->label_index;
5352 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
5353 }
5354
5355 /* Apply route-map. */
5356 if (bgp_static->rmap.name) {
5357 struct attr attr_tmp = attr;
5358
5359 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
5360 rmap_path.peer = bgp->peer_self;
5361 rmap_path.attr = &attr_tmp;
5362
5363 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
5364
5365 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
5366
5367 bgp->peer_self->rmap_type = 0;
5368
5369 if (ret == RMAP_DENYMATCH) {
5370 /* Free uninterned attribute. */
5371 bgp_attr_flush(&attr_tmp);
5372
5373 /* Unintern original. */
5374 aspath_unintern(&attr.aspath);
5375 bgp_static_withdraw(bgp, p, afi, safi);
5376 return;
5377 }
5378
5379 if (bgp_in_graceful_shutdown(bgp))
5380 bgp_attr_add_gshut_community(&attr_tmp);
5381
5382 attr_new = bgp_attr_intern(&attr_tmp);
5383 } else {
5384
5385 if (bgp_in_graceful_shutdown(bgp))
5386 bgp_attr_add_gshut_community(&attr);
5387
5388 attr_new = bgp_attr_intern(&attr);
5389 }
5390
5391 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
5392 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5393 && pi->sub_type == BGP_ROUTE_STATIC)
5394 break;
5395
5396 if (pi) {
5397 if (attrhash_cmp(pi->attr, attr_new)
5398 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
5399 && !CHECK_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS)) {
5400 bgp_dest_unlock_node(dest);
5401 bgp_attr_unintern(&attr_new);
5402 aspath_unintern(&attr.aspath);
5403 return;
5404 } else {
5405 /* The attribute is changed. */
5406 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
5407
5408 /* Rewrite BGP route information. */
5409 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
5410 bgp_path_info_restore(dest, pi);
5411 else
5412 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
5413 #ifdef ENABLE_BGP_VNC
5414 if ((afi == AFI_IP || afi == AFI_IP6)
5415 && (safi == SAFI_UNICAST)) {
5416 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
5417 /*
5418 * Implicit withdraw case.
5419 * We have to do this before pi is
5420 * changed
5421 */
5422 ++vnc_implicit_withdraw;
5423 vnc_import_bgp_del_route(bgp, p, pi);
5424 vnc_import_bgp_exterior_del_route(
5425 bgp, p, pi);
5426 }
5427 }
5428 #endif
5429 bgp_attr_unintern(&pi->attr);
5430 pi->attr = attr_new;
5431 pi->uptime = bgp_clock();
5432 #ifdef ENABLE_BGP_VNC
5433 if ((afi == AFI_IP || afi == AFI_IP6)
5434 && (safi == SAFI_UNICAST)) {
5435 if (vnc_implicit_withdraw) {
5436 vnc_import_bgp_add_route(bgp, p, pi);
5437 vnc_import_bgp_exterior_add_route(
5438 bgp, p, pi);
5439 }
5440 }
5441 #endif
5442
5443 /* Nexthop reachability check. */
5444 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
5445 && (safi == SAFI_UNICAST
5446 || safi == SAFI_LABELED_UNICAST)) {
5447
5448 struct bgp *bgp_nexthop = bgp;
5449
5450 if (pi->extra && pi->extra->bgp_orig)
5451 bgp_nexthop = pi->extra->bgp_orig;
5452
5453 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop,
5454 afi, safi, pi, NULL,
5455 0))
5456 bgp_path_info_set_flag(dest, pi,
5457 BGP_PATH_VALID);
5458 else {
5459 if (BGP_DEBUG(nht, NHT)) {
5460 char buf1[INET6_ADDRSTRLEN];
5461 inet_ntop(p->family,
5462 &p->u.prefix, buf1,
5463 INET6_ADDRSTRLEN);
5464 zlog_debug(
5465 "%s(%s): Route not in table, not advertising",
5466 __func__, buf1);
5467 }
5468 bgp_path_info_unset_flag(
5469 dest, pi, BGP_PATH_VALID);
5470 }
5471 } else {
5472 /* Delete the NHT structure if any, if we're
5473 * toggling between
5474 * enabling/disabling import check. We
5475 * deregister the route
5476 * from NHT to avoid overloading NHT and the
5477 * process interaction
5478 */
5479 bgp_unlink_nexthop(pi);
5480 bgp_path_info_set_flag(dest, pi,
5481 BGP_PATH_VALID);
5482 }
5483 /* Process change. */
5484 bgp_aggregate_increment(bgp, p, pi, afi, safi);
5485 bgp_process(bgp, dest, afi, safi);
5486
5487 if (SAFI_UNICAST == safi
5488 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5489 || bgp->inst_type
5490 == BGP_INSTANCE_TYPE_DEFAULT)) {
5491 vpn_leak_from_vrf_update(bgp_get_default(), bgp,
5492 pi);
5493 }
5494
5495 bgp_dest_unlock_node(dest);
5496 aspath_unintern(&attr.aspath);
5497 return;
5498 }
5499 }
5500
5501 /* Make new BGP info. */
5502 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
5503 attr_new, dest);
5504 /* Nexthop reachability check. */
5505 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
5506 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
5507 if (bgp_find_or_add_nexthop(bgp, bgp, afi, safi, new, NULL, 0))
5508 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
5509 else {
5510 if (BGP_DEBUG(nht, NHT)) {
5511 char buf1[INET6_ADDRSTRLEN];
5512 inet_ntop(p->family, &p->u.prefix, buf1,
5513 INET6_ADDRSTRLEN);
5514 zlog_debug(
5515 "%s(%s): Route not in table, not advertising",
5516 __func__, buf1);
5517 }
5518 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
5519 }
5520 } else {
5521 /* Delete the NHT structure if any, if we're toggling between
5522 * enabling/disabling import check. We deregister the route
5523 * from NHT to avoid overloading NHT and the process interaction
5524 */
5525 bgp_unlink_nexthop(new);
5526
5527 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
5528 }
5529
5530 /* Aggregate address increment. */
5531 bgp_aggregate_increment(bgp, p, new, afi, safi);
5532
5533 /* Register new BGP information. */
5534 bgp_path_info_add(dest, new);
5535
5536 /* route_node_get lock */
5537 bgp_dest_unlock_node(dest);
5538
5539 /* Process change. */
5540 bgp_process(bgp, dest, afi, safi);
5541
5542 if (SAFI_UNICAST == safi
5543 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5544 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
5545 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
5546 }
5547
5548 /* Unintern original. */
5549 aspath_unintern(&attr.aspath);
5550 }
5551
5552 void bgp_static_withdraw(struct bgp *bgp, const struct prefix *p, afi_t afi,
5553 safi_t safi)
5554 {
5555 struct bgp_dest *dest;
5556 struct bgp_path_info *pi;
5557
5558 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
5559
5560 /* Check selected route and self inserted route. */
5561 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
5562 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5563 && pi->sub_type == BGP_ROUTE_STATIC)
5564 break;
5565
5566 /* Withdraw static BGP route from routing table. */
5567 if (pi) {
5568 if (SAFI_UNICAST == safi
5569 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5570 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
5571 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
5572 }
5573 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
5574 bgp_unlink_nexthop(pi);
5575 bgp_path_info_delete(dest, pi);
5576 bgp_process(bgp, dest, afi, safi);
5577 }
5578
5579 /* Unlock bgp_node_lookup. */
5580 bgp_dest_unlock_node(dest);
5581 }
5582
5583 /*
5584 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
5585 */
5586 static void bgp_static_withdraw_safi(struct bgp *bgp, const struct prefix *p,
5587 afi_t afi, safi_t safi,
5588 struct prefix_rd *prd)
5589 {
5590 struct bgp_dest *dest;
5591 struct bgp_path_info *pi;
5592
5593 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
5594
5595 /* Check selected route and self inserted route. */
5596 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
5597 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5598 && pi->sub_type == BGP_ROUTE_STATIC)
5599 break;
5600
5601 /* Withdraw static BGP route from routing table. */
5602 if (pi) {
5603 #ifdef ENABLE_BGP_VNC
5604 rfapiProcessWithdraw(
5605 pi->peer, NULL, p, prd, pi->attr, afi, safi, pi->type,
5606 1); /* Kill, since it is an administrative change */
5607 #endif
5608 if (SAFI_MPLS_VPN == safi
5609 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
5610 vpn_leak_to_vrf_withdraw(bgp, pi);
5611 }
5612 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
5613 bgp_path_info_delete(dest, pi);
5614 bgp_process(bgp, dest, afi, safi);
5615 }
5616
5617 /* Unlock bgp_node_lookup. */
5618 bgp_dest_unlock_node(dest);
5619 }
5620
5621 static void bgp_static_update_safi(struct bgp *bgp, const struct prefix *p,
5622 struct bgp_static *bgp_static, afi_t afi,
5623 safi_t safi)
5624 {
5625 struct bgp_dest *dest;
5626 struct bgp_path_info *new;
5627 struct attr *attr_new;
5628 struct attr attr = {0};
5629 struct bgp_path_info *pi;
5630 #ifdef ENABLE_BGP_VNC
5631 mpls_label_t label = 0;
5632 #endif
5633 uint32_t num_labels = 0;
5634 union gw_addr add;
5635
5636 assert(bgp_static);
5637
5638 if (bgp_static->label != MPLS_INVALID_LABEL)
5639 num_labels = 1;
5640 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p,
5641 &bgp_static->prd);
5642
5643 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
5644
5645 attr.nexthop = bgp_static->igpnexthop;
5646 attr.med = bgp_static->igpmetric;
5647 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
5648
5649 if ((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN)
5650 || (safi == SAFI_ENCAP)) {
5651 if (afi == AFI_IP) {
5652 attr.mp_nexthop_global_in = bgp_static->igpnexthop;
5653 attr.mp_nexthop_len = IPV4_MAX_BYTELEN;
5654 }
5655 }
5656 if (afi == AFI_L2VPN) {
5657 if (bgp_static->gatewayIp.family == AF_INET)
5658 add.ipv4.s_addr =
5659 bgp_static->gatewayIp.u.prefix4.s_addr;
5660 else if (bgp_static->gatewayIp.family == AF_INET6)
5661 memcpy(&(add.ipv6), &(bgp_static->gatewayIp.u.prefix6),
5662 sizeof(struct in6_addr));
5663 memcpy(&attr.esi, bgp_static->eth_s_id, sizeof(esi_t));
5664 if (bgp_static->encap_tunneltype == BGP_ENCAP_TYPE_VXLAN) {
5665 struct bgp_encap_type_vxlan bet;
5666 memset(&bet, 0, sizeof(struct bgp_encap_type_vxlan));
5667 bet.vnid = p->u.prefix_evpn.prefix_addr.eth_tag;
5668 bgp_encap_type_vxlan_to_tlv(&bet, &attr);
5669 }
5670 if (bgp_static->router_mac) {
5671 bgp_add_routermac_ecom(&attr, bgp_static->router_mac);
5672 }
5673 }
5674 /* Apply route-map. */
5675 if (bgp_static->rmap.name) {
5676 struct attr attr_tmp = attr;
5677 struct bgp_path_info rmap_path;
5678 route_map_result_t ret;
5679
5680 rmap_path.peer = bgp->peer_self;
5681 rmap_path.attr = &attr_tmp;
5682
5683 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
5684
5685 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
5686
5687 bgp->peer_self->rmap_type = 0;
5688
5689 if (ret == RMAP_DENYMATCH) {
5690 /* Free uninterned attribute. */
5691 bgp_attr_flush(&attr_tmp);
5692
5693 /* Unintern original. */
5694 aspath_unintern(&attr.aspath);
5695 bgp_static_withdraw_safi(bgp, p, afi, safi,
5696 &bgp_static->prd);
5697 return;
5698 }
5699
5700 attr_new = bgp_attr_intern(&attr_tmp);
5701 } else {
5702 attr_new = bgp_attr_intern(&attr);
5703 }
5704
5705 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
5706 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5707 && pi->sub_type == BGP_ROUTE_STATIC)
5708 break;
5709
5710 if (pi) {
5711 memset(&add, 0, sizeof(union gw_addr));
5712 if (attrhash_cmp(pi->attr, attr_new)
5713 && overlay_index_equal(afi, pi, &add)
5714 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
5715 bgp_dest_unlock_node(dest);
5716 bgp_attr_unintern(&attr_new);
5717 aspath_unintern(&attr.aspath);
5718 return;
5719 } else {
5720 /* The attribute is changed. */
5721 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
5722
5723 /* Rewrite BGP route information. */
5724 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
5725 bgp_path_info_restore(dest, pi);
5726 else
5727 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
5728 bgp_attr_unintern(&pi->attr);
5729 pi->attr = attr_new;
5730 pi->uptime = bgp_clock();
5731 #ifdef ENABLE_BGP_VNC
5732 if (pi->extra)
5733 label = decode_label(&pi->extra->label[0]);
5734 #endif
5735
5736 /* Process change. */
5737 bgp_aggregate_increment(bgp, p, pi, afi, safi);
5738 bgp_process(bgp, dest, afi, safi);
5739
5740 if (SAFI_MPLS_VPN == safi
5741 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
5742 vpn_leak_to_vrf_update(bgp, pi);
5743 }
5744 #ifdef ENABLE_BGP_VNC
5745 rfapiProcessUpdate(pi->peer, NULL, p, &bgp_static->prd,
5746 pi->attr, afi, safi, pi->type,
5747 pi->sub_type, &label);
5748 #endif
5749 bgp_dest_unlock_node(dest);
5750 aspath_unintern(&attr.aspath);
5751 return;
5752 }
5753 }
5754
5755
5756 /* Make new BGP info. */
5757 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
5758 attr_new, dest);
5759 SET_FLAG(new->flags, BGP_PATH_VALID);
5760 new->extra = bgp_path_info_extra_new();
5761 if (num_labels) {
5762 new->extra->label[0] = bgp_static->label;
5763 new->extra->num_labels = num_labels;
5764 }
5765 #ifdef ENABLE_BGP_VNC
5766 label = decode_label(&bgp_static->label);
5767 #endif
5768
5769 /* Aggregate address increment. */
5770 bgp_aggregate_increment(bgp, p, new, afi, safi);
5771
5772 /* Register new BGP information. */
5773 bgp_path_info_add(dest, new);
5774 /* route_node_get lock */
5775 bgp_dest_unlock_node(dest);
5776
5777 /* Process change. */
5778 bgp_process(bgp, dest, afi, safi);
5779
5780 if (SAFI_MPLS_VPN == safi
5781 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
5782 vpn_leak_to_vrf_update(bgp, new);
5783 }
5784 #ifdef ENABLE_BGP_VNC
5785 rfapiProcessUpdate(new->peer, NULL, p, &bgp_static->prd, new->attr, afi,
5786 safi, new->type, new->sub_type, &label);
5787 #endif
5788
5789 /* Unintern original. */
5790 aspath_unintern(&attr.aspath);
5791 }
5792
5793 /* Configure static BGP network. When user don't run zebra, static
5794 route should be installed as valid. */
5795 int bgp_static_set(struct bgp *bgp, const char *negate, struct prefix *pfx,
5796 afi_t afi, safi_t safi, const char *rmap, int backdoor,
5797 uint32_t label_index, char *errmsg, size_t errmsg_len)
5798 {
5799 struct prefix p;
5800 struct bgp_static *bgp_static;
5801 struct bgp_dest *dest;
5802 uint8_t need_update = 0;
5803
5804 prefix_copy(&p, pfx);
5805 apply_mask(&p);
5806
5807 if (negate) {
5808
5809 /* Set BGP static route configuration. */
5810 dest = bgp_node_lookup(bgp->route[afi][safi], &p);
5811
5812 if (!dest) {
5813 snprintf(errmsg, errmsg_len,
5814 "Can't find static route specified\n");
5815 return -1;
5816 }
5817
5818 bgp_static = bgp_dest_get_bgp_static_info(dest);
5819
5820 if ((label_index != BGP_INVALID_LABEL_INDEX)
5821 && (label_index != bgp_static->label_index)) {
5822 snprintf(errmsg, errmsg_len,
5823 "label-index doesn't match static route\n");
5824 return -1;
5825 }
5826
5827 if ((rmap && bgp_static->rmap.name)
5828 && strcmp(rmap, bgp_static->rmap.name)) {
5829 snprintf(errmsg, errmsg_len,
5830 "route-map name doesn't match static route\n");
5831 return -1;
5832 }
5833
5834 /* Update BGP RIB. */
5835 if (!bgp_static->backdoor)
5836 bgp_static_withdraw(bgp, &p, afi, safi);
5837
5838 /* Clear configuration. */
5839 bgp_static_free(bgp_static);
5840 bgp_dest_set_bgp_static_info(dest, NULL);
5841 bgp_dest_unlock_node(dest);
5842 bgp_dest_unlock_node(dest);
5843 } else {
5844
5845 /* Set BGP static route configuration. */
5846 dest = bgp_node_get(bgp->route[afi][safi], &p);
5847 bgp_static = bgp_dest_get_bgp_static_info(dest);
5848 if (bgp_static) {
5849 /* Configuration change. */
5850 /* Label index cannot be changed. */
5851 if (bgp_static->label_index != label_index) {
5852 snprintf(errmsg, errmsg_len,
5853 "cannot change label-index\n");
5854 return -1;
5855 }
5856
5857 /* Check previous routes are installed into BGP. */
5858 if (bgp_static->valid
5859 && bgp_static->backdoor != backdoor)
5860 need_update = 1;
5861
5862 bgp_static->backdoor = backdoor;
5863
5864 if (rmap) {
5865 XFREE(MTYPE_ROUTE_MAP_NAME,
5866 bgp_static->rmap.name);
5867 route_map_counter_decrement(
5868 bgp_static->rmap.map);
5869 bgp_static->rmap.name =
5870 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
5871 bgp_static->rmap.map =
5872 route_map_lookup_by_name(rmap);
5873 route_map_counter_increment(
5874 bgp_static->rmap.map);
5875 } else {
5876 XFREE(MTYPE_ROUTE_MAP_NAME,
5877 bgp_static->rmap.name);
5878 route_map_counter_decrement(
5879 bgp_static->rmap.map);
5880 bgp_static->rmap.map = NULL;
5881 bgp_static->valid = 0;
5882 }
5883 bgp_dest_unlock_node(dest);
5884 } else {
5885 /* New configuration. */
5886 bgp_static = bgp_static_new();
5887 bgp_static->backdoor = backdoor;
5888 bgp_static->valid = 0;
5889 bgp_static->igpmetric = 0;
5890 bgp_static->igpnexthop.s_addr = INADDR_ANY;
5891 bgp_static->label_index = label_index;
5892
5893 if (rmap) {
5894 XFREE(MTYPE_ROUTE_MAP_NAME,
5895 bgp_static->rmap.name);
5896 route_map_counter_decrement(
5897 bgp_static->rmap.map);
5898 bgp_static->rmap.name =
5899 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
5900 bgp_static->rmap.map =
5901 route_map_lookup_by_name(rmap);
5902 route_map_counter_increment(
5903 bgp_static->rmap.map);
5904 }
5905 bgp_dest_set_bgp_static_info(dest, bgp_static);
5906 }
5907
5908 bgp_static->valid = 1;
5909 if (need_update)
5910 bgp_static_withdraw(bgp, &p, afi, safi);
5911
5912 if (!bgp_static->backdoor)
5913 bgp_static_update(bgp, &p, bgp_static, afi, safi);
5914 }
5915
5916 return 0;
5917 }
5918
5919 void bgp_static_add(struct bgp *bgp)
5920 {
5921 afi_t afi;
5922 safi_t safi;
5923 struct bgp_dest *dest;
5924 struct bgp_dest *rm;
5925 struct bgp_table *table;
5926 struct bgp_static *bgp_static;
5927
5928 FOREACH_AFI_SAFI (afi, safi)
5929 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
5930 dest = bgp_route_next(dest)) {
5931 if (!bgp_dest_has_bgp_path_info_data(dest))
5932 continue;
5933
5934 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
5935 || (safi == SAFI_EVPN)) {
5936 table = bgp_dest_get_bgp_table_info(dest);
5937
5938 for (rm = bgp_table_top(table); rm;
5939 rm = bgp_route_next(rm)) {
5940 bgp_static =
5941 bgp_dest_get_bgp_static_info(
5942 rm);
5943 bgp_static_update_safi(
5944 bgp, bgp_dest_get_prefix(rm),
5945 bgp_static, afi, safi);
5946 }
5947 } else {
5948 bgp_static_update(
5949 bgp, bgp_dest_get_prefix(dest),
5950 bgp_dest_get_bgp_static_info(dest), afi,
5951 safi);
5952 }
5953 }
5954 }
5955
5956 /* Called from bgp_delete(). Delete all static routes from the BGP
5957 instance. */
5958 void bgp_static_delete(struct bgp *bgp)
5959 {
5960 afi_t afi;
5961 safi_t safi;
5962 struct bgp_dest *dest;
5963 struct bgp_dest *rm;
5964 struct bgp_table *table;
5965 struct bgp_static *bgp_static;
5966
5967 FOREACH_AFI_SAFI (afi, safi)
5968 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
5969 dest = bgp_route_next(dest)) {
5970 if (!bgp_dest_has_bgp_path_info_data(dest))
5971 continue;
5972
5973 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
5974 || (safi == SAFI_EVPN)) {
5975 table = bgp_dest_get_bgp_table_info(dest);
5976
5977 for (rm = bgp_table_top(table); rm;
5978 rm = bgp_route_next(rm)) {
5979 bgp_static =
5980 bgp_dest_get_bgp_static_info(
5981 rm);
5982 if (!bgp_static)
5983 continue;
5984
5985 bgp_static_withdraw_safi(
5986 bgp, bgp_dest_get_prefix(rm),
5987 AFI_IP, safi,
5988 (struct prefix_rd *)
5989 bgp_dest_get_prefix(
5990 dest));
5991 bgp_static_free(bgp_static);
5992 bgp_dest_set_bgp_static_info(rm,
5993 NULL);
5994 bgp_dest_unlock_node(rm);
5995 }
5996 } else {
5997 bgp_static = bgp_dest_get_bgp_static_info(dest);
5998 bgp_static_withdraw(bgp,
5999 bgp_dest_get_prefix(dest),
6000 afi, safi);
6001 bgp_static_free(bgp_static);
6002 bgp_dest_set_bgp_static_info(dest, NULL);
6003 bgp_dest_unlock_node(dest);
6004 }
6005 }
6006 }
6007
6008 void bgp_static_redo_import_check(struct bgp *bgp)
6009 {
6010 afi_t afi;
6011 safi_t safi;
6012 struct bgp_dest *dest;
6013 struct bgp_dest *rm;
6014 struct bgp_table *table;
6015 struct bgp_static *bgp_static;
6016
6017 /* Use this flag to force reprocessing of the route */
6018 SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
6019 FOREACH_AFI_SAFI (afi, safi) {
6020 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6021 dest = bgp_route_next(dest)) {
6022 if (!bgp_dest_has_bgp_path_info_data(dest))
6023 continue;
6024
6025 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6026 || (safi == SAFI_EVPN)) {
6027 table = bgp_dest_get_bgp_table_info(dest);
6028
6029 for (rm = bgp_table_top(table); rm;
6030 rm = bgp_route_next(rm)) {
6031 bgp_static =
6032 bgp_dest_get_bgp_static_info(
6033 rm);
6034 bgp_static_update_safi(
6035 bgp, bgp_dest_get_prefix(rm),
6036 bgp_static, afi, safi);
6037 }
6038 } else {
6039 bgp_static = bgp_dest_get_bgp_static_info(dest);
6040 bgp_static_update(bgp,
6041 bgp_dest_get_prefix(dest),
6042 bgp_static, afi, safi);
6043 }
6044 }
6045 }
6046 UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
6047 }
6048
6049 static void bgp_purge_af_static_redist_routes(struct bgp *bgp, afi_t afi,
6050 safi_t safi)
6051 {
6052 struct bgp_table *table;
6053 struct bgp_dest *dest;
6054 struct bgp_path_info *pi;
6055
6056 /* Do not install the aggregate route if BGP is in the
6057 * process of termination.
6058 */
6059 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
6060 || (bgp->peer_self == NULL))
6061 return;
6062
6063 table = bgp->rib[afi][safi];
6064 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6065 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
6066 if (pi->peer == bgp->peer_self
6067 && ((pi->type == ZEBRA_ROUTE_BGP
6068 && pi->sub_type == BGP_ROUTE_STATIC)
6069 || (pi->type != ZEBRA_ROUTE_BGP
6070 && pi->sub_type
6071 == BGP_ROUTE_REDISTRIBUTE))) {
6072 bgp_aggregate_decrement(
6073 bgp, bgp_dest_get_prefix(dest), pi, afi,
6074 safi);
6075 bgp_unlink_nexthop(pi);
6076 bgp_path_info_delete(dest, pi);
6077 bgp_process(bgp, dest, afi, safi);
6078 }
6079 }
6080 }
6081 }
6082
6083 /*
6084 * Purge all networks and redistributed routes from routing table.
6085 * Invoked upon the instance going down.
6086 */
6087 void bgp_purge_static_redist_routes(struct bgp *bgp)
6088 {
6089 afi_t afi;
6090 safi_t safi;
6091
6092 FOREACH_AFI_SAFI (afi, safi)
6093 bgp_purge_af_static_redist_routes(bgp, afi, safi);
6094 }
6095
6096 /*
6097 * gpz 110624
6098 * Currently this is used to set static routes for VPN and ENCAP.
6099 * I think it can probably be factored with bgp_static_set.
6100 */
6101 int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty,
6102 const char *ip_str, const char *rd_str,
6103 const char *label_str, const char *rmap_str,
6104 int evpn_type, const char *esi, const char *gwip,
6105 const char *ethtag, const char *routermac)
6106 {
6107 VTY_DECLVAR_CONTEXT(bgp, bgp);
6108 int ret;
6109 struct prefix p;
6110 struct prefix_rd prd;
6111 struct bgp_dest *pdest;
6112 struct bgp_dest *dest;
6113 struct bgp_table *table;
6114 struct bgp_static *bgp_static;
6115 mpls_label_t label = MPLS_INVALID_LABEL;
6116 struct prefix gw_ip;
6117
6118 /* validate ip prefix */
6119 ret = str2prefix(ip_str, &p);
6120 if (!ret) {
6121 vty_out(vty, "%% Malformed prefix\n");
6122 return CMD_WARNING_CONFIG_FAILED;
6123 }
6124 apply_mask(&p);
6125 if ((afi == AFI_L2VPN)
6126 && (bgp_build_evpn_prefix(evpn_type,
6127 ethtag != NULL ? atol(ethtag) : 0, &p))) {
6128 vty_out(vty, "%% L2VPN prefix could not be forged\n");
6129 return CMD_WARNING_CONFIG_FAILED;
6130 }
6131
6132 ret = str2prefix_rd(rd_str, &prd);
6133 if (!ret) {
6134 vty_out(vty, "%% Malformed rd\n");
6135 return CMD_WARNING_CONFIG_FAILED;
6136 }
6137
6138 if (label_str) {
6139 unsigned long label_val;
6140 label_val = strtoul(label_str, NULL, 10);
6141 encode_label(label_val, &label);
6142 }
6143
6144 if (safi == SAFI_EVPN) {
6145 if (esi && str2esi(esi, NULL) == 0) {
6146 vty_out(vty, "%% Malformed ESI\n");
6147 return CMD_WARNING_CONFIG_FAILED;
6148 }
6149 if (routermac && prefix_str2mac(routermac, NULL) == 0) {
6150 vty_out(vty, "%% Malformed Router MAC\n");
6151 return CMD_WARNING_CONFIG_FAILED;
6152 }
6153 if (gwip) {
6154 memset(&gw_ip, 0, sizeof(struct prefix));
6155 ret = str2prefix(gwip, &gw_ip);
6156 if (!ret) {
6157 vty_out(vty, "%% Malformed GatewayIp\n");
6158 return CMD_WARNING_CONFIG_FAILED;
6159 }
6160 if ((gw_ip.family == AF_INET
6161 && is_evpn_prefix_ipaddr_v6(
6162 (struct prefix_evpn *)&p))
6163 || (gw_ip.family == AF_INET6
6164 && is_evpn_prefix_ipaddr_v4(
6165 (struct prefix_evpn *)&p))) {
6166 vty_out(vty,
6167 "%% GatewayIp family differs with IP prefix\n");
6168 return CMD_WARNING_CONFIG_FAILED;
6169 }
6170 }
6171 }
6172 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
6173 if (!bgp_dest_has_bgp_path_info_data(pdest))
6174 bgp_dest_set_bgp_table_info(pdest,
6175 bgp_table_init(bgp, afi, safi));
6176 table = bgp_dest_get_bgp_table_info(pdest);
6177
6178 dest = bgp_node_get(table, &p);
6179
6180 if (bgp_dest_has_bgp_path_info_data(dest)) {
6181 vty_out(vty, "%% Same network configuration exists\n");
6182 bgp_dest_unlock_node(dest);
6183 } else {
6184 /* New configuration. */
6185 bgp_static = bgp_static_new();
6186 bgp_static->backdoor = 0;
6187 bgp_static->valid = 0;
6188 bgp_static->igpmetric = 0;
6189 bgp_static->igpnexthop.s_addr = INADDR_ANY;
6190 bgp_static->label = label;
6191 bgp_static->prd = prd;
6192
6193 if (rmap_str) {
6194 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
6195 route_map_counter_decrement(bgp_static->rmap.map);
6196 bgp_static->rmap.name =
6197 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_str);
6198 bgp_static->rmap.map =
6199 route_map_lookup_by_name(rmap_str);
6200 route_map_counter_increment(bgp_static->rmap.map);
6201 }
6202
6203 if (safi == SAFI_EVPN) {
6204 if (esi) {
6205 bgp_static->eth_s_id =
6206 XCALLOC(MTYPE_ATTR,
6207 sizeof(esi_t));
6208 str2esi(esi, bgp_static->eth_s_id);
6209 }
6210 if (routermac) {
6211 bgp_static->router_mac =
6212 XCALLOC(MTYPE_ATTR, ETH_ALEN + 1);
6213 (void)prefix_str2mac(routermac,
6214 bgp_static->router_mac);
6215 }
6216 if (gwip)
6217 prefix_copy(&bgp_static->gatewayIp, &gw_ip);
6218 }
6219 bgp_dest_set_bgp_static_info(dest, bgp_static);
6220
6221 bgp_static->valid = 1;
6222 bgp_static_update_safi(bgp, &p, bgp_static, afi, safi);
6223 }
6224
6225 return CMD_SUCCESS;
6226 }
6227
6228 /* Configure static BGP network. */
6229 int bgp_static_unset_safi(afi_t afi, safi_t safi, struct vty *vty,
6230 const char *ip_str, const char *rd_str,
6231 const char *label_str, int evpn_type, const char *esi,
6232 const char *gwip, const char *ethtag)
6233 {
6234 VTY_DECLVAR_CONTEXT(bgp, bgp);
6235 int ret;
6236 struct prefix p;
6237 struct prefix_rd prd;
6238 struct bgp_dest *pdest;
6239 struct bgp_dest *dest;
6240 struct bgp_table *table;
6241 struct bgp_static *bgp_static;
6242 mpls_label_t label = MPLS_INVALID_LABEL;
6243
6244 /* Convert IP prefix string to struct prefix. */
6245 ret = str2prefix(ip_str, &p);
6246 if (!ret) {
6247 vty_out(vty, "%% Malformed prefix\n");
6248 return CMD_WARNING_CONFIG_FAILED;
6249 }
6250 apply_mask(&p);
6251 if ((afi == AFI_L2VPN)
6252 && (bgp_build_evpn_prefix(evpn_type,
6253 ethtag != NULL ? atol(ethtag) : 0, &p))) {
6254 vty_out(vty, "%% L2VPN prefix could not be forged\n");
6255 return CMD_WARNING_CONFIG_FAILED;
6256 }
6257 ret = str2prefix_rd(rd_str, &prd);
6258 if (!ret) {
6259 vty_out(vty, "%% Malformed rd\n");
6260 return CMD_WARNING_CONFIG_FAILED;
6261 }
6262
6263 if (label_str) {
6264 unsigned long label_val;
6265 label_val = strtoul(label_str, NULL, 10);
6266 encode_label(label_val, &label);
6267 }
6268
6269 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
6270 if (!bgp_dest_has_bgp_path_info_data(pdest))
6271 bgp_dest_set_bgp_table_info(pdest,
6272 bgp_table_init(bgp, afi, safi));
6273 else
6274 bgp_dest_unlock_node(pdest);
6275 table = bgp_dest_get_bgp_table_info(pdest);
6276
6277 dest = bgp_node_lookup(table, &p);
6278
6279 if (dest) {
6280 bgp_static_withdraw_safi(bgp, &p, afi, safi, &prd);
6281
6282 bgp_static = bgp_dest_get_bgp_static_info(dest);
6283 bgp_static_free(bgp_static);
6284 bgp_dest_set_bgp_static_info(dest, NULL);
6285 bgp_dest_unlock_node(dest);
6286 bgp_dest_unlock_node(dest);
6287 } else
6288 vty_out(vty, "%% Can't find the route\n");
6289
6290 return CMD_SUCCESS;
6291 }
6292
6293 static int bgp_table_map_set(struct vty *vty, afi_t afi, safi_t safi,
6294 const char *rmap_name)
6295 {
6296 VTY_DECLVAR_CONTEXT(bgp, bgp);
6297 struct bgp_rmap *rmap;
6298
6299 rmap = &bgp->table_map[afi][safi];
6300 if (rmap_name) {
6301 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
6302 route_map_counter_decrement(rmap->map);
6303 rmap->name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name);
6304 rmap->map = route_map_lookup_by_name(rmap_name);
6305 route_map_counter_increment(rmap->map);
6306 } else {
6307 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
6308 route_map_counter_decrement(rmap->map);
6309 rmap->map = NULL;
6310 }
6311
6312 if (bgp_fibupd_safi(safi))
6313 bgp_zebra_announce_table(bgp, afi, safi);
6314
6315 return CMD_SUCCESS;
6316 }
6317
6318 static int bgp_table_map_unset(struct vty *vty, afi_t afi, safi_t safi,
6319 const char *rmap_name)
6320 {
6321 VTY_DECLVAR_CONTEXT(bgp, bgp);
6322 struct bgp_rmap *rmap;
6323
6324 rmap = &bgp->table_map[afi][safi];
6325 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
6326 route_map_counter_decrement(rmap->map);
6327 rmap->map = NULL;
6328
6329 if (bgp_fibupd_safi(safi))
6330 bgp_zebra_announce_table(bgp, afi, safi);
6331
6332 return CMD_SUCCESS;
6333 }
6334
6335 void bgp_config_write_table_map(struct vty *vty, struct bgp *bgp, afi_t afi,
6336 safi_t safi)
6337 {
6338 if (bgp->table_map[afi][safi].name) {
6339 vty_out(vty, " table-map %s\n",
6340 bgp->table_map[afi][safi].name);
6341 }
6342 }
6343
6344 DEFUN (bgp_table_map,
6345 bgp_table_map_cmd,
6346 "table-map WORD",
6347 "BGP table to RIB route download filter\n"
6348 "Name of the route map\n")
6349 {
6350 int idx_word = 1;
6351 return bgp_table_map_set(vty, bgp_node_afi(vty), bgp_node_safi(vty),
6352 argv[idx_word]->arg);
6353 }
6354 DEFUN (no_bgp_table_map,
6355 no_bgp_table_map_cmd,
6356 "no table-map WORD",
6357 NO_STR
6358 "BGP table to RIB route download filter\n"
6359 "Name of the route map\n")
6360 {
6361 int idx_word = 2;
6362 return bgp_table_map_unset(vty, bgp_node_afi(vty), bgp_node_safi(vty),
6363 argv[idx_word]->arg);
6364 }
6365
6366 DEFPY_YANG (bgp_network, bgp_network_cmd,
6367 "[no] network \
6368 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
6369 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
6370 backdoor$backdoor}]",
6371 NO_STR
6372 "Specify a network to announce via BGP\n"
6373 "IPv4 prefix\n"
6374 "Network number\n"
6375 "Network mask\n"
6376 "Network mask\n"
6377 "Route-map to modify the attributes\n"
6378 "Name of the route map\n"
6379 "Label index to associate with the prefix\n"
6380 "Label index value\n"
6381 "Specify a BGP backdoor route\n")
6382 {
6383 char addr_prefix_str[PREFIX_STRLEN];
6384 char base_xpath[XPATH_MAXLEN];
6385 afi_t afi;
6386 safi_t safi;
6387
6388 if (address_str) {
6389 int ret;
6390
6391 ret = netmask_str2prefix_str(address_str, netmask_str,
6392 addr_prefix_str);
6393 if (!ret) {
6394 vty_out(vty, "%% Inconsistent address and mask\n");
6395 return CMD_WARNING_CONFIG_FAILED;
6396 }
6397 }
6398
6399 afi = bgp_node_afi(vty);
6400 safi = bgp_node_safi(vty);
6401
6402 if (no) {
6403 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
6404 } else {
6405 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
6406
6407 if (map_name)
6408 nb_cli_enqueue_change(vty, "./rmap-policy-export",
6409 NB_OP_CREATE, map_name);
6410 else
6411 nb_cli_enqueue_change(vty, "./rmap-policy-export",
6412 NB_OP_DESTROY, NULL);
6413
6414 if (label_index_str)
6415 nb_cli_enqueue_change(vty, "./label-index",
6416 NB_OP_MODIFY, label_index_str);
6417
6418 nb_cli_enqueue_change(vty, "./backdoor", NB_OP_MODIFY,
6419 backdoor ? "true" : "false");
6420 }
6421
6422 snprintf(
6423 base_xpath, sizeof(base_xpath),
6424 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/network-config[prefix='%s']",
6425 yang_afi_safi_value2identity(afi, safi),
6426 bgp_afi_safi_get_container_str(afi, safi),
6427 address_str ? addr_prefix_str : prefix_str);
6428
6429 return nb_cli_apply_changes(vty, base_xpath);
6430 }
6431
6432 DEFPY_YANG (ipv6_bgp_network,
6433 ipv6_bgp_network_cmd,
6434 "[no] network X:X::X:X/M$prefix \
6435 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
6436 NO_STR
6437 "Specify a network to announce via BGP\n"
6438 "IPv6 prefix\n"
6439 "Route-map to modify the attributes\n"
6440 "Name of the route map\n"
6441 "Label index to associate with the prefix\n"
6442 "Label index value\n")
6443 {
6444 char base_xpath[XPATH_MAXLEN];
6445 afi_t afi;
6446 safi_t safi;
6447
6448 afi = bgp_node_afi(vty);
6449 safi = bgp_node_safi(vty);
6450
6451 if (no) {
6452 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
6453 } else {
6454 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
6455
6456 if (map_name)
6457 nb_cli_enqueue_change(vty, "./rmap-policy-export",
6458 NB_OP_MODIFY, map_name);
6459 else
6460 nb_cli_enqueue_change(vty, "./rmap-policy-export",
6461 NB_OP_DESTROY, NULL);
6462
6463 if (label_index_str)
6464 nb_cli_enqueue_change(vty, "./label-index",
6465 NB_OP_MODIFY, label_index_str);
6466 }
6467
6468 snprintf(
6469 base_xpath, sizeof(base_xpath),
6470 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/network-config[prefix='%s']",
6471 yang_afi_safi_value2identity(afi, safi),
6472 bgp_afi_safi_get_container_str(afi, safi), prefix_str);
6473
6474 return nb_cli_apply_changes(vty, base_xpath);
6475 }
6476
6477 void cli_show_bgp_global_afi_safi_network_config(struct vty *vty,
6478 struct lyd_node *dnode,
6479 bool show_defaults)
6480 {
6481 vty_out(vty, " network %s", yang_dnode_get_string(dnode, "./prefix"));
6482
6483 if (yang_dnode_exists(dnode, "./label-index"))
6484 vty_out(vty, " label-index %s",
6485 yang_dnode_get_string(dnode, "./label-index"));
6486
6487 if (yang_dnode_exists(dnode, "./rmap-policy-export"))
6488 vty_out(vty, " route-map %s",
6489 yang_dnode_get_string(dnode, "./rmap-policy-export"));
6490
6491 if (yang_dnode_get_bool(dnode, "./backdoor"))
6492 vty_out(vty, " backdoor");
6493
6494 vty_out(vty, "\n");
6495 }
6496
6497 static struct bgp_aggregate *bgp_aggregate_new(void)
6498 {
6499 return XCALLOC(MTYPE_BGP_AGGREGATE, sizeof(struct bgp_aggregate));
6500 }
6501
6502 static void bgp_aggregate_free(struct bgp_aggregate *aggregate)
6503 {
6504 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
6505 route_map_counter_decrement(aggregate->suppress_map);
6506 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
6507 route_map_counter_decrement(aggregate->rmap.map);
6508 XFREE(MTYPE_BGP_AGGREGATE, aggregate);
6509 }
6510
6511 /**
6512 * Helper function to avoid repeated code: prepare variables for a
6513 * `route_map_apply` call.
6514 *
6515 * \returns `true` on route map match, otherwise `false`.
6516 */
6517 static bool aggr_suppress_map_test(struct bgp *bgp,
6518 struct bgp_aggregate *aggregate,
6519 struct bgp_path_info *pi)
6520 {
6521 const struct prefix *p = bgp_dest_get_prefix(pi->net);
6522 route_map_result_t rmr = RMAP_DENYMATCH;
6523 struct bgp_path_info rmap_path = {};
6524 struct attr attr = {};
6525
6526 /* No route map entries created, just don't match. */
6527 if (aggregate->suppress_map == NULL)
6528 return false;
6529
6530 /* Call route map matching and return result. */
6531 attr.aspath = aspath_empty();
6532 rmap_path.peer = bgp->peer_self;
6533 rmap_path.attr = &attr;
6534
6535 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_AGGREGATE);
6536 rmr = route_map_apply(aggregate->suppress_map, p, &rmap_path);
6537 bgp->peer_self->rmap_type = 0;
6538
6539 bgp_attr_flush(&attr);
6540
6541 return rmr == RMAP_PERMITMATCH;
6542 }
6543
6544 /** Test whether the aggregation has suppressed this path or not. */
6545 static bool aggr_suppress_exists(struct bgp_aggregate *aggregate,
6546 struct bgp_path_info *pi)
6547 {
6548 if (pi->extra == NULL || pi->extra->aggr_suppressors == NULL)
6549 return false;
6550
6551 return listnode_lookup(pi->extra->aggr_suppressors, aggregate) != NULL;
6552 }
6553
6554 /**
6555 * Suppress this path and keep the reference.
6556 *
6557 * \returns `true` if needs processing otherwise `false`.
6558 */
6559 static bool aggr_suppress_path(struct bgp_aggregate *aggregate,
6560 struct bgp_path_info *pi)
6561 {
6562 struct bgp_path_info_extra *pie;
6563
6564 /* Path is already suppressed by this aggregation. */
6565 if (aggr_suppress_exists(aggregate, pi))
6566 return false;
6567
6568 pie = bgp_path_info_extra_get(pi);
6569
6570 /* This is the first suppression, allocate memory and list it. */
6571 if (pie->aggr_suppressors == NULL)
6572 pie->aggr_suppressors = list_new();
6573
6574 listnode_add(pie->aggr_suppressors, aggregate);
6575
6576 /* Only mark for processing if suppressed. */
6577 if (listcount(pie->aggr_suppressors) == 1) {
6578 if (BGP_DEBUG(update, UPDATE_OUT))
6579 zlog_debug("aggregate-address suppressing: %pFX",
6580 bgp_dest_get_prefix(pi->net));
6581
6582 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
6583 return true;
6584 }
6585
6586 return false;
6587 }
6588
6589 /**
6590 * Unsuppress this path and remove the reference.
6591 *
6592 * \returns `true` if needs processing otherwise `false`.
6593 */
6594 static bool aggr_unsuppress_path(struct bgp_aggregate *aggregate,
6595 struct bgp_path_info *pi)
6596 {
6597 /* Path wasn't suppressed. */
6598 if (!aggr_suppress_exists(aggregate, pi))
6599 return false;
6600
6601 listnode_delete(pi->extra->aggr_suppressors, aggregate);
6602
6603 /* Unsuppress and free extra memory if last item. */
6604 if (listcount(pi->extra->aggr_suppressors) == 0) {
6605 if (BGP_DEBUG(update, UPDATE_OUT))
6606 zlog_debug("aggregate-address unsuppressing: %pFX",
6607 bgp_dest_get_prefix(pi->net));
6608
6609 list_delete(&pi->extra->aggr_suppressors);
6610 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
6611 return true;
6612 }
6613
6614 return false;
6615 }
6616
6617 static bool bgp_aggregate_info_same(struct bgp_path_info *pi, uint8_t origin,
6618 struct aspath *aspath,
6619 struct community *comm,
6620 struct ecommunity *ecomm,
6621 struct lcommunity *lcomm)
6622 {
6623 static struct aspath *ae = NULL;
6624
6625 if (!ae)
6626 ae = aspath_empty();
6627
6628 if (!pi)
6629 return false;
6630
6631 if (origin != pi->attr->origin)
6632 return false;
6633
6634 if (!aspath_cmp(pi->attr->aspath, (aspath) ? aspath : ae))
6635 return false;
6636
6637 if (!community_cmp(pi->attr->community, comm))
6638 return false;
6639
6640 if (!ecommunity_cmp(pi->attr->ecommunity, ecomm))
6641 return false;
6642
6643 if (!lcommunity_cmp(pi->attr->lcommunity, lcomm))
6644 return false;
6645
6646 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID))
6647 return false;
6648
6649 return true;
6650 }
6651
6652 static void bgp_aggregate_install(
6653 struct bgp *bgp, afi_t afi, safi_t safi, const struct prefix *p,
6654 uint8_t origin, struct aspath *aspath, struct community *community,
6655 struct ecommunity *ecommunity, struct lcommunity *lcommunity,
6656 uint8_t atomic_aggregate, struct bgp_aggregate *aggregate)
6657 {
6658 struct bgp_dest *dest;
6659 struct bgp_table *table;
6660 struct bgp_path_info *pi, *orig, *new;
6661 struct attr *attr;
6662
6663 table = bgp->rib[afi][safi];
6664
6665 dest = bgp_node_get(table, p);
6666
6667 for (orig = pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
6668 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6669 && pi->sub_type == BGP_ROUTE_AGGREGATE)
6670 break;
6671
6672 /*
6673 * If we have paths with different MEDs, then don't install
6674 * (or uninstall) the aggregate route.
6675 */
6676 if (aggregate->match_med && aggregate->med_mismatched)
6677 goto uninstall_aggregate_route;
6678
6679 if (aggregate->count > 0) {
6680 /*
6681 * If the aggregate information has not changed
6682 * no need to re-install it again.
6683 */
6684 if (bgp_aggregate_info_same(orig, origin, aspath, community,
6685 ecommunity, lcommunity)) {
6686 bgp_dest_unlock_node(dest);
6687
6688 if (aspath)
6689 aspath_free(aspath);
6690 if (community)
6691 community_free(&community);
6692 if (ecommunity)
6693 ecommunity_free(&ecommunity);
6694 if (lcommunity)
6695 lcommunity_free(&lcommunity);
6696
6697 return;
6698 }
6699
6700 /*
6701 * Mark the old as unusable
6702 */
6703 if (pi)
6704 bgp_path_info_delete(dest, pi);
6705
6706 attr = bgp_attr_aggregate_intern(
6707 bgp, origin, aspath, community, ecommunity, lcommunity,
6708 aggregate, atomic_aggregate, p);
6709
6710 if (!attr) {
6711 bgp_aggregate_delete(bgp, p, afi, safi, aggregate);
6712 if (BGP_DEBUG(update_groups, UPDATE_GROUPS))
6713 zlog_debug("%s: %pFX null attribute", __func__,
6714 p);
6715 return;
6716 }
6717
6718 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0,
6719 bgp->peer_self, attr, dest);
6720
6721 SET_FLAG(new->flags, BGP_PATH_VALID);
6722
6723 bgp_path_info_add(dest, new);
6724 bgp_process(bgp, dest, afi, safi);
6725 } else {
6726 uninstall_aggregate_route:
6727 for (pi = orig; pi; pi = pi->next)
6728 if (pi->peer == bgp->peer_self
6729 && pi->type == ZEBRA_ROUTE_BGP
6730 && pi->sub_type == BGP_ROUTE_AGGREGATE)
6731 break;
6732
6733 /* Withdraw static BGP route from routing table. */
6734 if (pi) {
6735 bgp_path_info_delete(dest, pi);
6736 bgp_process(bgp, dest, afi, safi);
6737 }
6738 }
6739
6740 bgp_dest_unlock_node(dest);
6741 }
6742
6743 /**
6744 * Check if the current path has different MED than other known paths.
6745 *
6746 * \returns `true` if the MED matched the others else `false`.
6747 */
6748 static bool bgp_aggregate_med_match(struct bgp_aggregate *aggregate,
6749 struct bgp *bgp, struct bgp_path_info *pi)
6750 {
6751 uint32_t cur_med = bgp_med_value(pi->attr, bgp);
6752
6753 /* This is the first route being analyzed. */
6754 if (!aggregate->med_initialized) {
6755 aggregate->med_initialized = true;
6756 aggregate->med_mismatched = false;
6757 aggregate->med_matched_value = cur_med;
6758 } else {
6759 /* Check if routes with different MED showed up. */
6760 if (cur_med != aggregate->med_matched_value)
6761 aggregate->med_mismatched = true;
6762 }
6763
6764 return !aggregate->med_mismatched;
6765 }
6766
6767 /**
6768 * Initializes and tests all routes in the aggregate address path for MED
6769 * values.
6770 *
6771 * \returns `true` if all MEDs are the same otherwise `false`.
6772 */
6773 static bool bgp_aggregate_test_all_med(struct bgp_aggregate *aggregate,
6774 struct bgp *bgp, const struct prefix *p,
6775 afi_t afi, safi_t safi)
6776 {
6777 struct bgp_table *table = bgp->rib[afi][safi];
6778 const struct prefix *dest_p;
6779 struct bgp_dest *dest, *top;
6780 struct bgp_path_info *pi;
6781 bool med_matched = true;
6782
6783 aggregate->med_initialized = false;
6784
6785 top = bgp_node_get(table, p);
6786 for (dest = bgp_node_get(table, p); dest;
6787 dest = bgp_route_next_until(dest, top)) {
6788 dest_p = bgp_dest_get_prefix(dest);
6789 if (dest_p->prefixlen <= p->prefixlen)
6790 continue;
6791
6792 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
6793 if (BGP_PATH_HOLDDOWN(pi))
6794 continue;
6795 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
6796 continue;
6797 if (!bgp_aggregate_med_match(aggregate, bgp, pi)) {
6798 med_matched = false;
6799 break;
6800 }
6801 }
6802 if (!med_matched)
6803 break;
6804 }
6805 bgp_dest_unlock_node(top);
6806
6807 return med_matched;
6808 }
6809
6810 /**
6811 * Toggles the route suppression status for this aggregate address
6812 * configuration.
6813 */
6814 void bgp_aggregate_toggle_suppressed(struct bgp_aggregate *aggregate,
6815 struct bgp *bgp, const struct prefix *p,
6816 afi_t afi, safi_t safi, bool suppress)
6817 {
6818 struct bgp_table *table = bgp->rib[afi][safi];
6819 const struct prefix *dest_p;
6820 struct bgp_dest *dest, *top;
6821 struct bgp_path_info *pi;
6822 bool toggle_suppression;
6823
6824 /* We've found a different MED we must revert any suppressed routes. */
6825 top = bgp_node_get(table, p);
6826 for (dest = bgp_node_get(table, p); dest;
6827 dest = bgp_route_next_until(dest, top)) {
6828 dest_p = bgp_dest_get_prefix(dest);
6829 if (dest_p->prefixlen <= p->prefixlen)
6830 continue;
6831
6832 toggle_suppression = false;
6833 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
6834 if (BGP_PATH_HOLDDOWN(pi))
6835 continue;
6836 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
6837 continue;
6838
6839 /* We are toggling suppression back. */
6840 if (suppress) {
6841 /* Suppress route if not suppressed already. */
6842 if (aggr_suppress_path(aggregate, pi))
6843 toggle_suppression = true;
6844 continue;
6845 }
6846
6847 /* Install route if there is no more suppression. */
6848 if (aggr_unsuppress_path(aggregate, pi))
6849 toggle_suppression = true;
6850 }
6851
6852 if (toggle_suppression)
6853 bgp_process(bgp, dest, afi, safi);
6854 }
6855 bgp_dest_unlock_node(top);
6856 }
6857
6858 /**
6859 * Aggregate address MED matching incremental test: this function is called
6860 * when the initial aggregation occurred and we are only testing a single
6861 * new path.
6862 *
6863 * In addition to testing and setting the MED validity it also installs back
6864 * suppressed routes (if summary is configured).
6865 *
6866 * Must not be called in `bgp_aggregate_route`.
6867 */
6868 static void bgp_aggregate_med_update(struct bgp_aggregate *aggregate,
6869 struct bgp *bgp, const struct prefix *p,
6870 afi_t afi, safi_t safi,
6871 struct bgp_path_info *pi, bool is_adding)
6872 {
6873 /* MED matching disabled. */
6874 if (!aggregate->match_med)
6875 return;
6876
6877 /* Aggregation with different MED, nothing to do. */
6878 if (aggregate->med_mismatched)
6879 return;
6880
6881 /*
6882 * Test the current entry:
6883 *
6884 * is_adding == true: if the new entry doesn't match then we must
6885 * install all suppressed routes.
6886 *
6887 * is_adding == false: if the entry being removed was the last
6888 * unmatching entry then we can suppress all routes.
6889 */
6890 if (!is_adding) {
6891 if (bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi)
6892 && aggregate->summary_only)
6893 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi,
6894 safi, true);
6895 } else
6896 bgp_aggregate_med_match(aggregate, bgp, pi);
6897
6898 /* No mismatches, just quit. */
6899 if (!aggregate->med_mismatched)
6900 return;
6901
6902 /* Route summarization is disabled. */
6903 if (!aggregate->summary_only)
6904 return;
6905
6906 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi, safi, false);
6907 }
6908
6909 /* Update an aggregate as routes are added/removed from the BGP table */
6910 void bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi,
6911 safi_t safi, struct bgp_aggregate *aggregate)
6912 {
6913 struct bgp_table *table;
6914 struct bgp_dest *top;
6915 struct bgp_dest *dest;
6916 uint8_t origin;
6917 struct aspath *aspath = NULL;
6918 struct community *community = NULL;
6919 struct ecommunity *ecommunity = NULL;
6920 struct lcommunity *lcommunity = NULL;
6921 struct bgp_path_info *pi;
6922 unsigned long match = 0;
6923 uint8_t atomic_aggregate = 0;
6924
6925 /* If the bgp instance is being deleted or self peer is deleted
6926 * then do not create aggregate route
6927 */
6928 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
6929 || (bgp->peer_self == NULL))
6930 return;
6931
6932 /* Initialize and test routes for MED difference. */
6933 if (aggregate->match_med)
6934 bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi);
6935
6936 /*
6937 * Reset aggregate count: we might've been called from route map
6938 * update so in that case we must retest all more specific routes.
6939 *
6940 * \see `bgp_route_map_process_update`.
6941 */
6942 aggregate->count = 0;
6943 aggregate->incomplete_origin_count = 0;
6944 aggregate->incomplete_origin_count = 0;
6945 aggregate->egp_origin_count = 0;
6946
6947 /* ORIGIN attribute: If at least one route among routes that are
6948 aggregated has ORIGIN with the value INCOMPLETE, then the
6949 aggregated route must have the ORIGIN attribute with the value
6950 INCOMPLETE. Otherwise, if at least one route among routes that
6951 are aggregated has ORIGIN with the value EGP, then the aggregated
6952 route must have the origin attribute with the value EGP. In all
6953 other case the value of the ORIGIN attribute of the aggregated
6954 route is INTERNAL. */
6955 origin = BGP_ORIGIN_IGP;
6956
6957 table = bgp->rib[afi][safi];
6958
6959 top = bgp_node_get(table, p);
6960 for (dest = bgp_node_get(table, p); dest;
6961 dest = bgp_route_next_until(dest, top)) {
6962 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
6963
6964 if (dest_p->prefixlen <= p->prefixlen)
6965 continue;
6966
6967 /* If suppress fib is enabled and route not installed
6968 * in FIB, skip the route
6969 */
6970 if (!bgp_check_advertise(bgp, dest))
6971 continue;
6972
6973 match = 0;
6974
6975 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
6976 if (BGP_PATH_HOLDDOWN(pi))
6977 continue;
6978
6979 if (pi->attr->flag
6980 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
6981 atomic_aggregate = 1;
6982
6983 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
6984 continue;
6985
6986 /*
6987 * summary-only aggregate route suppress
6988 * aggregated route announcements.
6989 *
6990 * MED matching:
6991 * Don't create summaries if MED didn't match
6992 * otherwise neither the specific routes and the
6993 * aggregation will be announced.
6994 */
6995 if (aggregate->summary_only
6996 && AGGREGATE_MED_VALID(aggregate)) {
6997 if (aggr_suppress_path(aggregate, pi))
6998 match++;
6999 }
7000
7001 /*
7002 * Suppress more specific routes that match the route
7003 * map results.
7004 *
7005 * MED matching:
7006 * Don't suppress routes if MED matching is enabled and
7007 * it mismatched otherwise we might end up with no
7008 * routes for this path.
7009 */
7010 if (aggregate->suppress_map_name
7011 && AGGREGATE_MED_VALID(aggregate)
7012 && aggr_suppress_map_test(bgp, aggregate, pi)) {
7013 if (aggr_suppress_path(aggregate, pi))
7014 match++;
7015 }
7016
7017 aggregate->count++;
7018
7019 /*
7020 * If at least one route among routes that are
7021 * aggregated has ORIGIN with the value INCOMPLETE,
7022 * then the aggregated route MUST have the ORIGIN
7023 * attribute with the value INCOMPLETE. Otherwise, if
7024 * at least one route among routes that are aggregated
7025 * has ORIGIN with the value EGP, then the aggregated
7026 * route MUST have the ORIGIN attribute with the value
7027 * EGP.
7028 */
7029 switch (pi->attr->origin) {
7030 case BGP_ORIGIN_INCOMPLETE:
7031 aggregate->incomplete_origin_count++;
7032 break;
7033 case BGP_ORIGIN_EGP:
7034 aggregate->egp_origin_count++;
7035 break;
7036 default:
7037 /*Do nothing.
7038 */
7039 break;
7040 }
7041
7042 if (!aggregate->as_set)
7043 continue;
7044
7045 /*
7046 * as-set aggregate route generate origin, as path,
7047 * and community aggregation.
7048 */
7049 /* Compute aggregate route's as-path.
7050 */
7051 bgp_compute_aggregate_aspath_hash(aggregate,
7052 pi->attr->aspath);
7053
7054 /* Compute aggregate route's community.
7055 */
7056 if (pi->attr->community)
7057 bgp_compute_aggregate_community_hash(
7058 aggregate,
7059 pi->attr->community);
7060
7061 /* Compute aggregate route's extended community.
7062 */
7063 if (pi->attr->ecommunity)
7064 bgp_compute_aggregate_ecommunity_hash(
7065 aggregate,
7066 pi->attr->ecommunity);
7067
7068 /* Compute aggregate route's large community.
7069 */
7070 if (pi->attr->lcommunity)
7071 bgp_compute_aggregate_lcommunity_hash(
7072 aggregate,
7073 pi->attr->lcommunity);
7074 }
7075 if (match)
7076 bgp_process(bgp, dest, afi, safi);
7077 }
7078 if (aggregate->as_set) {
7079 bgp_compute_aggregate_aspath_val(aggregate);
7080 bgp_compute_aggregate_community_val(aggregate);
7081 bgp_compute_aggregate_ecommunity_val(aggregate);
7082 bgp_compute_aggregate_lcommunity_val(aggregate);
7083 }
7084
7085
7086 bgp_dest_unlock_node(top);
7087
7088
7089 if (aggregate->incomplete_origin_count > 0)
7090 origin = BGP_ORIGIN_INCOMPLETE;
7091 else if (aggregate->egp_origin_count > 0)
7092 origin = BGP_ORIGIN_EGP;
7093
7094 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7095 origin = aggregate->origin;
7096
7097 if (aggregate->as_set) {
7098 if (aggregate->aspath)
7099 /* Retrieve aggregate route's as-path.
7100 */
7101 aspath = aspath_dup(aggregate->aspath);
7102
7103 if (aggregate->community)
7104 /* Retrieve aggregate route's community.
7105 */
7106 community = community_dup(aggregate->community);
7107
7108 if (aggregate->ecommunity)
7109 /* Retrieve aggregate route's ecommunity.
7110 */
7111 ecommunity = ecommunity_dup(aggregate->ecommunity);
7112
7113 if (aggregate->lcommunity)
7114 /* Retrieve aggregate route's lcommunity.
7115 */
7116 lcommunity = lcommunity_dup(aggregate->lcommunity);
7117 }
7118
7119 bgp_aggregate_install(bgp, afi, safi, p, origin, aspath, community,
7120 ecommunity, lcommunity, atomic_aggregate,
7121 aggregate);
7122 }
7123
7124 void bgp_aggregate_delete(struct bgp *bgp, const struct prefix *p, afi_t afi,
7125 safi_t safi, struct bgp_aggregate *aggregate)
7126 {
7127 struct bgp_table *table;
7128 struct bgp_dest *top;
7129 struct bgp_dest *dest;
7130 struct bgp_path_info *pi;
7131 unsigned long match;
7132
7133 table = bgp->rib[afi][safi];
7134
7135 /* If routes exists below this node, generate aggregate routes. */
7136 top = bgp_node_get(table, p);
7137 for (dest = bgp_node_get(table, p); dest;
7138 dest = bgp_route_next_until(dest, top)) {
7139 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
7140
7141 if (dest_p->prefixlen <= p->prefixlen)
7142 continue;
7143 match = 0;
7144
7145 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
7146 if (BGP_PATH_HOLDDOWN(pi))
7147 continue;
7148
7149 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7150 continue;
7151
7152 if (aggregate->summary_only && pi->extra
7153 && AGGREGATE_MED_VALID(aggregate)) {
7154 if (aggr_unsuppress_path(aggregate, pi))
7155 match++;
7156 }
7157
7158 if (aggregate->suppress_map_name
7159 && AGGREGATE_MED_VALID(aggregate)
7160 && aggr_suppress_map_test(bgp, aggregate, pi)) {
7161 if (aggr_unsuppress_path(aggregate, pi))
7162 match++;
7163 }
7164
7165 aggregate->count--;
7166
7167 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
7168 aggregate->incomplete_origin_count--;
7169 else if (pi->attr->origin == BGP_ORIGIN_EGP)
7170 aggregate->egp_origin_count--;
7171
7172 if (aggregate->as_set) {
7173 /* Remove as-path from aggregate.
7174 */
7175 bgp_remove_aspath_from_aggregate_hash(
7176 aggregate,
7177 pi->attr->aspath);
7178
7179 if (pi->attr->community)
7180 /* Remove community from aggregate.
7181 */
7182 bgp_remove_comm_from_aggregate_hash(
7183 aggregate,
7184 pi->attr->community);
7185
7186 if (pi->attr->ecommunity)
7187 /* Remove ecommunity from aggregate.
7188 */
7189 bgp_remove_ecomm_from_aggregate_hash(
7190 aggregate,
7191 pi->attr->ecommunity);
7192
7193 if (pi->attr->lcommunity)
7194 /* Remove lcommunity from aggregate.
7195 */
7196 bgp_remove_lcomm_from_aggregate_hash(
7197 aggregate,
7198 pi->attr->lcommunity);
7199 }
7200 }
7201
7202 /* If this node was suppressed, process the change. */
7203 if (match)
7204 bgp_process(bgp, dest, afi, safi);
7205 }
7206 if (aggregate->as_set) {
7207 aspath_free(aggregate->aspath);
7208 aggregate->aspath = NULL;
7209 if (aggregate->community)
7210 community_free(&aggregate->community);
7211 if (aggregate->ecommunity)
7212 ecommunity_free(&aggregate->ecommunity);
7213 if (aggregate->lcommunity)
7214 lcommunity_free(&aggregate->lcommunity);
7215 }
7216
7217 bgp_dest_unlock_node(top);
7218 }
7219
7220 static void bgp_add_route_to_aggregate(struct bgp *bgp,
7221 const struct prefix *aggr_p,
7222 struct bgp_path_info *pinew, afi_t afi,
7223 safi_t safi,
7224 struct bgp_aggregate *aggregate)
7225 {
7226 uint8_t origin;
7227 struct aspath *aspath = NULL;
7228 uint8_t atomic_aggregate = 0;
7229 struct community *community = NULL;
7230 struct ecommunity *ecommunity = NULL;
7231 struct lcommunity *lcommunity = NULL;
7232
7233 /* If the bgp instance is being deleted or self peer is deleted
7234 * then do not create aggregate route
7235 */
7236 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7237 || (bgp->peer_self == NULL))
7238 return;
7239
7240 /* ORIGIN attribute: If at least one route among routes that are
7241 * aggregated has ORIGIN with the value INCOMPLETE, then the
7242 * aggregated route must have the ORIGIN attribute with the value
7243 * INCOMPLETE. Otherwise, if at least one route among routes that
7244 * are aggregated has ORIGIN with the value EGP, then the aggregated
7245 * route must have the origin attribute with the value EGP. In all
7246 * other case the value of the ORIGIN attribute of the aggregated
7247 * route is INTERNAL.
7248 */
7249 origin = BGP_ORIGIN_IGP;
7250
7251 aggregate->count++;
7252
7253 /*
7254 * This must be called before `summary` check to avoid
7255 * "suppressing" twice.
7256 */
7257 if (aggregate->match_med)
7258 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi,
7259 pinew, true);
7260
7261 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
7262 aggr_suppress_path(aggregate, pinew);
7263
7264 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
7265 && aggr_suppress_map_test(bgp, aggregate, pinew))
7266 aggr_suppress_path(aggregate, pinew);
7267
7268 switch (pinew->attr->origin) {
7269 case BGP_ORIGIN_INCOMPLETE:
7270 aggregate->incomplete_origin_count++;
7271 break;
7272 case BGP_ORIGIN_EGP:
7273 aggregate->egp_origin_count++;
7274 break;
7275 default:
7276 /* Do nothing.
7277 */
7278 break;
7279 }
7280
7281 if (aggregate->incomplete_origin_count > 0)
7282 origin = BGP_ORIGIN_INCOMPLETE;
7283 else if (aggregate->egp_origin_count > 0)
7284 origin = BGP_ORIGIN_EGP;
7285
7286 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7287 origin = aggregate->origin;
7288
7289 if (aggregate->as_set) {
7290 /* Compute aggregate route's as-path.
7291 */
7292 bgp_compute_aggregate_aspath(aggregate,
7293 pinew->attr->aspath);
7294
7295 /* Compute aggregate route's community.
7296 */
7297 if (pinew->attr->community)
7298 bgp_compute_aggregate_community(
7299 aggregate,
7300 pinew->attr->community);
7301
7302 /* Compute aggregate route's extended community.
7303 */
7304 if (pinew->attr->ecommunity)
7305 bgp_compute_aggregate_ecommunity(
7306 aggregate,
7307 pinew->attr->ecommunity);
7308
7309 /* Compute aggregate route's large community.
7310 */
7311 if (pinew->attr->lcommunity)
7312 bgp_compute_aggregate_lcommunity(
7313 aggregate,
7314 pinew->attr->lcommunity);
7315
7316 /* Retrieve aggregate route's as-path.
7317 */
7318 if (aggregate->aspath)
7319 aspath = aspath_dup(aggregate->aspath);
7320
7321 /* Retrieve aggregate route's community.
7322 */
7323 if (aggregate->community)
7324 community = community_dup(aggregate->community);
7325
7326 /* Retrieve aggregate route's ecommunity.
7327 */
7328 if (aggregate->ecommunity)
7329 ecommunity = ecommunity_dup(aggregate->ecommunity);
7330
7331 /* Retrieve aggregate route's lcommunity.
7332 */
7333 if (aggregate->lcommunity)
7334 lcommunity = lcommunity_dup(aggregate->lcommunity);
7335 }
7336
7337 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
7338 aspath, community, ecommunity,
7339 lcommunity, atomic_aggregate, aggregate);
7340 }
7341
7342 static void bgp_remove_route_from_aggregate(struct bgp *bgp, afi_t afi,
7343 safi_t safi,
7344 struct bgp_path_info *pi,
7345 struct bgp_aggregate *aggregate,
7346 const struct prefix *aggr_p)
7347 {
7348 uint8_t origin;
7349 struct aspath *aspath = NULL;
7350 uint8_t atomic_aggregate = 0;
7351 struct community *community = NULL;
7352 struct ecommunity *ecommunity = NULL;
7353 struct lcommunity *lcommunity = NULL;
7354 unsigned long match = 0;
7355
7356 /* If the bgp instance is being deleted or self peer is deleted
7357 * then do not create aggregate route
7358 */
7359 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7360 || (bgp->peer_self == NULL))
7361 return;
7362
7363 if (BGP_PATH_HOLDDOWN(pi))
7364 return;
7365
7366 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7367 return;
7368
7369 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
7370 if (aggr_unsuppress_path(aggregate, pi))
7371 match++;
7372
7373 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
7374 && aggr_suppress_map_test(bgp, aggregate, pi))
7375 if (aggr_unsuppress_path(aggregate, pi))
7376 match++;
7377
7378 /*
7379 * This must be called after `summary`, `suppress-map` check to avoid
7380 * "unsuppressing" twice.
7381 */
7382 if (aggregate->match_med)
7383 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi, pi,
7384 true);
7385
7386 if (aggregate->count > 0)
7387 aggregate->count--;
7388
7389 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
7390 aggregate->incomplete_origin_count--;
7391 else if (pi->attr->origin == BGP_ORIGIN_EGP)
7392 aggregate->egp_origin_count--;
7393
7394 if (aggregate->as_set) {
7395 /* Remove as-path from aggregate.
7396 */
7397 bgp_remove_aspath_from_aggregate(aggregate,
7398 pi->attr->aspath);
7399
7400 if (pi->attr->community)
7401 /* Remove community from aggregate.
7402 */
7403 bgp_remove_community_from_aggregate(
7404 aggregate,
7405 pi->attr->community);
7406
7407 if (pi->attr->ecommunity)
7408 /* Remove ecommunity from aggregate.
7409 */
7410 bgp_remove_ecommunity_from_aggregate(
7411 aggregate,
7412 pi->attr->ecommunity);
7413
7414 if (pi->attr->lcommunity)
7415 /* Remove lcommunity from aggregate.
7416 */
7417 bgp_remove_lcommunity_from_aggregate(
7418 aggregate,
7419 pi->attr->lcommunity);
7420 }
7421
7422 /* If this node was suppressed, process the change. */
7423 if (match)
7424 bgp_process(bgp, pi->net, afi, safi);
7425
7426 origin = BGP_ORIGIN_IGP;
7427 if (aggregate->incomplete_origin_count > 0)
7428 origin = BGP_ORIGIN_INCOMPLETE;
7429 else if (aggregate->egp_origin_count > 0)
7430 origin = BGP_ORIGIN_EGP;
7431
7432 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7433 origin = aggregate->origin;
7434
7435 if (aggregate->as_set) {
7436 /* Retrieve aggregate route's as-path.
7437 */
7438 if (aggregate->aspath)
7439 aspath = aspath_dup(aggregate->aspath);
7440
7441 /* Retrieve aggregate route's community.
7442 */
7443 if (aggregate->community)
7444 community = community_dup(aggregate->community);
7445
7446 /* Retrieve aggregate route's ecommunity.
7447 */
7448 if (aggregate->ecommunity)
7449 ecommunity = ecommunity_dup(aggregate->ecommunity);
7450
7451 /* Retrieve aggregate route's lcommunity.
7452 */
7453 if (aggregate->lcommunity)
7454 lcommunity = lcommunity_dup(aggregate->lcommunity);
7455 }
7456
7457 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
7458 aspath, community, ecommunity,
7459 lcommunity, atomic_aggregate, aggregate);
7460 }
7461
7462 void bgp_aggregate_increment(struct bgp *bgp, const struct prefix *p,
7463 struct bgp_path_info *pi, afi_t afi, safi_t safi)
7464 {
7465 struct bgp_dest *child;
7466 struct bgp_dest *dest;
7467 struct bgp_aggregate *aggregate;
7468 struct bgp_table *table;
7469
7470 table = bgp->aggregate[afi][safi];
7471
7472 /* No aggregates configured. */
7473 if (bgp_table_top_nolock(table) == NULL)
7474 return;
7475
7476 if (p->prefixlen == 0)
7477 return;
7478
7479 if (BGP_PATH_HOLDDOWN(pi))
7480 return;
7481
7482 /* If suppress fib is enabled and route not installed
7483 * in FIB, do not update the aggregate route
7484 */
7485 if (!bgp_check_advertise(bgp, pi->net))
7486 return;
7487
7488 child = bgp_node_get(table, p);
7489
7490 /* Aggregate address configuration check. */
7491 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
7492 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
7493
7494 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
7495 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
7496 bgp_add_route_to_aggregate(bgp, dest_p, pi, afi, safi,
7497 aggregate);
7498 }
7499 }
7500 bgp_dest_unlock_node(child);
7501 }
7502
7503 void bgp_aggregate_decrement(struct bgp *bgp, const struct prefix *p,
7504 struct bgp_path_info *del, afi_t afi, safi_t safi)
7505 {
7506 struct bgp_dest *child;
7507 struct bgp_dest *dest;
7508 struct bgp_aggregate *aggregate;
7509 struct bgp_table *table;
7510
7511 table = bgp->aggregate[afi][safi];
7512
7513 /* No aggregates configured. */
7514 if (bgp_table_top_nolock(table) == NULL)
7515 return;
7516
7517 if (p->prefixlen == 0)
7518 return;
7519
7520 child = bgp_node_get(table, p);
7521
7522 /* Aggregate address configuration check. */
7523 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
7524 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
7525
7526 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
7527 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
7528 bgp_remove_route_from_aggregate(bgp, afi, safi, del,
7529 aggregate, dest_p);
7530 }
7531 }
7532 bgp_dest_unlock_node(child);
7533 }
7534
7535 /* Aggregate route attribute. */
7536 #define AGGREGATE_SUMMARY_ONLY 1
7537 #define AGGREGATE_AS_SET 1
7538 #define AGGREGATE_AS_UNSET 0
7539
7540 static const char *bgp_origin2str(uint8_t origin)
7541 {
7542 switch (origin) {
7543 case BGP_ORIGIN_IGP:
7544 return "igp";
7545 case BGP_ORIGIN_EGP:
7546 return "egp";
7547 case BGP_ORIGIN_INCOMPLETE:
7548 return "incomplete";
7549 }
7550 return "n/a";
7551 }
7552
7553 int bgp_aggregate_unset(struct bgp *bgp, struct prefix *prefix, afi_t afi,
7554 safi_t safi, char *errmsg, size_t errmsg_len)
7555 {
7556 struct bgp_dest *dest;
7557 struct bgp_aggregate *aggregate;
7558
7559 /* If the bgp instance is being deleted or self peer is deleted
7560 * then do not create aggregate route
7561 */
7562 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7563 || (bgp->peer_self == NULL))
7564 return 0;
7565
7566 apply_mask(prefix);
7567 /* Old configuration check. */
7568 dest = bgp_node_lookup(bgp->aggregate[afi][safi], prefix);
7569 if (!dest) {
7570 snprintf(errmsg, errmsg_len,
7571 "There is no aggregate-address configuration.\n");
7572 return -1;
7573 }
7574
7575 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
7576 bgp_aggregate_delete(bgp, prefix, afi, safi, aggregate);
7577 bgp_aggregate_install(bgp, afi, safi, prefix, 0, NULL, NULL, NULL, NULL,
7578 0, aggregate);
7579
7580 /* Unlock aggregate address configuration. */
7581 bgp_dest_set_bgp_aggregate_info(dest, NULL);
7582
7583 if (aggregate->community)
7584 community_free(&aggregate->community);
7585
7586 if (aggregate->community_hash) {
7587 /* Delete all communities in the hash.
7588 */
7589 hash_clean(aggregate->community_hash,
7590 bgp_aggr_community_remove);
7591 /* Free up the community_hash.
7592 */
7593 hash_free(aggregate->community_hash);
7594 }
7595
7596 if (aggregate->ecommunity)
7597 ecommunity_free(&aggregate->ecommunity);
7598
7599 if (aggregate->ecommunity_hash) {
7600 /* Delete all ecommunities in the hash.
7601 */
7602 hash_clean(aggregate->ecommunity_hash,
7603 bgp_aggr_ecommunity_remove);
7604 /* Free up the ecommunity_hash.
7605 */
7606 hash_free(aggregate->ecommunity_hash);
7607 }
7608
7609 if (aggregate->lcommunity)
7610 lcommunity_free(&aggregate->lcommunity);
7611
7612 if (aggregate->lcommunity_hash) {
7613 /* Delete all lcommunities in the hash.
7614 */
7615 hash_clean(aggregate->lcommunity_hash,
7616 bgp_aggr_lcommunity_remove);
7617 /* Free up the lcommunity_hash.
7618 */
7619 hash_free(aggregate->lcommunity_hash);
7620 }
7621
7622 if (aggregate->aspath)
7623 aspath_free(aggregate->aspath);
7624
7625 if (aggregate->aspath_hash) {
7626 /* Delete all as-paths in the hash.
7627 */
7628 hash_clean(aggregate->aspath_hash,
7629 bgp_aggr_aspath_remove);
7630 /* Free up the aspath_hash.
7631 */
7632 hash_free(aggregate->aspath_hash);
7633 }
7634
7635 bgp_aggregate_free(aggregate);
7636 bgp_dest_unlock_node(dest);
7637 bgp_dest_unlock_node(dest);
7638
7639 return 0;
7640 }
7641
7642 int bgp_aggregate_set(struct bgp *bgp, struct prefix *prefix, afi_t afi,
7643 safi_t safi, const char *rmap, uint8_t summary_only,
7644 uint8_t as_set, uint8_t origin, bool match_med,
7645 const char *suppress_map,
7646 char *errmsg, size_t errmsg_len)
7647 {
7648 int ret;
7649 struct bgp_dest *dest;
7650 struct bgp_aggregate *aggregate;
7651 uint8_t as_set_new = as_set;
7652 char buf[PREFIX2STR_BUFFER];
7653
7654 if (suppress_map && summary_only) {
7655 snprintf(errmsg, errmsg_len,
7656 "'summary-only' and 'suppress-map' can't be used at the same time\n");
7657 return -1;
7658 }
7659
7660 apply_mask(prefix);
7661
7662 if ((afi == AFI_IP && prefix->prefixlen == IPV4_MAX_BITLEN)
7663 || (afi == AFI_IP6 && prefix->prefixlen == IPV6_MAX_BITLEN)) {
7664 snprintf(
7665 errmsg, errmsg_len,
7666 "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
7667 prefix2str(prefix, buf, PREFIX_STRLEN));
7668 return -1;
7669 }
7670
7671 /* Old configuration check. */
7672 dest = bgp_node_get(bgp->aggregate[afi][safi], prefix);
7673 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
7674
7675 if (aggregate) {
7676 snprintf(errmsg, errmsg_len,
7677 "There is already same aggregate network.\n");
7678 /* try to remove the old entry */
7679 ret = bgp_aggregate_unset(bgp, prefix, afi, safi, errmsg,
7680 errmsg_len);
7681 if (ret) {
7682 snprintf(errmsg, errmsg_len,
7683 "Error deleting aggregate.\n");
7684 bgp_dest_unlock_node(dest);
7685 return -1;
7686 }
7687 }
7688
7689 /* Make aggregate address structure. */
7690 aggregate = bgp_aggregate_new();
7691 aggregate->summary_only = summary_only;
7692 aggregate->match_med = match_med;
7693
7694 /* Network operators MUST NOT locally generate any new
7695 * announcements containing AS_SET or AS_CONFED_SET. If they have
7696 * announced routes with AS_SET or AS_CONFED_SET in them, then they
7697 * SHOULD withdraw those routes and re-announce routes for the
7698 * aggregate or component prefixes (i.e., the more-specific routes
7699 * subsumed by the previously aggregated route) without AS_SET
7700 * or AS_CONFED_SET in the updates.
7701 */
7702 if (bgp->reject_as_sets) {
7703 if (as_set == AGGREGATE_AS_SET) {
7704 as_set_new = AGGREGATE_AS_UNSET;
7705 zlog_warn(
7706 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
7707 __func__);
7708 snprintf(
7709 errmsg, errmsg_len,
7710 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
7711 }
7712 }
7713
7714 aggregate->as_set = as_set_new;
7715 aggregate->safi = safi;
7716 /* Override ORIGIN attribute if defined.
7717 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
7718 * to IGP which is not what rfc4271 says.
7719 * This enables the same behavior, optionally.
7720 */
7721 aggregate->origin = origin;
7722
7723 if (rmap) {
7724 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
7725 route_map_counter_decrement(aggregate->rmap.map);
7726 aggregate->rmap.name =
7727 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
7728 aggregate->rmap.map = route_map_lookup_by_name(rmap);
7729 route_map_counter_increment(aggregate->rmap.map);
7730 }
7731
7732 if (suppress_map) {
7733 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
7734 route_map_counter_decrement(aggregate->suppress_map);
7735
7736 aggregate->suppress_map_name =
7737 XSTRDUP(MTYPE_ROUTE_MAP_NAME, suppress_map);
7738 aggregate->suppress_map =
7739 route_map_lookup_by_name(aggregate->suppress_map_name);
7740 route_map_counter_increment(aggregate->suppress_map);
7741 }
7742
7743 bgp_dest_set_bgp_aggregate_info(dest, aggregate);
7744
7745 /* Aggregate address insert into BGP routing table. */
7746 bgp_aggregate_route(bgp, prefix, afi, safi, aggregate);
7747
7748 return 0;
7749 }
7750
7751 DEFPY_YANG(
7752 aggregate_addressv4, aggregate_addressv4_cmd,
7753 "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> {"
7754 "as-set$as_set_s"
7755 "|summary-only$summary_only"
7756 "|route-map WORD$rmap_name"
7757 "|origin <egp|igp|incomplete>$origin_s"
7758 "|matching-MED-only$match_med"
7759 "|suppress-map WORD$suppress_map"
7760 "}",
7761 NO_STR
7762 "Configure BGP aggregate entries\n"
7763 "Aggregate prefix\n"
7764 "Aggregate address\n"
7765 "Aggregate mask\n"
7766 "Generate AS set path information\n"
7767 "Filter more specific routes from updates\n"
7768 "Apply route map to aggregate network\n"
7769 "Route map name\n"
7770 "BGP origin code\n"
7771 "Remote EGP\n"
7772 "Local IGP\n"
7773 "Unknown heritage\n"
7774 "Only aggregate routes with matching MED\n"
7775 "Suppress the selected more specific routes\n"
7776 "Route map with the route selectors\n")
7777 {
7778 char base_xpath[XPATH_MAXLEN];
7779 safi_t safi = bgp_node_safi(vty);
7780 char prefix_buf[PREFIX2STR_BUFFER];
7781
7782 if (addr_str) {
7783 if (netmask_str2prefix_str(addr_str, mask_str, prefix_buf)
7784 == 0) {
7785 vty_out(vty, "%% Inconsistent address and mask\n");
7786 return CMD_WARNING_CONFIG_FAILED;
7787 }
7788 } else {
7789 strlcpy(prefix_buf, prefix_str, sizeof(prefix_buf));
7790 }
7791
7792 if (!no && origin_s)
7793 nb_cli_enqueue_change(vty, "./origin", NB_OP_MODIFY, origin_s);
7794
7795 if (!no && as_set_s)
7796 nb_cli_enqueue_change(vty, "./as-set", NB_OP_MODIFY, "true");
7797 else
7798 nb_cli_enqueue_change(vty, "./as-set", NB_OP_MODIFY, "false");
7799
7800 if (!no && summary_only)
7801 nb_cli_enqueue_change(vty, "./summary-only", NB_OP_MODIFY,
7802 "true");
7803 else
7804 nb_cli_enqueue_change(vty, "./summary-only", NB_OP_MODIFY,
7805 "false");
7806
7807 if (!no && match_med)
7808 nb_cli_enqueue_change(vty, "./match-med", NB_OP_MODIFY, "true");
7809 else
7810 nb_cli_enqueue_change(vty, "./match-med", NB_OP_MODIFY,
7811 "false");
7812
7813 if (rmap_name)
7814 nb_cli_enqueue_change(vty, "./rmap-policy-export", NB_OP_MODIFY,
7815 rmap_name);
7816 else
7817 nb_cli_enqueue_change(vty, "./rmap-policy-export",
7818 NB_OP_DESTROY, NULL);
7819
7820 if (suppress_map)
7821 nb_cli_enqueue_change(vty, "./suppress-map", NB_OP_MODIFY,
7822 suppress_map);
7823 else
7824 nb_cli_enqueue_change(vty, "./suppress-map", NB_OP_DESTROY,
7825 NULL);
7826
7827 snprintf(
7828 base_xpath, sizeof(base_xpath),
7829 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/aggregate-route[prefix='%s']",
7830 yang_afi_safi_value2identity(AFI_IP, safi),
7831 bgp_afi_safi_get_container_str(AFI_IP, safi), prefix_buf);
7832
7833 if (no)
7834 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
7835 else
7836 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
7837
7838 return nb_cli_apply_changes(vty, base_xpath);
7839 }
7840
7841 DEFPY_YANG(aggregate_addressv6, aggregate_addressv6_cmd,
7842 "[no] aggregate-address X:X::X:X/M$prefix {"
7843 "as-set$as_set_s"
7844 "|summary-only$summary_only"
7845 "|route-map WORD$rmap_name"
7846 "|origin <egp|igp|incomplete>$origin_s"
7847 "|matching-MED-only$match_med"
7848 "|suppress-map WORD$suppress_map"
7849 "}",
7850 NO_STR
7851 "Configure BGP aggregate entries\n"
7852 "Aggregate prefix\n"
7853 "Generate AS set path information\n"
7854 "Filter more specific routes from updates\n"
7855 "Apply route map to aggregate network\n"
7856 "Route map name\n"
7857 "BGP origin code\n"
7858 "Remote EGP\n"
7859 "Local IGP\n"
7860 "Unknown heritage\n"
7861 "Only aggregate routes with matching MED\n"
7862 "Suppress the selected more specific routes\n"
7863 "Route map with the route selectors\n")
7864 {
7865 char base_xpath[XPATH_MAXLEN];
7866 safi_t safi = bgp_node_safi(vty);
7867
7868 if (!no && origin_s)
7869 nb_cli_enqueue_change(vty, "./origin", NB_OP_MODIFY, origin_s);
7870
7871 if (!no && as_set_s)
7872 nb_cli_enqueue_change(vty, "./as-set", NB_OP_MODIFY, "true");
7873 else
7874 nb_cli_enqueue_change(vty, "./as-set", NB_OP_MODIFY, "false");
7875
7876 if (!no && summary_only)
7877 nb_cli_enqueue_change(vty, "./summary-only", NB_OP_MODIFY,
7878 "true");
7879 else
7880 nb_cli_enqueue_change(vty, "./summary-only", NB_OP_MODIFY,
7881 "false");
7882
7883 if (!no && match_med)
7884 nb_cli_enqueue_change(vty, "./match-med", NB_OP_MODIFY, "true");
7885 else
7886 nb_cli_enqueue_change(vty, "./match-med", NB_OP_MODIFY,
7887 "false");
7888
7889 if (rmap_name)
7890 nb_cli_enqueue_change(vty, "./rmap-policy-export", NB_OP_MODIFY,
7891 rmap_name);
7892
7893 if (suppress_map)
7894 nb_cli_enqueue_change(vty, "./suppress-map", NB_OP_MODIFY,
7895 suppress_map);
7896 else
7897 nb_cli_enqueue_change(vty, "./suppress-map", NB_OP_DESTROY,
7898 NULL);
7899
7900 snprintf(
7901 base_xpath, sizeof(base_xpath),
7902 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/aggregate-route[prefix='%s']",
7903 yang_afi_safi_value2identity(AFI_IP6, safi),
7904 bgp_afi_safi_get_container_str(AFI_IP6, safi), prefix_str);
7905
7906 if (no)
7907 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
7908 else
7909 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
7910
7911 return nb_cli_apply_changes(vty, base_xpath);
7912 }
7913
7914 void cli_show_bgp_global_afi_safi_unicast_aggregate_route(
7915 struct vty *vty, struct lyd_node *dnode, bool show_defaults)
7916 {
7917 uint8_t origin;
7918
7919 vty_out(vty, " aggregate-address %s",
7920 yang_dnode_get_string(dnode, "./prefix"));
7921
7922 if (yang_dnode_get_bool(dnode, "./as-set"))
7923 vty_out(vty, " as-set");
7924
7925 if (yang_dnode_get_bool(dnode, "./summary-only"))
7926 vty_out(vty, " summary-only");
7927
7928 if (yang_dnode_exists(dnode, "./rmap-policy-export"))
7929 vty_out(vty, " route-map %s",
7930 yang_dnode_get_string(dnode, "./rmap-policy-export"));
7931
7932 origin = yang_dnode_get_enum(dnode, "./origin");
7933 if (origin != BGP_ORIGIN_UNSPECIFIED)
7934 vty_out(vty, " origin %s", bgp_origin2str(origin));
7935
7936 if (yang_dnode_get_bool(dnode, "./match-med"))
7937 vty_out(vty, " matching-MED-only");
7938
7939 vty_out(vty, "\n");
7940 }
7941
7942 /* Redistribute route treatment. */
7943 void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
7944 const union g_addr *nexthop, ifindex_t ifindex,
7945 enum nexthop_types_t nhtype, uint32_t metric,
7946 uint8_t type, unsigned short instance,
7947 route_tag_t tag)
7948 {
7949 struct bgp_path_info *new;
7950 struct bgp_path_info *bpi;
7951 struct bgp_path_info rmap_path;
7952 struct bgp_dest *bn;
7953 struct attr attr;
7954 struct attr *new_attr;
7955 afi_t afi;
7956 route_map_result_t ret;
7957 struct bgp_redist *red;
7958
7959 /* Make default attribute. */
7960 bgp_attr_default_set(&attr, BGP_ORIGIN_INCOMPLETE);
7961 /*
7962 * This must not be NULL to satisfy Coverity SA
7963 */
7964 assert(attr.aspath);
7965
7966 switch (nhtype) {
7967 case NEXTHOP_TYPE_IFINDEX:
7968 break;
7969 case NEXTHOP_TYPE_IPV4:
7970 case NEXTHOP_TYPE_IPV4_IFINDEX:
7971 attr.nexthop = nexthop->ipv4;
7972 break;
7973 case NEXTHOP_TYPE_IPV6:
7974 case NEXTHOP_TYPE_IPV6_IFINDEX:
7975 attr.mp_nexthop_global = nexthop->ipv6;
7976 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
7977 break;
7978 case NEXTHOP_TYPE_BLACKHOLE:
7979 switch (p->family) {
7980 case AF_INET:
7981 attr.nexthop.s_addr = INADDR_ANY;
7982 break;
7983 case AF_INET6:
7984 memset(&attr.mp_nexthop_global, 0,
7985 sizeof(attr.mp_nexthop_global));
7986 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
7987 break;
7988 }
7989 break;
7990 }
7991 attr.nh_ifindex = ifindex;
7992
7993 attr.med = metric;
7994 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
7995 attr.tag = tag;
7996
7997 afi = family2afi(p->family);
7998
7999 red = bgp_redist_lookup(bgp, afi, type, instance);
8000 if (red) {
8001 struct attr attr_new;
8002
8003 /* Copy attribute for modification. */
8004 attr_new = attr;
8005
8006 if (red->redist_metric_flag)
8007 attr_new.med = red->redist_metric;
8008
8009 /* Apply route-map. */
8010 if (red->rmap.name) {
8011 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
8012 rmap_path.peer = bgp->peer_self;
8013 rmap_path.attr = &attr_new;
8014
8015 SET_FLAG(bgp->peer_self->rmap_type,
8016 PEER_RMAP_TYPE_REDISTRIBUTE);
8017
8018 ret = route_map_apply(red->rmap.map, p, &rmap_path);
8019
8020 bgp->peer_self->rmap_type = 0;
8021
8022 if (ret == RMAP_DENYMATCH) {
8023 /* Free uninterned attribute. */
8024 bgp_attr_flush(&attr_new);
8025
8026 /* Unintern original. */
8027 aspath_unintern(&attr.aspath);
8028 bgp_redistribute_delete(bgp, p, type, instance);
8029 return;
8030 }
8031 }
8032
8033 if (bgp_in_graceful_shutdown(bgp))
8034 bgp_attr_add_gshut_community(&attr_new);
8035
8036 bn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8037 SAFI_UNICAST, p, NULL);
8038
8039 new_attr = bgp_attr_intern(&attr_new);
8040
8041 for (bpi = bgp_dest_get_bgp_path_info(bn); bpi; bpi = bpi->next)
8042 if (bpi->peer == bgp->peer_self
8043 && bpi->sub_type == BGP_ROUTE_REDISTRIBUTE)
8044 break;
8045
8046 if (bpi) {
8047 /* Ensure the (source route) type is updated. */
8048 bpi->type = type;
8049 if (attrhash_cmp(bpi->attr, new_attr)
8050 && !CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
8051 bgp_attr_unintern(&new_attr);
8052 aspath_unintern(&attr.aspath);
8053 bgp_dest_unlock_node(bn);
8054 return;
8055 } else {
8056 /* The attribute is changed. */
8057 bgp_path_info_set_flag(bn, bpi,
8058 BGP_PATH_ATTR_CHANGED);
8059
8060 /* Rewrite BGP route information. */
8061 if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
8062 bgp_path_info_restore(bn, bpi);
8063 else
8064 bgp_aggregate_decrement(
8065 bgp, p, bpi, afi, SAFI_UNICAST);
8066 bgp_attr_unintern(&bpi->attr);
8067 bpi->attr = new_attr;
8068 bpi->uptime = bgp_clock();
8069
8070 /* Process change. */
8071 bgp_aggregate_increment(bgp, p, bpi, afi,
8072 SAFI_UNICAST);
8073 bgp_process(bgp, bn, afi, SAFI_UNICAST);
8074 bgp_dest_unlock_node(bn);
8075 aspath_unintern(&attr.aspath);
8076
8077 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8078 || (bgp->inst_type
8079 == BGP_INSTANCE_TYPE_DEFAULT)) {
8080
8081 vpn_leak_from_vrf_update(
8082 bgp_get_default(), bgp, bpi);
8083 }
8084 return;
8085 }
8086 }
8087
8088 new = info_make(type, BGP_ROUTE_REDISTRIBUTE, instance,
8089 bgp->peer_self, new_attr, bn);
8090 SET_FLAG(new->flags, BGP_PATH_VALID);
8091
8092 bgp_aggregate_increment(bgp, p, new, afi, SAFI_UNICAST);
8093 bgp_path_info_add(bn, new);
8094 bgp_dest_unlock_node(bn);
8095 bgp_process(bgp, bn, afi, SAFI_UNICAST);
8096
8097 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8098 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8099
8100 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
8101 }
8102 }
8103
8104 /* Unintern original. */
8105 aspath_unintern(&attr.aspath);
8106 }
8107
8108 void bgp_redistribute_delete(struct bgp *bgp, struct prefix *p, uint8_t type,
8109 unsigned short instance)
8110 {
8111 afi_t afi;
8112 struct bgp_dest *dest;
8113 struct bgp_path_info *pi;
8114 struct bgp_redist *red;
8115
8116 afi = family2afi(p->family);
8117
8118 red = bgp_redist_lookup(bgp, afi, type, instance);
8119 if (red) {
8120 dest = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8121 SAFI_UNICAST, p, NULL);
8122
8123 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
8124 if (pi->peer == bgp->peer_self && pi->type == type)
8125 break;
8126
8127 if (pi) {
8128 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8129 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8130
8131 vpn_leak_from_vrf_withdraw(bgp_get_default(),
8132 bgp, pi);
8133 }
8134 bgp_aggregate_decrement(bgp, p, pi, afi, SAFI_UNICAST);
8135 bgp_path_info_delete(dest, pi);
8136 bgp_process(bgp, dest, afi, SAFI_UNICAST);
8137 }
8138 bgp_dest_unlock_node(dest);
8139 }
8140 }
8141
8142 /* Withdraw specified route type's route. */
8143 void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type,
8144 unsigned short instance)
8145 {
8146 struct bgp_dest *dest;
8147 struct bgp_path_info *pi;
8148 struct bgp_table *table;
8149
8150 table = bgp->rib[afi][SAFI_UNICAST];
8151
8152 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
8153 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
8154 if (pi->peer == bgp->peer_self && pi->type == type
8155 && pi->instance == instance)
8156 break;
8157
8158 if (pi) {
8159 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8160 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8161
8162 vpn_leak_from_vrf_withdraw(bgp_get_default(),
8163 bgp, pi);
8164 }
8165 bgp_aggregate_decrement(bgp, bgp_dest_get_prefix(dest),
8166 pi, afi, SAFI_UNICAST);
8167 bgp_path_info_delete(dest, pi);
8168 bgp_process(bgp, dest, afi, SAFI_UNICAST);
8169 }
8170 }
8171 }
8172
8173 /* Static function to display route. */
8174 static void route_vty_out_route(const struct prefix *p, struct vty *vty,
8175 json_object *json, bool wide)
8176 {
8177 int len = 0;
8178 char buf[BUFSIZ];
8179 char buf2[BUFSIZ];
8180
8181 if (p->family == AF_INET) {
8182 if (!json) {
8183 len = vty_out(vty, "%pFX", p);
8184 } else {
8185 json_object_string_add(json, "prefix",
8186 inet_ntop(p->family,
8187 &p->u.prefix, buf,
8188 BUFSIZ));
8189 json_object_int_add(json, "prefixLen", p->prefixlen);
8190 prefix2str(p, buf2, PREFIX_STRLEN);
8191 json_object_string_add(json, "network", buf2);
8192 }
8193 } else if (p->family == AF_ETHERNET) {
8194 len = vty_out(vty, "%pFX", p);
8195 } else if (p->family == AF_EVPN) {
8196 if (!json)
8197 len = vty_out(vty, "%pFX", (struct prefix_evpn *)p);
8198 else
8199 bgp_evpn_route2json((struct prefix_evpn *)p, json);
8200 } else if (p->family == AF_FLOWSPEC) {
8201 route_vty_out_flowspec(vty, p, NULL,
8202 json ?
8203 NLRI_STRING_FORMAT_JSON_SIMPLE :
8204 NLRI_STRING_FORMAT_MIN, json);
8205 } else {
8206 if (!json)
8207 len = vty_out(vty, "%pFX", p);
8208 else {
8209 json_object_string_add(json, "prefix",
8210 inet_ntop(p->family,
8211 &p->u.prefix, buf,
8212 BUFSIZ));
8213 json_object_int_add(json, "prefixLen", p->prefixlen);
8214 prefix2str(p, buf2, PREFIX_STRLEN);
8215 json_object_string_add(json, "network", buf2);
8216 }
8217 }
8218
8219 if (!json) {
8220 len = wide ? (45 - len) : (17 - len);
8221 if (len < 1)
8222 vty_out(vty, "\n%*s", 20, " ");
8223 else
8224 vty_out(vty, "%*s", len, " ");
8225 }
8226 }
8227
8228 enum bgp_display_type {
8229 normal_list,
8230 };
8231
8232 static const char *
8233 bgp_path_selection_reason2str(enum bgp_path_selection_reason reason)
8234 {
8235 switch (reason) {
8236 case bgp_path_selection_none:
8237 return "Nothing to Select";
8238 case bgp_path_selection_first:
8239 return "First path received";
8240 case bgp_path_selection_evpn_sticky_mac:
8241 return "EVPN Sticky Mac";
8242 case bgp_path_selection_evpn_seq:
8243 return "EVPN sequence number";
8244 case bgp_path_selection_evpn_lower_ip:
8245 return "EVPN lower IP";
8246 case bgp_path_selection_evpn_local_path:
8247 return "EVPN local ES path";
8248 case bgp_path_selection_evpn_non_proxy:
8249 return "EVPN non proxy";
8250 case bgp_path_selection_weight:
8251 return "Weight";
8252 case bgp_path_selection_local_pref:
8253 return "Local Pref";
8254 case bgp_path_selection_local_route:
8255 return "Local Route";
8256 case bgp_path_selection_confed_as_path:
8257 return "Confederation based AS Path";
8258 case bgp_path_selection_as_path:
8259 return "AS Path";
8260 case bgp_path_selection_origin:
8261 return "Origin";
8262 case bgp_path_selection_med:
8263 return "MED";
8264 case bgp_path_selection_peer:
8265 return "Peer Type";
8266 case bgp_path_selection_confed:
8267 return "Confed Peer Type";
8268 case bgp_path_selection_igp_metric:
8269 return "IGP Metric";
8270 case bgp_path_selection_older:
8271 return "Older Path";
8272 case bgp_path_selection_router_id:
8273 return "Router ID";
8274 case bgp_path_selection_cluster_length:
8275 return "Cluster length";
8276 case bgp_path_selection_stale:
8277 return "Path Staleness";
8278 case bgp_path_selection_local_configured:
8279 return "Locally configured route";
8280 case bgp_path_selection_neighbor_ip:
8281 return "Neighbor IP";
8282 case bgp_path_selection_default:
8283 return "Nothing left to compare";
8284 }
8285 return "Invalid (internal error)";
8286 }
8287
8288 /* Print the short form route status for a bgp_path_info */
8289 static void route_vty_short_status_out(struct vty *vty,
8290 struct bgp_path_info *path,
8291 json_object *json_path)
8292 {
8293 if (json_path) {
8294
8295 /* Route status display. */
8296 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
8297 json_object_boolean_true_add(json_path, "removed");
8298
8299 if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
8300 json_object_boolean_true_add(json_path, "stale");
8301
8302 if (path->extra && bgp_path_suppressed(path))
8303 json_object_boolean_true_add(json_path, "suppressed");
8304
8305 if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
8306 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
8307 json_object_boolean_true_add(json_path, "valid");
8308
8309 /* Selected */
8310 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
8311 json_object_boolean_true_add(json_path, "history");
8312
8313 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
8314 json_object_boolean_true_add(json_path, "damped");
8315
8316 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
8317 json_object_boolean_true_add(json_path, "bestpath");
8318 json_object_string_add(json_path, "selectionReason",
8319 bgp_path_selection_reason2str(
8320 path->net->reason));
8321 }
8322
8323 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
8324 json_object_boolean_true_add(json_path, "multipath");
8325
8326 /* Internal route. */
8327 if ((path->peer->as)
8328 && (path->peer->as == path->peer->local_as))
8329 json_object_string_add(json_path, "pathFrom",
8330 "internal");
8331 else
8332 json_object_string_add(json_path, "pathFrom",
8333 "external");
8334
8335 return;
8336 }
8337
8338 /* Route status display. */
8339 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
8340 vty_out(vty, "R");
8341 else if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
8342 vty_out(vty, "S");
8343 else if (bgp_path_suppressed(path))
8344 vty_out(vty, "s");
8345 else if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
8346 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
8347 vty_out(vty, "*");
8348 else
8349 vty_out(vty, " ");
8350
8351 /* Selected */
8352 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
8353 vty_out(vty, "h");
8354 else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
8355 vty_out(vty, "d");
8356 else if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
8357 vty_out(vty, ">");
8358 else if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
8359 vty_out(vty, "=");
8360 else
8361 vty_out(vty, " ");
8362
8363 /* Internal route. */
8364 if (path->peer && (path->peer->as)
8365 && (path->peer->as == path->peer->local_as))
8366 vty_out(vty, "i");
8367 else
8368 vty_out(vty, " ");
8369 }
8370
8371 static char *bgp_nexthop_hostname(struct peer *peer,
8372 struct bgp_nexthop_cache *bnc)
8373 {
8374 if (peer->hostname
8375 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME))
8376 return peer->hostname;
8377 return NULL;
8378 }
8379
8380 /* called from terminal list command */
8381 void route_vty_out(struct vty *vty, const struct prefix *p,
8382 struct bgp_path_info *path, int display, safi_t safi,
8383 json_object *json_paths, bool wide)
8384 {
8385 int len;
8386 struct attr *attr = path->attr;
8387 json_object *json_path = NULL;
8388 json_object *json_nexthops = NULL;
8389 json_object *json_nexthop_global = NULL;
8390 json_object *json_nexthop_ll = NULL;
8391 json_object *json_ext_community = NULL;
8392 char vrf_id_str[VRF_NAMSIZ] = {0};
8393 bool nexthop_self =
8394 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
8395 bool nexthop_othervrf = false;
8396 vrf_id_t nexthop_vrfid = VRF_DEFAULT;
8397 const char *nexthop_vrfname = VRF_DEFAULT_NAME;
8398 char *nexthop_hostname =
8399 bgp_nexthop_hostname(path->peer, path->nexthop);
8400 char esi_buf[ESI_STR_LEN];
8401
8402 if (json_paths)
8403 json_path = json_object_new_object();
8404
8405 /* short status lead text */
8406 route_vty_short_status_out(vty, path, json_path);
8407
8408 if (!json_paths) {
8409 /* print prefix and mask */
8410 if (!display)
8411 route_vty_out_route(p, vty, json_path, wide);
8412 else
8413 vty_out(vty, "%*s", (wide ? 45 : 17), " ");
8414 } else {
8415 route_vty_out_route(p, vty, json_path, wide);
8416 }
8417
8418 /*
8419 * If vrf id of nexthop is different from that of prefix,
8420 * set up printable string to append
8421 */
8422 if (path->extra && path->extra->bgp_orig) {
8423 const char *self = "";
8424
8425 if (nexthop_self)
8426 self = "<";
8427
8428 nexthop_othervrf = true;
8429 nexthop_vrfid = path->extra->bgp_orig->vrf_id;
8430
8431 if (path->extra->bgp_orig->vrf_id == VRF_UNKNOWN)
8432 snprintf(vrf_id_str, sizeof(vrf_id_str),
8433 "@%s%s", VRFID_NONE_STR, self);
8434 else
8435 snprintf(vrf_id_str, sizeof(vrf_id_str), "@%u%s",
8436 path->extra->bgp_orig->vrf_id, self);
8437
8438 if (path->extra->bgp_orig->inst_type
8439 != BGP_INSTANCE_TYPE_DEFAULT)
8440
8441 nexthop_vrfname = path->extra->bgp_orig->name;
8442 } else {
8443 const char *self = "";
8444
8445 if (nexthop_self)
8446 self = "<";
8447
8448 snprintf(vrf_id_str, sizeof(vrf_id_str), "%s", self);
8449 }
8450
8451 /*
8452 * For ENCAP and EVPN routes, nexthop address family is not
8453 * neccessarily the same as the prefix address family.
8454 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
8455 * EVPN routes are also exchanged with a MP nexthop. Currently,
8456 * this
8457 * is only IPv4, the value will be present in either
8458 * attr->nexthop or
8459 * attr->mp_nexthop_global_in
8460 */
8461 if ((safi == SAFI_ENCAP) || (safi == SAFI_MPLS_VPN)) {
8462 char buf[BUFSIZ];
8463 char nexthop[128];
8464 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
8465
8466 switch (af) {
8467 case AF_INET:
8468 snprintf(nexthop, sizeof(nexthop), "%s",
8469 inet_ntop(af, &attr->mp_nexthop_global_in, buf,
8470 BUFSIZ));
8471 break;
8472 case AF_INET6:
8473 snprintf(nexthop, sizeof(nexthop), "%s",
8474 inet_ntop(af, &attr->mp_nexthop_global, buf,
8475 BUFSIZ));
8476 break;
8477 default:
8478 snprintf(nexthop, sizeof(nexthop), "?");
8479 break;
8480 }
8481
8482 if (json_paths) {
8483 json_nexthop_global = json_object_new_object();
8484
8485 json_object_string_add(json_nexthop_global, "ip",
8486 nexthop);
8487
8488 if (path->peer->hostname)
8489 json_object_string_add(json_nexthop_global,
8490 "hostname",
8491 path->peer->hostname);
8492
8493 json_object_string_add(json_nexthop_global, "afi",
8494 (af == AF_INET) ? "ipv4"
8495 : "ipv6");
8496 json_object_boolean_true_add(json_nexthop_global,
8497 "used");
8498 } else {
8499 if (nexthop_hostname)
8500 len = vty_out(vty, "%s(%s)%s", nexthop,
8501 nexthop_hostname, vrf_id_str);
8502 else
8503 len = vty_out(vty, "%s%s", nexthop, vrf_id_str);
8504
8505 len = wide ? (41 - len) : (16 - len);
8506 if (len < 1)
8507 vty_out(vty, "\n%*s", 36, " ");
8508 else
8509 vty_out(vty, "%*s", len, " ");
8510 }
8511 } else if (safi == SAFI_EVPN) {
8512 if (json_paths) {
8513 char buf[BUFSIZ] = {0};
8514
8515 json_nexthop_global = json_object_new_object();
8516
8517 json_object_string_add(json_nexthop_global, "ip",
8518 inet_ntop(AF_INET,
8519 &attr->nexthop, buf,
8520 sizeof(buf)));
8521
8522 if (path->peer->hostname)
8523 json_object_string_add(json_nexthop_global,
8524 "hostname",
8525 path->peer->hostname);
8526
8527 json_object_string_add(json_nexthop_global, "afi",
8528 "ipv4");
8529 json_object_boolean_true_add(json_nexthop_global,
8530 "used");
8531 } else {
8532 if (nexthop_hostname)
8533 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
8534 nexthop_hostname, vrf_id_str);
8535 else
8536 len = vty_out(vty, "%pI4%s", &attr->nexthop,
8537 vrf_id_str);
8538
8539 len = wide ? (41 - len) : (16 - len);
8540 if (len < 1)
8541 vty_out(vty, "\n%*s", 36, " ");
8542 else
8543 vty_out(vty, "%*s", len, " ");
8544 }
8545 } else if (safi == SAFI_FLOWSPEC) {
8546 if (attr->nexthop.s_addr != INADDR_ANY) {
8547 if (json_paths) {
8548 char buf[BUFSIZ] = {0};
8549
8550 json_nexthop_global = json_object_new_object();
8551
8552 json_object_string_add(json_nexthop_global,
8553 "afi", "ipv4");
8554 json_object_string_add(
8555 json_nexthop_global, "ip",
8556 inet_ntop(AF_INET, &attr->nexthop, buf,
8557 sizeof(buf)));
8558
8559 if (path->peer->hostname)
8560 json_object_string_add(
8561 json_nexthop_global, "hostname",
8562 path->peer->hostname);
8563
8564 json_object_boolean_true_add(
8565 json_nexthop_global,
8566 "used");
8567 } else {
8568 if (nexthop_hostname)
8569 len = vty_out(vty, "%pI4(%s)%s",
8570 &attr->nexthop,
8571 nexthop_hostname,
8572 vrf_id_str);
8573 else
8574 len = vty_out(vty, "%pI4%s",
8575 &attr->nexthop,
8576 vrf_id_str);
8577
8578 len = wide ? (41 - len) : (16 - len);
8579 if (len < 1)
8580 vty_out(vty, "\n%*s", 36, " ");
8581 else
8582 vty_out(vty, "%*s", len, " ");
8583 }
8584 }
8585 } else if (p->family == AF_INET && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
8586 if (json_paths) {
8587 char buf[BUFSIZ] = {0};
8588
8589 json_nexthop_global = json_object_new_object();
8590
8591 json_object_string_add(json_nexthop_global, "ip",
8592 inet_ntop(AF_INET,
8593 &attr->nexthop, buf,
8594 sizeof(buf)));
8595
8596 if (path->peer->hostname)
8597 json_object_string_add(json_nexthop_global,
8598 "hostname",
8599 path->peer->hostname);
8600
8601 json_object_string_add(json_nexthop_global, "afi",
8602 "ipv4");
8603 json_object_boolean_true_add(json_nexthop_global,
8604 "used");
8605 } else {
8606 if (nexthop_hostname)
8607 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
8608 nexthop_hostname, vrf_id_str);
8609 else
8610 len = vty_out(vty, "%pI4%s", &attr->nexthop,
8611 vrf_id_str);
8612
8613 len = wide ? (41 - len) : (16 - len);
8614 if (len < 1)
8615 vty_out(vty, "\n%*s", 36, " ");
8616 else
8617 vty_out(vty, "%*s", len, " ");
8618 }
8619 }
8620
8621 /* IPv6 Next Hop */
8622 else if (p->family == AF_INET6 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
8623 char buf[BUFSIZ];
8624
8625 if (json_paths) {
8626 json_nexthop_global = json_object_new_object();
8627 json_object_string_add(
8628 json_nexthop_global, "ip",
8629 inet_ntop(AF_INET6, &attr->mp_nexthop_global,
8630 buf, BUFSIZ));
8631
8632 if (path->peer->hostname)
8633 json_object_string_add(json_nexthop_global,
8634 "hostname",
8635 path->peer->hostname);
8636
8637 json_object_string_add(json_nexthop_global, "afi",
8638 "ipv6");
8639 json_object_string_add(json_nexthop_global, "scope",
8640 "global");
8641
8642 /* We display both LL & GL if both have been
8643 * received */
8644 if ((attr->mp_nexthop_len
8645 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
8646 || (path->peer->conf_if)) {
8647 json_nexthop_ll = json_object_new_object();
8648 json_object_string_add(
8649 json_nexthop_ll, "ip",
8650 inet_ntop(AF_INET6,
8651 &attr->mp_nexthop_local, buf,
8652 BUFSIZ));
8653
8654 if (path->peer->hostname)
8655 json_object_string_add(
8656 json_nexthop_ll, "hostname",
8657 path->peer->hostname);
8658
8659 json_object_string_add(json_nexthop_ll, "afi",
8660 "ipv6");
8661 json_object_string_add(json_nexthop_ll, "scope",
8662 "link-local");
8663
8664 if ((IPV6_ADDR_CMP(&attr->mp_nexthop_global,
8665 &attr->mp_nexthop_local)
8666 != 0)
8667 && !attr->mp_nexthop_prefer_global)
8668 json_object_boolean_true_add(
8669 json_nexthop_ll, "used");
8670 else
8671 json_object_boolean_true_add(
8672 json_nexthop_global, "used");
8673 } else
8674 json_object_boolean_true_add(
8675 json_nexthop_global, "used");
8676 } else {
8677 /* Display LL if LL/Global both in table unless
8678 * prefer-global is set */
8679 if (((attr->mp_nexthop_len
8680 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
8681 && !attr->mp_nexthop_prefer_global)
8682 || (path->peer->conf_if)) {
8683 if (path->peer->conf_if) {
8684 len = vty_out(vty, "%s",
8685 path->peer->conf_if);
8686 /* len of IPv6 addr + max len of def
8687 * ifname */
8688 len = wide ? (41 - len) : (16 - len);
8689
8690 if (len < 1)
8691 vty_out(vty, "\n%*s", 36, " ");
8692 else
8693 vty_out(vty, "%*s", len, " ");
8694 } else {
8695 if (nexthop_hostname)
8696 len = vty_out(
8697 vty, "%pI6(%s)%s",
8698 &attr->mp_nexthop_local,
8699 nexthop_hostname,
8700 vrf_id_str);
8701 else
8702 len = vty_out(
8703 vty, "%pI6%s",
8704 &attr->mp_nexthop_local,
8705 vrf_id_str);
8706
8707 len = wide ? (41 - len) : (16 - len);
8708
8709 if (len < 1)
8710 vty_out(vty, "\n%*s", 36, " ");
8711 else
8712 vty_out(vty, "%*s", len, " ");
8713 }
8714 } else {
8715 if (nexthop_hostname)
8716 len = vty_out(vty, "%pI6(%s)%s",
8717 &attr->mp_nexthop_global,
8718 nexthop_hostname,
8719 vrf_id_str);
8720 else
8721 len = vty_out(vty, "%pI6%s",
8722 &attr->mp_nexthop_global,
8723 vrf_id_str);
8724
8725 len = wide ? (41 - len) : (16 - len);
8726
8727 if (len < 1)
8728 vty_out(vty, "\n%*s", 36, " ");
8729 else
8730 vty_out(vty, "%*s", len, " ");
8731 }
8732 }
8733 }
8734
8735 /* MED/Metric */
8736 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
8737 if (json_paths)
8738 json_object_int_add(json_path, "metric", attr->med);
8739 else if (wide)
8740 vty_out(vty, "%7u", attr->med);
8741 else
8742 vty_out(vty, "%10u", attr->med);
8743 else if (!json_paths) {
8744 if (wide)
8745 vty_out(vty, "%*s", 7, " ");
8746 else
8747 vty_out(vty, "%*s", 10, " ");
8748 }
8749
8750 /* Local Pref */
8751 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
8752 if (json_paths)
8753 json_object_int_add(json_path, "locPrf",
8754 attr->local_pref);
8755 else
8756 vty_out(vty, "%7u", attr->local_pref);
8757 else if (!json_paths)
8758 vty_out(vty, " ");
8759
8760 if (json_paths)
8761 json_object_int_add(json_path, "weight", attr->weight);
8762 else
8763 vty_out(vty, "%7u ", attr->weight);
8764
8765 if (json_paths) {
8766 char buf[BUFSIZ];
8767 json_object_string_add(
8768 json_path, "peerId",
8769 sockunion2str(&path->peer->su, buf, SU_ADDRSTRLEN));
8770 }
8771
8772 /* Print aspath */
8773 if (attr->aspath) {
8774 if (json_paths)
8775 json_object_string_add(json_path, "path",
8776 attr->aspath->str);
8777 else
8778 aspath_print_vty(vty, "%s", attr->aspath, " ");
8779 }
8780
8781 /* Print origin */
8782 if (json_paths)
8783 json_object_string_add(json_path, "origin",
8784 bgp_origin_long_str[attr->origin]);
8785 else
8786 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
8787
8788 if (json_paths) {
8789 if (bgp_evpn_is_esi_valid(&attr->esi)) {
8790 json_object_string_add(json_path, "esi",
8791 esi_to_str(&attr->esi,
8792 esi_buf, sizeof(esi_buf)));
8793 }
8794 if (safi == SAFI_EVPN &&
8795 attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
8796 json_ext_community = json_object_new_object();
8797 json_object_string_add(json_ext_community,
8798 "string",
8799 attr->ecommunity->str);
8800 json_object_object_add(json_path,
8801 "extendedCommunity",
8802 json_ext_community);
8803 }
8804
8805 if (nexthop_self)
8806 json_object_boolean_true_add(json_path,
8807 "announceNexthopSelf");
8808 if (nexthop_othervrf) {
8809 json_object_string_add(json_path, "nhVrfName",
8810 nexthop_vrfname);
8811
8812 json_object_int_add(json_path, "nhVrfId",
8813 ((nexthop_vrfid == VRF_UNKNOWN)
8814 ? -1
8815 : (int)nexthop_vrfid));
8816 }
8817 }
8818
8819 if (json_paths) {
8820 if (json_nexthop_global || json_nexthop_ll) {
8821 json_nexthops = json_object_new_array();
8822
8823 if (json_nexthop_global)
8824 json_object_array_add(json_nexthops,
8825 json_nexthop_global);
8826
8827 if (json_nexthop_ll)
8828 json_object_array_add(json_nexthops,
8829 json_nexthop_ll);
8830
8831 json_object_object_add(json_path, "nexthops",
8832 json_nexthops);
8833 }
8834
8835 json_object_array_add(json_paths, json_path);
8836 } else {
8837 vty_out(vty, "\n");
8838
8839 if (safi == SAFI_EVPN) {
8840 struct bgp_path_es_info *path_es_info = NULL;
8841
8842 if (path->extra)
8843 path_es_info = path->extra->es_info;
8844
8845 if (bgp_evpn_is_esi_valid(&attr->esi)) {
8846 /* XXX - add these params to the json out */
8847 vty_out(vty, "%*s", 20, " ");
8848 vty_out(vty, "ESI:%s",
8849 esi_to_str(&attr->esi, esi_buf,
8850 sizeof(esi_buf)));
8851 if (path_es_info && path_es_info->es)
8852 vty_out(vty, " VNI: %u",
8853 path_es_info->vni);
8854 vty_out(vty, "\n");
8855 }
8856 if (attr->flag &
8857 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
8858 vty_out(vty, "%*s", 20, " ");
8859 vty_out(vty, "%s\n", attr->ecommunity->str);
8860 }
8861 }
8862
8863 #ifdef ENABLE_BGP_VNC
8864 /* prints an additional line, indented, with VNC info, if
8865 * present */
8866 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
8867 rfapi_vty_out_vncinfo(vty, p, path, safi);
8868 #endif
8869 }
8870 }
8871
8872 /* called from terminal list command */
8873 void route_vty_out_tmp(struct vty *vty, const struct prefix *p,
8874 struct attr *attr, safi_t safi, bool use_json,
8875 json_object *json_ar, bool wide)
8876 {
8877 json_object *json_status = NULL;
8878 json_object *json_net = NULL;
8879 int len;
8880 char buff[BUFSIZ];
8881
8882 /* Route status display. */
8883 if (use_json) {
8884 json_status = json_object_new_object();
8885 json_net = json_object_new_object();
8886 } else {
8887 vty_out(vty, "*");
8888 vty_out(vty, ">");
8889 vty_out(vty, " ");
8890 }
8891
8892 /* print prefix and mask */
8893 if (use_json) {
8894 if (safi == SAFI_EVPN)
8895 bgp_evpn_route2json((struct prefix_evpn *)p, json_net);
8896 else if (p->family == AF_INET || p->family == AF_INET6) {
8897 json_object_string_add(
8898 json_net, "addrPrefix",
8899 inet_ntop(p->family, &p->u.prefix, buff,
8900 BUFSIZ));
8901 json_object_int_add(json_net, "prefixLen",
8902 p->prefixlen);
8903 prefix2str(p, buff, PREFIX_STRLEN);
8904 json_object_string_add(json_net, "network", buff);
8905 }
8906 } else
8907 route_vty_out_route(p, vty, NULL, wide);
8908
8909 /* Print attribute */
8910 if (attr) {
8911 if (use_json) {
8912 char buf[BUFSIZ] = {0};
8913
8914 if (p->family == AF_INET
8915 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
8916 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
8917 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
8918 json_object_string_add(
8919 json_net, "nextHop",
8920 inet_ntop(
8921 AF_INET,
8922 &attr->mp_nexthop_global_in,
8923 buf, sizeof(buf)));
8924 else
8925 json_object_string_add(
8926 json_net, "nextHop",
8927 inet_ntop(AF_INET,
8928 &attr->nexthop, buf,
8929 sizeof(buf)));
8930 } else if (p->family == AF_INET6
8931 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
8932 char buf[BUFSIZ];
8933
8934 json_object_string_add(
8935 json_net, "nextHopGlobal",
8936 inet_ntop(AF_INET6,
8937 &attr->mp_nexthop_global, buf,
8938 BUFSIZ));
8939 } else if (p->family == AF_EVPN
8940 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
8941 char buf[BUFSIZ] = {0};
8942
8943 json_object_string_add(
8944 json_net, "nextHop",
8945 inet_ntop(AF_INET,
8946 &attr->mp_nexthop_global_in,
8947 buf, sizeof(buf)));
8948 }
8949
8950 if (attr->flag
8951 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
8952 json_object_int_add(json_net, "metric",
8953 attr->med);
8954
8955 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
8956 json_object_int_add(json_net, "locPrf",
8957 attr->local_pref);
8958
8959 json_object_int_add(json_net, "weight", attr->weight);
8960
8961 /* Print aspath */
8962 if (attr->aspath)
8963 json_object_string_add(json_net, "path",
8964 attr->aspath->str);
8965
8966 /* Print origin */
8967 json_object_string_add(json_net, "bgpOriginCode",
8968 bgp_origin_str[attr->origin]);
8969 } else {
8970 if (p->family == AF_INET
8971 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
8972 || safi == SAFI_EVPN
8973 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
8974 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
8975 || safi == SAFI_EVPN)
8976 vty_out(vty, "%-16pI4",
8977 &attr->mp_nexthop_global_in);
8978 else if (wide)
8979 vty_out(vty, "%-41pI4", &attr->nexthop);
8980 else
8981 vty_out(vty, "%-16pI4", &attr->nexthop);
8982 } else if (p->family == AF_INET6
8983 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
8984 char buf[BUFSIZ];
8985
8986 len = vty_out(
8987 vty, "%s",
8988 inet_ntop(AF_INET6,
8989 &attr->mp_nexthop_global, buf,
8990 BUFSIZ));
8991 len = wide ? (41 - len) : (16 - len);
8992 if (len < 1)
8993 vty_out(vty, "\n%*s", 36, " ");
8994 else
8995 vty_out(vty, "%*s", len, " ");
8996 }
8997 if (attr->flag
8998 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
8999 if (wide)
9000 vty_out(vty, "%7u", attr->med);
9001 else
9002 vty_out(vty, "%10u", attr->med);
9003 else if (wide)
9004 vty_out(vty, " ");
9005 else
9006 vty_out(vty, " ");
9007
9008 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
9009 vty_out(vty, "%7u", attr->local_pref);
9010 else
9011 vty_out(vty, " ");
9012
9013 vty_out(vty, "%7u ", attr->weight);
9014
9015 /* Print aspath */
9016 if (attr->aspath)
9017 aspath_print_vty(vty, "%s", attr->aspath, " ");
9018
9019 /* Print origin */
9020 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9021 }
9022 }
9023 if (use_json) {
9024 json_object_boolean_true_add(json_status, "*");
9025 json_object_boolean_true_add(json_status, ">");
9026 json_object_object_add(json_net, "appliedStatusSymbols",
9027 json_status);
9028
9029 prefix2str(p, buff, PREFIX_STRLEN);
9030 json_object_object_add(json_ar, buff, json_net);
9031 } else
9032 vty_out(vty, "\n");
9033 }
9034
9035 void route_vty_out_tag(struct vty *vty, const struct prefix *p,
9036 struct bgp_path_info *path, int display, safi_t safi,
9037 json_object *json)
9038 {
9039 json_object *json_out = NULL;
9040 struct attr *attr;
9041 mpls_label_t label = MPLS_INVALID_LABEL;
9042
9043 if (!path->extra)
9044 return;
9045
9046 if (json)
9047 json_out = json_object_new_object();
9048
9049 /* short status lead text */
9050 route_vty_short_status_out(vty, path, json_out);
9051
9052 /* print prefix and mask */
9053 if (json == NULL) {
9054 if (!display)
9055 route_vty_out_route(p, vty, NULL, false);
9056 else
9057 vty_out(vty, "%*s", 17, " ");
9058 }
9059
9060 /* Print attribute */
9061 attr = path->attr;
9062 if (((p->family == AF_INET)
9063 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
9064 || (safi == SAFI_EVPN && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))
9065 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
9066 char buf[BUFSIZ] = {0};
9067
9068 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9069 || safi == SAFI_EVPN) {
9070 if (json)
9071 json_object_string_add(
9072 json_out, "mpNexthopGlobalIn",
9073 inet_ntop(AF_INET,
9074 &attr->mp_nexthop_global_in,
9075 buf, sizeof(buf)));
9076 else
9077 vty_out(vty, "%-16pI4",
9078 &attr->mp_nexthop_global_in);
9079 } else {
9080 if (json)
9081 json_object_string_add(
9082 json_out, "nexthop",
9083 inet_ntop(AF_INET, &attr->nexthop, buf,
9084 sizeof(buf)));
9085 else
9086 vty_out(vty, "%-16pI4", &attr->nexthop);
9087 }
9088 } else if (((p->family == AF_INET6)
9089 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
9090 || (safi == SAFI_EVPN && BGP_ATTR_NEXTHOP_AFI_IP6(attr))
9091 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
9092 char buf_a[512];
9093
9094 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL) {
9095 if (json)
9096 json_object_string_add(
9097 json_out, "mpNexthopGlobalIn",
9098 inet_ntop(AF_INET6,
9099 &attr->mp_nexthop_global,
9100 buf_a, sizeof(buf_a)));
9101 else
9102 vty_out(vty, "%s",
9103 inet_ntop(AF_INET6,
9104 &attr->mp_nexthop_global,
9105 buf_a, sizeof(buf_a)));
9106 } else if (attr->mp_nexthop_len
9107 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
9108 snprintfrr(buf_a, sizeof(buf_a), "%pI6(%pI6)",
9109 &attr->mp_nexthop_global,
9110 &attr->mp_nexthop_local);
9111 if (json)
9112 json_object_string_add(json_out,
9113 "mpNexthopGlobalLocal",
9114 buf_a);
9115 else
9116 vty_out(vty, "%s", buf_a);
9117 }
9118 }
9119
9120 label = decode_label(&path->extra->label[0]);
9121
9122 if (bgp_is_valid_label(&label)) {
9123 if (json) {
9124 json_object_int_add(json_out, "notag", label);
9125 json_object_array_add(json, json_out);
9126 } else {
9127 vty_out(vty, "notag/%d", label);
9128 vty_out(vty, "\n");
9129 }
9130 }
9131 }
9132
9133 void route_vty_out_overlay(struct vty *vty, const struct prefix *p,
9134 struct bgp_path_info *path, int display,
9135 json_object *json_paths)
9136 {
9137 struct attr *attr;
9138 char buf[BUFSIZ] = {0};
9139 json_object *json_path = NULL;
9140 json_object *json_nexthop = NULL;
9141 json_object *json_overlay = NULL;
9142
9143 if (!path->extra)
9144 return;
9145
9146 if (json_paths) {
9147 json_path = json_object_new_object();
9148 json_overlay = json_object_new_object();
9149 json_nexthop = json_object_new_object();
9150 }
9151
9152 /* short status lead text */
9153 route_vty_short_status_out(vty, path, json_path);
9154
9155 /* print prefix and mask */
9156 if (!display)
9157 route_vty_out_route(p, vty, json_path, false);
9158 else
9159 vty_out(vty, "%*s", 17, " ");
9160
9161 /* Print attribute */
9162 attr = path->attr;
9163 char buf1[BUFSIZ];
9164 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
9165
9166 switch (af) {
9167 case AF_INET:
9168 inet_ntop(af, &attr->mp_nexthop_global_in, buf, BUFSIZ);
9169 if (!json_path) {
9170 vty_out(vty, "%-16s", buf);
9171 } else {
9172 json_object_string_add(json_nexthop, "ip", buf);
9173
9174 json_object_string_add(json_nexthop, "afi", "ipv4");
9175
9176 json_object_object_add(json_path, "nexthop",
9177 json_nexthop);
9178 }
9179 break;
9180 case AF_INET6:
9181 inet_ntop(af, &attr->mp_nexthop_global, buf, BUFSIZ);
9182 inet_ntop(af, &attr->mp_nexthop_local, buf1, BUFSIZ);
9183 if (!json_path) {
9184 vty_out(vty, "%s(%s)", buf, buf1);
9185 } else {
9186 json_object_string_add(json_nexthop, "ipv6Global", buf);
9187
9188 json_object_string_add(json_nexthop, "ipv6LinkLocal",
9189 buf1);
9190
9191 json_object_string_add(json_nexthop, "afi", "ipv6");
9192
9193 json_object_object_add(json_path, "nexthop",
9194 json_nexthop);
9195 }
9196 break;
9197 default:
9198 if (!json_path) {
9199 vty_out(vty, "?");
9200 } else {
9201 json_object_string_add(json_nexthop, "Error",
9202 "Unsupported address-family");
9203 }
9204 }
9205
9206 const struct bgp_route_evpn *eo = bgp_attr_get_evpn_overlay(attr);
9207
9208 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn *)p))
9209 inet_ntop(AF_INET, &eo->gw_ip.ipv4, buf, BUFSIZ);
9210 else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn *)p))
9211 inet_ntop(AF_INET6, &eo->gw_ip.ipv6, buf, BUFSIZ);
9212
9213 if (!json_path)
9214 vty_out(vty, "/%s", buf);
9215 else
9216 json_object_string_add(json_overlay, "gw", buf);
9217
9218 if (attr->ecommunity) {
9219 char *mac = NULL;
9220 struct ecommunity_val *routermac = ecommunity_lookup(
9221 attr->ecommunity, ECOMMUNITY_ENCODE_EVPN,
9222 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC);
9223
9224 if (routermac)
9225 mac = ecom_mac2str((char *)routermac->val);
9226 if (mac) {
9227 if (!json_path) {
9228 vty_out(vty, "/%s", mac);
9229 } else {
9230 json_object_string_add(json_overlay, "rmac",
9231 mac);
9232 }
9233 XFREE(MTYPE_TMP, mac);
9234 }
9235 }
9236
9237 if (!json_path) {
9238 vty_out(vty, "\n");
9239 } else {
9240 json_object_object_add(json_path, "overlay", json_overlay);
9241
9242 json_object_array_add(json_paths, json_path);
9243 }
9244 }
9245
9246 /* dampening route */
9247 static void damp_route_vty_out(struct vty *vty, const struct prefix *p,
9248 struct bgp_path_info *path, int display,
9249 afi_t afi, safi_t safi, bool use_json,
9250 json_object *json)
9251 {
9252 struct attr *attr;
9253 int len;
9254 char timebuf[BGP_UPTIME_LEN];
9255
9256 /* short status lead text */
9257 route_vty_short_status_out(vty, path, json);
9258
9259 /* print prefix and mask */
9260 if (!use_json) {
9261 if (!display)
9262 route_vty_out_route(p, vty, NULL, false);
9263 else
9264 vty_out(vty, "%*s", 17, " ");
9265 }
9266
9267 len = vty_out(vty, "%s", path->peer->host);
9268 len = 17 - len;
9269 if (len < 1) {
9270 if (!use_json)
9271 vty_out(vty, "\n%*s", 34, " ");
9272 } else {
9273 if (use_json)
9274 json_object_int_add(json, "peerHost", len);
9275 else
9276 vty_out(vty, "%*s", len, " ");
9277 }
9278
9279 if (use_json)
9280 bgp_damp_reuse_time_vty(vty, path, timebuf, BGP_UPTIME_LEN, afi,
9281 safi, use_json, json);
9282 else
9283 vty_out(vty, "%s ",
9284 bgp_damp_reuse_time_vty(vty, path, timebuf,
9285 BGP_UPTIME_LEN, afi, safi,
9286 use_json, json));
9287
9288 /* Print attribute */
9289 attr = path->attr;
9290
9291 /* Print aspath */
9292 if (attr->aspath) {
9293 if (use_json)
9294 json_object_string_add(json, "asPath",
9295 attr->aspath->str);
9296 else
9297 aspath_print_vty(vty, "%s", attr->aspath, " ");
9298 }
9299
9300 /* Print origin */
9301 if (use_json)
9302 json_object_string_add(json, "origin",
9303 bgp_origin_str[attr->origin]);
9304 else
9305 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9306
9307 if (!use_json)
9308 vty_out(vty, "\n");
9309 }
9310
9311 /* flap route */
9312 static void flap_route_vty_out(struct vty *vty, const struct prefix *p,
9313 struct bgp_path_info *path, int display,
9314 afi_t afi, safi_t safi, bool use_json,
9315 json_object *json)
9316 {
9317 struct attr *attr;
9318 struct bgp_damp_info *bdi;
9319 char timebuf[BGP_UPTIME_LEN];
9320 int len;
9321
9322 if (!path->extra)
9323 return;
9324
9325 bdi = path->extra->damp_info;
9326
9327 /* short status lead text */
9328 route_vty_short_status_out(vty, path, json);
9329
9330 /* print prefix and mask */
9331 if (!use_json) {
9332 if (!display)
9333 route_vty_out_route(p, vty, NULL, false);
9334 else
9335 vty_out(vty, "%*s", 17, " ");
9336 }
9337
9338 len = vty_out(vty, "%s", path->peer->host);
9339 len = 16 - len;
9340 if (len < 1) {
9341 if (!use_json)
9342 vty_out(vty, "\n%*s", 33, " ");
9343 } else {
9344 if (use_json)
9345 json_object_int_add(json, "peerHost", len);
9346 else
9347 vty_out(vty, "%*s", len, " ");
9348 }
9349
9350 len = vty_out(vty, "%d", bdi->flap);
9351 len = 5 - len;
9352 if (len < 1) {
9353 if (!use_json)
9354 vty_out(vty, " ");
9355 } else {
9356 if (use_json)
9357 json_object_int_add(json, "bdiFlap", len);
9358 else
9359 vty_out(vty, "%*s", len, " ");
9360 }
9361
9362 if (use_json)
9363 peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, use_json,
9364 json);
9365 else
9366 vty_out(vty, "%s ", peer_uptime(bdi->start_time, timebuf,
9367 BGP_UPTIME_LEN, 0, NULL));
9368
9369 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
9370 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
9371 if (use_json)
9372 bgp_damp_reuse_time_vty(vty, path, timebuf,
9373 BGP_UPTIME_LEN, afi, safi,
9374 use_json, json);
9375 else
9376 vty_out(vty, "%s ",
9377 bgp_damp_reuse_time_vty(vty, path, timebuf,
9378 BGP_UPTIME_LEN, afi,
9379 safi, use_json, json));
9380 } else {
9381 if (!use_json)
9382 vty_out(vty, "%*s ", 8, " ");
9383 }
9384
9385 /* Print attribute */
9386 attr = path->attr;
9387
9388 /* Print aspath */
9389 if (attr->aspath) {
9390 if (use_json)
9391 json_object_string_add(json, "asPath",
9392 attr->aspath->str);
9393 else
9394 aspath_print_vty(vty, "%s", attr->aspath, " ");
9395 }
9396
9397 /* Print origin */
9398 if (use_json)
9399 json_object_string_add(json, "origin",
9400 bgp_origin_str[attr->origin]);
9401 else
9402 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9403
9404 if (!use_json)
9405 vty_out(vty, "\n");
9406 }
9407
9408 static void route_vty_out_advertised_to(struct vty *vty, struct peer *peer,
9409 int *first, const char *header,
9410 json_object *json_adv_to)
9411 {
9412 char buf1[INET6_ADDRSTRLEN];
9413 json_object *json_peer = NULL;
9414
9415 if (json_adv_to) {
9416 /* 'advertised-to' is a dictionary of peers we have advertised
9417 * this
9418 * prefix too. The key is the peer's IP or swpX, the value is
9419 * the
9420 * hostname if we know it and "" if not.
9421 */
9422 json_peer = json_object_new_object();
9423
9424 if (peer->hostname)
9425 json_object_string_add(json_peer, "hostname",
9426 peer->hostname);
9427
9428 if (peer->conf_if)
9429 json_object_object_add(json_adv_to, peer->conf_if,
9430 json_peer);
9431 else
9432 json_object_object_add(
9433 json_adv_to,
9434 sockunion2str(&peer->su, buf1, SU_ADDRSTRLEN),
9435 json_peer);
9436 } else {
9437 if (*first) {
9438 vty_out(vty, "%s", header);
9439 *first = 0;
9440 }
9441
9442 if (peer->hostname
9443 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
9444 if (peer->conf_if)
9445 vty_out(vty, " %s(%s)", peer->hostname,
9446 peer->conf_if);
9447 else
9448 vty_out(vty, " %s(%s)", peer->hostname,
9449 sockunion2str(&peer->su, buf1,
9450 SU_ADDRSTRLEN));
9451 } else {
9452 if (peer->conf_if)
9453 vty_out(vty, " %s", peer->conf_if);
9454 else
9455 vty_out(vty, " %s",
9456 sockunion2str(&peer->su, buf1,
9457 SU_ADDRSTRLEN));
9458 }
9459 }
9460 }
9461
9462 static void route_vty_out_tx_ids(struct vty *vty,
9463 struct bgp_addpath_info_data *d)
9464 {
9465 int i;
9466
9467 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
9468 vty_out(vty, "TX-%s %u%s", bgp_addpath_names(i)->human_name,
9469 d->addpath_tx_id[i],
9470 i < BGP_ADDPATH_MAX - 1 ? " " : "\n");
9471 }
9472 }
9473
9474 static void route_vty_out_detail_es_info(struct vty *vty,
9475 struct bgp_path_info *pi,
9476 struct attr *attr,
9477 json_object *json_path)
9478 {
9479 char esi_buf[ESI_STR_LEN];
9480 bool es_local = !!CHECK_FLAG(attr->es_flags, ATTR_ES_IS_LOCAL);
9481 bool peer_router = !!CHECK_FLAG(attr->es_flags,
9482 ATTR_ES_PEER_ROUTER);
9483 bool peer_active = !!CHECK_FLAG(attr->es_flags,
9484 ATTR_ES_PEER_ACTIVE);
9485 bool peer_proxy = !!CHECK_FLAG(attr->es_flags,
9486 ATTR_ES_PEER_PROXY);
9487 esi_to_str(&attr->esi, esi_buf, sizeof(esi_buf));
9488 if (json_path) {
9489 json_object *json_es_info = NULL;
9490
9491 json_object_string_add(
9492 json_path, "esi",
9493 esi_buf);
9494 if (es_local || bgp_evpn_attr_is_sync(attr)) {
9495 json_es_info = json_object_new_object();
9496 if (es_local)
9497 json_object_boolean_true_add(
9498 json_es_info, "localEs");
9499 if (peer_active)
9500 json_object_boolean_true_add(
9501 json_es_info, "peerActive");
9502 if (peer_proxy)
9503 json_object_boolean_true_add(
9504 json_es_info, "peerProxy");
9505 if (peer_router)
9506 json_object_boolean_true_add(
9507 json_es_info, "peerRouter");
9508 if (attr->mm_sync_seqnum)
9509 json_object_int_add(
9510 json_es_info, "peerSeq",
9511 attr->mm_sync_seqnum);
9512 json_object_object_add(
9513 json_path, "es_info",
9514 json_es_info);
9515 }
9516 } else {
9517 if (bgp_evpn_attr_is_sync(attr))
9518 vty_out(vty,
9519 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
9520 esi_buf,
9521 es_local ? "local-es":"",
9522 peer_proxy ? "proxy " : "",
9523 peer_active ? "active ":"",
9524 peer_router ? "router ":"",
9525 attr->mm_sync_seqnum);
9526 else
9527 vty_out(vty, " ESI %s %s\n",
9528 esi_buf,
9529 es_local ? "local-es":"");
9530 }
9531 }
9532
9533 void route_vty_out_detail(struct vty *vty, struct bgp *bgp,
9534 struct bgp_dest *bn, struct bgp_path_info *path,
9535 afi_t afi, safi_t safi, json_object *json_paths)
9536 {
9537 char buf[INET6_ADDRSTRLEN];
9538 char buf1[BUFSIZ];
9539 struct attr *attr = path->attr;
9540 int sockunion_vty_out(struct vty *, union sockunion *);
9541 time_t tbuf;
9542 json_object *json_bestpath = NULL;
9543 json_object *json_cluster_list = NULL;
9544 json_object *json_cluster_list_list = NULL;
9545 json_object *json_ext_community = NULL;
9546 json_object *json_last_update = NULL;
9547 json_object *json_pmsi = NULL;
9548 json_object *json_nexthop_global = NULL;
9549 json_object *json_nexthop_ll = NULL;
9550 json_object *json_nexthops = NULL;
9551 json_object *json_path = NULL;
9552 json_object *json_peer = NULL;
9553 json_object *json_string = NULL;
9554 json_object *json_adv_to = NULL;
9555 int first = 0;
9556 struct listnode *node, *nnode;
9557 struct peer *peer;
9558 int addpath_capable;
9559 int has_adj;
9560 unsigned int first_as;
9561 bool nexthop_self =
9562 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
9563 int i;
9564 char *nexthop_hostname =
9565 bgp_nexthop_hostname(path->peer, path->nexthop);
9566
9567 if (json_paths) {
9568 json_path = json_object_new_object();
9569 json_peer = json_object_new_object();
9570 json_nexthop_global = json_object_new_object();
9571 }
9572
9573 if (path->extra) {
9574 char tag_buf[30];
9575
9576 tag_buf[0] = '\0';
9577 if (path->extra && path->extra->num_labels) {
9578 bgp_evpn_label2str(path->extra->label,
9579 path->extra->num_labels, tag_buf,
9580 sizeof(tag_buf));
9581 }
9582 if (safi == SAFI_EVPN) {
9583 if (!json_paths) {
9584 vty_out(vty, " Route %pFX",
9585 (struct prefix_evpn *)
9586 bgp_dest_get_prefix(bn));
9587 if (tag_buf[0] != '\0')
9588 vty_out(vty, " VNI %s", tag_buf);
9589 vty_out(vty, "\n");
9590 } else {
9591 if (tag_buf[0])
9592 json_object_string_add(json_path, "VNI",
9593 tag_buf);
9594 }
9595 }
9596
9597 if (path->extra && path->extra->parent && !json_paths) {
9598 struct bgp_path_info *parent_ri;
9599 struct bgp_dest *dest, *pdest;
9600
9601 parent_ri = (struct bgp_path_info *)path->extra->parent;
9602 dest = parent_ri->net;
9603 if (dest && dest->pdest) {
9604 pdest = dest->pdest;
9605 prefix_rd2str(
9606 (struct prefix_rd *)bgp_dest_get_prefix(
9607 pdest),
9608 buf1, sizeof(buf1));
9609 if (is_pi_family_evpn(parent_ri)) {
9610 vty_out(vty,
9611 " Imported from %s:%pFX, VNI %s\n",
9612 buf1,
9613 (struct prefix_evpn *)
9614 bgp_dest_get_prefix(
9615 dest),
9616 tag_buf);
9617 } else
9618 vty_out(vty,
9619 " Imported from %s:%pFX\n",
9620 buf1,
9621 (struct prefix_evpn *)
9622 bgp_dest_get_prefix(
9623 dest));
9624 }
9625 }
9626 }
9627
9628 /* Line1 display AS-path, Aggregator */
9629 if (attr->aspath) {
9630 if (json_paths) {
9631 if (!attr->aspath->json)
9632 aspath_str_update(attr->aspath, true);
9633 json_object_lock(attr->aspath->json);
9634 json_object_object_add(json_path, "aspath",
9635 attr->aspath->json);
9636 } else {
9637 if (attr->aspath->segments)
9638 aspath_print_vty(vty, " %s", attr->aspath, "");
9639 else
9640 vty_out(vty, " Local");
9641 }
9642 }
9643
9644 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED)) {
9645 if (json_paths)
9646 json_object_boolean_true_add(json_path, "removed");
9647 else
9648 vty_out(vty, ", (removed)");
9649 }
9650
9651 if (CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
9652 if (json_paths)
9653 json_object_boolean_true_add(json_path, "stale");
9654 else
9655 vty_out(vty, ", (stale)");
9656 }
9657
9658 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
9659 if (json_paths) {
9660 char buf[BUFSIZ] = {0};
9661
9662 json_object_int_add(json_path, "aggregatorAs",
9663 attr->aggregator_as);
9664 json_object_string_add(json_path, "aggregatorId",
9665 inet_ntop(AF_INET,
9666 &attr->aggregator_addr,
9667 buf, sizeof(buf)));
9668 } else {
9669 vty_out(vty, ", (aggregated by %u %pI4)",
9670 attr->aggregator_as, &attr->aggregator_addr);
9671 }
9672 }
9673
9674 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
9675 PEER_FLAG_REFLECTOR_CLIENT)) {
9676 if (json_paths)
9677 json_object_boolean_true_add(json_path,
9678 "rxedFromRrClient");
9679 else
9680 vty_out(vty, ", (Received from a RR-client)");
9681 }
9682
9683 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
9684 PEER_FLAG_RSERVER_CLIENT)) {
9685 if (json_paths)
9686 json_object_boolean_true_add(json_path,
9687 "rxedFromRsClient");
9688 else
9689 vty_out(vty, ", (Received from a RS-client)");
9690 }
9691
9692 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
9693 if (json_paths)
9694 json_object_boolean_true_add(json_path,
9695 "dampeningHistoryEntry");
9696 else
9697 vty_out(vty, ", (history entry)");
9698 } else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)) {
9699 if (json_paths)
9700 json_object_boolean_true_add(json_path,
9701 "dampeningSuppressed");
9702 else
9703 vty_out(vty, ", (suppressed due to dampening)");
9704 }
9705
9706 if (!json_paths)
9707 vty_out(vty, "\n");
9708
9709 /* Line2 display Next-hop, Neighbor, Router-id */
9710 /* Display the nexthop */
9711 const struct prefix *bn_p = bgp_dest_get_prefix(bn);
9712
9713 if ((bn_p->family == AF_INET || bn_p->family == AF_ETHERNET
9714 || bn_p->family == AF_EVPN)
9715 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN
9716 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
9717 char buf[BUFSIZ] = {0};
9718
9719 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9720 || safi == SAFI_EVPN) {
9721 if (json_paths) {
9722 json_object_string_add(
9723 json_nexthop_global, "ip",
9724 inet_ntop(AF_INET,
9725 &attr->mp_nexthop_global_in,
9726 buf, sizeof(buf)));
9727
9728 if (path->peer->hostname)
9729 json_object_string_add(
9730 json_nexthop_global, "hostname",
9731 path->peer->hostname);
9732 } else {
9733 if (nexthop_hostname)
9734 vty_out(vty, " %pI4(%s)",
9735 &attr->mp_nexthop_global_in,
9736 nexthop_hostname);
9737 else
9738 vty_out(vty, " %pI4",
9739 &attr->mp_nexthop_global_in);
9740 }
9741 } else {
9742 if (json_paths) {
9743 json_object_string_add(
9744 json_nexthop_global, "ip",
9745 inet_ntop(AF_INET, &attr->nexthop, buf,
9746 sizeof(buf)));
9747
9748 if (path->peer->hostname)
9749 json_object_string_add(
9750 json_nexthop_global, "hostname",
9751 path->peer->hostname);
9752 } else {
9753 if (nexthop_hostname)
9754 vty_out(vty, " %pI4(%s)",
9755 &attr->nexthop,
9756 nexthop_hostname);
9757 else
9758 vty_out(vty, " %pI4",
9759 &attr->nexthop);
9760 }
9761 }
9762
9763 if (json_paths)
9764 json_object_string_add(json_nexthop_global, "afi",
9765 "ipv4");
9766 } else {
9767 if (json_paths) {
9768 json_object_string_add(
9769 json_nexthop_global, "ip",
9770 inet_ntop(AF_INET6, &attr->mp_nexthop_global,
9771 buf, INET6_ADDRSTRLEN));
9772
9773 if (path->peer->hostname)
9774 json_object_string_add(json_nexthop_global,
9775 "hostname",
9776 path->peer->hostname);
9777
9778 json_object_string_add(json_nexthop_global, "afi",
9779 "ipv6");
9780 json_object_string_add(json_nexthop_global, "scope",
9781 "global");
9782 } else {
9783 if (nexthop_hostname)
9784 vty_out(vty, " %pI6(%s)",
9785 &attr->mp_nexthop_global,
9786 nexthop_hostname);
9787 else
9788 vty_out(vty, " %pI6",
9789 &attr->mp_nexthop_global);
9790 }
9791 }
9792
9793 /* Display the IGP cost or 'inaccessible' */
9794 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
9795 if (json_paths)
9796 json_object_boolean_false_add(json_nexthop_global,
9797 "accessible");
9798 else
9799 vty_out(vty, " (inaccessible)");
9800 } else {
9801 if (path->extra && path->extra->igpmetric) {
9802 if (json_paths)
9803 json_object_int_add(json_nexthop_global,
9804 "metric",
9805 path->extra->igpmetric);
9806 else
9807 vty_out(vty, " (metric %u)",
9808 path->extra->igpmetric);
9809 }
9810
9811 /* IGP cost is 0, display this only for json */
9812 else {
9813 if (json_paths)
9814 json_object_int_add(json_nexthop_global,
9815 "metric", 0);
9816 }
9817
9818 if (json_paths)
9819 json_object_boolean_true_add(json_nexthop_global,
9820 "accessible");
9821 }
9822
9823 /* Display peer "from" output */
9824 /* This path was originated locally */
9825 if (path->peer == bgp->peer_self) {
9826
9827 if (safi == SAFI_EVPN
9828 || (bn_p->family == AF_INET
9829 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
9830 if (json_paths)
9831 json_object_string_add(json_peer, "peerId",
9832 "0.0.0.0");
9833 else
9834 vty_out(vty, " from 0.0.0.0 ");
9835 } else {
9836 if (json_paths)
9837 json_object_string_add(json_peer, "peerId",
9838 "::");
9839 else
9840 vty_out(vty, " from :: ");
9841 }
9842
9843 if (json_paths) {
9844 char buf[BUFSIZ] = {0};
9845
9846 json_object_string_add(json_peer, "routerId",
9847 inet_ntop(AF_INET,
9848 &bgp->router_id, buf,
9849 sizeof(buf)));
9850 } else {
9851 vty_out(vty, "(%pI4)", &bgp->router_id);
9852 }
9853 }
9854
9855 /* We RXed this path from one of our peers */
9856 else {
9857
9858 if (json_paths) {
9859 json_object_string_add(json_peer, "peerId",
9860 sockunion2str(&path->peer->su,
9861 buf,
9862 SU_ADDRSTRLEN));
9863 json_object_string_add(json_peer, "routerId",
9864 inet_ntop(AF_INET,
9865 &path->peer->remote_id,
9866 buf1, sizeof(buf1)));
9867
9868 if (path->peer->hostname)
9869 json_object_string_add(json_peer, "hostname",
9870 path->peer->hostname);
9871
9872 if (path->peer->domainname)
9873 json_object_string_add(json_peer, "domainname",
9874 path->peer->domainname);
9875
9876 if (path->peer->conf_if)
9877 json_object_string_add(json_peer, "interface",
9878 path->peer->conf_if);
9879 } else {
9880 if (path->peer->conf_if) {
9881 if (path->peer->hostname
9882 && CHECK_FLAG(path->peer->bgp->flags,
9883 BGP_FLAG_SHOW_HOSTNAME))
9884 vty_out(vty, " from %s(%s)",
9885 path->peer->hostname,
9886 path->peer->conf_if);
9887 else
9888 vty_out(vty, " from %s",
9889 path->peer->conf_if);
9890 } else {
9891 if (path->peer->hostname
9892 && CHECK_FLAG(path->peer->bgp->flags,
9893 BGP_FLAG_SHOW_HOSTNAME))
9894 vty_out(vty, " from %s(%s)",
9895 path->peer->hostname,
9896 path->peer->host);
9897 else
9898 vty_out(vty, " from %s",
9899 sockunion2str(&path->peer->su,
9900 buf,
9901 SU_ADDRSTRLEN));
9902 }
9903
9904 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
9905 vty_out(vty, " (%pI4)", &attr->originator_id);
9906 else
9907 vty_out(vty, " (%s)",
9908 inet_ntop(AF_INET,
9909 &path->peer->remote_id, buf1,
9910 sizeof(buf1)));
9911 }
9912 }
9913
9914 /*
9915 * Note when vrfid of nexthop is different from that of prefix
9916 */
9917 if (path->extra && path->extra->bgp_orig) {
9918 vrf_id_t nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9919
9920 if (json_paths) {
9921 const char *vn;
9922
9923 if (path->extra->bgp_orig->inst_type
9924 == BGP_INSTANCE_TYPE_DEFAULT)
9925 vn = VRF_DEFAULT_NAME;
9926 else
9927 vn = path->extra->bgp_orig->name;
9928
9929 json_object_string_add(json_path, "nhVrfName", vn);
9930
9931 if (nexthop_vrfid == VRF_UNKNOWN) {
9932 json_object_int_add(json_path, "nhVrfId", -1);
9933 } else {
9934 json_object_int_add(json_path, "nhVrfId",
9935 (int)nexthop_vrfid);
9936 }
9937 } else {
9938 if (nexthop_vrfid == VRF_UNKNOWN)
9939 vty_out(vty, " vrf ?");
9940 else {
9941 struct vrf *vrf;
9942
9943 vrf = vrf_lookup_by_id(nexthop_vrfid);
9944 vty_out(vty, " vrf %s(%u)",
9945 VRF_LOGNAME(vrf), nexthop_vrfid);
9946 }
9947 }
9948 }
9949
9950 if (nexthop_self) {
9951 if (json_paths) {
9952 json_object_boolean_true_add(json_path,
9953 "announceNexthopSelf");
9954 } else {
9955 vty_out(vty, " announce-nh-self");
9956 }
9957 }
9958
9959 if (!json_paths)
9960 vty_out(vty, "\n");
9961
9962 /* display the link-local nexthop */
9963 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
9964 if (json_paths) {
9965 json_nexthop_ll = json_object_new_object();
9966 json_object_string_add(
9967 json_nexthop_ll, "ip",
9968 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
9969 buf, INET6_ADDRSTRLEN));
9970
9971 if (path->peer->hostname)
9972 json_object_string_add(json_nexthop_ll,
9973 "hostname",
9974 path->peer->hostname);
9975
9976 json_object_string_add(json_nexthop_ll, "afi", "ipv6");
9977 json_object_string_add(json_nexthop_ll, "scope",
9978 "link-local");
9979
9980 json_object_boolean_true_add(json_nexthop_ll,
9981 "accessible");
9982
9983 if (!attr->mp_nexthop_prefer_global)
9984 json_object_boolean_true_add(json_nexthop_ll,
9985 "used");
9986 else
9987 json_object_boolean_true_add(
9988 json_nexthop_global, "used");
9989 } else {
9990 vty_out(vty, " (%s) %s\n",
9991 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
9992 buf, INET6_ADDRSTRLEN),
9993 attr->mp_nexthop_prefer_global
9994 ? "(prefer-global)"
9995 : "(used)");
9996 }
9997 }
9998 /* If we do not have a link-local nexthop then we must flag the
9999 global as "used" */
10000 else {
10001 if (json_paths)
10002 json_object_boolean_true_add(json_nexthop_global,
10003 "used");
10004 }
10005
10006 if (safi == SAFI_EVPN &&
10007 bgp_evpn_is_esi_valid(&attr->esi)) {
10008 route_vty_out_detail_es_info(vty, path, attr, json_path);
10009 }
10010
10011 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
10012 * Int/Ext/Local, Atomic, best */
10013 if (json_paths)
10014 json_object_string_add(json_path, "origin",
10015 bgp_origin_long_str[attr->origin]);
10016 else
10017 vty_out(vty, " Origin %s",
10018 bgp_origin_long_str[attr->origin]);
10019
10020 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
10021 if (json_paths)
10022 json_object_int_add(json_path, "metric", attr->med);
10023 else
10024 vty_out(vty, ", metric %u", attr->med);
10025 }
10026
10027 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
10028 if (json_paths)
10029 json_object_int_add(json_path, "locPrf",
10030 attr->local_pref);
10031 else
10032 vty_out(vty, ", localpref %u", attr->local_pref);
10033 }
10034
10035 if (attr->weight != 0) {
10036 if (json_paths)
10037 json_object_int_add(json_path, "weight", attr->weight);
10038 else
10039 vty_out(vty, ", weight %u", attr->weight);
10040 }
10041
10042 if (attr->tag != 0) {
10043 if (json_paths)
10044 json_object_int_add(json_path, "tag", attr->tag);
10045 else
10046 vty_out(vty, ", tag %" ROUTE_TAG_PRI, attr->tag);
10047 }
10048
10049 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
10050 if (json_paths)
10051 json_object_boolean_false_add(json_path, "valid");
10052 else
10053 vty_out(vty, ", invalid");
10054 } else if (!CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
10055 if (json_paths)
10056 json_object_boolean_true_add(json_path, "valid");
10057 else
10058 vty_out(vty, ", valid");
10059 }
10060
10061 if (path->peer != bgp->peer_self) {
10062 if (path->peer->as == path->peer->local_as) {
10063 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
10064 if (json_paths)
10065 json_object_string_add(
10066 json_peer, "type",
10067 "confed-internal");
10068 else
10069 vty_out(vty, ", confed-internal");
10070 } else {
10071 if (json_paths)
10072 json_object_string_add(
10073 json_peer, "type", "internal");
10074 else
10075 vty_out(vty, ", internal");
10076 }
10077 } else {
10078 if (bgp_confederation_peers_check(bgp,
10079 path->peer->as)) {
10080 if (json_paths)
10081 json_object_string_add(
10082 json_peer, "type",
10083 "confed-external");
10084 else
10085 vty_out(vty, ", confed-external");
10086 } else {
10087 if (json_paths)
10088 json_object_string_add(
10089 json_peer, "type", "external");
10090 else
10091 vty_out(vty, ", external");
10092 }
10093 }
10094 } else if (path->sub_type == BGP_ROUTE_AGGREGATE) {
10095 if (json_paths) {
10096 json_object_boolean_true_add(json_path, "aggregated");
10097 json_object_boolean_true_add(json_path, "local");
10098 } else {
10099 vty_out(vty, ", aggregated, local");
10100 }
10101 } else if (path->type != ZEBRA_ROUTE_BGP) {
10102 if (json_paths)
10103 json_object_boolean_true_add(json_path, "sourced");
10104 else
10105 vty_out(vty, ", sourced");
10106 } else {
10107 if (json_paths) {
10108 json_object_boolean_true_add(json_path, "sourced");
10109 json_object_boolean_true_add(json_path, "local");
10110 } else {
10111 vty_out(vty, ", sourced, local");
10112 }
10113 }
10114
10115 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
10116 if (json_paths)
10117 json_object_boolean_true_add(json_path,
10118 "atomicAggregate");
10119 else
10120 vty_out(vty, ", atomic-aggregate");
10121 }
10122
10123 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH)
10124 || (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)
10125 && bgp_path_info_mpath_count(path))) {
10126 if (json_paths)
10127 json_object_boolean_true_add(json_path, "multipath");
10128 else
10129 vty_out(vty, ", multipath");
10130 }
10131
10132 // Mark the bestpath(s)
10133 if (CHECK_FLAG(path->flags, BGP_PATH_DMED_SELECTED)) {
10134 first_as = aspath_get_first_as(attr->aspath);
10135
10136 if (json_paths) {
10137 if (!json_bestpath)
10138 json_bestpath = json_object_new_object();
10139 json_object_int_add(json_bestpath, "bestpathFromAs",
10140 first_as);
10141 } else {
10142 if (first_as)
10143 vty_out(vty, ", bestpath-from-AS %u", first_as);
10144 else
10145 vty_out(vty, ", bestpath-from-AS Local");
10146 }
10147 }
10148
10149 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
10150 if (json_paths) {
10151 if (!json_bestpath)
10152 json_bestpath = json_object_new_object();
10153 json_object_boolean_true_add(json_bestpath, "overall");
10154 json_object_string_add(
10155 json_bestpath, "selectionReason",
10156 bgp_path_selection_reason2str(bn->reason));
10157 } else {
10158 vty_out(vty, ", best");
10159 vty_out(vty, " (%s)",
10160 bgp_path_selection_reason2str(bn->reason));
10161 }
10162 }
10163
10164 if (json_bestpath)
10165 json_object_object_add(json_path, "bestpath", json_bestpath);
10166
10167 if (!json_paths)
10168 vty_out(vty, "\n");
10169
10170 /* Line 4 display Community */
10171 if (attr->community) {
10172 if (json_paths) {
10173 if (!attr->community->json)
10174 community_str(attr->community, true);
10175 json_object_lock(attr->community->json);
10176 json_object_object_add(json_path, "community",
10177 attr->community->json);
10178 } else {
10179 vty_out(vty, " Community: %s\n",
10180 attr->community->str);
10181 }
10182 }
10183
10184 /* Line 5 display Extended-community */
10185 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
10186 if (json_paths) {
10187 json_ext_community = json_object_new_object();
10188 json_object_string_add(json_ext_community, "string",
10189 attr->ecommunity->str);
10190 json_object_object_add(json_path, "extendedCommunity",
10191 json_ext_community);
10192 } else {
10193 vty_out(vty, " Extended Community: %s\n",
10194 attr->ecommunity->str);
10195 }
10196 }
10197
10198 /* Line 6 display Large community */
10199 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
10200 if (json_paths) {
10201 if (!attr->lcommunity->json)
10202 lcommunity_str(attr->lcommunity, true);
10203 json_object_lock(attr->lcommunity->json);
10204 json_object_object_add(json_path, "largeCommunity",
10205 attr->lcommunity->json);
10206 } else {
10207 vty_out(vty, " Large Community: %s\n",
10208 attr->lcommunity->str);
10209 }
10210 }
10211
10212 /* Line 7 display Originator, Cluster-id */
10213 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
10214 || (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) {
10215 char buf[BUFSIZ] = {0};
10216
10217 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) {
10218 if (json_paths)
10219 json_object_string_add(
10220 json_path, "originatorId",
10221 inet_ntop(AF_INET, &attr->originator_id,
10222 buf, sizeof(buf)));
10223 else
10224 vty_out(vty, " Originator: %pI4",
10225 &attr->originator_id);
10226 }
10227
10228 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) {
10229 struct cluster_list *cluster =
10230 bgp_attr_get_cluster(attr);
10231 int i;
10232
10233 if (json_paths) {
10234 json_cluster_list = json_object_new_object();
10235 json_cluster_list_list =
10236 json_object_new_array();
10237
10238 for (i = 0; i < cluster->length / 4; i++) {
10239 json_string = json_object_new_string(
10240 inet_ntop(AF_INET,
10241 &cluster->list[i],
10242 buf, sizeof(buf)));
10243 json_object_array_add(
10244 json_cluster_list_list,
10245 json_string);
10246 }
10247
10248 /*
10249 * struct cluster_list does not have
10250 * "str" variable like aspath and community
10251 * do. Add this someday if someone asks
10252 * for it.
10253 * json_object_string_add(json_cluster_list,
10254 * "string", cluster->str);
10255 */
10256 json_object_object_add(json_cluster_list,
10257 "list",
10258 json_cluster_list_list);
10259 json_object_object_add(json_path, "clusterList",
10260 json_cluster_list);
10261 } else {
10262 vty_out(vty, ", Cluster list: ");
10263
10264 for (i = 0; i < cluster->length / 4; i++) {
10265 vty_out(vty, "%pI4 ",
10266 &cluster->list[i]);
10267 }
10268 }
10269 }
10270
10271 if (!json_paths)
10272 vty_out(vty, "\n");
10273 }
10274
10275 if (path->extra && path->extra->damp_info)
10276 bgp_damp_info_vty(vty, bgp, path, afi, safi, json_path);
10277
10278 /* Remote Label */
10279 if (path->extra && bgp_is_valid_label(&path->extra->label[0])
10280 && (safi != SAFI_EVPN && !is_route_parent_evpn(path))) {
10281 mpls_label_t label = label_pton(&path->extra->label[0]);
10282
10283 if (json_paths)
10284 json_object_int_add(json_path, "remoteLabel", label);
10285 else
10286 vty_out(vty, " Remote label: %d\n", label);
10287 }
10288
10289 /* Remote SID */
10290 if (path->extra && path->extra->num_sids > 0 && safi != SAFI_EVPN) {
10291 inet_ntop(AF_INET6, &path->extra->sid, buf, sizeof(buf));
10292 if (json_paths)
10293 json_object_string_add(json_path, "remoteSid", buf);
10294 else
10295 vty_out(vty, " Remote SID: %s\n", buf);
10296 }
10297
10298 /* Label Index */
10299 if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
10300 if (json_paths)
10301 json_object_int_add(json_path, "labelIndex",
10302 attr->label_index);
10303 else
10304 vty_out(vty, " Label Index: %d\n",
10305 attr->label_index);
10306 }
10307
10308 /* Line 8 display Addpath IDs */
10309 if (path->addpath_rx_id
10310 || bgp_addpath_info_has_ids(&path->tx_addpath)) {
10311 if (json_paths) {
10312 json_object_int_add(json_path, "addpathRxId",
10313 path->addpath_rx_id);
10314
10315 /* Keep backwards compatibility with the old API
10316 * by putting TX All's ID in the old field
10317 */
10318 json_object_int_add(
10319 json_path, "addpathTxId",
10320 path->tx_addpath
10321 .addpath_tx_id[BGP_ADDPATH_ALL]);
10322
10323 /* ... but create a specific field for each
10324 * strategy
10325 */
10326 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
10327 json_object_int_add(
10328 json_path,
10329 bgp_addpath_names(i)->id_json_name,
10330 path->tx_addpath.addpath_tx_id[i]);
10331 }
10332 } else {
10333 vty_out(vty, " AddPath ID: RX %u, ",
10334 path->addpath_rx_id);
10335
10336 route_vty_out_tx_ids(vty, &path->tx_addpath);
10337 }
10338 }
10339
10340 /* If we used addpath to TX a non-bestpath we need to display
10341 * "Advertised to" on a path-by-path basis
10342 */
10343 if (bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
10344 first = 1;
10345
10346 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
10347 addpath_capable =
10348 bgp_addpath_encode_tx(peer, afi, safi);
10349 has_adj = bgp_adj_out_lookup(
10350 peer, path->net,
10351 bgp_addpath_id_for_peer(peer, afi, safi,
10352 &path->tx_addpath));
10353
10354 if ((addpath_capable && has_adj)
10355 || (!addpath_capable && has_adj
10356 && CHECK_FLAG(path->flags,
10357 BGP_PATH_SELECTED))) {
10358 if (json_path && !json_adv_to)
10359 json_adv_to = json_object_new_object();
10360
10361 route_vty_out_advertised_to(
10362 vty, peer, &first,
10363 " Advertised to:", json_adv_to);
10364 }
10365 }
10366
10367 if (json_path) {
10368 if (json_adv_to) {
10369 json_object_object_add(
10370 json_path, "advertisedTo", json_adv_to);
10371 }
10372 } else {
10373 if (!first) {
10374 vty_out(vty, "\n");
10375 }
10376 }
10377 }
10378
10379 /* Line 9 display Uptime */
10380 tbuf = time(NULL) - (bgp_clock() - path->uptime);
10381 if (json_paths) {
10382 json_last_update = json_object_new_object();
10383 json_object_int_add(json_last_update, "epoch", tbuf);
10384 json_object_string_add(json_last_update, "string",
10385 ctime(&tbuf));
10386 json_object_object_add(json_path, "lastUpdate",
10387 json_last_update);
10388 } else
10389 vty_out(vty, " Last update: %s", ctime(&tbuf));
10390
10391 /* Line 10 display PMSI tunnel attribute, if present */
10392 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
10393 const char *str = lookup_msg(bgp_pmsi_tnltype_str,
10394 bgp_attr_get_pmsi_tnl_type(attr),
10395 PMSI_TNLTYPE_STR_DEFAULT);
10396
10397 if (json_paths) {
10398 json_pmsi = json_object_new_object();
10399 json_object_string_add(json_pmsi, "tunnelType", str);
10400 json_object_int_add(json_pmsi, "label",
10401 label2vni(&attr->label));
10402 json_object_object_add(json_path, "pmsi", json_pmsi);
10403 } else
10404 vty_out(vty, " PMSI Tunnel Type: %s, label: %d\n",
10405 str, label2vni(&attr->label));
10406 }
10407
10408 /* Output some debug about internal state of the dest flags */
10409 if (json_paths) {
10410 if (CHECK_FLAG(bn->flags, BGP_NODE_PROCESS_SCHEDULED))
10411 json_object_boolean_true_add(json_path, "processScheduled");
10412 if (CHECK_FLAG(bn->flags, BGP_NODE_USER_CLEAR))
10413 json_object_boolean_true_add(json_path, "userCleared");
10414 if (CHECK_FLAG(bn->flags, BGP_NODE_LABEL_CHANGED))
10415 json_object_boolean_true_add(json_path, "labelChanged");
10416 if (CHECK_FLAG(bn->flags, BGP_NODE_REGISTERED_FOR_LABEL))
10417 json_object_boolean_true_add(json_path, "registeredForLabel");
10418 if (CHECK_FLAG(bn->flags, BGP_NODE_SELECT_DEFER))
10419 json_object_boolean_true_add(json_path, "selectDefered");
10420 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALLED))
10421 json_object_boolean_true_add(json_path, "fibInstalled");
10422 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALL_PENDING))
10423 json_object_boolean_true_add(json_path, "fibPending");
10424 }
10425
10426 /* We've constructed the json object for this path, add it to the json
10427 * array of paths
10428 */
10429 if (json_paths) {
10430 if (json_nexthop_global || json_nexthop_ll) {
10431 json_nexthops = json_object_new_array();
10432
10433 if (json_nexthop_global)
10434 json_object_array_add(json_nexthops,
10435 json_nexthop_global);
10436
10437 if (json_nexthop_ll)
10438 json_object_array_add(json_nexthops,
10439 json_nexthop_ll);
10440
10441 json_object_object_add(json_path, "nexthops",
10442 json_nexthops);
10443 }
10444
10445 json_object_object_add(json_path, "peer", json_peer);
10446 json_object_array_add(json_paths, json_path);
10447 }
10448 }
10449
10450 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
10451 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
10452 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
10453
10454 static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
10455 const char *prefix_list_str, afi_t afi,
10456 safi_t safi, enum bgp_show_type type);
10457 static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
10458 const char *filter, afi_t afi, safi_t safi,
10459 enum bgp_show_type type);
10460 static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
10461 const char *rmap_str, afi_t afi, safi_t safi,
10462 enum bgp_show_type type);
10463 static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
10464 const char *com, int exact, afi_t afi,
10465 safi_t safi);
10466 static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
10467 const char *prefix, afi_t afi, safi_t safi,
10468 enum bgp_show_type type);
10469 static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
10470 afi_t afi, safi_t safi, enum bgp_show_type type,
10471 bool use_json);
10472 static int bgp_show_community(struct vty *vty, struct bgp *bgp,
10473 const char *comstr, int exact, afi_t afi,
10474 safi_t safi, uint8_t show_flags);
10475
10476
10477 static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
10478 struct bgp_table *table, enum bgp_show_type type,
10479 void *output_arg, char *rd, int is_last,
10480 unsigned long *output_cum, unsigned long *total_cum,
10481 unsigned long *json_header_depth, uint8_t show_flags)
10482 {
10483 struct bgp_path_info *pi;
10484 struct bgp_dest *dest;
10485 int header = 1;
10486 int display;
10487 unsigned long output_count = 0;
10488 unsigned long total_count = 0;
10489 struct prefix *p;
10490 json_object *json_paths = NULL;
10491 int first = 1;
10492 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
10493 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
10494 bool all = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
10495
10496 if (output_cum && *output_cum != 0)
10497 header = 0;
10498
10499 if (use_json && !*json_header_depth) {
10500 if (all)
10501 *json_header_depth = 1;
10502 else {
10503 vty_out(vty, "{\n");
10504 *json_header_depth = 2;
10505 }
10506
10507 vty_out(vty,
10508 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
10509 ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
10510 " \"localAS\": %u,\n \"routes\": { ",
10511 bgp->vrf_id == VRF_UNKNOWN ? -1 : (int)bgp->vrf_id,
10512 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
10513 ? VRF_DEFAULT_NAME
10514 : bgp->name,
10515 table->version, &bgp->router_id,
10516 bgp->default_local_pref, bgp->as);
10517 if (rd) {
10518 vty_out(vty, " \"routeDistinguishers\" : {");
10519 ++*json_header_depth;
10520 }
10521 }
10522
10523 if (use_json && rd) {
10524 vty_out(vty, " \"%s\" : { ", rd);
10525 }
10526
10527 /* Start processing of routes. */
10528 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
10529 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
10530
10531 pi = bgp_dest_get_bgp_path_info(dest);
10532 if (pi == NULL)
10533 continue;
10534
10535 display = 0;
10536 if (use_json)
10537 json_paths = json_object_new_array();
10538 else
10539 json_paths = NULL;
10540
10541 for (; pi; pi = pi->next) {
10542 total_count++;
10543 if (type == bgp_show_type_flap_statistics
10544 || type == bgp_show_type_flap_neighbor
10545 || type == bgp_show_type_dampend_paths
10546 || type == bgp_show_type_damp_neighbor) {
10547 if (!(pi->extra && pi->extra->damp_info))
10548 continue;
10549 }
10550 if (type == bgp_show_type_regexp) {
10551 regex_t *regex = output_arg;
10552
10553 if (bgp_regexec(regex, pi->attr->aspath)
10554 == REG_NOMATCH)
10555 continue;
10556 }
10557 if (type == bgp_show_type_prefix_list) {
10558 struct prefix_list *plist = output_arg;
10559
10560 if (prefix_list_apply(plist, dest_p)
10561 != PREFIX_PERMIT)
10562 continue;
10563 }
10564 if (type == bgp_show_type_filter_list) {
10565 struct as_list *as_list = output_arg;
10566
10567 if (as_list_apply(as_list, pi->attr->aspath)
10568 != AS_FILTER_PERMIT)
10569 continue;
10570 }
10571 if (type == bgp_show_type_route_map) {
10572 struct route_map *rmap = output_arg;
10573 struct bgp_path_info path;
10574 struct attr dummy_attr;
10575 route_map_result_t ret;
10576
10577 dummy_attr = *pi->attr;
10578
10579 path.peer = pi->peer;
10580 path.attr = &dummy_attr;
10581
10582 ret = route_map_apply(rmap, dest_p, &path);
10583 if (ret == RMAP_DENYMATCH)
10584 continue;
10585 }
10586 if (type == bgp_show_type_neighbor
10587 || type == bgp_show_type_flap_neighbor
10588 || type == bgp_show_type_damp_neighbor) {
10589 union sockunion *su = output_arg;
10590
10591 if (pi->peer == NULL
10592 || pi->peer->su_remote == NULL
10593 || !sockunion_same(pi->peer->su_remote, su))
10594 continue;
10595 }
10596 if (type == bgp_show_type_cidr_only) {
10597 uint32_t destination;
10598
10599 destination = ntohl(dest_p->u.prefix4.s_addr);
10600 if (IN_CLASSC(destination)
10601 && dest_p->prefixlen == 24)
10602 continue;
10603 if (IN_CLASSB(destination)
10604 && dest_p->prefixlen == 16)
10605 continue;
10606 if (IN_CLASSA(destination)
10607 && dest_p->prefixlen == 8)
10608 continue;
10609 }
10610 if (type == bgp_show_type_prefix_longer) {
10611 p = output_arg;
10612 if (!prefix_match(p, dest_p))
10613 continue;
10614 }
10615 if (type == bgp_show_type_community_all) {
10616 if (!pi->attr->community)
10617 continue;
10618 }
10619 if (type == bgp_show_type_community) {
10620 struct community *com = output_arg;
10621
10622 if (!pi->attr->community
10623 || !community_match(pi->attr->community,
10624 com))
10625 continue;
10626 }
10627 if (type == bgp_show_type_community_exact) {
10628 struct community *com = output_arg;
10629
10630 if (!pi->attr->community
10631 || !community_cmp(pi->attr->community, com))
10632 continue;
10633 }
10634 if (type == bgp_show_type_community_list) {
10635 struct community_list *list = output_arg;
10636
10637 if (!community_list_match(pi->attr->community,
10638 list))
10639 continue;
10640 }
10641 if (type == bgp_show_type_community_list_exact) {
10642 struct community_list *list = output_arg;
10643
10644 if (!community_list_exact_match(
10645 pi->attr->community, list))
10646 continue;
10647 }
10648 if (type == bgp_show_type_lcommunity) {
10649 struct lcommunity *lcom = output_arg;
10650
10651 if (!pi->attr->lcommunity
10652 || !lcommunity_match(pi->attr->lcommunity,
10653 lcom))
10654 continue;
10655 }
10656
10657 if (type == bgp_show_type_lcommunity_exact) {
10658 struct lcommunity *lcom = output_arg;
10659
10660 if (!pi->attr->lcommunity
10661 || !lcommunity_cmp(pi->attr->lcommunity,
10662 lcom))
10663 continue;
10664 }
10665 if (type == bgp_show_type_lcommunity_list) {
10666 struct community_list *list = output_arg;
10667
10668 if (!lcommunity_list_match(pi->attr->lcommunity,
10669 list))
10670 continue;
10671 }
10672 if (type
10673 == bgp_show_type_lcommunity_list_exact) {
10674 struct community_list *list = output_arg;
10675
10676 if (!lcommunity_list_exact_match(
10677 pi->attr->lcommunity, list))
10678 continue;
10679 }
10680 if (type == bgp_show_type_lcommunity_all) {
10681 if (!pi->attr->lcommunity)
10682 continue;
10683 }
10684 if (type == bgp_show_type_dampend_paths
10685 || type == bgp_show_type_damp_neighbor) {
10686 if (!CHECK_FLAG(pi->flags, BGP_PATH_DAMPED)
10687 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
10688 continue;
10689 }
10690
10691 if (!use_json && header) {
10692 vty_out(vty,
10693 "BGP table version is %" PRIu64
10694 ", local router ID is %pI4, vrf id ",
10695 table->version, &bgp->router_id);
10696 if (bgp->vrf_id == VRF_UNKNOWN)
10697 vty_out(vty, "%s", VRFID_NONE_STR);
10698 else
10699 vty_out(vty, "%u", bgp->vrf_id);
10700 vty_out(vty, "\n");
10701 vty_out(vty, "Default local pref %u, ",
10702 bgp->default_local_pref);
10703 vty_out(vty, "local AS %u\n", bgp->as);
10704 vty_out(vty, BGP_SHOW_SCODE_HEADER);
10705 vty_out(vty, BGP_SHOW_NCODE_HEADER);
10706 vty_out(vty, BGP_SHOW_OCODE_HEADER);
10707 if (type == bgp_show_type_dampend_paths
10708 || type == bgp_show_type_damp_neighbor)
10709 vty_out(vty, BGP_SHOW_DAMP_HEADER);
10710 else if (type == bgp_show_type_flap_statistics
10711 || type == bgp_show_type_flap_neighbor)
10712 vty_out(vty, BGP_SHOW_FLAP_HEADER);
10713 else
10714 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
10715 : BGP_SHOW_HEADER));
10716 header = 0;
10717 }
10718 if (rd != NULL && !display && !output_count) {
10719 if (!use_json)
10720 vty_out(vty,
10721 "Route Distinguisher: %s\n",
10722 rd);
10723 }
10724 if (type == bgp_show_type_dampend_paths
10725 || type == bgp_show_type_damp_neighbor)
10726 damp_route_vty_out(vty, dest_p, pi, display,
10727 AFI_IP, safi, use_json,
10728 json_paths);
10729 else if (type == bgp_show_type_flap_statistics
10730 || type == bgp_show_type_flap_neighbor)
10731 flap_route_vty_out(vty, dest_p, pi, display,
10732 AFI_IP, safi, use_json,
10733 json_paths);
10734 else
10735 route_vty_out(vty, dest_p, pi, display, safi,
10736 json_paths, wide);
10737 display++;
10738 }
10739
10740 if (display) {
10741 output_count++;
10742 if (!use_json)
10743 continue;
10744
10745 /* encode prefix */
10746 if (dest_p->family == AF_FLOWSPEC) {
10747 char retstr[BGP_FLOWSPEC_STRING_DISPLAY_MAX];
10748
10749
10750 bgp_fs_nlri_get_string(
10751 (unsigned char *)
10752 dest_p->u.prefix_flowspec.ptr,
10753 dest_p->u.prefix_flowspec.prefixlen,
10754 retstr, NLRI_STRING_FORMAT_MIN, NULL,
10755 family2afi(dest_p->u
10756 .prefix_flowspec.family));
10757 if (first)
10758 vty_out(vty, "\"%s/%d\": ", retstr,
10759 dest_p->u.prefix_flowspec
10760 .prefixlen);
10761 else
10762 vty_out(vty, ",\"%s/%d\": ", retstr,
10763 dest_p->u.prefix_flowspec
10764 .prefixlen);
10765 } else {
10766 if (first)
10767 vty_out(vty, "\"%pFX\": ", dest_p);
10768 else
10769 vty_out(vty, ",\"%pFX\": ", dest_p);
10770 }
10771 vty_out(vty, "%s",
10772 json_object_to_json_string_ext(
10773 json_paths, JSON_C_TO_STRING_PRETTY));
10774 json_object_free(json_paths);
10775 json_paths = NULL;
10776 first = 0;
10777 } else
10778 json_object_free(json_paths);
10779 }
10780
10781 if (output_cum) {
10782 output_count += *output_cum;
10783 *output_cum = output_count;
10784 }
10785 if (total_cum) {
10786 total_count += *total_cum;
10787 *total_cum = total_count;
10788 }
10789 if (use_json) {
10790 if (rd) {
10791 vty_out(vty, " }%s ", (is_last ? "" : ","));
10792 }
10793 if (is_last) {
10794 unsigned long i;
10795 for (i = 0; i < *json_header_depth; ++i)
10796 vty_out(vty, " } ");
10797 if (!all)
10798 vty_out(vty, "\n");
10799 }
10800 } else {
10801 if (is_last) {
10802 /* No route is displayed */
10803 if (output_count == 0) {
10804 if (type == bgp_show_type_normal)
10805 vty_out(vty,
10806 "No BGP prefixes displayed, %ld exist\n",
10807 total_count);
10808 } else
10809 vty_out(vty,
10810 "\nDisplayed %ld routes and %ld total paths\n",
10811 output_count, total_count);
10812 }
10813 }
10814
10815 return CMD_SUCCESS;
10816 }
10817
10818 int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi,
10819 struct bgp_table *table, struct prefix_rd *prd_match,
10820 enum bgp_show_type type, void *output_arg, bool use_json)
10821 {
10822 struct bgp_dest *dest, *next;
10823 unsigned long output_cum = 0;
10824 unsigned long total_cum = 0;
10825 unsigned long json_header_depth = 0;
10826 struct bgp_table *itable;
10827 bool show_msg;
10828 uint8_t show_flags = 0;
10829
10830 show_msg = (!use_json && type == bgp_show_type_normal);
10831
10832 if (use_json)
10833 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
10834
10835 for (dest = bgp_table_top(table); dest; dest = next) {
10836 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
10837
10838 next = bgp_route_next(dest);
10839 if (prd_match && memcmp(dest_p->u.val, prd_match->val, 8) != 0)
10840 continue;
10841
10842 itable = bgp_dest_get_bgp_table_info(dest);
10843 if (itable != NULL) {
10844 struct prefix_rd prd;
10845 char rd[RD_ADDRSTRLEN];
10846
10847 memcpy(&prd, dest_p, sizeof(struct prefix_rd));
10848 prefix_rd2str(&prd, rd, sizeof(rd));
10849 bgp_show_table(vty, bgp, safi, itable, type, output_arg,
10850 rd, next == NULL, &output_cum,
10851 &total_cum, &json_header_depth,
10852 show_flags);
10853 if (next == NULL)
10854 show_msg = false;
10855 }
10856 }
10857 if (show_msg) {
10858 if (output_cum == 0)
10859 vty_out(vty, "No BGP prefixes displayed, %ld exist\n",
10860 total_cum);
10861 else
10862 vty_out(vty,
10863 "\nDisplayed %ld routes and %ld total paths\n",
10864 output_cum, total_cum);
10865 }
10866 return CMD_SUCCESS;
10867 }
10868 static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
10869 enum bgp_show_type type, void *output_arg,
10870 uint8_t show_flags)
10871 {
10872 struct bgp_table *table;
10873 unsigned long json_header_depth = 0;
10874 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
10875
10876 if (bgp == NULL) {
10877 bgp = bgp_get_default();
10878 }
10879
10880 if (bgp == NULL) {
10881 if (!use_json)
10882 vty_out(vty, "No BGP process is configured\n");
10883 else
10884 vty_out(vty, "{}\n");
10885 return CMD_WARNING;
10886 }
10887
10888 table = bgp->rib[afi][safi];
10889 /* use MPLS and ENCAP specific shows until they are merged */
10890 if (safi == SAFI_MPLS_VPN) {
10891 return bgp_show_table_rd(vty, bgp, safi, table, NULL, type,
10892 output_arg, use_json);
10893 }
10894
10895 if (safi == SAFI_FLOWSPEC && type == bgp_show_type_detail) {
10896 return bgp_show_table_flowspec(vty, bgp, afi, table, type,
10897 output_arg, use_json,
10898 1, NULL, NULL);
10899 }
10900 /* labeled-unicast routes live in the unicast table */
10901 else if (safi == SAFI_LABELED_UNICAST)
10902 safi = SAFI_UNICAST;
10903
10904 return bgp_show_table(vty, bgp, safi, table, type, output_arg, NULL, 1,
10905 NULL, NULL, &json_header_depth, show_flags);
10906 }
10907
10908 static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi,
10909 safi_t safi, uint8_t show_flags)
10910 {
10911 struct listnode *node, *nnode;
10912 struct bgp *bgp;
10913 int is_first = 1;
10914 bool route_output = false;
10915 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
10916
10917 if (use_json)
10918 vty_out(vty, "{\n");
10919
10920 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
10921 route_output = true;
10922 if (use_json) {
10923 if (!is_first)
10924 vty_out(vty, ",\n");
10925 else
10926 is_first = 0;
10927
10928 vty_out(vty, "\"%s\":",
10929 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
10930 ? VRF_DEFAULT_NAME
10931 : bgp->name);
10932 } else {
10933 vty_out(vty, "\nInstance %s:\n",
10934 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
10935 ? VRF_DEFAULT_NAME
10936 : bgp->name);
10937 }
10938 bgp_show(vty, bgp, afi, safi, bgp_show_type_normal, NULL,
10939 show_flags);
10940 }
10941
10942 if (use_json)
10943 vty_out(vty, "}\n");
10944 else if (!route_output)
10945 vty_out(vty, "%% BGP instance not found\n");
10946 }
10947
10948 /* Header of detailed BGP route information */
10949 void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
10950 struct bgp_dest *dest, struct prefix_rd *prd,
10951 afi_t afi, safi_t safi, json_object *json)
10952 {
10953 struct bgp_path_info *pi;
10954 const struct prefix *p;
10955 struct peer *peer;
10956 struct listnode *node, *nnode;
10957 char buf1[RD_ADDRSTRLEN];
10958 char prefix_str[BUFSIZ];
10959 int count = 0;
10960 int best = 0;
10961 int suppress = 0;
10962 int accept_own = 0;
10963 int route_filter_translated_v4 = 0;
10964 int route_filter_v4 = 0;
10965 int route_filter_translated_v6 = 0;
10966 int route_filter_v6 = 0;
10967 int llgr_stale = 0;
10968 int no_llgr = 0;
10969 int accept_own_nexthop = 0;
10970 int blackhole = 0;
10971 int no_export = 0;
10972 int no_advertise = 0;
10973 int local_as = 0;
10974 int no_peer = 0;
10975 int first = 1;
10976 int has_valid_label = 0;
10977 mpls_label_t label = 0;
10978 json_object *json_adv_to = NULL;
10979
10980 p = bgp_dest_get_prefix(dest);
10981 has_valid_label = bgp_is_valid_label(&dest->local_label);
10982
10983 if (has_valid_label)
10984 label = label_pton(&dest->local_label);
10985
10986 if (safi == SAFI_EVPN) {
10987
10988 if (!json) {
10989 vty_out(vty, "BGP routing table entry for %s%s%pFX\n",
10990 prd ? prefix_rd2str(prd, buf1, sizeof(buf1))
10991 : "",
10992 prd ? ":" : "", (struct prefix_evpn *)p);
10993 } else {
10994 json_object_string_add(json, "rd",
10995 prd ? prefix_rd2str(prd, buf1, sizeof(buf1)) :
10996 "");
10997 bgp_evpn_route2json((struct prefix_evpn *)p, json);
10998 }
10999 } else {
11000 if (!json) {
11001 vty_out(vty, "BGP routing table entry for %s%s%pFX\n",
11002 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
11003 ? prefix_rd2str(prd, buf1,
11004 sizeof(buf1))
11005 : ""),
11006 safi == SAFI_MPLS_VPN ? ":" : "", p);
11007
11008 } else
11009 json_object_string_add(json, "prefix",
11010 prefix2str(p, prefix_str, sizeof(prefix_str)));
11011 }
11012
11013 if (has_valid_label) {
11014 if (json)
11015 json_object_int_add(json, "localLabel", label);
11016 else
11017 vty_out(vty, "Local label: %d\n", label);
11018 }
11019
11020 if (!json)
11021 if (bgp_labeled_safi(safi) && safi != SAFI_EVPN)
11022 vty_out(vty, "not allocated\n");
11023
11024 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
11025 count++;
11026 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
11027 best = count;
11028 if (bgp_path_suppressed(pi))
11029 suppress = 1;
11030
11031 if (pi->attr->community == NULL)
11032 continue;
11033
11034 no_advertise += community_include(
11035 pi->attr->community, COMMUNITY_NO_ADVERTISE);
11036 no_export += community_include(pi->attr->community,
11037 COMMUNITY_NO_EXPORT);
11038 local_as += community_include(pi->attr->community,
11039 COMMUNITY_LOCAL_AS);
11040 accept_own += community_include(pi->attr->community,
11041 COMMUNITY_ACCEPT_OWN);
11042 route_filter_translated_v4 += community_include(
11043 pi->attr->community,
11044 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4);
11045 route_filter_translated_v6 += community_include(
11046 pi->attr->community,
11047 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6);
11048 route_filter_v4 += community_include(
11049 pi->attr->community, COMMUNITY_ROUTE_FILTER_v4);
11050 route_filter_v6 += community_include(
11051 pi->attr->community, COMMUNITY_ROUTE_FILTER_v6);
11052 llgr_stale += community_include(pi->attr->community,
11053 COMMUNITY_LLGR_STALE);
11054 no_llgr += community_include(pi->attr->community,
11055 COMMUNITY_NO_LLGR);
11056 accept_own_nexthop +=
11057 community_include(pi->attr->community,
11058 COMMUNITY_ACCEPT_OWN_NEXTHOP);
11059 blackhole += community_include(pi->attr->community,
11060 COMMUNITY_BLACKHOLE);
11061 no_peer += community_include(pi->attr->community,
11062 COMMUNITY_NO_PEER);
11063 }
11064 }
11065
11066 if (!json) {
11067 vty_out(vty, "Paths: (%d available", count);
11068 if (best) {
11069 vty_out(vty, ", best #%d", best);
11070 if (safi == SAFI_UNICAST) {
11071 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
11072 vty_out(vty, ", table %s",
11073 VRF_DEFAULT_NAME);
11074 else
11075 vty_out(vty, ", vrf %s",
11076 bgp->name);
11077 }
11078 } else
11079 vty_out(vty, ", no best path");
11080
11081 if (accept_own)
11082 vty_out(vty,
11083 ", accept own local route exported and imported in different VRF");
11084 else if (route_filter_translated_v4)
11085 vty_out(vty,
11086 ", mark translated RTs for VPNv4 route filtering");
11087 else if (route_filter_v4)
11088 vty_out(vty,
11089 ", attach RT as-is for VPNv4 route filtering");
11090 else if (route_filter_translated_v6)
11091 vty_out(vty,
11092 ", mark translated RTs for VPNv6 route filtering");
11093 else if (route_filter_v6)
11094 vty_out(vty,
11095 ", attach RT as-is for VPNv6 route filtering");
11096 else if (llgr_stale)
11097 vty_out(vty,
11098 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
11099 else if (no_llgr)
11100 vty_out(vty,
11101 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
11102 else if (accept_own_nexthop)
11103 vty_out(vty,
11104 ", accept local nexthop");
11105 else if (blackhole)
11106 vty_out(vty, ", inform peer to blackhole prefix");
11107 else if (no_export)
11108 vty_out(vty, ", not advertised to EBGP peer");
11109 else if (no_advertise)
11110 vty_out(vty, ", not advertised to any peer");
11111 else if (local_as)
11112 vty_out(vty, ", not advertised outside local AS");
11113 else if (no_peer)
11114 vty_out(vty,
11115 ", inform EBGP peer not to advertise to their EBGP peers");
11116
11117 if (suppress)
11118 vty_out(vty,
11119 ", Advertisements suppressed by an aggregate.");
11120 vty_out(vty, ")\n");
11121 }
11122
11123 /* If we are not using addpath then we can display Advertised to and
11124 * that will
11125 * show what peers we advertised the bestpath to. If we are using
11126 * addpath
11127 * though then we must display Advertised to on a path-by-path basis. */
11128 if (!bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
11129 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
11130 if (bgp_adj_out_lookup(peer, dest, 0)) {
11131 if (json && !json_adv_to)
11132 json_adv_to = json_object_new_object();
11133
11134 route_vty_out_advertised_to(
11135 vty, peer, &first,
11136 " Advertised to non peer-group peers:\n ",
11137 json_adv_to);
11138 }
11139 }
11140
11141 if (json) {
11142 if (json_adv_to) {
11143 json_object_object_add(json, "advertisedTo",
11144 json_adv_to);
11145 }
11146 } else {
11147 if (first)
11148 vty_out(vty, " Not advertised to any peer");
11149 vty_out(vty, "\n");
11150 }
11151 }
11152 }
11153
11154 static void bgp_show_path_info(struct prefix_rd *pfx_rd,
11155 struct bgp_dest *bgp_node, struct vty *vty,
11156 struct bgp *bgp, afi_t afi, safi_t safi,
11157 json_object *json, enum bgp_path_type pathtype,
11158 int *display)
11159 {
11160 struct bgp_path_info *pi;
11161 int header = 1;
11162 char rdbuf[RD_ADDRSTRLEN];
11163 json_object *json_header = NULL;
11164 json_object *json_paths = NULL;
11165
11166 for (pi = bgp_dest_get_bgp_path_info(bgp_node); pi; pi = pi->next) {
11167
11168 if (json && !json_paths) {
11169 /* Instantiate json_paths only if path is valid */
11170 json_paths = json_object_new_array();
11171 if (pfx_rd) {
11172 prefix_rd2str(pfx_rd, rdbuf, sizeof(rdbuf));
11173 json_header = json_object_new_object();
11174 } else
11175 json_header = json;
11176 }
11177
11178 if (header) {
11179 route_vty_out_detail_header(
11180 vty, bgp, bgp_node, pfx_rd,
11181 AFI_IP, safi, json_header);
11182 header = 0;
11183 }
11184 (*display)++;
11185
11186 if (pathtype == BGP_PATH_SHOW_ALL
11187 || (pathtype == BGP_PATH_SHOW_BESTPATH
11188 && CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
11189 || (pathtype == BGP_PATH_SHOW_MULTIPATH
11190 && (CHECK_FLAG(pi->flags, BGP_PATH_MULTIPATH)
11191 || CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))))
11192 route_vty_out_detail(vty, bgp, bgp_node,
11193 pi, AFI_IP, safi,
11194 json_paths);
11195 }
11196
11197 if (json && json_paths) {
11198 json_object_object_add(json_header, "paths", json_paths);
11199
11200 if (pfx_rd)
11201 json_object_object_add(json, rdbuf, json_header);
11202 }
11203 }
11204
11205 /* Display specified route of BGP table. */
11206 static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
11207 struct bgp_table *rib, const char *ip_str,
11208 afi_t afi, safi_t safi,
11209 struct prefix_rd *prd, int prefix_check,
11210 enum bgp_path_type pathtype, bool use_json)
11211 {
11212 int ret;
11213 int display = 0;
11214 struct prefix match;
11215 struct bgp_dest *dest;
11216 struct bgp_dest *rm;
11217 struct bgp_table *table;
11218 json_object *json = NULL;
11219 json_object *json_paths = NULL;
11220
11221 /* Check IP address argument. */
11222 ret = str2prefix(ip_str, &match);
11223 if (!ret) {
11224 vty_out(vty, "address is malformed\n");
11225 return CMD_WARNING;
11226 }
11227
11228 match.family = afi2family(afi);
11229
11230 if (use_json)
11231 json = json_object_new_object();
11232
11233 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP) {
11234 for (dest = bgp_table_top(rib); dest;
11235 dest = bgp_route_next(dest)) {
11236 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
11237
11238 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
11239 continue;
11240 table = bgp_dest_get_bgp_table_info(dest);
11241 if (!table)
11242 continue;
11243
11244 if ((rm = bgp_node_match(table, &match)) == NULL)
11245 continue;
11246
11247 const struct prefix *rm_p = bgp_dest_get_prefix(rm);
11248 if (prefix_check
11249 && rm_p->prefixlen != match.prefixlen) {
11250 bgp_dest_unlock_node(rm);
11251 continue;
11252 }
11253
11254 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
11255 bgp, afi, safi, json, pathtype,
11256 &display);
11257
11258 bgp_dest_unlock_node(rm);
11259 }
11260 } else if (safi == SAFI_EVPN) {
11261 struct bgp_dest *longest_pfx;
11262 bool is_exact_pfxlen_match = false;
11263
11264 for (dest = bgp_table_top(rib); dest;
11265 dest = bgp_route_next(dest)) {
11266 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
11267
11268 if (prd && memcmp(&dest_p->u.val, prd->val, 8) != 0)
11269 continue;
11270 table = bgp_dest_get_bgp_table_info(dest);
11271 if (!table)
11272 continue;
11273
11274 longest_pfx = NULL;
11275 is_exact_pfxlen_match = false;
11276 /*
11277 * Search through all the prefixes for a match. The
11278 * pfx's are enumerated in ascending order of pfxlens.
11279 * So, the last pfx match is the longest match. Set
11280 * is_exact_pfxlen_match when we get exact pfxlen match
11281 */
11282 for (rm = bgp_table_top(table); rm;
11283 rm = bgp_route_next(rm)) {
11284 const struct prefix *rm_p =
11285 bgp_dest_get_prefix(rm);
11286 /*
11287 * Get prefixlen of the ip-prefix within type5
11288 * evpn route
11289 */
11290 if (evpn_type5_prefix_match(rm_p, &match)
11291 && rm->info) {
11292 longest_pfx = rm;
11293 int type5_pfxlen =
11294 bgp_evpn_get_type5_prefixlen(
11295 rm_p);
11296 if (type5_pfxlen == match.prefixlen) {
11297 is_exact_pfxlen_match = true;
11298 bgp_dest_unlock_node(rm);
11299 break;
11300 }
11301 }
11302 }
11303
11304 if (!longest_pfx)
11305 continue;
11306
11307 if (prefix_check && !is_exact_pfxlen_match)
11308 continue;
11309
11310 rm = longest_pfx;
11311 bgp_dest_lock_node(rm);
11312
11313 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
11314 bgp, afi, safi, json, pathtype,
11315 &display);
11316
11317 bgp_dest_unlock_node(rm);
11318 }
11319 } else if (safi == SAFI_FLOWSPEC) {
11320 if (use_json)
11321 json_paths = json_object_new_array();
11322
11323 display = bgp_flowspec_display_match_per_ip(afi, rib,
11324 &match, prefix_check,
11325 vty,
11326 use_json,
11327 json_paths);
11328 if (use_json) {
11329 if (display)
11330 json_object_object_add(json, "paths",
11331 json_paths);
11332 else
11333 json_object_free(json_paths);
11334 }
11335 } else {
11336 if ((dest = bgp_node_match(rib, &match)) != NULL) {
11337 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
11338 if (!prefix_check
11339 || dest_p->prefixlen == match.prefixlen) {
11340 bgp_show_path_info(NULL, dest, vty, bgp, afi,
11341 safi, json, pathtype,
11342 &display);
11343 }
11344
11345 bgp_dest_unlock_node(dest);
11346 }
11347 }
11348
11349 if (use_json) {
11350 vty_out(vty, "%s\n", json_object_to_json_string_ext(
11351 json, JSON_C_TO_STRING_PRETTY |
11352 JSON_C_TO_STRING_NOSLASHESCAPE));
11353 json_object_free(json);
11354 } else {
11355 if (!display) {
11356 vty_out(vty, "%% Network not in table\n");
11357 return CMD_WARNING;
11358 }
11359 }
11360
11361 return CMD_SUCCESS;
11362 }
11363
11364 /* Display specified route of Main RIB */
11365 static int bgp_show_route(struct vty *vty, struct bgp *bgp, const char *ip_str,
11366 afi_t afi, safi_t safi, struct prefix_rd *prd,
11367 int prefix_check, enum bgp_path_type pathtype,
11368 bool use_json)
11369 {
11370 if (!bgp) {
11371 bgp = bgp_get_default();
11372 if (!bgp) {
11373 if (!use_json)
11374 vty_out(vty, "No BGP process is configured\n");
11375 else
11376 vty_out(vty, "{}\n");
11377 return CMD_WARNING;
11378 }
11379 }
11380
11381 /* labeled-unicast routes live in the unicast table */
11382 if (safi == SAFI_LABELED_UNICAST)
11383 safi = SAFI_UNICAST;
11384
11385 return bgp_show_route_in_table(vty, bgp, bgp->rib[afi][safi], ip_str,
11386 afi, safi, prd, prefix_check, pathtype,
11387 use_json);
11388 }
11389
11390 static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc,
11391 struct cmd_token **argv, bool exact, afi_t afi,
11392 safi_t safi, bool uj)
11393 {
11394 struct lcommunity *lcom;
11395 struct buffer *b;
11396 int i;
11397 char *str;
11398 int first = 0;
11399 uint8_t show_flags = 0;
11400 int ret;
11401
11402 if (uj)
11403 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11404
11405 b = buffer_new(1024);
11406 for (i = 0; i < argc; i++) {
11407 if (first)
11408 buffer_putc(b, ' ');
11409 else {
11410 if (strmatch(argv[i]->text, "AA:BB:CC")) {
11411 first = 1;
11412 buffer_putstr(b, argv[i]->arg);
11413 }
11414 }
11415 }
11416 buffer_putc(b, '\0');
11417
11418 str = buffer_getstr(b);
11419 buffer_free(b);
11420
11421 lcom = lcommunity_str2com(str);
11422 XFREE(MTYPE_TMP, str);
11423 if (!lcom) {
11424 vty_out(vty, "%% Large-community malformed\n");
11425 return CMD_WARNING;
11426 }
11427
11428 ret = bgp_show(vty, bgp, afi, safi,
11429 (exact ? bgp_show_type_lcommunity_exact
11430 : bgp_show_type_lcommunity),
11431 lcom, show_flags);
11432
11433 lcommunity_free(&lcom);
11434 return ret;
11435 }
11436
11437 static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp,
11438 const char *lcom, bool exact, afi_t afi,
11439 safi_t safi, bool uj)
11440 {
11441 struct community_list *list;
11442 uint8_t show_flags = 0;
11443
11444 if (uj)
11445 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11446
11447
11448 list = community_list_lookup(bgp_clist, lcom, 0,
11449 LARGE_COMMUNITY_LIST_MASTER);
11450 if (list == NULL) {
11451 vty_out(vty, "%% %s is not a valid large-community-list name\n",
11452 lcom);
11453 return CMD_WARNING;
11454 }
11455
11456 return bgp_show(vty, bgp, afi, safi,
11457 (exact ? bgp_show_type_lcommunity_list_exact
11458 : bgp_show_type_lcommunity_list),
11459 list, show_flags);
11460 }
11461
11462 DEFUN (show_ip_bgp_large_community_list,
11463 show_ip_bgp_large_community_list_cmd,
11464 "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]",
11465 SHOW_STR
11466 IP_STR
11467 BGP_STR
11468 BGP_INSTANCE_HELP_STR
11469 BGP_AFI_HELP_STR
11470 BGP_SAFI_WITH_LABEL_HELP_STR
11471 "Display routes matching the large-community-list\n"
11472 "large-community-list number\n"
11473 "large-community-list name\n"
11474 "Exact match of the large-communities\n"
11475 JSON_STR)
11476 {
11477 afi_t afi = AFI_IP6;
11478 safi_t safi = SAFI_UNICAST;
11479 int idx = 0;
11480 bool exact_match = 0;
11481 struct bgp *bgp = NULL;
11482 bool uj = use_json(argc, argv);
11483
11484 if (uj)
11485 argc--;
11486
11487 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11488 &bgp, uj);
11489 if (!idx)
11490 return CMD_WARNING;
11491
11492 argv_find(argv, argc, "large-community-list", &idx);
11493
11494 const char *clist_number_or_name = argv[++idx]->arg;
11495
11496 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
11497 exact_match = 1;
11498
11499 return bgp_show_lcommunity_list(vty, bgp, clist_number_or_name,
11500 exact_match, afi, safi, uj);
11501 }
11502 DEFUN (show_ip_bgp_large_community,
11503 show_ip_bgp_large_community_cmd,
11504 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] large-community [<AA:BB:CC> [exact-match]] [json]",
11505 SHOW_STR
11506 IP_STR
11507 BGP_STR
11508 BGP_INSTANCE_HELP_STR
11509 BGP_AFI_HELP_STR
11510 BGP_SAFI_WITH_LABEL_HELP_STR
11511 "Display routes matching the large-communities\n"
11512 "List of large-community numbers\n"
11513 "Exact match of the large-communities\n"
11514 JSON_STR)
11515 {
11516 afi_t afi = AFI_IP6;
11517 safi_t safi = SAFI_UNICAST;
11518 int idx = 0;
11519 bool exact_match = 0;
11520 struct bgp *bgp = NULL;
11521 bool uj = use_json(argc, argv);
11522 uint8_t show_flags = 0;
11523
11524 if (uj) {
11525 argc--;
11526 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11527 }
11528
11529 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11530 &bgp, uj);
11531 if (!idx)
11532 return CMD_WARNING;
11533
11534 if (argv_find(argv, argc, "AA:BB:CC", &idx)) {
11535 if (argv_find(argv, argc, "exact-match", &idx))
11536 exact_match = 1;
11537 return bgp_show_lcommunity(vty, bgp, argc, argv,
11538 exact_match, afi, safi, uj);
11539 } else
11540 return bgp_show(vty, bgp, afi, safi,
11541 bgp_show_type_lcommunity_all, NULL, show_flags);
11542 }
11543
11544 static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
11545 safi_t safi, struct json_object *json_array);
11546 static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
11547 safi_t safi, struct json_object *json);
11548
11549
11550 DEFUN(show_ip_bgp_statistics_all, show_ip_bgp_statistics_all_cmd,
11551 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
11552 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
11553 "Display number of prefixes for all afi/safi\n" JSON_STR)
11554 {
11555 bool uj = use_json(argc, argv);
11556 struct bgp *bgp = NULL;
11557 safi_t safi = SAFI_UNICAST;
11558 afi_t afi = AFI_IP6;
11559 int idx = 0;
11560 struct json_object *json_all = NULL;
11561 struct json_object *json_afi_safi = NULL;
11562
11563 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11564 &bgp, false);
11565 if (!idx)
11566 return CMD_WARNING;
11567
11568 if (uj)
11569 json_all = json_object_new_object();
11570
11571 FOREACH_AFI_SAFI (afi, safi) {
11572 /*
11573 * So limit output to those afi/safi pairs that
11574 * actually have something interesting in them
11575 */
11576 if (strmatch(get_afi_safi_str(afi, safi, true),
11577 "Unknown")) {
11578 continue;
11579 }
11580 if (uj) {
11581 json_afi_safi = json_object_new_array();
11582 json_object_object_add(
11583 json_all,
11584 get_afi_safi_str(afi, safi, true),
11585 json_afi_safi);
11586 } else {
11587 json_afi_safi = NULL;
11588 }
11589
11590 bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
11591 }
11592
11593 if (uj) {
11594 vty_out(vty, "%s",
11595 json_object_to_json_string_ext(
11596 json_all, JSON_C_TO_STRING_PRETTY));
11597 json_object_free(json_all);
11598 }
11599
11600 return CMD_SUCCESS;
11601 }
11602
11603 /* BGP route print out function without JSON */
11604 DEFUN (show_ip_bgp_l2vpn_evpn_statistics,
11605 show_ip_bgp_l2vpn_evpn_statistics_cmd,
11606 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
11607 SHOW_STR
11608 IP_STR
11609 BGP_STR
11610 BGP_INSTANCE_HELP_STR
11611 L2VPN_HELP_STR
11612 EVPN_HELP_STR
11613 "BGP RIB advertisement statistics\n"
11614 JSON_STR)
11615 {
11616 afi_t afi = AFI_IP6;
11617 safi_t safi = SAFI_UNICAST;
11618 struct bgp *bgp = NULL;
11619 int idx = 0, ret;
11620 bool uj = use_json(argc, argv);
11621 struct json_object *json_afi_safi = NULL, *json = NULL;
11622
11623 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11624 &bgp, false);
11625 if (!idx)
11626 return CMD_WARNING;
11627
11628 if (uj)
11629 json_afi_safi = json_object_new_array();
11630 else
11631 json_afi_safi = NULL;
11632
11633 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
11634
11635 if (uj) {
11636 json = json_object_new_object();
11637 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
11638 json_afi_safi);
11639 vty_out(vty, "%s", json_object_to_json_string_ext(
11640 json, JSON_C_TO_STRING_PRETTY));
11641 json_object_free(json);
11642 }
11643 return ret;
11644 }
11645
11646 /* BGP route print out function without JSON */
11647 DEFUN(show_ip_bgp_afi_safi_statistics, show_ip_bgp_afi_safi_statistics_cmd,
11648 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
11649 " [" BGP_SAFI_WITH_LABEL_CMD_STR
11650 "]]\
11651 statistics [json]",
11652 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
11653 BGP_SAFI_WITH_LABEL_HELP_STR
11654 "BGP RIB advertisement statistics\n" JSON_STR)
11655 {
11656 afi_t afi = AFI_IP6;
11657 safi_t safi = SAFI_UNICAST;
11658 struct bgp *bgp = NULL;
11659 int idx = 0, ret;
11660 bool uj = use_json(argc, argv);
11661 struct json_object *json_afi_safi = NULL, *json = NULL;
11662
11663 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11664 &bgp, false);
11665 if (!idx)
11666 return CMD_WARNING;
11667
11668 if (uj)
11669 json_afi_safi = json_object_new_array();
11670 else
11671 json_afi_safi = NULL;
11672
11673 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
11674
11675 if (uj) {
11676 json = json_object_new_object();
11677 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
11678 json_afi_safi);
11679 vty_out(vty, "%s",
11680 json_object_to_json_string_ext(
11681 json, JSON_C_TO_STRING_PRETTY));
11682 json_object_free(json);
11683 }
11684 return ret;
11685 }
11686
11687 /* BGP route print out function without JSON */
11688 DEFPY(show_ip_bgp, show_ip_bgp_cmd,
11689 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
11690 " [" BGP_SAFI_WITH_LABEL_CMD_STR
11691 "]]\
11692 <[all$all] dampening <parameters>\
11693 |route-map WORD\
11694 |prefix-list WORD\
11695 |filter-list WORD\
11696 |community-list <(1-500)|WORD> [exact-match]\
11697 |A.B.C.D/M longer-prefixes\
11698 |X:X::X:X/M longer-prefixes\
11699 >",
11700 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
11701 BGP_SAFI_WITH_LABEL_HELP_STR
11702 "Display the entries for all address families\n"
11703 "Display detailed information about dampening\n"
11704 "Display detail of configured dampening parameters\n"
11705 "Display routes matching the route-map\n"
11706 "A route-map to match on\n"
11707 "Display routes conforming to the prefix-list\n"
11708 "Prefix-list name\n"
11709 "Display routes conforming to the filter-list\n"
11710 "Regular expression access list name\n"
11711 "Display routes matching the community-list\n"
11712 "community-list number\n"
11713 "community-list name\n"
11714 "Exact match of the communities\n"
11715 "IPv4 prefix\n"
11716 "Display route and more specific routes\n"
11717 "IPv6 prefix\n"
11718 "Display route and more specific routes\n")
11719 {
11720 afi_t afi = AFI_IP6;
11721 safi_t safi = SAFI_UNICAST;
11722 int exact_match = 0;
11723 struct bgp *bgp = NULL;
11724 int idx = 0;
11725 uint8_t show_flags = 0;
11726
11727 /* [<ipv4|ipv6> [all]] */
11728 if (all) {
11729 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
11730 if (argv_find(argv, argc, "ipv4", &idx))
11731 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
11732
11733 if (argv_find(argv, argc, "ipv6", &idx))
11734 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
11735 }
11736
11737 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11738 &bgp, false);
11739 if (!idx)
11740 return CMD_WARNING;
11741
11742 if (argv_find(argv, argc, "dampening", &idx)) {
11743 if (argv_find(argv, argc, "parameters", &idx))
11744 return bgp_show_dampening_parameters(vty, afi, safi,
11745 show_flags);
11746 }
11747
11748 if (argv_find(argv, argc, "prefix-list", &idx))
11749 return bgp_show_prefix_list(vty, bgp, argv[idx + 1]->arg, afi,
11750 safi, bgp_show_type_prefix_list);
11751
11752 if (argv_find(argv, argc, "filter-list", &idx))
11753 return bgp_show_filter_list(vty, bgp, argv[idx + 1]->arg, afi,
11754 safi, bgp_show_type_filter_list);
11755
11756 if (argv_find(argv, argc, "route-map", &idx))
11757 return bgp_show_route_map(vty, bgp, argv[idx + 1]->arg, afi,
11758 safi, bgp_show_type_route_map);
11759
11760 if (argv_find(argv, argc, "community-list", &idx)) {
11761 const char *clist_number_or_name = argv[++idx]->arg;
11762 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
11763 exact_match = 1;
11764 return bgp_show_community_list(vty, bgp, clist_number_or_name,
11765 exact_match, afi, safi);
11766 }
11767 /* prefix-longer */
11768 if (argv_find(argv, argc, "A.B.C.D/M", &idx)
11769 || argv_find(argv, argc, "X:X::X:X/M", &idx))
11770 return bgp_show_prefix_longer(vty, bgp, argv[idx]->arg, afi,
11771 safi,
11772 bgp_show_type_prefix_longer);
11773
11774 return CMD_WARNING;
11775 }
11776
11777 /* BGP route print out function with JSON */
11778 DEFPY (show_ip_bgp_json,
11779 show_ip_bgp_json_cmd,
11780 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]\
11781 [all$all]\
11782 [cidr-only\
11783 |dampening <flap-statistics|dampened-paths>\
11784 |community [AA:NN|local-AS|no-advertise|no-export\
11785 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
11786 |accept-own|accept-own-nexthop|route-filter-v6\
11787 |route-filter-v4|route-filter-translated-v6\
11788 |route-filter-translated-v4] [exact-match]\
11789 ] [json$uj | wide$wide]",
11790 SHOW_STR
11791 IP_STR
11792 BGP_STR
11793 BGP_INSTANCE_HELP_STR
11794 BGP_AFI_HELP_STR
11795 BGP_SAFI_WITH_LABEL_HELP_STR
11796 "Display the entries for all address families\n"
11797 "Display only routes with non-natural netmasks\n"
11798 "Display detailed information about dampening\n"
11799 "Display flap statistics of routes\n"
11800 "Display paths suppressed due to dampening\n"
11801 "Display routes matching the communities\n"
11802 COMMUNITY_AANN_STR
11803 "Do not send outside local AS (well-known community)\n"
11804 "Do not advertise to any peer (well-known community)\n"
11805 "Do not export to next AS (well-known community)\n"
11806 "Graceful shutdown (well-known community)\n"
11807 "Do not export to any peer (well-known community)\n"
11808 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
11809 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
11810 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
11811 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
11812 "Should accept VPN route with local nexthop (well-known community)\n"
11813 "RT VPNv6 route filtering (well-known community)\n"
11814 "RT VPNv4 route filtering (well-known community)\n"
11815 "RT translated VPNv6 route filtering (well-known community)\n"
11816 "RT translated VPNv4 route filtering (well-known community)\n"
11817 "Exact match of the communities\n"
11818 JSON_STR
11819 "Increase table width for longer prefixes\n")
11820 {
11821 afi_t afi = AFI_IP6;
11822 safi_t safi = SAFI_UNICAST;
11823 enum bgp_show_type sh_type = bgp_show_type_normal;
11824 struct bgp *bgp = NULL;
11825 int idx = 0;
11826 int exact_match = 0;
11827 char *community = NULL;
11828 bool first = true;
11829 uint8_t show_flags = 0;
11830
11831
11832 if (uj) {
11833 argc--;
11834 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11835 }
11836
11837 /* [<ipv4|ipv6> [all]] */
11838 if (all) {
11839 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
11840
11841 if (argv_find(argv, argc, "ipv4", &idx))
11842 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
11843
11844 if (argv_find(argv, argc, "ipv6", &idx))
11845 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
11846 }
11847
11848 if (wide)
11849 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
11850
11851 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11852 &bgp, uj);
11853 if (!idx)
11854 return CMD_WARNING;
11855
11856 if (argv_find(argv, argc, "cidr-only", &idx))
11857 sh_type = bgp_show_type_cidr_only;
11858
11859 if (argv_find(argv, argc, "dampening", &idx)) {
11860 if (argv_find(argv, argc, "dampened-paths", &idx))
11861 sh_type = bgp_show_type_dampend_paths;
11862 else if (argv_find(argv, argc, "flap-statistics", &idx))
11863 sh_type = bgp_show_type_flap_statistics;
11864 }
11865
11866 if (argv_find(argv, argc, "community", &idx)) {
11867 char *maybecomm = NULL;
11868
11869 if (idx + 1 < argc) {
11870 if (argv[idx + 1]->type == VARIABLE_TKN)
11871 maybecomm = argv[idx + 1]->arg;
11872 else
11873 maybecomm = argv[idx + 1]->text;
11874 }
11875
11876 if (maybecomm && !strmatch(maybecomm, "json")
11877 && !strmatch(maybecomm, "exact-match"))
11878 community = maybecomm;
11879
11880 if (argv_find(argv, argc, "exact-match", &idx))
11881 exact_match = 1;
11882
11883 if (!community)
11884 sh_type = bgp_show_type_community_all;
11885 }
11886
11887 if (!all) {
11888 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
11889 if (community)
11890 return bgp_show_community(vty, bgp, community,
11891 exact_match, afi, safi,
11892 show_flags);
11893 else
11894 return bgp_show(vty, bgp, afi, safi, sh_type, NULL,
11895 show_flags);
11896 } else {
11897 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
11898 * AFI_IP6 */
11899
11900 if (uj)
11901 vty_out(vty, "{\n");
11902
11903 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
11904 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
11905 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
11906 ? AFI_IP
11907 : AFI_IP6;
11908 FOREACH_SAFI (safi) {
11909 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
11910 continue;
11911
11912 if (uj) {
11913 if (first)
11914 first = false;
11915 else
11916 vty_out(vty, ",\n");
11917 vty_out(vty, "\"%s\":{\n",
11918 get_afi_safi_str(afi, safi,
11919 true));
11920 } else
11921 vty_out(vty,
11922 "\nFor address family: %s\n",
11923 get_afi_safi_str(afi, safi,
11924 false));
11925
11926 if (community)
11927 bgp_show_community(vty, bgp, community,
11928 exact_match, afi,
11929 safi, show_flags);
11930 else
11931 bgp_show(vty, bgp, afi, safi, sh_type,
11932 NULL, show_flags);
11933 if (uj)
11934 vty_out(vty, "}\n");
11935 }
11936 } else {
11937 /* show <ip> bgp all: for each AFI and SAFI*/
11938 FOREACH_AFI_SAFI (afi, safi) {
11939 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
11940 continue;
11941
11942 if (uj) {
11943 if (first)
11944 first = false;
11945 else
11946 vty_out(vty, ",\n");
11947
11948 vty_out(vty, "\"%s\":{\n",
11949 get_afi_safi_str(afi, safi,
11950 true));
11951 } else
11952 vty_out(vty,
11953 "\nFor address family: %s\n",
11954 get_afi_safi_str(afi, safi,
11955 false));
11956
11957 if (community)
11958 bgp_show_community(vty, bgp, community,
11959 exact_match, afi,
11960 safi, show_flags);
11961 else
11962 bgp_show(vty, bgp, afi, safi, sh_type,
11963 NULL, show_flags);
11964 if (uj)
11965 vty_out(vty, "}\n");
11966 }
11967 }
11968 if (uj)
11969 vty_out(vty, "}\n");
11970 }
11971 return CMD_SUCCESS;
11972 }
11973
11974 DEFUN (show_ip_bgp_route,
11975 show_ip_bgp_route_cmd,
11976 "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]",
11977 SHOW_STR
11978 IP_STR
11979 BGP_STR
11980 BGP_INSTANCE_HELP_STR
11981 BGP_AFI_HELP_STR
11982 BGP_SAFI_WITH_LABEL_HELP_STR
11983 "Network in the BGP routing table to display\n"
11984 "IPv4 prefix\n"
11985 "Network in the BGP routing table to display\n"
11986 "IPv6 prefix\n"
11987 "Display only the bestpath\n"
11988 "Display only multipaths\n"
11989 JSON_STR)
11990 {
11991 int prefix_check = 0;
11992
11993 afi_t afi = AFI_IP6;
11994 safi_t safi = SAFI_UNICAST;
11995 char *prefix = NULL;
11996 struct bgp *bgp = NULL;
11997 enum bgp_path_type path_type;
11998 bool uj = use_json(argc, argv);
11999
12000 int idx = 0;
12001
12002 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12003 &bgp, uj);
12004 if (!idx)
12005 return CMD_WARNING;
12006
12007 if (!bgp) {
12008 vty_out(vty,
12009 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
12010 return CMD_WARNING;
12011 }
12012
12013 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
12014 if (argv_find(argv, argc, "A.B.C.D", &idx)
12015 || argv_find(argv, argc, "X:X::X:X", &idx))
12016 prefix_check = 0;
12017 else if (argv_find(argv, argc, "A.B.C.D/M", &idx)
12018 || argv_find(argv, argc, "X:X::X:X/M", &idx))
12019 prefix_check = 1;
12020
12021 if ((argv[idx]->type == IPV6_TKN || argv[idx]->type == IPV6_PREFIX_TKN)
12022 && afi != AFI_IP6) {
12023 vty_out(vty,
12024 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
12025 return CMD_WARNING;
12026 }
12027 if ((argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV4_PREFIX_TKN)
12028 && afi != AFI_IP) {
12029 vty_out(vty,
12030 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
12031 return CMD_WARNING;
12032 }
12033
12034 prefix = argv[idx]->arg;
12035
12036 /* [<bestpath|multipath>] */
12037 if (argv_find(argv, argc, "bestpath", &idx))
12038 path_type = BGP_PATH_SHOW_BESTPATH;
12039 else if (argv_find(argv, argc, "multipath", &idx))
12040 path_type = BGP_PATH_SHOW_MULTIPATH;
12041 else
12042 path_type = BGP_PATH_SHOW_ALL;
12043
12044 return bgp_show_route(vty, bgp, prefix, afi, safi, NULL, prefix_check,
12045 path_type, uj);
12046 }
12047
12048 DEFUN (show_ip_bgp_regexp,
12049 show_ip_bgp_regexp_cmd,
12050 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] regexp REGEX [json]",
12051 SHOW_STR
12052 IP_STR
12053 BGP_STR
12054 BGP_INSTANCE_HELP_STR
12055 BGP_AFI_HELP_STR
12056 BGP_SAFI_WITH_LABEL_HELP_STR
12057 "Display routes matching the AS path regular expression\n"
12058 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
12059 JSON_STR)
12060 {
12061 afi_t afi = AFI_IP6;
12062 safi_t safi = SAFI_UNICAST;
12063 struct bgp *bgp = NULL;
12064 bool uj = use_json(argc, argv);
12065 char *regstr = NULL;
12066
12067 int idx = 0;
12068 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12069 &bgp, false);
12070 if (!idx)
12071 return CMD_WARNING;
12072
12073 // get index of regex
12074 if (argv_find(argv, argc, "REGEX", &idx))
12075 regstr = argv[idx]->arg;
12076
12077 assert(regstr);
12078 return bgp_show_regexp(vty, bgp, (const char *)regstr, afi, safi,
12079 bgp_show_type_regexp, uj);
12080 }
12081
12082 DEFPY (show_ip_bgp_instance_all,
12083 show_ip_bgp_instance_all_cmd,
12084 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [json$uj | wide$wide]",
12085 SHOW_STR
12086 IP_STR
12087 BGP_STR
12088 BGP_INSTANCE_ALL_HELP_STR
12089 BGP_AFI_HELP_STR
12090 BGP_SAFI_WITH_LABEL_HELP_STR
12091 JSON_STR
12092 "Increase table width for longer prefixes\n")
12093 {
12094 afi_t afi = AFI_IP;
12095 safi_t safi = SAFI_UNICAST;
12096 struct bgp *bgp = NULL;
12097 int idx = 0;
12098 uint8_t show_flags = 0;
12099
12100 if (uj) {
12101 argc--;
12102 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12103 }
12104
12105 if (wide)
12106 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
12107
12108 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12109 &bgp, uj);
12110 if (!idx)
12111 return CMD_WARNING;
12112
12113 bgp_show_all_instances_routes_vty(vty, afi, safi, show_flags);
12114 return CMD_SUCCESS;
12115 }
12116
12117 static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
12118 afi_t afi, safi_t safi, enum bgp_show_type type,
12119 bool use_json)
12120 {
12121 regex_t *regex;
12122 int rc;
12123 uint8_t show_flags = 0;
12124
12125 if (use_json)
12126 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12127
12128 if (!config_bgp_aspath_validate(regstr)) {
12129 vty_out(vty, "Invalid character in REGEX %s\n",
12130 regstr);
12131 return CMD_WARNING_CONFIG_FAILED;
12132 }
12133
12134 regex = bgp_regcomp(regstr);
12135 if (!regex) {
12136 vty_out(vty, "Can't compile regexp %s\n", regstr);
12137 return CMD_WARNING;
12138 }
12139
12140 rc = bgp_show(vty, bgp, afi, safi, type, regex, show_flags);
12141 bgp_regex_free(regex);
12142 return rc;
12143 }
12144
12145 static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
12146 const char *prefix_list_str, afi_t afi,
12147 safi_t safi, enum bgp_show_type type)
12148 {
12149 struct prefix_list *plist;
12150 uint8_t show_flags = 0;
12151
12152 plist = prefix_list_lookup(afi, prefix_list_str);
12153 if (plist == NULL) {
12154 vty_out(vty, "%% %s is not a valid prefix-list name\n",
12155 prefix_list_str);
12156 return CMD_WARNING;
12157 }
12158
12159 return bgp_show(vty, bgp, afi, safi, type, plist, show_flags);
12160 }
12161
12162 static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
12163 const char *filter, afi_t afi, safi_t safi,
12164 enum bgp_show_type type)
12165 {
12166 struct as_list *as_list;
12167 uint8_t show_flags = 0;
12168
12169 as_list = as_list_lookup(filter);
12170 if (as_list == NULL) {
12171 vty_out(vty, "%% %s is not a valid AS-path access-list name\n",
12172 filter);
12173 return CMD_WARNING;
12174 }
12175
12176 return bgp_show(vty, bgp, afi, safi, type, as_list, show_flags);
12177 }
12178
12179 static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
12180 const char *rmap_str, afi_t afi, safi_t safi,
12181 enum bgp_show_type type)
12182 {
12183 struct route_map *rmap;
12184 uint8_t show_flags = 0;
12185
12186 rmap = route_map_lookup_by_name(rmap_str);
12187 if (!rmap) {
12188 vty_out(vty, "%% %s is not a valid route-map name\n", rmap_str);
12189 return CMD_WARNING;
12190 }
12191
12192 return bgp_show(vty, bgp, afi, safi, type, rmap, show_flags);
12193 }
12194
12195 static int bgp_show_community(struct vty *vty, struct bgp *bgp,
12196 const char *comstr, int exact, afi_t afi,
12197 safi_t safi, uint8_t show_flags)
12198 {
12199 struct community *com;
12200 int ret = 0;
12201
12202 com = community_str2com(comstr);
12203 if (!com) {
12204 vty_out(vty, "%% Community malformed: %s\n", comstr);
12205 return CMD_WARNING;
12206 }
12207
12208 ret = bgp_show(vty, bgp, afi, safi,
12209 (exact ? bgp_show_type_community_exact
12210 : bgp_show_type_community),
12211 com, show_flags);
12212 community_free(&com);
12213
12214 return ret;
12215 }
12216
12217 static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
12218 const char *com, int exact, afi_t afi,
12219 safi_t safi)
12220 {
12221 struct community_list *list;
12222 uint8_t show_flags = 0;
12223
12224 list = community_list_lookup(bgp_clist, com, 0, COMMUNITY_LIST_MASTER);
12225 if (list == NULL) {
12226 vty_out(vty, "%% %s is not a valid community-list name\n", com);
12227 return CMD_WARNING;
12228 }
12229
12230 return bgp_show(vty, bgp, afi, safi,
12231 (exact ? bgp_show_type_community_list_exact
12232 : bgp_show_type_community_list),
12233 list, show_flags);
12234 }
12235
12236 static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
12237 const char *prefix, afi_t afi, safi_t safi,
12238 enum bgp_show_type type)
12239 {
12240 int ret;
12241 struct prefix *p;
12242 uint8_t show_flags = 0;
12243
12244 p = prefix_new();
12245
12246 ret = str2prefix(prefix, p);
12247 if (!ret) {
12248 vty_out(vty, "%% Malformed Prefix\n");
12249 return CMD_WARNING;
12250 }
12251
12252 ret = bgp_show(vty, bgp, afi, safi, type, p, show_flags);
12253 prefix_free(&p);
12254 return ret;
12255 }
12256
12257 enum bgp_stats {
12258 BGP_STATS_MAXBITLEN = 0,
12259 BGP_STATS_RIB,
12260 BGP_STATS_PREFIXES,
12261 BGP_STATS_TOTPLEN,
12262 BGP_STATS_UNAGGREGATEABLE,
12263 BGP_STATS_MAX_AGGREGATEABLE,
12264 BGP_STATS_AGGREGATES,
12265 BGP_STATS_SPACE,
12266 BGP_STATS_ASPATH_COUNT,
12267 BGP_STATS_ASPATH_MAXHOPS,
12268 BGP_STATS_ASPATH_TOTHOPS,
12269 BGP_STATS_ASPATH_MAXSIZE,
12270 BGP_STATS_ASPATH_TOTSIZE,
12271 BGP_STATS_ASN_HIGHEST,
12272 BGP_STATS_MAX,
12273 };
12274
12275 #define TABLE_STATS_IDX_VTY 0
12276 #define TABLE_STATS_IDX_JSON 1
12277
12278 static const char *table_stats_strs[][2] = {
12279 [BGP_STATS_PREFIXES] = {"Total Prefixes", "totalPrefixes"},
12280 [BGP_STATS_TOTPLEN] = {"Average prefix length", "averagePrefixLength"},
12281 [BGP_STATS_RIB] = {"Total Advertisements", "totalAdvertisements"},
12282 [BGP_STATS_UNAGGREGATEABLE] = {"Unaggregateable prefixes",
12283 "unaggregateablePrefixes"},
12284 [BGP_STATS_MAX_AGGREGATEABLE] = {"Maximum aggregateable prefixes",
12285 "maximumAggregateablePrefixes"},
12286 [BGP_STATS_AGGREGATES] = {"BGP Aggregate advertisements",
12287 "bgpAggregateAdvertisements"},
12288 [BGP_STATS_SPACE] = {"Address space advertised",
12289 "addressSpaceAdvertised"},
12290 [BGP_STATS_ASPATH_COUNT] = {"Advertisements with paths",
12291 "advertisementsWithPaths"},
12292 [BGP_STATS_ASPATH_MAXHOPS] = {"Longest AS-Path (hops)",
12293 "longestAsPath"},
12294 [BGP_STATS_ASPATH_MAXSIZE] = {"Largest AS-Path (bytes)",
12295 "largestAsPath"},
12296 [BGP_STATS_ASPATH_TOTHOPS] = {"Average AS-Path length (hops)",
12297 "averageAsPathLengthHops"},
12298 [BGP_STATS_ASPATH_TOTSIZE] = {"Average AS-Path size (bytes)",
12299 "averageAsPathSizeBytes"},
12300 [BGP_STATS_ASN_HIGHEST] = {"Highest public ASN", "highestPublicAsn"},
12301 [BGP_STATS_MAX] = {NULL, NULL}
12302 };
12303
12304 struct bgp_table_stats {
12305 struct bgp_table *table;
12306 unsigned long long counts[BGP_STATS_MAX];
12307 double total_space;
12308 };
12309
12310 static void bgp_table_stats_rn(struct bgp_dest *dest, struct bgp_dest *top,
12311 struct bgp_table_stats *ts, unsigned int space)
12312 {
12313 struct bgp_dest *pdest = bgp_dest_parent_nolock(dest);
12314 struct bgp_path_info *pi;
12315 const struct prefix *rn_p;
12316
12317 if (!bgp_dest_has_bgp_path_info_data(dest))
12318 return;
12319
12320 rn_p = bgp_dest_get_prefix(dest);
12321 ts->counts[BGP_STATS_PREFIXES]++;
12322 ts->counts[BGP_STATS_TOTPLEN] += rn_p->prefixlen;
12323
12324 /* check if the prefix is included by any other announcements */
12325 while (pdest && !bgp_dest_has_bgp_path_info_data(pdest))
12326 pdest = bgp_dest_parent_nolock(pdest);
12327
12328 if (pdest == NULL || pdest == top) {
12329 ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
12330 /* announced address space */
12331 if (space)
12332 ts->total_space += pow(2.0, space - rn_p->prefixlen);
12333 } else if (bgp_dest_has_bgp_path_info_data(pdest))
12334 ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
12335
12336
12337 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
12338 ts->counts[BGP_STATS_RIB]++;
12339
12340 if (CHECK_FLAG(pi->attr->flag,
12341 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)))
12342 ts->counts[BGP_STATS_AGGREGATES]++;
12343
12344 /* as-path stats */
12345 if (pi->attr->aspath) {
12346 unsigned int hops = aspath_count_hops(pi->attr->aspath);
12347 unsigned int size = aspath_size(pi->attr->aspath);
12348 as_t highest = aspath_highest(pi->attr->aspath);
12349
12350 ts->counts[BGP_STATS_ASPATH_COUNT]++;
12351
12352 if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS])
12353 ts->counts[BGP_STATS_ASPATH_MAXHOPS] = hops;
12354
12355 if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE])
12356 ts->counts[BGP_STATS_ASPATH_MAXSIZE] = size;
12357
12358 ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
12359 ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
12360 if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
12361 ts->counts[BGP_STATS_ASN_HIGHEST] = highest;
12362 }
12363 }
12364 }
12365
12366 static int bgp_table_stats_walker(struct thread *t)
12367 {
12368 struct bgp_dest *dest, *ndest;
12369 struct bgp_dest *top;
12370 struct bgp_table_stats *ts = THREAD_ARG(t);
12371 unsigned int space = 0;
12372
12373 if (!(top = bgp_table_top(ts->table)))
12374 return 0;
12375
12376 switch (ts->table->afi) {
12377 case AFI_IP:
12378 space = IPV4_MAX_BITLEN;
12379 break;
12380 case AFI_IP6:
12381 space = IPV6_MAX_BITLEN;
12382 break;
12383 default:
12384 return 0;
12385 }
12386
12387 ts->counts[BGP_STATS_MAXBITLEN] = space;
12388
12389 for (dest = top; dest; dest = bgp_route_next(dest)) {
12390 if (ts->table->safi == SAFI_MPLS_VPN
12391 || ts->table->safi == SAFI_ENCAP
12392 || ts->table->safi == SAFI_EVPN) {
12393 struct bgp_table *table;
12394
12395 table = bgp_dest_get_bgp_table_info(dest);
12396 if (!table)
12397 continue;
12398
12399 top = bgp_table_top(table);
12400 for (ndest = bgp_table_top(table); ndest;
12401 ndest = bgp_route_next(ndest))
12402 bgp_table_stats_rn(ndest, top, ts, space);
12403 } else {
12404 bgp_table_stats_rn(dest, top, ts, space);
12405 }
12406 }
12407
12408 return 0;
12409 }
12410
12411 static void bgp_table_stats_all(struct vty *vty, afi_t afi, safi_t safi,
12412 struct json_object *json_array)
12413 {
12414 struct listnode *node, *nnode;
12415 struct bgp *bgp;
12416
12417 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
12418 bgp_table_stats_single(vty, bgp, afi, safi, json_array);
12419 }
12420
12421 static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
12422 safi_t safi, struct json_object *json_array)
12423 {
12424 struct bgp_table_stats ts;
12425 unsigned int i;
12426 int ret = CMD_SUCCESS;
12427 char temp_buf[20];
12428 struct json_object *json = NULL;
12429
12430 if (json_array)
12431 json = json_object_new_object();
12432
12433 if (!bgp->rib[afi][safi]) {
12434 char warning_msg[50];
12435
12436 snprintf(warning_msg, sizeof(warning_msg),
12437 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi,
12438 safi);
12439
12440 if (!json)
12441 vty_out(vty, "%s\n", warning_msg);
12442 else
12443 json_object_string_add(json, "warning", warning_msg);
12444
12445 ret = CMD_WARNING;
12446 goto end_table_stats;
12447 }
12448
12449 if (!json)
12450 vty_out(vty, "BGP %s RIB statistics (%s)\n",
12451 get_afi_safi_str(afi, safi, false), bgp->name_pretty);
12452 else
12453 json_object_string_add(json, "instance", bgp->name_pretty);
12454
12455 /* labeled-unicast routes live in the unicast table */
12456 if (safi == SAFI_LABELED_UNICAST)
12457 safi = SAFI_UNICAST;
12458
12459 memset(&ts, 0, sizeof(ts));
12460 ts.table = bgp->rib[afi][safi];
12461 thread_execute(bm->master, bgp_table_stats_walker, &ts, 0);
12462
12463 for (i = 0; i < BGP_STATS_MAX; i++) {
12464 if ((!json && !table_stats_strs[i][TABLE_STATS_IDX_VTY])
12465 || (json && !table_stats_strs[i][TABLE_STATS_IDX_JSON]))
12466 continue;
12467
12468 switch (i) {
12469 case BGP_STATS_ASPATH_TOTHOPS:
12470 case BGP_STATS_ASPATH_TOTSIZE:
12471 if (!json) {
12472 snprintf(
12473 temp_buf, sizeof(temp_buf), "%12.2f",
12474 ts.counts[i]
12475 ? (float)ts.counts[i]
12476 / (float)ts.counts
12477 [BGP_STATS_ASPATH_COUNT]
12478 : 0);
12479 vty_out(vty, "%-30s: %s",
12480 table_stats_strs[i]
12481 [TABLE_STATS_IDX_VTY],
12482 temp_buf);
12483 } else {
12484 json_object_double_add(
12485 json,
12486 table_stats_strs[i]
12487 [TABLE_STATS_IDX_JSON],
12488 ts.counts[i]
12489 ? (double)ts.counts[i]
12490 / (double)ts.counts
12491 [BGP_STATS_ASPATH_COUNT]
12492 : 0);
12493 }
12494 break;
12495 case BGP_STATS_TOTPLEN:
12496 if (!json) {
12497 snprintf(
12498 temp_buf, sizeof(temp_buf), "%12.2f",
12499 ts.counts[i]
12500 ? (float)ts.counts[i]
12501 / (float)ts.counts
12502 [BGP_STATS_PREFIXES]
12503 : 0);
12504 vty_out(vty, "%-30s: %s",
12505 table_stats_strs[i]
12506 [TABLE_STATS_IDX_VTY],
12507 temp_buf);
12508 } else {
12509 json_object_double_add(
12510 json,
12511 table_stats_strs[i]
12512 [TABLE_STATS_IDX_JSON],
12513 ts.counts[i]
12514 ? (double)ts.counts[i]
12515 / (double)ts.counts
12516 [BGP_STATS_PREFIXES]
12517 : 0);
12518 }
12519 break;
12520 case BGP_STATS_SPACE:
12521 if (!json) {
12522 snprintf(temp_buf, sizeof(temp_buf), "%12g",
12523 ts.total_space);
12524 vty_out(vty, "%-30s: %s\n",
12525 table_stats_strs[i]
12526 [TABLE_STATS_IDX_VTY],
12527 temp_buf);
12528 } else {
12529 json_object_double_add(
12530 json,
12531 table_stats_strs[i]
12532 [TABLE_STATS_IDX_JSON],
12533 (double)ts.total_space);
12534 }
12535 if (afi == AFI_IP6) {
12536 if (!json) {
12537 snprintf(temp_buf, sizeof(temp_buf),
12538 "%12g",
12539 ts.total_space
12540 * pow(2.0, -128 + 32));
12541 vty_out(vty, "%30s: %s\n",
12542 "/32 equivalent %s\n",
12543 temp_buf);
12544 } else {
12545 json_object_double_add(
12546 json, "/32equivalent",
12547 (double)(ts.total_space
12548 * pow(2.0,
12549 -128 + 32)));
12550 }
12551 if (!json) {
12552 snprintf(temp_buf, sizeof(temp_buf),
12553 "%12g",
12554 ts.total_space
12555 * pow(2.0, -128 + 48));
12556 vty_out(vty, "%30s: %s\n",
12557 "/48 equivalent %s\n",
12558 temp_buf);
12559 } else {
12560 json_object_double_add(
12561 json, "/48equivalent",
12562 (double)(ts.total_space
12563 * pow(2.0,
12564 -128 + 48)));
12565 }
12566 } else {
12567 if (!json) {
12568 snprintf(temp_buf, sizeof(temp_buf),
12569 "%12.2f",
12570 ts.total_space * 100.
12571 * pow(2.0, -32));
12572 vty_out(vty, "%30s: %s\n",
12573 "% announced ", temp_buf);
12574 } else {
12575 json_object_double_add(
12576 json, "%announced",
12577 (double)(ts.total_space * 100.
12578 * pow(2.0, -32)));
12579 }
12580 if (!json) {
12581 snprintf(temp_buf, sizeof(temp_buf),
12582 "%12.2f",
12583 ts.total_space
12584 * pow(2.0, -32 + 8));
12585 vty_out(vty, "%30s: %s\n",
12586 "/8 equivalent ", temp_buf);
12587 } else {
12588 json_object_double_add(
12589 json, "/8equivalent",
12590 (double)(ts.total_space
12591 * pow(2.0, -32 + 8)));
12592 }
12593 if (!json) {
12594 snprintf(temp_buf, sizeof(temp_buf),
12595 "%12.2f",
12596 ts.total_space
12597 * pow(2.0, -32 + 24));
12598 vty_out(vty, "%30s: %s\n",
12599 "/24 equivalent ", temp_buf);
12600 } else {
12601 json_object_double_add(
12602 json, "/24equivalent",
12603 (double)(ts.total_space
12604 * pow(2.0, -32 + 24)));
12605 }
12606 }
12607 break;
12608 default:
12609 if (!json) {
12610 snprintf(temp_buf, sizeof(temp_buf), "%12llu",
12611 ts.counts[i]);
12612 vty_out(vty, "%-30s: %s",
12613 table_stats_strs[i]
12614 [TABLE_STATS_IDX_VTY],
12615 temp_buf);
12616 } else {
12617 json_object_int_add(
12618 json,
12619 table_stats_strs[i]
12620 [TABLE_STATS_IDX_JSON],
12621 ts.counts[i]);
12622 }
12623 }
12624 if (!json)
12625 vty_out(vty, "\n");
12626 }
12627 end_table_stats:
12628 if (json)
12629 json_object_array_add(json_array, json);
12630 return ret;
12631 }
12632
12633 static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
12634 safi_t safi, struct json_object *json_array)
12635 {
12636 if (!bgp) {
12637 bgp_table_stats_all(vty, afi, safi, json_array);
12638 return CMD_SUCCESS;
12639 }
12640
12641 return bgp_table_stats_single(vty, bgp, afi, safi, json_array);
12642 }
12643
12644 enum bgp_pcounts {
12645 PCOUNT_ADJ_IN = 0,
12646 PCOUNT_DAMPED,
12647 PCOUNT_REMOVED,
12648 PCOUNT_HISTORY,
12649 PCOUNT_STALE,
12650 PCOUNT_VALID,
12651 PCOUNT_ALL,
12652 PCOUNT_COUNTED,
12653 PCOUNT_BPATH_SELECTED,
12654 PCOUNT_PFCNT, /* the figure we display to users */
12655 PCOUNT_MAX,
12656 };
12657
12658 static const char *const pcount_strs[] = {
12659 [PCOUNT_ADJ_IN] = "Adj-in",
12660 [PCOUNT_DAMPED] = "Damped",
12661 [PCOUNT_REMOVED] = "Removed",
12662 [PCOUNT_HISTORY] = "History",
12663 [PCOUNT_STALE] = "Stale",
12664 [PCOUNT_VALID] = "Valid",
12665 [PCOUNT_ALL] = "All RIB",
12666 [PCOUNT_COUNTED] = "PfxCt counted",
12667 [PCOUNT_BPATH_SELECTED] = "PfxCt Best Selected",
12668 [PCOUNT_PFCNT] = "Useable",
12669 [PCOUNT_MAX] = NULL,
12670 };
12671
12672 struct peer_pcounts {
12673 unsigned int count[PCOUNT_MAX];
12674 const struct peer *peer;
12675 const struct bgp_table *table;
12676 safi_t safi;
12677 };
12678
12679 static void bgp_peer_count_proc(struct bgp_dest *rn, struct peer_pcounts *pc)
12680 {
12681 const struct bgp_adj_in *ain;
12682 const struct bgp_path_info *pi;
12683 const struct peer *peer = pc->peer;
12684
12685 for (ain = rn->adj_in; ain; ain = ain->next)
12686 if (ain->peer == peer)
12687 pc->count[PCOUNT_ADJ_IN]++;
12688
12689 for (pi = bgp_dest_get_bgp_path_info(rn); pi; pi = pi->next) {
12690
12691 if (pi->peer != peer)
12692 continue;
12693
12694 pc->count[PCOUNT_ALL]++;
12695
12696 if (CHECK_FLAG(pi->flags, BGP_PATH_DAMPED))
12697 pc->count[PCOUNT_DAMPED]++;
12698 if (CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
12699 pc->count[PCOUNT_HISTORY]++;
12700 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
12701 pc->count[PCOUNT_REMOVED]++;
12702 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE))
12703 pc->count[PCOUNT_STALE]++;
12704 if (CHECK_FLAG(pi->flags, BGP_PATH_VALID))
12705 pc->count[PCOUNT_VALID]++;
12706 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
12707 pc->count[PCOUNT_PFCNT]++;
12708 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
12709 pc->count[PCOUNT_BPATH_SELECTED]++;
12710
12711 if (CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
12712 pc->count[PCOUNT_COUNTED]++;
12713 if (CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
12714 flog_err(
12715 EC_LIB_DEVELOPMENT,
12716 "Attempting to count but flags say it is unusable");
12717 } else {
12718 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
12719 flog_err(
12720 EC_LIB_DEVELOPMENT,
12721 "Not counted but flags say we should");
12722 }
12723 }
12724 }
12725
12726 static int bgp_peer_count_walker(struct thread *t)
12727 {
12728 struct bgp_dest *rn, *rm;
12729 const struct bgp_table *table;
12730 struct peer_pcounts *pc = THREAD_ARG(t);
12731
12732 if (pc->safi == SAFI_MPLS_VPN || pc->safi == SAFI_ENCAP
12733 || pc->safi == SAFI_EVPN) {
12734 /* Special handling for 2-level routing tables. */
12735 for (rn = bgp_table_top(pc->table); rn;
12736 rn = bgp_route_next(rn)) {
12737 table = bgp_dest_get_bgp_table_info(rn);
12738 if (table != NULL)
12739 for (rm = bgp_table_top(table); rm;
12740 rm = bgp_route_next(rm))
12741 bgp_peer_count_proc(rm, pc);
12742 }
12743 } else
12744 for (rn = bgp_table_top(pc->table); rn; rn = bgp_route_next(rn))
12745 bgp_peer_count_proc(rn, pc);
12746
12747 return 0;
12748 }
12749
12750 static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi,
12751 safi_t safi, bool use_json)
12752 {
12753 struct peer_pcounts pcounts = {.peer = peer};
12754 unsigned int i;
12755 json_object *json = NULL;
12756 json_object *json_loop = NULL;
12757
12758 if (use_json) {
12759 json = json_object_new_object();
12760 json_loop = json_object_new_object();
12761 }
12762
12763 if (!peer || !peer->bgp || !peer->afc[afi][safi]
12764 || !peer->bgp->rib[afi][safi]) {
12765 if (use_json) {
12766 json_object_string_add(
12767 json, "warning",
12768 "No such neighbor or address family");
12769 vty_out(vty, "%s\n", json_object_to_json_string(json));
12770 json_object_free(json);
12771 json_object_free(json_loop);
12772 } else
12773 vty_out(vty, "%% No such neighbor or address family\n");
12774
12775 return CMD_WARNING;
12776 }
12777
12778 memset(&pcounts, 0, sizeof(pcounts));
12779 pcounts.peer = peer;
12780 pcounts.table = peer->bgp->rib[afi][safi];
12781 pcounts.safi = safi;
12782
12783 /* in-place call via thread subsystem so as to record execution time
12784 * stats for the thread-walk (i.e. ensure this can't be blamed on
12785 * on just vty_read()).
12786 */
12787 thread_execute(bm->master, bgp_peer_count_walker, &pcounts, 0);
12788
12789 if (use_json) {
12790 json_object_string_add(json, "prefixCountsFor", peer->host);
12791 json_object_string_add(json, "multiProtocol",
12792 get_afi_safi_str(afi, safi, true));
12793 json_object_int_add(json, "pfxCounter",
12794 peer->pcount[afi][safi]);
12795
12796 for (i = 0; i < PCOUNT_MAX; i++)
12797 json_object_int_add(json_loop, pcount_strs[i],
12798 pcounts.count[i]);
12799
12800 json_object_object_add(json, "ribTableWalkCounters", json_loop);
12801
12802 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
12803 json_object_string_add(json, "pfxctDriftFor",
12804 peer->host);
12805 json_object_string_add(
12806 json, "recommended",
12807 "Please report this bug, with the above command output");
12808 }
12809 vty_out(vty, "%s\n", json_object_to_json_string_ext(
12810 json, JSON_C_TO_STRING_PRETTY));
12811 json_object_free(json);
12812 } else {
12813
12814 if (peer->hostname
12815 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
12816 vty_out(vty, "Prefix counts for %s/%s, %s\n",
12817 peer->hostname, peer->host,
12818 get_afi_safi_str(afi, safi, false));
12819 } else {
12820 vty_out(vty, "Prefix counts for %s, %s\n", peer->host,
12821 get_afi_safi_str(afi, safi, false));
12822 }
12823
12824 vty_out(vty, "PfxCt: %u\n", peer->pcount[afi][safi]);
12825 vty_out(vty, "\nCounts from RIB table walk:\n\n");
12826
12827 for (i = 0; i < PCOUNT_MAX; i++)
12828 vty_out(vty, "%20s: %-10d\n", pcount_strs[i],
12829 pcounts.count[i]);
12830
12831 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
12832 vty_out(vty, "%s [pcount] PfxCt drift!\n", peer->host);
12833 vty_out(vty,
12834 "Please report this bug, with the above command output\n");
12835 }
12836 }
12837
12838 return CMD_SUCCESS;
12839 }
12840
12841 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts,
12842 show_ip_bgp_instance_neighbor_prefix_counts_cmd,
12843 "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]",
12844 SHOW_STR
12845 IP_STR
12846 BGP_STR
12847 BGP_INSTANCE_HELP_STR
12848 BGP_AFI_HELP_STR
12849 BGP_SAFI_HELP_STR
12850 "Detailed information on TCP and BGP neighbor connections\n"
12851 "Neighbor to display information about\n"
12852 "Neighbor to display information about\n"
12853 "Neighbor on BGP configured interface\n"
12854 "Display detailed prefix count information\n"
12855 JSON_STR)
12856 {
12857 afi_t afi = AFI_IP6;
12858 safi_t safi = SAFI_UNICAST;
12859 struct peer *peer;
12860 int idx = 0;
12861 struct bgp *bgp = NULL;
12862 bool uj = use_json(argc, argv);
12863
12864 if (uj)
12865 argc--;
12866
12867 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12868 &bgp, uj);
12869 if (!idx)
12870 return CMD_WARNING;
12871
12872 argv_find(argv, argc, "neighbors", &idx);
12873 peer = peer_lookup_in_view(vty, bgp, argv[idx + 1]->arg, uj);
12874 if (!peer)
12875 return CMD_WARNING;
12876
12877 return bgp_peer_counts(vty, peer, afi, safi, uj);
12878 }
12879
12880 #ifdef KEEP_OLD_VPN_COMMANDS
12881 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts,
12882 show_ip_bgp_vpn_neighbor_prefix_counts_cmd,
12883 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
12884 SHOW_STR
12885 IP_STR
12886 BGP_STR
12887 BGP_VPNVX_HELP_STR
12888 "Display information about all VPNv4 NLRIs\n"
12889 "Detailed information on TCP and BGP neighbor connections\n"
12890 "Neighbor to display information about\n"
12891 "Neighbor to display information about\n"
12892 "Neighbor on BGP configured interface\n"
12893 "Display detailed prefix count information\n"
12894 JSON_STR)
12895 {
12896 int idx_peer = 6;
12897 struct peer *peer;
12898 bool uj = use_json(argc, argv);
12899
12900 peer = peer_lookup_in_view(vty, NULL, argv[idx_peer]->arg, uj);
12901 if (!peer)
12902 return CMD_WARNING;
12903
12904 return bgp_peer_counts(vty, peer, AFI_IP, SAFI_MPLS_VPN, uj);
12905 }
12906
12907 DEFUN (show_ip_bgp_vpn_all_route_prefix,
12908 show_ip_bgp_vpn_all_route_prefix_cmd,
12909 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
12910 SHOW_STR
12911 IP_STR
12912 BGP_STR
12913 BGP_VPNVX_HELP_STR
12914 "Display information about all VPNv4 NLRIs\n"
12915 "Network in the BGP routing table to display\n"
12916 "Network in the BGP routing table to display\n"
12917 JSON_STR)
12918 {
12919 int idx = 0;
12920 char *network = NULL;
12921 struct bgp *bgp = bgp_get_default();
12922 if (!bgp) {
12923 vty_out(vty, "Can't find default instance\n");
12924 return CMD_WARNING;
12925 }
12926
12927 if (argv_find(argv, argc, "A.B.C.D", &idx))
12928 network = argv[idx]->arg;
12929 else if (argv_find(argv, argc, "A.B.C.D/M", &idx))
12930 network = argv[idx]->arg;
12931 else {
12932 vty_out(vty, "Unable to figure out Network\n");
12933 return CMD_WARNING;
12934 }
12935
12936 return bgp_show_route(vty, bgp, network, AFI_IP, SAFI_MPLS_VPN, NULL, 0,
12937 BGP_PATH_SHOW_ALL, use_json(argc, argv));
12938 }
12939 #endif /* KEEP_OLD_VPN_COMMANDS */
12940
12941 DEFUN (show_bgp_l2vpn_evpn_route_prefix,
12942 show_bgp_l2vpn_evpn_route_prefix_cmd,
12943 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
12944 SHOW_STR
12945 BGP_STR
12946 L2VPN_HELP_STR
12947 EVPN_HELP_STR
12948 "Network in the BGP routing table to display\n"
12949 "Network in the BGP routing table to display\n"
12950 "Network in the BGP routing table to display\n"
12951 "Network in the BGP routing table to display\n"
12952 JSON_STR)
12953 {
12954 int idx = 0;
12955 char *network = NULL;
12956 int prefix_check = 0;
12957
12958 if (argv_find(argv, argc, "A.B.C.D", &idx) ||
12959 argv_find(argv, argc, "X:X::X:X", &idx))
12960 network = argv[idx]->arg;
12961 else if (argv_find(argv, argc, "A.B.C.D/M", &idx) ||
12962 argv_find(argv, argc, "X:X::X:X/M", &idx)) {
12963 network = argv[idx]->arg;
12964 prefix_check = 1;
12965 } else {
12966 vty_out(vty, "Unable to figure out Network\n");
12967 return CMD_WARNING;
12968 }
12969 return bgp_show_route(vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL,
12970 prefix_check, BGP_PATH_SHOW_ALL,
12971 use_json(argc, argv));
12972 }
12973
12974 static void show_adj_route_header(struct vty *vty, struct bgp *bgp,
12975 struct bgp_table *table, int *header1,
12976 int *header2, json_object *json,
12977 json_object *json_scode,
12978 json_object *json_ocode, bool wide)
12979 {
12980 uint64_t version = table ? table->version : 0;
12981 char buf[BUFSIZ] = {0};
12982
12983 if (*header1) {
12984 if (json) {
12985 json_object_int_add(json, "bgpTableVersion", version);
12986 json_object_string_add(json, "bgpLocalRouterId",
12987 inet_ntop(AF_INET,
12988 &bgp->router_id, buf,
12989 sizeof(buf)));
12990 json_object_int_add(json, "defaultLocPrf",
12991 bgp->default_local_pref);
12992 json_object_int_add(json, "localAS", bgp->as);
12993 json_object_object_add(json, "bgpStatusCodes",
12994 json_scode);
12995 json_object_object_add(json, "bgpOriginCodes",
12996 json_ocode);
12997 } else {
12998 vty_out(vty,
12999 "BGP table version is %" PRIu64
13000 ", local router ID is %pI4, vrf id ",
13001 version, &bgp->router_id);
13002 if (bgp->vrf_id == VRF_UNKNOWN)
13003 vty_out(vty, "%s", VRFID_NONE_STR);
13004 else
13005 vty_out(vty, "%u", bgp->vrf_id);
13006 vty_out(vty, "\n");
13007 vty_out(vty, "Default local pref %u, ",
13008 bgp->default_local_pref);
13009 vty_out(vty, "local AS %u\n", bgp->as);
13010 vty_out(vty, BGP_SHOW_SCODE_HEADER);
13011 vty_out(vty, BGP_SHOW_NCODE_HEADER);
13012 vty_out(vty, BGP_SHOW_OCODE_HEADER);
13013 }
13014 *header1 = 0;
13015 }
13016 if (*header2) {
13017 if (!json)
13018 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
13019 : BGP_SHOW_HEADER));
13020 *header2 = 0;
13021 }
13022 }
13023
13024 static void
13025 show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
13026 afi_t afi, safi_t safi, enum bgp_show_adj_route_type type,
13027 const char *rmap_name, json_object *json, json_object *json_ar,
13028 json_object *json_scode, json_object *json_ocode,
13029 uint8_t show_flags, int *header1, int *header2, char *rd_str,
13030 unsigned long *output_count, unsigned long *filtered_count)
13031 {
13032 struct bgp_adj_in *ain;
13033 struct bgp_adj_out *adj;
13034 struct bgp_dest *dest;
13035 struct bgp *bgp;
13036 struct attr attr;
13037 int ret;
13038 struct update_subgroup *subgrp;
13039 struct peer_af *paf;
13040 bool route_filtered;
13041 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13042 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
13043 bool show_rd = ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
13044 || (safi == SAFI_EVPN))
13045 ? true
13046 : false;
13047
13048 bgp = peer->bgp;
13049
13050 if (!bgp) {
13051 if (use_json) {
13052 json_object_string_add(json, "alert", "no BGP");
13053 vty_out(vty, "%s\n", json_object_to_json_string(json));
13054 json_object_free(json);
13055 } else
13056 vty_out(vty, "%% No bgp\n");
13057 return;
13058 }
13059
13060 subgrp = peer_subgroup(peer, afi, safi);
13061
13062 if (type == bgp_show_adj_route_advertised && subgrp
13063 && CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) {
13064 char buf[BUFSIZ] = {0};
13065
13066 if (use_json) {
13067 json_object_int_add(json, "bgpTableVersion",
13068 table->version);
13069 json_object_string_add(json, "bgpLocalRouterId",
13070 inet_ntop(AF_INET,
13071 &bgp->router_id, buf,
13072 sizeof(buf)));
13073 json_object_int_add(json, "defaultLocPrf",
13074 bgp->default_local_pref);
13075 json_object_int_add(json, "localAS", bgp->as);
13076 json_object_object_add(json, "bgpStatusCodes",
13077 json_scode);
13078 json_object_object_add(json, "bgpOriginCodes",
13079 json_ocode);
13080 json_object_string_add(
13081 json, "bgpOriginatingDefaultNetwork",
13082 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
13083 } else {
13084 vty_out(vty,
13085 "BGP table version is %" PRIu64
13086 ", local router ID is %pI4, vrf id ",
13087 table->version, &bgp->router_id);
13088 if (bgp->vrf_id == VRF_UNKNOWN)
13089 vty_out(vty, "%s", VRFID_NONE_STR);
13090 else
13091 vty_out(vty, "%u", bgp->vrf_id);
13092 vty_out(vty, "\n");
13093 vty_out(vty, "Default local pref %u, ",
13094 bgp->default_local_pref);
13095 vty_out(vty, "local AS %u\n", bgp->as);
13096 vty_out(vty, BGP_SHOW_SCODE_HEADER);
13097 vty_out(vty, BGP_SHOW_NCODE_HEADER);
13098 vty_out(vty, BGP_SHOW_OCODE_HEADER);
13099
13100 vty_out(vty, "Originating default network %s\n\n",
13101 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
13102 }
13103 *header1 = 0;
13104 }
13105
13106 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
13107 if (type == bgp_show_adj_route_received
13108 || type == bgp_show_adj_route_filtered) {
13109 for (ain = dest->adj_in; ain; ain = ain->next) {
13110 if (ain->peer != peer)
13111 continue;
13112
13113 show_adj_route_header(vty, bgp, table, header1,
13114 header2, json, json_scode,
13115 json_ocode, wide);
13116
13117 if ((safi == SAFI_MPLS_VPN)
13118 || (safi == SAFI_ENCAP)
13119 || (safi == SAFI_EVPN)) {
13120 if (use_json)
13121 json_object_string_add(
13122 json_ar, "rd", rd_str);
13123 else if (show_rd && rd_str) {
13124 vty_out(vty,
13125 "Route Distinguisher: %s\n",
13126 rd_str);
13127 show_rd = false;
13128 }
13129 }
13130
13131 attr = *ain->attr;
13132 route_filtered = false;
13133
13134 /* Filter prefix using distribute list,
13135 * filter list or prefix list
13136 */
13137 const struct prefix *rn_p =
13138 bgp_dest_get_prefix(dest);
13139 if ((bgp_input_filter(peer, rn_p, &attr, afi,
13140 safi))
13141 == FILTER_DENY)
13142 route_filtered = true;
13143
13144 /* Filter prefix using route-map */
13145 ret = bgp_input_modifier(peer, rn_p, &attr, afi,
13146 safi, rmap_name, NULL,
13147 0, NULL);
13148
13149 if (type == bgp_show_adj_route_filtered &&
13150 !route_filtered && ret != RMAP_DENY) {
13151 bgp_attr_undup(&attr, ain->attr);
13152 continue;
13153 }
13154
13155 if (type == bgp_show_adj_route_received
13156 && (route_filtered || ret == RMAP_DENY))
13157 (*filtered_count)++;
13158
13159 route_vty_out_tmp(vty, rn_p, &attr, safi,
13160 use_json, json_ar, wide);
13161 bgp_attr_undup(&attr, ain->attr);
13162 (*output_count)++;
13163 }
13164 } else if (type == bgp_show_adj_route_advertised) {
13165 RB_FOREACH (adj, bgp_adj_out_rb, &dest->adj_out)
13166 SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
13167 if (paf->peer != peer || !adj->attr)
13168 continue;
13169
13170 show_adj_route_header(vty, bgp, table,
13171 header1, header2,
13172 json, json_scode,
13173 json_ocode, wide);
13174
13175 const struct prefix *rn_p =
13176 bgp_dest_get_prefix(dest);
13177
13178 attr = *adj->attr;
13179 ret = bgp_output_modifier(
13180 peer, rn_p, &attr, afi, safi,
13181 rmap_name);
13182
13183 if (ret != RMAP_DENY) {
13184 if ((safi == SAFI_MPLS_VPN)
13185 || (safi == SAFI_ENCAP)
13186 || (safi == SAFI_EVPN)) {
13187 if (use_json)
13188 json_object_string_add(
13189 json_ar,
13190 "rd",
13191 rd_str);
13192 else if (show_rd
13193 && rd_str) {
13194 vty_out(vty,
13195 "Route Distinguisher: %s\n",
13196 rd_str);
13197 show_rd = false;
13198 }
13199 }
13200 route_vty_out_tmp(
13201 vty, rn_p, &attr, safi,
13202 use_json, json_ar,
13203 wide);
13204 (*output_count)++;
13205 } else {
13206 (*filtered_count)++;
13207 }
13208
13209 bgp_attr_undup(&attr, adj->attr);
13210 }
13211 } else if (type == bgp_show_adj_route_bestpath) {
13212 struct bgp_path_info *pi;
13213
13214 show_adj_route_header(vty, bgp, table, header1, header2,
13215 json, json_scode, json_ocode,
13216 wide);
13217
13218 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
13219 pi = pi->next) {
13220 if (pi->peer != peer)
13221 continue;
13222
13223 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
13224 continue;
13225
13226 route_vty_out_tmp(vty,
13227 bgp_dest_get_prefix(dest),
13228 pi->attr, safi, use_json,
13229 json_ar, wide);
13230 (*output_count)++;
13231 }
13232 }
13233 }
13234 }
13235
13236 static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
13237 safi_t safi, enum bgp_show_adj_route_type type,
13238 const char *rmap_name, uint8_t show_flags)
13239 {
13240 struct bgp *bgp;
13241 struct bgp_table *table;
13242 json_object *json = NULL;
13243 json_object *json_scode = NULL;
13244 json_object *json_ocode = NULL;
13245 json_object *json_ar = NULL;
13246 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13247
13248 /* Init BGP headers here so they're only displayed once
13249 * even if 'table' is 2-tier (MPLS_VPN, ENCAP, EVPN).
13250 */
13251 int header1 = 1;
13252 int header2 = 1;
13253
13254 /*
13255 * Initialize variables for each RD
13256 * All prefixes under an RD is aggregated within "json_routes"
13257 */
13258 char rd_str[BUFSIZ] = {0};
13259 json_object *json_routes = NULL;
13260
13261
13262 /* For 2-tier tables, prefix counts need to be
13263 * maintained across multiple runs of show_adj_route()
13264 */
13265 unsigned long output_count_per_rd;
13266 unsigned long filtered_count_per_rd;
13267 unsigned long output_count = 0;
13268 unsigned long filtered_count = 0;
13269
13270 if (use_json) {
13271 json = json_object_new_object();
13272 json_ar = json_object_new_object();
13273 json_scode = json_object_new_object();
13274 json_ocode = json_object_new_object();
13275
13276 json_object_string_add(json_scode, "suppressed", "s");
13277 json_object_string_add(json_scode, "damped", "d");
13278 json_object_string_add(json_scode, "history", "h");
13279 json_object_string_add(json_scode, "valid", "*");
13280 json_object_string_add(json_scode, "best", ">");
13281 json_object_string_add(json_scode, "multipath", "=");
13282 json_object_string_add(json_scode, "internal", "i");
13283 json_object_string_add(json_scode, "ribFailure", "r");
13284 json_object_string_add(json_scode, "stale", "S");
13285 json_object_string_add(json_scode, "removed", "R");
13286
13287 json_object_string_add(json_ocode, "igp", "i");
13288 json_object_string_add(json_ocode, "egp", "e");
13289 json_object_string_add(json_ocode, "incomplete", "?");
13290 }
13291
13292 if (!peer || !peer->afc[afi][safi]) {
13293 if (use_json) {
13294 json_object_string_add(
13295 json, "warning",
13296 "No such neighbor or address family");
13297 vty_out(vty, "%s\n", json_object_to_json_string(json));
13298 json_object_free(json);
13299 } else
13300 vty_out(vty, "%% No such neighbor or address family\n");
13301
13302 return CMD_WARNING;
13303 }
13304
13305 if ((type == bgp_show_adj_route_received
13306 || type == bgp_show_adj_route_filtered)
13307 && !CHECK_FLAG(peer->af_flags[afi][safi],
13308 PEER_FLAG_SOFT_RECONFIG)) {
13309 if (use_json) {
13310 json_object_string_add(
13311 json, "warning",
13312 "Inbound soft reconfiguration not enabled");
13313 vty_out(vty, "%s\n", json_object_to_json_string(json));
13314 json_object_free(json);
13315 } else
13316 vty_out(vty,
13317 "%% Inbound soft reconfiguration not enabled\n");
13318
13319 return CMD_WARNING;
13320 }
13321
13322 bgp = peer->bgp;
13323
13324 /* labeled-unicast routes live in the unicast table */
13325 if (safi == SAFI_LABELED_UNICAST)
13326 table = bgp->rib[afi][SAFI_UNICAST];
13327 else
13328 table = bgp->rib[afi][safi];
13329
13330 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
13331 || (safi == SAFI_EVPN)) {
13332
13333 struct bgp_dest *dest;
13334
13335 for (dest = bgp_table_top(table); dest;
13336 dest = bgp_route_next(dest)) {
13337 table = bgp_dest_get_bgp_table_info(dest);
13338 if (!table)
13339 continue;
13340
13341 output_count_per_rd = 0;
13342 filtered_count_per_rd = 0;
13343
13344 if (use_json)
13345 json_routes = json_object_new_object();
13346
13347 const struct prefix_rd *prd;
13348 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
13349 dest);
13350
13351 prefix_rd2str(prd, rd_str, sizeof(rd_str));
13352
13353 show_adj_route(vty, peer, table, afi, safi, type,
13354 rmap_name, json, json_routes, json_scode,
13355 json_ocode, show_flags, &header1,
13356 &header2, rd_str, &output_count_per_rd,
13357 &filtered_count_per_rd);
13358
13359 /* Don't include an empty RD in the output! */
13360 if (json_routes && (output_count_per_rd > 0))
13361 json_object_object_add(json_ar, rd_str,
13362 json_routes);
13363
13364 output_count += output_count_per_rd;
13365 filtered_count += filtered_count_per_rd;
13366 }
13367 } else
13368 show_adj_route(vty, peer, table, afi, safi, type, rmap_name,
13369 json, json_ar, json_scode, json_ocode,
13370 show_flags, &header1, &header2, rd_str,
13371 &output_count, &filtered_count);
13372
13373 if (use_json) {
13374 json_object_object_add(json, "advertisedRoutes", json_ar);
13375 json_object_int_add(json, "totalPrefixCounter", output_count);
13376 json_object_int_add(json, "filteredPrefixCounter",
13377 filtered_count);
13378
13379 vty_out(vty, "%s\n",
13380 json_object_to_json_string_ext(
13381 json, JSON_C_TO_STRING_PRETTY));
13382
13383 if (!output_count && !filtered_count) {
13384 json_object_free(json_scode);
13385 json_object_free(json_ocode);
13386 }
13387
13388 if (json)
13389 json_object_free(json);
13390
13391 } else if (output_count > 0) {
13392 if (filtered_count > 0)
13393 vty_out(vty,
13394 "\nTotal number of prefixes %ld (%ld filtered)\n",
13395 output_count, filtered_count);
13396 else
13397 vty_out(vty, "\nTotal number of prefixes %ld\n",
13398 output_count);
13399 }
13400
13401 return CMD_SUCCESS;
13402 }
13403
13404 DEFPY (show_ip_bgp_instance_neighbor_bestpath_route,
13405 show_ip_bgp_instance_neighbor_bestpath_route_cmd,
13406 "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]",
13407 SHOW_STR
13408 IP_STR
13409 BGP_STR
13410 BGP_INSTANCE_HELP_STR
13411 BGP_AFI_HELP_STR
13412 BGP_SAFI_WITH_LABEL_HELP_STR
13413 "Detailed information on TCP and BGP neighbor connections\n"
13414 "Neighbor to display information about\n"
13415 "Neighbor to display information about\n"
13416 "Neighbor on BGP configured interface\n"
13417 "Display the routes selected by best path\n"
13418 JSON_STR
13419 "Increase table width for longer prefixes\n")
13420 {
13421 afi_t afi = AFI_IP6;
13422 safi_t safi = SAFI_UNICAST;
13423 char *rmap_name = NULL;
13424 char *peerstr = NULL;
13425 struct bgp *bgp = NULL;
13426 struct peer *peer;
13427 enum bgp_show_adj_route_type type = bgp_show_adj_route_bestpath;
13428 int idx = 0;
13429 uint8_t show_flags = 0;
13430
13431 if (uj)
13432 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13433
13434 if (wide)
13435 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
13436
13437 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13438 &bgp, uj);
13439
13440 if (!idx)
13441 return CMD_WARNING;
13442
13443 argv_find(argv, argc, "neighbors", &idx);
13444 peerstr = argv[++idx]->arg;
13445
13446 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
13447 if (!peer)
13448 return CMD_WARNING;
13449
13450 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13451 show_flags);
13452 }
13453
13454 DEFPY (show_ip_bgp_instance_neighbor_advertised_route,
13455 show_ip_bgp_instance_neighbor_advertised_route_cmd,
13456 "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]",
13457 SHOW_STR
13458 IP_STR
13459 BGP_STR
13460 BGP_INSTANCE_HELP_STR
13461 BGP_AFI_HELP_STR
13462 BGP_SAFI_WITH_LABEL_HELP_STR
13463 "Display the entries for all address families\n"
13464 "Detailed information on TCP and BGP neighbor connections\n"
13465 "Neighbor to display information about\n"
13466 "Neighbor to display information about\n"
13467 "Neighbor on BGP configured interface\n"
13468 "Display the routes advertised to a BGP neighbor\n"
13469 "Display the received routes from neighbor\n"
13470 "Display the filtered routes received from neighbor\n"
13471 "Route-map to modify the attributes\n"
13472 "Name of the route map\n"
13473 JSON_STR
13474 "Increase table width for longer prefixes\n")
13475 {
13476 afi_t afi = AFI_IP6;
13477 safi_t safi = SAFI_UNICAST;
13478 char *rmap_name = NULL;
13479 char *peerstr = NULL;
13480 struct bgp *bgp = NULL;
13481 struct peer *peer;
13482 enum bgp_show_adj_route_type type = bgp_show_adj_route_advertised;
13483 int idx = 0;
13484 bool first = true;
13485 uint8_t show_flags = 0;
13486
13487 if (uj) {
13488 argc--;
13489 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13490 }
13491
13492 if (all) {
13493 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
13494 if (argv_find(argv, argc, "ipv4", &idx))
13495 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
13496
13497 if (argv_find(argv, argc, "ipv6", &idx))
13498 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
13499 }
13500
13501 if (wide)
13502 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
13503
13504 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13505 &bgp, uj);
13506 if (!idx)
13507 return CMD_WARNING;
13508
13509 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13510 argv_find(argv, argc, "neighbors", &idx);
13511 peerstr = argv[++idx]->arg;
13512
13513 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
13514 if (!peer)
13515 return CMD_WARNING;
13516
13517 if (argv_find(argv, argc, "advertised-routes", &idx))
13518 type = bgp_show_adj_route_advertised;
13519 else if (argv_find(argv, argc, "received-routes", &idx))
13520 type = bgp_show_adj_route_received;
13521 else if (argv_find(argv, argc, "filtered-routes", &idx))
13522 type = bgp_show_adj_route_filtered;
13523
13524 if (argv_find(argv, argc, "route-map", &idx))
13525 rmap_name = argv[++idx]->arg;
13526
13527 if (!all)
13528 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13529 show_flags);
13530 if (uj)
13531 vty_out(vty, "{\n");
13532
13533 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
13534 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
13535 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP) ? AFI_IP
13536 : AFI_IP6;
13537 FOREACH_SAFI (safi) {
13538 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
13539 continue;
13540
13541 if (uj) {
13542 if (first)
13543 first = false;
13544 else
13545 vty_out(vty, ",\n");
13546 vty_out(vty, "\"%s\":",
13547 get_afi_safi_str(afi, safi, true));
13548 } else
13549 vty_out(vty, "\nFor address family: %s\n",
13550 get_afi_safi_str(afi, safi, false));
13551
13552 peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13553 show_flags);
13554 }
13555 } else {
13556 FOREACH_AFI_SAFI (afi, safi) {
13557 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
13558 continue;
13559
13560 if (uj) {
13561 if (first)
13562 first = false;
13563 else
13564 vty_out(vty, ",\n");
13565 vty_out(vty, "\"%s\":",
13566 get_afi_safi_str(afi, safi, true));
13567 } else
13568 vty_out(vty, "\nFor address family: %s\n",
13569 get_afi_safi_str(afi, safi, false));
13570
13571 peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13572 show_flags);
13573 }
13574 }
13575 if (uj)
13576 vty_out(vty, "}\n");
13577
13578 return CMD_SUCCESS;
13579 }
13580
13581 DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
13582 show_ip_bgp_neighbor_received_prefix_filter_cmd,
13583 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
13584 SHOW_STR
13585 IP_STR
13586 BGP_STR
13587 "Address Family\n"
13588 "Address Family\n"
13589 "Address Family modifier\n"
13590 "Detailed information on TCP and BGP neighbor connections\n"
13591 "Neighbor to display information about\n"
13592 "Neighbor to display information about\n"
13593 "Neighbor on BGP configured interface\n"
13594 "Display information received from a BGP neighbor\n"
13595 "Display the prefixlist filter\n"
13596 JSON_STR)
13597 {
13598 afi_t afi = AFI_IP6;
13599 safi_t safi = SAFI_UNICAST;
13600 char *peerstr = NULL;
13601
13602 char name[BUFSIZ];
13603 union sockunion su;
13604 struct peer *peer;
13605 int count, ret;
13606
13607 int idx = 0;
13608
13609 /* show [ip] bgp */
13610 if (argv_find(argv, argc, "ip", &idx))
13611 afi = AFI_IP;
13612 /* [<ipv4|ipv6> [unicast]] */
13613 if (argv_find(argv, argc, "ipv4", &idx))
13614 afi = AFI_IP;
13615 if (argv_find(argv, argc, "ipv6", &idx))
13616 afi = AFI_IP6;
13617 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13618 argv_find(argv, argc, "neighbors", &idx);
13619 peerstr = argv[++idx]->arg;
13620
13621 bool uj = use_json(argc, argv);
13622
13623 ret = str2sockunion(peerstr, &su);
13624 if (ret < 0) {
13625 peer = peer_lookup_by_conf_if(NULL, peerstr);
13626 if (!peer) {
13627 if (uj)
13628 vty_out(vty, "{}\n");
13629 else
13630 vty_out(vty,
13631 "%% Malformed address or name: %s\n",
13632 peerstr);
13633 return CMD_WARNING;
13634 }
13635 } else {
13636 peer = peer_lookup(NULL, &su);
13637 if (!peer) {
13638 if (uj)
13639 vty_out(vty, "{}\n");
13640 else
13641 vty_out(vty, "No peer\n");
13642 return CMD_WARNING;
13643 }
13644 }
13645
13646 snprintf(name, sizeof(name), "%s.%d.%d", peer->host, afi, safi);
13647 count = prefix_bgp_show_prefix_list(NULL, afi, name, uj);
13648 if (count) {
13649 if (!uj)
13650 vty_out(vty, "Address Family: %s\n",
13651 get_afi_safi_str(afi, safi, false));
13652 prefix_bgp_show_prefix_list(vty, afi, name, uj);
13653 } else {
13654 if (uj)
13655 vty_out(vty, "{}\n");
13656 else
13657 vty_out(vty, "No functional output\n");
13658 }
13659
13660 return CMD_SUCCESS;
13661 }
13662
13663 static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer,
13664 afi_t afi, safi_t safi,
13665 enum bgp_show_type type, bool use_json)
13666 {
13667 uint8_t show_flags = 0;
13668
13669 if (use_json)
13670 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13671
13672 if (!peer || !peer->afc[afi][safi]) {
13673 if (use_json) {
13674 json_object *json_no = NULL;
13675 json_no = json_object_new_object();
13676 json_object_string_add(
13677 json_no, "warning",
13678 "No such neighbor or address family");
13679 vty_out(vty, "%s\n",
13680 json_object_to_json_string(json_no));
13681 json_object_free(json_no);
13682 } else
13683 vty_out(vty, "%% No such neighbor or address family\n");
13684 return CMD_WARNING;
13685 }
13686
13687 /* labeled-unicast routes live in the unicast table */
13688 if (safi == SAFI_LABELED_UNICAST)
13689 safi = SAFI_UNICAST;
13690
13691 return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, show_flags);
13692 }
13693
13694 DEFUN (show_ip_bgp_flowspec_routes_detailed,
13695 show_ip_bgp_flowspec_routes_detailed_cmd,
13696 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" flowspec] detail [json]",
13697 SHOW_STR
13698 IP_STR
13699 BGP_STR
13700 BGP_INSTANCE_HELP_STR
13701 BGP_AFI_HELP_STR
13702 "SAFI Flowspec\n"
13703 "Detailed information on flowspec entries\n"
13704 JSON_STR)
13705 {
13706 afi_t afi = AFI_IP;
13707 safi_t safi = SAFI_UNICAST;
13708 struct bgp *bgp = NULL;
13709 int idx = 0;
13710 bool uj = use_json(argc, argv);
13711 uint8_t show_flags = 0;
13712
13713 if (uj) {
13714 argc--;
13715 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13716 }
13717
13718 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13719 &bgp, uj);
13720 if (!idx)
13721 return CMD_WARNING;
13722
13723 return bgp_show(vty, bgp, afi, safi, bgp_show_type_detail, NULL,
13724 show_flags);
13725 }
13726
13727 DEFUN (show_ip_bgp_neighbor_routes,
13728 show_ip_bgp_neighbor_routes_cmd,
13729 "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]",
13730 SHOW_STR
13731 IP_STR
13732 BGP_STR
13733 BGP_INSTANCE_HELP_STR
13734 BGP_AFI_HELP_STR
13735 BGP_SAFI_WITH_LABEL_HELP_STR
13736 "Detailed information on TCP and BGP neighbor connections\n"
13737 "Neighbor to display information about\n"
13738 "Neighbor to display information about\n"
13739 "Neighbor on BGP configured interface\n"
13740 "Display flap statistics of the routes learned from neighbor\n"
13741 "Display the dampened routes received from neighbor\n"
13742 "Display routes learned from neighbor\n"
13743 JSON_STR)
13744 {
13745 char *peerstr = NULL;
13746 struct bgp *bgp = NULL;
13747 afi_t afi = AFI_IP6;
13748 safi_t safi = SAFI_UNICAST;
13749 struct peer *peer;
13750 enum bgp_show_type sh_type = bgp_show_type_neighbor;
13751 int idx = 0;
13752 bool uj = use_json(argc, argv);
13753
13754 if (uj)
13755 argc--;
13756
13757 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13758 &bgp, uj);
13759 if (!idx)
13760 return CMD_WARNING;
13761
13762 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13763 argv_find(argv, argc, "neighbors", &idx);
13764 peerstr = argv[++idx]->arg;
13765
13766 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
13767 if (!peer)
13768 return CMD_WARNING;
13769
13770 if (argv_find(argv, argc, "flap-statistics", &idx))
13771 sh_type = bgp_show_type_flap_neighbor;
13772 else if (argv_find(argv, argc, "dampened-routes", &idx))
13773 sh_type = bgp_show_type_damp_neighbor;
13774 else if (argv_find(argv, argc, "routes", &idx))
13775 sh_type = bgp_show_type_neighbor;
13776
13777 return bgp_show_neighbor_route(vty, peer, afi, safi, sh_type, uj);
13778 }
13779
13780 struct bgp_table *bgp_distance_table[AFI_MAX][SAFI_MAX];
13781
13782 struct bgp_distance {
13783 /* Distance value for the IP source prefix. */
13784 uint8_t distance;
13785
13786 /* Name of the access-list to be matched. */
13787 char *access_list;
13788 };
13789
13790 DEFUN (show_bgp_afi_vpn_rd_route,
13791 show_bgp_afi_vpn_rd_route_cmd,
13792 "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]",
13793 SHOW_STR
13794 BGP_STR
13795 BGP_AFI_HELP_STR
13796 "Address Family modifier\n"
13797 "Display information for a route distinguisher\n"
13798 "Route Distinguisher\n"
13799 "Network in the BGP routing table to display\n"
13800 "Network in the BGP routing table to display\n"
13801 JSON_STR)
13802 {
13803 int ret;
13804 struct prefix_rd prd;
13805 afi_t afi = AFI_MAX;
13806 int idx = 0;
13807
13808 if (!argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
13809 vty_out(vty, "%% Malformed Address Family\n");
13810 return CMD_WARNING;
13811 }
13812
13813 ret = str2prefix_rd(argv[5]->arg, &prd);
13814 if (!ret) {
13815 vty_out(vty, "%% Malformed Route Distinguisher\n");
13816 return CMD_WARNING;
13817 }
13818
13819 return bgp_show_route(vty, NULL, argv[6]->arg, afi, SAFI_MPLS_VPN, &prd,
13820 0, BGP_PATH_SHOW_ALL, use_json(argc, argv));
13821 }
13822
13823 static struct bgp_distance *bgp_distance_new(void)
13824 {
13825 return XCALLOC(MTYPE_BGP_DISTANCE, sizeof(struct bgp_distance));
13826 }
13827
13828 static void bgp_distance_free(struct bgp_distance *bdistance)
13829 {
13830 XFREE(MTYPE_BGP_DISTANCE, bdistance);
13831 }
13832
13833 int bgp_distance_set(uint8_t distance, const char *ip_str,
13834 const char *access_list_str, afi_t afi, safi_t safi,
13835 char *errmsg, size_t errmsg_len)
13836 {
13837 int ret;
13838 struct prefix p;
13839 struct bgp_dest *dest;
13840 struct bgp_distance *bdistance;
13841
13842 ret = str2prefix(ip_str, &p);
13843 if (ret == 0) {
13844 snprintf(errmsg, errmsg_len, "Malformed prefix\n");
13845 return CMD_WARNING_CONFIG_FAILED;
13846 }
13847
13848 /* Get BGP distance node. */
13849 dest = bgp_node_get(bgp_distance_table[afi][safi], &p);
13850 bdistance = bgp_dest_get_bgp_distance_info(dest);
13851 if (bdistance)
13852 bgp_dest_unlock_node(dest);
13853 else {
13854 bdistance = bgp_distance_new();
13855 bgp_dest_set_bgp_distance_info(dest, bdistance);
13856 }
13857
13858 /* Set distance value. */
13859 bdistance->distance = distance;
13860
13861 /* Reset access-list configuration. */
13862 XFREE(MTYPE_AS_LIST, bdistance->access_list);
13863 if (access_list_str)
13864 bdistance->access_list =
13865 XSTRDUP(MTYPE_AS_LIST, access_list_str);
13866
13867 return CMD_SUCCESS;
13868 }
13869
13870 int bgp_distance_unset(uint8_t distance, const char *ip_str,
13871 const char *access_list_str, afi_t afi, safi_t safi,
13872 char *errmsg, size_t errmsg_len)
13873 {
13874 int ret;
13875 struct prefix p;
13876 struct bgp_dest *dest;
13877 struct bgp_distance *bdistance;
13878
13879 ret = str2prefix(ip_str, &p);
13880 if (ret == 0) {
13881 snprintf(errmsg, errmsg_len, "Malformed prefix\n");
13882 return CMD_WARNING_CONFIG_FAILED;
13883 }
13884
13885 dest = bgp_node_lookup(bgp_distance_table[afi][safi], &p);
13886 if (!dest) {
13887 snprintf(errmsg, errmsg_len, "Can't find specified prefix\n");
13888 return CMD_WARNING_CONFIG_FAILED;
13889 }
13890
13891 bdistance = bgp_dest_get_bgp_distance_info(dest);
13892
13893 if (bdistance->distance != distance) {
13894 snprintf(errmsg, errmsg_len,
13895 "Distance does not match configured\n");
13896 return CMD_WARNING_CONFIG_FAILED;
13897 }
13898
13899 XFREE(MTYPE_AS_LIST, bdistance->access_list);
13900 bgp_distance_free(bdistance);
13901
13902 bgp_dest_set_bgp_path_info(dest, NULL);
13903 bgp_dest_unlock_node(dest);
13904 bgp_dest_unlock_node(dest);
13905
13906 return CMD_SUCCESS;
13907 }
13908
13909 /* Apply BGP information to distance method. */
13910 uint8_t bgp_distance_apply(const struct prefix *p, struct bgp_path_info *pinfo,
13911 afi_t afi, safi_t safi, struct bgp *bgp)
13912 {
13913 struct bgp_dest *dest;
13914 struct prefix q = {0};
13915 struct peer *peer;
13916 struct bgp_distance *bdistance;
13917 struct access_list *alist;
13918 struct bgp_static *bgp_static;
13919
13920 if (!bgp)
13921 return 0;
13922
13923 peer = pinfo->peer;
13924
13925 if (pinfo->attr->distance)
13926 return pinfo->attr->distance;
13927
13928 /* Check source address.
13929 * Note: for aggregate route, peer can have unspec af type.
13930 */
13931 if (pinfo->sub_type != BGP_ROUTE_AGGREGATE
13932 && !sockunion2hostprefix(&peer->su, &q))
13933 return 0;
13934
13935 dest = bgp_node_match(bgp_distance_table[afi][safi], &q);
13936 if (dest) {
13937 bdistance = bgp_dest_get_bgp_distance_info(dest);
13938 bgp_dest_unlock_node(dest);
13939
13940 if (bdistance->access_list) {
13941 alist = access_list_lookup(afi, bdistance->access_list);
13942 if (alist
13943 && access_list_apply(alist, p) == FILTER_PERMIT)
13944 return bdistance->distance;
13945 } else
13946 return bdistance->distance;
13947 }
13948
13949 /* Backdoor check. */
13950 dest = bgp_node_lookup(bgp->route[afi][safi], p);
13951 if (dest) {
13952 bgp_static = bgp_dest_get_bgp_static_info(dest);
13953 bgp_dest_unlock_node(dest);
13954
13955 if (bgp_static->backdoor) {
13956 if (bgp->distance_local[afi][safi])
13957 return bgp->distance_local[afi][safi];
13958 else
13959 return ZEBRA_IBGP_DISTANCE_DEFAULT;
13960 }
13961 }
13962
13963 if (peer->sort == BGP_PEER_EBGP) {
13964 if (bgp->distance_ebgp[afi][safi])
13965 return bgp->distance_ebgp[afi][safi];
13966 return ZEBRA_EBGP_DISTANCE_DEFAULT;
13967 } else if (peer->sort == BGP_PEER_IBGP) {
13968 if (bgp->distance_ibgp[afi][safi])
13969 return bgp->distance_ibgp[afi][safi];
13970 return ZEBRA_IBGP_DISTANCE_DEFAULT;
13971 } else {
13972 if (bgp->distance_local[afi][safi])
13973 return bgp->distance_local[afi][safi];
13974 return ZEBRA_IBGP_DISTANCE_DEFAULT;
13975 }
13976 }
13977
13978 /* If we enter `distance bgp (1-255) (1-255) (1-255)`,
13979 * we should tell ZEBRA update the routes for a specific
13980 * AFI/SAFI to reflect changes in RIB.
13981 */
13982 void bgp_announce_routes_distance_update(struct bgp *bgp, afi_t update_afi,
13983 safi_t update_safi)
13984 {
13985 afi_t afi;
13986 safi_t safi;
13987
13988 FOREACH_AFI_SAFI (afi, safi) {
13989 if (!bgp_fibupd_safi(safi))
13990 continue;
13991
13992 if (afi != update_afi && safi != update_safi)
13993 continue;
13994
13995 if (BGP_DEBUG(zebra, ZEBRA))
13996 zlog_debug(
13997 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
13998 __func__, afi, safi);
13999 bgp_zebra_announce_table(bgp, afi, safi);
14000 }
14001 }
14002
14003 DEFUN_YANG(bgp_distance, bgp_distance_cmd,
14004 "distance bgp (1-255) (1-255) (1-255)",
14005 "Define an administrative distance\n"
14006 "BGP distance\n"
14007 "Distance for routes external to the AS\n"
14008 "Distance for routes internal to the AS\n"
14009 "Distance for local routes\n")
14010 {
14011 int idx_number = 2;
14012 int idx_number_2 = 3;
14013 int idx_number_3 = 4;
14014 afi_t afi;
14015 safi_t safi;
14016 char xpath[XPATH_MAXLEN];
14017
14018 afi = bgp_node_afi(vty);
14019 safi = bgp_node_safi(vty);
14020
14021 snprintf(
14022 xpath, sizeof(xpath),
14023 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/external",
14024 yang_afi_safi_value2identity(afi, safi),
14025 bgp_afi_safi_get_container_str(afi, safi));
14026 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, argv[idx_number]->arg);
14027 snprintf(
14028 xpath, sizeof(xpath),
14029 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/internal",
14030 yang_afi_safi_value2identity(afi, safi),
14031 bgp_afi_safi_get_container_str(afi, safi));
14032 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY,
14033 argv[idx_number_2]->arg);
14034 snprintf(
14035 xpath, sizeof(xpath),
14036 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/local",
14037 yang_afi_safi_value2identity(afi, safi),
14038 bgp_afi_safi_get_container_str(afi, safi));
14039
14040 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY,
14041 argv[idx_number_3]->arg);
14042
14043 return nb_cli_apply_changes(vty, NULL);
14044 }
14045
14046 DEFUN_YANG(no_bgp_distance, no_bgp_distance_cmd,
14047 "no distance bgp [(1-255) (1-255) (1-255)]",
14048 NO_STR
14049 "Define an administrative distance\n"
14050 "BGP distance\n"
14051 "Distance for routes external to the AS\n"
14052 "Distance for routes internal to the AS\n"
14053 "Distance for local routes\n")
14054 {
14055 afi_t afi;
14056 safi_t safi;
14057 char xpath[XPATH_MAXLEN];
14058
14059 afi = bgp_node_afi(vty);
14060 safi = bgp_node_safi(vty);
14061
14062 snprintf(
14063 xpath, sizeof(xpath),
14064 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/external",
14065 yang_afi_safi_value2identity(afi, safi),
14066 bgp_afi_safi_get_container_str(afi, safi));
14067 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, NULL);
14068 snprintf(
14069 xpath, sizeof(xpath),
14070 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/internal",
14071 yang_afi_safi_value2identity(afi, safi),
14072 bgp_afi_safi_get_container_str(afi, safi));
14073 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, NULL);
14074 snprintf(
14075 xpath, sizeof(xpath),
14076 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/local",
14077 yang_afi_safi_value2identity(afi, safi),
14078 bgp_afi_safi_get_container_str(afi, safi));
14079
14080 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, NULL);
14081
14082 return nb_cli_apply_changes(vty, NULL);
14083 }
14084
14085 void cli_show_bgp_global_afi_safi_admin_distance_config(struct vty *vty,
14086 struct lyd_node *dnode,
14087 bool show_defaults)
14088 {
14089 uint8_t distance_ebgp, distance_ibgp, distance_local;
14090
14091 distance_ebgp = yang_dnode_get_uint8(dnode, "./external");
14092 distance_ibgp = yang_dnode_get_uint8(dnode, "./internal");
14093 distance_local = yang_dnode_get_uint8(dnode, "./local");
14094
14095 vty_out(vty, " distance bgp %d %d %d\n", distance_ebgp, distance_ibgp,
14096 distance_local);
14097 }
14098
14099 DEFPY_YANG(bgp_distance_source,
14100 bgp_distance_source_cmd,
14101 "[no] distance (1-255) <A.B.C.D/M | X:X::X:X/M>$prefix [WORD$acl]",
14102 NO_STR
14103 "Define an administrative distance\n"
14104 "Distance value\n"
14105 "IPv4 source prefix\n"
14106 "IPv6 source prefix\n"
14107 "Access list name\n")
14108 {
14109 afi_t afi;
14110 safi_t safi;
14111 char xpath[XPATH_MAXLEN];
14112
14113 afi = bgp_node_afi(vty);
14114 safi = bgp_node_safi(vty);
14115
14116 if (!no) {
14117 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
14118 nb_cli_enqueue_change(vty, "./distance", NB_OP_MODIFY,
14119 distance_str);
14120 if (acl)
14121 nb_cli_enqueue_change(vty,
14122 "./access-list-policy-export",
14123 NB_OP_CREATE, acl);
14124 else
14125 nb_cli_enqueue_change(vty,
14126 "./access-list-policy-export",
14127 NB_OP_DESTROY, NULL);
14128 } else {
14129 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
14130 }
14131
14132 snprintf(
14133 xpath, sizeof(xpath),
14134 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance-route[prefix='%s']",
14135 yang_afi_safi_value2identity(afi, safi),
14136 bgp_afi_safi_get_container_str(afi, safi), prefix_str);
14137
14138 return nb_cli_apply_changes(vty, xpath);
14139 }
14140
14141 void cli_show_bgp_global_afi_safi_unicast_admin_distance_route(
14142 struct vty *vty, struct lyd_node *dnode, bool show_defaults)
14143 {
14144 vty_out(vty, " distance %d %s %s\n",
14145 yang_dnode_get_uint8(dnode, "./distance"),
14146 yang_dnode_get_string(dnode, "./prefix"),
14147 (yang_dnode_exists(dnode, "./access-list-policy-export"))
14148 ? yang_dnode_get_string(dnode,
14149 "./access-list-policy-export")
14150 : "");
14151 }
14152
14153 DEFPY_YANG(
14154 bgp_dampening, bgp_dampening_cmd,
14155 "[no] bgp dampening [(1-45)$halflife [(1-20000)$reuse (1-20000)$suppress (1-255)$max_suppress]]",
14156 NO_STR
14157 "BGP Specific commands\n"
14158 "Enable route-flap dampening\n"
14159 "Half-life time for the penalty\n"
14160 "Value to start reusing a route\n"
14161 "Value to start suppressing a route\n"
14162 "Maximum duration to suppress a stable route\n")
14163 {
14164 afi_t afi;
14165 safi_t safi;
14166 char xpath[XPATH_MAXLEN];
14167
14168 afi = bgp_node_afi(vty);
14169 safi = bgp_node_safi(vty);
14170
14171 if (!no) {
14172 nb_cli_enqueue_change(vty, "./enable", NB_OP_MODIFY, "true");
14173 if (argc == 6) {
14174 nb_cli_enqueue_change(vty, "./reach-decay",
14175 NB_OP_MODIFY, halflife_str);
14176 nb_cli_enqueue_change(vty, "./reuse-above",
14177 NB_OP_MODIFY, reuse_str);
14178 nb_cli_enqueue_change(vty, "./suppress-above",
14179 NB_OP_MODIFY, suppress_str);
14180 nb_cli_enqueue_change(vty, "./unreach-decay",
14181 NB_OP_MODIFY, max_suppress_str);
14182 } if (argc == 3) {
14183 nb_cli_enqueue_change(vty, "./reach-decay",
14184 NB_OP_MODIFY, halflife_str);
14185 }
14186 } else {
14187 nb_cli_enqueue_change(vty, "./enable", NB_OP_MODIFY, "false");
14188 }
14189
14190 snprintf(
14191 xpath, sizeof(xpath),
14192 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/route-flap-dampening",
14193 yang_afi_safi_value2identity(afi, safi),
14194 bgp_afi_safi_get_container_str(afi, safi));
14195
14196 return nb_cli_apply_changes(vty, xpath);
14197 }
14198
14199 void cli_show_bgp_global_afi_safi_route_flap_dampening(struct vty *vty,
14200 struct lyd_node *dnode,
14201 bool show_defaults)
14202 {
14203 if (!yang_dnode_get_bool(dnode, "./enable"))
14204 return;
14205
14206 int half = DEFAULT_HALF_LIFE * 60;
14207 int reuse = DEFAULT_REUSE;
14208 int suppress = DEFAULT_SUPPRESS;
14209 int max;
14210
14211 half = yang_dnode_get_uint8(dnode, "../reach-decay");
14212 reuse = yang_dnode_get_uint16(dnode, "../reuse-above");
14213 suppress = yang_dnode_get_uint16(dnode, "../suppress-above");
14214 max = yang_dnode_get_uint8(dnode, "../unreach-decay");
14215
14216 if (half == DEFAULT_HALF_LIFE * 60 && reuse == DEFAULT_REUSE
14217 && suppress == DEFAULT_SUPPRESS && max == half * 4)
14218 vty_out(vty, " bgp dampening\n");
14219 else if (half != DEFAULT_HALF_LIFE * 60 && reuse == DEFAULT_REUSE
14220 && suppress == DEFAULT_SUPPRESS && max == half * 4)
14221 vty_out(vty, " bgp dampening %u\n", half);
14222 else
14223 vty_out(vty, " bgp dampening %u %d %d %d\n", half, reuse,
14224 suppress, max);
14225 }
14226
14227 /* Display specified route of BGP table. */
14228 static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
14229 const char *ip_str, afi_t afi, safi_t safi,
14230 struct prefix_rd *prd, int prefix_check)
14231 {
14232 int ret;
14233 struct prefix match;
14234 struct bgp_dest *dest;
14235 struct bgp_dest *rm;
14236 struct bgp_path_info *pi;
14237 struct bgp_path_info *pi_temp;
14238 struct bgp *bgp;
14239 struct bgp_table *table;
14240
14241 /* BGP structure lookup. */
14242 if (view_name) {
14243 bgp = bgp_lookup_by_name(view_name);
14244 if (bgp == NULL) {
14245 vty_out(vty, "%% Can't find BGP instance %s\n",
14246 view_name);
14247 return CMD_WARNING;
14248 }
14249 } else {
14250 bgp = bgp_get_default();
14251 if (bgp == NULL) {
14252 vty_out(vty, "%% No BGP process is configured\n");
14253 return CMD_WARNING;
14254 }
14255 }
14256
14257 /* Check IP address argument. */
14258 ret = str2prefix(ip_str, &match);
14259 if (!ret) {
14260 vty_out(vty, "%% address is malformed\n");
14261 return CMD_WARNING;
14262 }
14263
14264 match.family = afi2family(afi);
14265
14266 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
14267 || (safi == SAFI_EVPN)) {
14268 for (dest = bgp_table_top(bgp->rib[AFI_IP][safi]); dest;
14269 dest = bgp_route_next(dest)) {
14270 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
14271
14272 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
14273 continue;
14274 table = bgp_dest_get_bgp_table_info(dest);
14275 if (!table)
14276 continue;
14277 if ((rm = bgp_node_match(table, &match)) == NULL)
14278 continue;
14279
14280 const struct prefix *rm_p = bgp_dest_get_prefix(dest);
14281
14282 if (!prefix_check
14283 || rm_p->prefixlen == match.prefixlen) {
14284 pi = bgp_dest_get_bgp_path_info(rm);
14285 while (pi) {
14286 if (pi->extra && pi->extra->damp_info) {
14287 pi_temp = pi->next;
14288 bgp_damp_info_free(
14289 &pi->extra->damp_info,
14290 &bgp->damp[afi][safi],
14291 1, afi, safi);
14292 pi = pi_temp;
14293 } else
14294 pi = pi->next;
14295 }
14296 }
14297
14298 bgp_dest_unlock_node(rm);
14299 }
14300 } else {
14301 if ((dest = bgp_node_match(bgp->rib[afi][safi], &match))
14302 != NULL) {
14303 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
14304
14305 if (!prefix_check
14306 || dest_p->prefixlen == match.prefixlen) {
14307 pi = bgp_dest_get_bgp_path_info(dest);
14308 while (pi) {
14309 if (pi->extra && pi->extra->damp_info) {
14310 pi_temp = pi->next;
14311 bgp_damp_info_free(
14312 &pi->extra->damp_info,
14313 &bgp->damp[afi][safi],
14314 1, afi, safi);
14315 pi = pi_temp;
14316 } else
14317 pi = pi->next;
14318 }
14319 }
14320
14321 bgp_dest_unlock_node(dest);
14322 }
14323 }
14324
14325 return CMD_SUCCESS;
14326 }
14327
14328 DEFUN (clear_ip_bgp_dampening,
14329 clear_ip_bgp_dampening_cmd,
14330 "clear ip bgp dampening",
14331 CLEAR_STR
14332 IP_STR
14333 BGP_STR
14334 "Clear route flap dampening information\n")
14335 {
14336 VTY_DECLVAR_CONTEXT(bgp, bgp);
14337 bgp_damp_info_clean(&bgp->damp[AFI_IP][SAFI_UNICAST], AFI_IP,
14338 SAFI_UNICAST);
14339 return CMD_SUCCESS;
14340 }
14341
14342 DEFUN (clear_ip_bgp_dampening_prefix,
14343 clear_ip_bgp_dampening_prefix_cmd,
14344 "clear ip bgp dampening A.B.C.D/M",
14345 CLEAR_STR
14346 IP_STR
14347 BGP_STR
14348 "Clear route flap dampening information\n"
14349 "IPv4 prefix\n")
14350 {
14351 int idx_ipv4_prefixlen = 4;
14352 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4_prefixlen]->arg,
14353 AFI_IP, SAFI_UNICAST, NULL, 1);
14354 }
14355
14356 DEFUN (clear_ip_bgp_dampening_address,
14357 clear_ip_bgp_dampening_address_cmd,
14358 "clear ip bgp dampening A.B.C.D",
14359 CLEAR_STR
14360 IP_STR
14361 BGP_STR
14362 "Clear route flap dampening information\n"
14363 "Network to clear damping information\n")
14364 {
14365 int idx_ipv4 = 4;
14366 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4]->arg, AFI_IP,
14367 SAFI_UNICAST, NULL, 0);
14368 }
14369
14370 DEFUN (clear_ip_bgp_dampening_address_mask,
14371 clear_ip_bgp_dampening_address_mask_cmd,
14372 "clear ip bgp dampening A.B.C.D A.B.C.D",
14373 CLEAR_STR
14374 IP_STR
14375 BGP_STR
14376 "Clear route flap dampening information\n"
14377 "Network to clear damping information\n"
14378 "Network mask\n")
14379 {
14380 int idx_ipv4 = 4;
14381 int idx_ipv4_2 = 5;
14382 int ret;
14383 char prefix_str[BUFSIZ];
14384
14385 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
14386 prefix_str);
14387 if (!ret) {
14388 vty_out(vty, "%% Inconsistent address and mask\n");
14389 return CMD_WARNING;
14390 }
14391
14392 return bgp_clear_damp_route(vty, NULL, prefix_str, AFI_IP, SAFI_UNICAST,
14393 NULL, 0);
14394 }
14395
14396 static void show_bgp_peerhash_entry(struct hash_bucket *bucket, void *arg)
14397 {
14398 struct vty *vty = arg;
14399 struct peer *peer = bucket->data;
14400 char buf[SU_ADDRSTRLEN];
14401
14402 vty_out(vty, "\tPeer: %s %s\n", peer->host,
14403 sockunion2str(&peer->su, buf, sizeof(buf)));
14404 }
14405
14406 DEFUN (show_bgp_listeners,
14407 show_bgp_listeners_cmd,
14408 "show bgp listeners",
14409 SHOW_STR
14410 BGP_STR
14411 "Display Listen Sockets and who created them\n")
14412 {
14413 bgp_dump_listener_info(vty);
14414
14415 return CMD_SUCCESS;
14416 }
14417
14418 DEFUN (show_bgp_peerhash,
14419 show_bgp_peerhash_cmd,
14420 "show bgp peerhash",
14421 SHOW_STR
14422 BGP_STR
14423 "Display information about the BGP peerhash\n")
14424 {
14425 struct list *instances = bm->bgp;
14426 struct listnode *node;
14427 struct bgp *bgp;
14428
14429 for (ALL_LIST_ELEMENTS_RO(instances, node, bgp)) {
14430 vty_out(vty, "BGP: %s\n", bgp->name);
14431 hash_iterate(bgp->peerhash, show_bgp_peerhash_entry,
14432 vty);
14433 }
14434
14435 return CMD_SUCCESS;
14436 }
14437
14438 /* also used for encap safi */
14439 static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
14440 afi_t afi, safi_t safi)
14441 {
14442 struct bgp_dest *pdest;
14443 struct bgp_dest *dest;
14444 struct bgp_table *table;
14445 const struct prefix *p;
14446 const struct prefix_rd *prd;
14447 struct bgp_static *bgp_static;
14448 mpls_label_t label;
14449 char rdbuf[RD_ADDRSTRLEN];
14450
14451 /* Network configuration. */
14452 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
14453 pdest = bgp_route_next(pdest)) {
14454 table = bgp_dest_get_bgp_table_info(pdest);
14455 if (!table)
14456 continue;
14457
14458 for (dest = bgp_table_top(table); dest;
14459 dest = bgp_route_next(dest)) {
14460 bgp_static = bgp_dest_get_bgp_static_info(dest);
14461 if (bgp_static == NULL)
14462 continue;
14463
14464 p = bgp_dest_get_prefix(dest);
14465 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
14466 pdest);
14467
14468 /* "network" configuration display. */
14469 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
14470 label = decode_label(&bgp_static->label);
14471
14472 vty_out(vty, " network %pFX rd %s", p, rdbuf);
14473 if (safi == SAFI_MPLS_VPN)
14474 vty_out(vty, " label %u", label);
14475
14476 if (bgp_static->rmap.name)
14477 vty_out(vty, " route-map %s",
14478 bgp_static->rmap.name);
14479
14480 if (bgp_static->backdoor)
14481 vty_out(vty, " backdoor");
14482
14483 vty_out(vty, "\n");
14484 }
14485 }
14486 }
14487
14488 static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
14489 afi_t afi, safi_t safi)
14490 {
14491 struct bgp_dest *pdest;
14492 struct bgp_dest *dest;
14493 struct bgp_table *table;
14494 const struct prefix *p;
14495 const struct prefix_rd *prd;
14496 struct bgp_static *bgp_static;
14497 char buf[PREFIX_STRLEN * 2];
14498 char buf2[SU_ADDRSTRLEN];
14499 char rdbuf[RD_ADDRSTRLEN];
14500 char esi_buf[ESI_BYTES];
14501
14502 /* Network configuration. */
14503 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
14504 pdest = bgp_route_next(pdest)) {
14505 table = bgp_dest_get_bgp_table_info(pdest);
14506 if (!table)
14507 continue;
14508
14509 for (dest = bgp_table_top(table); dest;
14510 dest = bgp_route_next(dest)) {
14511 bgp_static = bgp_dest_get_bgp_static_info(dest);
14512 if (bgp_static == NULL)
14513 continue;
14514
14515 char *macrouter = NULL;
14516
14517 if (bgp_static->router_mac)
14518 macrouter = prefix_mac2str(
14519 bgp_static->router_mac, NULL, 0);
14520 if (bgp_static->eth_s_id)
14521 esi_to_str(bgp_static->eth_s_id,
14522 esi_buf, sizeof(esi_buf));
14523 p = bgp_dest_get_prefix(dest);
14524 prd = (struct prefix_rd *)bgp_dest_get_prefix(pdest);
14525
14526 /* "network" configuration display. */
14527 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
14528 if (p->u.prefix_evpn.route_type == 5) {
14529 char local_buf[PREFIX_STRLEN];
14530 uint8_t family = is_evpn_prefix_ipaddr_v4((
14531 struct prefix_evpn *)p)
14532 ? AF_INET
14533 : AF_INET6;
14534 inet_ntop(family,
14535 &p->u.prefix_evpn.prefix_addr.ip.ip.addr,
14536 local_buf, PREFIX_STRLEN);
14537 snprintf(buf, sizeof(buf), "%s/%u", local_buf,
14538 p->u.prefix_evpn.prefix_addr
14539 .ip_prefix_length);
14540 } else {
14541 prefix2str(p, buf, sizeof(buf));
14542 }
14543
14544 if (bgp_static->gatewayIp.family == AF_INET
14545 || bgp_static->gatewayIp.family == AF_INET6)
14546 inet_ntop(bgp_static->gatewayIp.family,
14547 &bgp_static->gatewayIp.u.prefix, buf2,
14548 sizeof(buf2));
14549 vty_out(vty,
14550 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
14551 buf, rdbuf,
14552 p->u.prefix_evpn.prefix_addr.eth_tag,
14553 decode_label(&bgp_static->label), esi_buf, buf2,
14554 macrouter);
14555
14556 XFREE(MTYPE_TMP, macrouter);
14557 }
14558 }
14559 }
14560
14561 /* Configuration of static route announcement and aggregate
14562 information. */
14563 void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
14564 safi_t safi)
14565 {
14566 struct bgp_dest *dest;
14567 const struct prefix *p;
14568 struct bgp_static *bgp_static;
14569 struct bgp_aggregate *bgp_aggregate;
14570
14571 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) {
14572 bgp_config_write_network_vpn(vty, bgp, afi, safi);
14573 return;
14574 }
14575
14576 if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
14577 bgp_config_write_network_evpn(vty, bgp, afi, safi);
14578 return;
14579 }
14580
14581 /* Network configuration. */
14582 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
14583 dest = bgp_route_next(dest)) {
14584 bgp_static = bgp_dest_get_bgp_static_info(dest);
14585 if (bgp_static == NULL)
14586 continue;
14587
14588 p = bgp_dest_get_prefix(dest);
14589
14590 vty_out(vty, " network %pFX", p);
14591
14592 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX)
14593 vty_out(vty, " label-index %u",
14594 bgp_static->label_index);
14595
14596 if (bgp_static->rmap.name)
14597 vty_out(vty, " route-map %s", bgp_static->rmap.name);
14598
14599 if (bgp_static->backdoor)
14600 vty_out(vty, " backdoor");
14601
14602 vty_out(vty, "\n");
14603 }
14604
14605 /* Aggregate-address configuration. */
14606 for (dest = bgp_table_top(bgp->aggregate[afi][safi]); dest;
14607 dest = bgp_route_next(dest)) {
14608 bgp_aggregate = bgp_dest_get_bgp_aggregate_info(dest);
14609 if (bgp_aggregate == NULL)
14610 continue;
14611
14612 p = bgp_dest_get_prefix(dest);
14613
14614 vty_out(vty, " aggregate-address %pFX", p);
14615
14616 if (bgp_aggregate->as_set)
14617 vty_out(vty, " as-set");
14618
14619 if (bgp_aggregate->summary_only)
14620 vty_out(vty, " summary-only");
14621
14622 if (bgp_aggregate->rmap.name)
14623 vty_out(vty, " route-map %s", bgp_aggregate->rmap.name);
14624
14625 if (bgp_aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
14626 vty_out(vty, " origin %s",
14627 bgp_origin2str(bgp_aggregate->origin));
14628
14629 if (bgp_aggregate->match_med)
14630 vty_out(vty, " matching-MED-only");
14631
14632 if (bgp_aggregate->suppress_map_name)
14633 vty_out(vty, " suppress-map %s",
14634 bgp_aggregate->suppress_map_name);
14635
14636 vty_out(vty, "\n");
14637 }
14638 }
14639
14640 void bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
14641 safi_t safi)
14642 {
14643 struct bgp_dest *dest;
14644 struct bgp_distance *bdistance;
14645
14646 /* Distance configuration. */
14647 if (bgp->distance_ebgp[afi][safi] && bgp->distance_ibgp[afi][safi]
14648 && bgp->distance_local[afi][safi]
14649 && (bgp->distance_ebgp[afi][safi] != ZEBRA_EBGP_DISTANCE_DEFAULT
14650 || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT
14651 || bgp->distance_local[afi][safi]
14652 != ZEBRA_IBGP_DISTANCE_DEFAULT)) {
14653 vty_out(vty, " distance bgp %d %d %d\n",
14654 bgp->distance_ebgp[afi][safi],
14655 bgp->distance_ibgp[afi][safi],
14656 bgp->distance_local[afi][safi]);
14657 }
14658
14659 for (dest = bgp_table_top(bgp_distance_table[afi][safi]); dest;
14660 dest = bgp_route_next(dest)) {
14661 bdistance = bgp_dest_get_bgp_distance_info(dest);
14662 if (bdistance != NULL)
14663 vty_out(vty, " distance %d %pBD %s\n",
14664 bdistance->distance, dest,
14665 bdistance->access_list ? bdistance->access_list
14666 : "");
14667 }
14668 }
14669
14670 /* Allocate routing table structure and install commands. */
14671 void bgp_route_init(void)
14672 {
14673 afi_t afi;
14674 safi_t safi;
14675
14676 /* Init BGP distance table. */
14677 FOREACH_AFI_SAFI (afi, safi)
14678 bgp_distance_table[afi][safi] = bgp_table_init(NULL, afi, safi);
14679
14680 /* IPv4 BGP commands. */
14681 install_element(BGP_NODE, &bgp_table_map_cmd);
14682 install_element(BGP_NODE, &bgp_network_cmd);
14683 install_element(BGP_NODE, &no_bgp_table_map_cmd);
14684
14685 install_element(BGP_NODE, &aggregate_addressv4_cmd);
14686
14687 /* IPv4 unicast configuration. */
14688 install_element(BGP_IPV4_NODE, &bgp_table_map_cmd);
14689 install_element(BGP_IPV4_NODE, &bgp_network_cmd);
14690 install_element(BGP_IPV4_NODE, &no_bgp_table_map_cmd);
14691
14692 install_element(BGP_IPV4_NODE, &aggregate_addressv4_cmd);
14693
14694 /* IPv4 multicast configuration. */
14695 install_element(BGP_IPV4M_NODE, &bgp_table_map_cmd);
14696 install_element(BGP_IPV4M_NODE, &bgp_network_cmd);
14697 install_element(BGP_IPV4M_NODE, &no_bgp_table_map_cmd);
14698 install_element(BGP_IPV4M_NODE, &aggregate_addressv4_cmd);
14699
14700 /* IPv4 labeled-unicast configuration. */
14701 install_element(BGP_IPV4L_NODE, &bgp_network_cmd);
14702 install_element(BGP_IPV4L_NODE, &aggregate_addressv4_cmd);
14703
14704 install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd);
14705 install_element(VIEW_NODE, &show_ip_bgp_cmd);
14706 install_element(VIEW_NODE, &show_ip_bgp_afi_safi_statistics_cmd);
14707 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_statistics_cmd);
14708 install_element(VIEW_NODE, &show_ip_bgp_json_cmd);
14709 install_element(VIEW_NODE, &show_ip_bgp_route_cmd);
14710 install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd);
14711 install_element(VIEW_NODE, &show_ip_bgp_statistics_all_cmd);
14712
14713 install_element(VIEW_NODE,
14714 &show_ip_bgp_instance_neighbor_advertised_route_cmd);
14715 install_element(VIEW_NODE,
14716 &show_ip_bgp_instance_neighbor_bestpath_route_cmd);
14717 install_element(VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd);
14718 install_element(VIEW_NODE,
14719 &show_ip_bgp_neighbor_received_prefix_filter_cmd);
14720 #ifdef KEEP_OLD_VPN_COMMANDS
14721 install_element(VIEW_NODE, &show_ip_bgp_vpn_all_route_prefix_cmd);
14722 #endif /* KEEP_OLD_VPN_COMMANDS */
14723 install_element(VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd);
14724 install_element(VIEW_NODE,
14725 &show_bgp_l2vpn_evpn_route_prefix_cmd);
14726
14727 /* BGP dampening clear commands */
14728 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
14729 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_prefix_cmd);
14730
14731 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd);
14732 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd);
14733
14734 /* prefix count */
14735 install_element(ENABLE_NODE,
14736 &show_ip_bgp_instance_neighbor_prefix_counts_cmd);
14737 #ifdef KEEP_OLD_VPN_COMMANDS
14738 install_element(ENABLE_NODE,
14739 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd);
14740 #endif /* KEEP_OLD_VPN_COMMANDS */
14741
14742 /* New config IPv6 BGP commands. */
14743 install_element(BGP_IPV6_NODE, &bgp_table_map_cmd);
14744 install_element(BGP_IPV6_NODE, &ipv6_bgp_network_cmd);
14745 install_element(BGP_IPV6_NODE, &no_bgp_table_map_cmd);
14746
14747 install_element(BGP_IPV6_NODE, &aggregate_addressv6_cmd);
14748
14749 install_element(BGP_IPV6M_NODE, &ipv6_bgp_network_cmd);
14750
14751 /* IPv6 labeled unicast address family. */
14752 install_element(BGP_IPV6L_NODE, &ipv6_bgp_network_cmd);
14753 install_element(BGP_IPV6L_NODE, &aggregate_addressv6_cmd);
14754
14755 install_element(BGP_NODE, &bgp_distance_cmd);
14756 install_element(BGP_NODE, &no_bgp_distance_cmd);
14757 install_element(BGP_NODE, &bgp_distance_source_cmd);
14758 install_element(BGP_IPV4_NODE, &bgp_distance_cmd);
14759 install_element(BGP_IPV4_NODE, &no_bgp_distance_cmd);
14760 install_element(BGP_IPV4_NODE, &bgp_distance_source_cmd);
14761 install_element(BGP_IPV4M_NODE, &bgp_distance_cmd);
14762 install_element(BGP_IPV4M_NODE, &no_bgp_distance_cmd);
14763 install_element(BGP_IPV4M_NODE, &bgp_distance_source_cmd);
14764 install_element(BGP_IPV6_NODE, &bgp_distance_cmd);
14765 install_element(BGP_IPV6_NODE, &no_bgp_distance_cmd);
14766 install_element(BGP_IPV6_NODE, &bgp_distance_source_cmd);
14767 install_element(BGP_IPV6M_NODE, &bgp_distance_cmd);
14768 install_element(BGP_IPV6M_NODE, &no_bgp_distance_cmd);
14769 install_element(BGP_IPV6M_NODE, &bgp_distance_source_cmd);
14770
14771 /* BGP dampening */
14772 install_element(BGP_NODE, &bgp_dampening_cmd);
14773 install_element(BGP_IPV4_NODE, &bgp_dampening_cmd);
14774 install_element(BGP_IPV4M_NODE, &bgp_dampening_cmd);
14775 install_element(BGP_IPV4L_NODE, &bgp_dampening_cmd);
14776 install_element(BGP_IPV6_NODE, &bgp_dampening_cmd);
14777 install_element(BGP_IPV6M_NODE, &bgp_dampening_cmd);
14778 install_element(BGP_IPV6L_NODE, &bgp_dampening_cmd);
14779
14780 /* Large Communities */
14781 install_element(VIEW_NODE, &show_ip_bgp_large_community_list_cmd);
14782 install_element(VIEW_NODE, &show_ip_bgp_large_community_cmd);
14783
14784 /* show bgp ipv4 flowspec detailed */
14785 install_element(VIEW_NODE, &show_ip_bgp_flowspec_routes_detailed_cmd);
14786
14787 install_element(VIEW_NODE, &show_bgp_listeners_cmd);
14788 install_element(VIEW_NODE, &show_bgp_peerhash_cmd);
14789 }
14790
14791 void bgp_route_finish(void)
14792 {
14793 afi_t afi;
14794 safi_t safi;
14795
14796 FOREACH_AFI_SAFI (afi, safi) {
14797 bgp_table_unlock(bgp_distance_table[afi][safi]);
14798 bgp_distance_table[afi][safi] = NULL;
14799 }
14800 }