1 /* BGP routing information
2 * Copyright (C) 1996, 97, 98, 99 Kunihiro Ishiguro
3 * Copyright (C) 2016 Job Snijders <job@instituut.net>
5 * This file is part of GNU Zebra.
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
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.
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
36 #include "sockunion.h"
39 #include "workqueue.h"
44 #include "lib_errors.h"
46 #include "bgpd/bgpd.h"
47 #include "bgpd/bgp_table.h"
48 #include "bgpd/bgp_route.h"
49 #include "bgpd/bgp_attr.h"
50 #include "bgpd/bgp_debug.h"
51 #include "bgpd/bgp_errors.h"
52 #include "bgpd/bgp_aspath.h"
53 #include "bgpd/bgp_regex.h"
54 #include "bgpd/bgp_community.h"
55 #include "bgpd/bgp_community_alias.h"
56 #include "bgpd/bgp_ecommunity.h"
57 #include "bgpd/bgp_lcommunity.h"
58 #include "bgpd/bgp_clist.h"
59 #include "bgpd/bgp_packet.h"
60 #include "bgpd/bgp_filter.h"
61 #include "bgpd/bgp_fsm.h"
62 #include "bgpd/bgp_mplsvpn.h"
63 #include "bgpd/bgp_nexthop.h"
64 #include "bgpd/bgp_damp.h"
65 #include "bgpd/bgp_advertise.h"
66 #include "bgpd/bgp_zebra.h"
67 #include "bgpd/bgp_vty.h"
68 #include "bgpd/bgp_mpath.h"
69 #include "bgpd/bgp_nht.h"
70 #include "bgpd/bgp_updgrp.h"
71 #include "bgpd/bgp_label.h"
72 #include "bgpd/bgp_addpath.h"
73 #include "bgpd/bgp_mac.h"
74 #include "bgpd/bgp_network.h"
75 #include "bgpd/bgp_trace.h"
76 #include "bgpd/bgp_rpki.h"
79 #include "bgpd/rfapi/rfapi_backend.h"
80 #include "bgpd/rfapi/vnc_import_bgp.h"
81 #include "bgpd/rfapi/vnc_export_bgp.h"
83 #include "bgpd/bgp_encap_types.h"
84 #include "bgpd/bgp_encap_tlv.h"
85 #include "bgpd/bgp_evpn.h"
86 #include "bgpd/bgp_evpn_mh.h"
87 #include "bgpd/bgp_evpn_vty.h"
88 #include "bgpd/bgp_flowspec.h"
89 #include "bgpd/bgp_flowspec_util.h"
90 #include "bgpd/bgp_pbr.h"
91 #include "northbound.h"
92 #include "northbound_cli.h"
93 #include "bgpd/bgp_nb.h"
95 #ifndef VTYSH_EXTRACT_PL
96 #include "bgpd/bgp_route_clippy.c"
99 DEFINE_HOOK(bgp_snmp_update_stats
,
100 (struct bgp_node
*rn
, struct bgp_path_info
*pi
, bool added
),
103 DEFINE_HOOK(bgp_rpki_prefix_status
,
104 (struct peer
*peer
, struct attr
*attr
,
105 const struct prefix
*prefix
),
106 (peer
, attr
, prefix
));
108 /* Extern from bgp_dump.c */
109 extern const char *bgp_origin_str
[];
110 extern const char *bgp_origin_long_str
[];
113 #define PMSI_TNLTYPE_STR_NO_INFO "No info"
114 #define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
115 static const struct message bgp_pmsi_tnltype_str
[] = {
116 {PMSI_TNLTYPE_NO_INFO
, PMSI_TNLTYPE_STR_NO_INFO
},
117 {PMSI_TNLTYPE_RSVP_TE_P2MP
, "RSVP-TE P2MP"},
118 {PMSI_TNLTYPE_MLDP_P2MP
, "mLDP P2MP"},
119 {PMSI_TNLTYPE_PIM_SSM
, "PIM-SSM"},
120 {PMSI_TNLTYPE_PIM_SM
, "PIM-SM"},
121 {PMSI_TNLTYPE_PIM_BIDIR
, "PIM-BIDIR"},
122 {PMSI_TNLTYPE_INGR_REPL
, "Ingress Replication"},
123 {PMSI_TNLTYPE_MLDP_MP2MP
, "mLDP MP2MP"},
127 #define VRFID_NONE_STR "-"
128 #define SOFT_RECONFIG_TASK_MAX_PREFIX 25000
130 DEFINE_HOOK(bgp_process
,
131 (struct bgp
* bgp
, afi_t afi
, safi_t safi
, struct bgp_dest
*bn
,
132 struct peer
*peer
, bool withdraw
),
133 (bgp
, afi
, safi
, bn
, peer
, withdraw
));
135 /** Test if path is suppressed. */
136 static bool bgp_path_suppressed(struct bgp_path_info
*pi
)
138 if (pi
->extra
== NULL
|| pi
->extra
->aggr_suppressors
== NULL
)
141 return listcount(pi
->extra
->aggr_suppressors
) > 0;
144 struct bgp_dest
*bgp_afi_node_get(struct bgp_table
*table
, afi_t afi
,
145 safi_t safi
, const struct prefix
*p
,
146 struct prefix_rd
*prd
)
148 struct bgp_dest
*dest
;
149 struct bgp_dest
*pdest
= NULL
;
153 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
154 || (safi
== SAFI_EVPN
)) {
155 pdest
= bgp_node_get(table
, (struct prefix
*)prd
);
157 if (!bgp_dest_has_bgp_path_info_data(pdest
))
158 bgp_dest_set_bgp_table_info(
159 pdest
, bgp_table_init(table
->bgp
, afi
, safi
));
161 bgp_dest_unlock_node(pdest
);
162 table
= bgp_dest_get_bgp_table_info(pdest
);
165 dest
= bgp_node_get(table
, p
);
167 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
168 || (safi
== SAFI_EVPN
))
174 struct bgp_dest
*bgp_afi_node_lookup(struct bgp_table
*table
, afi_t afi
,
175 safi_t safi
, const struct prefix
*p
,
176 struct prefix_rd
*prd
)
178 struct bgp_dest
*dest
;
179 struct bgp_dest
*pdest
= NULL
;
184 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
185 || (safi
== SAFI_EVPN
)) {
186 pdest
= bgp_node_lookup(table
, (struct prefix
*)prd
);
190 if (!bgp_dest_has_bgp_path_info_data(pdest
)) {
191 bgp_dest_unlock_node(pdest
);
195 table
= bgp_dest_get_bgp_table_info(pdest
);
198 dest
= bgp_node_lookup(table
, p
);
203 /* Allocate bgp_path_info_extra */
204 static struct bgp_path_info_extra
*bgp_path_info_extra_new(void)
206 struct bgp_path_info_extra
*new;
207 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA
,
208 sizeof(struct bgp_path_info_extra
));
209 new->label
[0] = MPLS_INVALID_LABEL
;
211 new->bgp_fs_pbr
= NULL
;
212 new->bgp_fs_iprule
= NULL
;
216 void bgp_path_info_extra_free(struct bgp_path_info_extra
**extra
)
218 struct bgp_path_info_extra
*e
;
220 if (!extra
|| !*extra
)
227 struct bgp_path_info
*bpi
= (struct bgp_path_info
*)e
->parent
;
230 /* FIXME: since multiple e may have the same e->parent
231 * and e->parent->net is holding a refcount for each
232 * of them, we need to do some fudging here.
234 * WARNING: if bpi->net->lock drops to 0, bpi may be
235 * freed as well (because bpi->net was holding the
236 * last reference to bpi) => write after free!
240 bpi
= bgp_path_info_lock(bpi
);
241 refcount
= bgp_dest_get_lock_count(bpi
->net
) - 1;
242 bgp_dest_unlock_node((struct bgp_dest
*)bpi
->net
);
245 bgp_path_info_unlock(bpi
);
247 bgp_path_info_unlock(e
->parent
);
252 bgp_unlock(e
->bgp_orig
);
254 if (e
->aggr_suppressors
)
255 list_delete(&e
->aggr_suppressors
);
258 bgp_evpn_path_mh_info_free(e
->mh_info
);
260 if ((*extra
)->bgp_fs_iprule
)
261 list_delete(&((*extra
)->bgp_fs_iprule
));
262 if ((*extra
)->bgp_fs_pbr
)
263 list_delete(&((*extra
)->bgp_fs_pbr
));
264 XFREE(MTYPE_BGP_ROUTE_EXTRA
, *extra
);
267 /* Get bgp_path_info extra information for the given bgp_path_info, lazy
268 * allocated if required.
270 struct bgp_path_info_extra
*bgp_path_info_extra_get(struct bgp_path_info
*pi
)
273 pi
->extra
= bgp_path_info_extra_new();
277 /* Free bgp route information. */
278 static void bgp_path_info_free(struct bgp_path_info
*path
)
280 bgp_attr_unintern(&path
->attr
);
282 bgp_unlink_nexthop(path
);
283 bgp_path_info_extra_free(&path
->extra
);
284 bgp_path_info_mpath_free(&path
->mpath
);
286 bgp_addpath_free_info_data(&path
->tx_addpath
,
287 &path
->net
->tx_addpath
);
289 peer_unlock(path
->peer
); /* bgp_path_info peer reference */
291 XFREE(MTYPE_BGP_ROUTE
, path
);
294 struct bgp_path_info
*bgp_path_info_lock(struct bgp_path_info
*path
)
300 struct bgp_path_info
*bgp_path_info_unlock(struct bgp_path_info
*path
)
302 assert(path
&& path
->lock
> 0);
305 if (path
->lock
== 0) {
307 zlog_debug ("%s: unlocked and freeing", __func__
);
308 zlog_backtrace (LOG_DEBUG
);
310 bgp_path_info_free(path
);
317 zlog_debug ("%s: unlocked to 1", __func__
);
318 zlog_backtrace (LOG_DEBUG
);
325 /* This function sets flag BGP_NODE_SELECT_DEFER based on condition */
326 static int bgp_dest_set_defer_flag(struct bgp_dest
*dest
, bool delete)
329 struct bgp_path_info
*old_pi
, *nextpi
;
330 bool set_flag
= false;
331 struct bgp
*bgp
= NULL
;
332 struct bgp_table
*table
= NULL
;
336 /* If the flag BGP_NODE_SELECT_DEFER is set and new path is added
337 * then the route selection is deferred
339 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
) && (!delete))
342 if (CHECK_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
)) {
343 if (BGP_DEBUG(update
, UPDATE_OUT
))
345 "Route %pBD is in workqueue and being processed, not deferred.",
351 table
= bgp_dest_table(dest
);
358 for (old_pi
= bgp_dest_get_bgp_path_info(dest
);
359 (old_pi
!= NULL
) && (nextpi
= old_pi
->next
, 1); old_pi
= nextpi
) {
360 if (CHECK_FLAG(old_pi
->flags
, BGP_PATH_SELECTED
))
363 /* Route selection is deferred if there is a stale path which
364 * which indicates peer is in restart mode
366 if (CHECK_FLAG(old_pi
->flags
, BGP_PATH_STALE
)
367 && (old_pi
->sub_type
== BGP_ROUTE_NORMAL
)) {
370 /* If the peer is graceful restart capable and peer is
371 * restarting mode, set the flag BGP_NODE_SELECT_DEFER
374 if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer
)
375 && BGP_PEER_RESTARTING_MODE(peer
)
377 && old_pi
->sub_type
== BGP_ROUTE_NORMAL
)) {
385 /* Set the flag BGP_NODE_SELECT_DEFER if route selection deferral timer
388 if (set_flag
&& table
) {
389 if (bgp
&& (bgp
->gr_info
[afi
][safi
].t_select_deferral
)) {
390 if (!CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
))
391 bgp
->gr_info
[afi
][safi
].gr_deferred
++;
392 SET_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
);
393 if (BGP_DEBUG(update
, UPDATE_OUT
))
394 zlog_debug("DEFER route %pBD, dest %p", dest
,
402 void bgp_path_info_add(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
404 struct bgp_path_info
*top
;
406 top
= bgp_dest_get_bgp_path_info(dest
);
412 bgp_dest_set_bgp_path_info(dest
, pi
);
414 bgp_path_info_lock(pi
);
415 bgp_dest_lock_node(dest
);
416 peer_lock(pi
->peer
); /* bgp_path_info peer reference */
417 bgp_dest_set_defer_flag(dest
, false);
418 hook_call(bgp_snmp_update_stats
, dest
, pi
, true);
421 /* Do the actual removal of info from RIB, for use by bgp_process
422 completion callback *only* */
423 void bgp_path_info_reap(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
426 pi
->next
->prev
= pi
->prev
;
428 pi
->prev
->next
= pi
->next
;
430 bgp_dest_set_bgp_path_info(dest
, pi
->next
);
432 bgp_path_info_mpath_dequeue(pi
);
433 bgp_path_info_unlock(pi
);
434 hook_call(bgp_snmp_update_stats
, dest
, pi
, false);
435 bgp_dest_unlock_node(dest
);
438 void bgp_path_info_delete(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
440 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_REMOVED
);
441 /* set of previous already took care of pcount */
442 UNSET_FLAG(pi
->flags
, BGP_PATH_VALID
);
445 /* undo the effects of a previous call to bgp_path_info_delete; typically
446 called when a route is deleted and then quickly re-added before the
447 deletion has been processed */
448 void bgp_path_info_restore(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
450 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_REMOVED
);
451 /* unset of previous already took care of pcount */
452 SET_FLAG(pi
->flags
, BGP_PATH_VALID
);
455 /* Adjust pcount as required */
456 static void bgp_pcount_adjust(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
458 struct bgp_table
*table
;
460 assert(dest
&& bgp_dest_table(dest
));
461 assert(pi
&& pi
->peer
&& pi
->peer
->bgp
);
463 table
= bgp_dest_table(dest
);
465 if (pi
->peer
== pi
->peer
->bgp
->peer_self
)
468 if (!BGP_PATH_COUNTABLE(pi
)
469 && CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
471 UNSET_FLAG(pi
->flags
, BGP_PATH_COUNTED
);
473 /* slight hack, but more robust against errors. */
474 if (pi
->peer
->pcount
[table
->afi
][table
->safi
])
475 pi
->peer
->pcount
[table
->afi
][table
->safi
]--;
477 flog_err(EC_LIB_DEVELOPMENT
,
478 "Asked to decrement 0 prefix count for peer");
479 } else if (BGP_PATH_COUNTABLE(pi
)
480 && !CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
481 SET_FLAG(pi
->flags
, BGP_PATH_COUNTED
);
482 pi
->peer
->pcount
[table
->afi
][table
->safi
]++;
486 static int bgp_label_index_differs(struct bgp_path_info
*pi1
,
487 struct bgp_path_info
*pi2
)
489 return (!(pi1
->attr
->label_index
== pi2
->attr
->label_index
));
492 /* Set/unset bgp_path_info flags, adjusting any other state as needed.
493 * This is here primarily to keep prefix-count in check.
495 void bgp_path_info_set_flag(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
498 SET_FLAG(pi
->flags
, flag
);
500 /* early bath if we know it's not a flag that changes countability state
502 if (!CHECK_FLAG(flag
,
503 BGP_PATH_VALID
| BGP_PATH_HISTORY
| BGP_PATH_REMOVED
))
506 bgp_pcount_adjust(dest
, pi
);
509 void bgp_path_info_unset_flag(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
512 UNSET_FLAG(pi
->flags
, flag
);
514 /* early bath if we know it's not a flag that changes countability state
516 if (!CHECK_FLAG(flag
,
517 BGP_PATH_VALID
| BGP_PATH_HISTORY
| BGP_PATH_REMOVED
))
520 bgp_pcount_adjust(dest
, pi
);
523 /* Get MED value. If MED value is missing and "bgp bestpath
524 missing-as-worst" is specified, treat it as the worst value. */
525 static uint32_t bgp_med_value(struct attr
*attr
, struct bgp
*bgp
)
527 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
530 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_MED_MISSING_AS_WORST
))
537 void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info
*pi
, char *buf
,
540 if (pi
->addpath_rx_id
)
541 snprintf(buf
, buf_len
, "path %s (addpath rxid %d)",
542 pi
->peer
->host
, pi
->addpath_rx_id
);
544 snprintf(buf
, buf_len
, "path %s", pi
->peer
->host
);
547 /* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
549 static int bgp_path_info_cmp(struct bgp
*bgp
, struct bgp_path_info
*new,
550 struct bgp_path_info
*exist
, int *paths_eq
,
551 struct bgp_maxpaths_cfg
*mpath_cfg
, int debug
,
552 char *pfx_buf
, afi_t afi
, safi_t safi
,
553 enum bgp_path_selection_reason
*reason
)
555 const struct prefix
*new_p
;
556 struct attr
*newattr
, *existattr
;
557 bgp_peer_sort_t new_sort
;
558 bgp_peer_sort_t exist_sort
;
564 uint32_t exist_weight
;
565 uint32_t newm
, existm
;
566 struct in_addr new_id
;
567 struct in_addr exist_id
;
570 int internal_as_route
;
573 int igp_metric_ret
= 0;
574 int peer_sort_ret
= -1;
575 char new_buf
[PATH_ADDPATH_STR_BUFFER
];
576 char exist_buf
[PATH_ADDPATH_STR_BUFFER
];
578 uint32_t exist_mm_seq
;
585 bool new_origin
, exist_origin
;
591 *reason
= bgp_path_selection_none
;
593 zlog_debug("%s: new is NULL", pfx_buf
);
598 bgp_path_info_path_with_addpath_rx_str(new, new_buf
,
602 *reason
= bgp_path_selection_first
;
604 zlog_debug("%s: %s is the initial bestpath", pfx_buf
,
610 bgp_path_info_path_with_addpath_rx_str(exist
, exist_buf
,
612 zlog_debug("%s: Comparing %s flags 0x%x with %s flags 0x%x",
613 pfx_buf
, new_buf
, new->flags
, exist_buf
,
618 existattr
= exist
->attr
;
620 new_p
= bgp_dest_get_prefix(new->net
);
622 /* For EVPN routes, we cannot just go by local vs remote, we have to
623 * look at the MAC mobility sequence number, if present.
625 if ((safi
== SAFI_EVPN
)
626 && (new_p
->u
.prefix_evpn
.route_type
== BGP_EVPN_MAC_IP_ROUTE
)) {
627 /* This is an error condition described in RFC 7432 Section
629 * states that in this scenario "the PE MUST alert the operator"
631 * does not state what other action to take. In order to provide
633 * consistency in this scenario we are going to prefer the path
637 if (newattr
->sticky
!= existattr
->sticky
) {
639 prefix2str(new_p
, pfx_buf
,
641 * PREFIX2STR_BUFFER
);
642 bgp_path_info_path_with_addpath_rx_str(
643 new, new_buf
, sizeof(new_buf
));
644 bgp_path_info_path_with_addpath_rx_str(
645 exist
, exist_buf
, sizeof(exist_buf
));
648 if (newattr
->sticky
&& !existattr
->sticky
) {
649 *reason
= bgp_path_selection_evpn_sticky_mac
;
652 "%s: %s wins over %s due to sticky MAC flag",
653 pfx_buf
, new_buf
, exist_buf
);
657 if (!newattr
->sticky
&& existattr
->sticky
) {
658 *reason
= bgp_path_selection_evpn_sticky_mac
;
661 "%s: %s loses to %s due to sticky MAC flag",
662 pfx_buf
, new_buf
, exist_buf
);
667 new_esi
= bgp_evpn_attr_get_esi(newattr
);
668 exist_esi
= bgp_evpn_attr_get_esi(existattr
);
669 if (bgp_evpn_is_esi_valid(new_esi
) &&
670 !memcmp(new_esi
, exist_esi
, sizeof(esi_t
))) {
676 /* If both paths have the same non-zero ES and
677 * one path is local it wins.
678 * PS: Note the local path wins even if the remote
679 * has the higher MM seq. The local path's
680 * MM seq will be fixed up to match the highest
681 * rem seq, subsequently.
684 char esi_buf
[ESI_STR_LEN
];
686 if (bgp_evpn_is_path_local(bgp
, new)) {
687 *reason
= bgp_path_selection_evpn_local_path
;
690 "%s: %s wins over %s as ES %s is same and local",
691 pfx_buf
, new_buf
, exist_buf
,
692 esi_to_str(new_esi
, esi_buf
,
696 if (bgp_evpn_is_path_local(bgp
, exist
)) {
697 *reason
= bgp_path_selection_evpn_local_path
;
700 "%s: %s loses to %s as ES %s is same and local",
701 pfx_buf
, new_buf
, exist_buf
,
702 esi_to_str(new_esi
, esi_buf
,
708 new_mm_seq
= mac_mobility_seqnum(newattr
);
709 exist_mm_seq
= mac_mobility_seqnum(existattr
);
711 if (new_mm_seq
> exist_mm_seq
) {
712 *reason
= bgp_path_selection_evpn_seq
;
715 "%s: %s wins over %s due to MM seq %u > %u",
716 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
721 if (new_mm_seq
< exist_mm_seq
) {
722 *reason
= bgp_path_selection_evpn_seq
;
725 "%s: %s loses to %s due to MM seq %u < %u",
726 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
731 /* if the sequence numbers and ESI are the same and one path
732 * is non-proxy it wins (over proxy)
734 new_proxy
= bgp_evpn_attr_is_proxy(newattr
);
735 old_proxy
= bgp_evpn_attr_is_proxy(existattr
);
736 if (same_esi
&& bgp_evpn_attr_is_local_es(newattr
) &&
737 old_proxy
!= new_proxy
) {
739 *reason
= bgp_path_selection_evpn_non_proxy
;
742 "%s: %s wins over %s, same seq/es and non-proxy",
743 pfx_buf
, new_buf
, exist_buf
);
747 *reason
= bgp_path_selection_evpn_non_proxy
;
750 "%s: %s loses to %s, same seq/es and non-proxy",
751 pfx_buf
, new_buf
, exist_buf
);
756 * if sequence numbers are the same path with the lowest IP
759 nh_cmp
= bgp_path_info_nexthop_cmp(new, exist
);
761 *reason
= bgp_path_selection_evpn_lower_ip
;
764 "%s: %s wins over %s due to same MM seq %u and lower IP %pI4",
765 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
766 &new->attr
->nexthop
);
770 *reason
= bgp_path_selection_evpn_lower_ip
;
773 "%s: %s loses to %s due to same MM seq %u and higher IP %pI4",
774 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
775 &new->attr
->nexthop
);
780 /* 1. Weight check. */
781 new_weight
= newattr
->weight
;
782 exist_weight
= existattr
->weight
;
784 if (new_weight
> exist_weight
) {
785 *reason
= bgp_path_selection_weight
;
787 zlog_debug("%s: %s wins over %s due to weight %d > %d",
788 pfx_buf
, new_buf
, exist_buf
, new_weight
,
793 if (new_weight
< exist_weight
) {
794 *reason
= bgp_path_selection_weight
;
796 zlog_debug("%s: %s loses to %s due to weight %d < %d",
797 pfx_buf
, new_buf
, exist_buf
, new_weight
,
802 /* 2. Local preference check. */
803 new_pref
= exist_pref
= bgp
->default_local_pref
;
805 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
806 new_pref
= newattr
->local_pref
;
807 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
808 exist_pref
= existattr
->local_pref
;
810 if (new_pref
> exist_pref
) {
811 *reason
= bgp_path_selection_local_pref
;
814 "%s: %s wins over %s due to localpref %d > %d",
815 pfx_buf
, new_buf
, exist_buf
, new_pref
,
820 if (new_pref
< exist_pref
) {
821 *reason
= bgp_path_selection_local_pref
;
824 "%s: %s loses to %s due to localpref %d < %d",
825 pfx_buf
, new_buf
, exist_buf
, new_pref
,
830 /* 3. Local route check. We prefer:
832 * - BGP_ROUTE_AGGREGATE
833 * - BGP_ROUTE_REDISTRIBUTE
835 new_origin
= !(new->sub_type
== BGP_ROUTE_NORMAL
||
836 new->sub_type
== BGP_ROUTE_IMPORTED
);
837 exist_origin
= !(exist
->sub_type
== BGP_ROUTE_NORMAL
||
838 exist
->sub_type
== BGP_ROUTE_IMPORTED
);
840 if (new_origin
&& !exist_origin
) {
841 *reason
= bgp_path_selection_local_route
;
844 "%s: %s wins over %s due to preferred BGP_ROUTE type",
845 pfx_buf
, new_buf
, exist_buf
);
849 if (!new_origin
&& exist_origin
) {
850 *reason
= bgp_path_selection_local_route
;
853 "%s: %s loses to %s due to preferred BGP_ROUTE type",
854 pfx_buf
, new_buf
, exist_buf
);
858 /* 4. AS path length check. */
859 if (!CHECK_FLAG(bgp
->flags
, BGP_FLAG_ASPATH_IGNORE
)) {
860 int exist_hops
= aspath_count_hops(existattr
->aspath
);
861 int exist_confeds
= aspath_count_confeds(existattr
->aspath
);
863 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_ASPATH_CONFED
)) {
866 aspath_hops
= aspath_count_hops(newattr
->aspath
);
867 aspath_hops
+= aspath_count_confeds(newattr
->aspath
);
869 if (aspath_hops
< (exist_hops
+ exist_confeds
)) {
870 *reason
= bgp_path_selection_confed_as_path
;
873 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
874 pfx_buf
, new_buf
, exist_buf
,
876 (exist_hops
+ exist_confeds
));
880 if (aspath_hops
> (exist_hops
+ exist_confeds
)) {
881 *reason
= bgp_path_selection_confed_as_path
;
884 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
885 pfx_buf
, new_buf
, exist_buf
,
887 (exist_hops
+ exist_confeds
));
891 int newhops
= aspath_count_hops(newattr
->aspath
);
893 if (newhops
< exist_hops
) {
894 *reason
= bgp_path_selection_as_path
;
897 "%s: %s wins over %s due to aspath hopcount %d < %d",
898 pfx_buf
, new_buf
, exist_buf
,
899 newhops
, exist_hops
);
903 if (newhops
> exist_hops
) {
904 *reason
= bgp_path_selection_as_path
;
907 "%s: %s loses to %s due to aspath hopcount %d > %d",
908 pfx_buf
, new_buf
, exist_buf
,
909 newhops
, exist_hops
);
915 /* 5. Origin check. */
916 if (newattr
->origin
< existattr
->origin
) {
917 *reason
= bgp_path_selection_origin
;
919 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
920 pfx_buf
, new_buf
, exist_buf
,
921 bgp_origin_long_str
[newattr
->origin
],
922 bgp_origin_long_str
[existattr
->origin
]);
926 if (newattr
->origin
> existattr
->origin
) {
927 *reason
= bgp_path_selection_origin
;
929 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
930 pfx_buf
, new_buf
, exist_buf
,
931 bgp_origin_long_str
[newattr
->origin
],
932 bgp_origin_long_str
[existattr
->origin
]);
937 internal_as_route
= (aspath_count_hops(newattr
->aspath
) == 0
938 && aspath_count_hops(existattr
->aspath
) == 0);
939 confed_as_route
= (aspath_count_confeds(newattr
->aspath
) > 0
940 && aspath_count_confeds(existattr
->aspath
) > 0
941 && aspath_count_hops(newattr
->aspath
) == 0
942 && aspath_count_hops(existattr
->aspath
) == 0);
944 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_ALWAYS_COMPARE_MED
)
945 || (CHECK_FLAG(bgp
->flags
, BGP_FLAG_MED_CONFED
) && confed_as_route
)
946 || aspath_cmp_left(newattr
->aspath
, existattr
->aspath
)
947 || aspath_cmp_left_confed(newattr
->aspath
, existattr
->aspath
)
948 || internal_as_route
) {
949 new_med
= bgp_med_value(new->attr
, bgp
);
950 exist_med
= bgp_med_value(exist
->attr
, bgp
);
952 if (new_med
< exist_med
) {
953 *reason
= bgp_path_selection_med
;
956 "%s: %s wins over %s due to MED %d < %d",
957 pfx_buf
, new_buf
, exist_buf
, new_med
,
962 if (new_med
> exist_med
) {
963 *reason
= bgp_path_selection_med
;
966 "%s: %s loses to %s due to MED %d > %d",
967 pfx_buf
, new_buf
, exist_buf
, new_med
,
973 /* 7. Peer type check. */
974 new_sort
= new->peer
->sort
;
975 exist_sort
= exist
->peer
->sort
;
977 if (new_sort
== BGP_PEER_EBGP
978 && (exist_sort
== BGP_PEER_IBGP
|| exist_sort
== BGP_PEER_CONFED
)) {
979 *reason
= bgp_path_selection_peer
;
982 "%s: %s wins over %s due to eBGP peer > iBGP peer",
983 pfx_buf
, new_buf
, exist_buf
);
984 if (!CHECK_FLAG(bgp
->flags
, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX
))
989 if (exist_sort
== BGP_PEER_EBGP
990 && (new_sort
== BGP_PEER_IBGP
|| new_sort
== BGP_PEER_CONFED
)) {
991 *reason
= bgp_path_selection_peer
;
994 "%s: %s loses to %s due to iBGP peer < eBGP peer",
995 pfx_buf
, new_buf
, exist_buf
);
996 if (!CHECK_FLAG(bgp
->flags
, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX
))
1001 /* 8. IGP metric check. */
1005 newm
= new->extra
->igpmetric
;
1007 existm
= exist
->extra
->igpmetric
;
1009 if (newm
< existm
) {
1010 if (debug
&& peer_sort_ret
< 0)
1012 "%s: %s wins over %s due to IGP metric %u < %u",
1013 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
1017 if (newm
> existm
) {
1018 if (debug
&& peer_sort_ret
< 0)
1020 "%s: %s loses to %s due to IGP metric %u > %u",
1021 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
1025 /* 9. Same IGP metric. Compare the cluster list length as
1026 representative of IGP hops metric. Rewrite the metric value
1027 pair (newm, existm) with the cluster list length. Prefer the
1028 path with smaller cluster list length. */
1029 if (newm
== existm
) {
1030 if (peer_sort_lookup(new->peer
) == BGP_PEER_IBGP
1031 && peer_sort_lookup(exist
->peer
) == BGP_PEER_IBGP
1032 && (mpath_cfg
== NULL
1034 mpath_cfg
->ibgp_flags
,
1035 BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN
))) {
1036 newm
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
1037 existm
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
1039 if (newm
< existm
) {
1040 if (debug
&& peer_sort_ret
< 0)
1042 "%s: %s wins over %s due to CLUSTER_LIST length %u < %u",
1043 pfx_buf
, new_buf
, exist_buf
,
1048 if (newm
> existm
) {
1049 if (debug
&& peer_sort_ret
< 0)
1051 "%s: %s loses to %s due to CLUSTER_LIST length %u > %u",
1052 pfx_buf
, new_buf
, exist_buf
,
1059 /* 10. confed-external vs. confed-internal */
1060 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
1061 if (new_sort
== BGP_PEER_CONFED
1062 && exist_sort
== BGP_PEER_IBGP
) {
1063 *reason
= bgp_path_selection_confed
;
1066 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
1067 pfx_buf
, new_buf
, exist_buf
);
1068 if (!CHECK_FLAG(bgp
->flags
,
1069 BGP_FLAG_PEERTYPE_MULTIPATH_RELAX
))
1074 if (exist_sort
== BGP_PEER_CONFED
1075 && new_sort
== BGP_PEER_IBGP
) {
1076 *reason
= bgp_path_selection_confed
;
1079 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
1080 pfx_buf
, new_buf
, exist_buf
);
1081 if (!CHECK_FLAG(bgp
->flags
,
1082 BGP_FLAG_PEERTYPE_MULTIPATH_RELAX
))
1088 /* 11. Maximum path check. */
1089 if (newm
== existm
) {
1090 /* If one path has a label but the other does not, do not treat
1091 * them as equals for multipath
1093 if ((new->extra
&&bgp_is_valid_label(&new->extra
->label
[0]))
1095 && bgp_is_valid_label(&exist
->extra
->label
[0]))) {
1098 "%s: %s and %s cannot be multipath, one has a label while the other does not",
1099 pfx_buf
, new_buf
, exist_buf
);
1100 } else if (CHECK_FLAG(bgp
->flags
,
1101 BGP_FLAG_ASPATH_MULTIPATH_RELAX
)) {
1104 * For the two paths, all comparison steps till IGP
1106 * have succeeded - including AS_PATH hop count. Since
1108 * bestpath as-path multipath-relax' knob is on, we
1110 * an exact match of AS_PATH. Thus, mark the paths are
1112 * That will trigger both these paths to get into the
1120 "%s: %s and %s are equal via multipath-relax",
1121 pfx_buf
, new_buf
, exist_buf
);
1122 } else if (new->peer
->sort
== BGP_PEER_IBGP
) {
1123 if (aspath_cmp(new->attr
->aspath
,
1124 exist
->attr
->aspath
)) {
1129 "%s: %s and %s are equal via matching aspaths",
1130 pfx_buf
, new_buf
, exist_buf
);
1132 } else if (new->peer
->as
== exist
->peer
->as
) {
1137 "%s: %s and %s are equal via same remote-as",
1138 pfx_buf
, new_buf
, exist_buf
);
1142 * TODO: If unequal cost ibgp multipath is enabled we can
1143 * mark the paths as equal here instead of returning
1146 /* Prior to the addition of BGP_FLAG_PEERTYPE_MULTIPATH_RELAX,
1147 * if either step 7 or 10 (peer type checks) yielded a winner,
1148 * that result was returned immediately. Returning from step 10
1149 * ignored the return value computed in steps 8 and 9 (IGP
1150 * metric checks). In order to preserve that behavior, if
1151 * peer_sort_ret is set, return that rather than igp_metric_ret.
1153 ret
= peer_sort_ret
;
1154 if (peer_sort_ret
< 0) {
1155 ret
= igp_metric_ret
;
1159 "%s: %s wins over %s after IGP metric comparison",
1160 pfx_buf
, new_buf
, exist_buf
);
1163 "%s: %s loses to %s after IGP metric comparison",
1164 pfx_buf
, new_buf
, exist_buf
);
1166 *reason
= bgp_path_selection_igp_metric
;
1172 * At this point, the decision whether to set *paths_eq = 1 has been
1173 * completed. If we deferred returning because of bestpath peer-type
1174 * relax configuration, return now.
1176 if (peer_sort_ret
>= 0)
1177 return peer_sort_ret
;
1179 /* 12. If both paths are external, prefer the path that was received
1180 first (the oldest one). This step minimizes route-flap, since a
1181 newer path won't displace an older one, even if it was the
1182 preferred route based on the additional decision criteria below. */
1183 if (!CHECK_FLAG(bgp
->flags
, BGP_FLAG_COMPARE_ROUTER_ID
)
1184 && new_sort
== BGP_PEER_EBGP
&& exist_sort
== BGP_PEER_EBGP
) {
1185 if (CHECK_FLAG(new->flags
, BGP_PATH_SELECTED
)) {
1186 *reason
= bgp_path_selection_older
;
1189 "%s: %s wins over %s due to oldest external",
1190 pfx_buf
, new_buf
, exist_buf
);
1194 if (CHECK_FLAG(exist
->flags
, BGP_PATH_SELECTED
)) {
1195 *reason
= bgp_path_selection_older
;
1198 "%s: %s loses to %s due to oldest external",
1199 pfx_buf
, new_buf
, exist_buf
);
1204 /* 13. Router-ID comparision. */
1205 /* If one of the paths is "stale", the corresponding peer router-id will
1206 * be 0 and would always win over the other path. If originator id is
1207 * used for the comparision, it will decide which path is better.
1209 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
1210 new_id
.s_addr
= newattr
->originator_id
.s_addr
;
1212 new_id
.s_addr
= new->peer
->remote_id
.s_addr
;
1213 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
1214 exist_id
.s_addr
= existattr
->originator_id
.s_addr
;
1216 exist_id
.s_addr
= exist
->peer
->remote_id
.s_addr
;
1218 if (ntohl(new_id
.s_addr
) < ntohl(exist_id
.s_addr
)) {
1219 *reason
= bgp_path_selection_router_id
;
1222 "%s: %s wins over %s due to Router-ID comparison",
1223 pfx_buf
, new_buf
, exist_buf
);
1227 if (ntohl(new_id
.s_addr
) > ntohl(exist_id
.s_addr
)) {
1228 *reason
= bgp_path_selection_router_id
;
1231 "%s: %s loses to %s due to Router-ID comparison",
1232 pfx_buf
, new_buf
, exist_buf
);
1236 /* 14. Cluster length comparision. */
1237 new_cluster
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
1238 exist_cluster
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
1240 if (new_cluster
< exist_cluster
) {
1241 *reason
= bgp_path_selection_cluster_length
;
1244 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1245 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
1250 if (new_cluster
> exist_cluster
) {
1251 *reason
= bgp_path_selection_cluster_length
;
1254 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1255 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
1260 /* 15. Neighbor address comparision. */
1261 /* Do this only if neither path is "stale" as stale paths do not have
1262 * valid peer information (as the connection may or may not be up).
1264 if (CHECK_FLAG(exist
->flags
, BGP_PATH_STALE
)) {
1265 *reason
= bgp_path_selection_stale
;
1268 "%s: %s wins over %s due to latter path being STALE",
1269 pfx_buf
, new_buf
, exist_buf
);
1273 if (CHECK_FLAG(new->flags
, BGP_PATH_STALE
)) {
1274 *reason
= bgp_path_selection_stale
;
1277 "%s: %s loses to %s due to former path being STALE",
1278 pfx_buf
, new_buf
, exist_buf
);
1282 /* locally configured routes to advertise do not have su_remote */
1283 if (new->peer
->su_remote
== NULL
) {
1284 *reason
= bgp_path_selection_local_configured
;
1287 if (exist
->peer
->su_remote
== NULL
) {
1288 *reason
= bgp_path_selection_local_configured
;
1292 ret
= sockunion_cmp(new->peer
->su_remote
, exist
->peer
->su_remote
);
1295 *reason
= bgp_path_selection_neighbor_ip
;
1298 "%s: %s loses to %s due to Neighor IP comparison",
1299 pfx_buf
, new_buf
, exist_buf
);
1304 *reason
= bgp_path_selection_neighbor_ip
;
1307 "%s: %s wins over %s due to Neighor IP comparison",
1308 pfx_buf
, new_buf
, exist_buf
);
1312 *reason
= bgp_path_selection_default
;
1314 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1315 pfx_buf
, new_buf
, exist_buf
);
1321 int bgp_evpn_path_info_cmp(struct bgp
*bgp
, struct bgp_path_info
*new,
1322 struct bgp_path_info
*exist
, int *paths_eq
)
1324 enum bgp_path_selection_reason reason
;
1325 char pfx_buf
[PREFIX2STR_BUFFER
];
1327 return bgp_path_info_cmp(bgp
, new, exist
, paths_eq
, NULL
, 0, pfx_buf
,
1328 AFI_L2VPN
, SAFI_EVPN
, &reason
);
1331 /* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1332 * is preferred, or 0 if they are the same (usually will only occur if
1333 * multipath is enabled
1334 * This version is compatible with */
1335 int bgp_path_info_cmp_compatible(struct bgp
*bgp
, struct bgp_path_info
*new,
1336 struct bgp_path_info
*exist
, char *pfx_buf
,
1337 afi_t afi
, safi_t safi
,
1338 enum bgp_path_selection_reason
*reason
)
1342 ret
= bgp_path_info_cmp(bgp
, new, exist
, &paths_eq
, NULL
, 0, pfx_buf
,
1356 static enum filter_type
bgp_input_filter(struct peer
*peer
,
1357 const struct prefix
*p
,
1358 struct attr
*attr
, afi_t afi
,
1361 struct bgp_filter
*filter
;
1362 enum filter_type ret
= FILTER_PERMIT
;
1364 filter
= &peer
->filter
[afi
][safi
];
1366 #define FILTER_EXIST_WARN(F, f, filter) \
1367 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
1368 zlog_debug("%s: Could not find configured input %s-list %s!", \
1369 peer->host, #f, F##_IN_NAME(filter));
1371 if (DISTRIBUTE_IN_NAME(filter
)) {
1372 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1374 if (access_list_apply(DISTRIBUTE_IN(filter
), p
)
1381 if (PREFIX_LIST_IN_NAME(filter
)) {
1382 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1384 if (prefix_list_apply(PREFIX_LIST_IN(filter
), p
)
1391 if (FILTER_LIST_IN_NAME(filter
)) {
1392 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1394 if (as_list_apply(FILTER_LIST_IN(filter
), attr
->aspath
)
1395 == AS_FILTER_DENY
) {
1402 if (frrtrace_enabled(frr_bgp
, input_filter
)) {
1403 char pfxprint
[PREFIX2STR_BUFFER
];
1405 prefix2str(p
, pfxprint
, sizeof(pfxprint
));
1406 frrtrace(5, frr_bgp
, input_filter
, peer
, pfxprint
, afi
, safi
,
1407 ret
== FILTER_PERMIT
? "permit" : "deny");
1411 #undef FILTER_EXIST_WARN
1414 static enum filter_type
bgp_output_filter(struct peer
*peer
,
1415 const struct prefix
*p
,
1416 struct attr
*attr
, afi_t afi
,
1419 struct bgp_filter
*filter
;
1420 enum filter_type ret
= FILTER_PERMIT
;
1422 filter
= &peer
->filter
[afi
][safi
];
1424 #define FILTER_EXIST_WARN(F, f, filter) \
1425 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
1426 zlog_debug("%s: Could not find configured output %s-list %s!", \
1427 peer->host, #f, F##_OUT_NAME(filter));
1429 if (DISTRIBUTE_OUT_NAME(filter
)) {
1430 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1432 if (access_list_apply(DISTRIBUTE_OUT(filter
), p
)
1439 if (PREFIX_LIST_OUT_NAME(filter
)) {
1440 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1442 if (prefix_list_apply(PREFIX_LIST_OUT(filter
), p
)
1449 if (FILTER_LIST_OUT_NAME(filter
)) {
1450 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1452 if (as_list_apply(FILTER_LIST_OUT(filter
), attr
->aspath
)
1453 == AS_FILTER_DENY
) {
1459 if (frrtrace_enabled(frr_bgp
, output_filter
)) {
1460 char pfxprint
[PREFIX2STR_BUFFER
];
1462 prefix2str(p
, pfxprint
, sizeof(pfxprint
));
1463 frrtrace(5, frr_bgp
, output_filter
, peer
, pfxprint
, afi
, safi
,
1464 ret
== FILTER_PERMIT
? "permit" : "deny");
1469 #undef FILTER_EXIST_WARN
1472 /* If community attribute includes no_export then return 1. */
1473 static bool bgp_community_filter(struct peer
*peer
, struct attr
*attr
)
1475 if (attr
->community
) {
1476 /* NO_ADVERTISE check. */
1477 if (community_include(attr
->community
, COMMUNITY_NO_ADVERTISE
))
1480 /* NO_EXPORT check. */
1481 if (peer
->sort
== BGP_PEER_EBGP
1482 && community_include(attr
->community
, COMMUNITY_NO_EXPORT
))
1485 /* NO_EXPORT_SUBCONFED check. */
1486 if (peer
->sort
== BGP_PEER_EBGP
1487 || peer
->sort
== BGP_PEER_CONFED
)
1488 if (community_include(attr
->community
,
1489 COMMUNITY_NO_EXPORT_SUBCONFED
))
1495 /* Route reflection loop check. */
1496 static bool bgp_cluster_filter(struct peer
*peer
, struct attr
*attr
)
1498 struct in_addr cluster_id
;
1499 struct cluster_list
*cluster
= bgp_attr_get_cluster(attr
);
1502 if (peer
->bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
1503 cluster_id
= peer
->bgp
->cluster_id
;
1505 cluster_id
= peer
->bgp
->router_id
;
1507 if (cluster_loop_check(cluster
, cluster_id
))
1513 static int bgp_input_modifier(struct peer
*peer
, const struct prefix
*p
,
1514 struct attr
*attr
, afi_t afi
, safi_t safi
,
1515 const char *rmap_name
, mpls_label_t
*label
,
1516 uint32_t num_labels
, struct bgp_dest
*dest
)
1518 struct bgp_filter
*filter
;
1519 struct bgp_path_info rmap_path
= { 0 };
1520 struct bgp_path_info_extra extra
= { 0 };
1521 route_map_result_t ret
;
1522 struct route_map
*rmap
= NULL
;
1524 filter
= &peer
->filter
[afi
][safi
];
1526 /* Apply default weight value. */
1527 if (peer
->weight
[afi
][safi
])
1528 attr
->weight
= peer
->weight
[afi
][safi
];
1531 rmap
= route_map_lookup_by_name(rmap_name
);
1536 if (ROUTE_MAP_IN_NAME(filter
)) {
1537 rmap
= ROUTE_MAP_IN(filter
);
1544 /* Route map apply. */
1546 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
1547 /* Duplicate current value to new strucutre for modification. */
1548 rmap_path
.peer
= peer
;
1549 rmap_path
.attr
= attr
;
1550 rmap_path
.extra
= &extra
;
1551 rmap_path
.net
= dest
;
1553 extra
.num_labels
= num_labels
;
1554 if (label
&& num_labels
&& num_labels
<= BGP_MAX_LABELS
)
1555 memcpy(extra
.label
, label
,
1556 num_labels
* sizeof(mpls_label_t
));
1558 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_IN
);
1560 /* Apply BGP route map to the attribute. */
1561 ret
= route_map_apply(rmap
, p
, &rmap_path
);
1563 peer
->rmap_type
= 0;
1565 if (ret
== RMAP_DENYMATCH
)
1571 static int bgp_output_modifier(struct peer
*peer
, const struct prefix
*p
,
1572 struct attr
*attr
, afi_t afi
, safi_t safi
,
1573 const char *rmap_name
)
1575 struct bgp_path_info rmap_path
;
1576 route_map_result_t ret
;
1577 struct route_map
*rmap
= NULL
;
1581 * So if we get to this point and have no rmap_name
1582 * we want to just show the output as it currently
1588 /* Apply default weight value. */
1589 if (peer
->weight
[afi
][safi
])
1590 attr
->weight
= peer
->weight
[afi
][safi
];
1592 rmap
= route_map_lookup_by_name(rmap_name
);
1595 * If we have a route map name and we do not find
1596 * the routemap that means we have an implicit
1602 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
1603 /* Route map apply. */
1604 /* Duplicate current value to new strucutre for modification. */
1605 rmap_path
.peer
= peer
;
1606 rmap_path
.attr
= attr
;
1608 rmap_type
= peer
->rmap_type
;
1609 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1611 /* Apply BGP route map to the attribute. */
1612 ret
= route_map_apply(rmap
, p
, &rmap_path
);
1614 peer
->rmap_type
= rmap_type
;
1616 if (ret
== RMAP_DENYMATCH
)
1618 * caller has multiple error paths with bgp_attr_flush()
1625 /* If this is an EBGP peer with remove-private-AS */
1626 static void bgp_peer_remove_private_as(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1627 struct peer
*peer
, struct attr
*attr
)
1629 if (peer
->sort
== BGP_PEER_EBGP
1630 && (peer_af_flag_check(peer
, afi
, safi
,
1631 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1632 || peer_af_flag_check(peer
, afi
, safi
,
1633 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
)
1634 || peer_af_flag_check(peer
, afi
, safi
,
1635 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)
1636 || peer_af_flag_check(peer
, afi
, safi
,
1637 PEER_FLAG_REMOVE_PRIVATE_AS
))) {
1638 // Take action on the entire aspath
1639 if (peer_af_flag_check(peer
, afi
, safi
,
1640 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1641 || peer_af_flag_check(peer
, afi
, safi
,
1642 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)) {
1643 if (peer_af_flag_check(
1645 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
))
1646 attr
->aspath
= aspath_replace_private_asns(
1647 attr
->aspath
, bgp
->as
, peer
->as
);
1649 // The entire aspath consists of private ASNs so create
1651 else if (aspath_private_as_check(attr
->aspath
))
1652 attr
->aspath
= aspath_empty_get();
1654 // There are some public and some private ASNs, remove
1657 attr
->aspath
= aspath_remove_private_asns(
1658 attr
->aspath
, peer
->as
);
1661 // 'all' was not specified so the entire aspath must be private
1663 // for us to do anything
1664 else if (aspath_private_as_check(attr
->aspath
)) {
1665 if (peer_af_flag_check(
1667 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
))
1668 attr
->aspath
= aspath_replace_private_asns(
1669 attr
->aspath
, bgp
->as
, peer
->as
);
1671 attr
->aspath
= aspath_empty_get();
1676 /* If this is an EBGP peer with as-override */
1677 static void bgp_peer_as_override(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1678 struct peer
*peer
, struct attr
*attr
)
1680 if (peer
->sort
== BGP_PEER_EBGP
1681 && peer_af_flag_check(peer
, afi
, safi
, PEER_FLAG_AS_OVERRIDE
)) {
1682 if (aspath_single_asn_check(attr
->aspath
, peer
->as
))
1683 attr
->aspath
= aspath_replace_specific_asn(
1684 attr
->aspath
, peer
->as
, bgp
->as
);
1688 void bgp_attr_add_gshut_community(struct attr
*attr
)
1690 struct community
*old
;
1691 struct community
*new;
1692 struct community
*merge
;
1693 struct community
*gshut
;
1695 old
= attr
->community
;
1696 gshut
= community_str2com("graceful-shutdown");
1701 merge
= community_merge(community_dup(old
), gshut
);
1703 if (old
->refcnt
== 0)
1704 community_free(&old
);
1706 new = community_uniq_sort(merge
);
1707 community_free(&merge
);
1709 new = community_dup(gshut
);
1712 community_free(&gshut
);
1713 attr
->community
= new;
1714 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
1716 /* When we add the graceful-shutdown community we must also
1717 * lower the local-preference */
1718 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1719 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1723 /* Notify BGP Conditional advertisement scanner process. */
1724 void bgp_notify_conditional_adv_scanner(struct update_subgroup
*subgrp
)
1726 struct peer
*temp_peer
;
1727 struct peer
*peer
= SUBGRP_PEER(subgrp
);
1728 struct listnode
*temp_node
, *temp_nnode
= NULL
;
1729 afi_t afi
= SUBGRP_AFI(subgrp
);
1730 safi_t safi
= SUBGRP_SAFI(subgrp
);
1731 struct bgp
*bgp
= SUBGRP_INST(subgrp
);
1732 struct bgp_filter
*filter
= &peer
->filter
[afi
][safi
];
1734 if (!ADVERTISE_MAP_NAME(filter
))
1737 for (ALL_LIST_ELEMENTS(bgp
->peer
, temp_node
, temp_nnode
, temp_peer
)) {
1738 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_CONFIG_NODE
))
1741 if (peer
!= temp_peer
)
1744 temp_peer
->advmap_table_change
= true;
1750 void subgroup_announce_reset_nhop(uint8_t family
, struct attr
*attr
)
1752 if (family
== AF_INET
) {
1753 attr
->nexthop
.s_addr
= INADDR_ANY
;
1754 attr
->mp_nexthop_global_in
.s_addr
= INADDR_ANY
;
1756 if (family
== AF_INET6
)
1757 memset(&attr
->mp_nexthop_global
, 0, IPV6_MAX_BYTELEN
);
1758 if (family
== AF_EVPN
)
1759 memset(&attr
->mp_nexthop_global_in
, 0, BGP_ATTR_NHLEN_IPV4
);
1762 bool subgroup_announce_check(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
1763 struct update_subgroup
*subgrp
,
1764 const struct prefix
*p
, struct attr
*attr
,
1765 bool skip_rmap_check
)
1767 struct bgp_filter
*filter
;
1770 struct peer
*onlypeer
;
1772 struct attr
*piattr
;
1773 route_map_result_t ret
;
1778 int samepeer_safe
= 0; /* for synthetic mplsvpns routes */
1779 bool nh_reset
= false;
1782 if (DISABLE_BGP_ANNOUNCE
)
1785 afi
= SUBGRP_AFI(subgrp
);
1786 safi
= SUBGRP_SAFI(subgrp
);
1787 peer
= SUBGRP_PEER(subgrp
);
1789 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_LONESOUL
))
1790 onlypeer
= SUBGRP_PFIRST(subgrp
)->peer
;
1793 filter
= &peer
->filter
[afi
][safi
];
1794 bgp
= SUBGRP_INST(subgrp
);
1795 piattr
= bgp_path_info_mpath_count(pi
) ? bgp_path_info_mpath_attr(pi
)
1798 #ifdef ENABLE_BGP_VNC
1799 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
)) && (safi
== SAFI_MPLS_VPN
)
1800 && ((pi
->type
== ZEBRA_ROUTE_BGP_DIRECT
)
1801 || (pi
->type
== ZEBRA_ROUTE_BGP_DIRECT_EXT
))) {
1804 * direct and direct_ext type routes originate internally even
1805 * though they can have peer pointers that reference other
1808 zlog_debug("%s: pfx %pFX bgp_direct->vpn route peer safe",
1814 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
))
1815 && ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_UNICAST
))
1816 && (pi
->type
== ZEBRA_ROUTE_BGP
)
1817 && (pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
1819 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1824 /* With addpath we may be asked to TX all kinds of paths so make sure
1826 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
)
1827 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)
1828 || CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
1832 /* If this is not the bestpath then check to see if there is an enabled
1834 * feature that requires us to advertise it */
1835 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
1836 if (!bgp_addpath_tx_path(peer
->addpath_type
[afi
][safi
], pi
)) {
1841 /* Aggregate-address suppress check. */
1842 if (bgp_path_suppressed(pi
) && !UNSUPPRESS_MAP_NAME(filter
))
1846 * If we are doing VRF 2 VRF leaking via the import
1847 * statement, we want to prevent the route going
1848 * off box as that the RT and RD created are localy
1849 * significant and globaly useless.
1851 if (safi
== SAFI_MPLS_VPN
&& pi
->extra
&& pi
->extra
->num_labels
1852 && pi
->extra
->label
[0] == BGP_PREVENT_VRF_2_VRF_LEAK
)
1855 /* If it's labeled safi, make sure the route has a valid label. */
1856 if (safi
== SAFI_LABELED_UNICAST
) {
1857 mpls_label_t label
= bgp_adv_label(dest
, pi
, peer
, afi
, safi
);
1858 if (!bgp_is_valid_label(&label
)) {
1859 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1860 zlog_debug("u%" PRIu64
":s%" PRIu64
1861 " %pFX is filtered - no label (%p)",
1862 subgrp
->update_group
->id
, subgrp
->id
,
1868 /* Do not send back route to sender. */
1869 if (onlypeer
&& from
== onlypeer
) {
1873 /* Do not send the default route in the BGP table if the neighbor is
1874 * configured for default-originate */
1875 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1876 PEER_FLAG_DEFAULT_ORIGINATE
)) {
1877 if (p
->family
== AF_INET
&& p
->u
.prefix4
.s_addr
== INADDR_ANY
)
1879 else if (p
->family
== AF_INET6
&& p
->prefixlen
== 0)
1883 /* Transparency check. */
1884 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
)
1885 && CHECK_FLAG(from
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
))
1890 /* If community is not disabled check the no-export and local. */
1891 if (!transparent
&& bgp_community_filter(peer
, piattr
)) {
1892 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1893 zlog_debug("%s: community filter check fail for %pFX",
1898 /* If the attribute has originator-id and it is same as remote
1900 if (onlypeer
&& piattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
1901 && (IPV4_ADDR_SAME(&onlypeer
->remote_id
, &piattr
->originator_id
))) {
1902 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1904 "%s [Update:SEND] %pFX originator-id is same as remote router-id",
1909 /* ORF prefix-list filter check */
1910 if (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_RM_ADV
)
1911 && (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_SM_RCV
)
1912 || CHECK_FLAG(peer
->af_cap
[afi
][safi
],
1913 PEER_CAP_ORF_PREFIX_SM_OLD_RCV
)))
1914 if (peer
->orf_plist
[afi
][safi
]) {
1915 if (prefix_list_apply(peer
->orf_plist
[afi
][safi
], p
)
1917 if (bgp_debug_update(NULL
, p
,
1918 subgrp
->update_group
, 0))
1920 "%s [Update:SEND] %pFX is filtered via ORF",
1926 /* Output filter check. */
1927 if (bgp_output_filter(peer
, p
, piattr
, afi
, safi
) == FILTER_DENY
) {
1928 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1929 zlog_debug("%s [Update:SEND] %pFX is filtered",
1934 /* AS path loop check. */
1935 if (onlypeer
&& onlypeer
->as_path_loop_detection
1936 && aspath_loop_check(piattr
->aspath
, onlypeer
->as
)) {
1937 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1939 "%s [Update:SEND] suppress announcement to peer AS %u that is part of AS path.",
1940 onlypeer
->host
, onlypeer
->as
);
1944 /* If we're a CONFED we need to loop check the CONFED ID too */
1945 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
1946 if (aspath_loop_check(piattr
->aspath
, bgp
->confed_id
)) {
1947 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1949 "%s [Update:SEND] suppress announcement to peer AS %u is AS path.",
1950 peer
->host
, bgp
->confed_id
);
1955 /* Route-Reflect check. */
1956 if (from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1961 /* IBGP reflection check. */
1962 if (reflect
&& !samepeer_safe
) {
1963 /* A route from a Client peer. */
1964 if (CHECK_FLAG(from
->af_flags
[afi
][safi
],
1965 PEER_FLAG_REFLECTOR_CLIENT
)) {
1966 /* Reflect to all the Non-Client peers and also to the
1967 Client peers other than the originator. Originator
1969 is already done. So there is noting to do. */
1970 /* no bgp client-to-client reflection check. */
1971 if (CHECK_FLAG(bgp
->flags
,
1972 BGP_FLAG_NO_CLIENT_TO_CLIENT
))
1973 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1974 PEER_FLAG_REFLECTOR_CLIENT
))
1977 /* A route from a Non-client peer. Reflect to all other
1979 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1980 PEER_FLAG_REFLECTOR_CLIENT
))
1985 /* For modify attribute, copy it to temporary structure. */
1988 /* If local-preference is not set. */
1989 if ((peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
)
1990 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))) {
1991 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1992 attr
->local_pref
= bgp
->default_local_pref
;
1995 /* If originator-id is not set and the route is to be reflected,
1996 set the originator id */
1998 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)))) {
1999 IPV4_ADDR_COPY(&(attr
->originator_id
), &(from
->remote_id
));
2000 SET_FLAG(attr
->flag
, BGP_ATTR_ORIGINATOR_ID
);
2003 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
2005 if (peer
->sort
== BGP_PEER_EBGP
2006 && attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
2007 if (from
!= bgp
->peer_self
&& !transparent
2008 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2009 PEER_FLAG_MED_UNCHANGED
))
2011 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
));
2014 /* Since the nexthop attribute can vary per peer, it is not explicitly
2016 * in announce check, only certain flags and length (or number of
2018 * -- for IPv6/MP_REACH) are set here in order to guide the update
2020 * code in setting the nexthop(s) on a per peer basis in
2022 * Typically, the source nexthop in the attribute is preserved but in
2024 * scenarios where we know it will always be overwritten, we reset the
2025 * nexthop to "0" in an attempt to achieve better Update packing. An
2026 * example of this is when a prefix from each of 2 IBGP peers needs to
2028 * announced to an EBGP peer (and they have the same attributes barring
2032 SET_FLAG(attr
->rmap_change_flags
, BATTR_REFLECTED
);
2034 #define NEXTHOP_IS_V6 \
2035 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
2036 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
2037 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
2038 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
2040 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
2042 * the peer (group) is configured to receive link-local nexthop
2044 * and it is available in the prefix OR we're not reflecting the route,
2045 * link-local nexthop address is valid and
2046 * the peer (group) to whom we're going to announce is on a shared
2048 * and this is either a self-originated route or the peer is EBGP.
2049 * By checking if nexthop LL address is valid we are sure that
2050 * we do not announce LL address as `::`.
2052 if (NEXTHOP_IS_V6
) {
2053 attr
->mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
2054 if ((CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2055 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)
2056 && IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
))
2058 && IN6_IS_ADDR_LINKLOCAL(&peer
->nexthop
.v6_local
)
2059 && peer
->shared_network
2060 && (from
== bgp
->peer_self
2061 || peer
->sort
== BGP_PEER_EBGP
))) {
2062 attr
->mp_nexthop_len
=
2063 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
;
2066 /* Clear off link-local nexthop in source, whenever it is not
2068 * ensure more prefixes share the same attribute for
2071 if (!(CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2072 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)))
2073 memset(&attr
->mp_nexthop_local
, 0, IPV6_MAX_BYTELEN
);
2076 bgp_peer_remove_private_as(bgp
, afi
, safi
, peer
, attr
);
2077 bgp_peer_as_override(bgp
, afi
, safi
, peer
, attr
);
2079 /* Route map & unsuppress-map apply. */
2080 if (!skip_rmap_check
2081 && (ROUTE_MAP_OUT_NAME(filter
) || bgp_path_suppressed(pi
))) {
2082 struct bgp_path_info rmap_path
= {0};
2083 struct bgp_path_info_extra dummy_rmap_path_extra
= {0};
2084 struct attr dummy_attr
= {0};
2086 /* Fill temp path_info */
2087 prep_for_rmap_apply(&rmap_path
, &dummy_rmap_path_extra
, dest
,
2090 /* don't confuse inbound and outbound setting */
2091 RESET_FLAG(attr
->rmap_change_flags
);
2094 * The route reflector is not allowed to modify the attributes
2095 * of the reflected IBGP routes unless explicitly allowed.
2097 if ((from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
2098 && !CHECK_FLAG(bgp
->flags
,
2099 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY
)) {
2101 rmap_path
.attr
= &dummy_attr
;
2104 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
2106 if (bgp_path_suppressed(pi
))
2107 ret
= route_map_apply(UNSUPPRESS_MAP(filter
), p
,
2110 ret
= route_map_apply(ROUTE_MAP_OUT(filter
), p
,
2113 peer
->rmap_type
= 0;
2115 if (ret
== RMAP_DENYMATCH
) {
2116 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2118 "%s [Update:SEND] %pFX is filtered by route-map",
2121 bgp_attr_flush(attr
);
2126 /* RFC 8212 to prevent route leaks.
2127 * This specification intends to improve this situation by requiring the
2128 * explicit configuration of both BGP Import and Export Policies for any
2129 * External BGP (EBGP) session such as customers, peers, or
2130 * confederation boundaries for all enabled address families. Through
2131 * codification of the aforementioned requirement, operators will
2132 * benefit from consistent behavior across different BGP
2135 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_EBGP_REQUIRES_POLICY
))
2136 if (!bgp_outbound_policy_exists(peer
, filter
))
2139 /* draft-ietf-idr-deprecate-as-set-confed-set
2140 * Filter routes having AS_SET or AS_CONFED_SET in the path.
2141 * Eventually, This document (if approved) updates RFC 4271
2142 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
2143 * and obsoletes RFC 6472.
2145 if (peer
->bgp
->reject_as_sets
)
2146 if (aspath_check_as_sets(attr
->aspath
))
2149 /* Codification of AS 0 Processing */
2150 if (aspath_check_as_zero(attr
->aspath
))
2153 if (bgp_in_graceful_shutdown(bgp
)) {
2154 if (peer
->sort
== BGP_PEER_IBGP
2155 || peer
->sort
== BGP_PEER_CONFED
) {
2156 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
2157 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
2159 bgp_attr_add_gshut_community(attr
);
2163 /* After route-map has been applied, we check to see if the nexthop to
2164 * be carried in the attribute (that is used for the announcement) can
2165 * be cleared off or not. We do this in all cases where we would be
2166 * setting the nexthop to "ourselves". For IPv6, we only need to
2168 * the global nexthop here; the link-local nexthop would have been
2170 * already, and if not, it is required by the update formation code.
2171 * Also see earlier comments in this function.
2174 * If route-map has performed some operation on the nexthop or the peer
2175 * configuration says to pass it unchanged, we cannot reset the nexthop
2176 * here, so only attempt to do it if these aren't true. Note that the
2177 * route-map handler itself might have cleared the nexthop, if for
2179 * it is configured as 'peer-address'.
2181 if (!bgp_rmap_nhop_changed(attr
->rmap_change_flags
,
2182 piattr
->rmap_change_flags
)
2184 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2185 PEER_FLAG_NEXTHOP_UNCHANGED
)) {
2186 /* We can reset the nexthop, if setting (or forcing) it to
2188 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2189 PEER_FLAG_NEXTHOP_SELF
)
2190 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2191 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
2193 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2194 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
2195 subgroup_announce_reset_nhop(
2196 (peer_cap_enhe(peer
, afi
, safi
)
2202 } else if (peer
->sort
== BGP_PEER_EBGP
) {
2203 /* Can also reset the nexthop if announcing to EBGP, but
2205 * no peer in the subgroup is on a shared subnet.
2206 * Note: 3rd party nexthop currently implemented for
2209 if ((p
->family
== AF_INET
) &&
2210 (!bgp_subgrp_multiaccess_check_v4(
2213 subgroup_announce_reset_nhop(
2214 (peer_cap_enhe(peer
, afi
, safi
)
2221 if ((p
->family
== AF_INET6
) &&
2222 (!bgp_subgrp_multiaccess_check_v6(
2223 piattr
->mp_nexthop_global
,
2225 subgroup_announce_reset_nhop(
2226 (peer_cap_enhe(peer
, afi
, safi
)
2235 } else if (CHECK_FLAG(pi
->flags
, BGP_PATH_ANNC_NH_SELF
)) {
2237 * This flag is used for leaked vpn-vrf routes
2239 int family
= p
->family
;
2241 if (peer_cap_enhe(peer
, afi
, safi
))
2244 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2246 "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
2247 __func__
, family2str(family
));
2248 subgroup_announce_reset_nhop(family
, attr
);
2253 /* If IPv6/MP and nexthop does not have any override and happens
2255 * be a link-local address, reset it so that we don't pass along
2257 * source's link-local IPv6 address to recipients who may not be
2259 * the same interface.
2261 if (p
->family
== AF_INET6
|| peer_cap_enhe(peer
, afi
, safi
)) {
2262 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
)) {
2263 subgroup_announce_reset_nhop(AF_INET6
, attr
);
2269 * When the next hop is set to ourselves, if all multipaths have
2270 * link-bandwidth announce the cumulative bandwidth as that makes
2271 * the most sense. However, don't modify if the link-bandwidth has
2272 * been explicitly set by user policy.
2275 bgp_path_info_mpath_chkwtd(bgp
, pi
) &&
2276 (cum_bw
= bgp_path_info_mpath_cumbw(pi
)) != 0 &&
2277 !CHECK_FLAG(attr
->rmap_change_flags
, BATTR_RMAP_LINK_BW_SET
))
2278 attr
->ecommunity
= ecommunity_replace_linkbw(
2279 bgp
->as
, attr
->ecommunity
, cum_bw
);
2284 static int bgp_route_select_timer_expire(struct thread
*thread
)
2286 struct afi_safi_info
*info
;
2291 info
= THREAD_ARG(thread
);
2296 if (BGP_DEBUG(update
, UPDATE_OUT
))
2297 zlog_debug("afi %d, safi %d : route select timer expired", afi
,
2300 bgp
->gr_info
[afi
][safi
].t_route_select
= NULL
;
2302 XFREE(MTYPE_TMP
, info
);
2304 /* Best path selection */
2305 return bgp_best_path_select_defer(bgp
, afi
, safi
);
2308 void bgp_best_selection(struct bgp
*bgp
, struct bgp_dest
*dest
,
2309 struct bgp_maxpaths_cfg
*mpath_cfg
,
2310 struct bgp_path_info_pair
*result
, afi_t afi
,
2313 struct bgp_path_info
*new_select
;
2314 struct bgp_path_info
*old_select
;
2315 struct bgp_path_info
*pi
;
2316 struct bgp_path_info
*pi1
;
2317 struct bgp_path_info
*pi2
;
2318 struct bgp_path_info
*nextpi
= NULL
;
2319 int paths_eq
, do_mpath
, debug
;
2320 struct list mp_list
;
2321 char pfx_buf
[PREFIX2STR_BUFFER
];
2322 char path_buf
[PATH_ADDPATH_STR_BUFFER
];
2324 bgp_mp_list_init(&mp_list
);
2326 (mpath_cfg
->maxpaths_ebgp
> 1 || mpath_cfg
->maxpaths_ibgp
> 1);
2328 debug
= bgp_debug_bestpath(dest
);
2331 prefix2str(bgp_dest_get_prefix(dest
), pfx_buf
, sizeof(pfx_buf
));
2333 dest
->reason
= bgp_path_selection_none
;
2334 /* bgp deterministic-med */
2336 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DETERMINISTIC_MED
)) {
2338 /* Clear BGP_PATH_DMED_SELECTED for all paths */
2339 for (pi1
= bgp_dest_get_bgp_path_info(dest
); pi1
;
2341 bgp_path_info_unset_flag(dest
, pi1
,
2342 BGP_PATH_DMED_SELECTED
);
2344 for (pi1
= bgp_dest_get_bgp_path_info(dest
); pi1
;
2346 if (CHECK_FLAG(pi1
->flags
, BGP_PATH_DMED_CHECK
))
2348 if (BGP_PATH_HOLDDOWN(pi1
))
2350 if (pi1
->peer
!= bgp
->peer_self
)
2351 if (!peer_established(pi1
->peer
))
2356 for (pi2
= pi1
->next
; pi2
; pi2
= pi2
->next
) {
2357 if (CHECK_FLAG(pi2
->flags
,
2358 BGP_PATH_DMED_CHECK
))
2360 if (BGP_PATH_HOLDDOWN(pi2
))
2362 if (pi2
->peer
!= bgp
->peer_self
2365 PEER_STATUS_NSF_WAIT
))
2366 if (pi2
->peer
->status
2370 if (!aspath_cmp_left(pi1
->attr
->aspath
,
2372 && !aspath_cmp_left_confed(
2377 if (bgp_path_info_cmp(
2378 bgp
, pi2
, new_select
,
2379 &paths_eq
, mpath_cfg
, debug
,
2382 bgp_path_info_unset_flag(
2384 BGP_PATH_DMED_SELECTED
);
2388 bgp_path_info_set_flag(
2389 dest
, pi2
, BGP_PATH_DMED_CHECK
);
2392 bgp_path_info_set_flag(dest
, new_select
,
2393 BGP_PATH_DMED_CHECK
);
2394 bgp_path_info_set_flag(dest
, new_select
,
2395 BGP_PATH_DMED_SELECTED
);
2398 bgp_path_info_path_with_addpath_rx_str(
2399 new_select
, path_buf
, sizeof(path_buf
));
2401 "%pBD: %s is the bestpath from AS %u",
2403 aspath_get_first_as(
2404 new_select
->attr
->aspath
));
2409 /* Check old selected route and new selected route. */
2412 for (pi
= bgp_dest_get_bgp_path_info(dest
);
2413 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2414 enum bgp_path_selection_reason reason
;
2416 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
2419 if (BGP_PATH_HOLDDOWN(pi
)) {
2420 /* reap REMOVED routes, if needs be
2421 * selected route must stay for a while longer though
2423 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
2424 && (pi
!= old_select
))
2425 bgp_path_info_reap(dest
, pi
);
2428 zlog_debug("%s: pi %p in holddown", __func__
,
2434 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2435 && !CHECK_FLAG(pi
->peer
->sflags
, PEER_STATUS_NSF_WAIT
))
2436 if (!peer_established(pi
->peer
)) {
2440 "%s: pi %p non self peer %s not estab state",
2441 __func__
, pi
, pi
->peer
->host
);
2446 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DETERMINISTIC_MED
)
2447 && (!CHECK_FLAG(pi
->flags
, BGP_PATH_DMED_SELECTED
))) {
2448 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_DMED_CHECK
);
2450 zlog_debug("%s: pi %p dmed", __func__
, pi
);
2454 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_DMED_CHECK
);
2456 reason
= dest
->reason
;
2457 if (bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
, mpath_cfg
,
2458 debug
, pfx_buf
, afi
, safi
,
2460 if (new_select
== NULL
&&
2461 reason
!= bgp_path_selection_none
)
2462 dest
->reason
= reason
;
2467 /* Now that we know which path is the bestpath see if any of the other
2469 * qualify as multipaths
2473 bgp_path_info_path_with_addpath_rx_str(
2474 new_select
, path_buf
, sizeof(path_buf
));
2476 snprintf(path_buf
, sizeof(path_buf
), "NONE");
2478 "%pBD: After path selection, newbest is %s oldbest was %s",
2480 old_select
? old_select
->peer
->host
: "NONE");
2483 if (do_mpath
&& new_select
) {
2484 for (pi
= bgp_dest_get_bgp_path_info(dest
);
2485 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2488 bgp_path_info_path_with_addpath_rx_str(
2489 pi
, path_buf
, sizeof(path_buf
));
2491 if (pi
== new_select
) {
2494 "%pBD: %s is the bestpath, add to the multipath list",
2496 bgp_mp_list_add(&mp_list
, pi
);
2500 if (BGP_PATH_HOLDDOWN(pi
))
2503 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2504 && !CHECK_FLAG(pi
->peer
->sflags
,
2505 PEER_STATUS_NSF_WAIT
))
2506 if (!peer_established(pi
->peer
))
2509 if (!bgp_path_info_nexthop_cmp(pi
, new_select
)) {
2512 "%pBD: %s has the same nexthop as the bestpath, skip it",
2517 bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
,
2518 mpath_cfg
, debug
, pfx_buf
, afi
, safi
,
2524 "%pBD: %s is equivalent to the bestpath, add to the multipath list",
2526 bgp_mp_list_add(&mp_list
, pi
);
2531 bgp_path_info_mpath_update(dest
, new_select
, old_select
, &mp_list
,
2533 bgp_path_info_mpath_aggregate_update(new_select
, old_select
);
2534 bgp_mp_list_clear(&mp_list
);
2536 bgp_addpath_update_ids(bgp
, dest
, afi
, safi
);
2538 result
->old
= old_select
;
2539 result
->new = new_select
;
2545 * A new route/change in bestpath of an existing route. Evaluate the path
2546 * for advertisement to the subgroup.
2548 void subgroup_process_announce_selected(struct update_subgroup
*subgrp
,
2549 struct bgp_path_info
*selected
,
2550 struct bgp_dest
*dest
,
2551 uint32_t addpath_tx_id
)
2553 const struct prefix
*p
;
2554 struct peer
*onlypeer
;
2561 p
= bgp_dest_get_prefix(dest
);
2562 afi
= SUBGRP_AFI(subgrp
);
2563 safi
= SUBGRP_SAFI(subgrp
);
2564 bgp
= SUBGRP_INST(subgrp
);
2565 onlypeer
= ((SUBGRP_PCOUNT(subgrp
) == 1) ? (SUBGRP_PFIRST(subgrp
))->peer
2568 if (BGP_DEBUG(update
, UPDATE_OUT
))
2569 zlog_debug("%s: p=%pFX, selected=%p", __func__
, p
, selected
);
2571 /* First update is deferred until ORF or ROUTE-REFRESH is received */
2572 if (onlypeer
&& CHECK_FLAG(onlypeer
->af_sflags
[afi
][safi
],
2573 PEER_STATUS_ORF_WAIT_REFRESH
))
2576 memset(&attr
, 0, sizeof(struct attr
));
2577 /* It's initialized in bgp_announce_check() */
2579 /* Announcement to the subgroup. If the route is filtered withdraw it.
2580 * If BGP_NODE_FIB_INSTALL_PENDING is set and data plane install status
2581 * is pending (BGP_NODE_FIB_INSTALL_PENDING), do not advertise the
2584 advertise
= bgp_check_advertise(bgp
, dest
);
2587 if (subgroup_announce_check(dest
, selected
, subgrp
, p
, &attr
,
2589 /* Route is selected, if the route is already installed
2590 * in FIB, then it is advertised
2593 bgp_adj_out_set_subgroup(dest
, subgrp
, &attr
,
2596 bgp_adj_out_unset_subgroup(dest
, subgrp
, 1,
2600 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2602 bgp_adj_out_unset_subgroup(dest
, subgrp
, 1, addpath_tx_id
);
2607 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2608 * This is called at the end of route processing.
2610 void bgp_zebra_clear_route_change_flags(struct bgp_dest
*dest
)
2612 struct bgp_path_info
*pi
;
2614 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
2615 if (BGP_PATH_HOLDDOWN(pi
))
2617 UNSET_FLAG(pi
->flags
, BGP_PATH_IGP_CHANGED
);
2618 UNSET_FLAG(pi
->flags
, BGP_PATH_ATTR_CHANGED
);
2623 * Has the route changed from the RIB's perspective? This is invoked only
2624 * if the route selection returns the same best route as earlier - to
2625 * determine if we need to update zebra or not.
2627 bool bgp_zebra_has_route_changed(struct bgp_path_info
*selected
)
2629 struct bgp_path_info
*mpinfo
;
2631 /* If this is multipath, check all selected paths for any nexthop
2632 * change or attribute change. Some attribute changes (e.g., community)
2633 * aren't of relevance to the RIB, but we'll update zebra to ensure
2634 * we handle the case of BGP nexthop change. This is the behavior
2635 * when the best path has an attribute change anyway.
2637 if (CHECK_FLAG(selected
->flags
, BGP_PATH_IGP_CHANGED
)
2638 || CHECK_FLAG(selected
->flags
, BGP_PATH_MULTIPATH_CHG
)
2639 || CHECK_FLAG(selected
->flags
, BGP_PATH_LINK_BW_CHG
))
2643 * If this is multipath, check all selected paths for any nexthop change
2645 for (mpinfo
= bgp_path_info_mpath_first(selected
); mpinfo
;
2646 mpinfo
= bgp_path_info_mpath_next(mpinfo
)) {
2647 if (CHECK_FLAG(mpinfo
->flags
, BGP_PATH_IGP_CHANGED
)
2648 || CHECK_FLAG(mpinfo
->flags
, BGP_PATH_ATTR_CHANGED
))
2652 /* Nothing has changed from the RIB's perspective. */
2656 struct bgp_process_queue
{
2658 STAILQ_HEAD(, bgp_dest
) pqueue
;
2659 #define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2661 unsigned int queued
;
2664 static void bgp_process_evpn_route_injection(struct bgp
*bgp
, afi_t afi
,
2665 safi_t safi
, struct bgp_dest
*dest
,
2666 struct bgp_path_info
*new_select
,
2667 struct bgp_path_info
*old_select
)
2669 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
2671 if ((afi
!= AFI_IP
&& afi
!= AFI_IP6
) || (safi
!= SAFI_UNICAST
))
2674 if (advertise_type5_routes(bgp
, afi
) && new_select
2675 && is_route_injectable_into_evpn(new_select
)) {
2677 /* apply the route-map */
2678 if (bgp
->adv_cmd_rmap
[afi
][safi
].map
) {
2679 route_map_result_t ret
;
2680 struct bgp_path_info rmap_path
;
2681 struct bgp_path_info_extra rmap_path_extra
;
2682 struct attr dummy_attr
;
2684 dummy_attr
= *new_select
->attr
;
2686 /* Fill temp path_info */
2687 prep_for_rmap_apply(&rmap_path
, &rmap_path_extra
, dest
,
2688 new_select
, new_select
->peer
,
2691 RESET_FLAG(dummy_attr
.rmap_change_flags
);
2693 ret
= route_map_apply(bgp
->adv_cmd_rmap
[afi
][safi
].map
,
2696 if (ret
== RMAP_DENYMATCH
) {
2697 bgp_attr_flush(&dummy_attr
);
2698 bgp_evpn_withdraw_type5_route(bgp
, p
, afi
,
2701 bgp_evpn_advertise_type5_route(
2702 bgp
, p
, &dummy_attr
, afi
, safi
);
2704 bgp_evpn_advertise_type5_route(bgp
, p
, new_select
->attr
,
2707 } else if (advertise_type5_routes(bgp
, afi
) && old_select
2708 && is_route_injectable_into_evpn(old_select
))
2709 bgp_evpn_withdraw_type5_route(bgp
, p
, afi
, safi
);
2713 * old_select = The old best path
2714 * new_select = the new best path
2716 * if (!old_select && new_select)
2717 * We are sending new information on.
2719 * if (old_select && new_select) {
2720 * if (new_select != old_select)
2721 * We have a new best path send a change
2723 * We've received a update with new attributes that needs
2727 * if (old_select && !new_select)
2728 * We have no eligible route that we can announce or the rn
2731 static void bgp_process_main_one(struct bgp
*bgp
, struct bgp_dest
*dest
,
2732 afi_t afi
, safi_t safi
)
2734 struct bgp_path_info
*new_select
;
2735 struct bgp_path_info
*old_select
;
2736 struct bgp_path_info_pair old_and_new
;
2739 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)) {
2741 debug
= bgp_debug_bestpath(dest
);
2744 "%s: bgp delete in progress, ignoring event, p=%pBD",
2748 /* Is it end of initial update? (after startup) */
2750 quagga_timestamp(3, bgp
->update_delay_zebra_resume_time
,
2751 sizeof(bgp
->update_delay_zebra_resume_time
));
2753 bgp
->main_zebra_update_hold
= 0;
2754 FOREACH_AFI_SAFI (afi
, safi
) {
2755 if (bgp_fibupd_safi(safi
))
2756 bgp_zebra_announce_table(bgp
, afi
, safi
);
2758 bgp
->main_peers_update_hold
= 0;
2760 bgp_start_routeadv(bgp
);
2764 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
2766 debug
= bgp_debug_bestpath(dest
);
2768 zlog_debug("%s: p=%pBD afi=%s, safi=%s start", __func__
, dest
,
2769 afi2str(afi
), safi2str(safi
));
2771 /* The best path calculation for the route is deferred if
2772 * BGP_NODE_SELECT_DEFER is set
2774 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
2775 if (BGP_DEBUG(update
, UPDATE_OUT
))
2776 zlog_debug("SELECT_DEFER flag set for route %p", dest
);
2780 /* Best path selection. */
2781 bgp_best_selection(bgp
, dest
, &bgp
->maxpaths
[afi
][safi
], &old_and_new
,
2783 old_select
= old_and_new
.old
;
2784 new_select
= old_and_new
.new;
2786 /* Do we need to allocate or free labels?
2787 * Right now, since we only deal with per-prefix labels, it is not
2788 * necessary to do this upon changes to best path. Exceptions:
2789 * - label index has changed -> recalculate resulting label
2790 * - path_info sub_type changed -> switch to/from implicit-null
2791 * - no valid label (due to removed static label binding) -> get new one
2793 if (bgp
->allocate_mpls_labels
[afi
][safi
]) {
2796 || bgp_label_index_differs(new_select
, old_select
)
2797 || new_select
->sub_type
!= old_select
->sub_type
2798 || !bgp_is_valid_label(&dest
->local_label
)) {
2799 /* Enforced penultimate hop popping:
2800 * implicit-null for local routes, aggregate
2801 * and redistributed routes
2803 if (new_select
->sub_type
== BGP_ROUTE_STATIC
2804 || new_select
->sub_type
2805 == BGP_ROUTE_AGGREGATE
2806 || new_select
->sub_type
2807 == BGP_ROUTE_REDISTRIBUTE
) {
2810 BGP_NODE_REGISTERED_FOR_LABEL
)
2813 BGP_NODE_LABEL_REQUESTED
))
2814 bgp_unregister_for_label(dest
);
2815 label_ntop(MPLS_LABEL_IMPLICIT_NULL
, 1,
2816 &dest
->local_label
);
2817 bgp_set_valid_label(&dest
->local_label
);
2819 bgp_register_for_label(dest
,
2822 } else if (CHECK_FLAG(dest
->flags
,
2823 BGP_NODE_REGISTERED_FOR_LABEL
)
2824 || CHECK_FLAG(dest
->flags
,
2825 BGP_NODE_LABEL_REQUESTED
)) {
2826 bgp_unregister_for_label(dest
);
2828 } else if (CHECK_FLAG(dest
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
)
2829 || CHECK_FLAG(dest
->flags
, BGP_NODE_LABEL_REQUESTED
)) {
2830 bgp_unregister_for_label(dest
);
2835 "%s: p=%pBD afi=%s, safi=%s, old_select=%p, new_select=%p",
2836 __func__
, dest
, afi2str(afi
), safi2str(safi
),
2837 old_select
, new_select
);
2839 /* If best route remains the same and this is not due to user-initiated
2840 * clear, see exactly what needs to be done.
2842 if (old_select
&& old_select
== new_select
2843 && !CHECK_FLAG(dest
->flags
, BGP_NODE_USER_CLEAR
)
2844 && !CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
2845 && !bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
2846 if (bgp_zebra_has_route_changed(old_select
)) {
2847 #ifdef ENABLE_BGP_VNC
2848 vnc_import_bgp_add_route(bgp
, p
, old_select
);
2849 vnc_import_bgp_exterior_add_route(bgp
, p
, old_select
);
2851 if (bgp_fibupd_safi(safi
)
2852 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2854 if (new_select
->type
== ZEBRA_ROUTE_BGP
2855 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2856 || new_select
->sub_type
2857 == BGP_ROUTE_IMPORTED
))
2859 bgp_zebra_announce(dest
, p
, old_select
,
2864 /* If there is a change of interest to peers, reannounce the
2866 if (CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
2867 || CHECK_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
)
2868 || CHECK_FLAG(dest
->flags
, BGP_NODE_LABEL_CHANGED
)) {
2869 group_announce_route(bgp
, afi
, safi
, dest
, new_select
);
2871 /* unicast routes must also be annouced to
2872 * labeled-unicast update-groups */
2873 if (safi
== SAFI_UNICAST
)
2874 group_announce_route(bgp
, afi
,
2875 SAFI_LABELED_UNICAST
, dest
,
2878 UNSET_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
);
2879 UNSET_FLAG(dest
->flags
, BGP_NODE_LABEL_CHANGED
);
2882 /* advertise/withdraw type-5 routes */
2883 if (CHECK_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
)
2884 || CHECK_FLAG(old_select
->flags
, BGP_PATH_MULTIPATH_CHG
))
2885 bgp_process_evpn_route_injection(
2886 bgp
, afi
, safi
, dest
, old_select
, old_select
);
2888 UNSET_FLAG(old_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
2889 UNSET_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
);
2890 bgp_zebra_clear_route_change_flags(dest
);
2891 UNSET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2895 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2897 UNSET_FLAG(dest
->flags
, BGP_NODE_USER_CLEAR
);
2899 /* bestpath has changed; bump version */
2900 if (old_select
|| new_select
) {
2901 bgp_bump_version(dest
);
2903 if (!bgp
->t_rmap_def_originate_eval
) {
2907 update_group_refresh_default_originate_route_map
,
2908 bgp
, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER
,
2909 &bgp
->t_rmap_def_originate_eval
);
2914 bgp_path_info_unset_flag(dest
, old_select
, BGP_PATH_SELECTED
);
2917 zlog_debug("%s: setting SELECTED flag", __func__
);
2918 bgp_path_info_set_flag(dest
, new_select
, BGP_PATH_SELECTED
);
2919 bgp_path_info_unset_flag(dest
, new_select
,
2920 BGP_PATH_ATTR_CHANGED
);
2921 UNSET_FLAG(new_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
2922 UNSET_FLAG(new_select
->flags
, BGP_PATH_LINK_BW_CHG
);
2925 #ifdef ENABLE_BGP_VNC
2926 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2927 if (old_select
!= new_select
) {
2929 vnc_import_bgp_exterior_del_route(bgp
, p
,
2931 vnc_import_bgp_del_route(bgp
, p
, old_select
);
2934 vnc_import_bgp_exterior_add_route(bgp
, p
,
2936 vnc_import_bgp_add_route(bgp
, p
, new_select
);
2942 group_announce_route(bgp
, afi
, safi
, dest
, new_select
);
2944 /* unicast routes must also be annouced to labeled-unicast update-groups
2946 if (safi
== SAFI_UNICAST
)
2947 group_announce_route(bgp
, afi
, SAFI_LABELED_UNICAST
, dest
,
2951 if (bgp_fibupd_safi(safi
) && (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VIEW
)
2952 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2953 if (new_select
&& new_select
->type
== ZEBRA_ROUTE_BGP
2954 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2955 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
2956 || new_select
->sub_type
== BGP_ROUTE_IMPORTED
)) {
2958 /* if this is an evpn imported type-5 prefix,
2959 * we need to withdraw the route first to clear
2960 * the nh neigh and the RMAC entry.
2963 is_route_parent_evpn(old_select
))
2964 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2966 bgp_zebra_announce(dest
, p
, new_select
, bgp
, afi
, safi
);
2968 /* Withdraw the route from the kernel. */
2969 if (old_select
&& old_select
->type
== ZEBRA_ROUTE_BGP
2970 && (old_select
->sub_type
== BGP_ROUTE_NORMAL
2971 || old_select
->sub_type
== BGP_ROUTE_AGGREGATE
2972 || old_select
->sub_type
== BGP_ROUTE_IMPORTED
))
2974 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2978 bgp_process_evpn_route_injection(bgp
, afi
, safi
, dest
, new_select
,
2981 /* Clear any route change flags. */
2982 bgp_zebra_clear_route_change_flags(dest
);
2984 /* Reap old select bgp_path_info, if it has been removed */
2985 if (old_select
&& CHECK_FLAG(old_select
->flags
, BGP_PATH_REMOVED
))
2986 bgp_path_info_reap(dest
, old_select
);
2988 UNSET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2992 /* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
2993 int bgp_best_path_select_defer(struct bgp
*bgp
, afi_t afi
, safi_t safi
)
2995 struct bgp_dest
*dest
;
2997 struct afi_safi_info
*thread_info
;
2999 if (bgp
->gr_info
[afi
][safi
].t_route_select
) {
3000 struct thread
*t
= bgp
->gr_info
[afi
][safi
].t_route_select
;
3002 thread_info
= THREAD_ARG(t
);
3003 XFREE(MTYPE_TMP
, thread_info
);
3004 BGP_TIMER_OFF(bgp
->gr_info
[afi
][safi
].t_route_select
);
3007 if (BGP_DEBUG(update
, UPDATE_OUT
)) {
3008 zlog_debug("%s: processing route for %s : cnt %d", __func__
,
3009 get_afi_safi_str(afi
, safi
, false),
3010 bgp
->gr_info
[afi
][safi
].gr_deferred
);
3013 /* Process the route list */
3014 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]);
3015 dest
&& bgp
->gr_info
[afi
][safi
].gr_deferred
!= 0;
3016 dest
= bgp_route_next(dest
)) {
3017 if (!CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
))
3020 UNSET_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
);
3021 bgp
->gr_info
[afi
][safi
].gr_deferred
--;
3022 bgp_process_main_one(bgp
, dest
, afi
, safi
);
3024 if (cnt
>= BGP_MAX_BEST_ROUTE_SELECT
) {
3025 bgp_dest_unlock_node(dest
);
3030 /* Send EOR message when all routes are processed */
3031 if (!bgp
->gr_info
[afi
][safi
].gr_deferred
) {
3032 bgp_send_delayed_eor(bgp
);
3033 /* Send route processing complete message to RIB */
3034 bgp_zebra_update(afi
, safi
, bgp
->vrf_id
,
3035 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE
);
3039 thread_info
= XMALLOC(MTYPE_TMP
, sizeof(struct afi_safi_info
));
3041 thread_info
->afi
= afi
;
3042 thread_info
->safi
= safi
;
3043 thread_info
->bgp
= bgp
;
3045 /* If there are more routes to be processed, start the
3048 thread_add_timer(bm
->master
, bgp_route_select_timer_expire
, thread_info
,
3049 BGP_ROUTE_SELECT_DELAY
,
3050 &bgp
->gr_info
[afi
][safi
].t_route_select
);
3054 static wq_item_status
bgp_process_wq(struct work_queue
*wq
, void *data
)
3056 struct bgp_process_queue
*pqnode
= data
;
3057 struct bgp
*bgp
= pqnode
->bgp
;
3058 struct bgp_table
*table
;
3059 struct bgp_dest
*dest
;
3062 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)) {
3063 bgp_process_main_one(bgp
, NULL
, 0, 0);
3064 /* should always have dedicated wq call */
3065 assert(STAILQ_FIRST(&pqnode
->pqueue
) == NULL
);
3069 while (!STAILQ_EMPTY(&pqnode
->pqueue
)) {
3070 dest
= STAILQ_FIRST(&pqnode
->pqueue
);
3071 STAILQ_REMOVE_HEAD(&pqnode
->pqueue
, pq
);
3072 STAILQ_NEXT(dest
, pq
) = NULL
; /* complete unlink */
3073 table
= bgp_dest_table(dest
);
3074 /* note, new DESTs may be added as part of processing */
3075 bgp_process_main_one(bgp
, dest
, table
->afi
, table
->safi
);
3077 bgp_dest_unlock_node(dest
);
3078 bgp_table_unlock(table
);
3084 static void bgp_processq_del(struct work_queue
*wq
, void *data
)
3086 struct bgp_process_queue
*pqnode
= data
;
3088 bgp_unlock(pqnode
->bgp
);
3090 XFREE(MTYPE_BGP_PROCESS_QUEUE
, pqnode
);
3093 void bgp_process_queue_init(struct bgp
*bgp
)
3095 if (!bgp
->process_queue
) {
3098 snprintf(name
, BUFSIZ
, "process_queue %s", bgp
->name_pretty
);
3099 bgp
->process_queue
= work_queue_new(bm
->master
, name
);
3102 bgp
->process_queue
->spec
.workfunc
= &bgp_process_wq
;
3103 bgp
->process_queue
->spec
.del_item_data
= &bgp_processq_del
;
3104 bgp
->process_queue
->spec
.max_retries
= 0;
3105 bgp
->process_queue
->spec
.hold
= 50;
3106 /* Use a higher yield value of 50ms for main queue processing */
3107 bgp
->process_queue
->spec
.yield
= 50 * 1000L;
3110 static struct bgp_process_queue
*bgp_processq_alloc(struct bgp
*bgp
)
3112 struct bgp_process_queue
*pqnode
;
3114 pqnode
= XCALLOC(MTYPE_BGP_PROCESS_QUEUE
,
3115 sizeof(struct bgp_process_queue
));
3117 /* unlocked in bgp_processq_del */
3118 pqnode
->bgp
= bgp_lock(bgp
);
3119 STAILQ_INIT(&pqnode
->pqueue
);
3124 void bgp_process(struct bgp
*bgp
, struct bgp_dest
*dest
, afi_t afi
, safi_t safi
)
3126 #define ARBITRARY_PROCESS_QLEN 10000
3127 struct work_queue
*wq
= bgp
->process_queue
;
3128 struct bgp_process_queue
*pqnode
;
3129 int pqnode_reuse
= 0;
3131 /* already scheduled for processing? */
3132 if (CHECK_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
3135 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
3138 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
3139 if (BGP_DEBUG(update
, UPDATE_OUT
))
3140 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
3145 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
)) {
3146 if (BGP_DEBUG(update
, UPDATE_OUT
))
3148 "Soft reconfigure table in progress for route %p",
3156 /* Add route nodes to an existing work queue item until reaching the
3157 limit only if is from the same BGP view and it's not an EOIU marker
3159 if (work_queue_item_count(wq
)) {
3160 struct work_queue_item
*item
= work_queue_last_item(wq
);
3161 pqnode
= item
->data
;
3163 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)
3164 || pqnode
->bgp
!= bgp
3165 || pqnode
->queued
>= ARBITRARY_PROCESS_QLEN
)
3166 pqnode
= bgp_processq_alloc(bgp
);
3170 pqnode
= bgp_processq_alloc(bgp
);
3171 /* all unlocked in bgp_process_wq */
3172 bgp_table_lock(bgp_dest_table(dest
));
3174 SET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
3175 bgp_dest_lock_node(dest
);
3177 /* can't be enqueued twice */
3178 assert(STAILQ_NEXT(dest
, pq
) == NULL
);
3179 STAILQ_INSERT_TAIL(&pqnode
->pqueue
, dest
, pq
);
3183 work_queue_add(wq
, pqnode
);
3188 void bgp_add_eoiu_mark(struct bgp
*bgp
)
3190 struct bgp_process_queue
*pqnode
;
3192 if (bgp
->process_queue
== NULL
)
3195 pqnode
= bgp_processq_alloc(bgp
);
3197 SET_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
);
3198 work_queue_add(bgp
->process_queue
, pqnode
);
3201 static int bgp_maximum_prefix_restart_timer(struct thread
*thread
)
3205 peer
= THREAD_ARG(thread
);
3206 peer
->t_pmax_restart
= NULL
;
3208 if (bgp_debug_neighbor_events(peer
))
3210 "%s Maximum-prefix restart timer expired, restore peering",
3213 if ((peer_clear(peer
, NULL
) < 0) && bgp_debug_neighbor_events(peer
))
3214 zlog_debug("%s: %s peer_clear failed", __func__
, peer
->host
);
3219 static uint32_t bgp_filtered_routes_count(struct peer
*peer
, afi_t afi
,
3223 bool filtered
= false;
3224 struct bgp_dest
*dest
;
3225 struct bgp_adj_in
*ain
;
3226 struct attr attr
= {};
3227 struct bgp_table
*table
= peer
->bgp
->rib
[afi
][safi
];
3229 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
3230 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
3231 const struct prefix
*rn_p
= bgp_dest_get_prefix(dest
);
3235 if (bgp_input_filter(peer
, rn_p
, &attr
, afi
, safi
)
3239 if (bgp_input_modifier(
3240 peer
, rn_p
, &attr
, afi
, safi
,
3241 ROUTE_MAP_IN_NAME(&peer
->filter
[afi
][safi
]),
3249 bgp_attr_undup(&attr
, ain
->attr
);
3256 bool bgp_maximum_prefix_overflow(struct peer
*peer
, afi_t afi
, safi_t safi
,
3260 iana_safi_t pkt_safi
;
3261 uint32_t pcount
= (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3262 PEER_FLAG_MAX_PREFIX_FORCE
))
3263 ? bgp_filtered_routes_count(peer
, afi
, safi
)
3264 + peer
->pcount
[afi
][safi
]
3265 : peer
->pcount
[afi
][safi
];
3267 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX
))
3270 if (pcount
> peer
->pmax
[afi
][safi
]) {
3271 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
3272 PEER_STATUS_PREFIX_LIMIT
)
3277 "%%MAXPFXEXCEED: No. of %s prefix received from %s %u exceed, limit %u",
3278 get_afi_safi_str(afi
, safi
, false), peer
->host
, pcount
,
3279 peer
->pmax
[afi
][safi
]);
3280 SET_FLAG(peer
->af_sflags
[afi
][safi
], PEER_STATUS_PREFIX_LIMIT
);
3282 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3283 PEER_FLAG_MAX_PREFIX_WARNING
))
3286 /* Convert AFI, SAFI to values for packet. */
3287 pkt_afi
= afi_int2iana(afi
);
3288 pkt_safi
= safi_int2iana(safi
);
3292 ndata
[0] = (pkt_afi
>> 8);
3294 ndata
[2] = pkt_safi
;
3295 ndata
[3] = (peer
->pmax
[afi
][safi
] >> 24);
3296 ndata
[4] = (peer
->pmax
[afi
][safi
] >> 16);
3297 ndata
[5] = (peer
->pmax
[afi
][safi
] >> 8);
3298 ndata
[6] = (peer
->pmax
[afi
][safi
]);
3300 SET_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
);
3301 bgp_notify_send_with_data(peer
, BGP_NOTIFY_CEASE
,
3302 BGP_NOTIFY_CEASE_MAX_PREFIX
,
3306 /* Dynamic peers will just close their connection. */
3307 if (peer_dynamic_neighbor(peer
))
3310 /* restart timer start */
3311 if (peer
->pmax_restart
[afi
][safi
]) {
3312 peer
->v_pmax_restart
=
3313 peer
->pmax_restart
[afi
][safi
] * 60;
3315 if (bgp_debug_neighbor_events(peer
))
3317 "%s Maximum-prefix restart timer started for %d secs",
3318 peer
->host
, peer
->v_pmax_restart
);
3320 BGP_TIMER_ON(peer
->t_pmax_restart
,
3321 bgp_maximum_prefix_restart_timer
,
3322 peer
->v_pmax_restart
);
3327 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
3328 PEER_STATUS_PREFIX_LIMIT
);
3331 > (peer
->pmax
[afi
][safi
] * peer
->pmax_threshold
[afi
][safi
] / 100)) {
3332 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
3333 PEER_STATUS_PREFIX_THRESHOLD
)
3338 "%%MAXPFX: No. of %s prefix received from %s reaches %u, max %u",
3339 get_afi_safi_str(afi
, safi
, false), peer
->host
, pcount
,
3340 peer
->pmax
[afi
][safi
]);
3341 SET_FLAG(peer
->af_sflags
[afi
][safi
],
3342 PEER_STATUS_PREFIX_THRESHOLD
);
3344 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
3345 PEER_STATUS_PREFIX_THRESHOLD
);
3349 /* Unconditionally remove the route from the RIB, without taking
3350 * damping into consideration (eg, because the session went down)
3352 void bgp_rib_remove(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
3353 struct peer
*peer
, afi_t afi
, safi_t safi
)
3356 struct bgp
*bgp
= NULL
;
3357 bool delete_route
= false;
3359 bgp_aggregate_decrement(peer
->bgp
, bgp_dest_get_prefix(dest
), pi
, afi
,
3362 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3363 bgp_path_info_delete(dest
, pi
); /* keep historical info */
3365 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3368 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
3369 delete_route
= true;
3370 else if (bgp_dest_set_defer_flag(dest
, true) < 0)
3371 delete_route
= true;
3373 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
3374 UNSET_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
);
3375 bgp
= pi
->peer
->bgp
;
3376 bgp
->gr_info
[afi
][safi
].gr_deferred
--;
3381 hook_call(bgp_process
, peer
->bgp
, afi
, safi
, dest
, peer
, true);
3382 bgp_process(peer
->bgp
, dest
, afi
, safi
);
3385 static void bgp_rib_withdraw(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
3386 struct peer
*peer
, afi_t afi
, safi_t safi
,
3387 struct prefix_rd
*prd
)
3389 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
3391 /* apply dampening, if result is suppressed, we'll be retaining
3392 * the bgp_path_info in the RIB for historical reference.
3394 if (peer
->sort
== BGP_PEER_EBGP
) {
3395 if (get_active_bdc_from_pi(pi
, afi
, safi
)) {
3396 if (bgp_damp_withdraw(pi
, dest
, afi
, safi
, 0)
3397 == BGP_DAMP_SUPPRESSED
) {
3398 bgp_aggregate_decrement(peer
->bgp
, p
, pi
, afi
,
3405 #ifdef ENABLE_BGP_VNC
3406 if (safi
== SAFI_MPLS_VPN
) {
3407 struct bgp_dest
*pdest
= NULL
;
3408 struct bgp_table
*table
= NULL
;
3410 pdest
= bgp_node_get(peer
->bgp
->rib
[afi
][safi
],
3411 (struct prefix
*)prd
);
3412 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
3413 table
= bgp_dest_get_bgp_table_info(pdest
);
3415 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3416 peer
->bgp
, prd
, table
, p
, pi
);
3418 bgp_dest_unlock_node(pdest
);
3420 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
3421 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
3423 vnc_import_bgp_del_route(peer
->bgp
, p
, pi
);
3424 vnc_import_bgp_exterior_del_route(peer
->bgp
, p
, pi
);
3429 /* If this is an EVPN route, process for un-import. */
3430 if (safi
== SAFI_EVPN
)
3431 bgp_evpn_unimport_route(peer
->bgp
, afi
, safi
, p
, pi
);
3433 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
3436 struct bgp_path_info
*info_make(int type
, int sub_type
, unsigned short instance
,
3437 struct peer
*peer
, struct attr
*attr
,
3438 struct bgp_dest
*dest
)
3440 struct bgp_path_info
*new;
3442 /* Make new BGP info. */
3443 new = XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_path_info
));
3445 new->instance
= instance
;
3446 new->sub_type
= sub_type
;
3449 new->uptime
= bgp_clock();
3454 static bool overlay_index_equal(afi_t afi
, struct bgp_path_info
*path
,
3455 union gw_addr
*gw_ip
)
3457 const struct bgp_route_evpn
*eo
= bgp_attr_get_evpn_overlay(path
->attr
);
3458 union gw_addr path_gw_ip
, *path_gw_ip_remote
;
3464 if (afi
!= AFI_L2VPN
)
3467 path_gw_ip
= eo
->gw_ip
;
3469 if (gw_ip
== NULL
) {
3470 memset(&temp
, 0, sizeof(temp
));
3471 path_gw_ip_remote
= &temp
.ip
;
3473 path_gw_ip_remote
= gw_ip
;
3475 return !!memcmp(&path_gw_ip
, path_gw_ip_remote
, sizeof(union gw_addr
));
3478 /* Check if received nexthop is valid or not. */
3479 bool bgp_update_martian_nexthop(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
3480 uint8_t type
, uint8_t stype
, struct attr
*attr
,
3481 struct bgp_dest
*dest
)
3484 bool is_bgp_static_route
=
3485 (type
== ZEBRA_ROUTE_BGP
&& stype
== BGP_ROUTE_STATIC
) ? true
3489 * Only validated for unicast and multicast currently.
3490 * Also valid for EVPN where the nexthop is an IP address.
3491 * If we are a bgp static route being checked then there is
3492 * no need to check to see if the nexthop is martian as
3493 * that it should be ok.
3495 if (is_bgp_static_route
||
3496 (safi
!= SAFI_UNICAST
&& safi
!= SAFI_MULTICAST
&& safi
!= SAFI_EVPN
))
3499 /* If NEXT_HOP is present, validate it. */
3500 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
3501 if (attr
->nexthop
.s_addr
== INADDR_ANY
3502 || IPV4_CLASS_DE(ntohl(attr
->nexthop
.s_addr
))
3503 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
, dest
))
3507 /* If MP_NEXTHOP is present, validate it. */
3508 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3509 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3510 * it is not an IPv6 link-local address.
3512 * If we receive an UPDATE with nexthop length set to 32 bytes
3513 * we shouldn't discard an UPDATE if it's set to (::).
3514 * The link-local (2st) is validated along the code path later.
3516 if (attr
->mp_nexthop_len
) {
3517 switch (attr
->mp_nexthop_len
) {
3518 case BGP_ATTR_NHLEN_IPV4
:
3519 case BGP_ATTR_NHLEN_VPNV4
:
3520 ret
= (attr
->mp_nexthop_global_in
.s_addr
== INADDR_ANY
3522 ntohl(attr
->mp_nexthop_global_in
.s_addr
))
3523 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3527 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
3528 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
3529 ret
= (IN6_IS_ADDR_UNSPECIFIED(
3530 &attr
->mp_nexthop_global
)
3531 || IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
3532 || IN6_IS_ADDR_MULTICAST(
3533 &attr
->mp_nexthop_global
)
3534 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3537 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
3538 ret
= (IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
3539 || IN6_IS_ADDR_MULTICAST(
3540 &attr
->mp_nexthop_global
)
3541 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3554 static void bgp_attr_add_no_export_community(struct attr
*attr
)
3556 struct community
*old
;
3557 struct community
*new;
3558 struct community
*merge
;
3559 struct community
*no_export
;
3561 old
= attr
->community
;
3562 no_export
= community_str2com("no-export");
3567 merge
= community_merge(community_dup(old
), no_export
);
3570 community_free(&old
);
3572 new = community_uniq_sort(merge
);
3573 community_free(&merge
);
3575 new = community_dup(no_export
);
3578 community_free(&no_export
);
3580 attr
->community
= new;
3581 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
3584 int bgp_update(struct peer
*peer
, const struct prefix
*p
, uint32_t addpath_id
,
3585 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
3586 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
3587 uint32_t num_labels
, int soft_reconfig
,
3588 struct bgp_route_evpn
*evpn
)
3591 int aspath_loop_count
= 0;
3592 struct bgp_dest
*dest
;
3594 struct attr new_attr
;
3595 struct attr
*attr_new
;
3596 struct bgp_path_info
*pi
;
3597 struct bgp_path_info
*new;
3598 struct bgp_path_info_extra
*extra
;
3600 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
3602 int do_loop_check
= 1;
3603 int has_valid_label
= 0;
3605 uint8_t pi_type
= 0;
3606 uint8_t pi_sub_type
= 0;
3608 if (frrtrace_enabled(frr_bgp
, process_update
)) {
3609 char pfxprint
[PREFIX2STR_BUFFER
];
3611 prefix2str(p
, pfxprint
, sizeof(pfxprint
));
3612 frrtrace(6, frr_bgp
, process_update
, peer
, pfxprint
, addpath_id
,
3616 #ifdef ENABLE_BGP_VNC
3617 int vnc_implicit_withdraw
= 0;
3621 memset(&new_attr
, 0, sizeof(struct attr
));
3622 new_attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
3623 new_attr
.label
= MPLS_INVALID_LABEL
;
3626 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
3627 /* TODO: Check to see if we can get rid of "is_valid_label" */
3628 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
3629 has_valid_label
= (num_labels
> 0) ? 1 : 0;
3631 has_valid_label
= bgp_is_valid_label(label
);
3633 if (has_valid_label
)
3634 assert(label
!= NULL
);
3636 /* Update overlay index of the attribute */
3637 if (afi
== AFI_L2VPN
&& evpn
)
3638 memcpy(&attr
->evpn_overlay
, evpn
,
3639 sizeof(struct bgp_route_evpn
));
3641 /* When peer's soft reconfiguration enabled. Record input packet in
3644 && CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
3645 && peer
!= bgp
->peer_self
)
3646 bgp_adj_in_set(dest
, peer
, attr
, addpath_id
);
3648 /* Check previously received route. */
3649 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
3650 if (pi
->peer
== peer
&& pi
->type
== type
3651 && pi
->sub_type
== sub_type
3652 && pi
->addpath_rx_id
== addpath_id
)
3655 /* AS path local-as loop check. */
3656 if (peer
->change_local_as
) {
3657 if (peer
->allowas_in
[afi
][safi
])
3658 aspath_loop_count
= peer
->allowas_in
[afi
][safi
];
3659 else if (!CHECK_FLAG(peer
->flags
,
3660 PEER_FLAG_LOCAL_AS_NO_PREPEND
))
3661 aspath_loop_count
= 1;
3663 if (aspath_loop_check(attr
->aspath
, peer
->change_local_as
)
3664 > aspath_loop_count
) {
3665 peer
->stat_pfx_aspath_loop
++;
3666 reason
= "as-path contains our own AS A;";
3671 /* If the peer is configured for "allowas-in origin" and the last ASN in
3673 * as-path is our ASN then we do not need to call aspath_loop_check
3675 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN_ORIGIN
))
3676 if (aspath_get_last_as(attr
->aspath
) == bgp
->as
)
3679 /* AS path loop check. */
3680 if (do_loop_check
) {
3681 if (aspath_loop_check(attr
->aspath
, bgp
->as
)
3682 > peer
->allowas_in
[afi
][safi
]
3683 || (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)
3684 && aspath_loop_check(attr
->aspath
, bgp
->confed_id
)
3685 > peer
->allowas_in
[afi
][safi
])) {
3686 peer
->stat_pfx_aspath_loop
++;
3687 reason
= "as-path contains our own AS;";
3692 /* Route reflector originator ID check. */
3693 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
3694 && IPV4_ADDR_SAME(&bgp
->router_id
, &attr
->originator_id
)) {
3695 peer
->stat_pfx_originator_loop
++;
3696 reason
= "originator is us;";
3700 /* Route reflector cluster ID check. */
3701 if (bgp_cluster_filter(peer
, attr
)) {
3702 peer
->stat_pfx_cluster_loop
++;
3703 reason
= "reflected from the same cluster;";
3707 /* Apply incoming filter. */
3708 if (bgp_input_filter(peer
, p
, attr
, afi
, safi
) == FILTER_DENY
) {
3709 peer
->stat_pfx_filter
++;
3714 /* RFC 8212 to prevent route leaks.
3715 * This specification intends to improve this situation by requiring the
3716 * explicit configuration of both BGP Import and Export Policies for any
3717 * External BGP (EBGP) session such as customers, peers, or
3718 * confederation boundaries for all enabled address families. Through
3719 * codification of the aforementioned requirement, operators will
3720 * benefit from consistent behavior across different BGP
3723 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_EBGP_REQUIRES_POLICY
))
3724 if (!bgp_inbound_policy_exists(peer
,
3725 &peer
->filter
[afi
][safi
])) {
3726 reason
= "inbound policy missing";
3730 /* draft-ietf-idr-deprecate-as-set-confed-set
3731 * Filter routes having AS_SET or AS_CONFED_SET in the path.
3732 * Eventually, This document (if approved) updates RFC 4271
3733 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
3734 * and obsoletes RFC 6472.
3736 if (peer
->bgp
->reject_as_sets
)
3737 if (aspath_check_as_sets(attr
->aspath
)) {
3739 "as-path contains AS_SET or AS_CONFED_SET type;";
3745 /* Apply incoming route-map.
3746 * NB: new_attr may now contain newly allocated values from route-map
3748 * commands, so we need bgp_attr_flush in the error paths, until we
3750 * the attr (which takes over the memory references) */
3751 if (bgp_input_modifier(peer
, p
, &new_attr
, afi
, safi
, NULL
, label
,
3754 peer
->stat_pfx_filter
++;
3755 reason
= "route-map;";
3756 bgp_attr_flush(&new_attr
);
3760 if (pi
&& pi
->attr
->rmap_table_id
!= new_attr
.rmap_table_id
) {
3761 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
3762 /* remove from RIB previous entry */
3763 bgp_zebra_withdraw(p
, pi
, bgp
, safi
);
3766 if (peer
->sort
== BGP_PEER_EBGP
) {
3769 * A BGP speaker receiving an announcement tagged with the
3770 * BLACKHOLE community SHOULD add the NO_ADVERTISE or
3771 * NO_EXPORT community as defined in RFC1997, or a
3772 * similar community, to prevent propagation of the
3773 * prefix outside the local AS. The community to prevent
3774 * propagation SHOULD be chosen according to the operator's
3777 if (new_attr
.community
3778 && community_include(new_attr
.community
,
3779 COMMUNITY_BLACKHOLE
))
3780 bgp_attr_add_no_export_community(&new_attr
);
3782 /* If we receive the graceful-shutdown community from an eBGP
3783 * peer we must lower local-preference */
3784 if (new_attr
.community
3785 && community_include(new_attr
.community
, COMMUNITY_GSHUT
)) {
3786 new_attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
3787 new_attr
.local_pref
= BGP_GSHUT_LOCAL_PREF
;
3789 /* If graceful-shutdown is configured then add the GSHUT
3790 * community to all paths received from eBGP peers */
3791 } else if (bgp_in_graceful_shutdown(peer
->bgp
))
3792 bgp_attr_add_gshut_community(&new_attr
);
3797 pi_sub_type
= pi
->sub_type
;
3800 /* next hop check. */
3801 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
)
3802 && bgp_update_martian_nexthop(bgp
, afi
, safi
, pi_type
, pi_sub_type
,
3804 peer
->stat_pfx_nh_invalid
++;
3805 reason
= "martian or self next-hop;";
3806 bgp_attr_flush(&new_attr
);
3810 if (bgp_mac_entry_exists(p
) || bgp_mac_exist(&attr
->rmac
)) {
3811 peer
->stat_pfx_nh_invalid
++;
3812 reason
= "self mac;";
3816 /* The flag BGP_NODE_FIB_INSTALL_PENDING is for the following
3818 * Suppress fib is enabled
3819 * BGP_OPT_NO_FIB is not enabled
3820 * Route type is BGP_ROUTE_NORMAL (peer learnt routes)
3821 * Route is being installed first time (BGP_NODE_FIB_INSTALLED not set)
3823 if (bgp_fibupd_safi(safi
) && BGP_SUPPRESS_FIB_ENABLED(bgp
)
3824 && (sub_type
== BGP_ROUTE_NORMAL
)
3825 && (!bgp_option_check(BGP_OPT_NO_FIB
))
3826 && (!CHECK_FLAG(dest
->flags
, BGP_NODE_FIB_INSTALLED
)))
3827 SET_FLAG(dest
->flags
, BGP_NODE_FIB_INSTALL_PENDING
);
3829 attr_new
= bgp_attr_intern(&new_attr
);
3831 /* If maximum prefix count is configured and current prefix
3834 if (bgp_maximum_prefix_overflow(peer
, afi
, safi
, 0))
3837 /* If the update is implicit withdraw. */
3839 pi
->uptime
= bgp_clock();
3840 same_attr
= attrhash_cmp(pi
->attr
, attr_new
);
3842 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, true);
3844 /* Same attribute comes in. */
3845 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
3847 && (!has_valid_label
3848 || memcmp(&(bgp_path_info_extra_get(pi
))->label
, label
,
3849 num_labels
* sizeof(mpls_label_t
))
3851 if (get_active_bdc_from_pi(pi
, afi
, safi
)
3852 && peer
->sort
== BGP_PEER_EBGP
3853 && CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3854 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3855 bgp_debug_rdpfxpath2str(
3856 afi
, safi
, prd
, p
, label
,
3857 num_labels
, addpath_id
? 1 : 0,
3858 addpath_id
, evpn
, pfx_buf
,
3860 zlog_debug("%s rcvd %s", peer
->host
,
3864 if (bgp_damp_update(pi
, dest
, afi
, safi
)
3865 != BGP_DAMP_SUPPRESSED
) {
3866 bgp_aggregate_increment(bgp
, p
, pi
, afi
,
3868 bgp_process(bgp
, dest
, afi
, safi
);
3870 } else /* Duplicate - odd */
3872 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3873 if (!peer
->rcvd_attr_printed
) {
3875 "%s rcvd UPDATE w/ attr: %s",
3877 peer
->rcvd_attr_str
);
3878 peer
->rcvd_attr_printed
= 1;
3881 bgp_debug_rdpfxpath2str(
3882 afi
, safi
, prd
, p
, label
,
3883 num_labels
, addpath_id
? 1 : 0,
3884 addpath_id
, evpn
, pfx_buf
,
3887 "%s rcvd %s...duplicate ignored",
3888 peer
->host
, pfx_buf
);
3891 /* graceful restart STALE flag unset. */
3892 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
3893 bgp_path_info_unset_flag(
3894 dest
, pi
, BGP_PATH_STALE
);
3895 bgp_dest_set_defer_flag(dest
, false);
3896 bgp_process(bgp
, dest
, afi
, safi
);
3900 bgp_dest_unlock_node(dest
);
3901 bgp_attr_unintern(&attr_new
);
3906 /* Withdraw/Announce before we fully processed the withdraw */
3907 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
3908 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3909 bgp_debug_rdpfxpath2str(
3910 afi
, safi
, prd
, p
, label
, num_labels
,
3911 addpath_id
? 1 : 0, addpath_id
, evpn
,
3912 pfx_buf
, sizeof(pfx_buf
));
3914 "%s rcvd %s, flapped quicker than processing",
3915 peer
->host
, pfx_buf
);
3918 bgp_path_info_restore(dest
, pi
);
3921 /* Received Logging. */
3922 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3923 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
3924 num_labels
, addpath_id
? 1 : 0,
3925 addpath_id
, evpn
, pfx_buf
,
3927 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3930 /* graceful restart STALE flag unset. */
3931 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
3932 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_STALE
);
3933 bgp_dest_set_defer_flag(dest
, false);
3936 /* The attribute is changed. */
3937 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
3939 /* implicit withdraw, decrement aggregate and pcount here.
3940 * only if update is accepted, they'll increment below.
3942 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
3944 /* Update bgp route dampening information. */
3945 if (get_active_bdc_from_pi(pi
, afi
, safi
)
3946 && peer
->sort
== BGP_PEER_EBGP
) {
3947 /* This is implicit withdraw so we should update
3948 * dampening information.
3950 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
3951 bgp_damp_withdraw(pi
, dest
, afi
, safi
, 1);
3953 #ifdef ENABLE_BGP_VNC
3954 if (safi
== SAFI_MPLS_VPN
) {
3955 struct bgp_dest
*pdest
= NULL
;
3956 struct bgp_table
*table
= NULL
;
3958 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
],
3959 (struct prefix
*)prd
);
3960 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
3961 table
= bgp_dest_get_bgp_table_info(pdest
);
3963 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3964 bgp
, prd
, table
, p
, pi
);
3966 bgp_dest_unlock_node(pdest
);
3968 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3969 && (safi
== SAFI_UNICAST
)) {
3970 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
3972 * Implicit withdraw case.
3974 ++vnc_implicit_withdraw
;
3975 vnc_import_bgp_del_route(bgp
, p
, pi
);
3976 vnc_import_bgp_exterior_del_route(bgp
, p
, pi
);
3981 /* Special handling for EVPN update of an existing route. If the
3982 * extended community attribute has changed, we need to
3984 * the route using its existing extended community. It will be
3985 * subsequently processed for import with the new extended
3988 if (((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
))
3991 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))
3993 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
3996 cmp
= ecommunity_cmp(pi
->attr
->ecommunity
,
3997 attr_new
->ecommunity
);
3999 if (bgp_debug_update(peer
, p
, NULL
, 1))
4001 "Change in EXT-COMM, existing %s new %s",
4003 pi
->attr
->ecommunity
),
4005 attr_new
->ecommunity
));
4006 if (safi
== SAFI_EVPN
)
4007 bgp_evpn_unimport_route(
4008 bgp
, afi
, safi
, p
, pi
);
4009 else /* SAFI_MPLS_VPN */
4010 vpn_leak_to_vrf_withdraw(bgp
,
4016 /* Update to new attribute. */
4017 bgp_attr_unintern(&pi
->attr
);
4018 pi
->attr
= attr_new
;
4020 /* Update MPLS label */
4021 if (has_valid_label
) {
4022 extra
= bgp_path_info_extra_get(pi
);
4023 if (extra
->label
!= label
) {
4024 memcpy(&extra
->label
, label
,
4025 num_labels
* sizeof(mpls_label_t
));
4026 extra
->num_labels
= num_labels
;
4028 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
4029 bgp_set_valid_label(&extra
->label
[0]);
4032 /* Update SRv6 SID */
4033 if (attr
->srv6_l3vpn
) {
4034 extra
= bgp_path_info_extra_get(pi
);
4035 if (sid_diff(&extra
->sid
[0], &attr
->srv6_l3vpn
->sid
)) {
4036 sid_copy(&extra
->sid
[0],
4037 &attr
->srv6_l3vpn
->sid
);
4038 extra
->num_sids
= 1;
4040 } else if (attr
->srv6_vpn
) {
4041 extra
= bgp_path_info_extra_get(pi
);
4042 if (sid_diff(&extra
->sid
[0], &attr
->srv6_vpn
->sid
)) {
4043 sid_copy(&extra
->sid
[0], &attr
->srv6_vpn
->sid
);
4044 extra
->num_sids
= 1;
4048 #ifdef ENABLE_BGP_VNC
4049 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4050 && (safi
== SAFI_UNICAST
)) {
4051 if (vnc_implicit_withdraw
) {
4053 * Add back the route with its new attributes
4055 * The route is still selected, until the route
4057 * queued by bgp_process actually runs. We have
4059 * update to the VNC side immediately to avoid
4061 * configuration changes (e.g., route-map
4063 * trigger re-importation of the entire RIB.
4065 vnc_import_bgp_add_route(bgp
, p
, pi
);
4066 vnc_import_bgp_exterior_add_route(bgp
, p
, pi
);
4071 /* Update bgp route dampening information. */
4072 if (get_active_bdc_from_pi(pi
, afi
, safi
)
4073 && peer
->sort
== BGP_PEER_EBGP
) {
4074 /* Now we do normal update dampening. */
4075 ret
= bgp_damp_update(pi
, dest
, afi
, safi
);
4076 if (ret
== BGP_DAMP_SUPPRESSED
) {
4077 bgp_dest_unlock_node(dest
);
4082 /* Nexthop reachability check - for unicast and
4083 * labeled-unicast.. */
4084 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
4085 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
4086 || (safi
== SAFI_EVPN
&&
4087 bgp_evpn_is_prefix_nht_supported(p
))) {
4088 if (safi
!= SAFI_EVPN
&& peer
->sort
== BGP_PEER_EBGP
4089 && peer
->ttl
== BGP_DEFAULT_TTL
4090 && !CHECK_FLAG(peer
->flags
,
4091 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
4092 && !CHECK_FLAG(bgp
->flags
,
4093 BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
4098 struct bgp
*bgp_nexthop
= bgp
;
4100 if (pi
->extra
&& pi
->extra
->bgp_orig
)
4101 bgp_nexthop
= pi
->extra
->bgp_orig
;
4103 nh_afi
= BGP_ATTR_NH_AFI(afi
, pi
->attr
);
4105 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
, nh_afi
,
4106 safi
, pi
, NULL
, connected
)
4107 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
4108 bgp_path_info_set_flag(dest
, pi
,
4111 if (BGP_DEBUG(nht
, NHT
)) {
4112 zlog_debug("%s(%pI4): NH unresolved",
4114 (in_addr_t
*)&attr_new
->nexthop
);
4116 bgp_path_info_unset_flag(dest
, pi
,
4120 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_VALID
);
4122 #ifdef ENABLE_BGP_VNC
4123 if (safi
== SAFI_MPLS_VPN
) {
4124 struct bgp_dest
*pdest
= NULL
;
4125 struct bgp_table
*table
= NULL
;
4127 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
],
4128 (struct prefix
*)prd
);
4129 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
4130 table
= bgp_dest_get_bgp_table_info(pdest
);
4132 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4133 bgp
, prd
, table
, p
, pi
);
4135 bgp_dest_unlock_node(pdest
);
4139 /* If this is an EVPN route and some attribute has changed,
4141 * route for import. If the extended community has changed, we
4143 * have done the un-import earlier and the import would result
4145 * route getting injected into appropriate L2 VNIs. If it is
4147 * some other attribute change, the import will result in
4149 * the attributes for the route in the VNI(s).
4151 if (safi
== SAFI_EVPN
&& !same_attr
&&
4152 CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
4153 bgp_evpn_import_route(bgp
, afi
, safi
, p
, pi
);
4155 /* Process change. */
4156 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
4158 bgp_process(bgp
, dest
, afi
, safi
);
4159 bgp_dest_unlock_node(dest
);
4161 if (SAFI_UNICAST
== safi
4162 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4163 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4165 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, pi
);
4167 if ((SAFI_MPLS_VPN
== safi
)
4168 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4170 vpn_leak_to_vrf_update(bgp
, pi
);
4173 #ifdef ENABLE_BGP_VNC
4174 if (SAFI_MPLS_VPN
== safi
) {
4175 mpls_label_t label_decoded
= decode_label(label
);
4177 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
4178 type
, sub_type
, &label_decoded
);
4180 if (SAFI_ENCAP
== safi
) {
4181 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
4182 type
, sub_type
, NULL
);
4187 } // End of implicit withdraw
4189 /* Received Logging. */
4190 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4191 if (!peer
->rcvd_attr_printed
) {
4192 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
4193 peer
->rcvd_attr_str
);
4194 peer
->rcvd_attr_printed
= 1;
4197 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4198 addpath_id
? 1 : 0, addpath_id
, evpn
,
4199 pfx_buf
, sizeof(pfx_buf
));
4200 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
4203 /* Make new BGP info. */
4204 new = info_make(type
, sub_type
, 0, peer
, attr_new
, dest
);
4206 /* Update MPLS label */
4207 if (has_valid_label
) {
4208 extra
= bgp_path_info_extra_get(new);
4209 if (extra
->label
!= label
) {
4210 memcpy(&extra
->label
, label
,
4211 num_labels
* sizeof(mpls_label_t
));
4212 extra
->num_labels
= num_labels
;
4214 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
4215 bgp_set_valid_label(&extra
->label
[0]);
4218 /* Update SRv6 SID */
4219 if (safi
== SAFI_MPLS_VPN
) {
4220 extra
= bgp_path_info_extra_get(new);
4221 if (attr
->srv6_l3vpn
) {
4222 sid_copy(&extra
->sid
[0], &attr
->srv6_l3vpn
->sid
);
4223 extra
->num_sids
= 1;
4224 } else if (attr
->srv6_vpn
) {
4225 sid_copy(&extra
->sid
[0], &attr
->srv6_vpn
->sid
);
4226 extra
->num_sids
= 1;
4230 /* Nexthop reachability check. */
4231 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
4232 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
4233 || (safi
== SAFI_EVPN
&& bgp_evpn_is_prefix_nht_supported(p
))) {
4234 if (safi
!= SAFI_EVPN
&& peer
->sort
== BGP_PEER_EBGP
4235 && peer
->ttl
== BGP_DEFAULT_TTL
4236 && !CHECK_FLAG(peer
->flags
,
4237 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
4238 && !CHECK_FLAG(bgp
->flags
,
4239 BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
4244 nh_afi
= BGP_ATTR_NH_AFI(afi
, new->attr
);
4246 if (bgp_find_or_add_nexthop(bgp
, bgp
, nh_afi
, safi
, new, NULL
,
4248 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
4249 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
4251 if (BGP_DEBUG(nht
, NHT
)) {
4252 char buf1
[INET6_ADDRSTRLEN
];
4254 (const void *)&attr_new
->nexthop
,
4255 buf1
, INET6_ADDRSTRLEN
);
4256 zlog_debug("%s(%s): NH unresolved", __func__
,
4259 bgp_path_info_unset_flag(dest
, new, BGP_PATH_VALID
);
4262 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
4265 new->addpath_rx_id
= addpath_id
;
4267 /* Increment prefix */
4268 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4270 /* Register new BGP information. */
4271 bgp_path_info_add(dest
, new);
4273 /* route_node_get lock */
4274 bgp_dest_unlock_node(dest
);
4276 #ifdef ENABLE_BGP_VNC
4277 if (safi
== SAFI_MPLS_VPN
) {
4278 struct bgp_dest
*pdest
= NULL
;
4279 struct bgp_table
*table
= NULL
;
4281 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
4282 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
4283 table
= bgp_dest_get_bgp_table_info(pdest
);
4285 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4286 bgp
, prd
, table
, p
, new);
4288 bgp_dest_unlock_node(pdest
);
4292 /* If this is an EVPN route, process for import. */
4293 if (safi
== SAFI_EVPN
&& CHECK_FLAG(new->flags
, BGP_PATH_VALID
))
4294 bgp_evpn_import_route(bgp
, afi
, safi
, p
, new);
4296 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, false);
4298 /* Process change. */
4299 bgp_process(bgp
, dest
, afi
, safi
);
4301 if (SAFI_UNICAST
== safi
4302 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4303 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4304 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
4306 if ((SAFI_MPLS_VPN
== safi
)
4307 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4309 vpn_leak_to_vrf_update(bgp
, new);
4311 #ifdef ENABLE_BGP_VNC
4312 if (SAFI_MPLS_VPN
== safi
) {
4313 mpls_label_t label_decoded
= decode_label(label
);
4315 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
4316 sub_type
, &label_decoded
);
4318 if (SAFI_ENCAP
== safi
) {
4319 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
4326 /* This BGP update is filtered. Log the reason then update BGP
4329 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, true);
4331 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4332 if (!peer
->rcvd_attr_printed
) {
4333 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
4334 peer
->rcvd_attr_str
);
4335 peer
->rcvd_attr_printed
= 1;
4338 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4339 addpath_id
? 1 : 0, addpath_id
, evpn
,
4340 pfx_buf
, sizeof(pfx_buf
));
4341 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
4342 peer
->host
, pfx_buf
, reason
);
4346 /* If this is an EVPN route, un-import it as it is now filtered.
4348 if (safi
== SAFI_EVPN
)
4349 bgp_evpn_unimport_route(bgp
, afi
, safi
, p
, pi
);
4351 if (SAFI_UNICAST
== safi
4352 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4353 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4355 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
4357 if ((SAFI_MPLS_VPN
== safi
)
4358 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4360 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4363 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
4366 bgp_dest_unlock_node(dest
);
4368 #ifdef ENABLE_BGP_VNC
4370 * Filtered update is treated as an implicit withdrawal (see
4372 * a few lines above)
4374 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
4375 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
4383 int bgp_withdraw(struct peer
*peer
, const struct prefix
*p
, uint32_t addpath_id
,
4384 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
4385 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
4386 uint32_t num_labels
, struct bgp_route_evpn
*evpn
)
4389 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
4390 struct bgp_dest
*dest
;
4391 struct bgp_path_info
*pi
;
4393 #ifdef ENABLE_BGP_VNC
4394 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
4395 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
4403 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4405 /* If peer is soft reconfiguration enabled. Record input packet for
4406 * further calculation.
4408 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4409 * routes that are filtered. This tanks out Quagga RS pretty badly due
4411 * the iteration over all RS clients.
4412 * Since we need to remove the entry from adj_in anyway, do that first
4414 * if there was no entry, we don't need to do anything more.
4416 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
4417 && peer
!= bgp
->peer_self
)
4418 if (!bgp_adj_in_unset(dest
, peer
, addpath_id
)) {
4419 peer
->stat_pfx_dup_withdraw
++;
4421 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4422 bgp_debug_rdpfxpath2str(
4423 afi
, safi
, prd
, p
, label
, num_labels
,
4424 addpath_id
? 1 : 0, addpath_id
, NULL
,
4425 pfx_buf
, sizeof(pfx_buf
));
4427 "%s withdrawing route %s not in adj-in",
4428 peer
->host
, pfx_buf
);
4430 bgp_dest_unlock_node(dest
);
4434 /* Lookup withdrawn route. */
4435 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
4436 if (pi
->peer
== peer
&& pi
->type
== type
4437 && pi
->sub_type
== sub_type
4438 && pi
->addpath_rx_id
== addpath_id
)
4442 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4443 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4444 addpath_id
? 1 : 0, addpath_id
, NULL
,
4445 pfx_buf
, sizeof(pfx_buf
));
4446 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer
->host
,
4450 /* Withdraw specified route from routing table. */
4451 if (pi
&& !CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
4452 bgp_rib_withdraw(dest
, pi
, peer
, afi
, safi
, prd
);
4453 if (SAFI_UNICAST
== safi
4454 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4455 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4456 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
4458 if ((SAFI_MPLS_VPN
== safi
)
4459 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4461 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4463 } else if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4464 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4465 addpath_id
? 1 : 0, addpath_id
, NULL
,
4466 pfx_buf
, sizeof(pfx_buf
));
4467 zlog_debug("%s Can't find the route %s", peer
->host
, pfx_buf
);
4470 /* Unlock bgp_node_get() lock. */
4471 bgp_dest_unlock_node(dest
);
4476 void bgp_default_originate(struct peer
*peer
, afi_t afi
, safi_t safi
,
4479 struct update_subgroup
*subgrp
;
4480 subgrp
= peer_subgroup(peer
, afi
, safi
);
4481 subgroup_default_originate(subgrp
, withdraw
);
4486 * bgp_stop_announce_route_timer
4488 void bgp_stop_announce_route_timer(struct peer_af
*paf
)
4490 if (!paf
->t_announce_route
)
4493 thread_cancel(&paf
->t_announce_route
);
4497 * bgp_announce_route_timer_expired
4499 * Callback that is invoked when the route announcement timer for a
4502 static int bgp_announce_route_timer_expired(struct thread
*t
)
4504 struct peer_af
*paf
;
4507 paf
= THREAD_ARG(t
);
4510 if (!peer_established(peer
))
4513 if (!peer
->afc_nego
[paf
->afi
][paf
->safi
])
4516 peer_af_announce_route(paf
, 1);
4518 /* Notify BGP conditional advertisement scanner percess */
4519 peer
->advmap_config_change
[paf
->afi
][paf
->safi
] = true;
4525 * bgp_announce_route
4527 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
4529 void bgp_announce_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4531 struct peer_af
*paf
;
4532 struct update_subgroup
*subgrp
;
4534 paf
= peer_af_find(peer
, afi
, safi
);
4537 subgrp
= PAF_SUBGRP(paf
);
4540 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
4541 * or a refresh has already been triggered.
4543 if (!subgrp
|| paf
->t_announce_route
)
4547 * Start a timer to stagger/delay the announce. This serves
4548 * two purposes - announcement can potentially be combined for
4549 * multiple peers and the announcement doesn't happen in the
4552 thread_add_timer_msec(bm
->master
, bgp_announce_route_timer_expired
, paf
,
4553 (subgrp
->peer_count
== 1)
4554 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
4555 : BGP_ANNOUNCE_ROUTE_DELAY_MS
,
4556 &paf
->t_announce_route
);
4560 * Announce routes from all AF tables to a peer.
4562 * This should ONLY be called when there is a need to refresh the
4563 * routes to the peer based on a policy change for this peer alone
4564 * or a route refresh request received from the peer.
4565 * The operation will result in splitting the peer from its existing
4566 * subgroups and putting it in new subgroups.
4568 void bgp_announce_route_all(struct peer
*peer
)
4573 FOREACH_AFI_SAFI (afi
, safi
)
4574 bgp_announce_route(peer
, afi
, safi
);
4577 /* Flag or unflag bgp_dest to determine whether it should be treated by
4578 * bgp_soft_reconfig_table_task.
4579 * Flag if flag is true. Unflag if flag is false.
4581 static void bgp_soft_reconfig_table_flag(struct bgp_table
*table
, bool flag
)
4583 struct bgp_dest
*dest
;
4584 struct bgp_adj_in
*ain
;
4589 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
4590 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
4591 if (ain
->peer
!= NULL
)
4594 if (flag
&& ain
!= NULL
&& ain
->peer
!= NULL
)
4595 SET_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
);
4597 UNSET_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
);
4601 static int bgp_soft_reconfig_table_update(struct peer
*peer
,
4602 struct bgp_dest
*dest
,
4603 struct bgp_adj_in
*ain
, afi_t afi
,
4604 safi_t safi
, struct prefix_rd
*prd
)
4606 struct bgp_path_info
*pi
;
4607 uint32_t num_labels
= 0;
4608 mpls_label_t
*label_pnt
= NULL
;
4609 struct bgp_route_evpn evpn
;
4611 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
4612 if (pi
->peer
== peer
)
4615 if (pi
&& pi
->extra
)
4616 num_labels
= pi
->extra
->num_labels
;
4618 label_pnt
= &pi
->extra
->label
[0];
4620 memcpy(&evpn
, bgp_attr_get_evpn_overlay(pi
->attr
),
4623 memset(&evpn
, 0, sizeof(evpn
));
4625 return bgp_update(peer
, bgp_dest_get_prefix(dest
), ain
->addpath_rx_id
,
4626 ain
->attr
, afi
, safi
, ZEBRA_ROUTE_BGP
,
4627 BGP_ROUTE_NORMAL
, prd
, label_pnt
, num_labels
, 1,
4631 static void bgp_soft_reconfig_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
4632 struct bgp_table
*table
,
4633 struct prefix_rd
*prd
)
4636 struct bgp_dest
*dest
;
4637 struct bgp_adj_in
*ain
;
4640 table
= peer
->bgp
->rib
[afi
][safi
];
4642 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
))
4643 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
4644 if (ain
->peer
!= peer
)
4647 ret
= bgp_soft_reconfig_table_update(peer
, dest
, ain
,
4651 bgp_dest_unlock_node(dest
);
4657 /* Do soft reconfig table per bgp table.
4658 * Walk on SOFT_RECONFIG_TASK_MAX_PREFIX bgp_dest,
4659 * when BGP_NODE_SOFT_RECONFIG is set,
4660 * reconfig bgp_dest for list of table->soft_reconfig_peers peers.
4661 * Schedule a new thread to continue the job.
4662 * Without splitting the full job into several part,
4663 * vtysh waits for the job to finish before responding to a BGP command
4665 static int bgp_soft_reconfig_table_task(struct thread
*thread
)
4667 uint32_t iter
, max_iter
;
4669 struct bgp_dest
*dest
;
4670 struct bgp_adj_in
*ain
;
4672 struct bgp_table
*table
;
4673 struct prefix_rd
*prd
;
4674 struct listnode
*node
, *nnode
;
4676 table
= THREAD_ARG(thread
);
4679 max_iter
= SOFT_RECONFIG_TASK_MAX_PREFIX
;
4680 if (table
->soft_reconfig_init
) {
4681 /* first call of the function with a new srta structure.
4682 * Don't do any treatment this time on nodes
4683 * in order vtysh to respond quickly
4688 for (iter
= 0, dest
= bgp_table_top(table
); (dest
&& iter
< max_iter
);
4689 dest
= bgp_route_next(dest
)) {
4690 if (!CHECK_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
))
4693 UNSET_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
);
4695 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
4696 for (ALL_LIST_ELEMENTS(table
->soft_reconfig_peers
, node
,
4698 if (ain
->peer
!= peer
)
4701 ret
= bgp_soft_reconfig_table_update(
4702 peer
, dest
, ain
, table
->afi
,
4707 bgp_dest_unlock_node(dest
);
4709 table
->soft_reconfig_peers
,
4711 bgp_announce_route(peer
, table
->afi
,
4714 table
->soft_reconfig_peers
)) {
4716 &table
->soft_reconfig_peers
);
4717 bgp_soft_reconfig_table_flag(
4726 /* we're either starting the initial iteration,
4727 * or we're going to continue an ongoing iteration
4729 if (dest
|| table
->soft_reconfig_init
) {
4730 table
->soft_reconfig_init
= false;
4731 thread_add_event(bm
->master
, bgp_soft_reconfig_table_task
,
4732 table
, 0, &table
->soft_reconfig_thread
);
4735 /* we're done, clean up the background iteration context info and
4736 schedule route annoucement
4738 for (ALL_LIST_ELEMENTS(table
->soft_reconfig_peers
, node
, nnode
, peer
)) {
4739 listnode_delete(table
->soft_reconfig_peers
, peer
);
4740 bgp_announce_route(peer
, table
->afi
, table
->safi
);
4743 list_delete(&table
->soft_reconfig_peers
);
4749 /* Cancel soft_reconfig_table task matching bgp instance, bgp_table
4751 * - bgp cannot be NULL
4752 * - if table and peer are NULL, cancel all threads within the bgp instance
4753 * - if table is NULL and peer is not,
4754 * remove peer in all threads within the bgp instance
4755 * - if peer is NULL, cancel all threads matching table within the bgp instance
4757 void bgp_soft_reconfig_table_task_cancel(const struct bgp
*bgp
,
4758 const struct bgp_table
*table
,
4759 const struct peer
*peer
)
4762 struct listnode
*node
, *nnode
;
4764 struct bgp_table
*ntable
;
4769 FOREACH_AFI_SAFI (afi
, safi
) {
4770 ntable
= bgp
->rib
[afi
][safi
];
4773 if (table
&& table
!= ntable
)
4776 for (ALL_LIST_ELEMENTS(ntable
->soft_reconfig_peers
, node
, nnode
,
4778 if (peer
&& peer
!= npeer
)
4780 listnode_delete(ntable
->soft_reconfig_peers
, npeer
);
4783 if (!ntable
->soft_reconfig_peers
4784 || !list_isempty(ntable
->soft_reconfig_peers
))
4787 list_delete(&ntable
->soft_reconfig_peers
);
4788 bgp_soft_reconfig_table_flag(ntable
, false);
4789 BGP_TIMER_OFF(ntable
->soft_reconfig_thread
);
4793 void bgp_soft_reconfig_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
4795 struct bgp_dest
*dest
;
4796 struct bgp_table
*table
;
4797 struct listnode
*node
, *nnode
;
4799 struct peer_af
*paf
;
4801 if (!peer_established(peer
))
4804 if ((safi
!= SAFI_MPLS_VPN
) && (safi
!= SAFI_ENCAP
)
4805 && (safi
!= SAFI_EVPN
)) {
4806 table
= peer
->bgp
->rib
[afi
][safi
];
4810 table
->soft_reconfig_init
= true;
4812 if (!table
->soft_reconfig_peers
)
4813 table
->soft_reconfig_peers
= list_new();
4815 /* add peer to the table soft_reconfig_peers if not already
4818 for (ALL_LIST_ELEMENTS(table
->soft_reconfig_peers
, node
, nnode
,
4824 listnode_add(table
->soft_reconfig_peers
, peer
);
4826 /* (re)flag all bgp_dest in table. Existing soft_reconfig_in job
4827 * on table would start back at the beginning.
4829 bgp_soft_reconfig_table_flag(table
, true);
4831 if (!table
->soft_reconfig_thread
)
4832 thread_add_event(bm
->master
,
4833 bgp_soft_reconfig_table_task
, table
, 0,
4834 &table
->soft_reconfig_thread
);
4835 /* Cancel bgp_announce_route_timer_expired threads.
4836 * bgp_announce_route_timer_expired threads have been scheduled
4837 * to announce routes as soon as the soft_reconfigure process
4839 * In this case, soft_reconfigure is also scheduled by using
4840 * a thread but is planned after the
4841 * bgp_announce_route_timer_expired threads. It means that,
4842 * without cancelling the threads, the route announcement task
4843 * would run before the soft reconfiguration one. That would
4844 * useless and would block vtysh during several seconds. Route
4845 * announcements are rescheduled as soon as the soft_reconfigure
4848 paf
= peer_af_find(peer
, afi
, safi
);
4850 bgp_stop_announce_route_timer(paf
);
4852 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
4853 dest
= bgp_route_next(dest
)) {
4854 table
= bgp_dest_get_bgp_table_info(dest
);
4859 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
4860 struct prefix_rd prd
;
4862 prd
.family
= AF_UNSPEC
;
4864 memcpy(&prd
.val
, p
->u
.val
, 8);
4866 bgp_soft_reconfig_table(peer
, afi
, safi
, table
, &prd
);
4871 struct bgp_clear_node_queue
{
4872 struct bgp_dest
*dest
;
4875 static wq_item_status
bgp_clear_route_node(struct work_queue
*wq
, void *data
)
4877 struct bgp_clear_node_queue
*cnq
= data
;
4878 struct bgp_dest
*dest
= cnq
->dest
;
4879 struct peer
*peer
= wq
->spec
.data
;
4880 struct bgp_path_info
*pi
;
4882 afi_t afi
= bgp_dest_table(dest
)->afi
;
4883 safi_t safi
= bgp_dest_table(dest
)->safi
;
4885 assert(dest
&& peer
);
4888 /* It is possible that we have multiple paths for a prefix from a peer
4889 * if that peer is using AddPath.
4891 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
4892 if (pi
->peer
!= peer
)
4895 /* graceful restart STALE flag set. */
4896 if (((CHECK_FLAG(peer
->sflags
, PEER_STATUS_NSF_WAIT
)
4897 && peer
->nsf
[afi
][safi
])
4898 || CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
4899 PEER_STATUS_ENHANCED_REFRESH
))
4900 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
4901 && !CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
4902 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_STALE
);
4904 /* If this is an EVPN route, process for
4906 if (safi
== SAFI_EVPN
)
4907 bgp_evpn_unimport_route(
4909 bgp_dest_get_prefix(dest
), pi
);
4910 /* Handle withdraw for VRF route-leaking and L3VPN */
4911 if (SAFI_UNICAST
== safi
4912 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
||
4913 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4914 vpn_leak_from_vrf_withdraw(bgp_get_default(),
4917 if (SAFI_MPLS_VPN
== safi
&&
4918 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4919 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4922 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
4928 static void bgp_clear_node_queue_del(struct work_queue
*wq
, void *data
)
4930 struct bgp_clear_node_queue
*cnq
= data
;
4931 struct bgp_dest
*dest
= cnq
->dest
;
4932 struct bgp_table
*table
= bgp_dest_table(dest
);
4934 bgp_dest_unlock_node(dest
);
4935 bgp_table_unlock(table
);
4936 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE
, cnq
);
4939 static void bgp_clear_node_complete(struct work_queue
*wq
)
4941 struct peer
*peer
= wq
->spec
.data
;
4943 /* Tickle FSM to start moving again */
4944 BGP_EVENT_ADD(peer
, Clearing_Completed
);
4946 peer_unlock(peer
); /* bgp_clear_route */
4949 static void bgp_clear_node_queue_init(struct peer
*peer
)
4951 char wname
[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
4953 snprintf(wname
, sizeof(wname
), "clear %s", peer
->host
);
4954 #undef CLEAR_QUEUE_NAME_LEN
4956 peer
->clear_node_queue
= work_queue_new(bm
->master
, wname
);
4957 peer
->clear_node_queue
->spec
.hold
= 10;
4958 peer
->clear_node_queue
->spec
.workfunc
= &bgp_clear_route_node
;
4959 peer
->clear_node_queue
->spec
.del_item_data
= &bgp_clear_node_queue_del
;
4960 peer
->clear_node_queue
->spec
.completion_func
= &bgp_clear_node_complete
;
4961 peer
->clear_node_queue
->spec
.max_retries
= 0;
4963 /* we only 'lock' this peer reference when the queue is actually active
4965 peer
->clear_node_queue
->spec
.data
= peer
;
4968 static void bgp_clear_route_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
4969 struct bgp_table
*table
)
4971 struct bgp_dest
*dest
;
4972 int force
= peer
->bgp
->process_queue
? 0 : 1;
4975 table
= peer
->bgp
->rib
[afi
][safi
];
4977 /* If still no table => afi/safi isn't configured at all or smth. */
4981 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
4982 struct bgp_path_info
*pi
, *next
;
4983 struct bgp_adj_in
*ain
;
4984 struct bgp_adj_in
*ain_next
;
4986 /* XXX:TODO: This is suboptimal, every non-empty route_node is
4987 * queued for every clearing peer, regardless of whether it is
4988 * relevant to the peer at hand.
4990 * Overview: There are 3 different indices which need to be
4991 * scrubbed, potentially, when a peer is removed:
4993 * 1 peer's routes visible via the RIB (ie accepted routes)
4994 * 2 peer's routes visible by the (optional) peer's adj-in index
4995 * 3 other routes visible by the peer's adj-out index
4997 * 3 there is no hurry in scrubbing, once the struct peer is
4998 * removed from bgp->peer, we could just GC such deleted peer's
4999 * adj-outs at our leisure.
5001 * 1 and 2 must be 'scrubbed' in some way, at least made
5002 * invisible via RIB index before peer session is allowed to be
5003 * brought back up. So one needs to know when such a 'search' is
5008 * - there'd be a single global queue or a single RIB walker
5009 * - rather than tracking which route_nodes still need to be
5010 * examined on a peer basis, we'd track which peers still
5013 * Given that our per-peer prefix-counts now should be reliable,
5014 * this may actually be achievable. It doesn't seem to be a huge
5015 * problem at this time,
5017 * It is possible that we have multiple paths for a prefix from
5019 * if that peer is using AddPath.
5023 ain_next
= ain
->next
;
5025 if (ain
->peer
== peer
)
5026 bgp_adj_in_remove(dest
, ain
);
5031 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= next
) {
5033 if (pi
->peer
!= peer
)
5037 bgp_path_info_reap(dest
, pi
);
5039 struct bgp_clear_node_queue
*cnq
;
5041 /* both unlocked in bgp_clear_node_queue_del */
5042 bgp_table_lock(bgp_dest_table(dest
));
5043 bgp_dest_lock_node(dest
);
5045 MTYPE_BGP_CLEAR_NODE_QUEUE
,
5046 sizeof(struct bgp_clear_node_queue
));
5048 work_queue_add(peer
->clear_node_queue
, cnq
);
5056 void bgp_clear_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
5058 struct bgp_dest
*dest
;
5059 struct bgp_table
*table
;
5061 if (peer
->clear_node_queue
== NULL
)
5062 bgp_clear_node_queue_init(peer
);
5064 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
5065 * Idle until it receives a Clearing_Completed event. This protects
5066 * against peers which flap faster than we can we clear, which could
5069 * a) race with routes from the new session being installed before
5070 * clear_route_node visits the node (to delete the route of that
5072 * b) resource exhaustion, clear_route_node likely leads to an entry
5073 * on the process_main queue. Fast-flapping could cause that queue
5077 /* lock peer in assumption that clear-node-queue will get nodes; if so,
5078 * the unlock will happen upon work-queue completion; other wise, the
5079 * unlock happens at the end of this function.
5081 if (!peer
->clear_node_queue
->thread
)
5084 if (safi
!= SAFI_MPLS_VPN
&& safi
!= SAFI_ENCAP
&& safi
!= SAFI_EVPN
)
5085 bgp_clear_route_table(peer
, afi
, safi
, NULL
);
5087 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5088 dest
= bgp_route_next(dest
)) {
5089 table
= bgp_dest_get_bgp_table_info(dest
);
5093 bgp_clear_route_table(peer
, afi
, safi
, table
);
5096 /* unlock if no nodes got added to the clear-node-queue. */
5097 if (!peer
->clear_node_queue
->thread
)
5101 void bgp_clear_route_all(struct peer
*peer
)
5106 FOREACH_AFI_SAFI (afi
, safi
)
5107 bgp_clear_route(peer
, afi
, safi
);
5109 #ifdef ENABLE_BGP_VNC
5110 rfapiProcessPeerDown(peer
);
5114 void bgp_clear_adj_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
5116 struct bgp_table
*table
;
5117 struct bgp_dest
*dest
;
5118 struct bgp_adj_in
*ain
;
5119 struct bgp_adj_in
*ain_next
;
5121 table
= peer
->bgp
->rib
[afi
][safi
];
5123 /* It is possible that we have multiple paths for a prefix from a peer
5124 * if that peer is using AddPath.
5126 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
5130 ain_next
= ain
->next
;
5132 if (ain
->peer
== peer
)
5133 bgp_adj_in_remove(dest
, ain
);
5140 void bgp_clear_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
5142 struct bgp_dest
*dest
;
5143 struct bgp_path_info
*pi
;
5144 struct bgp_table
*table
;
5146 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
5147 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5148 dest
= bgp_route_next(dest
)) {
5149 struct bgp_dest
*rm
;
5151 /* look for neighbor in tables */
5152 table
= bgp_dest_get_bgp_table_info(dest
);
5156 for (rm
= bgp_table_top(table
); rm
;
5157 rm
= bgp_route_next(rm
))
5158 for (pi
= bgp_dest_get_bgp_path_info(rm
); pi
;
5160 if (pi
->peer
!= peer
)
5162 if (!CHECK_FLAG(pi
->flags
,
5166 bgp_rib_remove(rm
, pi
, peer
, afi
, safi
);
5171 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5172 dest
= bgp_route_next(dest
))
5173 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
5175 if (pi
->peer
!= peer
)
5177 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
5179 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
5185 void bgp_set_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
5187 struct bgp_dest
*dest
, *ndest
;
5188 struct bgp_path_info
*pi
;
5189 struct bgp_table
*table
;
5191 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
5192 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5193 dest
= bgp_route_next(dest
)) {
5194 table
= bgp_dest_get_bgp_table_info(dest
);
5198 for (ndest
= bgp_table_top(table
); ndest
;
5199 ndest
= bgp_route_next(ndest
)) {
5200 for (pi
= bgp_dest_get_bgp_path_info(ndest
); pi
;
5202 if (pi
->peer
!= peer
)
5206 peer
->af_sflags
[afi
][safi
],
5207 PEER_STATUS_ENHANCED_REFRESH
))
5208 && !CHECK_FLAG(pi
->flags
,
5212 BGP_PATH_UNUSEABLE
)) {
5213 if (bgp_debug_neighbor_events(
5216 "%s: route-refresh for %s/%s, marking prefix %pFX as stale",
5220 bgp_dest_get_prefix(
5223 bgp_path_info_set_flag(
5231 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5232 dest
= bgp_route_next(dest
)) {
5233 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
5235 if (pi
->peer
!= peer
)
5238 if ((CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
5239 PEER_STATUS_ENHANCED_REFRESH
))
5240 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
5241 && !CHECK_FLAG(pi
->flags
,
5242 BGP_PATH_UNUSEABLE
)) {
5243 if (bgp_debug_neighbor_events(peer
))
5245 "%s: route-refresh for %s/%s, marking prefix %pFX as stale",
5249 bgp_dest_get_prefix(
5252 bgp_path_info_set_flag(dest
, pi
,
5260 bool bgp_outbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
5262 if (peer
->sort
== BGP_PEER_IBGP
)
5265 if (peer
->sort
== BGP_PEER_EBGP
5266 && (ROUTE_MAP_OUT_NAME(filter
) || PREFIX_LIST_OUT_NAME(filter
)
5267 || FILTER_LIST_OUT_NAME(filter
)
5268 || DISTRIBUTE_OUT_NAME(filter
)))
5273 bool bgp_inbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
5275 if (peer
->sort
== BGP_PEER_IBGP
)
5278 if (peer
->sort
== BGP_PEER_EBGP
5279 && (ROUTE_MAP_IN_NAME(filter
) || PREFIX_LIST_IN_NAME(filter
)
5280 || FILTER_LIST_IN_NAME(filter
)
5281 || DISTRIBUTE_IN_NAME(filter
)))
5286 static void bgp_cleanup_table(struct bgp
*bgp
, struct bgp_table
*table
,
5289 struct bgp_dest
*dest
;
5290 struct bgp_path_info
*pi
;
5291 struct bgp_path_info
*next
;
5293 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
))
5294 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= next
) {
5295 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
5299 /* Unimport EVPN routes from VRFs */
5300 if (safi
== SAFI_EVPN
)
5301 bgp_evpn_unimport_route(bgp
, AFI_L2VPN
,
5304 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)
5305 && pi
->type
== ZEBRA_ROUTE_BGP
5306 && (pi
->sub_type
== BGP_ROUTE_NORMAL
5307 || pi
->sub_type
== BGP_ROUTE_AGGREGATE
5308 || pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
5310 if (bgp_fibupd_safi(safi
))
5311 bgp_zebra_withdraw(p
, pi
, bgp
, safi
);
5314 bgp_path_info_reap(dest
, pi
);
5318 /* Delete all kernel routes. */
5319 void bgp_cleanup_routes(struct bgp
*bgp
)
5322 struct bgp_dest
*dest
;
5323 struct bgp_table
*table
;
5325 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
5326 if (afi
== AFI_L2VPN
)
5328 bgp_cleanup_table(bgp
, bgp
->rib
[afi
][SAFI_UNICAST
],
5331 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
5333 if (afi
!= AFI_L2VPN
) {
5335 safi
= SAFI_MPLS_VPN
;
5336 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); dest
;
5337 dest
= bgp_route_next(dest
)) {
5338 table
= bgp_dest_get_bgp_table_info(dest
);
5339 if (table
!= NULL
) {
5340 bgp_cleanup_table(bgp
, table
, safi
);
5341 bgp_table_finish(&table
);
5342 bgp_dest_set_bgp_table_info(dest
, NULL
);
5343 bgp_dest_unlock_node(dest
);
5347 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); dest
;
5348 dest
= bgp_route_next(dest
)) {
5349 table
= bgp_dest_get_bgp_table_info(dest
);
5350 if (table
!= NULL
) {
5351 bgp_cleanup_table(bgp
, table
, safi
);
5352 bgp_table_finish(&table
);
5353 bgp_dest_set_bgp_table_info(dest
, NULL
);
5354 bgp_dest_unlock_node(dest
);
5359 for (dest
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); dest
;
5360 dest
= bgp_route_next(dest
)) {
5361 table
= bgp_dest_get_bgp_table_info(dest
);
5362 if (table
!= NULL
) {
5363 bgp_cleanup_table(bgp
, table
, SAFI_EVPN
);
5364 bgp_table_finish(&table
);
5365 bgp_dest_set_bgp_table_info(dest
, NULL
);
5366 bgp_dest_unlock_node(dest
);
5371 void bgp_reset(void)
5374 bgp_zclient_reset();
5375 access_list_reset();
5376 prefix_list_reset();
5379 static int bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
5381 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
5382 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
5383 PEER_CAP_ADDPATH_AF_TX_RCV
));
5386 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
5388 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
5389 struct bgp_nlri
*packet
)
5398 int addpath_encoded
;
5399 uint32_t addpath_id
;
5402 lim
= pnt
+ packet
->length
;
5404 safi
= packet
->safi
;
5406 addpath_encoded
= bgp_addpath_encode_rx(peer
, afi
, safi
);
5408 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
5409 syntactic validity. If the field is syntactically incorrect,
5410 then the Error Subcode is set to Invalid Network Field. */
5411 for (; pnt
< lim
; pnt
+= psize
) {
5412 /* Clear prefix structure. */
5413 memset(&p
, 0, sizeof(struct prefix
));
5415 if (addpath_encoded
) {
5417 /* When packet overflow occurs return immediately. */
5418 if (pnt
+ BGP_ADDPATH_ID_LEN
>= lim
)
5419 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
5421 memcpy(&addpath_id
, pnt
, BGP_ADDPATH_ID_LEN
);
5422 addpath_id
= ntohl(addpath_id
);
5423 pnt
+= BGP_ADDPATH_ID_LEN
;
5426 /* Fetch prefix length. */
5427 p
.prefixlen
= *pnt
++;
5428 /* afi/safi validity already verified by caller,
5429 * bgp_update_receive */
5430 p
.family
= afi2family(afi
);
5432 /* Prefix length check. */
5433 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
5436 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
5437 peer
->host
, p
.prefixlen
, packet
->afi
);
5438 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH
;
5441 /* Packet size overflow check. */
5442 psize
= PSIZE(p
.prefixlen
);
5444 /* When packet overflow occur return immediately. */
5445 if (pnt
+ psize
> lim
) {
5448 "%s [Error] Update packet error (prefix length %d overflows packet)",
5449 peer
->host
, p
.prefixlen
);
5450 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
5453 /* Defensive coding, double-check the psize fits in a struct
5455 if (psize
> (ssize_t
)sizeof(p
.u
)) {
5458 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
5459 peer
->host
, p
.prefixlen
, sizeof(p
.u
));
5460 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
5463 /* Fetch prefix from NLRI packet. */
5464 memcpy(p
.u
.val
, pnt
, psize
);
5466 /* Check address. */
5467 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
5468 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
5469 /* From RFC4271 Section 6.3:
5471 * If a prefix in the NLRI field is semantically
5473 * (e.g., an unexpected multicast IP address),
5475 * be logged locally, and the prefix SHOULD be
5480 "%s: IPv4 unicast NLRI is multicast address %pI4, ignoring",
5481 peer
->host
, &p
.u
.prefix4
);
5486 /* Check address. */
5487 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
5488 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
5491 "%s: IPv6 unicast NLRI is link-local address %pI6, ignoring",
5492 peer
->host
, &p
.u
.prefix6
);
5496 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
5499 "%s: IPv6 unicast NLRI is multicast address %pI6, ignoring",
5500 peer
->host
, &p
.u
.prefix6
);
5506 /* Normal process. */
5508 ret
= bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
5509 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
5510 NULL
, NULL
, 0, 0, NULL
);
5512 ret
= bgp_withdraw(peer
, &p
, addpath_id
, attr
, afi
,
5513 safi
, ZEBRA_ROUTE_BGP
,
5514 BGP_ROUTE_NORMAL
, NULL
, NULL
, 0,
5517 /* Do not send BGP notification twice when maximum-prefix count
5519 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
))
5520 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW
;
5522 /* Address family configuration mismatch. */
5524 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY
;
5527 /* Packet length consistency check. */
5531 "%s [Error] Update packet error (prefix length mismatch with total length)",
5533 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
5536 return BGP_NLRI_PARSE_OK
;
5539 static struct bgp_static
*bgp_static_new(void)
5541 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
5544 static void bgp_static_free(struct bgp_static
*bgp_static
)
5546 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
5547 route_map_counter_decrement(bgp_static
->rmap
.map
);
5549 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
5550 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
5553 void bgp_static_update(struct bgp
*bgp
, const struct prefix
*p
,
5554 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
5556 struct bgp_dest
*dest
;
5557 struct bgp_path_info
*pi
;
5558 struct bgp_path_info
*new;
5559 struct bgp_path_info rmap_path
;
5561 struct attr
*attr_new
;
5562 route_map_result_t ret
;
5563 #ifdef ENABLE_BGP_VNC
5564 int vnc_implicit_withdraw
= 0;
5569 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
5571 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
5573 attr
.nexthop
= bgp_static
->igpnexthop
;
5574 attr
.med
= bgp_static
->igpmetric
;
5575 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
5577 if (bgp_static
->atomic
)
5578 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
5580 /* Store label index, if required. */
5581 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
5582 attr
.label_index
= bgp_static
->label_index
;
5583 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
5586 /* Apply route-map. */
5587 if (bgp_static
->rmap
.name
) {
5588 struct attr attr_tmp
= attr
;
5590 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
5591 rmap_path
.peer
= bgp
->peer_self
;
5592 rmap_path
.attr
= &attr_tmp
;
5594 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
5596 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, &rmap_path
);
5598 bgp
->peer_self
->rmap_type
= 0;
5600 if (ret
== RMAP_DENYMATCH
) {
5601 /* Free uninterned attribute. */
5602 bgp_attr_flush(&attr_tmp
);
5604 /* Unintern original. */
5605 aspath_unintern(&attr
.aspath
);
5606 bgp_static_withdraw(bgp
, p
, afi
, safi
);
5610 if (bgp_in_graceful_shutdown(bgp
))
5611 bgp_attr_add_gshut_community(&attr_tmp
);
5613 attr_new
= bgp_attr_intern(&attr_tmp
);
5616 if (bgp_in_graceful_shutdown(bgp
))
5617 bgp_attr_add_gshut_community(&attr
);
5619 attr_new
= bgp_attr_intern(&attr
);
5622 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
5623 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5624 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5628 if (attrhash_cmp(pi
->attr
, attr_new
)
5629 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
5630 && !CHECK_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
5631 bgp_dest_unlock_node(dest
);
5632 bgp_attr_unintern(&attr_new
);
5633 aspath_unintern(&attr
.aspath
);
5636 /* The attribute is changed. */
5637 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
5639 /* Rewrite BGP route information. */
5640 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
5641 bgp_path_info_restore(dest
, pi
);
5643 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
5644 #ifdef ENABLE_BGP_VNC
5645 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
5646 && (safi
== SAFI_UNICAST
)) {
5647 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
5649 * Implicit withdraw case.
5650 * We have to do this before pi is
5653 ++vnc_implicit_withdraw
;
5654 vnc_import_bgp_del_route(bgp
, p
, pi
);
5655 vnc_import_bgp_exterior_del_route(
5660 bgp_attr_unintern(&pi
->attr
);
5661 pi
->attr
= attr_new
;
5662 pi
->uptime
= bgp_clock();
5663 #ifdef ENABLE_BGP_VNC
5664 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
5665 && (safi
== SAFI_UNICAST
)) {
5666 if (vnc_implicit_withdraw
) {
5667 vnc_import_bgp_add_route(bgp
, p
, pi
);
5668 vnc_import_bgp_exterior_add_route(
5674 /* Nexthop reachability check. */
5675 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
)
5676 && (safi
== SAFI_UNICAST
5677 || safi
== SAFI_LABELED_UNICAST
)) {
5679 struct bgp
*bgp_nexthop
= bgp
;
5681 if (pi
->extra
&& pi
->extra
->bgp_orig
)
5682 bgp_nexthop
= pi
->extra
->bgp_orig
;
5684 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
,
5685 afi
, safi
, pi
, NULL
,
5687 bgp_path_info_set_flag(dest
, pi
,
5690 if (BGP_DEBUG(nht
, NHT
)) {
5691 char buf1
[INET6_ADDRSTRLEN
];
5692 inet_ntop(p
->family
,
5696 "%s(%s): Route not in table, not advertising",
5699 bgp_path_info_unset_flag(
5700 dest
, pi
, BGP_PATH_VALID
);
5703 /* Delete the NHT structure if any, if we're
5705 * enabling/disabling import check. We
5706 * deregister the route
5707 * from NHT to avoid overloading NHT and the
5708 * process interaction
5710 bgp_unlink_nexthop(pi
);
5711 bgp_path_info_set_flag(dest
, pi
,
5714 /* Process change. */
5715 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
5716 bgp_process(bgp
, dest
, afi
, safi
);
5718 if (SAFI_UNICAST
== safi
5719 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
5721 == BGP_INSTANCE_TYPE_DEFAULT
)) {
5722 vpn_leak_from_vrf_update(bgp_get_default(), bgp
,
5726 bgp_dest_unlock_node(dest
);
5727 aspath_unintern(&attr
.aspath
);
5732 /* Make new BGP info. */
5733 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
5735 /* Nexthop reachability check. */
5736 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
)
5737 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
5738 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, safi
, new, NULL
, 0))
5739 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
5741 if (BGP_DEBUG(nht
, NHT
)) {
5742 char buf1
[INET6_ADDRSTRLEN
];
5743 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
5746 "%s(%s): Route not in table, not advertising",
5749 bgp_path_info_unset_flag(dest
, new, BGP_PATH_VALID
);
5752 /* Delete the NHT structure if any, if we're toggling between
5753 * enabling/disabling import check. We deregister the route
5754 * from NHT to avoid overloading NHT and the process interaction
5756 bgp_unlink_nexthop(new);
5758 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
5761 /* Aggregate address increment. */
5762 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
5764 /* Register new BGP information. */
5765 bgp_path_info_add(dest
, new);
5767 /* route_node_get lock */
5768 bgp_dest_unlock_node(dest
);
5770 /* Process change. */
5771 bgp_process(bgp
, dest
, afi
, safi
);
5773 if (SAFI_UNICAST
== safi
5774 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
5775 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
5776 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
5779 /* Unintern original. */
5780 aspath_unintern(&attr
.aspath
);
5783 void bgp_static_withdraw(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
5786 struct bgp_dest
*dest
;
5787 struct bgp_path_info
*pi
;
5789 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
5791 /* Check selected route and self inserted route. */
5792 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
5793 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5794 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5797 /* Withdraw static BGP route from routing table. */
5799 if (SAFI_UNICAST
== safi
5800 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
5801 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
5802 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
5804 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
5805 bgp_unlink_nexthop(pi
);
5806 bgp_path_info_delete(dest
, pi
);
5807 bgp_process(bgp
, dest
, afi
, safi
);
5810 /* Unlock bgp_node_lookup. */
5811 bgp_dest_unlock_node(dest
);
5815 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
5817 static void bgp_static_withdraw_safi(struct bgp
*bgp
, const struct prefix
*p
,
5818 afi_t afi
, safi_t safi
,
5819 struct prefix_rd
*prd
)
5821 struct bgp_dest
*dest
;
5822 struct bgp_path_info
*pi
;
5824 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
5826 /* Check selected route and self inserted route. */
5827 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
5828 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5829 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5832 /* Withdraw static BGP route from routing table. */
5834 #ifdef ENABLE_BGP_VNC
5835 rfapiProcessWithdraw(
5836 pi
->peer
, NULL
, p
, prd
, pi
->attr
, afi
, safi
, pi
->type
,
5837 1); /* Kill, since it is an administrative change */
5839 if (SAFI_MPLS_VPN
== safi
5840 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5841 vpn_leak_to_vrf_withdraw(bgp
, pi
);
5843 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
5844 bgp_path_info_delete(dest
, pi
);
5845 bgp_process(bgp
, dest
, afi
, safi
);
5848 /* Unlock bgp_node_lookup. */
5849 bgp_dest_unlock_node(dest
);
5852 static void bgp_static_update_safi(struct bgp
*bgp
, const struct prefix
*p
,
5853 struct bgp_static
*bgp_static
, afi_t afi
,
5856 struct bgp_dest
*dest
;
5857 struct bgp_path_info
*new;
5858 struct attr
*attr_new
;
5859 struct attr attr
= {0};
5860 struct bgp_path_info
*pi
;
5861 #ifdef ENABLE_BGP_VNC
5862 mpls_label_t label
= 0;
5864 uint32_t num_labels
= 0;
5869 if (bgp_static
->label
!= MPLS_INVALID_LABEL
)
5871 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
5874 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
5876 attr
.nexthop
= bgp_static
->igpnexthop
;
5877 attr
.med
= bgp_static
->igpmetric
;
5878 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
5880 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
5881 || (safi
== SAFI_ENCAP
)) {
5882 if (afi
== AFI_IP
) {
5883 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
5884 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
5887 if (afi
== AFI_L2VPN
) {
5888 if (bgp_static
->gatewayIp
.family
== AF_INET
)
5890 bgp_static
->gatewayIp
.u
.prefix4
.s_addr
;
5891 else if (bgp_static
->gatewayIp
.family
== AF_INET6
)
5892 memcpy(&(add
.ipv6
), &(bgp_static
->gatewayIp
.u
.prefix6
),
5893 sizeof(struct in6_addr
));
5894 memcpy(&attr
.esi
, bgp_static
->eth_s_id
, sizeof(esi_t
));
5895 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
5896 struct bgp_encap_type_vxlan bet
;
5897 memset(&bet
, 0, sizeof(struct bgp_encap_type_vxlan
));
5898 bet
.vnid
= p
->u
.prefix_evpn
.prefix_addr
.eth_tag
;
5899 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
5901 if (bgp_static
->router_mac
) {
5902 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
5905 /* Apply route-map. */
5906 if (bgp_static
->rmap
.name
) {
5907 struct attr attr_tmp
= attr
;
5908 struct bgp_path_info rmap_path
;
5909 route_map_result_t ret
;
5911 rmap_path
.peer
= bgp
->peer_self
;
5912 rmap_path
.attr
= &attr_tmp
;
5914 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
5916 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, &rmap_path
);
5918 bgp
->peer_self
->rmap_type
= 0;
5920 if (ret
== RMAP_DENYMATCH
) {
5921 /* Free uninterned attribute. */
5922 bgp_attr_flush(&attr_tmp
);
5924 /* Unintern original. */
5925 aspath_unintern(&attr
.aspath
);
5926 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
5931 attr_new
= bgp_attr_intern(&attr_tmp
);
5933 attr_new
= bgp_attr_intern(&attr
);
5936 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
5937 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5938 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5942 memset(&add
, 0, sizeof(union gw_addr
));
5943 if (attrhash_cmp(pi
->attr
, attr_new
)
5944 && overlay_index_equal(afi
, pi
, &add
)
5945 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
5946 bgp_dest_unlock_node(dest
);
5947 bgp_attr_unintern(&attr_new
);
5948 aspath_unintern(&attr
.aspath
);
5951 /* The attribute is changed. */
5952 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
5954 /* Rewrite BGP route information. */
5955 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
5956 bgp_path_info_restore(dest
, pi
);
5958 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
5959 bgp_attr_unintern(&pi
->attr
);
5960 pi
->attr
= attr_new
;
5961 pi
->uptime
= bgp_clock();
5962 #ifdef ENABLE_BGP_VNC
5964 label
= decode_label(&pi
->extra
->label
[0]);
5967 /* Process change. */
5968 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
5969 bgp_process(bgp
, dest
, afi
, safi
);
5971 if (SAFI_MPLS_VPN
== safi
5972 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5973 vpn_leak_to_vrf_update(bgp
, pi
);
5975 #ifdef ENABLE_BGP_VNC
5976 rfapiProcessUpdate(pi
->peer
, NULL
, p
, &bgp_static
->prd
,
5977 pi
->attr
, afi
, safi
, pi
->type
,
5978 pi
->sub_type
, &label
);
5980 bgp_dest_unlock_node(dest
);
5981 aspath_unintern(&attr
.aspath
);
5987 /* Make new BGP info. */
5988 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
5990 SET_FLAG(new->flags
, BGP_PATH_VALID
);
5991 new->extra
= bgp_path_info_extra_new();
5993 new->extra
->label
[0] = bgp_static
->label
;
5994 new->extra
->num_labels
= num_labels
;
5996 #ifdef ENABLE_BGP_VNC
5997 label
= decode_label(&bgp_static
->label
);
6000 /* Aggregate address increment. */
6001 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
6003 /* Register new BGP information. */
6004 bgp_path_info_add(dest
, new);
6005 /* route_node_get lock */
6006 bgp_dest_unlock_node(dest
);
6008 /* Process change. */
6009 bgp_process(bgp
, dest
, afi
, safi
);
6011 if (SAFI_MPLS_VPN
== safi
6012 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
6013 vpn_leak_to_vrf_update(bgp
, new);
6015 #ifdef ENABLE_BGP_VNC
6016 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
6017 safi
, new->type
, new->sub_type
, &label
);
6020 /* Unintern original. */
6021 aspath_unintern(&attr
.aspath
);
6024 /* Configure static BGP network. When user don't run zebra, static
6025 route should be installed as valid. */
6026 int bgp_static_set(struct bgp
*bgp
, const char *negate
, struct prefix
*pfx
,
6027 afi_t afi
, safi_t safi
, const char *rmap
, int backdoor
,
6028 uint32_t label_index
, char *errmsg
, size_t errmsg_len
)
6031 struct bgp_static
*bgp_static
;
6032 struct bgp_dest
*dest
;
6033 uint8_t need_update
= 0;
6035 prefix_copy(&p
, pfx
);
6040 /* Set BGP static route configuration. */
6041 dest
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
6044 snprintf(errmsg
, errmsg_len
,
6045 "Can't find static route specified\n");
6049 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6051 if ((label_index
!= BGP_INVALID_LABEL_INDEX
)
6052 && (label_index
!= bgp_static
->label_index
)) {
6053 snprintf(errmsg
, errmsg_len
,
6054 "label-index doesn't match static route\n");
6058 if ((rmap
&& bgp_static
->rmap
.name
)
6059 && strcmp(rmap
, bgp_static
->rmap
.name
)) {
6060 snprintf(errmsg
, errmsg_len
,
6061 "route-map name doesn't match static route\n");
6065 /* Update BGP RIB. */
6066 if (!bgp_static
->backdoor
)
6067 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
6069 /* Clear configuration. */
6070 bgp_static_free(bgp_static
);
6071 bgp_dest_set_bgp_static_info(dest
, NULL
);
6072 bgp_dest_unlock_node(dest
);
6073 bgp_dest_unlock_node(dest
);
6076 /* Set BGP static route configuration. */
6077 dest
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
6078 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6080 /* Configuration change. */
6081 /* Label index cannot be changed. */
6082 if (bgp_static
->label_index
!= label_index
) {
6083 snprintf(errmsg
, errmsg_len
,
6084 "cannot change label-index\n");
6088 /* Check previous routes are installed into BGP. */
6089 if (bgp_static
->valid
6090 && bgp_static
->backdoor
!= backdoor
)
6093 bgp_static
->backdoor
= backdoor
;
6096 XFREE(MTYPE_ROUTE_MAP_NAME
,
6097 bgp_static
->rmap
.name
);
6098 route_map_counter_decrement(
6099 bgp_static
->rmap
.map
);
6100 bgp_static
->rmap
.name
=
6101 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
6102 bgp_static
->rmap
.map
=
6103 route_map_lookup_by_name(rmap
);
6104 route_map_counter_increment(
6105 bgp_static
->rmap
.map
);
6107 XFREE(MTYPE_ROUTE_MAP_NAME
,
6108 bgp_static
->rmap
.name
);
6109 route_map_counter_decrement(
6110 bgp_static
->rmap
.map
);
6111 bgp_static
->rmap
.map
= NULL
;
6112 bgp_static
->valid
= 0;
6114 bgp_dest_unlock_node(dest
);
6116 /* New configuration. */
6117 bgp_static
= bgp_static_new();
6118 bgp_static
->backdoor
= backdoor
;
6119 bgp_static
->valid
= 0;
6120 bgp_static
->igpmetric
= 0;
6121 bgp_static
->igpnexthop
.s_addr
= INADDR_ANY
;
6122 bgp_static
->label_index
= label_index
;
6125 XFREE(MTYPE_ROUTE_MAP_NAME
,
6126 bgp_static
->rmap
.name
);
6127 route_map_counter_decrement(
6128 bgp_static
->rmap
.map
);
6129 bgp_static
->rmap
.name
=
6130 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
6131 bgp_static
->rmap
.map
=
6132 route_map_lookup_by_name(rmap
);
6133 route_map_counter_increment(
6134 bgp_static
->rmap
.map
);
6136 bgp_dest_set_bgp_static_info(dest
, bgp_static
);
6139 bgp_static
->valid
= 1;
6141 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
6143 if (!bgp_static
->backdoor
)
6144 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
6150 void bgp_static_add(struct bgp
*bgp
)
6154 struct bgp_dest
*dest
;
6155 struct bgp_dest
*rm
;
6156 struct bgp_table
*table
;
6157 struct bgp_static
*bgp_static
;
6159 SET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6160 FOREACH_AFI_SAFI (afi
, safi
)
6161 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
6162 dest
= bgp_route_next(dest
)) {
6163 if (!bgp_dest_has_bgp_path_info_data(dest
))
6166 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
6167 || (safi
== SAFI_EVPN
)) {
6168 table
= bgp_dest_get_bgp_table_info(dest
);
6170 for (rm
= bgp_table_top(table
); rm
;
6171 rm
= bgp_route_next(rm
)) {
6173 bgp_dest_get_bgp_static_info(
6175 bgp_static_update_safi(
6176 bgp
, bgp_dest_get_prefix(rm
),
6177 bgp_static
, afi
, safi
);
6181 bgp
, bgp_dest_get_prefix(dest
),
6182 bgp_dest_get_bgp_static_info(dest
), afi
,
6186 UNSET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6189 /* Called from bgp_delete(). Delete all static routes from the BGP
6191 void bgp_static_delete(struct bgp
*bgp
)
6195 struct bgp_dest
*dest
;
6196 struct bgp_dest
*rm
;
6197 struct bgp_table
*table
;
6198 struct bgp_static
*bgp_static
;
6200 FOREACH_AFI_SAFI (afi
, safi
)
6201 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
6202 dest
= bgp_route_next(dest
)) {
6203 if (!bgp_dest_has_bgp_path_info_data(dest
))
6206 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
6207 || (safi
== SAFI_EVPN
)) {
6208 table
= bgp_dest_get_bgp_table_info(dest
);
6210 for (rm
= bgp_table_top(table
); rm
;
6211 rm
= bgp_route_next(rm
)) {
6213 bgp_dest_get_bgp_static_info(
6218 bgp_static_withdraw_safi(
6219 bgp
, bgp_dest_get_prefix(rm
),
6221 (struct prefix_rd
*)
6222 bgp_dest_get_prefix(
6224 bgp_static_free(bgp_static
);
6225 bgp_dest_set_bgp_static_info(rm
,
6227 bgp_dest_unlock_node(rm
);
6230 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6231 bgp_static_withdraw(bgp
,
6232 bgp_dest_get_prefix(dest
),
6234 bgp_static_free(bgp_static
);
6235 bgp_dest_set_bgp_static_info(dest
, NULL
);
6236 bgp_dest_unlock_node(dest
);
6241 void bgp_static_redo_import_check(struct bgp
*bgp
)
6245 struct bgp_dest
*dest
;
6246 struct bgp_dest
*rm
;
6247 struct bgp_table
*table
;
6248 struct bgp_static
*bgp_static
;
6250 /* Use this flag to force reprocessing of the route */
6251 SET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6252 FOREACH_AFI_SAFI (afi
, safi
) {
6253 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
6254 dest
= bgp_route_next(dest
)) {
6255 if (!bgp_dest_has_bgp_path_info_data(dest
))
6258 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
6259 || (safi
== SAFI_EVPN
)) {
6260 table
= bgp_dest_get_bgp_table_info(dest
);
6262 for (rm
= bgp_table_top(table
); rm
;
6263 rm
= bgp_route_next(rm
)) {
6265 bgp_dest_get_bgp_static_info(
6267 bgp_static_update_safi(
6268 bgp
, bgp_dest_get_prefix(rm
),
6269 bgp_static
, afi
, safi
);
6272 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6273 bgp_static_update(bgp
,
6274 bgp_dest_get_prefix(dest
),
6275 bgp_static
, afi
, safi
);
6279 UNSET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6282 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
6285 struct bgp_table
*table
;
6286 struct bgp_dest
*dest
;
6287 struct bgp_path_info
*pi
;
6289 /* Do not install the aggregate route if BGP is in the
6290 * process of termination.
6292 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
6293 || (bgp
->peer_self
== NULL
))
6296 table
= bgp
->rib
[afi
][safi
];
6297 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
6298 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
6299 if (pi
->peer
== bgp
->peer_self
6300 && ((pi
->type
== ZEBRA_ROUTE_BGP
6301 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6302 || (pi
->type
!= ZEBRA_ROUTE_BGP
6304 == BGP_ROUTE_REDISTRIBUTE
))) {
6305 bgp_aggregate_decrement(
6306 bgp
, bgp_dest_get_prefix(dest
), pi
, afi
,
6308 bgp_unlink_nexthop(pi
);
6309 bgp_path_info_delete(dest
, pi
);
6310 bgp_process(bgp
, dest
, afi
, safi
);
6317 * Purge all networks and redistributed routes from routing table.
6318 * Invoked upon the instance going down.
6320 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
6325 FOREACH_AFI_SAFI (afi
, safi
)
6326 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
6331 * Currently this is used to set static routes for VPN and ENCAP.
6332 * I think it can probably be factored with bgp_static_set.
6334 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
6335 const char *ip_str
, const char *rd_str
,
6336 const char *label_str
, const char *rmap_str
,
6337 int evpn_type
, const char *esi
, const char *gwip
,
6338 const char *ethtag
, const char *routermac
)
6340 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6343 struct prefix_rd prd
;
6344 struct bgp_dest
*pdest
;
6345 struct bgp_dest
*dest
;
6346 struct bgp_table
*table
;
6347 struct bgp_static
*bgp_static
;
6348 mpls_label_t label
= MPLS_INVALID_LABEL
;
6349 struct prefix gw_ip
;
6351 /* validate ip prefix */
6352 ret
= str2prefix(ip_str
, &p
);
6354 vty_out(vty
, "%% Malformed prefix\n");
6355 return CMD_WARNING_CONFIG_FAILED
;
6358 if ((afi
== AFI_L2VPN
)
6359 && (bgp_build_evpn_prefix(evpn_type
,
6360 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
6361 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
6362 return CMD_WARNING_CONFIG_FAILED
;
6365 ret
= str2prefix_rd(rd_str
, &prd
);
6367 vty_out(vty
, "%% Malformed rd\n");
6368 return CMD_WARNING_CONFIG_FAILED
;
6372 unsigned long label_val
;
6373 label_val
= strtoul(label_str
, NULL
, 10);
6374 encode_label(label_val
, &label
);
6377 if (safi
== SAFI_EVPN
) {
6378 if (esi
&& str2esi(esi
, NULL
) == 0) {
6379 vty_out(vty
, "%% Malformed ESI\n");
6380 return CMD_WARNING_CONFIG_FAILED
;
6382 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
6383 vty_out(vty
, "%% Malformed Router MAC\n");
6384 return CMD_WARNING_CONFIG_FAILED
;
6387 memset(&gw_ip
, 0, sizeof(struct prefix
));
6388 ret
= str2prefix(gwip
, &gw_ip
);
6390 vty_out(vty
, "%% Malformed GatewayIp\n");
6391 return CMD_WARNING_CONFIG_FAILED
;
6393 if ((gw_ip
.family
== AF_INET
6394 && is_evpn_prefix_ipaddr_v6(
6395 (struct prefix_evpn
*)&p
))
6396 || (gw_ip
.family
== AF_INET6
6397 && is_evpn_prefix_ipaddr_v4(
6398 (struct prefix_evpn
*)&p
))) {
6400 "%% GatewayIp family differs with IP prefix\n");
6401 return CMD_WARNING_CONFIG_FAILED
;
6405 pdest
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
6406 if (!bgp_dest_has_bgp_path_info_data(pdest
))
6407 bgp_dest_set_bgp_table_info(pdest
,
6408 bgp_table_init(bgp
, afi
, safi
));
6409 table
= bgp_dest_get_bgp_table_info(pdest
);
6411 dest
= bgp_node_get(table
, &p
);
6413 if (bgp_dest_has_bgp_path_info_data(dest
)) {
6414 vty_out(vty
, "%% Same network configuration exists\n");
6415 bgp_dest_unlock_node(dest
);
6417 /* New configuration. */
6418 bgp_static
= bgp_static_new();
6419 bgp_static
->backdoor
= 0;
6420 bgp_static
->valid
= 0;
6421 bgp_static
->igpmetric
= 0;
6422 bgp_static
->igpnexthop
.s_addr
= INADDR_ANY
;
6423 bgp_static
->label
= label
;
6424 bgp_static
->prd
= prd
;
6427 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
6428 route_map_counter_decrement(bgp_static
->rmap
.map
);
6429 bgp_static
->rmap
.name
=
6430 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
6431 bgp_static
->rmap
.map
=
6432 route_map_lookup_by_name(rmap_str
);
6433 route_map_counter_increment(bgp_static
->rmap
.map
);
6436 if (safi
== SAFI_EVPN
) {
6438 bgp_static
->eth_s_id
=
6441 str2esi(esi
, bgp_static
->eth_s_id
);
6444 bgp_static
->router_mac
=
6445 XCALLOC(MTYPE_ATTR
, ETH_ALEN
+ 1);
6446 (void)prefix_str2mac(routermac
,
6447 bgp_static
->router_mac
);
6450 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
6452 bgp_dest_set_bgp_static_info(dest
, bgp_static
);
6454 bgp_static
->valid
= 1;
6455 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
6461 /* Configure static BGP network. */
6462 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
6463 const char *ip_str
, const char *rd_str
,
6464 const char *label_str
, int evpn_type
, const char *esi
,
6465 const char *gwip
, const char *ethtag
)
6467 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6470 struct prefix_rd prd
;
6471 struct bgp_dest
*pdest
;
6472 struct bgp_dest
*dest
;
6473 struct bgp_table
*table
;
6474 struct bgp_static
*bgp_static
;
6475 mpls_label_t label
= MPLS_INVALID_LABEL
;
6477 /* Convert IP prefix string to struct prefix. */
6478 ret
= str2prefix(ip_str
, &p
);
6480 vty_out(vty
, "%% Malformed prefix\n");
6481 return CMD_WARNING_CONFIG_FAILED
;
6484 if ((afi
== AFI_L2VPN
)
6485 && (bgp_build_evpn_prefix(evpn_type
,
6486 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
6487 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
6488 return CMD_WARNING_CONFIG_FAILED
;
6490 ret
= str2prefix_rd(rd_str
, &prd
);
6492 vty_out(vty
, "%% Malformed rd\n");
6493 return CMD_WARNING_CONFIG_FAILED
;
6497 unsigned long label_val
;
6498 label_val
= strtoul(label_str
, NULL
, 10);
6499 encode_label(label_val
, &label
);
6502 pdest
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
6503 if (!bgp_dest_has_bgp_path_info_data(pdest
))
6504 bgp_dest_set_bgp_table_info(pdest
,
6505 bgp_table_init(bgp
, afi
, safi
));
6507 bgp_dest_unlock_node(pdest
);
6508 table
= bgp_dest_get_bgp_table_info(pdest
);
6510 dest
= bgp_node_lookup(table
, &p
);
6513 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
6515 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6516 bgp_static_free(bgp_static
);
6517 bgp_dest_set_bgp_static_info(dest
, NULL
);
6518 bgp_dest_unlock_node(dest
);
6519 bgp_dest_unlock_node(dest
);
6521 vty_out(vty
, "%% Can't find the route\n");
6526 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
6527 const char *rmap_name
)
6529 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6530 struct bgp_rmap
*rmap
;
6532 rmap
= &bgp
->table_map
[afi
][safi
];
6534 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
6535 route_map_counter_decrement(rmap
->map
);
6536 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
6537 rmap
->map
= route_map_lookup_by_name(rmap_name
);
6538 route_map_counter_increment(rmap
->map
);
6540 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
6541 route_map_counter_decrement(rmap
->map
);
6545 if (bgp_fibupd_safi(safi
))
6546 bgp_zebra_announce_table(bgp
, afi
, safi
);
6551 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
6552 const char *rmap_name
)
6554 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6555 struct bgp_rmap
*rmap
;
6557 rmap
= &bgp
->table_map
[afi
][safi
];
6558 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
6559 route_map_counter_decrement(rmap
->map
);
6562 if (bgp_fibupd_safi(safi
))
6563 bgp_zebra_announce_table(bgp
, afi
, safi
);
6568 void bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
6571 if (bgp
->table_map
[afi
][safi
].name
) {
6572 vty_out(vty
, " table-map %s\n",
6573 bgp
->table_map
[afi
][safi
].name
);
6577 DEFUN (bgp_table_map
,
6580 "BGP table to RIB route download filter\n"
6581 "Name of the route map\n")
6584 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
6585 argv
[idx_word
]->arg
);
6587 DEFUN (no_bgp_table_map
,
6588 no_bgp_table_map_cmd
,
6589 "no table-map WORD",
6591 "BGP table to RIB route download filter\n"
6592 "Name of the route map\n")
6595 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
6596 argv
[idx_word
]->arg
);
6599 DEFPY_YANG (bgp_network
, bgp_network_cmd
,
6601 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
6602 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
6603 backdoor$backdoor}]",
6605 "Specify a network to announce via BGP\n"
6610 "Route-map to modify the attributes\n"
6611 "Name of the route map\n"
6612 "Label index to associate with the prefix\n"
6613 "Label index value\n"
6614 "Specify a BGP backdoor route\n")
6616 char addr_prefix_str
[PREFIX_STRLEN
];
6617 char base_xpath
[XPATH_MAXLEN
];
6624 ret
= netmask_str2prefix_str(address_str
, netmask_str
,
6626 sizeof(addr_prefix_str
));
6628 vty_out(vty
, "%% Inconsistent address and mask\n");
6629 return CMD_WARNING_CONFIG_FAILED
;
6633 afi
= bgp_node_afi(vty
);
6634 safi
= bgp_node_safi(vty
);
6637 nb_cli_enqueue_change(vty
, ".", NB_OP_DESTROY
, NULL
);
6639 nb_cli_enqueue_change(vty
, ".", NB_OP_CREATE
, NULL
);
6642 nb_cli_enqueue_change(vty
, "./rmap-policy-export",
6643 NB_OP_CREATE
, map_name
);
6645 nb_cli_enqueue_change(vty
, "./rmap-policy-export",
6646 NB_OP_DESTROY
, NULL
);
6648 if (label_index_str
)
6649 nb_cli_enqueue_change(vty
, "./label-index",
6650 NB_OP_MODIFY
, label_index_str
);
6652 nb_cli_enqueue_change(vty
, "./backdoor", NB_OP_MODIFY
,
6653 backdoor
? "true" : "false");
6657 base_xpath
, sizeof(base_xpath
),
6658 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/network-config[prefix='%s']",
6659 yang_afi_safi_value2identity(afi
, safi
),
6660 bgp_afi_safi_get_container_str(afi
, safi
),
6661 address_str
? addr_prefix_str
: prefix_str
);
6663 return nb_cli_apply_changes(vty
, base_xpath
);
6666 DEFPY_YANG (ipv6_bgp_network
,
6667 ipv6_bgp_network_cmd
,
6668 "[no] network X:X::X:X/M$prefix \
6669 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
6671 "Specify a network to announce via BGP\n"
6673 "Route-map to modify the attributes\n"
6674 "Name of the route map\n"
6675 "Label index to associate with the prefix\n"
6676 "Label index value\n")
6678 char base_xpath
[XPATH_MAXLEN
];
6682 afi
= bgp_node_afi(vty
);
6683 safi
= bgp_node_safi(vty
);
6686 nb_cli_enqueue_change(vty
, ".", NB_OP_DESTROY
, NULL
);
6688 nb_cli_enqueue_change(vty
, ".", NB_OP_CREATE
, NULL
);
6691 nb_cli_enqueue_change(vty
, "./rmap-policy-export",
6692 NB_OP_MODIFY
, map_name
);
6694 nb_cli_enqueue_change(vty
, "./rmap-policy-export",
6695 NB_OP_DESTROY
, NULL
);
6697 if (label_index_str
)
6698 nb_cli_enqueue_change(vty
, "./label-index",
6699 NB_OP_MODIFY
, label_index_str
);
6703 base_xpath
, sizeof(base_xpath
),
6704 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/network-config[prefix='%s']",
6705 yang_afi_safi_value2identity(afi
, safi
),
6706 bgp_afi_safi_get_container_str(afi
, safi
), prefix_str
);
6708 return nb_cli_apply_changes(vty
, base_xpath
);
6711 void cli_show_bgp_global_afi_safi_network_config(struct vty
*vty
,
6712 struct lyd_node
*dnode
,
6715 vty_out(vty
, " network %s", yang_dnode_get_string(dnode
, "./prefix"));
6717 if (yang_dnode_exists(dnode
, "./label-index"))
6718 vty_out(vty
, " label-index %s",
6719 yang_dnode_get_string(dnode
, "./label-index"));
6721 if (yang_dnode_exists(dnode
, "./rmap-policy-export"))
6722 vty_out(vty
, " route-map %s",
6723 yang_dnode_get_string(dnode
, "./rmap-policy-export"));
6725 if (yang_dnode_get_bool(dnode
, "./backdoor"))
6726 vty_out(vty
, " backdoor");
6731 static struct bgp_aggregate
*bgp_aggregate_new(void)
6733 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
6736 static void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
6738 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->suppress_map_name
);
6739 route_map_counter_decrement(aggregate
->suppress_map
);
6740 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
6741 route_map_counter_decrement(aggregate
->rmap
.map
);
6742 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
6746 * Helper function to avoid repeated code: prepare variables for a
6747 * `route_map_apply` call.
6749 * \returns `true` on route map match, otherwise `false`.
6751 static bool aggr_suppress_map_test(struct bgp
*bgp
,
6752 struct bgp_aggregate
*aggregate
,
6753 struct bgp_path_info
*pi
)
6755 const struct prefix
*p
= bgp_dest_get_prefix(pi
->net
);
6756 route_map_result_t rmr
= RMAP_DENYMATCH
;
6757 struct bgp_path_info rmap_path
= {};
6758 struct attr attr
= {};
6760 /* No route map entries created, just don't match. */
6761 if (aggregate
->suppress_map
== NULL
)
6764 /* Call route map matching and return result. */
6765 attr
.aspath
= aspath_empty();
6766 rmap_path
.peer
= bgp
->peer_self
;
6767 rmap_path
.attr
= &attr
;
6769 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_AGGREGATE
);
6770 rmr
= route_map_apply(aggregate
->suppress_map
, p
, &rmap_path
);
6771 bgp
->peer_self
->rmap_type
= 0;
6773 bgp_attr_flush(&attr
);
6775 return rmr
== RMAP_PERMITMATCH
;
6778 /** Test whether the aggregation has suppressed this path or not. */
6779 static bool aggr_suppress_exists(struct bgp_aggregate
*aggregate
,
6780 struct bgp_path_info
*pi
)
6782 if (pi
->extra
== NULL
|| pi
->extra
->aggr_suppressors
== NULL
)
6785 return listnode_lookup(pi
->extra
->aggr_suppressors
, aggregate
) != NULL
;
6789 * Suppress this path and keep the reference.
6791 * \returns `true` if needs processing otherwise `false`.
6793 static bool aggr_suppress_path(struct bgp_aggregate
*aggregate
,
6794 struct bgp_path_info
*pi
)
6796 struct bgp_path_info_extra
*pie
;
6798 /* Path is already suppressed by this aggregation. */
6799 if (aggr_suppress_exists(aggregate
, pi
))
6802 pie
= bgp_path_info_extra_get(pi
);
6804 /* This is the first suppression, allocate memory and list it. */
6805 if (pie
->aggr_suppressors
== NULL
)
6806 pie
->aggr_suppressors
= list_new();
6808 listnode_add(pie
->aggr_suppressors
, aggregate
);
6810 /* Only mark for processing if suppressed. */
6811 if (listcount(pie
->aggr_suppressors
) == 1) {
6812 if (BGP_DEBUG(update
, UPDATE_OUT
))
6813 zlog_debug("aggregate-address suppressing: %pFX",
6814 bgp_dest_get_prefix(pi
->net
));
6816 bgp_path_info_set_flag(pi
->net
, pi
, BGP_PATH_ATTR_CHANGED
);
6824 * Unsuppress this path and remove the reference.
6826 * \returns `true` if needs processing otherwise `false`.
6828 static bool aggr_unsuppress_path(struct bgp_aggregate
*aggregate
,
6829 struct bgp_path_info
*pi
)
6831 /* Path wasn't suppressed. */
6832 if (!aggr_suppress_exists(aggregate
, pi
))
6835 listnode_delete(pi
->extra
->aggr_suppressors
, aggregate
);
6837 /* Unsuppress and free extra memory if last item. */
6838 if (listcount(pi
->extra
->aggr_suppressors
) == 0) {
6839 if (BGP_DEBUG(update
, UPDATE_OUT
))
6840 zlog_debug("aggregate-address unsuppressing: %pFX",
6841 bgp_dest_get_prefix(pi
->net
));
6843 list_delete(&pi
->extra
->aggr_suppressors
);
6844 bgp_path_info_set_flag(pi
->net
, pi
, BGP_PATH_ATTR_CHANGED
);
6851 static bool bgp_aggregate_info_same(struct bgp_path_info
*pi
, uint8_t origin
,
6852 struct aspath
*aspath
,
6853 struct community
*comm
,
6854 struct ecommunity
*ecomm
,
6855 struct lcommunity
*lcomm
)
6857 static struct aspath
*ae
= NULL
;
6860 ae
= aspath_empty();
6865 if (origin
!= pi
->attr
->origin
)
6868 if (!aspath_cmp(pi
->attr
->aspath
, (aspath
) ? aspath
: ae
))
6871 if (!community_cmp(pi
->attr
->community
, comm
))
6874 if (!ecommunity_cmp(pi
->attr
->ecommunity
, ecomm
))
6877 if (!lcommunity_cmp(pi
->attr
->lcommunity
, lcomm
))
6880 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
6886 static void bgp_aggregate_install(
6887 struct bgp
*bgp
, afi_t afi
, safi_t safi
, const struct prefix
*p
,
6888 uint8_t origin
, struct aspath
*aspath
, struct community
*community
,
6889 struct ecommunity
*ecommunity
, struct lcommunity
*lcommunity
,
6890 uint8_t atomic_aggregate
, struct bgp_aggregate
*aggregate
)
6892 struct bgp_dest
*dest
;
6893 struct bgp_table
*table
;
6894 struct bgp_path_info
*pi
, *orig
, *new;
6897 table
= bgp
->rib
[afi
][safi
];
6899 dest
= bgp_node_get(table
, p
);
6901 for (orig
= pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6902 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6903 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6907 * If we have paths with different MEDs, then don't install
6908 * (or uninstall) the aggregate route.
6910 if (aggregate
->match_med
&& aggregate
->med_mismatched
)
6911 goto uninstall_aggregate_route
;
6913 if (aggregate
->count
> 0) {
6915 * If the aggregate information has not changed
6916 * no need to re-install it again.
6918 if (bgp_aggregate_info_same(orig
, origin
, aspath
, community
,
6919 ecommunity
, lcommunity
)) {
6920 bgp_dest_unlock_node(dest
);
6923 aspath_free(aspath
);
6925 community_free(&community
);
6927 ecommunity_free(&ecommunity
);
6929 lcommunity_free(&lcommunity
);
6935 * Mark the old as unusable
6938 bgp_path_info_delete(dest
, pi
);
6940 attr
= bgp_attr_aggregate_intern(
6941 bgp
, origin
, aspath
, community
, ecommunity
, lcommunity
,
6942 aggregate
, atomic_aggregate
, p
);
6945 bgp_aggregate_delete(bgp
, p
, afi
, safi
, aggregate
);
6946 if (BGP_DEBUG(update_groups
, UPDATE_GROUPS
))
6947 zlog_debug("%s: %pFX null attribute", __func__
,
6952 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0,
6953 bgp
->peer_self
, attr
, dest
);
6955 SET_FLAG(new->flags
, BGP_PATH_VALID
);
6957 bgp_path_info_add(dest
, new);
6958 bgp_process(bgp
, dest
, afi
, safi
);
6960 uninstall_aggregate_route
:
6961 for (pi
= orig
; pi
; pi
= pi
->next
)
6962 if (pi
->peer
== bgp
->peer_self
6963 && pi
->type
== ZEBRA_ROUTE_BGP
6964 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6967 /* Withdraw static BGP route from routing table. */
6969 bgp_path_info_delete(dest
, pi
);
6970 bgp_process(bgp
, dest
, afi
, safi
);
6974 bgp_dest_unlock_node(dest
);
6978 * Check if the current path has different MED than other known paths.
6980 * \returns `true` if the MED matched the others else `false`.
6982 static bool bgp_aggregate_med_match(struct bgp_aggregate
*aggregate
,
6983 struct bgp
*bgp
, struct bgp_path_info
*pi
)
6985 uint32_t cur_med
= bgp_med_value(pi
->attr
, bgp
);
6987 /* This is the first route being analyzed. */
6988 if (!aggregate
->med_initialized
) {
6989 aggregate
->med_initialized
= true;
6990 aggregate
->med_mismatched
= false;
6991 aggregate
->med_matched_value
= cur_med
;
6993 /* Check if routes with different MED showed up. */
6994 if (cur_med
!= aggregate
->med_matched_value
)
6995 aggregate
->med_mismatched
= true;
6998 return !aggregate
->med_mismatched
;
7002 * Initializes and tests all routes in the aggregate address path for MED
7005 * \returns `true` if all MEDs are the same otherwise `false`.
7007 static bool bgp_aggregate_test_all_med(struct bgp_aggregate
*aggregate
,
7008 struct bgp
*bgp
, const struct prefix
*p
,
7009 afi_t afi
, safi_t safi
)
7011 struct bgp_table
*table
= bgp
->rib
[afi
][safi
];
7012 const struct prefix
*dest_p
;
7013 struct bgp_dest
*dest
, *top
;
7014 struct bgp_path_info
*pi
;
7015 bool med_matched
= true;
7017 aggregate
->med_initialized
= false;
7019 top
= bgp_node_get(table
, p
);
7020 for (dest
= bgp_node_get(table
, p
); dest
;
7021 dest
= bgp_route_next_until(dest
, top
)) {
7022 dest_p
= bgp_dest_get_prefix(dest
);
7023 if (dest_p
->prefixlen
<= p
->prefixlen
)
7026 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7027 if (BGP_PATH_HOLDDOWN(pi
))
7029 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7031 if (!bgp_aggregate_med_match(aggregate
, bgp
, pi
)) {
7032 med_matched
= false;
7039 bgp_dest_unlock_node(top
);
7045 * Toggles the route suppression status for this aggregate address
7048 void bgp_aggregate_toggle_suppressed(struct bgp_aggregate
*aggregate
,
7049 struct bgp
*bgp
, const struct prefix
*p
,
7050 afi_t afi
, safi_t safi
, bool suppress
)
7052 struct bgp_table
*table
= bgp
->rib
[afi
][safi
];
7053 const struct prefix
*dest_p
;
7054 struct bgp_dest
*dest
, *top
;
7055 struct bgp_path_info
*pi
;
7056 bool toggle_suppression
;
7058 /* We've found a different MED we must revert any suppressed routes. */
7059 top
= bgp_node_get(table
, p
);
7060 for (dest
= bgp_node_get(table
, p
); dest
;
7061 dest
= bgp_route_next_until(dest
, top
)) {
7062 dest_p
= bgp_dest_get_prefix(dest
);
7063 if (dest_p
->prefixlen
<= p
->prefixlen
)
7066 toggle_suppression
= false;
7067 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7068 if (BGP_PATH_HOLDDOWN(pi
))
7070 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7073 /* We are toggling suppression back. */
7075 /* Suppress route if not suppressed already. */
7076 if (aggr_suppress_path(aggregate
, pi
))
7077 toggle_suppression
= true;
7081 /* Install route if there is no more suppression. */
7082 if (aggr_unsuppress_path(aggregate
, pi
))
7083 toggle_suppression
= true;
7086 if (toggle_suppression
)
7087 bgp_process(bgp
, dest
, afi
, safi
);
7089 bgp_dest_unlock_node(top
);
7093 * Aggregate address MED matching incremental test: this function is called
7094 * when the initial aggregation occurred and we are only testing a single
7097 * In addition to testing and setting the MED validity it also installs back
7098 * suppressed routes (if summary is configured).
7100 * Must not be called in `bgp_aggregate_route`.
7102 static void bgp_aggregate_med_update(struct bgp_aggregate
*aggregate
,
7103 struct bgp
*bgp
, const struct prefix
*p
,
7104 afi_t afi
, safi_t safi
,
7105 struct bgp_path_info
*pi
, bool is_adding
)
7107 /* MED matching disabled. */
7108 if (!aggregate
->match_med
)
7111 /* Aggregation with different MED, nothing to do. */
7112 if (aggregate
->med_mismatched
)
7116 * Test the current entry:
7118 * is_adding == true: if the new entry doesn't match then we must
7119 * install all suppressed routes.
7121 * is_adding == false: if the entry being removed was the last
7122 * unmatching entry then we can suppress all routes.
7125 if (bgp_aggregate_test_all_med(aggregate
, bgp
, p
, afi
, safi
)
7126 && aggregate
->summary_only
)
7127 bgp_aggregate_toggle_suppressed(aggregate
, bgp
, p
, afi
,
7130 bgp_aggregate_med_match(aggregate
, bgp
, pi
);
7132 /* No mismatches, just quit. */
7133 if (!aggregate
->med_mismatched
)
7136 /* Route summarization is disabled. */
7137 if (!aggregate
->summary_only
)
7140 bgp_aggregate_toggle_suppressed(aggregate
, bgp
, p
, afi
, safi
, false);
7143 /* Update an aggregate as routes are added/removed from the BGP table */
7144 void bgp_aggregate_route(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
7145 safi_t safi
, struct bgp_aggregate
*aggregate
)
7147 struct bgp_table
*table
;
7148 struct bgp_dest
*top
;
7149 struct bgp_dest
*dest
;
7151 struct aspath
*aspath
= NULL
;
7152 struct community
*community
= NULL
;
7153 struct ecommunity
*ecommunity
= NULL
;
7154 struct lcommunity
*lcommunity
= NULL
;
7155 struct bgp_path_info
*pi
;
7156 unsigned long match
= 0;
7157 uint8_t atomic_aggregate
= 0;
7159 /* If the bgp instance is being deleted or self peer is deleted
7160 * then do not create aggregate route
7162 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
7163 || (bgp
->peer_self
== NULL
))
7166 /* Initialize and test routes for MED difference. */
7167 if (aggregate
->match_med
)
7168 bgp_aggregate_test_all_med(aggregate
, bgp
, p
, afi
, safi
);
7171 * Reset aggregate count: we might've been called from route map
7172 * update so in that case we must retest all more specific routes.
7174 * \see `bgp_route_map_process_update`.
7176 aggregate
->count
= 0;
7177 aggregate
->incomplete_origin_count
= 0;
7178 aggregate
->incomplete_origin_count
= 0;
7179 aggregate
->egp_origin_count
= 0;
7181 /* ORIGIN attribute: If at least one route among routes that are
7182 aggregated has ORIGIN with the value INCOMPLETE, then the
7183 aggregated route must have the ORIGIN attribute with the value
7184 INCOMPLETE. Otherwise, if at least one route among routes that
7185 are aggregated has ORIGIN with the value EGP, then the aggregated
7186 route must have the origin attribute with the value EGP. In all
7187 other case the value of the ORIGIN attribute of the aggregated
7188 route is INTERNAL. */
7189 origin
= BGP_ORIGIN_IGP
;
7191 table
= bgp
->rib
[afi
][safi
];
7193 top
= bgp_node_get(table
, p
);
7194 for (dest
= bgp_node_get(table
, p
); dest
;
7195 dest
= bgp_route_next_until(dest
, top
)) {
7196 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
7198 if (dest_p
->prefixlen
<= p
->prefixlen
)
7201 /* If suppress fib is enabled and route not installed
7202 * in FIB, skip the route
7204 if (!bgp_check_advertise(bgp
, dest
))
7209 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7210 if (BGP_PATH_HOLDDOWN(pi
))
7214 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
7215 atomic_aggregate
= 1;
7217 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7221 * summary-only aggregate route suppress
7222 * aggregated route announcements.
7225 * Don't create summaries if MED didn't match
7226 * otherwise neither the specific routes and the
7227 * aggregation will be announced.
7229 if (aggregate
->summary_only
7230 && AGGREGATE_MED_VALID(aggregate
)) {
7231 if (aggr_suppress_path(aggregate
, pi
))
7236 * Suppress more specific routes that match the route
7240 * Don't suppress routes if MED matching is enabled and
7241 * it mismatched otherwise we might end up with no
7242 * routes for this path.
7244 if (aggregate
->suppress_map_name
7245 && AGGREGATE_MED_VALID(aggregate
)
7246 && aggr_suppress_map_test(bgp
, aggregate
, pi
)) {
7247 if (aggr_suppress_path(aggregate
, pi
))
7254 * If at least one route among routes that are
7255 * aggregated has ORIGIN with the value INCOMPLETE,
7256 * then the aggregated route MUST have the ORIGIN
7257 * attribute with the value INCOMPLETE. Otherwise, if
7258 * at least one route among routes that are aggregated
7259 * has ORIGIN with the value EGP, then the aggregated
7260 * route MUST have the ORIGIN attribute with the value
7263 switch (pi
->attr
->origin
) {
7264 case BGP_ORIGIN_INCOMPLETE
:
7265 aggregate
->incomplete_origin_count
++;
7267 case BGP_ORIGIN_EGP
:
7268 aggregate
->egp_origin_count
++;
7276 if (!aggregate
->as_set
)
7280 * as-set aggregate route generate origin, as path,
7281 * and community aggregation.
7283 /* Compute aggregate route's as-path.
7285 bgp_compute_aggregate_aspath_hash(aggregate
,
7288 /* Compute aggregate route's community.
7290 if (pi
->attr
->community
)
7291 bgp_compute_aggregate_community_hash(
7293 pi
->attr
->community
);
7295 /* Compute aggregate route's extended community.
7297 if (pi
->attr
->ecommunity
)
7298 bgp_compute_aggregate_ecommunity_hash(
7300 pi
->attr
->ecommunity
);
7302 /* Compute aggregate route's large community.
7304 if (pi
->attr
->lcommunity
)
7305 bgp_compute_aggregate_lcommunity_hash(
7307 pi
->attr
->lcommunity
);
7310 bgp_process(bgp
, dest
, afi
, safi
);
7312 if (aggregate
->as_set
) {
7313 bgp_compute_aggregate_aspath_val(aggregate
);
7314 bgp_compute_aggregate_community_val(aggregate
);
7315 bgp_compute_aggregate_ecommunity_val(aggregate
);
7316 bgp_compute_aggregate_lcommunity_val(aggregate
);
7320 bgp_dest_unlock_node(top
);
7323 if (aggregate
->incomplete_origin_count
> 0)
7324 origin
= BGP_ORIGIN_INCOMPLETE
;
7325 else if (aggregate
->egp_origin_count
> 0)
7326 origin
= BGP_ORIGIN_EGP
;
7328 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
7329 origin
= aggregate
->origin
;
7331 if (aggregate
->as_set
) {
7332 if (aggregate
->aspath
)
7333 /* Retrieve aggregate route's as-path.
7335 aspath
= aspath_dup(aggregate
->aspath
);
7337 if (aggregate
->community
)
7338 /* Retrieve aggregate route's community.
7340 community
= community_dup(aggregate
->community
);
7342 if (aggregate
->ecommunity
)
7343 /* Retrieve aggregate route's ecommunity.
7345 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
7347 if (aggregate
->lcommunity
)
7348 /* Retrieve aggregate route's lcommunity.
7350 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
7353 bgp_aggregate_install(bgp
, afi
, safi
, p
, origin
, aspath
, community
,
7354 ecommunity
, lcommunity
, atomic_aggregate
,
7358 void bgp_aggregate_delete(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
7359 safi_t safi
, struct bgp_aggregate
*aggregate
)
7361 struct bgp_table
*table
;
7362 struct bgp_dest
*top
;
7363 struct bgp_dest
*dest
;
7364 struct bgp_path_info
*pi
;
7365 unsigned long match
;
7367 table
= bgp
->rib
[afi
][safi
];
7369 /* If routes exists below this node, generate aggregate routes. */
7370 top
= bgp_node_get(table
, p
);
7371 for (dest
= bgp_node_get(table
, p
); dest
;
7372 dest
= bgp_route_next_until(dest
, top
)) {
7373 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
7375 if (dest_p
->prefixlen
<= p
->prefixlen
)
7379 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7380 if (BGP_PATH_HOLDDOWN(pi
))
7383 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7386 if (aggregate
->summary_only
&& pi
->extra
7387 && AGGREGATE_MED_VALID(aggregate
)) {
7388 if (aggr_unsuppress_path(aggregate
, pi
))
7392 if (aggregate
->suppress_map_name
7393 && AGGREGATE_MED_VALID(aggregate
)
7394 && aggr_suppress_map_test(bgp
, aggregate
, pi
)) {
7395 if (aggr_unsuppress_path(aggregate
, pi
))
7401 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
7402 aggregate
->incomplete_origin_count
--;
7403 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
7404 aggregate
->egp_origin_count
--;
7406 if (aggregate
->as_set
) {
7407 /* Remove as-path from aggregate.
7409 bgp_remove_aspath_from_aggregate_hash(
7413 if (pi
->attr
->community
)
7414 /* Remove community from aggregate.
7416 bgp_remove_comm_from_aggregate_hash(
7418 pi
->attr
->community
);
7420 if (pi
->attr
->ecommunity
)
7421 /* Remove ecommunity from aggregate.
7423 bgp_remove_ecomm_from_aggregate_hash(
7425 pi
->attr
->ecommunity
);
7427 if (pi
->attr
->lcommunity
)
7428 /* Remove lcommunity from aggregate.
7430 bgp_remove_lcomm_from_aggregate_hash(
7432 pi
->attr
->lcommunity
);
7436 /* If this node was suppressed, process the change. */
7438 bgp_process(bgp
, dest
, afi
, safi
);
7440 if (aggregate
->as_set
) {
7441 aspath_free(aggregate
->aspath
);
7442 aggregate
->aspath
= NULL
;
7443 if (aggregate
->community
)
7444 community_free(&aggregate
->community
);
7445 if (aggregate
->ecommunity
)
7446 ecommunity_free(&aggregate
->ecommunity
);
7447 if (aggregate
->lcommunity
)
7448 lcommunity_free(&aggregate
->lcommunity
);
7451 bgp_dest_unlock_node(top
);
7454 static void bgp_add_route_to_aggregate(struct bgp
*bgp
,
7455 const struct prefix
*aggr_p
,
7456 struct bgp_path_info
*pinew
, afi_t afi
,
7458 struct bgp_aggregate
*aggregate
)
7461 struct aspath
*aspath
= NULL
;
7462 uint8_t atomic_aggregate
= 0;
7463 struct community
*community
= NULL
;
7464 struct ecommunity
*ecommunity
= NULL
;
7465 struct lcommunity
*lcommunity
= NULL
;
7467 /* If the bgp instance is being deleted or self peer is deleted
7468 * then do not create aggregate route
7470 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
7471 || (bgp
->peer_self
== NULL
))
7474 /* ORIGIN attribute: If at least one route among routes that are
7475 * aggregated has ORIGIN with the value INCOMPLETE, then the
7476 * aggregated route must have the ORIGIN attribute with the value
7477 * INCOMPLETE. Otherwise, if at least one route among routes that
7478 * are aggregated has ORIGIN with the value EGP, then the aggregated
7479 * route must have the origin attribute with the value EGP. In all
7480 * other case the value of the ORIGIN attribute of the aggregated
7481 * route is INTERNAL.
7483 origin
= BGP_ORIGIN_IGP
;
7488 * This must be called before `summary` check to avoid
7489 * "suppressing" twice.
7491 if (aggregate
->match_med
)
7492 bgp_aggregate_med_update(aggregate
, bgp
, aggr_p
, afi
, safi
,
7495 if (aggregate
->summary_only
&& AGGREGATE_MED_VALID(aggregate
))
7496 aggr_suppress_path(aggregate
, pinew
);
7498 if (aggregate
->suppress_map_name
&& AGGREGATE_MED_VALID(aggregate
)
7499 && aggr_suppress_map_test(bgp
, aggregate
, pinew
))
7500 aggr_suppress_path(aggregate
, pinew
);
7502 switch (pinew
->attr
->origin
) {
7503 case BGP_ORIGIN_INCOMPLETE
:
7504 aggregate
->incomplete_origin_count
++;
7506 case BGP_ORIGIN_EGP
:
7507 aggregate
->egp_origin_count
++;
7515 if (aggregate
->incomplete_origin_count
> 0)
7516 origin
= BGP_ORIGIN_INCOMPLETE
;
7517 else if (aggregate
->egp_origin_count
> 0)
7518 origin
= BGP_ORIGIN_EGP
;
7520 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
7521 origin
= aggregate
->origin
;
7523 if (aggregate
->as_set
) {
7524 /* Compute aggregate route's as-path.
7526 bgp_compute_aggregate_aspath(aggregate
,
7527 pinew
->attr
->aspath
);
7529 /* Compute aggregate route's community.
7531 if (pinew
->attr
->community
)
7532 bgp_compute_aggregate_community(
7534 pinew
->attr
->community
);
7536 /* Compute aggregate route's extended community.
7538 if (pinew
->attr
->ecommunity
)
7539 bgp_compute_aggregate_ecommunity(
7541 pinew
->attr
->ecommunity
);
7543 /* Compute aggregate route's large community.
7545 if (pinew
->attr
->lcommunity
)
7546 bgp_compute_aggregate_lcommunity(
7548 pinew
->attr
->lcommunity
);
7550 /* Retrieve aggregate route's as-path.
7552 if (aggregate
->aspath
)
7553 aspath
= aspath_dup(aggregate
->aspath
);
7555 /* Retrieve aggregate route's community.
7557 if (aggregate
->community
)
7558 community
= community_dup(aggregate
->community
);
7560 /* Retrieve aggregate route's ecommunity.
7562 if (aggregate
->ecommunity
)
7563 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
7565 /* Retrieve aggregate route's lcommunity.
7567 if (aggregate
->lcommunity
)
7568 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
7571 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
7572 aspath
, community
, ecommunity
,
7573 lcommunity
, atomic_aggregate
, aggregate
);
7576 static void bgp_remove_route_from_aggregate(struct bgp
*bgp
, afi_t afi
,
7578 struct bgp_path_info
*pi
,
7579 struct bgp_aggregate
*aggregate
,
7580 const struct prefix
*aggr_p
)
7583 struct aspath
*aspath
= NULL
;
7584 uint8_t atomic_aggregate
= 0;
7585 struct community
*community
= NULL
;
7586 struct ecommunity
*ecommunity
= NULL
;
7587 struct lcommunity
*lcommunity
= NULL
;
7588 unsigned long match
= 0;
7590 /* If the bgp instance is being deleted or self peer is deleted
7591 * then do not create aggregate route
7593 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
7594 || (bgp
->peer_self
== NULL
))
7597 if (BGP_PATH_HOLDDOWN(pi
))
7600 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7603 if (aggregate
->summary_only
&& AGGREGATE_MED_VALID(aggregate
))
7604 if (aggr_unsuppress_path(aggregate
, pi
))
7607 if (aggregate
->suppress_map_name
&& AGGREGATE_MED_VALID(aggregate
)
7608 && aggr_suppress_map_test(bgp
, aggregate
, pi
))
7609 if (aggr_unsuppress_path(aggregate
, pi
))
7613 * This must be called after `summary`, `suppress-map` check to avoid
7614 * "unsuppressing" twice.
7616 if (aggregate
->match_med
)
7617 bgp_aggregate_med_update(aggregate
, bgp
, aggr_p
, afi
, safi
, pi
,
7620 if (aggregate
->count
> 0)
7623 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
7624 aggregate
->incomplete_origin_count
--;
7625 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
7626 aggregate
->egp_origin_count
--;
7628 if (aggregate
->as_set
) {
7629 /* Remove as-path from aggregate.
7631 bgp_remove_aspath_from_aggregate(aggregate
,
7634 if (pi
->attr
->community
)
7635 /* Remove community from aggregate.
7637 bgp_remove_community_from_aggregate(
7639 pi
->attr
->community
);
7641 if (pi
->attr
->ecommunity
)
7642 /* Remove ecommunity from aggregate.
7644 bgp_remove_ecommunity_from_aggregate(
7646 pi
->attr
->ecommunity
);
7648 if (pi
->attr
->lcommunity
)
7649 /* Remove lcommunity from aggregate.
7651 bgp_remove_lcommunity_from_aggregate(
7653 pi
->attr
->lcommunity
);
7656 /* If this node was suppressed, process the change. */
7658 bgp_process(bgp
, pi
->net
, afi
, safi
);
7660 origin
= BGP_ORIGIN_IGP
;
7661 if (aggregate
->incomplete_origin_count
> 0)
7662 origin
= BGP_ORIGIN_INCOMPLETE
;
7663 else if (aggregate
->egp_origin_count
> 0)
7664 origin
= BGP_ORIGIN_EGP
;
7666 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
7667 origin
= aggregate
->origin
;
7669 if (aggregate
->as_set
) {
7670 /* Retrieve aggregate route's as-path.
7672 if (aggregate
->aspath
)
7673 aspath
= aspath_dup(aggregate
->aspath
);
7675 /* Retrieve aggregate route's community.
7677 if (aggregate
->community
)
7678 community
= community_dup(aggregate
->community
);
7680 /* Retrieve aggregate route's ecommunity.
7682 if (aggregate
->ecommunity
)
7683 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
7685 /* Retrieve aggregate route's lcommunity.
7687 if (aggregate
->lcommunity
)
7688 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
7691 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
7692 aspath
, community
, ecommunity
,
7693 lcommunity
, atomic_aggregate
, aggregate
);
7696 void bgp_aggregate_increment(struct bgp
*bgp
, const struct prefix
*p
,
7697 struct bgp_path_info
*pi
, afi_t afi
, safi_t safi
)
7699 struct bgp_dest
*child
;
7700 struct bgp_dest
*dest
;
7701 struct bgp_aggregate
*aggregate
;
7702 struct bgp_table
*table
;
7704 table
= bgp
->aggregate
[afi
][safi
];
7706 /* No aggregates configured. */
7707 if (bgp_table_top_nolock(table
) == NULL
)
7710 if (p
->prefixlen
== 0)
7713 if (BGP_PATH_HOLDDOWN(pi
))
7716 /* If suppress fib is enabled and route not installed
7717 * in FIB, do not update the aggregate route
7719 if (!bgp_check_advertise(bgp
, pi
->net
))
7722 child
= bgp_node_get(table
, p
);
7724 /* Aggregate address configuration check. */
7725 for (dest
= child
; dest
; dest
= bgp_dest_parent_nolock(dest
)) {
7726 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
7728 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
7729 if (aggregate
!= NULL
&& dest_p
->prefixlen
< p
->prefixlen
) {
7730 bgp_add_route_to_aggregate(bgp
, dest_p
, pi
, afi
, safi
,
7734 bgp_dest_unlock_node(child
);
7737 void bgp_aggregate_decrement(struct bgp
*bgp
, const struct prefix
*p
,
7738 struct bgp_path_info
*del
, afi_t afi
, safi_t safi
)
7740 struct bgp_dest
*child
;
7741 struct bgp_dest
*dest
;
7742 struct bgp_aggregate
*aggregate
;
7743 struct bgp_table
*table
;
7745 table
= bgp
->aggregate
[afi
][safi
];
7747 /* No aggregates configured. */
7748 if (bgp_table_top_nolock(table
) == NULL
)
7751 if (p
->prefixlen
== 0)
7754 child
= bgp_node_get(table
, p
);
7756 /* Aggregate address configuration check. */
7757 for (dest
= child
; dest
; dest
= bgp_dest_parent_nolock(dest
)) {
7758 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
7760 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
7761 if (aggregate
!= NULL
&& dest_p
->prefixlen
< p
->prefixlen
) {
7762 bgp_remove_route_from_aggregate(bgp
, afi
, safi
, del
,
7766 bgp_dest_unlock_node(child
);
7769 /* Aggregate route attribute. */
7770 #define AGGREGATE_SUMMARY_ONLY 1
7771 #define AGGREGATE_AS_SET 1
7772 #define AGGREGATE_AS_UNSET 0
7774 static const char *bgp_origin2str(uint8_t origin
)
7777 case BGP_ORIGIN_IGP
:
7779 case BGP_ORIGIN_EGP
:
7781 case BGP_ORIGIN_INCOMPLETE
:
7782 return "incomplete";
7787 static const char *bgp_rpki_validation2str(enum rpki_states v_state
)
7790 case RPKI_NOT_BEING_USED
:
7800 assert(!"We should never get here this is a dev escape");
7804 int bgp_aggregate_unset(struct bgp
*bgp
, struct prefix
*prefix
, afi_t afi
,
7805 safi_t safi
, char *errmsg
, size_t errmsg_len
)
7807 struct bgp_dest
*dest
;
7808 struct bgp_aggregate
*aggregate
;
7810 /* If the bgp instance is being deleted or self peer is deleted
7811 * then do not create aggregate route
7813 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
7814 || (bgp
->peer_self
== NULL
))
7818 /* Old configuration check. */
7819 dest
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], prefix
);
7821 snprintf(errmsg
, errmsg_len
,
7822 "There is no aggregate-address configuration.\n");
7826 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
7827 bgp_aggregate_delete(bgp
, prefix
, afi
, safi
, aggregate
);
7828 bgp_aggregate_install(bgp
, afi
, safi
, prefix
, 0, NULL
, NULL
, NULL
, NULL
,
7831 /* Unlock aggregate address configuration. */
7832 bgp_dest_set_bgp_aggregate_info(dest
, NULL
);
7834 if (aggregate
->community
)
7835 community_free(&aggregate
->community
);
7837 if (aggregate
->community_hash
) {
7838 /* Delete all communities in the hash.
7840 hash_clean(aggregate
->community_hash
,
7841 bgp_aggr_community_remove
);
7842 /* Free up the community_hash.
7844 hash_free(aggregate
->community_hash
);
7847 if (aggregate
->ecommunity
)
7848 ecommunity_free(&aggregate
->ecommunity
);
7850 if (aggregate
->ecommunity_hash
) {
7851 /* Delete all ecommunities in the hash.
7853 hash_clean(aggregate
->ecommunity_hash
,
7854 bgp_aggr_ecommunity_remove
);
7855 /* Free up the ecommunity_hash.
7857 hash_free(aggregate
->ecommunity_hash
);
7860 if (aggregate
->lcommunity
)
7861 lcommunity_free(&aggregate
->lcommunity
);
7863 if (aggregate
->lcommunity_hash
) {
7864 /* Delete all lcommunities in the hash.
7866 hash_clean(aggregate
->lcommunity_hash
,
7867 bgp_aggr_lcommunity_remove
);
7868 /* Free up the lcommunity_hash.
7870 hash_free(aggregate
->lcommunity_hash
);
7873 if (aggregate
->aspath
)
7874 aspath_free(aggregate
->aspath
);
7876 if (aggregate
->aspath_hash
) {
7877 /* Delete all as-paths in the hash.
7879 hash_clean(aggregate
->aspath_hash
,
7880 bgp_aggr_aspath_remove
);
7881 /* Free up the aspath_hash.
7883 hash_free(aggregate
->aspath_hash
);
7886 bgp_aggregate_free(aggregate
);
7887 bgp_dest_unlock_node(dest
);
7888 bgp_dest_unlock_node(dest
);
7893 int bgp_aggregate_set(struct bgp
*bgp
, struct prefix
*prefix
, afi_t afi
,
7894 safi_t safi
, const char *rmap
, uint8_t summary_only
,
7895 uint8_t as_set
, uint8_t origin
, bool match_med
,
7896 const char *suppress_map
,
7897 char *errmsg
, size_t errmsg_len
)
7900 struct bgp_dest
*dest
;
7901 struct bgp_aggregate
*aggregate
;
7902 uint8_t as_set_new
= as_set
;
7903 char buf
[PREFIX2STR_BUFFER
];
7905 if (suppress_map
&& summary_only
) {
7906 snprintf(errmsg
, errmsg_len
,
7907 "'summary-only' and 'suppress-map' can't be used at the same time\n");
7913 if ((afi
== AFI_IP
&& prefix
->prefixlen
== IPV4_MAX_BITLEN
)
7914 || (afi
== AFI_IP6
&& prefix
->prefixlen
== IPV6_MAX_BITLEN
)) {
7917 "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
7918 prefix2str(prefix
, buf
, PREFIX_STRLEN
));
7922 /* Old configuration check. */
7923 dest
= bgp_node_get(bgp
->aggregate
[afi
][safi
], prefix
);
7924 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
7927 snprintf(errmsg
, errmsg_len
,
7928 "There is already same aggregate network.\n");
7929 /* try to remove the old entry */
7930 ret
= bgp_aggregate_unset(bgp
, prefix
, afi
, safi
, errmsg
,
7933 snprintf(errmsg
, errmsg_len
,
7934 "Error deleting aggregate.\n");
7935 bgp_dest_unlock_node(dest
);
7940 /* Make aggregate address structure. */
7941 aggregate
= bgp_aggregate_new();
7942 aggregate
->summary_only
= summary_only
;
7943 aggregate
->match_med
= match_med
;
7945 /* Network operators MUST NOT locally generate any new
7946 * announcements containing AS_SET or AS_CONFED_SET. If they have
7947 * announced routes with AS_SET or AS_CONFED_SET in them, then they
7948 * SHOULD withdraw those routes and re-announce routes for the
7949 * aggregate or component prefixes (i.e., the more-specific routes
7950 * subsumed by the previously aggregated route) without AS_SET
7951 * or AS_CONFED_SET in the updates.
7953 if (bgp
->reject_as_sets
) {
7954 if (as_set
== AGGREGATE_AS_SET
) {
7955 as_set_new
= AGGREGATE_AS_UNSET
;
7957 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
7961 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
7965 aggregate
->as_set
= as_set_new
;
7966 aggregate
->safi
= safi
;
7967 /* Override ORIGIN attribute if defined.
7968 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
7969 * to IGP which is not what rfc4271 says.
7970 * This enables the same behavior, optionally.
7972 aggregate
->origin
= origin
;
7975 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
7976 route_map_counter_decrement(aggregate
->rmap
.map
);
7977 aggregate
->rmap
.name
=
7978 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
7979 aggregate
->rmap
.map
= route_map_lookup_by_name(rmap
);
7980 route_map_counter_increment(aggregate
->rmap
.map
);
7984 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->suppress_map_name
);
7985 route_map_counter_decrement(aggregate
->suppress_map
);
7987 aggregate
->suppress_map_name
=
7988 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, suppress_map
);
7989 aggregate
->suppress_map
=
7990 route_map_lookup_by_name(aggregate
->suppress_map_name
);
7991 route_map_counter_increment(aggregate
->suppress_map
);
7994 bgp_dest_set_bgp_aggregate_info(dest
, aggregate
);
7996 /* Aggregate address insert into BGP routing table. */
7997 bgp_aggregate_route(bgp
, prefix
, afi
, safi
, aggregate
);
8003 aggregate_addressv4
, aggregate_addressv4_cmd
,
8004 "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> [{"
8006 "|summary-only$summary_only"
8007 "|route-map WORD$rmap_name"
8008 "|origin <egp|igp|incomplete>$origin_s"
8009 "|matching-MED-only$match_med"
8010 "|suppress-map WORD$suppress_map"
8013 "Configure BGP aggregate entries\n"
8014 "Aggregate prefix\n"
8015 "Aggregate address\n"
8017 "Generate AS set path information\n"
8018 "Filter more specific routes from updates\n"
8019 "Apply route map to aggregate network\n"
8024 "Unknown heritage\n"
8025 "Only aggregate routes with matching MED\n"
8026 "Suppress the selected more specific routes\n"
8027 "Route map with the route selectors\n")
8029 char base_xpath
[XPATH_MAXLEN
];
8030 safi_t safi
= bgp_node_safi(vty
);
8031 char prefix_buf
[PREFIX2STR_BUFFER
];
8034 if (netmask_str2prefix_str(addr_str
, mask_str
, prefix_buf
,
8037 vty_out(vty
, "%% Inconsistent address and mask\n");
8038 return CMD_WARNING_CONFIG_FAILED
;
8041 strlcpy(prefix_buf
, prefix_str
, sizeof(prefix_buf
));
8044 if (!no
&& origin_s
)
8045 nb_cli_enqueue_change(vty
, "./origin", NB_OP_MODIFY
, origin_s
);
8047 if (!no
&& as_set_s
)
8048 nb_cli_enqueue_change(vty
, "./as-set", NB_OP_MODIFY
, "true");
8050 nb_cli_enqueue_change(vty
, "./as-set", NB_OP_MODIFY
, "false");
8052 if (!no
&& summary_only
)
8053 nb_cli_enqueue_change(vty
, "./summary-only", NB_OP_MODIFY
,
8056 nb_cli_enqueue_change(vty
, "./summary-only", NB_OP_MODIFY
,
8059 if (!no
&& match_med
)
8060 nb_cli_enqueue_change(vty
, "./match-med", NB_OP_MODIFY
, "true");
8062 nb_cli_enqueue_change(vty
, "./match-med", NB_OP_MODIFY
,
8066 nb_cli_enqueue_change(vty
, "./rmap-policy-export", NB_OP_MODIFY
,
8069 nb_cli_enqueue_change(vty
, "./rmap-policy-export",
8070 NB_OP_DESTROY
, NULL
);
8073 nb_cli_enqueue_change(vty
, "./suppress-map", NB_OP_MODIFY
,
8076 nb_cli_enqueue_change(vty
, "./suppress-map", NB_OP_DESTROY
,
8080 base_xpath
, sizeof(base_xpath
),
8081 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/aggregate-route[prefix='%s']",
8082 yang_afi_safi_value2identity(AFI_IP
, safi
),
8083 bgp_afi_safi_get_container_str(AFI_IP
, safi
), prefix_buf
);
8086 nb_cli_enqueue_change(vty
, ".", NB_OP_DESTROY
, NULL
);
8088 nb_cli_enqueue_change(vty
, ".", NB_OP_CREATE
, NULL
);
8090 return nb_cli_apply_changes(vty
, base_xpath
);
8093 DEFPY_YANG(aggregate_addressv6
, aggregate_addressv6_cmd
,
8094 "[no] aggregate-address X:X::X:X/M$prefix [{"
8096 "|summary-only$summary_only"
8097 "|route-map WORD$rmap_name"
8098 "|origin <egp|igp|incomplete>$origin_s"
8099 "|matching-MED-only$match_med"
8100 "|suppress-map WORD$suppress_map"
8103 "Configure BGP aggregate entries\n"
8104 "Aggregate prefix\n"
8105 "Generate AS set path information\n"
8106 "Filter more specific routes from updates\n"
8107 "Apply route map to aggregate network\n"
8112 "Unknown heritage\n"
8113 "Only aggregate routes with matching MED\n"
8114 "Suppress the selected more specific routes\n"
8115 "Route map with the route selectors\n")
8117 char base_xpath
[XPATH_MAXLEN
];
8118 safi_t safi
= bgp_node_safi(vty
);
8120 if (!no
&& origin_s
)
8121 nb_cli_enqueue_change(vty
, "./origin", NB_OP_MODIFY
, origin_s
);
8123 if (!no
&& as_set_s
)
8124 nb_cli_enqueue_change(vty
, "./as-set", NB_OP_MODIFY
, "true");
8126 nb_cli_enqueue_change(vty
, "./as-set", NB_OP_MODIFY
, "false");
8128 if (!no
&& summary_only
)
8129 nb_cli_enqueue_change(vty
, "./summary-only", NB_OP_MODIFY
,
8132 nb_cli_enqueue_change(vty
, "./summary-only", NB_OP_MODIFY
,
8135 if (!no
&& match_med
)
8136 nb_cli_enqueue_change(vty
, "./match-med", NB_OP_MODIFY
, "true");
8138 nb_cli_enqueue_change(vty
, "./match-med", NB_OP_MODIFY
,
8142 nb_cli_enqueue_change(vty
, "./rmap-policy-export", NB_OP_MODIFY
,
8146 nb_cli_enqueue_change(vty
, "./suppress-map", NB_OP_MODIFY
,
8149 nb_cli_enqueue_change(vty
, "./suppress-map", NB_OP_DESTROY
,
8153 base_xpath
, sizeof(base_xpath
),
8154 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/aggregate-route[prefix='%s']",
8155 yang_afi_safi_value2identity(AFI_IP6
, safi
),
8156 bgp_afi_safi_get_container_str(AFI_IP6
, safi
), prefix_str
);
8159 nb_cli_enqueue_change(vty
, ".", NB_OP_DESTROY
, NULL
);
8161 nb_cli_enqueue_change(vty
, ".", NB_OP_CREATE
, NULL
);
8163 return nb_cli_apply_changes(vty
, base_xpath
);
8166 void cli_show_bgp_global_afi_safi_unicast_aggregate_route(
8167 struct vty
*vty
, struct lyd_node
*dnode
, bool show_defaults
)
8171 vty_out(vty
, " aggregate-address %s",
8172 yang_dnode_get_string(dnode
, "./prefix"));
8174 if (yang_dnode_get_bool(dnode
, "./as-set"))
8175 vty_out(vty
, " as-set");
8177 if (yang_dnode_get_bool(dnode
, "./summary-only"))
8178 vty_out(vty
, " summary-only");
8180 if (yang_dnode_exists(dnode
, "./rmap-policy-export"))
8181 vty_out(vty
, " route-map %s",
8182 yang_dnode_get_string(dnode
, "./rmap-policy-export"));
8184 origin
= yang_dnode_get_enum(dnode
, "./origin");
8185 if (origin
!= BGP_ORIGIN_UNSPECIFIED
)
8186 vty_out(vty
, " origin %s", bgp_origin2str(origin
));
8188 if (yang_dnode_get_bool(dnode
, "./match-med"))
8189 vty_out(vty
, " matching-MED-only");
8194 /* Redistribute route treatment. */
8195 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
8196 const union g_addr
*nexthop
, ifindex_t ifindex
,
8197 enum nexthop_types_t nhtype
, uint32_t metric
,
8198 uint8_t type
, unsigned short instance
,
8201 struct bgp_path_info
*new;
8202 struct bgp_path_info
*bpi
;
8203 struct bgp_path_info rmap_path
;
8204 struct bgp_dest
*bn
;
8206 struct attr
*new_attr
;
8208 route_map_result_t ret
;
8209 struct bgp_redist
*red
;
8211 /* Make default attribute. */
8212 bgp_attr_default_set(&attr
, BGP_ORIGIN_INCOMPLETE
);
8214 * This must not be NULL to satisfy Coverity SA
8216 assert(attr
.aspath
);
8219 case NEXTHOP_TYPE_IFINDEX
:
8221 case NEXTHOP_TYPE_IPV4
:
8222 case NEXTHOP_TYPE_IPV4_IFINDEX
:
8223 attr
.nexthop
= nexthop
->ipv4
;
8225 case NEXTHOP_TYPE_IPV6
:
8226 case NEXTHOP_TYPE_IPV6_IFINDEX
:
8227 attr
.mp_nexthop_global
= nexthop
->ipv6
;
8228 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
8230 case NEXTHOP_TYPE_BLACKHOLE
:
8231 switch (p
->family
) {
8233 attr
.nexthop
.s_addr
= INADDR_ANY
;
8236 memset(&attr
.mp_nexthop_global
, 0,
8237 sizeof(attr
.mp_nexthop_global
));
8238 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
8243 attr
.nh_ifindex
= ifindex
;
8246 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
8249 afi
= family2afi(p
->family
);
8251 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
8253 struct attr attr_new
;
8255 /* Copy attribute for modification. */
8258 if (red
->redist_metric_flag
)
8259 attr_new
.med
= red
->redist_metric
;
8261 /* Apply route-map. */
8262 if (red
->rmap
.name
) {
8263 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
8264 rmap_path
.peer
= bgp
->peer_self
;
8265 rmap_path
.attr
= &attr_new
;
8267 SET_FLAG(bgp
->peer_self
->rmap_type
,
8268 PEER_RMAP_TYPE_REDISTRIBUTE
);
8270 ret
= route_map_apply(red
->rmap
.map
, p
, &rmap_path
);
8272 bgp
->peer_self
->rmap_type
= 0;
8274 if (ret
== RMAP_DENYMATCH
) {
8275 /* Free uninterned attribute. */
8276 bgp_attr_flush(&attr_new
);
8278 /* Unintern original. */
8279 aspath_unintern(&attr
.aspath
);
8280 bgp_redistribute_delete(bgp
, p
, type
, instance
);
8285 if (bgp_in_graceful_shutdown(bgp
))
8286 bgp_attr_add_gshut_community(&attr_new
);
8288 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
8289 SAFI_UNICAST
, p
, NULL
);
8291 new_attr
= bgp_attr_intern(&attr_new
);
8293 for (bpi
= bgp_dest_get_bgp_path_info(bn
); bpi
; bpi
= bpi
->next
)
8294 if (bpi
->peer
== bgp
->peer_self
8295 && bpi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
8299 /* Ensure the (source route) type is updated. */
8301 if (attrhash_cmp(bpi
->attr
, new_attr
)
8302 && !CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
)) {
8303 bgp_attr_unintern(&new_attr
);
8304 aspath_unintern(&attr
.aspath
);
8305 bgp_dest_unlock_node(bn
);
8308 /* The attribute is changed. */
8309 bgp_path_info_set_flag(bn
, bpi
,
8310 BGP_PATH_ATTR_CHANGED
);
8312 /* Rewrite BGP route information. */
8313 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
8314 bgp_path_info_restore(bn
, bpi
);
8316 bgp_aggregate_decrement(
8317 bgp
, p
, bpi
, afi
, SAFI_UNICAST
);
8318 bgp_attr_unintern(&bpi
->attr
);
8319 bpi
->attr
= new_attr
;
8320 bpi
->uptime
= bgp_clock();
8322 /* Process change. */
8323 bgp_aggregate_increment(bgp
, p
, bpi
, afi
,
8325 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
8326 bgp_dest_unlock_node(bn
);
8327 aspath_unintern(&attr
.aspath
);
8329 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8331 == BGP_INSTANCE_TYPE_DEFAULT
)) {
8333 vpn_leak_from_vrf_update(
8334 bgp_get_default(), bgp
, bpi
);
8340 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
8341 bgp
->peer_self
, new_attr
, bn
);
8342 SET_FLAG(new->flags
, BGP_PATH_VALID
);
8344 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
8345 bgp_path_info_add(bn
, new);
8346 bgp_dest_unlock_node(bn
);
8347 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
8349 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8350 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8352 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
8356 /* Unintern original. */
8357 aspath_unintern(&attr
.aspath
);
8360 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, uint8_t type
,
8361 unsigned short instance
)
8364 struct bgp_dest
*dest
;
8365 struct bgp_path_info
*pi
;
8366 struct bgp_redist
*red
;
8368 afi
= family2afi(p
->family
);
8370 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
8372 dest
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
8373 SAFI_UNICAST
, p
, NULL
);
8375 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
8376 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
)
8380 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8381 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8383 vpn_leak_from_vrf_withdraw(bgp_get_default(),
8386 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, SAFI_UNICAST
);
8387 bgp_path_info_delete(dest
, pi
);
8388 bgp_process(bgp
, dest
, afi
, SAFI_UNICAST
);
8390 bgp_dest_unlock_node(dest
);
8394 /* Withdraw specified route type's route. */
8395 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
8396 unsigned short instance
)
8398 struct bgp_dest
*dest
;
8399 struct bgp_path_info
*pi
;
8400 struct bgp_table
*table
;
8402 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
8404 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
8405 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
8406 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
8407 && pi
->instance
== instance
)
8411 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8412 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8414 vpn_leak_from_vrf_withdraw(bgp_get_default(),
8417 bgp_aggregate_decrement(bgp
, bgp_dest_get_prefix(dest
),
8418 pi
, afi
, SAFI_UNICAST
);
8419 bgp_path_info_delete(dest
, pi
);
8420 bgp_process(bgp
, dest
, afi
, SAFI_UNICAST
);
8425 /* Static function to display route. */
8426 static void route_vty_out_route(struct bgp_dest
*dest
, const struct prefix
*p
,
8427 struct vty
*vty
, json_object
*json
, bool wide
)
8433 if (p
->family
== AF_INET
) {
8435 len
= vty_out(vty
, "%pFX", p
);
8437 json_object_string_add(json
, "prefix",
8438 inet_ntop(p
->family
,
8441 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
8442 prefix2str(p
, buf2
, PREFIX_STRLEN
);
8443 json_object_string_add(json
, "network", buf2
);
8444 json_object_int_add(json
, "version", dest
->version
);
8446 } else if (p
->family
== AF_ETHERNET
) {
8447 len
= vty_out(vty
, "%pFX", p
);
8448 } else if (p
->family
== AF_EVPN
) {
8450 len
= vty_out(vty
, "%pFX", (struct prefix_evpn
*)p
);
8452 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
8453 } else if (p
->family
== AF_FLOWSPEC
) {
8454 route_vty_out_flowspec(vty
, p
, NULL
,
8456 NLRI_STRING_FORMAT_JSON_SIMPLE
:
8457 NLRI_STRING_FORMAT_MIN
, json
);
8460 len
= vty_out(vty
, "%pFX", p
);
8462 json_object_string_add(json
, "prefix",
8463 inet_ntop(p
->family
,
8466 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
8467 prefix2str(p
, buf2
, PREFIX_STRLEN
);
8468 json_object_string_add(json
, "network", buf2
);
8469 json_object_int_add(json
, "version", dest
->version
);
8474 len
= wide
? (45 - len
) : (17 - len
);
8476 vty_out(vty
, "\n%*s", 20, " ");
8478 vty_out(vty
, "%*s", len
, " ");
8482 enum bgp_display_type
{
8487 bgp_path_selection_reason2str(enum bgp_path_selection_reason reason
)
8490 case bgp_path_selection_none
:
8491 return "Nothing to Select";
8492 case bgp_path_selection_first
:
8493 return "First path received";
8494 case bgp_path_selection_evpn_sticky_mac
:
8495 return "EVPN Sticky Mac";
8496 case bgp_path_selection_evpn_seq
:
8497 return "EVPN sequence number";
8498 case bgp_path_selection_evpn_lower_ip
:
8499 return "EVPN lower IP";
8500 case bgp_path_selection_evpn_local_path
:
8501 return "EVPN local ES path";
8502 case bgp_path_selection_evpn_non_proxy
:
8503 return "EVPN non proxy";
8504 case bgp_path_selection_weight
:
8506 case bgp_path_selection_local_pref
:
8507 return "Local Pref";
8508 case bgp_path_selection_local_route
:
8509 return "Local Route";
8510 case bgp_path_selection_confed_as_path
:
8511 return "Confederation based AS Path";
8512 case bgp_path_selection_as_path
:
8514 case bgp_path_selection_origin
:
8516 case bgp_path_selection_med
:
8518 case bgp_path_selection_peer
:
8520 case bgp_path_selection_confed
:
8521 return "Confed Peer Type";
8522 case bgp_path_selection_igp_metric
:
8523 return "IGP Metric";
8524 case bgp_path_selection_older
:
8525 return "Older Path";
8526 case bgp_path_selection_router_id
:
8528 case bgp_path_selection_cluster_length
:
8529 return "Cluster length";
8530 case bgp_path_selection_stale
:
8531 return "Path Staleness";
8532 case bgp_path_selection_local_configured
:
8533 return "Locally configured route";
8534 case bgp_path_selection_neighbor_ip
:
8535 return "Neighbor IP";
8536 case bgp_path_selection_default
:
8537 return "Nothing left to compare";
8539 return "Invalid (internal error)";
8542 /* Print the short form route status for a bgp_path_info */
8543 static void route_vty_short_status_out(struct vty
*vty
,
8544 struct bgp_path_info
*path
,
8545 const struct prefix
*p
,
8546 json_object
*json_path
)
8548 enum rpki_states rpki_state
= RPKI_NOT_BEING_USED
;
8552 /* Route status display. */
8553 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
8554 json_object_boolean_true_add(json_path
, "removed");
8556 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
8557 json_object_boolean_true_add(json_path
, "stale");
8559 if (path
->extra
&& bgp_path_suppressed(path
))
8560 json_object_boolean_true_add(json_path
, "suppressed");
8562 if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
8563 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
8564 json_object_boolean_true_add(json_path
, "valid");
8567 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
8568 json_object_boolean_true_add(json_path
, "history");
8570 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
8571 json_object_boolean_true_add(json_path
, "damped");
8573 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
8574 json_object_boolean_true_add(json_path
, "bestpath");
8575 json_object_string_add(json_path
, "selectionReason",
8576 bgp_path_selection_reason2str(
8577 path
->net
->reason
));
8580 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
8581 json_object_boolean_true_add(json_path
, "multipath");
8583 /* Internal route. */
8584 if ((path
->peer
->as
)
8585 && (path
->peer
->as
== path
->peer
->local_as
))
8586 json_object_string_add(json_path
, "pathFrom",
8589 json_object_string_add(json_path
, "pathFrom",
8595 /* RPKI validation state */
8597 hook_call(bgp_rpki_prefix_status
, path
->peer
, path
->attr
, p
);
8599 if (rpki_state
== RPKI_VALID
)
8601 else if (rpki_state
== RPKI_INVALID
)
8603 else if (rpki_state
== RPKI_NOTFOUND
)
8606 /* Route status display. */
8607 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
8609 else if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
8611 else if (bgp_path_suppressed(path
))
8613 else if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
8614 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
8620 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
8622 else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
8624 else if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
8626 else if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
8631 /* Internal route. */
8632 if (path
->peer
&& (path
->peer
->as
)
8633 && (path
->peer
->as
== path
->peer
->local_as
))
8639 static char *bgp_nexthop_hostname(struct peer
*peer
,
8640 struct bgp_nexthop_cache
*bnc
)
8643 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME
))
8644 return peer
->hostname
;
8648 /* called from terminal list command */
8649 void route_vty_out(struct vty
*vty
, const struct prefix
*p
,
8650 struct bgp_path_info
*path
, int display
, safi_t safi
,
8651 json_object
*json_paths
, bool wide
)
8654 struct attr
*attr
= path
->attr
;
8655 json_object
*json_path
= NULL
;
8656 json_object
*json_nexthops
= NULL
;
8657 json_object
*json_nexthop_global
= NULL
;
8658 json_object
*json_nexthop_ll
= NULL
;
8659 json_object
*json_ext_community
= NULL
;
8660 char vrf_id_str
[VRF_NAMSIZ
] = {0};
8662 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
8663 bool nexthop_othervrf
= false;
8664 vrf_id_t nexthop_vrfid
= VRF_DEFAULT
;
8665 const char *nexthop_vrfname
= VRF_DEFAULT_NAME
;
8666 char *nexthop_hostname
=
8667 bgp_nexthop_hostname(path
->peer
, path
->nexthop
);
8668 char esi_buf
[ESI_STR_LEN
];
8671 json_path
= json_object_new_object();
8673 /* short status lead text */
8674 route_vty_short_status_out(vty
, path
, p
, json_path
);
8677 /* print prefix and mask */
8679 route_vty_out_route(path
->net
, p
, vty
, json_path
, wide
);
8681 vty_out(vty
, "%*s", (wide
? 45 : 17), " ");
8683 route_vty_out_route(path
->net
, p
, vty
, json_path
, wide
);
8687 * If vrf id of nexthop is different from that of prefix,
8688 * set up printable string to append
8690 if (path
->extra
&& path
->extra
->bgp_orig
) {
8691 const char *self
= "";
8696 nexthop_othervrf
= true;
8697 nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
8699 if (path
->extra
->bgp_orig
->vrf_id
== VRF_UNKNOWN
)
8700 snprintf(vrf_id_str
, sizeof(vrf_id_str
),
8701 "@%s%s", VRFID_NONE_STR
, self
);
8703 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "@%u%s",
8704 path
->extra
->bgp_orig
->vrf_id
, self
);
8706 if (path
->extra
->bgp_orig
->inst_type
8707 != BGP_INSTANCE_TYPE_DEFAULT
)
8709 nexthop_vrfname
= path
->extra
->bgp_orig
->name
;
8711 const char *self
= "";
8716 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "%s", self
);
8720 * For ENCAP and EVPN routes, nexthop address family is not
8721 * neccessarily the same as the prefix address family.
8722 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
8723 * EVPN routes are also exchanged with a MP nexthop. Currently,
8725 * is only IPv4, the value will be present in either
8727 * attr->mp_nexthop_global_in
8729 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
8732 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
8736 snprintf(nexthop
, sizeof(nexthop
), "%s",
8737 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
8741 snprintf(nexthop
, sizeof(nexthop
), "%s",
8742 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
8746 snprintf(nexthop
, sizeof(nexthop
), "?");
8751 json_nexthop_global
= json_object_new_object();
8753 json_object_string_add(json_nexthop_global
, "ip",
8756 if (path
->peer
->hostname
)
8757 json_object_string_add(json_nexthop_global
,
8759 path
->peer
->hostname
);
8761 json_object_string_add(json_nexthop_global
, "afi",
8762 (af
== AF_INET
) ? "ipv4"
8764 json_object_boolean_true_add(json_nexthop_global
,
8767 if (nexthop_hostname
)
8768 len
= vty_out(vty
, "%s(%s)%s", nexthop
,
8769 nexthop_hostname
, vrf_id_str
);
8771 len
= vty_out(vty
, "%s%s", nexthop
, vrf_id_str
);
8773 len
= wide
? (41 - len
) : (16 - len
);
8775 vty_out(vty
, "\n%*s", 36, " ");
8777 vty_out(vty
, "%*s", len
, " ");
8779 } else if (safi
== SAFI_EVPN
) {
8781 char buf
[BUFSIZ
] = {0};
8783 json_nexthop_global
= json_object_new_object();
8785 json_object_string_add(json_nexthop_global
, "ip",
8787 &attr
->nexthop
, buf
,
8790 if (path
->peer
->hostname
)
8791 json_object_string_add(json_nexthop_global
,
8793 path
->peer
->hostname
);
8795 json_object_string_add(json_nexthop_global
, "afi",
8797 json_object_boolean_true_add(json_nexthop_global
,
8800 if (nexthop_hostname
)
8801 len
= vty_out(vty
, "%pI4(%s)%s", &attr
->nexthop
,
8802 nexthop_hostname
, vrf_id_str
);
8804 len
= vty_out(vty
, "%pI4%s", &attr
->nexthop
,
8807 len
= wide
? (41 - len
) : (16 - len
);
8809 vty_out(vty
, "\n%*s", 36, " ");
8811 vty_out(vty
, "%*s", len
, " ");
8813 } else if (safi
== SAFI_FLOWSPEC
) {
8814 if (attr
->nexthop
.s_addr
!= INADDR_ANY
) {
8816 char buf
[BUFSIZ
] = {0};
8818 json_nexthop_global
= json_object_new_object();
8820 json_object_string_add(json_nexthop_global
,
8822 json_object_string_add(
8823 json_nexthop_global
, "ip",
8824 inet_ntop(AF_INET
, &attr
->nexthop
, buf
,
8827 if (path
->peer
->hostname
)
8828 json_object_string_add(
8829 json_nexthop_global
, "hostname",
8830 path
->peer
->hostname
);
8832 json_object_boolean_true_add(
8833 json_nexthop_global
,
8836 if (nexthop_hostname
)
8837 len
= vty_out(vty
, "%pI4(%s)%s",
8842 len
= vty_out(vty
, "%pI4%s",
8846 len
= wide
? (41 - len
) : (16 - len
);
8848 vty_out(vty
, "\n%*s", 36, " ");
8850 vty_out(vty
, "%*s", len
, " ");
8853 } else if (p
->family
== AF_INET
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
8855 char buf
[BUFSIZ
] = {0};
8857 json_nexthop_global
= json_object_new_object();
8859 json_object_string_add(json_nexthop_global
, "ip",
8861 &attr
->nexthop
, buf
,
8864 if (path
->peer
->hostname
)
8865 json_object_string_add(json_nexthop_global
,
8867 path
->peer
->hostname
);
8869 json_object_string_add(json_nexthop_global
, "afi",
8871 json_object_boolean_true_add(json_nexthop_global
,
8874 if (nexthop_hostname
)
8875 len
= vty_out(vty
, "%pI4(%s)%s", &attr
->nexthop
,
8876 nexthop_hostname
, vrf_id_str
);
8878 len
= vty_out(vty
, "%pI4%s", &attr
->nexthop
,
8881 len
= wide
? (41 - len
) : (16 - len
);
8883 vty_out(vty
, "\n%*s", 36, " ");
8885 vty_out(vty
, "%*s", len
, " ");
8890 else if (p
->family
== AF_INET6
|| BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
8894 json_nexthop_global
= json_object_new_object();
8895 json_object_string_add(
8896 json_nexthop_global
, "ip",
8897 inet_ntop(AF_INET6
, &attr
->mp_nexthop_global
,
8900 if (path
->peer
->hostname
)
8901 json_object_string_add(json_nexthop_global
,
8903 path
->peer
->hostname
);
8905 json_object_string_add(json_nexthop_global
, "afi",
8907 json_object_string_add(json_nexthop_global
, "scope",
8910 /* We display both LL & GL if both have been
8912 if ((attr
->mp_nexthop_len
8913 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
8914 || (path
->peer
->conf_if
)) {
8915 json_nexthop_ll
= json_object_new_object();
8916 json_object_string_add(
8917 json_nexthop_ll
, "ip",
8919 &attr
->mp_nexthop_local
, buf
,
8922 if (path
->peer
->hostname
)
8923 json_object_string_add(
8924 json_nexthop_ll
, "hostname",
8925 path
->peer
->hostname
);
8927 json_object_string_add(json_nexthop_ll
, "afi",
8929 json_object_string_add(json_nexthop_ll
, "scope",
8932 if ((IPV6_ADDR_CMP(&attr
->mp_nexthop_global
,
8933 &attr
->mp_nexthop_local
)
8935 && !attr
->mp_nexthop_prefer_global
)
8936 json_object_boolean_true_add(
8937 json_nexthop_ll
, "used");
8939 json_object_boolean_true_add(
8940 json_nexthop_global
, "used");
8942 json_object_boolean_true_add(
8943 json_nexthop_global
, "used");
8945 /* Display LL if LL/Global both in table unless
8946 * prefer-global is set */
8947 if (((attr
->mp_nexthop_len
8948 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
8949 && !attr
->mp_nexthop_prefer_global
)
8950 || (path
->peer
->conf_if
)) {
8951 if (path
->peer
->conf_if
) {
8952 len
= vty_out(vty
, "%s",
8953 path
->peer
->conf_if
);
8954 /* len of IPv6 addr + max len of def
8956 len
= wide
? (41 - len
) : (16 - len
);
8959 vty_out(vty
, "\n%*s", 36, " ");
8961 vty_out(vty
, "%*s", len
, " ");
8963 if (nexthop_hostname
)
8966 &attr
->mp_nexthop_local
,
8972 &attr
->mp_nexthop_local
,
8975 len
= wide
? (41 - len
) : (16 - len
);
8978 vty_out(vty
, "\n%*s", 36, " ");
8980 vty_out(vty
, "%*s", len
, " ");
8983 if (nexthop_hostname
)
8984 len
= vty_out(vty
, "%pI6(%s)%s",
8985 &attr
->mp_nexthop_global
,
8989 len
= vty_out(vty
, "%pI6%s",
8990 &attr
->mp_nexthop_global
,
8993 len
= wide
? (41 - len
) : (16 - len
);
8996 vty_out(vty
, "\n%*s", 36, " ");
8998 vty_out(vty
, "%*s", len
, " ");
9004 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
9006 json_object_int_add(json_path
, "metric", attr
->med
);
9008 vty_out(vty
, "%7u", attr
->med
);
9010 vty_out(vty
, "%10u", attr
->med
);
9011 else if (!json_paths
) {
9013 vty_out(vty
, "%*s", 7, " ");
9015 vty_out(vty
, "%*s", 10, " ");
9019 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
9021 json_object_int_add(json_path
, "locPrf",
9024 vty_out(vty
, "%7u", attr
->local_pref
);
9025 else if (!json_paths
)
9029 json_object_int_add(json_path
, "weight", attr
->weight
);
9031 vty_out(vty
, "%7u ", attr
->weight
);
9035 json_object_string_add(
9036 json_path
, "peerId",
9037 sockunion2str(&path
->peer
->su
, buf
, SU_ADDRSTRLEN
));
9043 json_object_string_add(json_path
, "path",
9046 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
9051 json_object_string_add(json_path
, "origin",
9052 bgp_origin_long_str
[attr
->origin
]);
9054 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9057 if (bgp_evpn_is_esi_valid(&attr
->esi
)) {
9058 json_object_string_add(json_path
, "esi",
9059 esi_to_str(&attr
->esi
,
9060 esi_buf
, sizeof(esi_buf
)));
9062 if (safi
== SAFI_EVPN
&&
9063 attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
9064 json_ext_community
= json_object_new_object();
9065 json_object_string_add(json_ext_community
,
9067 attr
->ecommunity
->str
);
9068 json_object_object_add(json_path
,
9069 "extendedCommunity",
9070 json_ext_community
);
9074 json_object_boolean_true_add(json_path
,
9075 "announceNexthopSelf");
9076 if (nexthop_othervrf
) {
9077 json_object_string_add(json_path
, "nhVrfName",
9080 json_object_int_add(json_path
, "nhVrfId",
9081 ((nexthop_vrfid
== VRF_UNKNOWN
)
9083 : (int)nexthop_vrfid
));
9088 if (json_nexthop_global
|| json_nexthop_ll
) {
9089 json_nexthops
= json_object_new_array();
9091 if (json_nexthop_global
)
9092 json_object_array_add(json_nexthops
,
9093 json_nexthop_global
);
9095 if (json_nexthop_ll
)
9096 json_object_array_add(json_nexthops
,
9099 json_object_object_add(json_path
, "nexthops",
9103 json_object_array_add(json_paths
, json_path
);
9107 if (safi
== SAFI_EVPN
) {
9108 struct bgp_path_es_info
*path_es_info
= NULL
;
9110 if (bgp_evpn_is_esi_valid(&attr
->esi
)) {
9111 /* XXX - add these params to the json out */
9112 vty_out(vty
, "%*s", 20, " ");
9113 vty_out(vty
, "ESI:%s",
9114 esi_to_str(&attr
->esi
, esi_buf
,
9117 if (path
->extra
&& path
->extra
->mh_info
)
9119 path
->extra
->mh_info
->es_info
;
9121 if (path_es_info
&& path_es_info
->es
)
9122 vty_out(vty
, " VNI: %u",
9127 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
9128 vty_out(vty
, "%*s", 20, " ");
9129 vty_out(vty
, "%s\n", attr
->ecommunity
->str
);
9133 #ifdef ENABLE_BGP_VNC
9134 /* prints an additional line, indented, with VNC info, if
9136 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
9137 rfapi_vty_out_vncinfo(vty
, p
, path
, safi
);
9142 /* called from terminal list command */
9143 void route_vty_out_tmp(struct vty
*vty
, struct bgp_dest
*dest
,
9144 const struct prefix
*p
, struct attr
*attr
, safi_t safi
,
9145 bool use_json
, json_object
*json_ar
, bool wide
)
9147 json_object
*json_status
= NULL
;
9148 json_object
*json_net
= NULL
;
9152 /* Route status display. */
9154 json_status
= json_object_new_object();
9155 json_net
= json_object_new_object();
9162 /* print prefix and mask */
9164 if (safi
== SAFI_EVPN
)
9165 bgp_evpn_route2json((struct prefix_evpn
*)p
, json_net
);
9166 else if (p
->family
== AF_INET
|| p
->family
== AF_INET6
) {
9167 json_object_string_add(
9168 json_net
, "addrPrefix",
9169 inet_ntop(p
->family
, &p
->u
.prefix
, buff
,
9171 json_object_int_add(json_net
, "prefixLen",
9173 prefix2str(p
, buff
, PREFIX_STRLEN
);
9174 json_object_string_add(json_net
, "network", buff
);
9177 route_vty_out_route(dest
, p
, vty
, NULL
, wide
);
9179 /* Print attribute */
9182 char buf
[BUFSIZ
] = {0};
9184 if (p
->family
== AF_INET
9185 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
9186 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
9187 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
9188 json_object_string_add(
9189 json_net
, "nextHop",
9192 &attr
->mp_nexthop_global_in
,
9195 json_object_string_add(
9196 json_net
, "nextHop",
9198 &attr
->nexthop
, buf
,
9200 } else if (p
->family
== AF_INET6
9201 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
9204 json_object_string_add(
9205 json_net
, "nextHopGlobal",
9207 &attr
->mp_nexthop_global
, buf
,
9209 } else if (p
->family
== AF_EVPN
9210 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
9211 char buf
[BUFSIZ
] = {0};
9213 json_object_string_add(
9214 json_net
, "nextHop",
9216 &attr
->mp_nexthop_global_in
,
9221 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
9222 json_object_int_add(json_net
, "metric",
9225 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
9226 json_object_int_add(json_net
, "locPrf",
9229 json_object_int_add(json_net
, "weight", attr
->weight
);
9233 json_object_string_add(json_net
, "path",
9237 json_object_string_add(json_net
, "bgpOriginCode",
9238 bgp_origin_str
[attr
->origin
]);
9240 if (p
->family
== AF_INET
9241 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
9242 || safi
== SAFI_EVPN
9243 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
9244 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
9245 || safi
== SAFI_EVPN
)
9246 vty_out(vty
, "%-16pI4",
9247 &attr
->mp_nexthop_global_in
);
9249 vty_out(vty
, "%-41pI4", &attr
->nexthop
);
9251 vty_out(vty
, "%-16pI4", &attr
->nexthop
);
9252 } else if (p
->family
== AF_INET6
9253 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
9259 &attr
->mp_nexthop_global
, buf
,
9261 len
= wide
? (41 - len
) : (16 - len
);
9263 vty_out(vty
, "\n%*s", 36, " ");
9265 vty_out(vty
, "%*s", len
, " ");
9268 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
9270 vty_out(vty
, "%7u", attr
->med
);
9272 vty_out(vty
, "%10u", attr
->med
);
9278 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
9279 vty_out(vty
, "%7u", attr
->local_pref
);
9283 vty_out(vty
, "%7u ", attr
->weight
);
9287 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
9290 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9294 json_object_boolean_true_add(json_status
, "*");
9295 json_object_boolean_true_add(json_status
, ">");
9296 json_object_object_add(json_net
, "appliedStatusSymbols",
9299 prefix2str(p
, buff
, PREFIX_STRLEN
);
9300 json_object_object_add(json_ar
, buff
, json_net
);
9305 void route_vty_out_tag(struct vty
*vty
, const struct prefix
*p
,
9306 struct bgp_path_info
*path
, int display
, safi_t safi
,
9309 json_object
*json_out
= NULL
;
9311 mpls_label_t label
= MPLS_INVALID_LABEL
;
9317 json_out
= json_object_new_object();
9319 /* short status lead text */
9320 route_vty_short_status_out(vty
, path
, p
, json_out
);
9322 /* print prefix and mask */
9325 route_vty_out_route(path
->net
, p
, vty
, NULL
, false);
9327 vty_out(vty
, "%*s", 17, " ");
9330 /* Print attribute */
9332 if (((p
->family
== AF_INET
)
9333 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
9334 || (safi
== SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
9335 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
9336 char buf
[BUFSIZ
] = {0};
9338 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
9339 || safi
== SAFI_EVPN
) {
9341 json_object_string_add(
9342 json_out
, "mpNexthopGlobalIn",
9344 &attr
->mp_nexthop_global_in
,
9347 vty_out(vty
, "%-16pI4",
9348 &attr
->mp_nexthop_global_in
);
9351 json_object_string_add(
9352 json_out
, "nexthop",
9353 inet_ntop(AF_INET
, &attr
->nexthop
, buf
,
9356 vty_out(vty
, "%-16pI4", &attr
->nexthop
);
9358 } else if (((p
->family
== AF_INET6
)
9359 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
9360 || (safi
== SAFI_EVPN
&& BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
9361 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
9364 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
9366 json_object_string_add(
9367 json_out
, "mpNexthopGlobalIn",
9369 &attr
->mp_nexthop_global
,
9370 buf_a
, sizeof(buf_a
)));
9374 &attr
->mp_nexthop_global
,
9375 buf_a
, sizeof(buf_a
)));
9376 } else if (attr
->mp_nexthop_len
9377 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
9378 snprintfrr(buf_a
, sizeof(buf_a
), "%pI6(%pI6)",
9379 &attr
->mp_nexthop_global
,
9380 &attr
->mp_nexthop_local
);
9382 json_object_string_add(json_out
,
9383 "mpNexthopGlobalLocal",
9386 vty_out(vty
, "%s", buf_a
);
9390 label
= decode_label(&path
->extra
->label
[0]);
9392 if (bgp_is_valid_label(&label
)) {
9394 json_object_int_add(json_out
, "notag", label
);
9395 json_object_array_add(json
, json_out
);
9397 vty_out(vty
, "notag/%d", label
);
9403 void route_vty_out_overlay(struct vty
*vty
, const struct prefix
*p
,
9404 struct bgp_path_info
*path
, int display
,
9405 json_object
*json_paths
)
9408 char buf
[BUFSIZ
] = {0};
9409 json_object
*json_path
= NULL
;
9410 json_object
*json_nexthop
= NULL
;
9411 json_object
*json_overlay
= NULL
;
9417 json_path
= json_object_new_object();
9418 json_overlay
= json_object_new_object();
9419 json_nexthop
= json_object_new_object();
9422 /* short status lead text */
9423 route_vty_short_status_out(vty
, path
, p
, json_path
);
9425 /* print prefix and mask */
9427 route_vty_out_route(path
->net
, p
, vty
, json_path
, false);
9429 vty_out(vty
, "%*s", 17, " ");
9431 /* Print attribute */
9434 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
9438 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
, BUFSIZ
);
9440 vty_out(vty
, "%-16s", buf
);
9442 json_object_string_add(json_nexthop
, "ip", buf
);
9444 json_object_string_add(json_nexthop
, "afi", "ipv4");
9446 json_object_object_add(json_path
, "nexthop",
9451 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
, BUFSIZ
);
9452 inet_ntop(af
, &attr
->mp_nexthop_local
, buf1
, BUFSIZ
);
9454 vty_out(vty
, "%s(%s)", buf
, buf1
);
9456 json_object_string_add(json_nexthop
, "ipv6Global", buf
);
9458 json_object_string_add(json_nexthop
, "ipv6LinkLocal",
9461 json_object_string_add(json_nexthop
, "afi", "ipv6");
9463 json_object_object_add(json_path
, "nexthop",
9471 json_object_string_add(json_nexthop
, "Error",
9472 "Unsupported address-family");
9476 const struct bgp_route_evpn
*eo
= bgp_attr_get_evpn_overlay(attr
);
9478 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn
*)p
))
9479 inet_ntop(AF_INET
, &eo
->gw_ip
.ipv4
, buf
, BUFSIZ
);
9480 else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn
*)p
))
9481 inet_ntop(AF_INET6
, &eo
->gw_ip
.ipv6
, buf
, BUFSIZ
);
9484 vty_out(vty
, "/%s", buf
);
9486 json_object_string_add(json_overlay
, "gw", buf
);
9488 if (attr
->ecommunity
) {
9490 struct ecommunity_val
*routermac
= ecommunity_lookup(
9491 attr
->ecommunity
, ECOMMUNITY_ENCODE_EVPN
,
9492 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
9495 mac
= ecom_mac2str((char *)routermac
->val
);
9498 vty_out(vty
, "/%s", mac
);
9500 json_object_string_add(json_overlay
, "rmac",
9503 XFREE(MTYPE_TMP
, mac
);
9510 json_object_object_add(json_path
, "overlay", json_overlay
);
9512 json_object_array_add(json_paths
, json_path
);
9516 /* dampening route */
9517 static void damp_route_vty_out(struct vty
*vty
, const struct prefix
*p
,
9518 struct bgp_path_info
*path
, int display
,
9519 afi_t afi
, safi_t safi
, bool use_json
,
9524 char timebuf
[BGP_UPTIME_LEN
];
9526 /* short status lead text */
9527 route_vty_short_status_out(vty
, path
, p
, json
);
9529 /* print prefix and mask */
9532 route_vty_out_route(path
->net
, p
, vty
, NULL
, false);
9534 vty_out(vty
, "%*s", 17, " ");
9537 len
= vty_out(vty
, "%s", path
->peer
->host
);
9541 vty_out(vty
, "\n%*s", 34, " ");
9544 json_object_int_add(json
, "peerHost", len
);
9546 vty_out(vty
, "%*s", len
, " ");
9550 bgp_damp_reuse_time_vty(vty
, path
, timebuf
, BGP_UPTIME_LEN
, afi
,
9551 safi
, use_json
, json
);
9554 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
9555 BGP_UPTIME_LEN
, afi
, safi
,
9558 /* Print attribute */
9564 json_object_string_add(json
, "asPath",
9567 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
9572 json_object_string_add(json
, "origin",
9573 bgp_origin_str
[attr
->origin
]);
9575 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9582 static void flap_route_vty_out(struct vty
*vty
, const struct prefix
*p
,
9583 struct bgp_path_info
*path
, int display
,
9584 afi_t afi
, safi_t safi
, bool use_json
,
9588 struct bgp_damp_info
*bdi
;
9589 char timebuf
[BGP_UPTIME_LEN
];
9595 bdi
= path
->extra
->damp_info
;
9597 /* short status lead text */
9598 route_vty_short_status_out(vty
, path
, p
, json
);
9600 /* print prefix and mask */
9603 route_vty_out_route(path
->net
, p
, vty
, NULL
, false);
9605 vty_out(vty
, "%*s", 17, " ");
9608 len
= vty_out(vty
, "%s", path
->peer
->host
);
9612 vty_out(vty
, "\n%*s", 33, " ");
9615 json_object_int_add(json
, "peerHost", len
);
9617 vty_out(vty
, "%*s", len
, " ");
9620 len
= vty_out(vty
, "%d", bdi
->flap
);
9627 json_object_int_add(json
, "bdiFlap", len
);
9629 vty_out(vty
, "%*s", len
, " ");
9633 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
9636 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
9637 BGP_UPTIME_LEN
, 0, NULL
));
9639 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
9640 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
9642 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
9643 BGP_UPTIME_LEN
, afi
, safi
,
9647 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
9648 BGP_UPTIME_LEN
, afi
,
9649 safi
, use_json
, json
));
9652 vty_out(vty
, "%*s ", 8, " ");
9655 /* Print attribute */
9661 json_object_string_add(json
, "asPath",
9664 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
9669 json_object_string_add(json
, "origin",
9670 bgp_origin_str
[attr
->origin
]);
9672 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9678 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
9679 int *first
, const char *header
,
9680 json_object
*json_adv_to
)
9682 char buf1
[INET6_ADDRSTRLEN
];
9683 json_object
*json_peer
= NULL
;
9686 /* 'advertised-to' is a dictionary of peers we have advertised
9688 * prefix too. The key is the peer's IP or swpX, the value is
9690 * hostname if we know it and "" if not.
9692 json_peer
= json_object_new_object();
9695 json_object_string_add(json_peer
, "hostname",
9699 json_object_object_add(json_adv_to
, peer
->conf_if
,
9702 json_object_object_add(
9704 sockunion2str(&peer
->su
, buf1
, SU_ADDRSTRLEN
),
9708 vty_out(vty
, "%s", header
);
9713 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_HOSTNAME
)) {
9715 vty_out(vty
, " %s(%s)", peer
->hostname
,
9718 vty_out(vty
, " %s(%s)", peer
->hostname
,
9719 sockunion2str(&peer
->su
, buf1
,
9723 vty_out(vty
, " %s", peer
->conf_if
);
9726 sockunion2str(&peer
->su
, buf1
,
9732 static void route_vty_out_tx_ids(struct vty
*vty
,
9733 struct bgp_addpath_info_data
*d
)
9737 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
9738 vty_out(vty
, "TX-%s %u%s", bgp_addpath_names(i
)->human_name
,
9739 d
->addpath_tx_id
[i
],
9740 i
< BGP_ADDPATH_MAX
- 1 ? " " : "\n");
9744 static void route_vty_out_detail_es_info(struct vty
*vty
,
9745 struct bgp_path_info
*pi
,
9747 json_object
*json_path
)
9749 char esi_buf
[ESI_STR_LEN
];
9750 bool es_local
= !!CHECK_FLAG(attr
->es_flags
, ATTR_ES_IS_LOCAL
);
9751 bool peer_router
= !!CHECK_FLAG(attr
->es_flags
,
9752 ATTR_ES_PEER_ROUTER
);
9753 bool peer_active
= !!CHECK_FLAG(attr
->es_flags
,
9754 ATTR_ES_PEER_ACTIVE
);
9755 bool peer_proxy
= !!CHECK_FLAG(attr
->es_flags
,
9756 ATTR_ES_PEER_PROXY
);
9757 esi_to_str(&attr
->esi
, esi_buf
, sizeof(esi_buf
));
9759 json_object
*json_es_info
= NULL
;
9761 json_object_string_add(
9764 if (es_local
|| bgp_evpn_attr_is_sync(attr
)) {
9765 json_es_info
= json_object_new_object();
9767 json_object_boolean_true_add(
9768 json_es_info
, "localEs");
9770 json_object_boolean_true_add(
9771 json_es_info
, "peerActive");
9773 json_object_boolean_true_add(
9774 json_es_info
, "peerProxy");
9776 json_object_boolean_true_add(
9777 json_es_info
, "peerRouter");
9778 if (attr
->mm_sync_seqnum
)
9779 json_object_int_add(
9780 json_es_info
, "peerSeq",
9781 attr
->mm_sync_seqnum
);
9782 json_object_object_add(
9783 json_path
, "es_info",
9787 if (bgp_evpn_attr_is_sync(attr
))
9789 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
9791 es_local
? "local-es":"",
9792 peer_proxy
? "proxy " : "",
9793 peer_active
? "active ":"",
9794 peer_router
? "router ":"",
9795 attr
->mm_sync_seqnum
);
9797 vty_out(vty
, " ESI %s %s\n",
9799 es_local
? "local-es":"");
9803 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
, struct bgp_dest
*bn
,
9804 struct bgp_path_info
*path
, afi_t afi
, safi_t safi
,
9805 enum rpki_states rpki_curr_state
,
9806 json_object
*json_paths
)
9808 char buf
[INET6_ADDRSTRLEN
];
9810 struct attr
*attr
= path
->attr
;
9811 int sockunion_vty_out(struct vty
*, union sockunion
*);
9813 json_object
*json_bestpath
= NULL
;
9814 json_object
*json_cluster_list
= NULL
;
9815 json_object
*json_cluster_list_list
= NULL
;
9816 json_object
*json_ext_community
= NULL
;
9817 json_object
*json_last_update
= NULL
;
9818 json_object
*json_pmsi
= NULL
;
9819 json_object
*json_nexthop_global
= NULL
;
9820 json_object
*json_nexthop_ll
= NULL
;
9821 json_object
*json_nexthops
= NULL
;
9822 json_object
*json_path
= NULL
;
9823 json_object
*json_peer
= NULL
;
9824 json_object
*json_string
= NULL
;
9825 json_object
*json_adv_to
= NULL
;
9827 struct listnode
*node
, *nnode
;
9829 int addpath_capable
;
9831 unsigned int first_as
;
9833 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
9835 char *nexthop_hostname
=
9836 bgp_nexthop_hostname(path
->peer
, path
->nexthop
);
9839 json_path
= json_object_new_object();
9840 json_peer
= json_object_new_object();
9841 json_nexthop_global
= json_object_new_object();
9844 if (safi
== SAFI_EVPN
) {
9846 vty_out(vty
, " Route %pRN", bn
);
9853 if (path
->extra
&& path
->extra
->num_labels
) {
9854 bgp_evpn_label2str(path
->extra
->label
,
9855 path
->extra
->num_labels
, tag_buf
,
9858 if (safi
== SAFI_EVPN
) {
9860 if (tag_buf
[0] != '\0')
9861 vty_out(vty
, " VNI %s", tag_buf
);
9864 json_object_string_add(json_path
, "VNI",
9869 if (path
->extra
&& path
->extra
->parent
&& !json_paths
) {
9870 struct bgp_path_info
*parent_ri
;
9871 struct bgp_dest
*dest
, *pdest
;
9873 parent_ri
= (struct bgp_path_info
*)path
->extra
->parent
;
9874 dest
= parent_ri
->net
;
9875 if (dest
&& dest
->pdest
) {
9876 pdest
= dest
->pdest
;
9878 (struct prefix_rd
*)bgp_dest_get_prefix(
9880 buf1
, sizeof(buf1
));
9881 if (is_pi_family_evpn(parent_ri
)) {
9883 " Imported from %s:%pFX, VNI %s",
9885 (struct prefix_evpn
*)
9886 bgp_dest_get_prefix(
9889 if (attr
->es_flags
& ATTR_ES_L3_NHG
)
9890 vty_out(vty
, ", L3NHG %s",
9892 & ATTR_ES_L3_NHG_ACTIVE
)
9899 " Imported from %s:%pFX\n",
9901 (struct prefix_evpn
*)
9902 bgp_dest_get_prefix(
9908 if (safi
== SAFI_EVPN
9909 && attr
->evpn_overlay
.type
== OVERLAY_INDEX_GATEWAY_IP
) {
9910 char gwip_buf
[INET6_ADDRSTRLEN
];
9912 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn
*)&bn
->p
))
9913 inet_ntop(AF_INET
, &attr
->evpn_overlay
.gw_ip
.ipv4
,
9914 gwip_buf
, sizeof(gwip_buf
));
9916 inet_ntop(AF_INET6
, &attr
->evpn_overlay
.gw_ip
.ipv6
,
9917 gwip_buf
, sizeof(gwip_buf
));
9920 json_object_string_add(json_path
, "gatewayIP",
9923 vty_out(vty
, " Gateway IP %s", gwip_buf
);
9926 if (safi
== SAFI_EVPN
)
9929 /* Line1 display AS-path, Aggregator */
9932 if (!attr
->aspath
->json
)
9933 aspath_str_update(attr
->aspath
, true);
9934 json_object_lock(attr
->aspath
->json
);
9935 json_object_object_add(json_path
, "aspath",
9936 attr
->aspath
->json
);
9938 if (attr
->aspath
->segments
)
9939 aspath_print_vty(vty
, " %s", attr
->aspath
, "");
9941 vty_out(vty
, " Local");
9945 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
)) {
9947 json_object_boolean_true_add(json_path
, "removed");
9949 vty_out(vty
, ", (removed)");
9952 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
9954 json_object_boolean_true_add(json_path
, "stale");
9956 vty_out(vty
, ", (stale)");
9959 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
9961 char buf
[BUFSIZ
] = {0};
9963 json_object_int_add(json_path
, "aggregatorAs",
9964 attr
->aggregator_as
);
9965 json_object_string_add(json_path
, "aggregatorId",
9967 &attr
->aggregator_addr
,
9970 vty_out(vty
, ", (aggregated by %u %pI4)",
9971 attr
->aggregator_as
, &attr
->aggregator_addr
);
9975 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
9976 PEER_FLAG_REFLECTOR_CLIENT
)) {
9978 json_object_boolean_true_add(json_path
,
9979 "rxedFromRrClient");
9981 vty_out(vty
, ", (Received from a RR-client)");
9984 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
9985 PEER_FLAG_RSERVER_CLIENT
)) {
9987 json_object_boolean_true_add(json_path
,
9988 "rxedFromRsClient");
9990 vty_out(vty
, ", (Received from a RS-client)");
9993 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
9995 json_object_boolean_true_add(json_path
,
9996 "dampeningHistoryEntry");
9998 vty_out(vty
, ", (history entry)");
9999 } else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)) {
10001 json_object_boolean_true_add(json_path
,
10002 "dampeningSuppressed");
10004 vty_out(vty
, ", (suppressed due to dampening)");
10008 vty_out(vty
, "\n");
10010 /* Line2 display Next-hop, Neighbor, Router-id */
10011 /* Display the nexthop */
10012 const struct prefix
*bn_p
= bgp_dest_get_prefix(bn
);
10014 if ((bn_p
->family
== AF_INET
|| bn_p
->family
== AF_ETHERNET
10015 || bn_p
->family
== AF_EVPN
)
10016 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
10017 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
10018 char buf
[BUFSIZ
] = {0};
10020 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
10021 || safi
== SAFI_EVPN
) {
10023 json_object_string_add(
10024 json_nexthop_global
, "ip",
10026 &attr
->mp_nexthop_global_in
,
10027 buf
, sizeof(buf
)));
10029 if (path
->peer
->hostname
)
10030 json_object_string_add(
10031 json_nexthop_global
, "hostname",
10032 path
->peer
->hostname
);
10034 if (nexthop_hostname
)
10035 vty_out(vty
, " %pI4(%s)",
10036 &attr
->mp_nexthop_global_in
,
10039 vty_out(vty
, " %pI4",
10040 &attr
->mp_nexthop_global_in
);
10044 json_object_string_add(
10045 json_nexthop_global
, "ip",
10046 inet_ntop(AF_INET
, &attr
->nexthop
, buf
,
10049 if (path
->peer
->hostname
)
10050 json_object_string_add(
10051 json_nexthop_global
, "hostname",
10052 path
->peer
->hostname
);
10054 if (nexthop_hostname
)
10055 vty_out(vty
, " %pI4(%s)",
10059 vty_out(vty
, " %pI4",
10065 json_object_string_add(json_nexthop_global
, "afi",
10069 json_object_string_add(
10070 json_nexthop_global
, "ip",
10071 inet_ntop(AF_INET6
, &attr
->mp_nexthop_global
,
10072 buf
, INET6_ADDRSTRLEN
));
10074 if (path
->peer
->hostname
)
10075 json_object_string_add(json_nexthop_global
,
10077 path
->peer
->hostname
);
10079 json_object_string_add(json_nexthop_global
, "afi",
10081 json_object_string_add(json_nexthop_global
, "scope",
10084 if (nexthop_hostname
)
10085 vty_out(vty
, " %pI6(%s)",
10086 &attr
->mp_nexthop_global
,
10089 vty_out(vty
, " %pI6",
10090 &attr
->mp_nexthop_global
);
10094 /* Display the IGP cost or 'inaccessible' */
10095 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
10097 json_object_boolean_false_add(json_nexthop_global
,
10100 vty_out(vty
, " (inaccessible)");
10102 if (path
->extra
&& path
->extra
->igpmetric
) {
10104 json_object_int_add(json_nexthop_global
,
10106 path
->extra
->igpmetric
);
10108 vty_out(vty
, " (metric %u)",
10109 path
->extra
->igpmetric
);
10112 /* IGP cost is 0, display this only for json */
10115 json_object_int_add(json_nexthop_global
,
10120 json_object_boolean_true_add(json_nexthop_global
,
10124 /* Display peer "from" output */
10125 /* This path was originated locally */
10126 if (path
->peer
== bgp
->peer_self
) {
10128 if (safi
== SAFI_EVPN
10129 || (bn_p
->family
== AF_INET
10130 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
10132 json_object_string_add(json_peer
, "peerId",
10135 vty_out(vty
, " from 0.0.0.0 ");
10138 json_object_string_add(json_peer
, "peerId",
10141 vty_out(vty
, " from :: ");
10145 char buf
[BUFSIZ
] = {0};
10147 json_object_string_add(json_peer
, "routerId",
10149 &bgp
->router_id
, buf
,
10152 vty_out(vty
, "(%pI4)", &bgp
->router_id
);
10156 /* We RXed this path from one of our peers */
10160 json_object_string_add(json_peer
, "peerId",
10161 sockunion2str(&path
->peer
->su
,
10164 json_object_string_add(json_peer
, "routerId",
10166 &path
->peer
->remote_id
,
10167 buf1
, sizeof(buf1
)));
10169 if (path
->peer
->hostname
)
10170 json_object_string_add(json_peer
, "hostname",
10171 path
->peer
->hostname
);
10173 if (path
->peer
->domainname
)
10174 json_object_string_add(json_peer
, "domainname",
10175 path
->peer
->domainname
);
10177 if (path
->peer
->conf_if
)
10178 json_object_string_add(json_peer
, "interface",
10179 path
->peer
->conf_if
);
10181 if (path
->peer
->conf_if
) {
10182 if (path
->peer
->hostname
10183 && CHECK_FLAG(path
->peer
->bgp
->flags
,
10184 BGP_FLAG_SHOW_HOSTNAME
))
10185 vty_out(vty
, " from %s(%s)",
10186 path
->peer
->hostname
,
10187 path
->peer
->conf_if
);
10189 vty_out(vty
, " from %s",
10190 path
->peer
->conf_if
);
10192 if (path
->peer
->hostname
10193 && CHECK_FLAG(path
->peer
->bgp
->flags
,
10194 BGP_FLAG_SHOW_HOSTNAME
))
10195 vty_out(vty
, " from %s(%s)",
10196 path
->peer
->hostname
,
10199 vty_out(vty
, " from %s",
10200 sockunion2str(&path
->peer
->su
,
10205 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
10206 vty_out(vty
, " (%pI4)", &attr
->originator_id
);
10208 vty_out(vty
, " (%s)",
10210 &path
->peer
->remote_id
, buf1
,
10216 * Note when vrfid of nexthop is different from that of prefix
10218 if (path
->extra
&& path
->extra
->bgp_orig
) {
10219 vrf_id_t nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
10224 if (path
->extra
->bgp_orig
->inst_type
10225 == BGP_INSTANCE_TYPE_DEFAULT
)
10226 vn
= VRF_DEFAULT_NAME
;
10228 vn
= path
->extra
->bgp_orig
->name
;
10230 json_object_string_add(json_path
, "nhVrfName", vn
);
10232 if (nexthop_vrfid
== VRF_UNKNOWN
) {
10233 json_object_int_add(json_path
, "nhVrfId", -1);
10235 json_object_int_add(json_path
, "nhVrfId",
10236 (int)nexthop_vrfid
);
10239 if (nexthop_vrfid
== VRF_UNKNOWN
)
10240 vty_out(vty
, " vrf ?");
10244 vrf
= vrf_lookup_by_id(nexthop_vrfid
);
10245 vty_out(vty
, " vrf %s(%u)",
10246 VRF_LOGNAME(vrf
), nexthop_vrfid
);
10251 if (nexthop_self
) {
10253 json_object_boolean_true_add(json_path
,
10254 "announceNexthopSelf");
10256 vty_out(vty
, " announce-nh-self");
10261 vty_out(vty
, "\n");
10263 /* display the link-local nexthop */
10264 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
10266 json_nexthop_ll
= json_object_new_object();
10267 json_object_string_add(
10268 json_nexthop_ll
, "ip",
10269 inet_ntop(AF_INET6
, &attr
->mp_nexthop_local
,
10270 buf
, INET6_ADDRSTRLEN
));
10272 if (path
->peer
->hostname
)
10273 json_object_string_add(json_nexthop_ll
,
10275 path
->peer
->hostname
);
10277 json_object_string_add(json_nexthop_ll
, "afi", "ipv6");
10278 json_object_string_add(json_nexthop_ll
, "scope",
10281 json_object_boolean_true_add(json_nexthop_ll
,
10284 if (!attr
->mp_nexthop_prefer_global
)
10285 json_object_boolean_true_add(json_nexthop_ll
,
10288 json_object_boolean_true_add(
10289 json_nexthop_global
, "used");
10291 vty_out(vty
, " (%s) %s\n",
10292 inet_ntop(AF_INET6
, &attr
->mp_nexthop_local
,
10293 buf
, INET6_ADDRSTRLEN
),
10294 attr
->mp_nexthop_prefer_global
10295 ? "(prefer-global)"
10299 /* If we do not have a link-local nexthop then we must flag the
10300 global as "used" */
10303 json_object_boolean_true_add(json_nexthop_global
,
10307 if (safi
== SAFI_EVPN
&&
10308 bgp_evpn_is_esi_valid(&attr
->esi
)) {
10309 route_vty_out_detail_es_info(vty
, path
, attr
, json_path
);
10312 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
10313 * Int/Ext/Local, Atomic, best */
10315 json_object_string_add(json_path
, "origin",
10316 bgp_origin_long_str
[attr
->origin
]);
10318 vty_out(vty
, " Origin %s",
10319 bgp_origin_long_str
[attr
->origin
]);
10321 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
10323 json_object_int_add(json_path
, "metric", attr
->med
);
10325 vty_out(vty
, ", metric %u", attr
->med
);
10328 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
10330 json_object_int_add(json_path
, "locPrf",
10333 vty_out(vty
, ", localpref %u", attr
->local_pref
);
10336 if (attr
->weight
!= 0) {
10338 json_object_int_add(json_path
, "weight", attr
->weight
);
10340 vty_out(vty
, ", weight %u", attr
->weight
);
10343 if (attr
->tag
!= 0) {
10345 json_object_int_add(json_path
, "tag", attr
->tag
);
10347 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
, attr
->tag
);
10350 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
10352 json_object_boolean_false_add(json_path
, "valid");
10354 vty_out(vty
, ", invalid");
10355 } else if (!CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
10357 json_object_boolean_true_add(json_path
, "valid");
10359 vty_out(vty
, ", valid");
10363 json_object_int_add(json_path
, "version", bn
->version
);
10365 if (path
->peer
!= bgp
->peer_self
) {
10366 if (path
->peer
->as
== path
->peer
->local_as
) {
10367 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
10369 json_object_string_add(
10371 "confed-internal");
10373 vty_out(vty
, ", confed-internal");
10376 json_object_string_add(
10377 json_peer
, "type", "internal");
10379 vty_out(vty
, ", internal");
10382 if (bgp_confederation_peers_check(bgp
,
10385 json_object_string_add(
10387 "confed-external");
10389 vty_out(vty
, ", confed-external");
10392 json_object_string_add(
10393 json_peer
, "type", "external");
10395 vty_out(vty
, ", external");
10398 } else if (path
->sub_type
== BGP_ROUTE_AGGREGATE
) {
10400 json_object_boolean_true_add(json_path
, "aggregated");
10401 json_object_boolean_true_add(json_path
, "local");
10403 vty_out(vty
, ", aggregated, local");
10405 } else if (path
->type
!= ZEBRA_ROUTE_BGP
) {
10407 json_object_boolean_true_add(json_path
, "sourced");
10409 vty_out(vty
, ", sourced");
10412 json_object_boolean_true_add(json_path
, "sourced");
10413 json_object_boolean_true_add(json_path
, "local");
10415 vty_out(vty
, ", sourced, local");
10419 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
10421 json_object_boolean_true_add(json_path
,
10422 "atomicAggregate");
10424 vty_out(vty
, ", atomic-aggregate");
10427 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
)
10428 || (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)
10429 && bgp_path_info_mpath_count(path
))) {
10431 json_object_boolean_true_add(json_path
, "multipath");
10433 vty_out(vty
, ", multipath");
10436 // Mark the bestpath(s)
10437 if (CHECK_FLAG(path
->flags
, BGP_PATH_DMED_SELECTED
)) {
10438 first_as
= aspath_get_first_as(attr
->aspath
);
10441 if (!json_bestpath
)
10442 json_bestpath
= json_object_new_object();
10443 json_object_int_add(json_bestpath
, "bestpathFromAs",
10447 vty_out(vty
, ", bestpath-from-AS %u", first_as
);
10449 vty_out(vty
, ", bestpath-from-AS Local");
10453 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
10455 if (!json_bestpath
)
10456 json_bestpath
= json_object_new_object();
10457 json_object_boolean_true_add(json_bestpath
, "overall");
10458 json_object_string_add(
10459 json_bestpath
, "selectionReason",
10460 bgp_path_selection_reason2str(bn
->reason
));
10462 vty_out(vty
, ", best");
10463 vty_out(vty
, " (%s)",
10464 bgp_path_selection_reason2str(bn
->reason
));
10468 if (rpki_curr_state
!= RPKI_NOT_BEING_USED
) {
10470 json_object_string_add(
10471 json_path
, "rpkiValidationState",
10472 bgp_rpki_validation2str(rpki_curr_state
));
10474 vty_out(vty
, ", rpki validation-state: %s",
10475 bgp_rpki_validation2str(rpki_curr_state
));
10479 json_object_object_add(json_path
, "bestpath", json_bestpath
);
10482 vty_out(vty
, "\n");
10484 /* Line 4 display Community */
10485 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
)) {
10487 if (!attr
->community
->json
)
10488 community_str(attr
->community
, true);
10489 json_object_lock(attr
->community
->json
);
10490 json_object_object_add(json_path
, "community",
10491 attr
->community
->json
);
10493 vty_out(vty
, " Community: %s\n",
10494 attr
->community
->str
);
10498 /* Line 5 display Extended-community */
10499 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
10501 json_ext_community
= json_object_new_object();
10502 json_object_string_add(json_ext_community
, "string",
10503 attr
->ecommunity
->str
);
10504 json_object_object_add(json_path
, "extendedCommunity",
10505 json_ext_community
);
10507 vty_out(vty
, " Extended Community: %s\n",
10508 attr
->ecommunity
->str
);
10512 /* Line 6 display Large community */
10513 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
10515 if (!attr
->lcommunity
->json
)
10516 lcommunity_str(attr
->lcommunity
, true);
10517 json_object_lock(attr
->lcommunity
->json
);
10518 json_object_object_add(json_path
, "largeCommunity",
10519 attr
->lcommunity
->json
);
10521 vty_out(vty
, " Large Community: %s\n",
10522 attr
->lcommunity
->str
);
10526 /* Line 7 display Originator, Cluster-id */
10527 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
10528 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
10529 char buf
[BUFSIZ
] = {0};
10531 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
10533 json_object_string_add(
10534 json_path
, "originatorId",
10535 inet_ntop(AF_INET
, &attr
->originator_id
,
10536 buf
, sizeof(buf
)));
10538 vty_out(vty
, " Originator: %pI4",
10539 &attr
->originator_id
);
10542 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
10543 struct cluster_list
*cluster
=
10544 bgp_attr_get_cluster(attr
);
10548 json_cluster_list
= json_object_new_object();
10549 json_cluster_list_list
=
10550 json_object_new_array();
10552 for (i
= 0; i
< cluster
->length
/ 4; i
++) {
10553 json_string
= json_object_new_string(
10556 buf
, sizeof(buf
)));
10557 json_object_array_add(
10558 json_cluster_list_list
,
10563 * struct cluster_list does not have
10564 * "str" variable like aspath and community
10565 * do. Add this someday if someone asks
10567 * json_object_string_add(json_cluster_list,
10568 * "string", cluster->str);
10570 json_object_object_add(json_cluster_list
,
10572 json_cluster_list_list
);
10573 json_object_object_add(json_path
, "clusterList",
10574 json_cluster_list
);
10576 vty_out(vty
, ", Cluster list: ");
10578 for (i
= 0; i
< cluster
->length
/ 4; i
++) {
10579 vty_out(vty
, "%pI4 ",
10580 &cluster
->list
[i
]);
10586 vty_out(vty
, "\n");
10589 if (path
->extra
&& path
->extra
->damp_info
)
10590 bgp_damp_info_vty(vty
, bgp
, path
, afi
, safi
, json_path
);
10593 if (path
->extra
&& bgp_is_valid_label(&path
->extra
->label
[0])
10594 && (safi
!= SAFI_EVPN
&& !is_route_parent_evpn(path
))) {
10595 mpls_label_t label
= label_pton(&path
->extra
->label
[0]);
10598 json_object_int_add(json_path
, "remoteLabel", label
);
10600 vty_out(vty
, " Remote label: %d\n", label
);
10604 if (path
->extra
&& path
->extra
->num_sids
> 0 && safi
!= SAFI_EVPN
) {
10605 inet_ntop(AF_INET6
, &path
->extra
->sid
, buf
, sizeof(buf
));
10607 json_object_string_add(json_path
, "remoteSid", buf
);
10609 vty_out(vty
, " Remote SID: %s\n", buf
);
10613 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
10615 json_object_int_add(json_path
, "labelIndex",
10616 attr
->label_index
);
10618 vty_out(vty
, " Label Index: %d\n",
10619 attr
->label_index
);
10622 /* Line 8 display Addpath IDs */
10623 if (path
->addpath_rx_id
10624 || bgp_addpath_info_has_ids(&path
->tx_addpath
)) {
10626 json_object_int_add(json_path
, "addpathRxId",
10627 path
->addpath_rx_id
);
10629 /* Keep backwards compatibility with the old API
10630 * by putting TX All's ID in the old field
10632 json_object_int_add(
10633 json_path
, "addpathTxId",
10635 .addpath_tx_id
[BGP_ADDPATH_ALL
]);
10637 /* ... but create a specific field for each
10640 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
10641 json_object_int_add(
10643 bgp_addpath_names(i
)->id_json_name
,
10644 path
->tx_addpath
.addpath_tx_id
[i
]);
10647 vty_out(vty
, " AddPath ID: RX %u, ",
10648 path
->addpath_rx_id
);
10650 route_vty_out_tx_ids(vty
, &path
->tx_addpath
);
10654 /* If we used addpath to TX a non-bestpath we need to display
10655 * "Advertised to" on a path-by-path basis
10657 if (bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
10660 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
10662 bgp_addpath_encode_tx(peer
, afi
, safi
);
10663 has_adj
= bgp_adj_out_lookup(
10665 bgp_addpath_id_for_peer(peer
, afi
, safi
,
10666 &path
->tx_addpath
));
10668 if ((addpath_capable
&& has_adj
)
10669 || (!addpath_capable
&& has_adj
10670 && CHECK_FLAG(path
->flags
,
10671 BGP_PATH_SELECTED
))) {
10672 if (json_path
&& !json_adv_to
)
10673 json_adv_to
= json_object_new_object();
10675 route_vty_out_advertised_to(
10677 " Advertised to:", json_adv_to
);
10683 json_object_object_add(
10684 json_path
, "advertisedTo", json_adv_to
);
10688 vty_out(vty
, "\n");
10693 /* Line 9 display Uptime */
10694 tbuf
= time(NULL
) - (bgp_clock() - path
->uptime
);
10696 json_last_update
= json_object_new_object();
10697 json_object_int_add(json_last_update
, "epoch", tbuf
);
10698 json_object_string_add(json_last_update
, "string",
10700 json_object_object_add(json_path
, "lastUpdate",
10703 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
10705 /* Line 10 display PMSI tunnel attribute, if present */
10706 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
10707 const char *str
= lookup_msg(bgp_pmsi_tnltype_str
,
10708 bgp_attr_get_pmsi_tnl_type(attr
),
10709 PMSI_TNLTYPE_STR_DEFAULT
);
10712 json_pmsi
= json_object_new_object();
10713 json_object_string_add(json_pmsi
, "tunnelType", str
);
10714 json_object_int_add(json_pmsi
, "label",
10715 label2vni(&attr
->label
));
10716 json_object_object_add(json_path
, "pmsi", json_pmsi
);
10718 vty_out(vty
, " PMSI Tunnel Type: %s, label: %d\n",
10719 str
, label2vni(&attr
->label
));
10722 /* Output some debug about internal state of the dest flags */
10724 if (CHECK_FLAG(bn
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
10725 json_object_boolean_true_add(json_path
, "processScheduled");
10726 if (CHECK_FLAG(bn
->flags
, BGP_NODE_USER_CLEAR
))
10727 json_object_boolean_true_add(json_path
, "userCleared");
10728 if (CHECK_FLAG(bn
->flags
, BGP_NODE_LABEL_CHANGED
))
10729 json_object_boolean_true_add(json_path
, "labelChanged");
10730 if (CHECK_FLAG(bn
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
))
10731 json_object_boolean_true_add(json_path
, "registeredForLabel");
10732 if (CHECK_FLAG(bn
->flags
, BGP_NODE_SELECT_DEFER
))
10733 json_object_boolean_true_add(json_path
, "selectDefered");
10734 if (CHECK_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALLED
))
10735 json_object_boolean_true_add(json_path
, "fibInstalled");
10736 if (CHECK_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALL_PENDING
))
10737 json_object_boolean_true_add(json_path
, "fibPending");
10740 /* We've constructed the json object for this path, add it to the json
10744 if (json_nexthop_global
|| json_nexthop_ll
) {
10745 json_nexthops
= json_object_new_array();
10747 if (json_nexthop_global
)
10748 json_object_array_add(json_nexthops
,
10749 json_nexthop_global
);
10751 if (json_nexthop_ll
)
10752 json_object_array_add(json_nexthops
,
10755 json_object_object_add(json_path
, "nexthops",
10759 json_object_object_add(json_path
, "peer", json_peer
);
10760 json_object_array_add(json_paths
, json_path
);
10764 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
10765 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
10766 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
10768 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
10769 const char *prefix_list_str
, afi_t afi
,
10770 safi_t safi
, enum bgp_show_type type
);
10771 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
10772 const char *filter
, afi_t afi
, safi_t safi
,
10773 enum bgp_show_type type
);
10774 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
10775 const char *rmap_str
, afi_t afi
, safi_t safi
,
10776 enum bgp_show_type type
);
10777 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
10778 const char *com
, int exact
, afi_t afi
,
10780 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
10781 const char *prefix
, afi_t afi
, safi_t safi
,
10782 enum bgp_show_type type
);
10783 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
10784 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
10786 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
10787 const char *comstr
, int exact
, afi_t afi
,
10788 safi_t safi
, uint16_t show_flags
);
10790 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
10791 struct bgp_table
*table
, enum bgp_show_type type
,
10792 void *output_arg
, char *rd
, int is_last
,
10793 unsigned long *output_cum
, unsigned long *total_cum
,
10794 unsigned long *json_header_depth
, uint16_t show_flags
,
10795 enum rpki_states rpki_target_state
)
10797 struct bgp_path_info
*pi
;
10798 struct bgp_dest
*dest
;
10801 unsigned long output_count
= 0;
10802 unsigned long total_count
= 0;
10804 json_object
*json_paths
= NULL
;
10806 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
10807 bool wide
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
10808 bool all
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
10810 if (output_cum
&& *output_cum
!= 0)
10813 if (use_json
&& !*json_header_depth
) {
10815 *json_header_depth
= 1;
10817 vty_out(vty
, "{\n");
10818 *json_header_depth
= 2;
10822 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
10823 ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
10824 " \"localAS\": %u,\n \"routes\": { ",
10825 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
10826 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
10829 table
->version
, &bgp
->router_id
,
10830 bgp
->default_local_pref
, bgp
->as
);
10832 vty_out(vty
, " \"routeDistinguishers\" : {");
10833 ++*json_header_depth
;
10837 if (use_json
&& rd
) {
10838 vty_out(vty
, " \"%s\" : { ", rd
);
10841 /* Start processing of routes. */
10842 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
10843 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
10844 enum rpki_states rpki_curr_state
= RPKI_NOT_BEING_USED
;
10846 pi
= bgp_dest_get_bgp_path_info(dest
);
10852 json_paths
= json_object_new_array();
10856 for (; pi
; pi
= pi
->next
) {
10859 if (type
== bgp_show_type_prefix_version
) {
10861 strtoul(output_arg
, NULL
, 10);
10862 if (dest
->version
< version
)
10866 if (type
== bgp_show_type_community_alias
) {
10867 char *alias
= output_arg
;
10868 char **communities
;
10870 bool found
= false;
10872 if (pi
->attr
->community
) {
10873 frrstr_split(pi
->attr
->community
->str
,
10874 " ", &communities
, &num
);
10875 for (int i
= 0; i
< num
; i
++) {
10876 const char *com2alias
=
10877 bgp_community2alias(
10879 if (strncmp(alias
, com2alias
,
10888 if (!found
&& pi
->attr
->lcommunity
) {
10889 frrstr_split(pi
->attr
->lcommunity
->str
,
10890 " ", &communities
, &num
);
10891 for (int i
= 0; i
< num
; i
++) {
10892 const char *com2alias
=
10893 bgp_community2alias(
10895 if (strncmp(alias
, com2alias
,
10908 if (type
== bgp_show_type_rpki
) {
10909 if (dest_p
->family
== AF_INET
10910 || dest_p
->family
== AF_INET6
)
10911 rpki_curr_state
= hook_call(
10912 bgp_rpki_prefix_status
,
10913 pi
->peer
, pi
->attr
, dest_p
);
10914 if (rpki_target_state
!= RPKI_NOT_BEING_USED
10915 && rpki_curr_state
!= rpki_target_state
)
10919 if (type
== bgp_show_type_flap_statistics
10920 || type
== bgp_show_type_flap_neighbor
10921 || type
== bgp_show_type_dampend_paths
10922 || type
== bgp_show_type_damp_neighbor
) {
10923 if (!(pi
->extra
&& pi
->extra
->damp_info
))
10926 if (type
== bgp_show_type_regexp
) {
10927 regex_t
*regex
= output_arg
;
10929 if (bgp_regexec(regex
, pi
->attr
->aspath
)
10933 if (type
== bgp_show_type_prefix_list
) {
10934 struct prefix_list
*plist
= output_arg
;
10936 if (prefix_list_apply(plist
, dest_p
)
10940 if (type
== bgp_show_type_filter_list
) {
10941 struct as_list
*as_list
= output_arg
;
10943 if (as_list_apply(as_list
, pi
->attr
->aspath
)
10944 != AS_FILTER_PERMIT
)
10947 if (type
== bgp_show_type_route_map
) {
10948 struct route_map
*rmap
= output_arg
;
10949 struct bgp_path_info path
;
10950 struct attr dummy_attr
;
10951 route_map_result_t ret
;
10953 dummy_attr
= *pi
->attr
;
10955 path
.peer
= pi
->peer
;
10956 path
.attr
= &dummy_attr
;
10958 ret
= route_map_apply(rmap
, dest_p
, &path
);
10959 if (ret
== RMAP_DENYMATCH
)
10962 if (type
== bgp_show_type_neighbor
10963 || type
== bgp_show_type_flap_neighbor
10964 || type
== bgp_show_type_damp_neighbor
) {
10965 union sockunion
*su
= output_arg
;
10967 if (pi
->peer
== NULL
10968 || pi
->peer
->su_remote
== NULL
10969 || !sockunion_same(pi
->peer
->su_remote
, su
))
10972 if (type
== bgp_show_type_cidr_only
) {
10973 uint32_t destination
;
10975 destination
= ntohl(dest_p
->u
.prefix4
.s_addr
);
10976 if (IN_CLASSC(destination
)
10977 && dest_p
->prefixlen
== 24)
10979 if (IN_CLASSB(destination
)
10980 && dest_p
->prefixlen
== 16)
10982 if (IN_CLASSA(destination
)
10983 && dest_p
->prefixlen
== 8)
10986 if (type
== bgp_show_type_prefix_longer
) {
10988 if (!prefix_match(p
, dest_p
))
10991 if (type
== bgp_show_type_community_all
) {
10992 if (!pi
->attr
->community
)
10995 if (type
== bgp_show_type_community
) {
10996 struct community
*com
= output_arg
;
10998 if (!pi
->attr
->community
10999 || !community_match(pi
->attr
->community
,
11003 if (type
== bgp_show_type_community_exact
) {
11004 struct community
*com
= output_arg
;
11006 if (!pi
->attr
->community
11007 || !community_cmp(pi
->attr
->community
, com
))
11010 if (type
== bgp_show_type_community_list
) {
11011 struct community_list
*list
= output_arg
;
11013 if (!community_list_match(pi
->attr
->community
,
11017 if (type
== bgp_show_type_community_list_exact
) {
11018 struct community_list
*list
= output_arg
;
11020 if (!community_list_exact_match(
11021 pi
->attr
->community
, list
))
11024 if (type
== bgp_show_type_lcommunity
) {
11025 struct lcommunity
*lcom
= output_arg
;
11027 if (!pi
->attr
->lcommunity
11028 || !lcommunity_match(pi
->attr
->lcommunity
,
11033 if (type
== bgp_show_type_lcommunity_exact
) {
11034 struct lcommunity
*lcom
= output_arg
;
11036 if (!pi
->attr
->lcommunity
11037 || !lcommunity_cmp(pi
->attr
->lcommunity
,
11041 if (type
== bgp_show_type_lcommunity_list
) {
11042 struct community_list
*list
= output_arg
;
11044 if (!lcommunity_list_match(pi
->attr
->lcommunity
,
11049 == bgp_show_type_lcommunity_list_exact
) {
11050 struct community_list
*list
= output_arg
;
11052 if (!lcommunity_list_exact_match(
11053 pi
->attr
->lcommunity
, list
))
11056 if (type
== bgp_show_type_lcommunity_all
) {
11057 if (!pi
->attr
->lcommunity
)
11060 if (type
== bgp_show_type_dampend_paths
11061 || type
== bgp_show_type_damp_neighbor
) {
11062 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
)
11063 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
11067 if (!use_json
&& header
) {
11069 "BGP table version is %" PRIu64
11070 ", local router ID is %pI4, vrf id ",
11071 table
->version
, &bgp
->router_id
);
11072 if (bgp
->vrf_id
== VRF_UNKNOWN
)
11073 vty_out(vty
, "%s", VRFID_NONE_STR
);
11075 vty_out(vty
, "%u", bgp
->vrf_id
);
11076 vty_out(vty
, "\n");
11077 vty_out(vty
, "Default local pref %u, ",
11078 bgp
->default_local_pref
);
11079 vty_out(vty
, "local AS %u\n", bgp
->as
);
11080 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
11081 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
11082 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
11083 vty_out(vty
, BGP_SHOW_RPKI_HEADER
);
11084 if (type
== bgp_show_type_dampend_paths
11085 || type
== bgp_show_type_damp_neighbor
)
11086 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
11087 else if (type
== bgp_show_type_flap_statistics
11088 || type
== bgp_show_type_flap_neighbor
)
11089 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
11091 vty_out(vty
, (wide
? BGP_SHOW_HEADER_WIDE
11092 : BGP_SHOW_HEADER
));
11095 if (rd
!= NULL
&& !display
&& !output_count
) {
11098 "Route Distinguisher: %s\n",
11101 if (type
== bgp_show_type_dampend_paths
11102 || type
== bgp_show_type_damp_neighbor
)
11103 damp_route_vty_out(vty
, dest_p
, pi
, display
,
11104 AFI_IP
, safi
, use_json
,
11106 else if (type
== bgp_show_type_flap_statistics
11107 || type
== bgp_show_type_flap_neighbor
)
11108 flap_route_vty_out(vty
, dest_p
, pi
, display
,
11109 AFI_IP
, safi
, use_json
,
11112 if (CHECK_FLAG(show_flags
, BGP_SHOW_OPT_DETAIL
))
11113 route_vty_out_detail(
11114 vty
, bgp
, dest
, pi
,
11115 family2afi(dest_p
->family
),
11116 safi
, RPKI_NOT_BEING_USED
,
11119 route_vty_out(vty
, dest_p
, pi
, display
,
11120 safi
, json_paths
, wide
);
11130 /* encode prefix */
11131 if (dest_p
->family
== AF_FLOWSPEC
) {
11132 char retstr
[BGP_FLOWSPEC_STRING_DISPLAY_MAX
];
11135 bgp_fs_nlri_get_string(
11137 dest_p
->u
.prefix_flowspec
.ptr
,
11138 dest_p
->u
.prefix_flowspec
.prefixlen
,
11139 retstr
, NLRI_STRING_FORMAT_MIN
, NULL
,
11140 family2afi(dest_p
->u
11141 .prefix_flowspec
.family
));
11143 vty_out(vty
, "\"%s/%d\": ", retstr
,
11144 dest_p
->u
.prefix_flowspec
11147 vty_out(vty
, ",\"%s/%d\": ", retstr
,
11148 dest_p
->u
.prefix_flowspec
11152 vty_out(vty
, "\"%pFX\": ", dest_p
);
11154 vty_out(vty
, ",\"%pFX\": ", dest_p
);
11157 json_object_to_json_string_ext(
11158 json_paths
, JSON_C_TO_STRING_PRETTY
));
11159 json_object_free(json_paths
);
11163 json_object_free(json_paths
);
11167 output_count
+= *output_cum
;
11168 *output_cum
= output_count
;
11171 total_count
+= *total_cum
;
11172 *total_cum
= total_count
;
11176 vty_out(vty
, " }%s ", (is_last
? "" : ","));
11180 for (i
= 0; i
< *json_header_depth
; ++i
)
11181 vty_out(vty
, " } ");
11183 vty_out(vty
, "\n");
11187 /* No route is displayed */
11188 if (output_count
== 0) {
11189 if (type
== bgp_show_type_normal
)
11191 "No BGP prefixes displayed, %ld exist\n",
11195 "\nDisplayed %ld routes and %ld total paths\n",
11196 output_count
, total_count
);
11200 return CMD_SUCCESS
;
11203 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
11204 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
11205 enum bgp_show_type type
, void *output_arg
, bool use_json
)
11207 struct bgp_dest
*dest
, *next
;
11208 unsigned long output_cum
= 0;
11209 unsigned long total_cum
= 0;
11210 unsigned long json_header_depth
= 0;
11211 struct bgp_table
*itable
;
11213 uint16_t show_flags
= 0;
11215 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
11218 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11220 for (dest
= bgp_table_top(table
); dest
; dest
= next
) {
11221 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11223 next
= bgp_route_next(dest
);
11224 if (prd_match
&& memcmp(dest_p
->u
.val
, prd_match
->val
, 8) != 0)
11227 itable
= bgp_dest_get_bgp_table_info(dest
);
11228 if (itable
!= NULL
) {
11229 struct prefix_rd prd
;
11230 char rd
[RD_ADDRSTRLEN
];
11232 memcpy(&prd
, dest_p
, sizeof(struct prefix_rd
));
11233 prefix_rd2str(&prd
, rd
, sizeof(rd
));
11234 bgp_show_table(vty
, bgp
, safi
, itable
, type
, output_arg
,
11235 rd
, next
== NULL
, &output_cum
,
11236 &total_cum
, &json_header_depth
,
11237 show_flags
, RPKI_NOT_BEING_USED
);
11243 if (output_cum
== 0)
11244 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
11248 "\nDisplayed %ld routes and %ld total paths\n",
11249 output_cum
, total_cum
);
11251 return CMD_SUCCESS
;
11253 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
11254 enum bgp_show_type type
, void *output_arg
,
11255 uint16_t show_flags
, enum rpki_states rpki_target_state
)
11257 struct bgp_table
*table
;
11258 unsigned long json_header_depth
= 0;
11259 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11262 bgp
= bgp_get_default();
11267 vty_out(vty
, "No BGP process is configured\n");
11269 vty_out(vty
, "{}\n");
11270 return CMD_WARNING
;
11273 table
= bgp
->rib
[afi
][safi
];
11274 /* use MPLS and ENCAP specific shows until they are merged */
11275 if (safi
== SAFI_MPLS_VPN
) {
11276 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
11277 output_arg
, use_json
);
11280 if (safi
== SAFI_FLOWSPEC
&& type
== bgp_show_type_detail
) {
11281 return bgp_show_table_flowspec(vty
, bgp
, afi
, table
, type
,
11282 output_arg
, use_json
,
11285 /* labeled-unicast routes live in the unicast table */
11286 else if (safi
== SAFI_LABELED_UNICAST
)
11287 safi
= SAFI_UNICAST
;
11289 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, NULL
, 1,
11290 NULL
, NULL
, &json_header_depth
, show_flags
,
11291 rpki_target_state
);
11294 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
11295 safi_t safi
, uint16_t show_flags
)
11297 struct listnode
*node
, *nnode
;
11300 bool route_output
= false;
11301 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11304 vty_out(vty
, "{\n");
11306 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
11307 route_output
= true;
11310 vty_out(vty
, ",\n");
11314 vty_out(vty
, "\"%s\":",
11315 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
11319 vty_out(vty
, "\nInstance %s:\n",
11320 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
11324 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
11325 show_flags
, RPKI_NOT_BEING_USED
);
11329 vty_out(vty
, "}\n");
11330 else if (!route_output
)
11331 vty_out(vty
, "%% BGP instance not found\n");
11334 /* Header of detailed BGP route information */
11335 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
11336 struct bgp_dest
*dest
, struct prefix_rd
*prd
,
11337 afi_t afi
, safi_t safi
, json_object
*json
)
11339 struct bgp_path_info
*pi
;
11340 const struct prefix
*p
;
11342 struct listnode
*node
, *nnode
;
11343 char buf1
[RD_ADDRSTRLEN
];
11344 char prefix_str
[BUFSIZ
];
11348 int accept_own
= 0;
11349 int route_filter_translated_v4
= 0;
11350 int route_filter_v4
= 0;
11351 int route_filter_translated_v6
= 0;
11352 int route_filter_v6
= 0;
11353 int llgr_stale
= 0;
11355 int accept_own_nexthop
= 0;
11358 int no_advertise
= 0;
11362 int has_valid_label
= 0;
11363 mpls_label_t label
= 0;
11364 json_object
*json_adv_to
= NULL
;
11366 p
= bgp_dest_get_prefix(dest
);
11367 has_valid_label
= bgp_is_valid_label(&dest
->local_label
);
11369 if (has_valid_label
)
11370 label
= label_pton(&dest
->local_label
);
11372 if (safi
== SAFI_EVPN
) {
11375 vty_out(vty
, "BGP routing table entry for %s%s%pFX\n",
11376 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
))
11378 prd
? ":" : "", (struct prefix_evpn
*)p
);
11380 json_object_string_add(json
, "rd",
11381 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
)) :
11383 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
11388 "BGP routing table entry for %s%s%pFX, version %" PRIu64
11390 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
11391 ? prefix_rd2str(prd
, buf1
,
11394 safi
== SAFI_MPLS_VPN
? ":" : "", p
,
11398 json_object_string_add(json
, "prefix",
11399 prefix2str(p
, prefix_str
, sizeof(prefix_str
)));
11400 json_object_int_add(json
, "version", dest
->version
);
11405 if (has_valid_label
) {
11407 json_object_int_add(json
, "localLabel", label
);
11409 vty_out(vty
, "Local label: %d\n", label
);
11413 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
11414 vty_out(vty
, "not allocated\n");
11416 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
11418 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
11420 if (bgp_path_suppressed(pi
))
11423 if (pi
->attr
->community
== NULL
)
11426 no_advertise
+= community_include(
11427 pi
->attr
->community
, COMMUNITY_NO_ADVERTISE
);
11428 no_export
+= community_include(pi
->attr
->community
,
11429 COMMUNITY_NO_EXPORT
);
11430 local_as
+= community_include(pi
->attr
->community
,
11431 COMMUNITY_LOCAL_AS
);
11432 accept_own
+= community_include(pi
->attr
->community
,
11433 COMMUNITY_ACCEPT_OWN
);
11434 route_filter_translated_v4
+= community_include(
11435 pi
->attr
->community
,
11436 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4
);
11437 route_filter_translated_v6
+= community_include(
11438 pi
->attr
->community
,
11439 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6
);
11440 route_filter_v4
+= community_include(
11441 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v4
);
11442 route_filter_v6
+= community_include(
11443 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v6
);
11444 llgr_stale
+= community_include(pi
->attr
->community
,
11445 COMMUNITY_LLGR_STALE
);
11446 no_llgr
+= community_include(pi
->attr
->community
,
11447 COMMUNITY_NO_LLGR
);
11448 accept_own_nexthop
+=
11449 community_include(pi
->attr
->community
,
11450 COMMUNITY_ACCEPT_OWN_NEXTHOP
);
11451 blackhole
+= community_include(pi
->attr
->community
,
11452 COMMUNITY_BLACKHOLE
);
11453 no_peer
+= community_include(pi
->attr
->community
,
11454 COMMUNITY_NO_PEER
);
11459 vty_out(vty
, "Paths: (%d available", count
);
11461 vty_out(vty
, ", best #%d", best
);
11462 if (safi
== SAFI_UNICAST
) {
11463 if (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
11464 vty_out(vty
, ", table %s",
11467 vty_out(vty
, ", vrf %s",
11471 vty_out(vty
, ", no best path");
11475 ", accept own local route exported and imported in different VRF");
11476 else if (route_filter_translated_v4
)
11478 ", mark translated RTs for VPNv4 route filtering");
11479 else if (route_filter_v4
)
11481 ", attach RT as-is for VPNv4 route filtering");
11482 else if (route_filter_translated_v6
)
11484 ", mark translated RTs for VPNv6 route filtering");
11485 else if (route_filter_v6
)
11487 ", attach RT as-is for VPNv6 route filtering");
11488 else if (llgr_stale
)
11490 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
11493 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
11494 else if (accept_own_nexthop
)
11496 ", accept local nexthop");
11497 else if (blackhole
)
11498 vty_out(vty
, ", inform peer to blackhole prefix");
11499 else if (no_export
)
11500 vty_out(vty
, ", not advertised to EBGP peer");
11501 else if (no_advertise
)
11502 vty_out(vty
, ", not advertised to any peer");
11504 vty_out(vty
, ", not advertised outside local AS");
11507 ", inform EBGP peer not to advertise to their EBGP peers");
11511 ", Advertisements suppressed by an aggregate.");
11512 vty_out(vty
, ")\n");
11515 /* If we are not using addpath then we can display Advertised to and
11517 * show what peers we advertised the bestpath to. If we are using
11519 * though then we must display Advertised to on a path-by-path basis. */
11520 if (!bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
11521 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
11522 if (bgp_adj_out_lookup(peer
, dest
, 0)) {
11523 if (json
&& !json_adv_to
)
11524 json_adv_to
= json_object_new_object();
11526 route_vty_out_advertised_to(
11528 " Advertised to non peer-group peers:\n ",
11535 json_object_object_add(json
, "advertisedTo",
11540 vty_out(vty
, " Not advertised to any peer");
11541 vty_out(vty
, "\n");
11546 static void bgp_show_path_info(struct prefix_rd
*pfx_rd
,
11547 struct bgp_dest
*bgp_node
, struct vty
*vty
,
11548 struct bgp
*bgp
, afi_t afi
, safi_t safi
,
11549 json_object
*json
, enum bgp_path_type pathtype
,
11550 int *display
, enum rpki_states rpki_target_state
)
11552 struct bgp_path_info
*pi
;
11554 char rdbuf
[RD_ADDRSTRLEN
];
11555 json_object
*json_header
= NULL
;
11556 json_object
*json_paths
= NULL
;
11557 const struct prefix
*p
= bgp_dest_get_prefix(bgp_node
);
11559 for (pi
= bgp_dest_get_bgp_path_info(bgp_node
); pi
; pi
= pi
->next
) {
11560 enum rpki_states rpki_curr_state
= RPKI_NOT_BEING_USED
;
11562 if (p
->family
== AF_INET
|| p
->family
== AF_INET6
)
11563 rpki_curr_state
= hook_call(bgp_rpki_prefix_status
,
11564 pi
->peer
, pi
->attr
, p
);
11566 if (rpki_target_state
!= RPKI_NOT_BEING_USED
11567 && rpki_curr_state
!= rpki_target_state
)
11570 if (json
&& !json_paths
) {
11571 /* Instantiate json_paths only if path is valid */
11572 json_paths
= json_object_new_array();
11574 prefix_rd2str(pfx_rd
, rdbuf
, sizeof(rdbuf
));
11575 json_header
= json_object_new_object();
11577 json_header
= json
;
11581 route_vty_out_detail_header(
11582 vty
, bgp
, bgp_node
, pfx_rd
,
11583 AFI_IP
, safi
, json_header
);
11588 if (pathtype
== BGP_PATH_SHOW_ALL
11589 || (pathtype
== BGP_PATH_SHOW_BESTPATH
11590 && CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
11591 || (pathtype
== BGP_PATH_SHOW_MULTIPATH
11592 && (CHECK_FLAG(pi
->flags
, BGP_PATH_MULTIPATH
)
11593 || CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))))
11594 route_vty_out_detail(vty
, bgp
, bgp_node
, pi
, AFI_IP
,
11595 safi
, rpki_curr_state
, json_paths
);
11598 if (json
&& json_paths
) {
11599 json_object_object_add(json_header
, "paths", json_paths
);
11602 json_object_object_add(json
, rdbuf
, json_header
);
11606 /* Display specified route of BGP table. */
11607 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
11608 struct bgp_table
*rib
, const char *ip_str
,
11609 afi_t afi
, safi_t safi
,
11610 enum rpki_states rpki_target_state
,
11611 struct prefix_rd
*prd
, int prefix_check
,
11612 enum bgp_path_type pathtype
, bool use_json
)
11616 struct prefix match
;
11617 struct bgp_dest
*dest
;
11618 struct bgp_dest
*rm
;
11619 struct bgp_table
*table
;
11620 json_object
*json
= NULL
;
11621 json_object
*json_paths
= NULL
;
11623 /* Check IP address argument. */
11624 ret
= str2prefix(ip_str
, &match
);
11626 vty_out(vty
, "address is malformed\n");
11627 return CMD_WARNING
;
11630 match
.family
= afi2family(afi
);
11633 json
= json_object_new_object();
11635 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
) {
11636 for (dest
= bgp_table_top(rib
); dest
;
11637 dest
= bgp_route_next(dest
)) {
11638 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11640 if (prd
&& memcmp(dest_p
->u
.val
, prd
->val
, 8) != 0)
11642 table
= bgp_dest_get_bgp_table_info(dest
);
11646 rm
= bgp_node_match(table
, &match
);
11650 const struct prefix
*rm_p
= bgp_dest_get_prefix(rm
);
11652 && rm_p
->prefixlen
!= match
.prefixlen
) {
11653 bgp_dest_unlock_node(rm
);
11657 bgp_show_path_info((struct prefix_rd
*)dest_p
, rm
, vty
,
11658 bgp
, afi
, safi
, json
, pathtype
,
11659 &display
, rpki_target_state
);
11661 bgp_dest_unlock_node(rm
);
11663 } else if (safi
== SAFI_EVPN
) {
11664 struct bgp_dest
*longest_pfx
;
11665 bool is_exact_pfxlen_match
= false;
11667 for (dest
= bgp_table_top(rib
); dest
;
11668 dest
= bgp_route_next(dest
)) {
11669 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11671 if (prd
&& memcmp(&dest_p
->u
.val
, prd
->val
, 8) != 0)
11673 table
= bgp_dest_get_bgp_table_info(dest
);
11677 longest_pfx
= NULL
;
11678 is_exact_pfxlen_match
= false;
11680 * Search through all the prefixes for a match. The
11681 * pfx's are enumerated in ascending order of pfxlens.
11682 * So, the last pfx match is the longest match. Set
11683 * is_exact_pfxlen_match when we get exact pfxlen match
11685 for (rm
= bgp_table_top(table
); rm
;
11686 rm
= bgp_route_next(rm
)) {
11687 const struct prefix
*rm_p
=
11688 bgp_dest_get_prefix(rm
);
11690 * Get prefixlen of the ip-prefix within type5
11693 if (evpn_type5_prefix_match(rm_p
, &match
)
11697 bgp_evpn_get_type5_prefixlen(
11699 if (type5_pfxlen
== match
.prefixlen
) {
11700 is_exact_pfxlen_match
= true;
11701 bgp_dest_unlock_node(rm
);
11710 if (prefix_check
&& !is_exact_pfxlen_match
)
11714 bgp_dest_lock_node(rm
);
11716 bgp_show_path_info((struct prefix_rd
*)dest_p
, rm
, vty
,
11717 bgp
, afi
, safi
, json
, pathtype
,
11718 &display
, rpki_target_state
);
11720 bgp_dest_unlock_node(rm
);
11722 } else if (safi
== SAFI_FLOWSPEC
) {
11724 json_paths
= json_object_new_array();
11726 display
= bgp_flowspec_display_match_per_ip(afi
, rib
,
11727 &match
, prefix_check
,
11733 json_object_object_add(json
, "paths",
11736 json_object_free(json_paths
);
11739 dest
= bgp_node_match(rib
, &match
);
11740 if (dest
!= NULL
) {
11741 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11743 || dest_p
->prefixlen
== match
.prefixlen
) {
11744 bgp_show_path_info(NULL
, dest
, vty
, bgp
, afi
,
11745 safi
, json
, pathtype
,
11746 &display
, rpki_target_state
);
11749 bgp_dest_unlock_node(dest
);
11754 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
11755 json
, JSON_C_TO_STRING_PRETTY
|
11756 JSON_C_TO_STRING_NOSLASHESCAPE
));
11757 json_object_free(json
);
11760 vty_out(vty
, "%% Network not in table\n");
11761 return CMD_WARNING
;
11765 return CMD_SUCCESS
;
11768 /* Display specified route of Main RIB */
11769 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
11770 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
11771 int prefix_check
, enum bgp_path_type pathtype
,
11772 enum rpki_states rpki_target_state
, bool use_json
)
11775 bgp
= bgp_get_default();
11778 vty_out(vty
, "No BGP process is configured\n");
11780 vty_out(vty
, "{}\n");
11781 return CMD_WARNING
;
11785 /* labeled-unicast routes live in the unicast table */
11786 if (safi
== SAFI_LABELED_UNICAST
)
11787 safi
= SAFI_UNICAST
;
11789 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
11790 afi
, safi
, rpki_target_state
, prd
,
11791 prefix_check
, pathtype
, use_json
);
11794 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
11795 struct cmd_token
**argv
, bool exact
, afi_t afi
,
11796 safi_t safi
, bool uj
)
11798 struct lcommunity
*lcom
;
11803 uint16_t show_flags
= 0;
11807 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11809 b
= buffer_new(1024);
11810 for (i
= 0; i
< argc
; i
++) {
11812 buffer_putc(b
, ' ');
11814 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
11816 buffer_putstr(b
, argv
[i
]->arg
);
11820 buffer_putc(b
, '\0');
11822 str
= buffer_getstr(b
);
11825 lcom
= lcommunity_str2com(str
);
11826 XFREE(MTYPE_TMP
, str
);
11828 vty_out(vty
, "%% Large-community malformed\n");
11829 return CMD_WARNING
;
11832 ret
= bgp_show(vty
, bgp
, afi
, safi
,
11833 (exact
? bgp_show_type_lcommunity_exact
11834 : bgp_show_type_lcommunity
),
11835 lcom
, show_flags
, RPKI_NOT_BEING_USED
);
11837 lcommunity_free(&lcom
);
11841 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
11842 const char *lcom
, bool exact
, afi_t afi
,
11843 safi_t safi
, bool uj
)
11845 struct community_list
*list
;
11846 uint16_t show_flags
= 0;
11849 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11852 list
= community_list_lookup(bgp_clist
, lcom
, 0,
11853 LARGE_COMMUNITY_LIST_MASTER
);
11854 if (list
== NULL
) {
11855 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
11857 return CMD_WARNING
;
11860 return bgp_show(vty
, bgp
, afi
, safi
,
11861 (exact
? bgp_show_type_lcommunity_list_exact
11862 : bgp_show_type_lcommunity_list
),
11863 list
, show_flags
, RPKI_NOT_BEING_USED
);
11866 DEFUN (show_ip_bgp_large_community_list
,
11867 show_ip_bgp_large_community_list_cmd
,
11868 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community-list <(1-500)|WORD> [exact-match] [json]",
11872 BGP_INSTANCE_HELP_STR
11874 BGP_SAFI_WITH_LABEL_HELP_STR
11875 "Display routes matching the large-community-list\n"
11876 "large-community-list number\n"
11877 "large-community-list name\n"
11878 "Exact match of the large-communities\n"
11881 afi_t afi
= AFI_IP6
;
11882 safi_t safi
= SAFI_UNICAST
;
11884 bool exact_match
= 0;
11885 struct bgp
*bgp
= NULL
;
11886 bool uj
= use_json(argc
, argv
);
11891 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11894 return CMD_WARNING
;
11896 argv_find(argv
, argc
, "large-community-list", &idx
);
11898 const char *clist_number_or_name
= argv
[++idx
]->arg
;
11900 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
11903 return bgp_show_lcommunity_list(vty
, bgp
, clist_number_or_name
,
11904 exact_match
, afi
, safi
, uj
);
11906 DEFUN (show_ip_bgp_large_community
,
11907 show_ip_bgp_large_community_cmd
,
11908 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [<AA:BB:CC> [exact-match]] [json]",
11912 BGP_INSTANCE_HELP_STR
11914 BGP_SAFI_WITH_LABEL_HELP_STR
11915 "Display routes matching the large-communities\n"
11916 "List of large-community numbers\n"
11917 "Exact match of the large-communities\n"
11920 afi_t afi
= AFI_IP6
;
11921 safi_t safi
= SAFI_UNICAST
;
11923 bool exact_match
= 0;
11924 struct bgp
*bgp
= NULL
;
11925 bool uj
= use_json(argc
, argv
);
11926 uint16_t show_flags
= 0;
11930 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11933 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11936 return CMD_WARNING
;
11938 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
)) {
11939 if (argv_find(argv
, argc
, "exact-match", &idx
))
11941 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
,
11942 exact_match
, afi
, safi
, uj
);
11944 return bgp_show(vty
, bgp
, afi
, safi
,
11945 bgp_show_type_lcommunity_all
, NULL
, show_flags
,
11946 RPKI_NOT_BEING_USED
);
11949 static int bgp_table_stats_single(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11950 safi_t safi
, struct json_object
*json_array
);
11951 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11952 safi_t safi
, struct json_object
*json
);
11955 DEFUN(show_ip_bgp_statistics_all
, show_ip_bgp_statistics_all_cmd
,
11956 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
11957 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
11958 "Display number of prefixes for all afi/safi\n" JSON_STR
)
11960 bool uj
= use_json(argc
, argv
);
11961 struct bgp
*bgp
= NULL
;
11962 safi_t safi
= SAFI_UNICAST
;
11963 afi_t afi
= AFI_IP6
;
11965 struct json_object
*json_all
= NULL
;
11966 struct json_object
*json_afi_safi
= NULL
;
11968 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11971 return CMD_WARNING
;
11974 json_all
= json_object_new_object();
11976 FOREACH_AFI_SAFI (afi
, safi
) {
11978 * So limit output to those afi/safi pairs that
11979 * actually have something interesting in them
11981 if (strmatch(get_afi_safi_str(afi
, safi
, true),
11986 json_afi_safi
= json_object_new_array();
11987 json_object_object_add(
11989 get_afi_safi_str(afi
, safi
, true),
11992 json_afi_safi
= NULL
;
11995 bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
12000 json_object_to_json_string_ext(
12001 json_all
, JSON_C_TO_STRING_PRETTY
));
12002 json_object_free(json_all
);
12005 return CMD_SUCCESS
;
12008 /* BGP route print out function without JSON */
12009 DEFUN (show_ip_bgp_l2vpn_evpn_statistics
,
12010 show_ip_bgp_l2vpn_evpn_statistics_cmd
,
12011 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
12015 BGP_INSTANCE_HELP_STR
12018 "BGP RIB advertisement statistics\n"
12021 afi_t afi
= AFI_IP6
;
12022 safi_t safi
= SAFI_UNICAST
;
12023 struct bgp
*bgp
= NULL
;
12025 bool uj
= use_json(argc
, argv
);
12026 struct json_object
*json_afi_safi
= NULL
, *json
= NULL
;
12028 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12031 return CMD_WARNING
;
12034 json_afi_safi
= json_object_new_array();
12036 json_afi_safi
= NULL
;
12038 ret
= bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
12041 json
= json_object_new_object();
12042 json_object_object_add(json
, get_afi_safi_str(afi
, safi
, true),
12044 vty_out(vty
, "%s", json_object_to_json_string_ext(
12045 json
, JSON_C_TO_STRING_PRETTY
));
12046 json_object_free(json
);
12051 /* BGP route print out function without JSON */
12052 DEFUN(show_ip_bgp_afi_safi_statistics
, show_ip_bgp_afi_safi_statistics_cmd
,
12053 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12054 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12056 statistics [json]",
12057 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12058 BGP_SAFI_WITH_LABEL_HELP_STR
12059 "BGP RIB advertisement statistics\n" JSON_STR
)
12061 afi_t afi
= AFI_IP6
;
12062 safi_t safi
= SAFI_UNICAST
;
12063 struct bgp
*bgp
= NULL
;
12065 bool uj
= use_json(argc
, argv
);
12066 struct json_object
*json_afi_safi
= NULL
, *json
= NULL
;
12068 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12071 return CMD_WARNING
;
12074 json_afi_safi
= json_object_new_array();
12076 json_afi_safi
= NULL
;
12078 ret
= bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
12081 json
= json_object_new_object();
12082 json_object_object_add(json
, get_afi_safi_str(afi
, safi
, true),
12085 json_object_to_json_string_ext(
12086 json
, JSON_C_TO_STRING_PRETTY
));
12087 json_object_free(json
);
12092 /* BGP route print out function without JSON */
12093 DEFPY(show_ip_bgp
, show_ip_bgp_cmd
,
12094 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12095 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12097 <[all$all] dampening <parameters>\
12101 |community-list <(1-500)|WORD> [exact-match]\
12102 |A.B.C.D/M longer-prefixes\
12103 |X:X::X:X/M longer-prefixes\
12105 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12106 BGP_SAFI_WITH_LABEL_HELP_STR
12107 "Display the entries for all address families\n"
12108 "Display detailed information about dampening\n"
12109 "Display detail of configured dampening parameters\n"
12110 "Display routes matching the route-map\n"
12111 "A route-map to match on\n"
12112 "Display routes conforming to the prefix-list\n"
12113 "Prefix-list name\n"
12114 "Display routes conforming to the filter-list\n"
12115 "Regular expression access list name\n"
12116 "Display routes matching the community-list\n"
12117 "community-list number\n"
12118 "community-list name\n"
12119 "Exact match of the communities\n"
12121 "Display route and more specific routes\n"
12123 "Display route and more specific routes\n")
12125 afi_t afi
= AFI_IP6
;
12126 safi_t safi
= SAFI_UNICAST
;
12127 int exact_match
= 0;
12128 struct bgp
*bgp
= NULL
;
12130 uint16_t show_flags
= 0;
12132 /* [<ipv4|ipv6> [all]] */
12134 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
12135 if (argv_find(argv
, argc
, "ipv4", &idx
))
12136 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
12138 if (argv_find(argv
, argc
, "ipv6", &idx
))
12139 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
12142 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12145 return CMD_WARNING
;
12147 if (argv_find(argv
, argc
, "dampening", &idx
)) {
12148 if (argv_find(argv
, argc
, "parameters", &idx
))
12149 return bgp_show_dampening_parameters(vty
, afi
, safi
,
12153 if (argv_find(argv
, argc
, "prefix-list", &idx
))
12154 return bgp_show_prefix_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
12155 safi
, bgp_show_type_prefix_list
);
12157 if (argv_find(argv
, argc
, "filter-list", &idx
))
12158 return bgp_show_filter_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
12159 safi
, bgp_show_type_filter_list
);
12161 if (argv_find(argv
, argc
, "route-map", &idx
))
12162 return bgp_show_route_map(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
12163 safi
, bgp_show_type_route_map
);
12165 if (argv_find(argv
, argc
, "community-list", &idx
)) {
12166 const char *clist_number_or_name
= argv
[++idx
]->arg
;
12167 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
12169 return bgp_show_community_list(vty
, bgp
, clist_number_or_name
,
12170 exact_match
, afi
, safi
);
12172 /* prefix-longer */
12173 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
12174 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
12175 return bgp_show_prefix_longer(vty
, bgp
, argv
[idx
]->arg
, afi
,
12177 bgp_show_type_prefix_longer
);
12179 return CMD_WARNING
;
12182 /* BGP route print out function with JSON */
12183 DEFPY(show_ip_bgp_json
, show_ip_bgp_json_cmd
,
12184 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12185 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12189 |dampening <flap-statistics|dampened-paths>\
12190 |community [AA:NN|local-AS|no-advertise|no-export\
12191 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
12192 |accept-own|accept-own-nexthop|route-filter-v6\
12193 |route-filter-v4|route-filter-translated-v6\
12194 |route-filter-translated-v4] [exact-match]\
12195 |rpki <invalid|valid|notfound>\
12196 |version (1-4294967295)\
12198 ] [json$uj [detail$detail] | wide$wide]",
12199 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12200 BGP_SAFI_WITH_LABEL_HELP_STR
12201 "Display the entries for all address families\n"
12202 "Display only routes with non-natural netmasks\n"
12203 "Display detailed information about dampening\n"
12204 "Display flap statistics of routes\n"
12205 "Display paths suppressed due to dampening\n"
12206 "Display routes matching the communities\n" COMMUNITY_AANN_STR
12207 "Do not send outside local AS (well-known community)\n"
12208 "Do not advertise to any peer (well-known community)\n"
12209 "Do not export to next AS (well-known community)\n"
12210 "Graceful shutdown (well-known community)\n"
12211 "Do not export to any peer (well-known community)\n"
12212 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
12213 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
12214 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
12215 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
12216 "Should accept VPN route with local nexthop (well-known community)\n"
12217 "RT VPNv6 route filtering (well-known community)\n"
12218 "RT VPNv4 route filtering (well-known community)\n"
12219 "RT translated VPNv6 route filtering (well-known community)\n"
12220 "RT translated VPNv4 route filtering (well-known community)\n"
12221 "Exact match of the communities\n"
12222 "RPKI route types\n"
12223 "A valid path as determined by rpki\n"
12224 "A invalid path as determined by rpki\n"
12225 "A path that has no rpki data\n"
12226 "Display prefixes with matching version numbers\n"
12227 "Version number and above\n"
12228 "Display prefixes with matching BGP community alias\n"
12229 "BGP community alias\n" JSON_STR
12230 "Display detailed version of JSON output\n"
12231 "Increase table width for longer prefixes\n")
12233 afi_t afi
= AFI_IP6
;
12234 safi_t safi
= SAFI_UNICAST
;
12235 enum bgp_show_type sh_type
= bgp_show_type_normal
;
12236 struct bgp
*bgp
= NULL
;
12238 int exact_match
= 0;
12239 char *community
= NULL
;
12240 char *prefix_version
= NULL
;
12241 char *bgp_community_alias
= NULL
;
12243 uint16_t show_flags
= 0;
12244 enum rpki_states rpki_target_state
= RPKI_NOT_BEING_USED
;
12248 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12252 SET_FLAG(show_flags
, BGP_SHOW_OPT_DETAIL
);
12254 /* [<ipv4|ipv6> [all]] */
12256 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
12258 if (argv_find(argv
, argc
, "ipv4", &idx
))
12259 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
12261 if (argv_find(argv
, argc
, "ipv6", &idx
))
12262 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
12266 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
12268 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12271 return CMD_WARNING
;
12273 if (argv_find(argv
, argc
, "cidr-only", &idx
))
12274 sh_type
= bgp_show_type_cidr_only
;
12276 if (argv_find(argv
, argc
, "dampening", &idx
)) {
12277 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
12278 sh_type
= bgp_show_type_dampend_paths
;
12279 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
12280 sh_type
= bgp_show_type_flap_statistics
;
12283 if (argv_find(argv
, argc
, "community", &idx
)) {
12284 char *maybecomm
= NULL
;
12286 if (idx
+ 1 < argc
) {
12287 if (argv
[idx
+ 1]->type
== VARIABLE_TKN
)
12288 maybecomm
= argv
[idx
+ 1]->arg
;
12290 maybecomm
= argv
[idx
+ 1]->text
;
12293 if (maybecomm
&& !strmatch(maybecomm
, "json")
12294 && !strmatch(maybecomm
, "exact-match"))
12295 community
= maybecomm
;
12297 if (argv_find(argv
, argc
, "exact-match", &idx
))
12301 sh_type
= bgp_show_type_community_all
;
12304 if (argv_find(argv
, argc
, "rpki", &idx
)) {
12305 sh_type
= bgp_show_type_rpki
;
12306 if (argv_find(argv
, argc
, "valid", &idx
))
12307 rpki_target_state
= RPKI_VALID
;
12308 else if (argv_find(argv
, argc
, "invalid", &idx
))
12309 rpki_target_state
= RPKI_INVALID
;
12312 /* Display prefixes with matching version numbers */
12313 if (argv_find(argv
, argc
, "version", &idx
)) {
12314 sh_type
= bgp_show_type_prefix_version
;
12315 prefix_version
= argv
[idx
+ 1]->arg
;
12318 /* Display prefixes with matching BGP community alias */
12319 if (argv_find(argv
, argc
, "alias", &idx
)) {
12320 sh_type
= bgp_show_type_community_alias
;
12321 bgp_community_alias
= argv
[idx
+ 1]->arg
;
12325 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
12327 return bgp_show_community(vty
, bgp
, community
,
12328 exact_match
, afi
, safi
,
12330 else if (prefix_version
)
12331 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
,
12332 prefix_version
, show_flags
,
12333 rpki_target_state
);
12334 else if (bgp_community_alias
)
12335 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
,
12336 bgp_community_alias
, show_flags
,
12337 rpki_target_state
);
12339 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
, NULL
,
12340 show_flags
, rpki_target_state
);
12342 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
12346 vty_out(vty
, "{\n");
12348 if (CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
12349 || CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
)) {
12350 afi
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
12353 FOREACH_SAFI (safi
) {
12354 if (!bgp_afi_safi_peer_exists(bgp
, afi
, safi
))
12361 vty_out(vty
, ",\n");
12362 vty_out(vty
, "\"%s\":{\n",
12363 get_afi_safi_str(afi
, safi
,
12367 "\nFor address family: %s\n",
12368 get_afi_safi_str(afi
, safi
,
12372 bgp_show_community(vty
, bgp
, community
,
12375 else if (prefix_version
)
12376 return bgp_show(vty
, bgp
, afi
, safi
,
12377 sh_type
, prefix_version
,
12379 rpki_target_state
);
12380 else if (bgp_community_alias
)
12382 vty
, bgp
, afi
, safi
, sh_type
,
12383 bgp_community_alias
, show_flags
,
12384 rpki_target_state
);
12386 bgp_show(vty
, bgp
, afi
, safi
, sh_type
,
12388 rpki_target_state
);
12390 vty_out(vty
, "}\n");
12393 /* show <ip> bgp all: for each AFI and SAFI*/
12394 FOREACH_AFI_SAFI (afi
, safi
) {
12395 if (!bgp_afi_safi_peer_exists(bgp
, afi
, safi
))
12402 vty_out(vty
, ",\n");
12404 vty_out(vty
, "\"%s\":{\n",
12405 get_afi_safi_str(afi
, safi
,
12409 "\nFor address family: %s\n",
12410 get_afi_safi_str(afi
, safi
,
12414 bgp_show_community(vty
, bgp
, community
,
12417 else if (prefix_version
)
12418 return bgp_show(vty
, bgp
, afi
, safi
,
12419 sh_type
, prefix_version
,
12421 rpki_target_state
);
12423 bgp_show(vty
, bgp
, afi
, safi
, sh_type
,
12425 rpki_target_state
);
12427 vty_out(vty
, "}\n");
12431 vty_out(vty
, "}\n");
12433 return CMD_SUCCESS
;
12436 DEFUN (show_ip_bgp_route
,
12437 show_ip_bgp_route_cmd
,
12438 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [rpki <valid|invalid|notfound>] [json]",
12442 BGP_INSTANCE_HELP_STR
12444 BGP_SAFI_WITH_LABEL_HELP_STR
12445 "Network in the BGP routing table to display\n"
12447 "Network in the BGP routing table to display\n"
12449 "Display only the bestpath\n"
12450 "Display only multipaths\n"
12451 "Display only paths that match the specified rpki state\n"
12452 "A valid path as determined by rpki\n"
12453 "A invalid path as determined by rpki\n"
12454 "A path that has no rpki data\n"
12457 int prefix_check
= 0;
12459 afi_t afi
= AFI_IP6
;
12460 safi_t safi
= SAFI_UNICAST
;
12461 char *prefix
= NULL
;
12462 struct bgp
*bgp
= NULL
;
12463 enum bgp_path_type path_type
;
12464 bool uj
= use_json(argc
, argv
);
12468 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12471 return CMD_WARNING
;
12475 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
12476 return CMD_WARNING
;
12479 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
12480 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
12481 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
12483 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
12484 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
12487 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
12488 && afi
!= AFI_IP6
) {
12490 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
12491 return CMD_WARNING
;
12493 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
12494 && afi
!= AFI_IP
) {
12496 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
12497 return CMD_WARNING
;
12500 prefix
= argv
[idx
]->arg
;
12502 /* [<bestpath|multipath>] */
12503 if (argv_find(argv
, argc
, "bestpath", &idx
))
12504 path_type
= BGP_PATH_SHOW_BESTPATH
;
12505 else if (argv_find(argv
, argc
, "multipath", &idx
))
12506 path_type
= BGP_PATH_SHOW_MULTIPATH
;
12508 path_type
= BGP_PATH_SHOW_ALL
;
12510 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
12511 path_type
, RPKI_NOT_BEING_USED
, uj
);
12514 DEFUN (show_ip_bgp_regexp
,
12515 show_ip_bgp_regexp_cmd
,
12516 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX [json]",
12520 BGP_INSTANCE_HELP_STR
12522 BGP_SAFI_WITH_LABEL_HELP_STR
12523 "Display routes matching the AS path regular expression\n"
12524 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
12527 afi_t afi
= AFI_IP6
;
12528 safi_t safi
= SAFI_UNICAST
;
12529 struct bgp
*bgp
= NULL
;
12530 bool uj
= use_json(argc
, argv
);
12531 char *regstr
= NULL
;
12534 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12537 return CMD_WARNING
;
12539 // get index of regex
12540 if (argv_find(argv
, argc
, "REGEX", &idx
))
12541 regstr
= argv
[idx
]->arg
;
12544 return bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
12545 bgp_show_type_regexp
, uj
);
12548 DEFPY (show_ip_bgp_instance_all
,
12549 show_ip_bgp_instance_all_cmd
,
12550 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json$uj | wide$wide]",
12554 BGP_INSTANCE_ALL_HELP_STR
12556 BGP_SAFI_WITH_LABEL_HELP_STR
12558 "Increase table width for longer prefixes\n")
12560 afi_t afi
= AFI_IP
;
12561 safi_t safi
= SAFI_UNICAST
;
12562 struct bgp
*bgp
= NULL
;
12564 uint16_t show_flags
= 0;
12568 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12572 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
12574 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12577 return CMD_WARNING
;
12579 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, show_flags
);
12580 return CMD_SUCCESS
;
12583 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
12584 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
12589 uint16_t show_flags
= 0;
12592 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12594 if (!config_bgp_aspath_validate(regstr
)) {
12595 vty_out(vty
, "Invalid character in REGEX %s\n",
12597 return CMD_WARNING_CONFIG_FAILED
;
12600 regex
= bgp_regcomp(regstr
);
12602 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
12603 return CMD_WARNING
;
12606 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, show_flags
,
12607 RPKI_NOT_BEING_USED
);
12608 bgp_regex_free(regex
);
12612 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
12613 const char *prefix_list_str
, afi_t afi
,
12614 safi_t safi
, enum bgp_show_type type
)
12616 struct prefix_list
*plist
;
12617 uint16_t show_flags
= 0;
12619 plist
= prefix_list_lookup(afi
, prefix_list_str
);
12620 if (plist
== NULL
) {
12621 vty_out(vty
, "%% %s is not a valid prefix-list name\n",
12623 return CMD_WARNING
;
12626 return bgp_show(vty
, bgp
, afi
, safi
, type
, plist
, show_flags
,
12627 RPKI_NOT_BEING_USED
);
12630 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
12631 const char *filter
, afi_t afi
, safi_t safi
,
12632 enum bgp_show_type type
)
12634 struct as_list
*as_list
;
12635 uint16_t show_flags
= 0;
12637 as_list
= as_list_lookup(filter
);
12638 if (as_list
== NULL
) {
12639 vty_out(vty
, "%% %s is not a valid AS-path access-list name\n",
12641 return CMD_WARNING
;
12644 return bgp_show(vty
, bgp
, afi
, safi
, type
, as_list
, show_flags
,
12645 RPKI_NOT_BEING_USED
);
12648 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
12649 const char *rmap_str
, afi_t afi
, safi_t safi
,
12650 enum bgp_show_type type
)
12652 struct route_map
*rmap
;
12653 uint16_t show_flags
= 0;
12655 rmap
= route_map_lookup_by_name(rmap_str
);
12657 vty_out(vty
, "%% %s is not a valid route-map name\n", rmap_str
);
12658 return CMD_WARNING
;
12661 return bgp_show(vty
, bgp
, afi
, safi
, type
, rmap
, show_flags
,
12662 RPKI_NOT_BEING_USED
);
12665 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
12666 const char *comstr
, int exact
, afi_t afi
,
12667 safi_t safi
, uint16_t show_flags
)
12669 struct community
*com
;
12672 com
= community_str2com(comstr
);
12674 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
12675 return CMD_WARNING
;
12678 ret
= bgp_show(vty
, bgp
, afi
, safi
,
12679 (exact
? bgp_show_type_community_exact
12680 : bgp_show_type_community
),
12681 com
, show_flags
, RPKI_NOT_BEING_USED
);
12682 community_free(&com
);
12687 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
12688 const char *com
, int exact
, afi_t afi
,
12691 struct community_list
*list
;
12692 uint16_t show_flags
= 0;
12694 list
= community_list_lookup(bgp_clist
, com
, 0, COMMUNITY_LIST_MASTER
);
12695 if (list
== NULL
) {
12696 vty_out(vty
, "%% %s is not a valid community-list name\n", com
);
12697 return CMD_WARNING
;
12700 return bgp_show(vty
, bgp
, afi
, safi
,
12701 (exact
? bgp_show_type_community_list_exact
12702 : bgp_show_type_community_list
),
12703 list
, show_flags
, RPKI_NOT_BEING_USED
);
12706 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
12707 const char *prefix
, afi_t afi
, safi_t safi
,
12708 enum bgp_show_type type
)
12712 uint16_t show_flags
= 0;
12716 ret
= str2prefix(prefix
, p
);
12718 vty_out(vty
, "%% Malformed Prefix\n");
12719 return CMD_WARNING
;
12722 ret
= bgp_show(vty
, bgp
, afi
, safi
, type
, p
, show_flags
,
12723 RPKI_NOT_BEING_USED
);
12729 BGP_STATS_MAXBITLEN
= 0,
12731 BGP_STATS_PREFIXES
,
12733 BGP_STATS_UNAGGREGATEABLE
,
12734 BGP_STATS_MAX_AGGREGATEABLE
,
12735 BGP_STATS_AGGREGATES
,
12737 BGP_STATS_ASPATH_COUNT
,
12738 BGP_STATS_ASPATH_MAXHOPS
,
12739 BGP_STATS_ASPATH_TOTHOPS
,
12740 BGP_STATS_ASPATH_MAXSIZE
,
12741 BGP_STATS_ASPATH_TOTSIZE
,
12742 BGP_STATS_ASN_HIGHEST
,
12746 #define TABLE_STATS_IDX_VTY 0
12747 #define TABLE_STATS_IDX_JSON 1
12749 static const char *table_stats_strs
[][2] = {
12750 [BGP_STATS_PREFIXES
] = {"Total Prefixes", "totalPrefixes"},
12751 [BGP_STATS_TOTPLEN
] = {"Average prefix length", "averagePrefixLength"},
12752 [BGP_STATS_RIB
] = {"Total Advertisements", "totalAdvertisements"},
12753 [BGP_STATS_UNAGGREGATEABLE
] = {"Unaggregateable prefixes",
12754 "unaggregateablePrefixes"},
12755 [BGP_STATS_MAX_AGGREGATEABLE
] = {"Maximum aggregateable prefixes",
12756 "maximumAggregateablePrefixes"},
12757 [BGP_STATS_AGGREGATES
] = {"BGP Aggregate advertisements",
12758 "bgpAggregateAdvertisements"},
12759 [BGP_STATS_SPACE
] = {"Address space advertised",
12760 "addressSpaceAdvertised"},
12761 [BGP_STATS_ASPATH_COUNT
] = {"Advertisements with paths",
12762 "advertisementsWithPaths"},
12763 [BGP_STATS_ASPATH_MAXHOPS
] = {"Longest AS-Path (hops)",
12765 [BGP_STATS_ASPATH_MAXSIZE
] = {"Largest AS-Path (bytes)",
12767 [BGP_STATS_ASPATH_TOTHOPS
] = {"Average AS-Path length (hops)",
12768 "averageAsPathLengthHops"},
12769 [BGP_STATS_ASPATH_TOTSIZE
] = {"Average AS-Path size (bytes)",
12770 "averageAsPathSizeBytes"},
12771 [BGP_STATS_ASN_HIGHEST
] = {"Highest public ASN", "highestPublicAsn"},
12772 [BGP_STATS_MAX
] = {NULL
, NULL
}
12775 struct bgp_table_stats
{
12776 struct bgp_table
*table
;
12777 unsigned long long counts
[BGP_STATS_MAX
];
12778 double total_space
;
12781 static void bgp_table_stats_rn(struct bgp_dest
*dest
, struct bgp_dest
*top
,
12782 struct bgp_table_stats
*ts
, unsigned int space
)
12784 struct bgp_dest
*pdest
= bgp_dest_parent_nolock(dest
);
12785 struct bgp_path_info
*pi
;
12786 const struct prefix
*rn_p
;
12788 if (!bgp_dest_has_bgp_path_info_data(dest
))
12791 rn_p
= bgp_dest_get_prefix(dest
);
12792 ts
->counts
[BGP_STATS_PREFIXES
]++;
12793 ts
->counts
[BGP_STATS_TOTPLEN
] += rn_p
->prefixlen
;
12795 /* check if the prefix is included by any other announcements */
12796 while (pdest
&& !bgp_dest_has_bgp_path_info_data(pdest
))
12797 pdest
= bgp_dest_parent_nolock(pdest
);
12799 if (pdest
== NULL
|| pdest
== top
) {
12800 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
12801 /* announced address space */
12803 ts
->total_space
+= pow(2.0, space
- rn_p
->prefixlen
);
12804 } else if (bgp_dest_has_bgp_path_info_data(pdest
))
12805 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
12808 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
12809 ts
->counts
[BGP_STATS_RIB
]++;
12811 if (CHECK_FLAG(pi
->attr
->flag
,
12812 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)))
12813 ts
->counts
[BGP_STATS_AGGREGATES
]++;
12815 /* as-path stats */
12816 if (pi
->attr
->aspath
) {
12817 unsigned int hops
= aspath_count_hops(pi
->attr
->aspath
);
12818 unsigned int size
= aspath_size(pi
->attr
->aspath
);
12819 as_t highest
= aspath_highest(pi
->attr
->aspath
);
12821 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
12823 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
12824 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] = hops
;
12826 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
12827 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] = size
;
12829 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
12830 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
12831 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
12832 ts
->counts
[BGP_STATS_ASN_HIGHEST
] = highest
;
12837 static int bgp_table_stats_walker(struct thread
*t
)
12839 struct bgp_dest
*dest
, *ndest
;
12840 struct bgp_dest
*top
;
12841 struct bgp_table_stats
*ts
= THREAD_ARG(t
);
12842 unsigned int space
= 0;
12844 if (!(top
= bgp_table_top(ts
->table
)))
12847 switch (ts
->table
->afi
) {
12849 space
= IPV4_MAX_BITLEN
;
12852 space
= IPV6_MAX_BITLEN
;
12855 space
= EVPN_ROUTE_PREFIXLEN
;
12861 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
12863 for (dest
= top
; dest
; dest
= bgp_route_next(dest
)) {
12864 if (ts
->table
->safi
== SAFI_MPLS_VPN
12865 || ts
->table
->safi
== SAFI_ENCAP
12866 || ts
->table
->safi
== SAFI_EVPN
) {
12867 struct bgp_table
*table
;
12869 table
= bgp_dest_get_bgp_table_info(dest
);
12873 top
= bgp_table_top(table
);
12874 for (ndest
= bgp_table_top(table
); ndest
;
12875 ndest
= bgp_route_next(ndest
))
12876 bgp_table_stats_rn(ndest
, top
, ts
, space
);
12878 bgp_table_stats_rn(dest
, top
, ts
, space
);
12885 static void bgp_table_stats_all(struct vty
*vty
, afi_t afi
, safi_t safi
,
12886 struct json_object
*json_array
)
12888 struct listnode
*node
, *nnode
;
12891 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
))
12892 bgp_table_stats_single(vty
, bgp
, afi
, safi
, json_array
);
12895 static int bgp_table_stats_single(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12896 safi_t safi
, struct json_object
*json_array
)
12898 struct bgp_table_stats ts
;
12900 int ret
= CMD_SUCCESS
;
12902 struct json_object
*json
= NULL
;
12905 json
= json_object_new_object();
12907 if (!bgp
->rib
[afi
][safi
]) {
12908 char warning_msg
[50];
12910 snprintf(warning_msg
, sizeof(warning_msg
),
12911 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi
,
12915 vty_out(vty
, "%s\n", warning_msg
);
12917 json_object_string_add(json
, "warning", warning_msg
);
12920 goto end_table_stats
;
12924 vty_out(vty
, "BGP %s RIB statistics (%s)\n",
12925 get_afi_safi_str(afi
, safi
, false), bgp
->name_pretty
);
12927 json_object_string_add(json
, "instance", bgp
->name_pretty
);
12929 /* labeled-unicast routes live in the unicast table */
12930 if (safi
== SAFI_LABELED_UNICAST
)
12931 safi
= SAFI_UNICAST
;
12933 memset(&ts
, 0, sizeof(ts
));
12934 ts
.table
= bgp
->rib
[afi
][safi
];
12935 thread_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
12937 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
12938 if ((!json
&& !table_stats_strs
[i
][TABLE_STATS_IDX_VTY
])
12939 || (json
&& !table_stats_strs
[i
][TABLE_STATS_IDX_JSON
]))
12943 case BGP_STATS_ASPATH_TOTHOPS
:
12944 case BGP_STATS_ASPATH_TOTSIZE
:
12947 temp_buf
, sizeof(temp_buf
), "%12.2f",
12949 ? (float)ts
.counts
[i
]
12951 [BGP_STATS_ASPATH_COUNT
]
12953 vty_out(vty
, "%-30s: %s",
12954 table_stats_strs
[i
]
12955 [TABLE_STATS_IDX_VTY
],
12958 json_object_double_add(
12960 table_stats_strs
[i
]
12961 [TABLE_STATS_IDX_JSON
],
12963 ? (double)ts
.counts
[i
]
12964 / (double)ts
.counts
12965 [BGP_STATS_ASPATH_COUNT
]
12969 case BGP_STATS_TOTPLEN
:
12972 temp_buf
, sizeof(temp_buf
), "%12.2f",
12974 ? (float)ts
.counts
[i
]
12976 [BGP_STATS_PREFIXES
]
12978 vty_out(vty
, "%-30s: %s",
12979 table_stats_strs
[i
]
12980 [TABLE_STATS_IDX_VTY
],
12983 json_object_double_add(
12985 table_stats_strs
[i
]
12986 [TABLE_STATS_IDX_JSON
],
12988 ? (double)ts
.counts
[i
]
12989 / (double)ts
.counts
12990 [BGP_STATS_PREFIXES
]
12994 case BGP_STATS_SPACE
:
12996 snprintf(temp_buf
, sizeof(temp_buf
), "%12g",
12998 vty_out(vty
, "%-30s: %s\n",
12999 table_stats_strs
[i
]
13000 [TABLE_STATS_IDX_VTY
],
13003 json_object_double_add(
13005 table_stats_strs
[i
]
13006 [TABLE_STATS_IDX_JSON
],
13007 (double)ts
.total_space
);
13009 if (afi
== AFI_IP6
) {
13011 snprintf(temp_buf
, sizeof(temp_buf
),
13014 * pow(2.0, -128 + 32));
13015 vty_out(vty
, "%30s: %s\n",
13016 "/32 equivalent %s\n",
13019 json_object_double_add(
13020 json
, "/32equivalent",
13021 (double)(ts
.total_space
13026 snprintf(temp_buf
, sizeof(temp_buf
),
13029 * pow(2.0, -128 + 48));
13030 vty_out(vty
, "%30s: %s\n",
13031 "/48 equivalent %s\n",
13034 json_object_double_add(
13035 json
, "/48equivalent",
13036 (double)(ts
.total_space
13042 snprintf(temp_buf
, sizeof(temp_buf
),
13044 ts
.total_space
* 100.
13046 vty_out(vty
, "%30s: %s\n",
13047 "% announced ", temp_buf
);
13049 json_object_double_add(
13050 json
, "%announced",
13051 (double)(ts
.total_space
* 100.
13055 snprintf(temp_buf
, sizeof(temp_buf
),
13058 * pow(2.0, -32 + 8));
13059 vty_out(vty
, "%30s: %s\n",
13060 "/8 equivalent ", temp_buf
);
13062 json_object_double_add(
13063 json
, "/8equivalent",
13064 (double)(ts
.total_space
13065 * pow(2.0, -32 + 8)));
13068 snprintf(temp_buf
, sizeof(temp_buf
),
13071 * pow(2.0, -32 + 24));
13072 vty_out(vty
, "%30s: %s\n",
13073 "/24 equivalent ", temp_buf
);
13075 json_object_double_add(
13076 json
, "/24equivalent",
13077 (double)(ts
.total_space
13078 * pow(2.0, -32 + 24)));
13084 snprintf(temp_buf
, sizeof(temp_buf
), "%12llu",
13086 vty_out(vty
, "%-30s: %s",
13087 table_stats_strs
[i
]
13088 [TABLE_STATS_IDX_VTY
],
13091 json_object_int_add(
13093 table_stats_strs
[i
]
13094 [TABLE_STATS_IDX_JSON
],
13099 vty_out(vty
, "\n");
13103 json_object_array_add(json_array
, json
);
13107 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
13108 safi_t safi
, struct json_object
*json_array
)
13111 bgp_table_stats_all(vty
, afi
, safi
, json_array
);
13112 return CMD_SUCCESS
;
13115 return bgp_table_stats_single(vty
, bgp
, afi
, safi
, json_array
);
13127 PCOUNT_BPATH_SELECTED
,
13128 PCOUNT_PFCNT
, /* the figure we display to users */
13132 static const char *const pcount_strs
[] = {
13133 [PCOUNT_ADJ_IN
] = "Adj-in",
13134 [PCOUNT_DAMPED
] = "Damped",
13135 [PCOUNT_REMOVED
] = "Removed",
13136 [PCOUNT_HISTORY
] = "History",
13137 [PCOUNT_STALE
] = "Stale",
13138 [PCOUNT_VALID
] = "Valid",
13139 [PCOUNT_ALL
] = "All RIB",
13140 [PCOUNT_COUNTED
] = "PfxCt counted",
13141 [PCOUNT_BPATH_SELECTED
] = "PfxCt Best Selected",
13142 [PCOUNT_PFCNT
] = "Useable",
13143 [PCOUNT_MAX
] = NULL
,
13146 struct peer_pcounts
{
13147 unsigned int count
[PCOUNT_MAX
];
13148 const struct peer
*peer
;
13149 const struct bgp_table
*table
;
13153 static void bgp_peer_count_proc(struct bgp_dest
*rn
, struct peer_pcounts
*pc
)
13155 const struct bgp_adj_in
*ain
;
13156 const struct bgp_path_info
*pi
;
13157 const struct peer
*peer
= pc
->peer
;
13159 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
13160 if (ain
->peer
== peer
)
13161 pc
->count
[PCOUNT_ADJ_IN
]++;
13163 for (pi
= bgp_dest_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
13165 if (pi
->peer
!= peer
)
13168 pc
->count
[PCOUNT_ALL
]++;
13170 if (CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
))
13171 pc
->count
[PCOUNT_DAMPED
]++;
13172 if (CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
13173 pc
->count
[PCOUNT_HISTORY
]++;
13174 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
13175 pc
->count
[PCOUNT_REMOVED
]++;
13176 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
13177 pc
->count
[PCOUNT_STALE
]++;
13178 if (CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
13179 pc
->count
[PCOUNT_VALID
]++;
13180 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
13181 pc
->count
[PCOUNT_PFCNT
]++;
13182 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
13183 pc
->count
[PCOUNT_BPATH_SELECTED
]++;
13185 if (CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
13186 pc
->count
[PCOUNT_COUNTED
]++;
13187 if (CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
13189 EC_LIB_DEVELOPMENT
,
13190 "Attempting to count but flags say it is unusable");
13192 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
13194 EC_LIB_DEVELOPMENT
,
13195 "Not counted but flags say we should");
13200 static int bgp_peer_count_walker(struct thread
*t
)
13202 struct bgp_dest
*rn
, *rm
;
13203 const struct bgp_table
*table
;
13204 struct peer_pcounts
*pc
= THREAD_ARG(t
);
13206 if (pc
->safi
== SAFI_MPLS_VPN
|| pc
->safi
== SAFI_ENCAP
13207 || pc
->safi
== SAFI_EVPN
) {
13208 /* Special handling for 2-level routing tables. */
13209 for (rn
= bgp_table_top(pc
->table
); rn
;
13210 rn
= bgp_route_next(rn
)) {
13211 table
= bgp_dest_get_bgp_table_info(rn
);
13213 for (rm
= bgp_table_top(table
); rm
;
13214 rm
= bgp_route_next(rm
))
13215 bgp_peer_count_proc(rm
, pc
);
13218 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
))
13219 bgp_peer_count_proc(rn
, pc
);
13224 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
13225 safi_t safi
, bool use_json
)
13227 struct peer_pcounts pcounts
= {.peer
= peer
};
13229 json_object
*json
= NULL
;
13230 json_object
*json_loop
= NULL
;
13233 json
= json_object_new_object();
13234 json_loop
= json_object_new_object();
13237 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
13238 || !peer
->bgp
->rib
[afi
][safi
]) {
13240 json_object_string_add(
13242 "No such neighbor or address family");
13243 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
13244 json_object_free(json
);
13245 json_object_free(json_loop
);
13247 vty_out(vty
, "%% No such neighbor or address family\n");
13249 return CMD_WARNING
;
13252 memset(&pcounts
, 0, sizeof(pcounts
));
13253 pcounts
.peer
= peer
;
13254 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
13255 pcounts
.safi
= safi
;
13257 /* in-place call via thread subsystem so as to record execution time
13258 * stats for the thread-walk (i.e. ensure this can't be blamed on
13259 * on just vty_read()).
13261 thread_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
13264 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
13265 json_object_string_add(json
, "multiProtocol",
13266 get_afi_safi_str(afi
, safi
, true));
13267 json_object_int_add(json
, "pfxCounter",
13268 peer
->pcount
[afi
][safi
]);
13270 for (i
= 0; i
< PCOUNT_MAX
; i
++)
13271 json_object_int_add(json_loop
, pcount_strs
[i
],
13274 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
13276 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
13277 json_object_string_add(json
, "pfxctDriftFor",
13279 json_object_string_add(
13280 json
, "recommended",
13281 "Please report this bug, with the above command output");
13283 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
13284 json
, JSON_C_TO_STRING_PRETTY
));
13285 json_object_free(json
);
13289 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_HOSTNAME
)) {
13290 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
13291 peer
->hostname
, peer
->host
,
13292 get_afi_safi_str(afi
, safi
, false));
13294 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
13295 get_afi_safi_str(afi
, safi
, false));
13298 vty_out(vty
, "PfxCt: %u\n", peer
->pcount
[afi
][safi
]);
13299 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
13301 for (i
= 0; i
< PCOUNT_MAX
; i
++)
13302 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
13305 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
13306 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
13308 "Please report this bug, with the above command output\n");
13312 return CMD_SUCCESS
;
13315 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
13316 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
13317 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_CMD_STR
"]] neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
13321 BGP_INSTANCE_HELP_STR
13324 "Detailed information on TCP and BGP neighbor connections\n"
13325 "Neighbor to display information about\n"
13326 "Neighbor to display information about\n"
13327 "Neighbor on BGP configured interface\n"
13328 "Display detailed prefix count information\n"
13331 afi_t afi
= AFI_IP6
;
13332 safi_t safi
= SAFI_UNICAST
;
13335 struct bgp
*bgp
= NULL
;
13336 bool uj
= use_json(argc
, argv
);
13341 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13344 return CMD_WARNING
;
13346 argv_find(argv
, argc
, "neighbors", &idx
);
13347 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
13349 return CMD_WARNING
;
13351 return bgp_peer_counts(vty
, peer
, afi
, safi
, uj
);
13354 #ifdef KEEP_OLD_VPN_COMMANDS
13355 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
13356 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
13357 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
13362 "Display information about all VPNv4 NLRIs\n"
13363 "Detailed information on TCP and BGP neighbor connections\n"
13364 "Neighbor to display information about\n"
13365 "Neighbor to display information about\n"
13366 "Neighbor on BGP configured interface\n"
13367 "Display detailed prefix count information\n"
13372 bool uj
= use_json(argc
, argv
);
13374 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
13376 return CMD_WARNING
;
13378 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
13381 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
13382 show_ip_bgp_vpn_all_route_prefix_cmd
,
13383 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
13388 "Display information about all VPNv4 NLRIs\n"
13389 "Network in the BGP routing table to display\n"
13390 "Network in the BGP routing table to display\n"
13394 char *network
= NULL
;
13395 struct bgp
*bgp
= bgp_get_default();
13397 vty_out(vty
, "Can't find default instance\n");
13398 return CMD_WARNING
;
13401 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
13402 network
= argv
[idx
]->arg
;
13403 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
13404 network
= argv
[idx
]->arg
;
13406 vty_out(vty
, "Unable to figure out Network\n");
13407 return CMD_WARNING
;
13410 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
13411 BGP_PATH_SHOW_ALL
, RPKI_NOT_BEING_USED
,
13412 use_json(argc
, argv
));
13414 #endif /* KEEP_OLD_VPN_COMMANDS */
13416 DEFUN (show_bgp_l2vpn_evpn_route_prefix
,
13417 show_bgp_l2vpn_evpn_route_prefix_cmd
,
13418 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
13423 "Network in the BGP routing table to display\n"
13424 "Network in the BGP routing table to display\n"
13425 "Network in the BGP routing table to display\n"
13426 "Network in the BGP routing table to display\n"
13430 char *network
= NULL
;
13431 int prefix_check
= 0;
13433 if (argv_find(argv
, argc
, "A.B.C.D", &idx
) ||
13434 argv_find(argv
, argc
, "X:X::X:X", &idx
))
13435 network
= argv
[idx
]->arg
;
13436 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
) ||
13437 argv_find(argv
, argc
, "X:X::X:X/M", &idx
)) {
13438 network
= argv
[idx
]->arg
;
13441 vty_out(vty
, "Unable to figure out Network\n");
13442 return CMD_WARNING
;
13444 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
,
13445 prefix_check
, BGP_PATH_SHOW_ALL
,
13446 RPKI_NOT_BEING_USED
, use_json(argc
, argv
));
13449 static void show_adj_route_header(struct vty
*vty
, struct bgp
*bgp
,
13450 struct bgp_table
*table
, int *header1
,
13451 int *header2
, json_object
*json
,
13452 json_object
*json_scode
,
13453 json_object
*json_ocode
, bool wide
)
13455 uint64_t version
= table
? table
->version
: 0;
13456 char buf
[BUFSIZ
] = {0};
13460 json_object_int_add(json
, "bgpTableVersion", version
);
13461 json_object_string_add(json
, "bgpLocalRouterId",
13463 &bgp
->router_id
, buf
,
13465 json_object_int_add(json
, "defaultLocPrf",
13466 bgp
->default_local_pref
);
13467 json_object_int_add(json
, "localAS", bgp
->as
);
13468 json_object_object_add(json
, "bgpStatusCodes",
13470 json_object_object_add(json
, "bgpOriginCodes",
13474 "BGP table version is %" PRIu64
13475 ", local router ID is %pI4, vrf id ",
13476 version
, &bgp
->router_id
);
13477 if (bgp
->vrf_id
== VRF_UNKNOWN
)
13478 vty_out(vty
, "%s", VRFID_NONE_STR
);
13480 vty_out(vty
, "%u", bgp
->vrf_id
);
13481 vty_out(vty
, "\n");
13482 vty_out(vty
, "Default local pref %u, ",
13483 bgp
->default_local_pref
);
13484 vty_out(vty
, "local AS %u\n", bgp
->as
);
13485 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
13486 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
13487 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
13488 vty_out(vty
, BGP_SHOW_RPKI_HEADER
);
13494 vty_out(vty
, (wide
? BGP_SHOW_HEADER_WIDE
13495 : BGP_SHOW_HEADER
));
13501 show_adj_route(struct vty
*vty
, struct peer
*peer
, struct bgp_table
*table
,
13502 afi_t afi
, safi_t safi
, enum bgp_show_adj_route_type type
,
13503 const char *rmap_name
, json_object
*json
, json_object
*json_ar
,
13504 json_object
*json_scode
, json_object
*json_ocode
,
13505 uint16_t show_flags
, int *header1
, int *header2
, char *rd_str
,
13506 unsigned long *output_count
, unsigned long *filtered_count
)
13508 struct bgp_adj_in
*ain
;
13509 struct bgp_adj_out
*adj
;
13510 struct bgp_dest
*dest
;
13514 struct update_subgroup
*subgrp
;
13515 struct peer_af
*paf
;
13516 bool route_filtered
;
13517 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13518 bool wide
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
13519 bool show_rd
= ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
13520 || (safi
== SAFI_EVPN
))
13528 json_object_string_add(json
, "alert", "no BGP");
13529 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
13530 json_object_free(json
);
13532 vty_out(vty
, "%% No bgp\n");
13536 subgrp
= peer_subgroup(peer
, afi
, safi
);
13538 if (type
== bgp_show_adj_route_advertised
&& subgrp
13539 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
13540 char buf
[BUFSIZ
] = {0};
13543 json_object_int_add(json
, "bgpTableVersion",
13545 json_object_string_add(json
, "bgpLocalRouterId",
13547 &bgp
->router_id
, buf
,
13549 json_object_int_add(json
, "defaultLocPrf",
13550 bgp
->default_local_pref
);
13551 json_object_int_add(json
, "localAS", bgp
->as
);
13552 json_object_object_add(json
, "bgpStatusCodes",
13554 json_object_object_add(json
, "bgpOriginCodes",
13556 json_object_string_add(
13557 json
, "bgpOriginatingDefaultNetwork",
13558 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
13561 "BGP table version is %" PRIu64
13562 ", local router ID is %pI4, vrf id ",
13563 table
->version
, &bgp
->router_id
);
13564 if (bgp
->vrf_id
== VRF_UNKNOWN
)
13565 vty_out(vty
, "%s", VRFID_NONE_STR
);
13567 vty_out(vty
, "%u", bgp
->vrf_id
);
13568 vty_out(vty
, "\n");
13569 vty_out(vty
, "Default local pref %u, ",
13570 bgp
->default_local_pref
);
13571 vty_out(vty
, "local AS %u\n", bgp
->as
);
13572 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
13573 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
13574 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
13575 vty_out(vty
, BGP_SHOW_RPKI_HEADER
);
13577 vty_out(vty
, "Originating default network %s\n\n",
13578 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
13583 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
13584 if (type
== bgp_show_adj_route_received
13585 || type
== bgp_show_adj_route_filtered
) {
13586 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
13587 if (ain
->peer
!= peer
)
13590 show_adj_route_header(vty
, bgp
, table
, header1
,
13591 header2
, json
, json_scode
,
13594 if ((safi
== SAFI_MPLS_VPN
)
13595 || (safi
== SAFI_ENCAP
)
13596 || (safi
== SAFI_EVPN
)) {
13598 json_object_string_add(
13599 json_ar
, "rd", rd_str
);
13600 else if (show_rd
&& rd_str
) {
13602 "Route Distinguisher: %s\n",
13609 route_filtered
= false;
13611 /* Filter prefix using distribute list,
13612 * filter list or prefix list
13614 const struct prefix
*rn_p
=
13615 bgp_dest_get_prefix(dest
);
13616 if ((bgp_input_filter(peer
, rn_p
, &attr
, afi
,
13619 route_filtered
= true;
13621 /* Filter prefix using route-map */
13622 ret
= bgp_input_modifier(peer
, rn_p
, &attr
, afi
,
13623 safi
, rmap_name
, NULL
,
13626 if (type
== bgp_show_adj_route_filtered
&&
13627 !route_filtered
&& ret
!= RMAP_DENY
) {
13628 bgp_attr_undup(&attr
, ain
->attr
);
13632 if (type
== bgp_show_adj_route_received
13633 && (route_filtered
|| ret
== RMAP_DENY
))
13634 (*filtered_count
)++;
13636 route_vty_out_tmp(vty
, dest
, rn_p
, &attr
, safi
,
13637 use_json
, json_ar
, wide
);
13638 bgp_attr_undup(&attr
, ain
->attr
);
13641 } else if (type
== bgp_show_adj_route_advertised
) {
13642 RB_FOREACH (adj
, bgp_adj_out_rb
, &dest
->adj_out
)
13643 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
13644 if (paf
->peer
!= peer
|| !adj
->attr
)
13647 show_adj_route_header(vty
, bgp
, table
,
13652 const struct prefix
*rn_p
=
13653 bgp_dest_get_prefix(dest
);
13656 ret
= bgp_output_modifier(
13657 peer
, rn_p
, &attr
, afi
, safi
,
13660 if (ret
!= RMAP_DENY
) {
13661 if ((safi
== SAFI_MPLS_VPN
)
13662 || (safi
== SAFI_ENCAP
)
13663 || (safi
== SAFI_EVPN
)) {
13665 json_object_string_add(
13672 "Route Distinguisher: %s\n",
13678 vty
, dest
, rn_p
, &attr
,
13679 safi
, use_json
, json_ar
,
13683 (*filtered_count
)++;
13686 bgp_attr_undup(&attr
, adj
->attr
);
13688 } else if (type
== bgp_show_adj_route_bestpath
) {
13689 struct bgp_path_info
*pi
;
13691 show_adj_route_header(vty
, bgp
, table
, header1
, header2
,
13692 json
, json_scode
, json_ocode
,
13695 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
13697 if (pi
->peer
!= peer
)
13700 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
13703 route_vty_out_tmp(vty
, dest
,
13704 bgp_dest_get_prefix(dest
),
13705 pi
->attr
, safi
, use_json
,
13713 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
13714 safi_t safi
, enum bgp_show_adj_route_type type
,
13715 const char *rmap_name
, uint16_t show_flags
)
13718 struct bgp_table
*table
;
13719 json_object
*json
= NULL
;
13720 json_object
*json_scode
= NULL
;
13721 json_object
*json_ocode
= NULL
;
13722 json_object
*json_ar
= NULL
;
13723 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13725 /* Init BGP headers here so they're only displayed once
13726 * even if 'table' is 2-tier (MPLS_VPN, ENCAP, EVPN).
13732 * Initialize variables for each RD
13733 * All prefixes under an RD is aggregated within "json_routes"
13735 char rd_str
[BUFSIZ
] = {0};
13736 json_object
*json_routes
= NULL
;
13739 /* For 2-tier tables, prefix counts need to be
13740 * maintained across multiple runs of show_adj_route()
13742 unsigned long output_count_per_rd
;
13743 unsigned long filtered_count_per_rd
;
13744 unsigned long output_count
= 0;
13745 unsigned long filtered_count
= 0;
13748 json
= json_object_new_object();
13749 json_ar
= json_object_new_object();
13750 json_scode
= json_object_new_object();
13751 json_ocode
= json_object_new_object();
13753 json_object_string_add(json_scode
, "suppressed", "s");
13754 json_object_string_add(json_scode
, "damped", "d");
13755 json_object_string_add(json_scode
, "history", "h");
13756 json_object_string_add(json_scode
, "valid", "*");
13757 json_object_string_add(json_scode
, "best", ">");
13758 json_object_string_add(json_scode
, "multipath", "=");
13759 json_object_string_add(json_scode
, "internal", "i");
13760 json_object_string_add(json_scode
, "ribFailure", "r");
13761 json_object_string_add(json_scode
, "stale", "S");
13762 json_object_string_add(json_scode
, "removed", "R");
13764 json_object_string_add(json_ocode
, "igp", "i");
13765 json_object_string_add(json_ocode
, "egp", "e");
13766 json_object_string_add(json_ocode
, "incomplete", "?");
13769 if (!peer
|| !peer
->afc
[afi
][safi
]) {
13771 json_object_string_add(
13773 "No such neighbor or address family");
13774 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
13775 json_object_free(json
);
13777 vty_out(vty
, "%% No such neighbor or address family\n");
13779 return CMD_WARNING
;
13782 if ((type
== bgp_show_adj_route_received
13783 || type
== bgp_show_adj_route_filtered
)
13784 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
13785 PEER_FLAG_SOFT_RECONFIG
)) {
13787 json_object_string_add(
13789 "Inbound soft reconfiguration not enabled");
13790 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
13791 json_object_free(json
);
13794 "%% Inbound soft reconfiguration not enabled\n");
13796 return CMD_WARNING
;
13801 /* labeled-unicast routes live in the unicast table */
13802 if (safi
== SAFI_LABELED_UNICAST
)
13803 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
13805 table
= bgp
->rib
[afi
][safi
];
13807 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
13808 || (safi
== SAFI_EVPN
)) {
13810 struct bgp_dest
*dest
;
13812 for (dest
= bgp_table_top(table
); dest
;
13813 dest
= bgp_route_next(dest
)) {
13814 table
= bgp_dest_get_bgp_table_info(dest
);
13818 output_count_per_rd
= 0;
13819 filtered_count_per_rd
= 0;
13822 json_routes
= json_object_new_object();
13824 const struct prefix_rd
*prd
;
13825 prd
= (const struct prefix_rd
*)bgp_dest_get_prefix(
13828 prefix_rd2str(prd
, rd_str
, sizeof(rd_str
));
13830 show_adj_route(vty
, peer
, table
, afi
, safi
, type
,
13831 rmap_name
, json
, json_routes
, json_scode
,
13832 json_ocode
, show_flags
, &header1
,
13833 &header2
, rd_str
, &output_count_per_rd
,
13834 &filtered_count_per_rd
);
13836 /* Don't include an empty RD in the output! */
13837 if (json_routes
&& (output_count_per_rd
> 0))
13838 json_object_object_add(json_ar
, rd_str
,
13841 output_count
+= output_count_per_rd
;
13842 filtered_count
+= filtered_count_per_rd
;
13845 show_adj_route(vty
, peer
, table
, afi
, safi
, type
, rmap_name
,
13846 json
, json_ar
, json_scode
, json_ocode
,
13847 show_flags
, &header1
, &header2
, rd_str
,
13848 &output_count
, &filtered_count
);
13851 json_object_object_add(json
, "advertisedRoutes", json_ar
);
13852 json_object_int_add(json
, "totalPrefixCounter", output_count
);
13853 json_object_int_add(json
, "filteredPrefixCounter",
13856 vty_out(vty
, "%s\n",
13857 json_object_to_json_string_ext(
13858 json
, JSON_C_TO_STRING_PRETTY
));
13860 if (!output_count
&& !filtered_count
) {
13861 json_object_free(json_scode
);
13862 json_object_free(json_ocode
);
13866 json_object_free(json
);
13868 } else if (output_count
> 0) {
13869 if (filtered_count
> 0)
13871 "\nTotal number of prefixes %ld (%ld filtered)\n",
13872 output_count
, filtered_count
);
13874 vty_out(vty
, "\nTotal number of prefixes %ld\n",
13878 return CMD_SUCCESS
;
13881 DEFPY (show_ip_bgp_instance_neighbor_bestpath_route
,
13882 show_ip_bgp_instance_neighbor_bestpath_route_cmd
,
13883 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] neighbors <A.B.C.D|X:X::X:X|WORD> bestpath-routes [json$uj | wide$wide]",
13887 BGP_INSTANCE_HELP_STR
13889 BGP_SAFI_WITH_LABEL_HELP_STR
13890 "Detailed information on TCP and BGP neighbor connections\n"
13891 "Neighbor to display information about\n"
13892 "Neighbor to display information about\n"
13893 "Neighbor on BGP configured interface\n"
13894 "Display the routes selected by best path\n"
13896 "Increase table width for longer prefixes\n")
13898 afi_t afi
= AFI_IP6
;
13899 safi_t safi
= SAFI_UNICAST
;
13900 char *rmap_name
= NULL
;
13901 char *peerstr
= NULL
;
13902 struct bgp
*bgp
= NULL
;
13904 enum bgp_show_adj_route_type type
= bgp_show_adj_route_bestpath
;
13906 uint16_t show_flags
= 0;
13909 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13912 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
13914 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13918 return CMD_WARNING
;
13920 argv_find(argv
, argc
, "neighbors", &idx
);
13921 peerstr
= argv
[++idx
]->arg
;
13923 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
13925 return CMD_WARNING
;
13927 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
,
13931 DEFPY (show_ip_bgp_instance_neighbor_advertised_route
,
13932 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
13933 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [all$all] neighbors <A.B.C.D|X:X::X:X|WORD> <advertised-routes|received-routes|filtered-routes> [route-map WORD] [json$uj | wide$wide]",
13937 BGP_INSTANCE_HELP_STR
13939 BGP_SAFI_WITH_LABEL_HELP_STR
13940 "Display the entries for all address families\n"
13941 "Detailed information on TCP and BGP neighbor connections\n"
13942 "Neighbor to display information about\n"
13943 "Neighbor to display information about\n"
13944 "Neighbor on BGP configured interface\n"
13945 "Display the routes advertised to a BGP neighbor\n"
13946 "Display the received routes from neighbor\n"
13947 "Display the filtered routes received from neighbor\n"
13948 "Route-map to modify the attributes\n"
13949 "Name of the route map\n"
13951 "Increase table width for longer prefixes\n")
13953 afi_t afi
= AFI_IP6
;
13954 safi_t safi
= SAFI_UNICAST
;
13955 char *rmap_name
= NULL
;
13956 char *peerstr
= NULL
;
13957 struct bgp
*bgp
= NULL
;
13959 enum bgp_show_adj_route_type type
= bgp_show_adj_route_advertised
;
13962 uint16_t show_flags
= 0;
13966 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13970 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
13971 if (argv_find(argv
, argc
, "ipv4", &idx
))
13972 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
13974 if (argv_find(argv
, argc
, "ipv6", &idx
))
13975 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
13979 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
13981 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13984 return CMD_WARNING
;
13986 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13987 argv_find(argv
, argc
, "neighbors", &idx
);
13988 peerstr
= argv
[++idx
]->arg
;
13990 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
13992 return CMD_WARNING
;
13994 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
13995 type
= bgp_show_adj_route_advertised
;
13996 else if (argv_find(argv
, argc
, "received-routes", &idx
))
13997 type
= bgp_show_adj_route_received
;
13998 else if (argv_find(argv
, argc
, "filtered-routes", &idx
))
13999 type
= bgp_show_adj_route_filtered
;
14001 if (argv_find(argv
, argc
, "route-map", &idx
))
14002 rmap_name
= argv
[++idx
]->arg
;
14005 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
,
14008 vty_out(vty
, "{\n");
14010 if (CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
14011 || CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
)) {
14012 afi
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
) ? AFI_IP
14014 FOREACH_SAFI (safi
) {
14015 if (!bgp_afi_safi_peer_exists(bgp
, afi
, safi
))
14022 vty_out(vty
, ",\n");
14023 vty_out(vty
, "\"%s\":",
14024 get_afi_safi_str(afi
, safi
, true));
14026 vty_out(vty
, "\nFor address family: %s\n",
14027 get_afi_safi_str(afi
, safi
, false));
14029 peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
,
14033 FOREACH_AFI_SAFI (afi
, safi
) {
14034 if (!bgp_afi_safi_peer_exists(bgp
, afi
, safi
))
14041 vty_out(vty
, ",\n");
14042 vty_out(vty
, "\"%s\":",
14043 get_afi_safi_str(afi
, safi
, true));
14045 vty_out(vty
, "\nFor address family: %s\n",
14046 get_afi_safi_str(afi
, safi
, false));
14048 peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
,
14053 vty_out(vty
, "}\n");
14055 return CMD_SUCCESS
;
14058 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
14059 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
14060 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
14066 "Address Family modifier\n"
14067 "Detailed information on TCP and BGP neighbor connections\n"
14068 "Neighbor to display information about\n"
14069 "Neighbor to display information about\n"
14070 "Neighbor on BGP configured interface\n"
14071 "Display information received from a BGP neighbor\n"
14072 "Display the prefixlist filter\n"
14075 afi_t afi
= AFI_IP6
;
14076 safi_t safi
= SAFI_UNICAST
;
14077 char *peerstr
= NULL
;
14080 union sockunion su
;
14086 /* show [ip] bgp */
14087 if (argv_find(argv
, argc
, "ip", &idx
))
14089 /* [<ipv4|ipv6> [unicast]] */
14090 if (argv_find(argv
, argc
, "ipv4", &idx
))
14092 if (argv_find(argv
, argc
, "ipv6", &idx
))
14094 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14095 argv_find(argv
, argc
, "neighbors", &idx
);
14096 peerstr
= argv
[++idx
]->arg
;
14098 bool uj
= use_json(argc
, argv
);
14100 ret
= str2sockunion(peerstr
, &su
);
14102 peer
= peer_lookup_by_conf_if(NULL
, peerstr
);
14105 vty_out(vty
, "{}\n");
14108 "%% Malformed address or name: %s\n",
14110 return CMD_WARNING
;
14113 peer
= peer_lookup(NULL
, &su
);
14116 vty_out(vty
, "{}\n");
14118 vty_out(vty
, "No peer\n");
14119 return CMD_WARNING
;
14123 snprintf(name
, sizeof(name
), "%s.%d.%d", peer
->host
, afi
, safi
);
14124 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
14127 vty_out(vty
, "Address Family: %s\n",
14128 get_afi_safi_str(afi
, safi
, false));
14129 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
14132 vty_out(vty
, "{}\n");
14134 vty_out(vty
, "No functional output\n");
14137 return CMD_SUCCESS
;
14140 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
14141 afi_t afi
, safi_t safi
,
14142 enum bgp_show_type type
, bool use_json
)
14144 uint16_t show_flags
= 0;
14147 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14149 if (!peer
|| !peer
->afc
[afi
][safi
]) {
14151 json_object
*json_no
= NULL
;
14152 json_no
= json_object_new_object();
14153 json_object_string_add(
14154 json_no
, "warning",
14155 "No such neighbor or address family");
14156 vty_out(vty
, "%s\n",
14157 json_object_to_json_string(json_no
));
14158 json_object_free(json_no
);
14160 vty_out(vty
, "%% No such neighbor or address family\n");
14161 return CMD_WARNING
;
14164 /* labeled-unicast routes live in the unicast table */
14165 if (safi
== SAFI_LABELED_UNICAST
)
14166 safi
= SAFI_UNICAST
;
14168 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, show_flags
,
14169 RPKI_NOT_BEING_USED
);
14172 DEFUN (show_ip_bgp_flowspec_routes_detailed
,
14173 show_ip_bgp_flowspec_routes_detailed_cmd
,
14174 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" flowspec] detail [json]",
14178 BGP_INSTANCE_HELP_STR
14181 "Detailed information on flowspec entries\n"
14184 afi_t afi
= AFI_IP
;
14185 safi_t safi
= SAFI_UNICAST
;
14186 struct bgp
*bgp
= NULL
;
14188 bool uj
= use_json(argc
, argv
);
14189 uint16_t show_flags
= 0;
14193 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14196 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14199 return CMD_WARNING
;
14201 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_detail
, NULL
,
14202 show_flags
, RPKI_NOT_BEING_USED
);
14205 DEFUN (show_ip_bgp_neighbor_routes
,
14206 show_ip_bgp_neighbor_routes_cmd
,
14207 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] neighbors <A.B.C.D|X:X::X:X|WORD> <flap-statistics|dampened-routes|routes> [json]",
14211 BGP_INSTANCE_HELP_STR
14213 BGP_SAFI_WITH_LABEL_HELP_STR
14214 "Detailed information on TCP and BGP neighbor connections\n"
14215 "Neighbor to display information about\n"
14216 "Neighbor to display information about\n"
14217 "Neighbor on BGP configured interface\n"
14218 "Display flap statistics of the routes learned from neighbor\n"
14219 "Display the dampened routes received from neighbor\n"
14220 "Display routes learned from neighbor\n"
14223 char *peerstr
= NULL
;
14224 struct bgp
*bgp
= NULL
;
14225 afi_t afi
= AFI_IP6
;
14226 safi_t safi
= SAFI_UNICAST
;
14228 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
14230 bool uj
= use_json(argc
, argv
);
14235 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14238 return CMD_WARNING
;
14240 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14241 argv_find(argv
, argc
, "neighbors", &idx
);
14242 peerstr
= argv
[++idx
]->arg
;
14244 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14246 return CMD_WARNING
;
14248 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
14249 sh_type
= bgp_show_type_flap_neighbor
;
14250 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
14251 sh_type
= bgp_show_type_damp_neighbor
;
14252 else if (argv_find(argv
, argc
, "routes", &idx
))
14253 sh_type
= bgp_show_type_neighbor
;
14255 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
14258 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
14260 struct bgp_distance
{
14261 /* Distance value for the IP source prefix. */
14264 /* Name of the access-list to be matched. */
14268 DEFUN (show_bgp_afi_vpn_rd_route
,
14269 show_bgp_afi_vpn_rd_route_cmd
,
14270 "show bgp "BGP_AFI_CMD_STR
" vpn rd <ASN:NN_OR_IP-ADDRESS:NN|all> <A.B.C.D/M|X:X::X:X/M> [json]",
14274 "Address Family modifier\n"
14275 "Display information for a route distinguisher\n"
14276 "Route Distinguisher\n"
14277 "All Route Distinguishers\n"
14278 "Network in the BGP routing table to display\n"
14279 "Network in the BGP routing table to display\n"
14283 struct prefix_rd prd
;
14284 afi_t afi
= AFI_MAX
;
14287 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
14288 vty_out(vty
, "%% Malformed Address Family\n");
14289 return CMD_WARNING
;
14292 if (!strcmp(argv
[5]->arg
, "all"))
14293 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
,
14294 SAFI_MPLS_VPN
, NULL
, 0, BGP_PATH_SHOW_ALL
,
14295 RPKI_NOT_BEING_USED
,
14296 use_json(argc
, argv
));
14298 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
14300 vty_out(vty
, "%% Malformed Route Distinguisher\n");
14301 return CMD_WARNING
;
14304 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
14305 0, BGP_PATH_SHOW_ALL
, RPKI_NOT_BEING_USED
,
14306 use_json(argc
, argv
));
14309 static struct bgp_distance
*bgp_distance_new(void)
14311 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
14314 static void bgp_distance_free(struct bgp_distance
*bdistance
)
14316 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
14319 int bgp_distance_set(uint8_t distance
, const char *ip_str
,
14320 const char *access_list_str
, afi_t afi
, safi_t safi
,
14321 char *errmsg
, size_t errmsg_len
)
14325 struct bgp_dest
*dest
;
14326 struct bgp_distance
*bdistance
;
14328 ret
= str2prefix(ip_str
, &p
);
14330 snprintf(errmsg
, errmsg_len
, "Malformed prefix\n");
14331 return CMD_WARNING_CONFIG_FAILED
;
14334 /* Get BGP distance node. */
14335 dest
= bgp_node_get(bgp_distance_table
[afi
][safi
], &p
);
14336 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
14338 bgp_dest_unlock_node(dest
);
14340 bdistance
= bgp_distance_new();
14341 bgp_dest_set_bgp_distance_info(dest
, bdistance
);
14344 /* Set distance value. */
14345 bdistance
->distance
= distance
;
14347 /* Reset access-list configuration. */
14348 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
14349 if (access_list_str
)
14350 bdistance
->access_list
=
14351 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
14353 return CMD_SUCCESS
;
14356 int bgp_distance_unset(uint8_t distance
, const char *ip_str
,
14357 const char *access_list_str
, afi_t afi
, safi_t safi
,
14358 char *errmsg
, size_t errmsg_len
)
14362 struct bgp_dest
*dest
;
14363 struct bgp_distance
*bdistance
;
14365 ret
= str2prefix(ip_str
, &p
);
14367 snprintf(errmsg
, errmsg_len
, "Malformed prefix\n");
14368 return CMD_WARNING_CONFIG_FAILED
;
14371 dest
= bgp_node_lookup(bgp_distance_table
[afi
][safi
], &p
);
14373 snprintf(errmsg
, errmsg_len
, "Can't find specified prefix\n");
14374 return CMD_WARNING_CONFIG_FAILED
;
14377 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
14379 if (bdistance
->distance
!= distance
) {
14380 snprintf(errmsg
, errmsg_len
,
14381 "Distance does not match configured\n");
14382 bgp_dest_unlock_node(dest
);
14383 return CMD_WARNING_CONFIG_FAILED
;
14386 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
14387 bgp_distance_free(bdistance
);
14389 bgp_dest_set_bgp_path_info(dest
, NULL
);
14390 bgp_dest_unlock_node(dest
);
14391 bgp_dest_unlock_node(dest
);
14393 return CMD_SUCCESS
;
14396 /* Apply BGP information to distance method. */
14397 uint8_t bgp_distance_apply(const struct prefix
*p
, struct bgp_path_info
*pinfo
,
14398 afi_t afi
, safi_t safi
, struct bgp
*bgp
)
14400 struct bgp_dest
*dest
;
14401 struct prefix q
= {0};
14403 struct bgp_distance
*bdistance
;
14404 struct access_list
*alist
;
14405 struct bgp_static
*bgp_static
;
14410 peer
= pinfo
->peer
;
14412 if (pinfo
->attr
->distance
)
14413 return pinfo
->attr
->distance
;
14415 /* Check source address.
14416 * Note: for aggregate route, peer can have unspec af type.
14418 if (pinfo
->sub_type
!= BGP_ROUTE_AGGREGATE
14419 && !sockunion2hostprefix(&peer
->su
, &q
))
14422 dest
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
14424 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
14425 bgp_dest_unlock_node(dest
);
14427 if (bdistance
->access_list
) {
14428 alist
= access_list_lookup(afi
, bdistance
->access_list
);
14430 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
14431 return bdistance
->distance
;
14433 return bdistance
->distance
;
14436 /* Backdoor check. */
14437 dest
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
14439 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
14440 bgp_dest_unlock_node(dest
);
14442 if (bgp_static
->backdoor
) {
14443 if (bgp
->distance_local
[afi
][safi
])
14444 return bgp
->distance_local
[afi
][safi
];
14446 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
14450 if (peer
->sort
== BGP_PEER_EBGP
) {
14451 if (bgp
->distance_ebgp
[afi
][safi
])
14452 return bgp
->distance_ebgp
[afi
][safi
];
14453 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
14454 } else if (peer
->sort
== BGP_PEER_IBGP
) {
14455 if (bgp
->distance_ibgp
[afi
][safi
])
14456 return bgp
->distance_ibgp
[afi
][safi
];
14457 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
14459 if (bgp
->distance_local
[afi
][safi
])
14460 return bgp
->distance_local
[afi
][safi
];
14461 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
14465 /* If we enter `distance bgp (1-255) (1-255) (1-255)`,
14466 * we should tell ZEBRA update the routes for a specific
14467 * AFI/SAFI to reflect changes in RIB.
14469 void bgp_announce_routes_distance_update(struct bgp
*bgp
, afi_t update_afi
,
14470 safi_t update_safi
)
14475 FOREACH_AFI_SAFI (afi
, safi
) {
14476 if (!bgp_fibupd_safi(safi
))
14479 if (afi
!= update_afi
&& safi
!= update_safi
)
14482 if (BGP_DEBUG(zebra
, ZEBRA
))
14484 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
14485 __func__
, afi
, safi
);
14486 bgp_zebra_announce_table(bgp
, afi
, safi
);
14490 DEFUN_YANG(bgp_distance
, bgp_distance_cmd
,
14491 "distance bgp (1-255) (1-255) (1-255)",
14492 "Define an administrative distance\n"
14494 "Distance for routes external to the AS\n"
14495 "Distance for routes internal to the AS\n"
14496 "Distance for local routes\n")
14498 int idx_number
= 2;
14499 int idx_number_2
= 3;
14500 int idx_number_3
= 4;
14503 char xpath
[XPATH_MAXLEN
];
14505 afi
= bgp_node_afi(vty
);
14506 safi
= bgp_node_safi(vty
);
14509 xpath
, sizeof(xpath
),
14510 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/external",
14511 yang_afi_safi_value2identity(afi
, safi
),
14512 bgp_afi_safi_get_container_str(afi
, safi
));
14513 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
, argv
[idx_number
]->arg
);
14515 xpath
, sizeof(xpath
),
14516 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/internal",
14517 yang_afi_safi_value2identity(afi
, safi
),
14518 bgp_afi_safi_get_container_str(afi
, safi
));
14519 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
,
14520 argv
[idx_number_2
]->arg
);
14522 xpath
, sizeof(xpath
),
14523 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/local",
14524 yang_afi_safi_value2identity(afi
, safi
),
14525 bgp_afi_safi_get_container_str(afi
, safi
));
14527 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
,
14528 argv
[idx_number_3
]->arg
);
14530 return nb_cli_apply_changes(vty
, NULL
);
14533 DEFUN_YANG(no_bgp_distance
, no_bgp_distance_cmd
,
14534 "no distance bgp [(1-255) (1-255) (1-255)]",
14536 "Define an administrative distance\n"
14538 "Distance for routes external to the AS\n"
14539 "Distance for routes internal to the AS\n"
14540 "Distance for local routes\n")
14544 char xpath
[XPATH_MAXLEN
];
14546 afi
= bgp_node_afi(vty
);
14547 safi
= bgp_node_safi(vty
);
14550 xpath
, sizeof(xpath
),
14551 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/external",
14552 yang_afi_safi_value2identity(afi
, safi
),
14553 bgp_afi_safi_get_container_str(afi
, safi
));
14554 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
, NULL
);
14556 xpath
, sizeof(xpath
),
14557 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/internal",
14558 yang_afi_safi_value2identity(afi
, safi
),
14559 bgp_afi_safi_get_container_str(afi
, safi
));
14560 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
, NULL
);
14562 xpath
, sizeof(xpath
),
14563 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/local",
14564 yang_afi_safi_value2identity(afi
, safi
),
14565 bgp_afi_safi_get_container_str(afi
, safi
));
14567 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
, NULL
);
14569 return nb_cli_apply_changes(vty
, NULL
);
14572 void cli_show_bgp_global_afi_safi_admin_distance_config(struct vty
*vty
,
14573 struct lyd_node
*dnode
,
14574 bool show_defaults
)
14576 uint8_t distance_ebgp
, distance_ibgp
, distance_local
;
14578 distance_ebgp
= yang_dnode_get_uint8(dnode
, "./external");
14579 distance_ibgp
= yang_dnode_get_uint8(dnode
, "./internal");
14580 distance_local
= yang_dnode_get_uint8(dnode
, "./local");
14582 vty_out(vty
, " distance bgp %d %d %d\n", distance_ebgp
, distance_ibgp
,
14586 DEFPY_YANG(bgp_distance_source
,
14587 bgp_distance_source_cmd
,
14588 "[no] distance (1-255) <A.B.C.D/M | X:X::X:X/M>$prefix [WORD$acl]",
14590 "Define an administrative distance\n"
14592 "IPv4 source prefix\n"
14593 "IPv6 source prefix\n"
14594 "Access list name\n")
14598 char xpath
[XPATH_MAXLEN
];
14600 afi
= bgp_node_afi(vty
);
14601 safi
= bgp_node_safi(vty
);
14604 nb_cli_enqueue_change(vty
, ".", NB_OP_CREATE
, NULL
);
14605 nb_cli_enqueue_change(vty
, "./distance", NB_OP_MODIFY
,
14608 nb_cli_enqueue_change(vty
,
14609 "./access-list-policy-export",
14610 NB_OP_CREATE
, acl
);
14612 nb_cli_enqueue_change(vty
,
14613 "./access-list-policy-export",
14614 NB_OP_DESTROY
, NULL
);
14616 nb_cli_enqueue_change(vty
, ".", NB_OP_DESTROY
, NULL
);
14620 xpath
, sizeof(xpath
),
14621 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance-route[prefix='%s']",
14622 yang_afi_safi_value2identity(afi
, safi
),
14623 bgp_afi_safi_get_container_str(afi
, safi
), prefix_str
);
14625 return nb_cli_apply_changes(vty
, xpath
);
14628 void cli_show_bgp_global_afi_safi_unicast_admin_distance_route(
14629 struct vty
*vty
, struct lyd_node
*dnode
, bool show_defaults
)
14631 vty_out(vty
, " distance %d %s %s\n",
14632 yang_dnode_get_uint8(dnode
, "./distance"),
14633 yang_dnode_get_string(dnode
, "./prefix"),
14634 (yang_dnode_exists(dnode
, "./access-list-policy-export"))
14635 ? yang_dnode_get_string(dnode
,
14636 "./access-list-policy-export")
14641 bgp_dampening
, bgp_dampening_cmd
,
14642 "[no] bgp dampening [(1-45)$halflife [(1-20000)$reuse (1-20000)$suppress (1-255)$max_suppress]]",
14644 "BGP Specific commands\n"
14645 "Enable route-flap dampening\n"
14646 "Half-life time for the penalty\n"
14647 "Value to start reusing a route\n"
14648 "Value to start suppressing a route\n"
14649 "Maximum duration to suppress a stable route\n")
14653 char xpath
[XPATH_MAXLEN
];
14655 afi
= bgp_node_afi(vty
);
14656 safi
= bgp_node_safi(vty
);
14659 nb_cli_enqueue_change(vty
, "./enable", NB_OP_MODIFY
, "true");
14661 nb_cli_enqueue_change(vty
, "./reach-decay",
14662 NB_OP_MODIFY
, halflife_str
);
14663 nb_cli_enqueue_change(vty
, "./reuse-above",
14664 NB_OP_MODIFY
, reuse_str
);
14665 nb_cli_enqueue_change(vty
, "./suppress-above",
14666 NB_OP_MODIFY
, suppress_str
);
14667 nb_cli_enqueue_change(vty
, "./unreach-decay",
14668 NB_OP_MODIFY
, max_suppress_str
);
14670 nb_cli_enqueue_change(vty
, "./reach-decay",
14671 NB_OP_MODIFY
, halflife_str
);
14674 nb_cli_enqueue_change(vty
, "./enable", NB_OP_MODIFY
, "false");
14678 xpath
, sizeof(xpath
),
14679 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/route-flap-dampening",
14680 yang_afi_safi_value2identity(afi
, safi
),
14681 bgp_afi_safi_get_container_str(afi
, safi
));
14683 return nb_cli_apply_changes(vty
, xpath
);
14686 void cli_show_bgp_global_afi_safi_route_flap_dampening(struct vty
*vty
,
14687 struct lyd_node
*dnode
,
14688 bool show_defaults
)
14690 if (!yang_dnode_get_bool(dnode
, "./enable"))
14693 int half
= DEFAULT_HALF_LIFE
* 60;
14694 int reuse
= DEFAULT_REUSE
;
14695 int suppress
= DEFAULT_SUPPRESS
;
14698 half
= yang_dnode_get_uint8(dnode
, "../reach-decay");
14699 reuse
= yang_dnode_get_uint16(dnode
, "../reuse-above");
14700 suppress
= yang_dnode_get_uint16(dnode
, "../suppress-above");
14701 max
= yang_dnode_get_uint8(dnode
, "../unreach-decay");
14703 if (half
== DEFAULT_HALF_LIFE
* 60 && reuse
== DEFAULT_REUSE
14704 && suppress
== DEFAULT_SUPPRESS
&& max
== half
* 4)
14705 vty_out(vty
, " bgp dampening\n");
14706 else if (half
!= DEFAULT_HALF_LIFE
* 60 && reuse
== DEFAULT_REUSE
14707 && suppress
== DEFAULT_SUPPRESS
&& max
== half
* 4)
14708 vty_out(vty
, " bgp dampening %u\n", half
);
14710 vty_out(vty
, " bgp dampening %u %d %d %d\n", half
, reuse
,
14714 /* Display specified route of BGP table. */
14715 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
14716 const char *ip_str
, afi_t afi
, safi_t safi
,
14717 struct prefix_rd
*prd
, int prefix_check
)
14720 struct prefix match
;
14721 struct bgp_dest
*dest
;
14722 struct bgp_dest
*rm
;
14723 struct bgp_path_info
*pi
;
14724 struct bgp_path_info
*pi_temp
;
14726 struct bgp_table
*table
;
14728 /* BGP structure lookup. */
14730 bgp
= bgp_lookup_by_name(view_name
);
14732 vty_out(vty
, "%% Can't find BGP instance %s\n",
14734 return CMD_WARNING
;
14737 bgp
= bgp_get_default();
14739 vty_out(vty
, "%% No BGP process is configured\n");
14740 return CMD_WARNING
;
14744 /* Check IP address argument. */
14745 ret
= str2prefix(ip_str
, &match
);
14747 vty_out(vty
, "%% address is malformed\n");
14748 return CMD_WARNING
;
14751 match
.family
= afi2family(afi
);
14753 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
14754 || (safi
== SAFI_EVPN
)) {
14755 for (dest
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); dest
;
14756 dest
= bgp_route_next(dest
)) {
14757 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
14759 if (prd
&& memcmp(dest_p
->u
.val
, prd
->val
, 8) != 0)
14761 table
= bgp_dest_get_bgp_table_info(dest
);
14764 rm
= bgp_node_match(table
, &match
);
14768 const struct prefix
*rm_p
= bgp_dest_get_prefix(dest
);
14771 || rm_p
->prefixlen
== match
.prefixlen
) {
14772 pi
= bgp_dest_get_bgp_path_info(rm
);
14774 if (pi
->extra
&& pi
->extra
->damp_info
) {
14775 pi_temp
= pi
->next
;
14776 bgp_damp_info_free(
14777 &pi
->extra
->damp_info
,
14778 &bgp
->damp
[afi
][safi
],
14786 bgp_dest_unlock_node(rm
);
14789 dest
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
);
14790 if (dest
!= NULL
) {
14791 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
14794 || dest_p
->prefixlen
== match
.prefixlen
) {
14795 pi
= bgp_dest_get_bgp_path_info(dest
);
14797 if (pi
->extra
&& pi
->extra
->damp_info
) {
14798 pi_temp
= pi
->next
;
14799 struct bgp_damp_info
*bdi
=
14800 pi
->extra
->damp_info
;
14801 if (bdi
->lastrecord
14802 == BGP_RECORD_UPDATE
) {
14803 bgp_aggregate_increment(
14814 bgp_damp_info_free(
14815 &pi
->extra
->damp_info
,
14816 &bgp
->damp
[afi
][safi
],
14824 bgp_dest_unlock_node(dest
);
14828 return CMD_SUCCESS
;
14831 DEFUN (clear_ip_bgp_dampening
,
14832 clear_ip_bgp_dampening_cmd
,
14833 "clear ip bgp dampening",
14837 "Clear route flap dampening information\n")
14839 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
14840 bgp_damp_info_clean(bgp
, &bgp
->damp
[AFI_IP
][SAFI_UNICAST
], AFI_IP
,
14842 return CMD_SUCCESS
;
14845 DEFUN (clear_ip_bgp_dampening_prefix
,
14846 clear_ip_bgp_dampening_prefix_cmd
,
14847 "clear ip bgp dampening A.B.C.D/M",
14851 "Clear route flap dampening information\n"
14854 int idx_ipv4_prefixlen
= 4;
14855 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
14856 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
14859 DEFUN (clear_ip_bgp_dampening_address
,
14860 clear_ip_bgp_dampening_address_cmd
,
14861 "clear ip bgp dampening A.B.C.D",
14865 "Clear route flap dampening information\n"
14866 "Network to clear damping information\n")
14869 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
14870 SAFI_UNICAST
, NULL
, 0);
14873 DEFUN (clear_ip_bgp_dampening_address_mask
,
14874 clear_ip_bgp_dampening_address_mask_cmd
,
14875 "clear ip bgp dampening A.B.C.D A.B.C.D",
14879 "Clear route flap dampening information\n"
14880 "Network to clear damping information\n"
14884 int idx_ipv4_2
= 5;
14886 char prefix_str
[BUFSIZ
];
14888 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
14889 prefix_str
, sizeof(prefix_str
));
14891 vty_out(vty
, "%% Inconsistent address and mask\n");
14892 return CMD_WARNING
;
14895 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
14899 static void show_bgp_peerhash_entry(struct hash_bucket
*bucket
, void *arg
)
14901 struct vty
*vty
= arg
;
14902 struct peer
*peer
= bucket
->data
;
14903 char buf
[SU_ADDRSTRLEN
];
14905 vty_out(vty
, "\tPeer: %s %s\n", peer
->host
,
14906 sockunion2str(&peer
->su
, buf
, sizeof(buf
)));
14909 DEFUN (show_bgp_listeners
,
14910 show_bgp_listeners_cmd
,
14911 "show bgp listeners",
14914 "Display Listen Sockets and who created them\n")
14916 bgp_dump_listener_info(vty
);
14918 return CMD_SUCCESS
;
14921 DEFUN (show_bgp_peerhash
,
14922 show_bgp_peerhash_cmd
,
14923 "show bgp peerhash",
14926 "Display information about the BGP peerhash\n")
14928 struct list
*instances
= bm
->bgp
;
14929 struct listnode
*node
;
14932 for (ALL_LIST_ELEMENTS_RO(instances
, node
, bgp
)) {
14933 vty_out(vty
, "BGP: %s\n", bgp
->name
);
14934 hash_iterate(bgp
->peerhash
, show_bgp_peerhash_entry
,
14938 return CMD_SUCCESS
;
14941 /* also used for encap safi */
14942 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
14943 afi_t afi
, safi_t safi
)
14945 struct bgp_dest
*pdest
;
14946 struct bgp_dest
*dest
;
14947 struct bgp_table
*table
;
14948 const struct prefix
*p
;
14949 const struct prefix_rd
*prd
;
14950 struct bgp_static
*bgp_static
;
14951 mpls_label_t label
;
14952 char rdbuf
[RD_ADDRSTRLEN
];
14954 /* Network configuration. */
14955 for (pdest
= bgp_table_top(bgp
->route
[afi
][safi
]); pdest
;
14956 pdest
= bgp_route_next(pdest
)) {
14957 table
= bgp_dest_get_bgp_table_info(pdest
);
14961 for (dest
= bgp_table_top(table
); dest
;
14962 dest
= bgp_route_next(dest
)) {
14963 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
14964 if (bgp_static
== NULL
)
14967 p
= bgp_dest_get_prefix(dest
);
14968 prd
= (const struct prefix_rd
*)bgp_dest_get_prefix(
14971 /* "network" configuration display. */
14972 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
14973 label
= decode_label(&bgp_static
->label
);
14975 vty_out(vty
, " network %pFX rd %s", p
, rdbuf
);
14976 if (safi
== SAFI_MPLS_VPN
)
14977 vty_out(vty
, " label %u", label
);
14979 if (bgp_static
->rmap
.name
)
14980 vty_out(vty
, " route-map %s",
14981 bgp_static
->rmap
.name
);
14983 if (bgp_static
->backdoor
)
14984 vty_out(vty
, " backdoor");
14986 vty_out(vty
, "\n");
14991 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
14992 afi_t afi
, safi_t safi
)
14994 struct bgp_dest
*pdest
;
14995 struct bgp_dest
*dest
;
14996 struct bgp_table
*table
;
14997 const struct prefix
*p
;
14998 const struct prefix_rd
*prd
;
14999 struct bgp_static
*bgp_static
;
15000 char buf
[PREFIX_STRLEN
* 2];
15001 char buf2
[SU_ADDRSTRLEN
];
15002 char rdbuf
[RD_ADDRSTRLEN
];
15003 char esi_buf
[ESI_BYTES
];
15005 /* Network configuration. */
15006 for (pdest
= bgp_table_top(bgp
->route
[afi
][safi
]); pdest
;
15007 pdest
= bgp_route_next(pdest
)) {
15008 table
= bgp_dest_get_bgp_table_info(pdest
);
15012 for (dest
= bgp_table_top(table
); dest
;
15013 dest
= bgp_route_next(dest
)) {
15014 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
15015 if (bgp_static
== NULL
)
15018 char *macrouter
= NULL
;
15020 if (bgp_static
->router_mac
)
15021 macrouter
= prefix_mac2str(
15022 bgp_static
->router_mac
, NULL
, 0);
15023 if (bgp_static
->eth_s_id
)
15024 esi_to_str(bgp_static
->eth_s_id
,
15025 esi_buf
, sizeof(esi_buf
));
15026 p
= bgp_dest_get_prefix(dest
);
15027 prd
= (struct prefix_rd
*)bgp_dest_get_prefix(pdest
);
15029 /* "network" configuration display. */
15030 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
15031 if (p
->u
.prefix_evpn
.route_type
== 5) {
15032 char local_buf
[PREFIX_STRLEN
];
15033 uint8_t family
= is_evpn_prefix_ipaddr_v4((
15034 struct prefix_evpn
*)p
)
15038 &p
->u
.prefix_evpn
.prefix_addr
.ip
.ip
.addr
,
15039 local_buf
, PREFIX_STRLEN
);
15040 snprintf(buf
, sizeof(buf
), "%s/%u", local_buf
,
15041 p
->u
.prefix_evpn
.prefix_addr
15042 .ip_prefix_length
);
15044 prefix2str(p
, buf
, sizeof(buf
));
15047 if (bgp_static
->gatewayIp
.family
== AF_INET
15048 || bgp_static
->gatewayIp
.family
== AF_INET6
)
15049 inet_ntop(bgp_static
->gatewayIp
.family
,
15050 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
15053 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
15055 p
->u
.prefix_evpn
.prefix_addr
.eth_tag
,
15056 decode_label(&bgp_static
->label
), esi_buf
, buf2
,
15059 XFREE(MTYPE_TMP
, macrouter
);
15064 /* Configuration of static route announcement and aggregate
15066 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
15069 struct bgp_dest
*dest
;
15070 const struct prefix
*p
;
15071 struct bgp_static
*bgp_static
;
15072 struct bgp_aggregate
*bgp_aggregate
;
15074 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
15075 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
15079 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
15080 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
15084 /* Network configuration. */
15085 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
15086 dest
= bgp_route_next(dest
)) {
15087 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
15088 if (bgp_static
== NULL
)
15091 p
= bgp_dest_get_prefix(dest
);
15093 vty_out(vty
, " network %pFX", p
);
15095 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
15096 vty_out(vty
, " label-index %u",
15097 bgp_static
->label_index
);
15099 if (bgp_static
->rmap
.name
)
15100 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
15102 if (bgp_static
->backdoor
)
15103 vty_out(vty
, " backdoor");
15105 vty_out(vty
, "\n");
15108 /* Aggregate-address configuration. */
15109 for (dest
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); dest
;
15110 dest
= bgp_route_next(dest
)) {
15111 bgp_aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
15112 if (bgp_aggregate
== NULL
)
15115 p
= bgp_dest_get_prefix(dest
);
15117 vty_out(vty
, " aggregate-address %pFX", p
);
15119 if (bgp_aggregate
->as_set
)
15120 vty_out(vty
, " as-set");
15122 if (bgp_aggregate
->summary_only
)
15123 vty_out(vty
, " summary-only");
15125 if (bgp_aggregate
->rmap
.name
)
15126 vty_out(vty
, " route-map %s", bgp_aggregate
->rmap
.name
);
15128 if (bgp_aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
15129 vty_out(vty
, " origin %s",
15130 bgp_origin2str(bgp_aggregate
->origin
));
15132 if (bgp_aggregate
->match_med
)
15133 vty_out(vty
, " matching-MED-only");
15135 if (bgp_aggregate
->suppress_map_name
)
15136 vty_out(vty
, " suppress-map %s",
15137 bgp_aggregate
->suppress_map_name
);
15139 vty_out(vty
, "\n");
15143 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
15146 struct bgp_dest
*dest
;
15147 struct bgp_distance
*bdistance
;
15149 /* Distance configuration. */
15150 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
15151 && bgp
->distance_local
[afi
][safi
]
15152 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
15153 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
15154 || bgp
->distance_local
[afi
][safi
]
15155 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
15156 vty_out(vty
, " distance bgp %d %d %d\n",
15157 bgp
->distance_ebgp
[afi
][safi
],
15158 bgp
->distance_ibgp
[afi
][safi
],
15159 bgp
->distance_local
[afi
][safi
]);
15162 for (dest
= bgp_table_top(bgp_distance_table
[afi
][safi
]); dest
;
15163 dest
= bgp_route_next(dest
)) {
15164 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
15165 if (bdistance
!= NULL
)
15166 vty_out(vty
, " distance %d %pBD %s\n",
15167 bdistance
->distance
, dest
,
15168 bdistance
->access_list
? bdistance
->access_list
15173 /* Allocate routing table structure and install commands. */
15174 void bgp_route_init(void)
15179 /* Init BGP distance table. */
15180 FOREACH_AFI_SAFI (afi
, safi
)
15181 bgp_distance_table
[afi
][safi
] = bgp_table_init(NULL
, afi
, safi
);
15183 /* IPv4 BGP commands. */
15184 install_element(BGP_NODE
, &bgp_table_map_cmd
);
15185 install_element(BGP_NODE
, &bgp_network_cmd
);
15186 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
15188 install_element(BGP_NODE
, &aggregate_addressv4_cmd
);
15190 /* IPv4 unicast configuration. */
15191 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
15192 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
15193 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
15195 install_element(BGP_IPV4_NODE
, &aggregate_addressv4_cmd
);
15197 /* IPv4 multicast configuration. */
15198 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
15199 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
15200 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
15201 install_element(BGP_IPV4M_NODE
, &aggregate_addressv4_cmd
);
15203 /* IPv4 labeled-unicast configuration. */
15204 install_element(BGP_IPV4L_NODE
, &bgp_network_cmd
);
15205 install_element(BGP_IPV4L_NODE
, &aggregate_addressv4_cmd
);
15207 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
15208 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
15209 install_element(VIEW_NODE
, &show_ip_bgp_afi_safi_statistics_cmd
);
15210 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_statistics_cmd
);
15211 install_element(VIEW_NODE
, &show_ip_bgp_json_cmd
);
15212 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
15213 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
15214 install_element(VIEW_NODE
, &show_ip_bgp_statistics_all_cmd
);
15216 install_element(VIEW_NODE
,
15217 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
15218 install_element(VIEW_NODE
,
15219 &show_ip_bgp_instance_neighbor_bestpath_route_cmd
);
15220 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
15221 install_element(VIEW_NODE
,
15222 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
15223 #ifdef KEEP_OLD_VPN_COMMANDS
15224 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
15225 #endif /* KEEP_OLD_VPN_COMMANDS */
15226 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
15227 install_element(VIEW_NODE
,
15228 &show_bgp_l2vpn_evpn_route_prefix_cmd
);
15230 /* BGP dampening clear commands */
15231 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
15232 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
15234 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
15235 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
15238 install_element(ENABLE_NODE
,
15239 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
15240 #ifdef KEEP_OLD_VPN_COMMANDS
15241 install_element(ENABLE_NODE
,
15242 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
15243 #endif /* KEEP_OLD_VPN_COMMANDS */
15245 /* New config IPv6 BGP commands. */
15246 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
15247 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
15248 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
15250 install_element(BGP_IPV6_NODE
, &aggregate_addressv6_cmd
);
15252 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
15254 /* IPv6 labeled unicast address family. */
15255 install_element(BGP_IPV6L_NODE
, &ipv6_bgp_network_cmd
);
15256 install_element(BGP_IPV6L_NODE
, &aggregate_addressv6_cmd
);
15258 install_element(BGP_NODE
, &bgp_distance_cmd
);
15259 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
15260 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
15261 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
15262 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
15263 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
15264 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
15265 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
15266 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
15267 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
15268 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
15269 install_element(BGP_IPV6_NODE
, &bgp_distance_source_cmd
);
15270 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
15271 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
15272 install_element(BGP_IPV6M_NODE
, &bgp_distance_source_cmd
);
15274 /* BGP dampening */
15275 install_element(BGP_NODE
, &bgp_dampening_cmd
);
15276 install_element(BGP_IPV4_NODE
, &bgp_dampening_cmd
);
15277 install_element(BGP_IPV4M_NODE
, &bgp_dampening_cmd
);
15278 install_element(BGP_IPV4L_NODE
, &bgp_dampening_cmd
);
15279 install_element(BGP_IPV6_NODE
, &bgp_dampening_cmd
);
15280 install_element(BGP_IPV6M_NODE
, &bgp_dampening_cmd
);
15281 install_element(BGP_IPV6L_NODE
, &bgp_dampening_cmd
);
15283 /* Large Communities */
15284 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
15285 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
15287 /* show bgp ipv4 flowspec detailed */
15288 install_element(VIEW_NODE
, &show_ip_bgp_flowspec_routes_detailed_cmd
);
15290 install_element(VIEW_NODE
, &show_bgp_listeners_cmd
);
15291 install_element(VIEW_NODE
, &show_bgp_peerhash_cmd
);
15294 void bgp_route_finish(void)
15299 FOREACH_AFI_SAFI (afi
, safi
) {
15300 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
15301 bgp_distance_table
[afi
][safi
] = NULL
;