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"
92 #ifndef VTYSH_EXTRACT_PL
93 #include "bgpd/bgp_route_clippy.c"
96 DEFINE_HOOK(bgp_snmp_update_stats
,
97 (struct bgp_node
*rn
, struct bgp_path_info
*pi
, bool added
),
100 DEFINE_HOOK(bgp_rpki_prefix_status
,
101 (struct peer
*peer
, struct attr
*attr
,
102 const struct prefix
*prefix
),
103 (peer
, attr
, prefix
));
105 /* Extern from bgp_dump.c */
106 extern const char *bgp_origin_str
[];
107 extern const char *bgp_origin_long_str
[];
110 #define PMSI_TNLTYPE_STR_NO_INFO "No info"
111 #define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
112 static const struct message bgp_pmsi_tnltype_str
[] = {
113 {PMSI_TNLTYPE_NO_INFO
, PMSI_TNLTYPE_STR_NO_INFO
},
114 {PMSI_TNLTYPE_RSVP_TE_P2MP
, "RSVP-TE P2MP"},
115 {PMSI_TNLTYPE_MLDP_P2MP
, "mLDP P2MP"},
116 {PMSI_TNLTYPE_PIM_SSM
, "PIM-SSM"},
117 {PMSI_TNLTYPE_PIM_SM
, "PIM-SM"},
118 {PMSI_TNLTYPE_PIM_BIDIR
, "PIM-BIDIR"},
119 {PMSI_TNLTYPE_INGR_REPL
, "Ingress Replication"},
120 {PMSI_TNLTYPE_MLDP_MP2MP
, "mLDP MP2MP"},
124 #define VRFID_NONE_STR "-"
125 #define SOFT_RECONFIG_TASK_MAX_PREFIX 25000
127 DEFINE_HOOK(bgp_process
,
128 (struct bgp
* bgp
, afi_t afi
, safi_t safi
, struct bgp_dest
*bn
,
129 struct peer
*peer
, bool withdraw
),
130 (bgp
, afi
, safi
, bn
, peer
, withdraw
));
132 /** Test if path is suppressed. */
133 static bool bgp_path_suppressed(struct bgp_path_info
*pi
)
135 if (pi
->extra
== NULL
|| pi
->extra
->aggr_suppressors
== NULL
)
138 return listcount(pi
->extra
->aggr_suppressors
) > 0;
141 struct bgp_dest
*bgp_afi_node_get(struct bgp_table
*table
, afi_t afi
,
142 safi_t safi
, const struct prefix
*p
,
143 struct prefix_rd
*prd
)
145 struct bgp_dest
*dest
;
146 struct bgp_dest
*pdest
= NULL
;
150 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
151 || (safi
== SAFI_EVPN
)) {
152 pdest
= bgp_node_get(table
, (struct prefix
*)prd
);
154 if (!bgp_dest_has_bgp_path_info_data(pdest
))
155 bgp_dest_set_bgp_table_info(
156 pdest
, bgp_table_init(table
->bgp
, afi
, safi
));
158 bgp_dest_unlock_node(pdest
);
159 table
= bgp_dest_get_bgp_table_info(pdest
);
162 dest
= bgp_node_get(table
, p
);
164 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
165 || (safi
== SAFI_EVPN
))
171 struct bgp_dest
*bgp_afi_node_lookup(struct bgp_table
*table
, afi_t afi
,
172 safi_t safi
, const struct prefix
*p
,
173 struct prefix_rd
*prd
)
175 struct bgp_dest
*dest
;
176 struct bgp_dest
*pdest
= NULL
;
181 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
182 || (safi
== SAFI_EVPN
)) {
183 pdest
= bgp_node_lookup(table
, (struct prefix
*)prd
);
187 if (!bgp_dest_has_bgp_path_info_data(pdest
)) {
188 bgp_dest_unlock_node(pdest
);
192 table
= bgp_dest_get_bgp_table_info(pdest
);
195 dest
= bgp_node_lookup(table
, p
);
200 /* Allocate bgp_path_info_extra */
201 static struct bgp_path_info_extra
*bgp_path_info_extra_new(void)
203 struct bgp_path_info_extra
*new;
204 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA
,
205 sizeof(struct bgp_path_info_extra
));
206 new->label
[0] = MPLS_INVALID_LABEL
;
208 new->bgp_fs_pbr
= NULL
;
209 new->bgp_fs_iprule
= NULL
;
213 void bgp_path_info_extra_free(struct bgp_path_info_extra
**extra
)
215 struct bgp_path_info_extra
*e
;
217 if (!extra
|| !*extra
)
222 bgp_damp_info_free(e
->damp_info
, 0, e
->damp_info
->afi
,
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
,
2280 CHECK_FLAG(peer
->flags
,
2281 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE
));
2286 static int bgp_route_select_timer_expire(struct thread
*thread
)
2288 struct afi_safi_info
*info
;
2293 info
= THREAD_ARG(thread
);
2298 if (BGP_DEBUG(update
, UPDATE_OUT
))
2299 zlog_debug("afi %d, safi %d : route select timer expired", afi
,
2302 bgp
->gr_info
[afi
][safi
].t_route_select
= NULL
;
2304 XFREE(MTYPE_TMP
, info
);
2306 /* Best path selection */
2307 return bgp_best_path_select_defer(bgp
, afi
, safi
);
2310 void bgp_best_selection(struct bgp
*bgp
, struct bgp_dest
*dest
,
2311 struct bgp_maxpaths_cfg
*mpath_cfg
,
2312 struct bgp_path_info_pair
*result
, afi_t afi
,
2315 struct bgp_path_info
*new_select
;
2316 struct bgp_path_info
*old_select
;
2317 struct bgp_path_info
*pi
;
2318 struct bgp_path_info
*pi1
;
2319 struct bgp_path_info
*pi2
;
2320 struct bgp_path_info
*nextpi
= NULL
;
2321 int paths_eq
, do_mpath
, debug
;
2322 struct list mp_list
;
2323 char pfx_buf
[PREFIX2STR_BUFFER
];
2324 char path_buf
[PATH_ADDPATH_STR_BUFFER
];
2326 bgp_mp_list_init(&mp_list
);
2328 (mpath_cfg
->maxpaths_ebgp
> 1 || mpath_cfg
->maxpaths_ibgp
> 1);
2330 debug
= bgp_debug_bestpath(dest
);
2333 prefix2str(bgp_dest_get_prefix(dest
), pfx_buf
, sizeof(pfx_buf
));
2335 dest
->reason
= bgp_path_selection_none
;
2336 /* bgp deterministic-med */
2338 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DETERMINISTIC_MED
)) {
2340 /* Clear BGP_PATH_DMED_SELECTED for all paths */
2341 for (pi1
= bgp_dest_get_bgp_path_info(dest
); pi1
;
2343 bgp_path_info_unset_flag(dest
, pi1
,
2344 BGP_PATH_DMED_SELECTED
);
2346 for (pi1
= bgp_dest_get_bgp_path_info(dest
); pi1
;
2348 if (CHECK_FLAG(pi1
->flags
, BGP_PATH_DMED_CHECK
))
2350 if (BGP_PATH_HOLDDOWN(pi1
))
2352 if (pi1
->peer
!= bgp
->peer_self
)
2353 if (!peer_established(pi1
->peer
))
2358 for (pi2
= pi1
->next
; pi2
; pi2
= pi2
->next
) {
2359 if (CHECK_FLAG(pi2
->flags
,
2360 BGP_PATH_DMED_CHECK
))
2362 if (BGP_PATH_HOLDDOWN(pi2
))
2364 if (pi2
->peer
!= bgp
->peer_self
2367 PEER_STATUS_NSF_WAIT
))
2368 if (pi2
->peer
->status
2372 if (!aspath_cmp_left(pi1
->attr
->aspath
,
2374 && !aspath_cmp_left_confed(
2379 if (bgp_path_info_cmp(
2380 bgp
, pi2
, new_select
,
2381 &paths_eq
, mpath_cfg
, debug
,
2384 bgp_path_info_unset_flag(
2386 BGP_PATH_DMED_SELECTED
);
2390 bgp_path_info_set_flag(
2391 dest
, pi2
, BGP_PATH_DMED_CHECK
);
2394 bgp_path_info_set_flag(dest
, new_select
,
2395 BGP_PATH_DMED_CHECK
);
2396 bgp_path_info_set_flag(dest
, new_select
,
2397 BGP_PATH_DMED_SELECTED
);
2400 bgp_path_info_path_with_addpath_rx_str(
2401 new_select
, path_buf
, sizeof(path_buf
));
2403 "%pBD: %s is the bestpath from AS %u",
2405 aspath_get_first_as(
2406 new_select
->attr
->aspath
));
2411 /* Check old selected route and new selected route. */
2414 for (pi
= bgp_dest_get_bgp_path_info(dest
);
2415 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2416 enum bgp_path_selection_reason reason
;
2418 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
2421 if (BGP_PATH_HOLDDOWN(pi
)) {
2422 /* reap REMOVED routes, if needs be
2423 * selected route must stay for a while longer though
2425 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
2426 && (pi
!= old_select
))
2427 bgp_path_info_reap(dest
, pi
);
2430 zlog_debug("%s: pi %p in holddown", __func__
,
2436 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2437 && !CHECK_FLAG(pi
->peer
->sflags
, PEER_STATUS_NSF_WAIT
))
2438 if (!peer_established(pi
->peer
)) {
2442 "%s: pi %p non self peer %s not estab state",
2443 __func__
, pi
, pi
->peer
->host
);
2448 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DETERMINISTIC_MED
)
2449 && (!CHECK_FLAG(pi
->flags
, BGP_PATH_DMED_SELECTED
))) {
2450 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_DMED_CHECK
);
2452 zlog_debug("%s: pi %p dmed", __func__
, pi
);
2456 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_DMED_CHECK
);
2458 reason
= dest
->reason
;
2459 if (bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
, mpath_cfg
,
2460 debug
, pfx_buf
, afi
, safi
,
2462 if (new_select
== NULL
&&
2463 reason
!= bgp_path_selection_none
)
2464 dest
->reason
= reason
;
2469 /* Now that we know which path is the bestpath see if any of the other
2471 * qualify as multipaths
2475 bgp_path_info_path_with_addpath_rx_str(
2476 new_select
, path_buf
, sizeof(path_buf
));
2478 snprintf(path_buf
, sizeof(path_buf
), "NONE");
2480 "%pBD: After path selection, newbest is %s oldbest was %s",
2482 old_select
? old_select
->peer
->host
: "NONE");
2485 if (do_mpath
&& new_select
) {
2486 for (pi
= bgp_dest_get_bgp_path_info(dest
);
2487 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2490 bgp_path_info_path_with_addpath_rx_str(
2491 pi
, path_buf
, sizeof(path_buf
));
2493 if (pi
== new_select
) {
2496 "%pBD: %s is the bestpath, add to the multipath list",
2498 bgp_mp_list_add(&mp_list
, pi
);
2502 if (BGP_PATH_HOLDDOWN(pi
))
2505 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2506 && !CHECK_FLAG(pi
->peer
->sflags
,
2507 PEER_STATUS_NSF_WAIT
))
2508 if (!peer_established(pi
->peer
))
2511 if (!bgp_path_info_nexthop_cmp(pi
, new_select
)) {
2514 "%pBD: %s has the same nexthop as the bestpath, skip it",
2519 bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
,
2520 mpath_cfg
, debug
, pfx_buf
, afi
, safi
,
2526 "%pBD: %s is equivalent to the bestpath, add to the multipath list",
2528 bgp_mp_list_add(&mp_list
, pi
);
2533 bgp_path_info_mpath_update(dest
, new_select
, old_select
, &mp_list
,
2535 bgp_path_info_mpath_aggregate_update(new_select
, old_select
);
2536 bgp_mp_list_clear(&mp_list
);
2538 bgp_addpath_update_ids(bgp
, dest
, afi
, safi
);
2540 result
->old
= old_select
;
2541 result
->new = new_select
;
2547 * A new route/change in bestpath of an existing route. Evaluate the path
2548 * for advertisement to the subgroup.
2550 void subgroup_process_announce_selected(struct update_subgroup
*subgrp
,
2551 struct bgp_path_info
*selected
,
2552 struct bgp_dest
*dest
,
2553 uint32_t addpath_tx_id
)
2555 const struct prefix
*p
;
2556 struct peer
*onlypeer
;
2563 p
= bgp_dest_get_prefix(dest
);
2564 afi
= SUBGRP_AFI(subgrp
);
2565 safi
= SUBGRP_SAFI(subgrp
);
2566 bgp
= SUBGRP_INST(subgrp
);
2567 onlypeer
= ((SUBGRP_PCOUNT(subgrp
) == 1) ? (SUBGRP_PFIRST(subgrp
))->peer
2570 if (BGP_DEBUG(update
, UPDATE_OUT
))
2571 zlog_debug("%s: p=%pFX, selected=%p", __func__
, p
, selected
);
2573 /* First update is deferred until ORF or ROUTE-REFRESH is received */
2574 if (onlypeer
&& CHECK_FLAG(onlypeer
->af_sflags
[afi
][safi
],
2575 PEER_STATUS_ORF_WAIT_REFRESH
))
2578 memset(&attr
, 0, sizeof(struct attr
));
2579 /* It's initialized in bgp_announce_check() */
2581 /* Announcement to the subgroup. If the route is filtered withdraw it.
2582 * If BGP_NODE_FIB_INSTALL_PENDING is set and data plane install status
2583 * is pending (BGP_NODE_FIB_INSTALL_PENDING), do not advertise the
2586 advertise
= bgp_check_advertise(bgp
, dest
);
2589 if (subgroup_announce_check(dest
, selected
, subgrp
, p
, &attr
,
2591 /* Route is selected, if the route is already installed
2592 * in FIB, then it is advertised
2595 bgp_adj_out_set_subgroup(dest
, subgrp
, &attr
,
2598 bgp_adj_out_unset_subgroup(dest
, subgrp
, 1,
2602 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2604 bgp_adj_out_unset_subgroup(dest
, subgrp
, 1, addpath_tx_id
);
2609 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2610 * This is called at the end of route processing.
2612 void bgp_zebra_clear_route_change_flags(struct bgp_dest
*dest
)
2614 struct bgp_path_info
*pi
;
2616 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
2617 if (BGP_PATH_HOLDDOWN(pi
))
2619 UNSET_FLAG(pi
->flags
, BGP_PATH_IGP_CHANGED
);
2620 UNSET_FLAG(pi
->flags
, BGP_PATH_ATTR_CHANGED
);
2625 * Has the route changed from the RIB's perspective? This is invoked only
2626 * if the route selection returns the same best route as earlier - to
2627 * determine if we need to update zebra or not.
2629 bool bgp_zebra_has_route_changed(struct bgp_path_info
*selected
)
2631 struct bgp_path_info
*mpinfo
;
2633 /* If this is multipath, check all selected paths for any nexthop
2634 * change or attribute change. Some attribute changes (e.g., community)
2635 * aren't of relevance to the RIB, but we'll update zebra to ensure
2636 * we handle the case of BGP nexthop change. This is the behavior
2637 * when the best path has an attribute change anyway.
2639 if (CHECK_FLAG(selected
->flags
, BGP_PATH_IGP_CHANGED
)
2640 || CHECK_FLAG(selected
->flags
, BGP_PATH_MULTIPATH_CHG
)
2641 || CHECK_FLAG(selected
->flags
, BGP_PATH_LINK_BW_CHG
))
2645 * If this is multipath, check all selected paths for any nexthop change
2647 for (mpinfo
= bgp_path_info_mpath_first(selected
); mpinfo
;
2648 mpinfo
= bgp_path_info_mpath_next(mpinfo
)) {
2649 if (CHECK_FLAG(mpinfo
->flags
, BGP_PATH_IGP_CHANGED
)
2650 || CHECK_FLAG(mpinfo
->flags
, BGP_PATH_ATTR_CHANGED
))
2654 /* Nothing has changed from the RIB's perspective. */
2658 struct bgp_process_queue
{
2660 STAILQ_HEAD(, bgp_dest
) pqueue
;
2661 #define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2663 unsigned int queued
;
2666 static void bgp_process_evpn_route_injection(struct bgp
*bgp
, afi_t afi
,
2667 safi_t safi
, struct bgp_dest
*dest
,
2668 struct bgp_path_info
*new_select
,
2669 struct bgp_path_info
*old_select
)
2671 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
2673 if ((afi
!= AFI_IP
&& afi
!= AFI_IP6
) || (safi
!= SAFI_UNICAST
))
2676 if (advertise_type5_routes(bgp
, afi
) && new_select
2677 && is_route_injectable_into_evpn(new_select
)) {
2679 /* apply the route-map */
2680 if (bgp
->adv_cmd_rmap
[afi
][safi
].map
) {
2681 route_map_result_t ret
;
2682 struct bgp_path_info rmap_path
;
2683 struct bgp_path_info_extra rmap_path_extra
;
2684 struct attr dummy_attr
;
2686 dummy_attr
= *new_select
->attr
;
2688 /* Fill temp path_info */
2689 prep_for_rmap_apply(&rmap_path
, &rmap_path_extra
, dest
,
2690 new_select
, new_select
->peer
,
2693 RESET_FLAG(dummy_attr
.rmap_change_flags
);
2695 ret
= route_map_apply(bgp
->adv_cmd_rmap
[afi
][safi
].map
,
2698 if (ret
== RMAP_DENYMATCH
) {
2699 bgp_attr_flush(&dummy_attr
);
2700 bgp_evpn_withdraw_type5_route(bgp
, p
, afi
,
2703 bgp_evpn_advertise_type5_route(
2704 bgp
, p
, &dummy_attr
, afi
, safi
);
2706 bgp_evpn_advertise_type5_route(bgp
, p
, new_select
->attr
,
2709 } else if (advertise_type5_routes(bgp
, afi
) && old_select
2710 && is_route_injectable_into_evpn(old_select
))
2711 bgp_evpn_withdraw_type5_route(bgp
, p
, afi
, safi
);
2715 * old_select = The old best path
2716 * new_select = the new best path
2718 * if (!old_select && new_select)
2719 * We are sending new information on.
2721 * if (old_select && new_select) {
2722 * if (new_select != old_select)
2723 * We have a new best path send a change
2725 * We've received a update with new attributes that needs
2729 * if (old_select && !new_select)
2730 * We have no eligible route that we can announce or the rn
2733 static void bgp_process_main_one(struct bgp
*bgp
, struct bgp_dest
*dest
,
2734 afi_t afi
, safi_t safi
)
2736 struct bgp_path_info
*new_select
;
2737 struct bgp_path_info
*old_select
;
2738 struct bgp_path_info_pair old_and_new
;
2741 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)) {
2743 debug
= bgp_debug_bestpath(dest
);
2746 "%s: bgp delete in progress, ignoring event, p=%pBD",
2750 /* Is it end of initial update? (after startup) */
2752 quagga_timestamp(3, bgp
->update_delay_zebra_resume_time
,
2753 sizeof(bgp
->update_delay_zebra_resume_time
));
2755 bgp
->main_zebra_update_hold
= 0;
2756 FOREACH_AFI_SAFI (afi
, safi
) {
2757 if (bgp_fibupd_safi(safi
))
2758 bgp_zebra_announce_table(bgp
, afi
, safi
);
2760 bgp
->main_peers_update_hold
= 0;
2762 bgp_start_routeadv(bgp
);
2766 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
2768 debug
= bgp_debug_bestpath(dest
);
2770 zlog_debug("%s: p=%pBD afi=%s, safi=%s start", __func__
, dest
,
2771 afi2str(afi
), safi2str(safi
));
2773 /* The best path calculation for the route is deferred if
2774 * BGP_NODE_SELECT_DEFER is set
2776 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
2777 if (BGP_DEBUG(update
, UPDATE_OUT
))
2778 zlog_debug("SELECT_DEFER flag set for route %p", dest
);
2782 /* Best path selection. */
2783 bgp_best_selection(bgp
, dest
, &bgp
->maxpaths
[afi
][safi
], &old_and_new
,
2785 old_select
= old_and_new
.old
;
2786 new_select
= old_and_new
.new;
2788 /* Do we need to allocate or free labels?
2789 * Right now, since we only deal with per-prefix labels, it is not
2790 * necessary to do this upon changes to best path. Exceptions:
2791 * - label index has changed -> recalculate resulting label
2792 * - path_info sub_type changed -> switch to/from implicit-null
2793 * - no valid label (due to removed static label binding) -> get new one
2795 if (bgp
->allocate_mpls_labels
[afi
][safi
]) {
2798 || bgp_label_index_differs(new_select
, old_select
)
2799 || new_select
->sub_type
!= old_select
->sub_type
2800 || !bgp_is_valid_label(&dest
->local_label
)) {
2801 /* Enforced penultimate hop popping:
2802 * implicit-null for local routes, aggregate
2803 * and redistributed routes
2805 if (new_select
->sub_type
== BGP_ROUTE_STATIC
2806 || new_select
->sub_type
2807 == BGP_ROUTE_AGGREGATE
2808 || new_select
->sub_type
2809 == BGP_ROUTE_REDISTRIBUTE
) {
2812 BGP_NODE_REGISTERED_FOR_LABEL
)
2815 BGP_NODE_LABEL_REQUESTED
))
2816 bgp_unregister_for_label(dest
);
2817 label_ntop(MPLS_LABEL_IMPLICIT_NULL
, 1,
2818 &dest
->local_label
);
2819 bgp_set_valid_label(&dest
->local_label
);
2821 bgp_register_for_label(dest
,
2824 } else if (CHECK_FLAG(dest
->flags
,
2825 BGP_NODE_REGISTERED_FOR_LABEL
)
2826 || CHECK_FLAG(dest
->flags
,
2827 BGP_NODE_LABEL_REQUESTED
)) {
2828 bgp_unregister_for_label(dest
);
2830 } else if (CHECK_FLAG(dest
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
)
2831 || CHECK_FLAG(dest
->flags
, BGP_NODE_LABEL_REQUESTED
)) {
2832 bgp_unregister_for_label(dest
);
2837 "%s: p=%pBD afi=%s, safi=%s, old_select=%p, new_select=%p",
2838 __func__
, dest
, afi2str(afi
), safi2str(safi
),
2839 old_select
, new_select
);
2841 /* If best route remains the same and this is not due to user-initiated
2842 * clear, see exactly what needs to be done.
2844 if (old_select
&& old_select
== new_select
2845 && !CHECK_FLAG(dest
->flags
, BGP_NODE_USER_CLEAR
)
2846 && !CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
2847 && !bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
2848 if (bgp_zebra_has_route_changed(old_select
)) {
2849 #ifdef ENABLE_BGP_VNC
2850 vnc_import_bgp_add_route(bgp
, p
, old_select
);
2851 vnc_import_bgp_exterior_add_route(bgp
, p
, old_select
);
2853 if (bgp_fibupd_safi(safi
)
2854 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2856 if (new_select
->type
== ZEBRA_ROUTE_BGP
2857 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2858 || new_select
->sub_type
2859 == BGP_ROUTE_IMPORTED
))
2861 bgp_zebra_announce(dest
, p
, old_select
,
2866 /* If there is a change of interest to peers, reannounce the
2868 if (CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
2869 || CHECK_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
)
2870 || CHECK_FLAG(dest
->flags
, BGP_NODE_LABEL_CHANGED
)) {
2871 group_announce_route(bgp
, afi
, safi
, dest
, new_select
);
2873 /* unicast routes must also be annouced to
2874 * labeled-unicast update-groups */
2875 if (safi
== SAFI_UNICAST
)
2876 group_announce_route(bgp
, afi
,
2877 SAFI_LABELED_UNICAST
, dest
,
2880 UNSET_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
);
2881 UNSET_FLAG(dest
->flags
, BGP_NODE_LABEL_CHANGED
);
2884 /* advertise/withdraw type-5 routes */
2885 if (CHECK_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
)
2886 || CHECK_FLAG(old_select
->flags
, BGP_PATH_MULTIPATH_CHG
))
2887 bgp_process_evpn_route_injection(
2888 bgp
, afi
, safi
, dest
, old_select
, old_select
);
2890 UNSET_FLAG(old_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
2891 UNSET_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
);
2892 bgp_zebra_clear_route_change_flags(dest
);
2893 UNSET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2897 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2899 UNSET_FLAG(dest
->flags
, BGP_NODE_USER_CLEAR
);
2901 /* bestpath has changed; bump version */
2902 if (old_select
|| new_select
) {
2903 bgp_bump_version(dest
);
2905 if (!bgp
->t_rmap_def_originate_eval
) {
2909 update_group_refresh_default_originate_route_map
,
2910 bgp
, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER
,
2911 &bgp
->t_rmap_def_originate_eval
);
2916 bgp_path_info_unset_flag(dest
, old_select
, BGP_PATH_SELECTED
);
2919 zlog_debug("%s: setting SELECTED flag", __func__
);
2920 bgp_path_info_set_flag(dest
, new_select
, BGP_PATH_SELECTED
);
2921 bgp_path_info_unset_flag(dest
, new_select
,
2922 BGP_PATH_ATTR_CHANGED
);
2923 UNSET_FLAG(new_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
2924 UNSET_FLAG(new_select
->flags
, BGP_PATH_LINK_BW_CHG
);
2927 #ifdef ENABLE_BGP_VNC
2928 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2929 if (old_select
!= new_select
) {
2931 vnc_import_bgp_exterior_del_route(bgp
, p
,
2933 vnc_import_bgp_del_route(bgp
, p
, old_select
);
2936 vnc_import_bgp_exterior_add_route(bgp
, p
,
2938 vnc_import_bgp_add_route(bgp
, p
, new_select
);
2944 group_announce_route(bgp
, afi
, safi
, dest
, new_select
);
2946 /* unicast routes must also be annouced to labeled-unicast update-groups
2948 if (safi
== SAFI_UNICAST
)
2949 group_announce_route(bgp
, afi
, SAFI_LABELED_UNICAST
, dest
,
2953 if (bgp_fibupd_safi(safi
) && (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VIEW
)
2954 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2955 if (new_select
&& new_select
->type
== ZEBRA_ROUTE_BGP
2956 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2957 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
2958 || new_select
->sub_type
== BGP_ROUTE_IMPORTED
)) {
2960 /* if this is an evpn imported type-5 prefix,
2961 * we need to withdraw the route first to clear
2962 * the nh neigh and the RMAC entry.
2965 is_route_parent_evpn(old_select
))
2966 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2968 bgp_zebra_announce(dest
, p
, new_select
, bgp
, afi
, safi
);
2970 /* Withdraw the route from the kernel. */
2971 if (old_select
&& old_select
->type
== ZEBRA_ROUTE_BGP
2972 && (old_select
->sub_type
== BGP_ROUTE_NORMAL
2973 || old_select
->sub_type
== BGP_ROUTE_AGGREGATE
2974 || old_select
->sub_type
== BGP_ROUTE_IMPORTED
))
2976 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2980 bgp_process_evpn_route_injection(bgp
, afi
, safi
, dest
, new_select
,
2983 /* Clear any route change flags. */
2984 bgp_zebra_clear_route_change_flags(dest
);
2986 /* Reap old select bgp_path_info, if it has been removed */
2987 if (old_select
&& CHECK_FLAG(old_select
->flags
, BGP_PATH_REMOVED
))
2988 bgp_path_info_reap(dest
, old_select
);
2990 UNSET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2994 /* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
2995 int bgp_best_path_select_defer(struct bgp
*bgp
, afi_t afi
, safi_t safi
)
2997 struct bgp_dest
*dest
;
2999 struct afi_safi_info
*thread_info
;
3001 if (bgp
->gr_info
[afi
][safi
].t_route_select
) {
3002 struct thread
*t
= bgp
->gr_info
[afi
][safi
].t_route_select
;
3004 thread_info
= THREAD_ARG(t
);
3005 XFREE(MTYPE_TMP
, thread_info
);
3006 BGP_TIMER_OFF(bgp
->gr_info
[afi
][safi
].t_route_select
);
3009 if (BGP_DEBUG(update
, UPDATE_OUT
)) {
3010 zlog_debug("%s: processing route for %s : cnt %d", __func__
,
3011 get_afi_safi_str(afi
, safi
, false),
3012 bgp
->gr_info
[afi
][safi
].gr_deferred
);
3015 /* Process the route list */
3016 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]);
3017 dest
&& bgp
->gr_info
[afi
][safi
].gr_deferred
!= 0;
3018 dest
= bgp_route_next(dest
)) {
3019 if (!CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
))
3022 UNSET_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
);
3023 bgp
->gr_info
[afi
][safi
].gr_deferred
--;
3024 bgp_process_main_one(bgp
, dest
, afi
, safi
);
3026 if (cnt
>= BGP_MAX_BEST_ROUTE_SELECT
) {
3027 bgp_dest_unlock_node(dest
);
3032 /* Send EOR message when all routes are processed */
3033 if (!bgp
->gr_info
[afi
][safi
].gr_deferred
) {
3034 bgp_send_delayed_eor(bgp
);
3035 /* Send route processing complete message to RIB */
3036 bgp_zebra_update(afi
, safi
, bgp
->vrf_id
,
3037 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE
);
3041 thread_info
= XMALLOC(MTYPE_TMP
, sizeof(struct afi_safi_info
));
3043 thread_info
->afi
= afi
;
3044 thread_info
->safi
= safi
;
3045 thread_info
->bgp
= bgp
;
3047 /* If there are more routes to be processed, start the
3050 thread_add_timer(bm
->master
, bgp_route_select_timer_expire
, thread_info
,
3051 BGP_ROUTE_SELECT_DELAY
,
3052 &bgp
->gr_info
[afi
][safi
].t_route_select
);
3056 static wq_item_status
bgp_process_wq(struct work_queue
*wq
, void *data
)
3058 struct bgp_process_queue
*pqnode
= data
;
3059 struct bgp
*bgp
= pqnode
->bgp
;
3060 struct bgp_table
*table
;
3061 struct bgp_dest
*dest
;
3064 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)) {
3065 bgp_process_main_one(bgp
, NULL
, 0, 0);
3066 /* should always have dedicated wq call */
3067 assert(STAILQ_FIRST(&pqnode
->pqueue
) == NULL
);
3071 while (!STAILQ_EMPTY(&pqnode
->pqueue
)) {
3072 dest
= STAILQ_FIRST(&pqnode
->pqueue
);
3073 STAILQ_REMOVE_HEAD(&pqnode
->pqueue
, pq
);
3074 STAILQ_NEXT(dest
, pq
) = NULL
; /* complete unlink */
3075 table
= bgp_dest_table(dest
);
3076 /* note, new DESTs may be added as part of processing */
3077 bgp_process_main_one(bgp
, dest
, table
->afi
, table
->safi
);
3079 bgp_dest_unlock_node(dest
);
3080 bgp_table_unlock(table
);
3086 static void bgp_processq_del(struct work_queue
*wq
, void *data
)
3088 struct bgp_process_queue
*pqnode
= data
;
3090 bgp_unlock(pqnode
->bgp
);
3092 XFREE(MTYPE_BGP_PROCESS_QUEUE
, pqnode
);
3095 void bgp_process_queue_init(struct bgp
*bgp
)
3097 if (!bgp
->process_queue
) {
3100 snprintf(name
, BUFSIZ
, "process_queue %s", bgp
->name_pretty
);
3101 bgp
->process_queue
= work_queue_new(bm
->master
, name
);
3104 bgp
->process_queue
->spec
.workfunc
= &bgp_process_wq
;
3105 bgp
->process_queue
->spec
.del_item_data
= &bgp_processq_del
;
3106 bgp
->process_queue
->spec
.max_retries
= 0;
3107 bgp
->process_queue
->spec
.hold
= 50;
3108 /* Use a higher yield value of 50ms for main queue processing */
3109 bgp
->process_queue
->spec
.yield
= 50 * 1000L;
3112 static struct bgp_process_queue
*bgp_processq_alloc(struct bgp
*bgp
)
3114 struct bgp_process_queue
*pqnode
;
3116 pqnode
= XCALLOC(MTYPE_BGP_PROCESS_QUEUE
,
3117 sizeof(struct bgp_process_queue
));
3119 /* unlocked in bgp_processq_del */
3120 pqnode
->bgp
= bgp_lock(bgp
);
3121 STAILQ_INIT(&pqnode
->pqueue
);
3126 void bgp_process(struct bgp
*bgp
, struct bgp_dest
*dest
, afi_t afi
, safi_t safi
)
3128 #define ARBITRARY_PROCESS_QLEN 10000
3129 struct work_queue
*wq
= bgp
->process_queue
;
3130 struct bgp_process_queue
*pqnode
;
3131 int pqnode_reuse
= 0;
3133 /* already scheduled for processing? */
3134 if (CHECK_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
3137 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
3140 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
3141 if (BGP_DEBUG(update
, UPDATE_OUT
))
3142 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
3147 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
)) {
3148 if (BGP_DEBUG(update
, UPDATE_OUT
))
3150 "Soft reconfigure table in progress for route %p",
3158 /* Add route nodes to an existing work queue item until reaching the
3159 limit only if is from the same BGP view and it's not an EOIU marker
3161 if (work_queue_item_count(wq
)) {
3162 struct work_queue_item
*item
= work_queue_last_item(wq
);
3163 pqnode
= item
->data
;
3165 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)
3166 || pqnode
->bgp
!= bgp
3167 || pqnode
->queued
>= ARBITRARY_PROCESS_QLEN
)
3168 pqnode
= bgp_processq_alloc(bgp
);
3172 pqnode
= bgp_processq_alloc(bgp
);
3173 /* all unlocked in bgp_process_wq */
3174 bgp_table_lock(bgp_dest_table(dest
));
3176 SET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
3177 bgp_dest_lock_node(dest
);
3179 /* can't be enqueued twice */
3180 assert(STAILQ_NEXT(dest
, pq
) == NULL
);
3181 STAILQ_INSERT_TAIL(&pqnode
->pqueue
, dest
, pq
);
3185 work_queue_add(wq
, pqnode
);
3190 void bgp_add_eoiu_mark(struct bgp
*bgp
)
3192 struct bgp_process_queue
*pqnode
;
3194 if (bgp
->process_queue
== NULL
)
3197 pqnode
= bgp_processq_alloc(bgp
);
3199 SET_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
);
3200 work_queue_add(bgp
->process_queue
, pqnode
);
3203 static int bgp_maximum_prefix_restart_timer(struct thread
*thread
)
3207 peer
= THREAD_ARG(thread
);
3208 peer
->t_pmax_restart
= NULL
;
3210 if (bgp_debug_neighbor_events(peer
))
3212 "%s Maximum-prefix restart timer expired, restore peering",
3215 if ((peer_clear(peer
, NULL
) < 0) && bgp_debug_neighbor_events(peer
))
3216 zlog_debug("%s: %s peer_clear failed", __func__
, peer
->host
);
3221 static uint32_t bgp_filtered_routes_count(struct peer
*peer
, afi_t afi
,
3225 bool filtered
= false;
3226 struct bgp_dest
*dest
;
3227 struct bgp_adj_in
*ain
;
3228 struct attr attr
= {};
3229 struct bgp_table
*table
= peer
->bgp
->rib
[afi
][safi
];
3231 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
3232 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
3233 const struct prefix
*rn_p
= bgp_dest_get_prefix(dest
);
3237 if (bgp_input_filter(peer
, rn_p
, &attr
, afi
, safi
)
3241 if (bgp_input_modifier(
3242 peer
, rn_p
, &attr
, afi
, safi
,
3243 ROUTE_MAP_IN_NAME(&peer
->filter
[afi
][safi
]),
3251 bgp_attr_undup(&attr
, ain
->attr
);
3258 bool bgp_maximum_prefix_overflow(struct peer
*peer
, afi_t afi
, safi_t safi
,
3262 iana_safi_t pkt_safi
;
3263 uint32_t pcount
= (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3264 PEER_FLAG_MAX_PREFIX_FORCE
))
3265 ? bgp_filtered_routes_count(peer
, afi
, safi
)
3266 + peer
->pcount
[afi
][safi
]
3267 : peer
->pcount
[afi
][safi
];
3269 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX
))
3272 if (pcount
> peer
->pmax
[afi
][safi
]) {
3273 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
3274 PEER_STATUS_PREFIX_LIMIT
)
3279 "%%MAXPFXEXCEED: No. of %s prefix received from %s %u exceed, limit %u",
3280 get_afi_safi_str(afi
, safi
, false), peer
->host
, pcount
,
3281 peer
->pmax
[afi
][safi
]);
3282 SET_FLAG(peer
->af_sflags
[afi
][safi
], PEER_STATUS_PREFIX_LIMIT
);
3284 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3285 PEER_FLAG_MAX_PREFIX_WARNING
))
3288 /* Convert AFI, SAFI to values for packet. */
3289 pkt_afi
= afi_int2iana(afi
);
3290 pkt_safi
= safi_int2iana(safi
);
3294 ndata
[0] = (pkt_afi
>> 8);
3296 ndata
[2] = pkt_safi
;
3297 ndata
[3] = (peer
->pmax
[afi
][safi
] >> 24);
3298 ndata
[4] = (peer
->pmax
[afi
][safi
] >> 16);
3299 ndata
[5] = (peer
->pmax
[afi
][safi
] >> 8);
3300 ndata
[6] = (peer
->pmax
[afi
][safi
]);
3302 SET_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
);
3303 bgp_notify_send_with_data(peer
, BGP_NOTIFY_CEASE
,
3304 BGP_NOTIFY_CEASE_MAX_PREFIX
,
3308 /* Dynamic peers will just close their connection. */
3309 if (peer_dynamic_neighbor(peer
))
3312 /* restart timer start */
3313 if (peer
->pmax_restart
[afi
][safi
]) {
3314 peer
->v_pmax_restart
=
3315 peer
->pmax_restart
[afi
][safi
] * 60;
3317 if (bgp_debug_neighbor_events(peer
))
3319 "%s Maximum-prefix restart timer started for %d secs",
3320 peer
->host
, peer
->v_pmax_restart
);
3322 BGP_TIMER_ON(peer
->t_pmax_restart
,
3323 bgp_maximum_prefix_restart_timer
,
3324 peer
->v_pmax_restart
);
3329 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
3330 PEER_STATUS_PREFIX_LIMIT
);
3333 > (peer
->pmax
[afi
][safi
] * peer
->pmax_threshold
[afi
][safi
] / 100)) {
3334 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
3335 PEER_STATUS_PREFIX_THRESHOLD
)
3340 "%%MAXPFX: No. of %s prefix received from %s reaches %u, max %u",
3341 get_afi_safi_str(afi
, safi
, false), peer
->host
, pcount
,
3342 peer
->pmax
[afi
][safi
]);
3343 SET_FLAG(peer
->af_sflags
[afi
][safi
],
3344 PEER_STATUS_PREFIX_THRESHOLD
);
3346 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
3347 PEER_STATUS_PREFIX_THRESHOLD
);
3351 /* Unconditionally remove the route from the RIB, without taking
3352 * damping into consideration (eg, because the session went down)
3354 void bgp_rib_remove(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
3355 struct peer
*peer
, afi_t afi
, safi_t safi
)
3358 struct bgp
*bgp
= NULL
;
3359 bool delete_route
= false;
3361 bgp_aggregate_decrement(peer
->bgp
, bgp_dest_get_prefix(dest
), pi
, afi
,
3364 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3365 bgp_path_info_delete(dest
, pi
); /* keep historical info */
3367 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3370 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
3371 delete_route
= true;
3372 else if (bgp_dest_set_defer_flag(dest
, true) < 0)
3373 delete_route
= true;
3375 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
3376 UNSET_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
);
3377 bgp
= pi
->peer
->bgp
;
3378 bgp
->gr_info
[afi
][safi
].gr_deferred
--;
3383 hook_call(bgp_process
, peer
->bgp
, afi
, safi
, dest
, peer
, true);
3384 bgp_process(peer
->bgp
, dest
, afi
, safi
);
3387 static void bgp_rib_withdraw(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
3388 struct peer
*peer
, afi_t afi
, safi_t safi
,
3389 struct prefix_rd
*prd
)
3391 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
3393 /* apply dampening, if result is suppressed, we'll be retaining
3394 * the bgp_path_info in the RIB for historical reference.
3396 if (CHECK_FLAG(peer
->bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3397 && peer
->sort
== BGP_PEER_EBGP
)
3398 if ((bgp_damp_withdraw(pi
, dest
, afi
, safi
, 0))
3399 == BGP_DAMP_SUPPRESSED
) {
3400 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;
3607 bool force_evpn_import
= false;
3609 if (frrtrace_enabled(frr_bgp
, process_update
)) {
3610 char pfxprint
[PREFIX2STR_BUFFER
];
3612 prefix2str(p
, pfxprint
, sizeof(pfxprint
));
3613 frrtrace(6, frr_bgp
, process_update
, peer
, pfxprint
, addpath_id
,
3617 #ifdef ENABLE_BGP_VNC
3618 int vnc_implicit_withdraw
= 0;
3622 memset(&new_attr
, 0, sizeof(struct attr
));
3623 new_attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
3624 new_attr
.label
= MPLS_INVALID_LABEL
;
3627 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
3628 /* TODO: Check to see if we can get rid of "is_valid_label" */
3629 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
3630 has_valid_label
= (num_labels
> 0) ? 1 : 0;
3632 has_valid_label
= bgp_is_valid_label(label
);
3634 if (has_valid_label
)
3635 assert(label
!= NULL
);
3637 /* Update overlay index of the attribute */
3638 if (afi
== AFI_L2VPN
&& evpn
)
3639 memcpy(&attr
->evpn_overlay
, evpn
,
3640 sizeof(struct bgp_route_evpn
));
3642 /* When peer's soft reconfiguration enabled. Record input packet in
3645 && CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
3646 && peer
!= bgp
->peer_self
)
3647 bgp_adj_in_set(dest
, peer
, attr
, addpath_id
);
3649 /* Check previously received route. */
3650 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
3651 if (pi
->peer
== peer
&& pi
->type
== type
3652 && pi
->sub_type
== sub_type
3653 && pi
->addpath_rx_id
== addpath_id
)
3656 /* AS path local-as loop check. */
3657 if (peer
->change_local_as
) {
3658 if (peer
->allowas_in
[afi
][safi
])
3659 aspath_loop_count
= peer
->allowas_in
[afi
][safi
];
3660 else if (!CHECK_FLAG(peer
->flags
,
3661 PEER_FLAG_LOCAL_AS_NO_PREPEND
))
3662 aspath_loop_count
= 1;
3664 if (aspath_loop_check(attr
->aspath
, peer
->change_local_as
)
3665 > aspath_loop_count
) {
3666 peer
->stat_pfx_aspath_loop
++;
3667 reason
= "as-path contains our own AS;";
3672 /* If the peer is configured for "allowas-in origin" and the last ASN in
3674 * as-path is our ASN then we do not need to call aspath_loop_check
3676 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN_ORIGIN
))
3677 if (aspath_get_last_as(attr
->aspath
) == bgp
->as
)
3680 /* AS path loop check. */
3681 if (do_loop_check
) {
3682 if (aspath_loop_check(attr
->aspath
, bgp
->as
)
3683 > peer
->allowas_in
[afi
][safi
]
3684 || (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)
3685 && aspath_loop_check(attr
->aspath
, bgp
->confed_id
)
3686 > peer
->allowas_in
[afi
][safi
])) {
3687 peer
->stat_pfx_aspath_loop
++;
3688 reason
= "as-path contains our own AS;";
3693 /* Route reflector originator ID check. */
3694 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
3695 && IPV4_ADDR_SAME(&bgp
->router_id
, &attr
->originator_id
)) {
3696 peer
->stat_pfx_originator_loop
++;
3697 reason
= "originator is us;";
3701 /* Route reflector cluster ID check. */
3702 if (bgp_cluster_filter(peer
, attr
)) {
3703 peer
->stat_pfx_cluster_loop
++;
3704 reason
= "reflected from the same cluster;";
3708 /* Apply incoming filter. */
3709 if (bgp_input_filter(peer
, p
, attr
, afi
, safi
) == FILTER_DENY
) {
3710 peer
->stat_pfx_filter
++;
3715 /* RFC 8212 to prevent route leaks.
3716 * This specification intends to improve this situation by requiring the
3717 * explicit configuration of both BGP Import and Export Policies for any
3718 * External BGP (EBGP) session such as customers, peers, or
3719 * confederation boundaries for all enabled address families. Through
3720 * codification of the aforementioned requirement, operators will
3721 * benefit from consistent behavior across different BGP
3724 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_EBGP_REQUIRES_POLICY
))
3725 if (!bgp_inbound_policy_exists(peer
,
3726 &peer
->filter
[afi
][safi
])) {
3727 reason
= "inbound policy missing";
3731 /* draft-ietf-idr-deprecate-as-set-confed-set
3732 * Filter routes having AS_SET or AS_CONFED_SET in the path.
3733 * Eventually, This document (if approved) updates RFC 4271
3734 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
3735 * and obsoletes RFC 6472.
3737 if (peer
->bgp
->reject_as_sets
)
3738 if (aspath_check_as_sets(attr
->aspath
)) {
3740 "as-path contains AS_SET or AS_CONFED_SET type;";
3746 /* Apply incoming route-map.
3747 * NB: new_attr may now contain newly allocated values from route-map
3749 * commands, so we need bgp_attr_flush in the error paths, until we
3751 * the attr (which takes over the memory references) */
3752 if (bgp_input_modifier(peer
, p
, &new_attr
, afi
, safi
, NULL
, label
,
3755 peer
->stat_pfx_filter
++;
3756 reason
= "route-map;";
3757 bgp_attr_flush(&new_attr
);
3761 if (pi
&& pi
->attr
->rmap_table_id
!= new_attr
.rmap_table_id
) {
3762 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
3763 /* remove from RIB previous entry */
3764 bgp_zebra_withdraw(p
, pi
, bgp
, safi
);
3767 if (peer
->sort
== BGP_PEER_EBGP
) {
3770 * A BGP speaker receiving an announcement tagged with the
3771 * BLACKHOLE community SHOULD add the NO_ADVERTISE or
3772 * NO_EXPORT community as defined in RFC1997, or a
3773 * similar community, to prevent propagation of the
3774 * prefix outside the local AS. The community to prevent
3775 * propagation SHOULD be chosen according to the operator's
3778 if (new_attr
.community
3779 && community_include(new_attr
.community
,
3780 COMMUNITY_BLACKHOLE
))
3781 bgp_attr_add_no_export_community(&new_attr
);
3783 /* If we receive the graceful-shutdown community from an eBGP
3784 * peer we must lower local-preference */
3785 if (new_attr
.community
3786 && community_include(new_attr
.community
, COMMUNITY_GSHUT
)) {
3787 new_attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
3788 new_attr
.local_pref
= BGP_GSHUT_LOCAL_PREF
;
3790 /* If graceful-shutdown is configured then add the GSHUT
3791 * community to all paths received from eBGP peers */
3792 } else if (bgp_in_graceful_shutdown(peer
->bgp
))
3793 bgp_attr_add_gshut_community(&new_attr
);
3798 pi_sub_type
= pi
->sub_type
;
3801 /* next hop check. */
3802 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
)
3803 && bgp_update_martian_nexthop(bgp
, afi
, safi
, pi_type
, pi_sub_type
,
3805 peer
->stat_pfx_nh_invalid
++;
3806 reason
= "martian or self next-hop;";
3807 bgp_attr_flush(&new_attr
);
3811 if (bgp_mac_entry_exists(p
) || bgp_mac_exist(&attr
->rmac
)) {
3812 peer
->stat_pfx_nh_invalid
++;
3813 reason
= "self mac;";
3817 /* The flag BGP_NODE_FIB_INSTALL_PENDING is for the following
3819 * Suppress fib is enabled
3820 * BGP_OPT_NO_FIB is not enabled
3821 * Route type is BGP_ROUTE_NORMAL (peer learnt routes)
3822 * Route is being installed first time (BGP_NODE_FIB_INSTALLED not set)
3824 if (bgp_fibupd_safi(safi
) && BGP_SUPPRESS_FIB_ENABLED(bgp
)
3825 && (sub_type
== BGP_ROUTE_NORMAL
)
3826 && (!bgp_option_check(BGP_OPT_NO_FIB
))
3827 && (!CHECK_FLAG(dest
->flags
, BGP_NODE_FIB_INSTALLED
)))
3828 SET_FLAG(dest
->flags
, BGP_NODE_FIB_INSTALL_PENDING
);
3830 attr_new
= bgp_attr_intern(&new_attr
);
3832 /* If maximum prefix count is configured and current prefix
3835 if (bgp_maximum_prefix_overflow(peer
, afi
, safi
, 0))
3838 /* If the update is implicit withdraw. */
3840 pi
->uptime
= bgp_clock();
3841 same_attr
= attrhash_cmp(pi
->attr
, attr_new
);
3843 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, true);
3845 /* Same attribute comes in. */
3846 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
3848 && (!has_valid_label
3849 || memcmp(&(bgp_path_info_extra_get(pi
))->label
, label
,
3850 num_labels
* sizeof(mpls_label_t
))
3852 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
3853 BGP_CONFIG_DAMPENING
)
3854 && peer
->sort
== BGP_PEER_EBGP
3855 && CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3856 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3857 bgp_debug_rdpfxpath2str(
3858 afi
, safi
, prd
, p
, label
,
3859 num_labels
, addpath_id
? 1 : 0,
3860 addpath_id
, evpn
, pfx_buf
,
3862 zlog_debug("%s rcvd %s", peer
->host
,
3866 if (bgp_damp_update(pi
, dest
, afi
, safi
)
3867 != BGP_DAMP_SUPPRESSED
) {
3868 bgp_aggregate_increment(bgp
, p
, pi
, afi
,
3870 bgp_process(bgp
, dest
, afi
, safi
);
3872 } else /* Duplicate - odd */
3874 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3875 if (!peer
->rcvd_attr_printed
) {
3877 "%s rcvd UPDATE w/ attr: %s",
3879 peer
->rcvd_attr_str
);
3880 peer
->rcvd_attr_printed
= 1;
3883 bgp_debug_rdpfxpath2str(
3884 afi
, safi
, prd
, p
, label
,
3885 num_labels
, addpath_id
? 1 : 0,
3886 addpath_id
, evpn
, pfx_buf
,
3889 "%s rcvd %s...duplicate ignored",
3890 peer
->host
, pfx_buf
);
3893 /* graceful restart STALE flag unset. */
3894 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
3895 bgp_path_info_unset_flag(
3896 dest
, pi
, BGP_PATH_STALE
);
3897 bgp_dest_set_defer_flag(dest
, false);
3898 bgp_process(bgp
, dest
, afi
, safi
);
3902 bgp_dest_unlock_node(dest
);
3903 bgp_attr_unintern(&attr_new
);
3908 /* Withdraw/Announce before we fully processed the withdraw */
3909 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
3910 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3911 bgp_debug_rdpfxpath2str(
3912 afi
, safi
, prd
, p
, label
, num_labels
,
3913 addpath_id
? 1 : 0, addpath_id
, evpn
,
3914 pfx_buf
, sizeof(pfx_buf
));
3916 "%s rcvd %s, flapped quicker than processing",
3917 peer
->host
, pfx_buf
);
3920 bgp_path_info_restore(dest
, pi
);
3923 * If the BGP_PATH_REMOVED flag is set, then EVPN
3924 * routes would have been unimported already when a
3925 * prior BGP withdraw processing happened. Such routes
3926 * need to be imported again, so flag accordingly.
3928 force_evpn_import
= true;
3931 /* Received Logging. */
3932 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3933 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
3934 num_labels
, addpath_id
? 1 : 0,
3935 addpath_id
, evpn
, pfx_buf
,
3937 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3940 /* graceful restart STALE flag unset. */
3941 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
3942 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_STALE
);
3943 bgp_dest_set_defer_flag(dest
, false);
3946 /* The attribute is changed. */
3947 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
3949 /* implicit withdraw, decrement aggregate and pcount here.
3950 * only if update is accepted, they'll increment below.
3952 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
3954 /* Update bgp route dampening information. */
3955 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3956 && peer
->sort
== BGP_PEER_EBGP
) {
3957 /* This is implicit withdraw so we should update
3960 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
3961 bgp_damp_withdraw(pi
, dest
, afi
, safi
, 1);
3963 #ifdef ENABLE_BGP_VNC
3964 if (safi
== SAFI_MPLS_VPN
) {
3965 struct bgp_dest
*pdest
= NULL
;
3966 struct bgp_table
*table
= NULL
;
3968 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
],
3969 (struct prefix
*)prd
);
3970 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
3971 table
= bgp_dest_get_bgp_table_info(pdest
);
3973 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3974 bgp
, prd
, table
, p
, pi
);
3976 bgp_dest_unlock_node(pdest
);
3978 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3979 && (safi
== SAFI_UNICAST
)) {
3980 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
3982 * Implicit withdraw case.
3984 ++vnc_implicit_withdraw
;
3985 vnc_import_bgp_del_route(bgp
, p
, pi
);
3986 vnc_import_bgp_exterior_del_route(bgp
, p
, pi
);
3991 /* Special handling for EVPN update of an existing route. If the
3992 * extended community attribute has changed, we need to
3994 * the route using its existing extended community. It will be
3995 * subsequently processed for import with the new extended
3998 if (((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
))
4001 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))
4003 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
4006 cmp
= ecommunity_cmp(pi
->attr
->ecommunity
,
4007 attr_new
->ecommunity
);
4009 if (bgp_debug_update(peer
, p
, NULL
, 1))
4011 "Change in EXT-COMM, existing %s new %s",
4013 pi
->attr
->ecommunity
),
4015 attr_new
->ecommunity
));
4016 if (safi
== SAFI_EVPN
)
4017 bgp_evpn_unimport_route(
4018 bgp
, afi
, safi
, p
, pi
);
4019 else /* SAFI_MPLS_VPN */
4020 vpn_leak_to_vrf_withdraw(bgp
,
4026 /* Update to new attribute. */
4027 bgp_attr_unintern(&pi
->attr
);
4028 pi
->attr
= attr_new
;
4030 /* Update MPLS label */
4031 if (has_valid_label
) {
4032 extra
= bgp_path_info_extra_get(pi
);
4033 if (extra
->label
!= label
) {
4034 memcpy(&extra
->label
, label
,
4035 num_labels
* sizeof(mpls_label_t
));
4036 extra
->num_labels
= num_labels
;
4038 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
4039 bgp_set_valid_label(&extra
->label
[0]);
4042 /* Update SRv6 SID */
4043 if (attr
->srv6_l3vpn
) {
4044 extra
= bgp_path_info_extra_get(pi
);
4045 if (sid_diff(&extra
->sid
[0], &attr
->srv6_l3vpn
->sid
)) {
4046 sid_copy(&extra
->sid
[0],
4047 &attr
->srv6_l3vpn
->sid
);
4048 extra
->num_sids
= 1;
4050 } else if (attr
->srv6_vpn
) {
4051 extra
= bgp_path_info_extra_get(pi
);
4052 if (sid_diff(&extra
->sid
[0], &attr
->srv6_vpn
->sid
)) {
4053 sid_copy(&extra
->sid
[0], &attr
->srv6_vpn
->sid
);
4054 extra
->num_sids
= 1;
4058 #ifdef ENABLE_BGP_VNC
4059 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4060 && (safi
== SAFI_UNICAST
)) {
4061 if (vnc_implicit_withdraw
) {
4063 * Add back the route with its new attributes
4065 * The route is still selected, until the route
4067 * queued by bgp_process actually runs. We have
4069 * update to the VNC side immediately to avoid
4071 * configuration changes (e.g., route-map
4073 * trigger re-importation of the entire RIB.
4075 vnc_import_bgp_add_route(bgp
, p
, pi
);
4076 vnc_import_bgp_exterior_add_route(bgp
, p
, pi
);
4081 /* Update bgp route dampening information. */
4082 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
4083 && peer
->sort
== BGP_PEER_EBGP
) {
4084 /* Now we do normal update dampening. */
4085 ret
= bgp_damp_update(pi
, dest
, afi
, safi
);
4086 if (ret
== BGP_DAMP_SUPPRESSED
) {
4087 bgp_dest_unlock_node(dest
);
4092 /* Nexthop reachability check - for unicast and
4093 * labeled-unicast.. */
4094 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
4095 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
4096 || (safi
== SAFI_EVPN
&&
4097 bgp_evpn_is_prefix_nht_supported(p
))) {
4098 if (safi
!= SAFI_EVPN
&& peer
->sort
== BGP_PEER_EBGP
4099 && peer
->ttl
== BGP_DEFAULT_TTL
4100 && !CHECK_FLAG(peer
->flags
,
4101 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
4102 && !CHECK_FLAG(bgp
->flags
,
4103 BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
4108 struct bgp
*bgp_nexthop
= bgp
;
4110 if (pi
->extra
&& pi
->extra
->bgp_orig
)
4111 bgp_nexthop
= pi
->extra
->bgp_orig
;
4113 nh_afi
= BGP_ATTR_NH_AFI(afi
, pi
->attr
);
4115 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
, nh_afi
,
4116 safi
, pi
, NULL
, connected
,
4118 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
4119 bgp_path_info_set_flag(dest
, pi
,
4122 if (BGP_DEBUG(nht
, NHT
)) {
4123 zlog_debug("%s(%pI4): NH unresolved",
4125 (in_addr_t
*)&attr_new
->nexthop
);
4127 bgp_path_info_unset_flag(dest
, pi
,
4131 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_VALID
);
4133 #ifdef ENABLE_BGP_VNC
4134 if (safi
== SAFI_MPLS_VPN
) {
4135 struct bgp_dest
*pdest
= NULL
;
4136 struct bgp_table
*table
= NULL
;
4138 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
],
4139 (struct prefix
*)prd
);
4140 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
4141 table
= bgp_dest_get_bgp_table_info(pdest
);
4143 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4144 bgp
, prd
, table
, p
, pi
);
4146 bgp_dest_unlock_node(pdest
);
4150 /* If this is an EVPN route and some attribute has changed,
4151 * or we are explicitly told to perform a route import, process
4152 * route for import. If the extended community has changed, we
4154 * have done the un-import earlier and the import would result
4156 * route getting injected into appropriate L2 VNIs. If it is
4158 * some other attribute change, the import will result in
4160 * the attributes for the route in the VNI(s).
4162 if (safi
== SAFI_EVPN
&&
4163 (!same_attr
|| force_evpn_import
) &&
4164 CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
4165 bgp_evpn_import_route(bgp
, afi
, safi
, p
, pi
);
4167 /* Process change. */
4168 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
4170 bgp_process(bgp
, dest
, afi
, safi
);
4171 bgp_dest_unlock_node(dest
);
4173 if (SAFI_UNICAST
== safi
4174 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4175 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4177 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, pi
);
4179 if ((SAFI_MPLS_VPN
== safi
)
4180 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4182 vpn_leak_to_vrf_update(bgp
, pi
);
4185 #ifdef ENABLE_BGP_VNC
4186 if (SAFI_MPLS_VPN
== safi
) {
4187 mpls_label_t label_decoded
= decode_label(label
);
4189 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
4190 type
, sub_type
, &label_decoded
);
4192 if (SAFI_ENCAP
== safi
) {
4193 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
4194 type
, sub_type
, NULL
);
4199 } // End of implicit withdraw
4201 /* Received Logging. */
4202 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4203 if (!peer
->rcvd_attr_printed
) {
4204 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
4205 peer
->rcvd_attr_str
);
4206 peer
->rcvd_attr_printed
= 1;
4209 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4210 addpath_id
? 1 : 0, addpath_id
, evpn
,
4211 pfx_buf
, sizeof(pfx_buf
));
4212 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
4215 /* Make new BGP info. */
4216 new = info_make(type
, sub_type
, 0, peer
, attr_new
, dest
);
4218 /* Update MPLS label */
4219 if (has_valid_label
) {
4220 extra
= bgp_path_info_extra_get(new);
4221 if (extra
->label
!= label
) {
4222 memcpy(&extra
->label
, label
,
4223 num_labels
* sizeof(mpls_label_t
));
4224 extra
->num_labels
= num_labels
;
4226 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
4227 bgp_set_valid_label(&extra
->label
[0]);
4230 /* Update SRv6 SID */
4231 if (safi
== SAFI_MPLS_VPN
) {
4232 extra
= bgp_path_info_extra_get(new);
4233 if (attr
->srv6_l3vpn
) {
4234 sid_copy(&extra
->sid
[0], &attr
->srv6_l3vpn
->sid
);
4235 extra
->num_sids
= 1;
4236 } else if (attr
->srv6_vpn
) {
4237 sid_copy(&extra
->sid
[0], &attr
->srv6_vpn
->sid
);
4238 extra
->num_sids
= 1;
4242 /* Nexthop reachability check. */
4243 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
4244 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
4245 || (safi
== SAFI_EVPN
&& bgp_evpn_is_prefix_nht_supported(p
))) {
4246 if (safi
!= SAFI_EVPN
&& peer
->sort
== BGP_PEER_EBGP
4247 && peer
->ttl
== BGP_DEFAULT_TTL
4248 && !CHECK_FLAG(peer
->flags
,
4249 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
4250 && !CHECK_FLAG(bgp
->flags
,
4251 BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
4256 nh_afi
= BGP_ATTR_NH_AFI(afi
, new->attr
);
4258 if (bgp_find_or_add_nexthop(bgp
, bgp
, nh_afi
, safi
, new, NULL
,
4260 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
4261 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
4263 if (BGP_DEBUG(nht
, NHT
)) {
4264 char buf1
[INET6_ADDRSTRLEN
];
4266 (const void *)&attr_new
->nexthop
,
4267 buf1
, INET6_ADDRSTRLEN
);
4268 zlog_debug("%s(%s): NH unresolved", __func__
,
4271 bgp_path_info_unset_flag(dest
, new, BGP_PATH_VALID
);
4274 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
4277 new->addpath_rx_id
= addpath_id
;
4279 /* Increment prefix */
4280 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4282 /* Register new BGP information. */
4283 bgp_path_info_add(dest
, new);
4285 /* route_node_get lock */
4286 bgp_dest_unlock_node(dest
);
4288 #ifdef ENABLE_BGP_VNC
4289 if (safi
== SAFI_MPLS_VPN
) {
4290 struct bgp_dest
*pdest
= NULL
;
4291 struct bgp_table
*table
= NULL
;
4293 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
4294 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
4295 table
= bgp_dest_get_bgp_table_info(pdest
);
4297 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4298 bgp
, prd
, table
, p
, new);
4300 bgp_dest_unlock_node(pdest
);
4304 /* If this is an EVPN route, process for import. */
4305 if (safi
== SAFI_EVPN
&& CHECK_FLAG(new->flags
, BGP_PATH_VALID
))
4306 bgp_evpn_import_route(bgp
, afi
, safi
, p
, new);
4308 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, false);
4310 /* Process change. */
4311 bgp_process(bgp
, dest
, afi
, safi
);
4313 if (SAFI_UNICAST
== safi
4314 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4315 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4316 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
4318 if ((SAFI_MPLS_VPN
== safi
)
4319 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4321 vpn_leak_to_vrf_update(bgp
, new);
4323 #ifdef ENABLE_BGP_VNC
4324 if (SAFI_MPLS_VPN
== safi
) {
4325 mpls_label_t label_decoded
= decode_label(label
);
4327 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
4328 sub_type
, &label_decoded
);
4330 if (SAFI_ENCAP
== safi
) {
4331 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
4338 /* This BGP update is filtered. Log the reason then update BGP
4341 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, true);
4343 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4344 if (!peer
->rcvd_attr_printed
) {
4345 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
4346 peer
->rcvd_attr_str
);
4347 peer
->rcvd_attr_printed
= 1;
4350 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4351 addpath_id
? 1 : 0, addpath_id
, evpn
,
4352 pfx_buf
, sizeof(pfx_buf
));
4353 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
4354 peer
->host
, pfx_buf
, reason
);
4358 /* If this is an EVPN route, un-import it as it is now filtered.
4360 if (safi
== SAFI_EVPN
)
4361 bgp_evpn_unimport_route(bgp
, afi
, safi
, p
, pi
);
4363 if (SAFI_UNICAST
== safi
4364 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4365 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4367 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
4369 if ((SAFI_MPLS_VPN
== safi
)
4370 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4372 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4375 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
4378 bgp_dest_unlock_node(dest
);
4380 #ifdef ENABLE_BGP_VNC
4382 * Filtered update is treated as an implicit withdrawal (see
4384 * a few lines above)
4386 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
4387 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
4395 int bgp_withdraw(struct peer
*peer
, const struct prefix
*p
, uint32_t addpath_id
,
4396 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
4397 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
4398 uint32_t num_labels
, struct bgp_route_evpn
*evpn
)
4401 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
4402 struct bgp_dest
*dest
;
4403 struct bgp_path_info
*pi
;
4405 #ifdef ENABLE_BGP_VNC
4406 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
4407 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
4415 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4417 /* If peer is soft reconfiguration enabled. Record input packet for
4418 * further calculation.
4420 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4421 * routes that are filtered. This tanks out Quagga RS pretty badly due
4423 * the iteration over all RS clients.
4424 * Since we need to remove the entry from adj_in anyway, do that first
4426 * if there was no entry, we don't need to do anything more.
4428 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
4429 && peer
!= bgp
->peer_self
)
4430 if (!bgp_adj_in_unset(dest
, peer
, addpath_id
)) {
4431 peer
->stat_pfx_dup_withdraw
++;
4433 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4434 bgp_debug_rdpfxpath2str(
4435 afi
, safi
, prd
, p
, label
, num_labels
,
4436 addpath_id
? 1 : 0, addpath_id
, NULL
,
4437 pfx_buf
, sizeof(pfx_buf
));
4439 "%s withdrawing route %s not in adj-in",
4440 peer
->host
, pfx_buf
);
4442 bgp_dest_unlock_node(dest
);
4446 /* Lookup withdrawn route. */
4447 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
4448 if (pi
->peer
== peer
&& pi
->type
== type
4449 && pi
->sub_type
== sub_type
4450 && pi
->addpath_rx_id
== addpath_id
)
4454 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4455 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4456 addpath_id
? 1 : 0, addpath_id
, NULL
,
4457 pfx_buf
, sizeof(pfx_buf
));
4458 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer
->host
,
4462 /* Withdraw specified route from routing table. */
4463 if (pi
&& !CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
4464 bgp_rib_withdraw(dest
, pi
, peer
, afi
, safi
, prd
);
4465 if (SAFI_UNICAST
== safi
4466 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4467 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4468 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
4470 if ((SAFI_MPLS_VPN
== safi
)
4471 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4473 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4475 } else if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4476 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4477 addpath_id
? 1 : 0, addpath_id
, NULL
,
4478 pfx_buf
, sizeof(pfx_buf
));
4479 zlog_debug("%s Can't find the route %s", peer
->host
, pfx_buf
);
4482 /* Unlock bgp_node_get() lock. */
4483 bgp_dest_unlock_node(dest
);
4488 void bgp_default_originate(struct peer
*peer
, afi_t afi
, safi_t safi
,
4491 struct update_subgroup
*subgrp
;
4492 subgrp
= peer_subgroup(peer
, afi
, safi
);
4493 subgroup_default_originate(subgrp
, withdraw
);
4498 * bgp_stop_announce_route_timer
4500 void bgp_stop_announce_route_timer(struct peer_af
*paf
)
4502 if (!paf
->t_announce_route
)
4505 thread_cancel(&paf
->t_announce_route
);
4509 * bgp_announce_route_timer_expired
4511 * Callback that is invoked when the route announcement timer for a
4514 static int bgp_announce_route_timer_expired(struct thread
*t
)
4516 struct peer_af
*paf
;
4519 paf
= THREAD_ARG(t
);
4522 if (!peer_established(peer
))
4525 if (!peer
->afc_nego
[paf
->afi
][paf
->safi
])
4528 peer_af_announce_route(paf
, 1);
4530 /* Notify BGP conditional advertisement scanner percess */
4531 peer
->advmap_config_change
[paf
->afi
][paf
->safi
] = true;
4537 * bgp_announce_route
4539 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
4541 void bgp_announce_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4543 struct peer_af
*paf
;
4544 struct update_subgroup
*subgrp
;
4546 paf
= peer_af_find(peer
, afi
, safi
);
4549 subgrp
= PAF_SUBGRP(paf
);
4552 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
4553 * or a refresh has already been triggered.
4555 if (!subgrp
|| paf
->t_announce_route
)
4559 * Start a timer to stagger/delay the announce. This serves
4560 * two purposes - announcement can potentially be combined for
4561 * multiple peers and the announcement doesn't happen in the
4564 thread_add_timer_msec(bm
->master
, bgp_announce_route_timer_expired
, paf
,
4565 (subgrp
->peer_count
== 1)
4566 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
4567 : BGP_ANNOUNCE_ROUTE_DELAY_MS
,
4568 &paf
->t_announce_route
);
4572 * Announce routes from all AF tables to a peer.
4574 * This should ONLY be called when there is a need to refresh the
4575 * routes to the peer based on a policy change for this peer alone
4576 * or a route refresh request received from the peer.
4577 * The operation will result in splitting the peer from its existing
4578 * subgroups and putting it in new subgroups.
4580 void bgp_announce_route_all(struct peer
*peer
)
4585 FOREACH_AFI_SAFI (afi
, safi
)
4586 bgp_announce_route(peer
, afi
, safi
);
4589 /* Flag or unflag bgp_dest to determine whether it should be treated by
4590 * bgp_soft_reconfig_table_task.
4591 * Flag if flag is true. Unflag if flag is false.
4593 static void bgp_soft_reconfig_table_flag(struct bgp_table
*table
, bool flag
)
4595 struct bgp_dest
*dest
;
4596 struct bgp_adj_in
*ain
;
4601 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
4602 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
4603 if (ain
->peer
!= NULL
)
4606 if (flag
&& ain
!= NULL
&& ain
->peer
!= NULL
)
4607 SET_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
);
4609 UNSET_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
);
4613 static int bgp_soft_reconfig_table_update(struct peer
*peer
,
4614 struct bgp_dest
*dest
,
4615 struct bgp_adj_in
*ain
, afi_t afi
,
4616 safi_t safi
, struct prefix_rd
*prd
)
4618 struct bgp_path_info
*pi
;
4619 uint32_t num_labels
= 0;
4620 mpls_label_t
*label_pnt
= NULL
;
4621 struct bgp_route_evpn evpn
;
4623 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
4624 if (pi
->peer
== peer
)
4627 if (pi
&& pi
->extra
)
4628 num_labels
= pi
->extra
->num_labels
;
4630 label_pnt
= &pi
->extra
->label
[0];
4632 memcpy(&evpn
, bgp_attr_get_evpn_overlay(pi
->attr
),
4635 memset(&evpn
, 0, sizeof(evpn
));
4637 return bgp_update(peer
, bgp_dest_get_prefix(dest
), ain
->addpath_rx_id
,
4638 ain
->attr
, afi
, safi
, ZEBRA_ROUTE_BGP
,
4639 BGP_ROUTE_NORMAL
, prd
, label_pnt
, num_labels
, 1,
4643 static void bgp_soft_reconfig_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
4644 struct bgp_table
*table
,
4645 struct prefix_rd
*prd
)
4648 struct bgp_dest
*dest
;
4649 struct bgp_adj_in
*ain
;
4652 table
= peer
->bgp
->rib
[afi
][safi
];
4654 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
))
4655 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
4656 if (ain
->peer
!= peer
)
4659 ret
= bgp_soft_reconfig_table_update(peer
, dest
, ain
,
4663 bgp_dest_unlock_node(dest
);
4669 /* Do soft reconfig table per bgp table.
4670 * Walk on SOFT_RECONFIG_TASK_MAX_PREFIX bgp_dest,
4671 * when BGP_NODE_SOFT_RECONFIG is set,
4672 * reconfig bgp_dest for list of table->soft_reconfig_peers peers.
4673 * Schedule a new thread to continue the job.
4674 * Without splitting the full job into several part,
4675 * vtysh waits for the job to finish before responding to a BGP command
4677 static int bgp_soft_reconfig_table_task(struct thread
*thread
)
4679 uint32_t iter
, max_iter
;
4681 struct bgp_dest
*dest
;
4682 struct bgp_adj_in
*ain
;
4684 struct bgp_table
*table
;
4685 struct prefix_rd
*prd
;
4686 struct listnode
*node
, *nnode
;
4688 table
= THREAD_ARG(thread
);
4691 max_iter
= SOFT_RECONFIG_TASK_MAX_PREFIX
;
4692 if (table
->soft_reconfig_init
) {
4693 /* first call of the function with a new srta structure.
4694 * Don't do any treatment this time on nodes
4695 * in order vtysh to respond quickly
4700 for (iter
= 0, dest
= bgp_table_top(table
); (dest
&& iter
< max_iter
);
4701 dest
= bgp_route_next(dest
)) {
4702 if (!CHECK_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
))
4705 UNSET_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
);
4707 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
4708 for (ALL_LIST_ELEMENTS(table
->soft_reconfig_peers
, node
,
4710 if (ain
->peer
!= peer
)
4713 ret
= bgp_soft_reconfig_table_update(
4714 peer
, dest
, ain
, table
->afi
,
4719 bgp_dest_unlock_node(dest
);
4721 table
->soft_reconfig_peers
,
4723 bgp_announce_route(peer
, table
->afi
,
4726 table
->soft_reconfig_peers
)) {
4728 &table
->soft_reconfig_peers
);
4729 bgp_soft_reconfig_table_flag(
4738 /* we're either starting the initial iteration,
4739 * or we're going to continue an ongoing iteration
4741 if (dest
|| table
->soft_reconfig_init
) {
4742 table
->soft_reconfig_init
= false;
4743 thread_add_event(bm
->master
, bgp_soft_reconfig_table_task
,
4744 table
, 0, &table
->soft_reconfig_thread
);
4747 /* we're done, clean up the background iteration context info and
4748 schedule route annoucement
4750 for (ALL_LIST_ELEMENTS(table
->soft_reconfig_peers
, node
, nnode
, peer
)) {
4751 listnode_delete(table
->soft_reconfig_peers
, peer
);
4752 bgp_announce_route(peer
, table
->afi
, table
->safi
);
4755 list_delete(&table
->soft_reconfig_peers
);
4761 /* Cancel soft_reconfig_table task matching bgp instance, bgp_table
4763 * - bgp cannot be NULL
4764 * - if table and peer are NULL, cancel all threads within the bgp instance
4765 * - if table is NULL and peer is not,
4766 * remove peer in all threads within the bgp instance
4767 * - if peer is NULL, cancel all threads matching table within the bgp instance
4769 void bgp_soft_reconfig_table_task_cancel(const struct bgp
*bgp
,
4770 const struct bgp_table
*table
,
4771 const struct peer
*peer
)
4774 struct listnode
*node
, *nnode
;
4776 struct bgp_table
*ntable
;
4781 FOREACH_AFI_SAFI (afi
, safi
) {
4782 ntable
= bgp
->rib
[afi
][safi
];
4785 if (table
&& table
!= ntable
)
4788 for (ALL_LIST_ELEMENTS(ntable
->soft_reconfig_peers
, node
, nnode
,
4790 if (peer
&& peer
!= npeer
)
4792 listnode_delete(ntable
->soft_reconfig_peers
, npeer
);
4795 if (!ntable
->soft_reconfig_peers
4796 || !list_isempty(ntable
->soft_reconfig_peers
))
4799 list_delete(&ntable
->soft_reconfig_peers
);
4800 bgp_soft_reconfig_table_flag(ntable
, false);
4801 BGP_TIMER_OFF(ntable
->soft_reconfig_thread
);
4805 void bgp_soft_reconfig_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
4807 struct bgp_dest
*dest
;
4808 struct bgp_table
*table
;
4809 struct listnode
*node
, *nnode
;
4811 struct peer_af
*paf
;
4813 if (!peer_established(peer
))
4816 if ((safi
!= SAFI_MPLS_VPN
) && (safi
!= SAFI_ENCAP
)
4817 && (safi
!= SAFI_EVPN
)) {
4818 table
= peer
->bgp
->rib
[afi
][safi
];
4822 table
->soft_reconfig_init
= true;
4824 if (!table
->soft_reconfig_peers
)
4825 table
->soft_reconfig_peers
= list_new();
4827 /* add peer to the table soft_reconfig_peers if not already
4830 for (ALL_LIST_ELEMENTS(table
->soft_reconfig_peers
, node
, nnode
,
4836 listnode_add(table
->soft_reconfig_peers
, peer
);
4838 /* (re)flag all bgp_dest in table. Existing soft_reconfig_in job
4839 * on table would start back at the beginning.
4841 bgp_soft_reconfig_table_flag(table
, true);
4843 if (!table
->soft_reconfig_thread
)
4844 thread_add_event(bm
->master
,
4845 bgp_soft_reconfig_table_task
, table
, 0,
4846 &table
->soft_reconfig_thread
);
4847 /* Cancel bgp_announce_route_timer_expired threads.
4848 * bgp_announce_route_timer_expired threads have been scheduled
4849 * to announce routes as soon as the soft_reconfigure process
4851 * In this case, soft_reconfigure is also scheduled by using
4852 * a thread but is planned after the
4853 * bgp_announce_route_timer_expired threads. It means that,
4854 * without cancelling the threads, the route announcement task
4855 * would run before the soft reconfiguration one. That would
4856 * useless and would block vtysh during several seconds. Route
4857 * announcements are rescheduled as soon as the soft_reconfigure
4860 paf
= peer_af_find(peer
, afi
, safi
);
4862 bgp_stop_announce_route_timer(paf
);
4864 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
4865 dest
= bgp_route_next(dest
)) {
4866 table
= bgp_dest_get_bgp_table_info(dest
);
4871 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
4872 struct prefix_rd prd
;
4874 prd
.family
= AF_UNSPEC
;
4876 memcpy(&prd
.val
, p
->u
.val
, 8);
4878 bgp_soft_reconfig_table(peer
, afi
, safi
, table
, &prd
);
4883 struct bgp_clear_node_queue
{
4884 struct bgp_dest
*dest
;
4887 static wq_item_status
bgp_clear_route_node(struct work_queue
*wq
, void *data
)
4889 struct bgp_clear_node_queue
*cnq
= data
;
4890 struct bgp_dest
*dest
= cnq
->dest
;
4891 struct peer
*peer
= wq
->spec
.data
;
4892 struct bgp_path_info
*pi
;
4894 afi_t afi
= bgp_dest_table(dest
)->afi
;
4895 safi_t safi
= bgp_dest_table(dest
)->safi
;
4897 assert(dest
&& peer
);
4900 /* It is possible that we have multiple paths for a prefix from a peer
4901 * if that peer is using AddPath.
4903 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
4904 if (pi
->peer
!= peer
)
4907 /* graceful restart STALE flag set. */
4908 if (((CHECK_FLAG(peer
->sflags
, PEER_STATUS_NSF_WAIT
)
4909 && peer
->nsf
[afi
][safi
])
4910 || CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
4911 PEER_STATUS_ENHANCED_REFRESH
))
4912 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
4913 && !CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
4914 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_STALE
);
4916 /* If this is an EVPN route, process for
4918 if (safi
== SAFI_EVPN
)
4919 bgp_evpn_unimport_route(
4921 bgp_dest_get_prefix(dest
), pi
);
4922 /* Handle withdraw for VRF route-leaking and L3VPN */
4923 if (SAFI_UNICAST
== safi
4924 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
||
4925 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4926 vpn_leak_from_vrf_withdraw(bgp_get_default(),
4929 if (SAFI_MPLS_VPN
== safi
&&
4930 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4931 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4934 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
4940 static void bgp_clear_node_queue_del(struct work_queue
*wq
, void *data
)
4942 struct bgp_clear_node_queue
*cnq
= data
;
4943 struct bgp_dest
*dest
= cnq
->dest
;
4944 struct bgp_table
*table
= bgp_dest_table(dest
);
4946 bgp_dest_unlock_node(dest
);
4947 bgp_table_unlock(table
);
4948 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE
, cnq
);
4951 static void bgp_clear_node_complete(struct work_queue
*wq
)
4953 struct peer
*peer
= wq
->spec
.data
;
4955 /* Tickle FSM to start moving again */
4956 BGP_EVENT_ADD(peer
, Clearing_Completed
);
4958 peer_unlock(peer
); /* bgp_clear_route */
4961 static void bgp_clear_node_queue_init(struct peer
*peer
)
4963 char wname
[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
4965 snprintf(wname
, sizeof(wname
), "clear %s", peer
->host
);
4966 #undef CLEAR_QUEUE_NAME_LEN
4968 peer
->clear_node_queue
= work_queue_new(bm
->master
, wname
);
4969 peer
->clear_node_queue
->spec
.hold
= 10;
4970 peer
->clear_node_queue
->spec
.workfunc
= &bgp_clear_route_node
;
4971 peer
->clear_node_queue
->spec
.del_item_data
= &bgp_clear_node_queue_del
;
4972 peer
->clear_node_queue
->spec
.completion_func
= &bgp_clear_node_complete
;
4973 peer
->clear_node_queue
->spec
.max_retries
= 0;
4975 /* we only 'lock' this peer reference when the queue is actually active
4977 peer
->clear_node_queue
->spec
.data
= peer
;
4980 static void bgp_clear_route_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
4981 struct bgp_table
*table
)
4983 struct bgp_dest
*dest
;
4984 int force
= peer
->bgp
->process_queue
? 0 : 1;
4987 table
= peer
->bgp
->rib
[afi
][safi
];
4989 /* If still no table => afi/safi isn't configured at all or smth. */
4993 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
4994 struct bgp_path_info
*pi
, *next
;
4995 struct bgp_adj_in
*ain
;
4996 struct bgp_adj_in
*ain_next
;
4998 /* XXX:TODO: This is suboptimal, every non-empty route_node is
4999 * queued for every clearing peer, regardless of whether it is
5000 * relevant to the peer at hand.
5002 * Overview: There are 3 different indices which need to be
5003 * scrubbed, potentially, when a peer is removed:
5005 * 1 peer's routes visible via the RIB (ie accepted routes)
5006 * 2 peer's routes visible by the (optional) peer's adj-in index
5007 * 3 other routes visible by the peer's adj-out index
5009 * 3 there is no hurry in scrubbing, once the struct peer is
5010 * removed from bgp->peer, we could just GC such deleted peer's
5011 * adj-outs at our leisure.
5013 * 1 and 2 must be 'scrubbed' in some way, at least made
5014 * invisible via RIB index before peer session is allowed to be
5015 * brought back up. So one needs to know when such a 'search' is
5020 * - there'd be a single global queue or a single RIB walker
5021 * - rather than tracking which route_nodes still need to be
5022 * examined on a peer basis, we'd track which peers still
5025 * Given that our per-peer prefix-counts now should be reliable,
5026 * this may actually be achievable. It doesn't seem to be a huge
5027 * problem at this time,
5029 * It is possible that we have multiple paths for a prefix from
5031 * if that peer is using AddPath.
5035 ain_next
= ain
->next
;
5037 if (ain
->peer
== peer
)
5038 bgp_adj_in_remove(dest
, ain
);
5043 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= next
) {
5045 if (pi
->peer
!= peer
)
5049 bgp_path_info_reap(dest
, pi
);
5051 struct bgp_clear_node_queue
*cnq
;
5053 /* both unlocked in bgp_clear_node_queue_del */
5054 bgp_table_lock(bgp_dest_table(dest
));
5055 bgp_dest_lock_node(dest
);
5057 MTYPE_BGP_CLEAR_NODE_QUEUE
,
5058 sizeof(struct bgp_clear_node_queue
));
5060 work_queue_add(peer
->clear_node_queue
, cnq
);
5068 void bgp_clear_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
5070 struct bgp_dest
*dest
;
5071 struct bgp_table
*table
;
5073 if (peer
->clear_node_queue
== NULL
)
5074 bgp_clear_node_queue_init(peer
);
5076 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
5077 * Idle until it receives a Clearing_Completed event. This protects
5078 * against peers which flap faster than we can we clear, which could
5081 * a) race with routes from the new session being installed before
5082 * clear_route_node visits the node (to delete the route of that
5084 * b) resource exhaustion, clear_route_node likely leads to an entry
5085 * on the process_main queue. Fast-flapping could cause that queue
5089 /* lock peer in assumption that clear-node-queue will get nodes; if so,
5090 * the unlock will happen upon work-queue completion; other wise, the
5091 * unlock happens at the end of this function.
5093 if (!peer
->clear_node_queue
->thread
)
5096 if (safi
!= SAFI_MPLS_VPN
&& safi
!= SAFI_ENCAP
&& safi
!= SAFI_EVPN
)
5097 bgp_clear_route_table(peer
, afi
, safi
, NULL
);
5099 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5100 dest
= bgp_route_next(dest
)) {
5101 table
= bgp_dest_get_bgp_table_info(dest
);
5105 bgp_clear_route_table(peer
, afi
, safi
, table
);
5108 /* unlock if no nodes got added to the clear-node-queue. */
5109 if (!peer
->clear_node_queue
->thread
)
5113 void bgp_clear_route_all(struct peer
*peer
)
5118 FOREACH_AFI_SAFI (afi
, safi
)
5119 bgp_clear_route(peer
, afi
, safi
);
5121 #ifdef ENABLE_BGP_VNC
5122 rfapiProcessPeerDown(peer
);
5126 void bgp_clear_adj_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
5128 struct bgp_table
*table
;
5129 struct bgp_dest
*dest
;
5130 struct bgp_adj_in
*ain
;
5131 struct bgp_adj_in
*ain_next
;
5133 table
= peer
->bgp
->rib
[afi
][safi
];
5135 /* It is possible that we have multiple paths for a prefix from a peer
5136 * if that peer is using AddPath.
5138 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
5142 ain_next
= ain
->next
;
5144 if (ain
->peer
== peer
)
5145 bgp_adj_in_remove(dest
, ain
);
5152 void bgp_clear_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
5154 struct bgp_dest
*dest
;
5155 struct bgp_path_info
*pi
;
5156 struct bgp_table
*table
;
5158 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
5159 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5160 dest
= bgp_route_next(dest
)) {
5161 struct bgp_dest
*rm
;
5163 /* look for neighbor in tables */
5164 table
= bgp_dest_get_bgp_table_info(dest
);
5168 for (rm
= bgp_table_top(table
); rm
;
5169 rm
= bgp_route_next(rm
))
5170 for (pi
= bgp_dest_get_bgp_path_info(rm
); pi
;
5172 if (pi
->peer
!= peer
)
5174 if (!CHECK_FLAG(pi
->flags
,
5178 bgp_rib_remove(rm
, pi
, peer
, afi
, safi
);
5183 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5184 dest
= bgp_route_next(dest
))
5185 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
5187 if (pi
->peer
!= peer
)
5189 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
5191 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
5197 void bgp_set_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
5199 struct bgp_dest
*dest
, *ndest
;
5200 struct bgp_path_info
*pi
;
5201 struct bgp_table
*table
;
5203 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
5204 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5205 dest
= bgp_route_next(dest
)) {
5206 table
= bgp_dest_get_bgp_table_info(dest
);
5210 for (ndest
= bgp_table_top(table
); ndest
;
5211 ndest
= bgp_route_next(ndest
)) {
5212 for (pi
= bgp_dest_get_bgp_path_info(ndest
); pi
;
5214 if (pi
->peer
!= peer
)
5218 peer
->af_sflags
[afi
][safi
],
5219 PEER_STATUS_ENHANCED_REFRESH
))
5220 && !CHECK_FLAG(pi
->flags
,
5224 BGP_PATH_UNUSEABLE
)) {
5225 if (bgp_debug_neighbor_events(
5228 "%s: route-refresh for %s/%s, marking prefix %pFX as stale",
5232 bgp_dest_get_prefix(
5235 bgp_path_info_set_flag(
5243 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5244 dest
= bgp_route_next(dest
)) {
5245 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
5247 if (pi
->peer
!= peer
)
5250 if ((CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
5251 PEER_STATUS_ENHANCED_REFRESH
))
5252 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
5253 && !CHECK_FLAG(pi
->flags
,
5254 BGP_PATH_UNUSEABLE
)) {
5255 if (bgp_debug_neighbor_events(peer
))
5257 "%s: route-refresh for %s/%s, marking prefix %pFX as stale",
5261 bgp_dest_get_prefix(
5264 bgp_path_info_set_flag(dest
, pi
,
5272 bool bgp_outbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
5274 if (peer
->sort
== BGP_PEER_IBGP
)
5277 if (peer
->sort
== BGP_PEER_EBGP
5278 && (ROUTE_MAP_OUT_NAME(filter
) || PREFIX_LIST_OUT_NAME(filter
)
5279 || FILTER_LIST_OUT_NAME(filter
)
5280 || DISTRIBUTE_OUT_NAME(filter
)))
5285 bool bgp_inbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
5287 if (peer
->sort
== BGP_PEER_IBGP
)
5290 if (peer
->sort
== BGP_PEER_EBGP
5291 && (ROUTE_MAP_IN_NAME(filter
) || PREFIX_LIST_IN_NAME(filter
)
5292 || FILTER_LIST_IN_NAME(filter
)
5293 || DISTRIBUTE_IN_NAME(filter
)))
5298 static void bgp_cleanup_table(struct bgp
*bgp
, struct bgp_table
*table
,
5301 struct bgp_dest
*dest
;
5302 struct bgp_path_info
*pi
;
5303 struct bgp_path_info
*next
;
5305 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
))
5306 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= next
) {
5307 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
5311 /* Unimport EVPN routes from VRFs */
5312 if (safi
== SAFI_EVPN
)
5313 bgp_evpn_unimport_route(bgp
, AFI_L2VPN
,
5316 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)
5317 && pi
->type
== ZEBRA_ROUTE_BGP
5318 && (pi
->sub_type
== BGP_ROUTE_NORMAL
5319 || pi
->sub_type
== BGP_ROUTE_AGGREGATE
5320 || pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
5322 if (bgp_fibupd_safi(safi
))
5323 bgp_zebra_withdraw(p
, pi
, bgp
, safi
);
5326 bgp_path_info_reap(dest
, pi
);
5330 /* Delete all kernel routes. */
5331 void bgp_cleanup_routes(struct bgp
*bgp
)
5334 struct bgp_dest
*dest
;
5335 struct bgp_table
*table
;
5337 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
5338 if (afi
== AFI_L2VPN
)
5340 bgp_cleanup_table(bgp
, bgp
->rib
[afi
][SAFI_UNICAST
],
5343 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
5345 if (afi
!= AFI_L2VPN
) {
5347 safi
= SAFI_MPLS_VPN
;
5348 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); dest
;
5349 dest
= bgp_route_next(dest
)) {
5350 table
= bgp_dest_get_bgp_table_info(dest
);
5351 if (table
!= NULL
) {
5352 bgp_cleanup_table(bgp
, table
, safi
);
5353 bgp_table_finish(&table
);
5354 bgp_dest_set_bgp_table_info(dest
, NULL
);
5355 bgp_dest_unlock_node(dest
);
5359 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); 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
);
5364 bgp_table_finish(&table
);
5365 bgp_dest_set_bgp_table_info(dest
, NULL
);
5366 bgp_dest_unlock_node(dest
);
5371 for (dest
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); dest
;
5372 dest
= bgp_route_next(dest
)) {
5373 table
= bgp_dest_get_bgp_table_info(dest
);
5374 if (table
!= NULL
) {
5375 bgp_cleanup_table(bgp
, table
, SAFI_EVPN
);
5376 bgp_table_finish(&table
);
5377 bgp_dest_set_bgp_table_info(dest
, NULL
);
5378 bgp_dest_unlock_node(dest
);
5383 void bgp_reset(void)
5386 bgp_zclient_reset();
5387 access_list_reset();
5388 prefix_list_reset();
5391 static int bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
5393 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
5394 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
5395 PEER_CAP_ADDPATH_AF_TX_RCV
));
5398 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
5400 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
5401 struct bgp_nlri
*packet
)
5410 int addpath_encoded
;
5411 uint32_t addpath_id
;
5414 lim
= pnt
+ packet
->length
;
5416 safi
= packet
->safi
;
5418 addpath_encoded
= bgp_addpath_encode_rx(peer
, afi
, safi
);
5420 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
5421 syntactic validity. If the field is syntactically incorrect,
5422 then the Error Subcode is set to Invalid Network Field. */
5423 for (; pnt
< lim
; pnt
+= psize
) {
5424 /* Clear prefix structure. */
5425 memset(&p
, 0, sizeof(struct prefix
));
5427 if (addpath_encoded
) {
5429 /* When packet overflow occurs return immediately. */
5430 if (pnt
+ BGP_ADDPATH_ID_LEN
>= lim
)
5431 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
5433 memcpy(&addpath_id
, pnt
, BGP_ADDPATH_ID_LEN
);
5434 addpath_id
= ntohl(addpath_id
);
5435 pnt
+= BGP_ADDPATH_ID_LEN
;
5438 /* Fetch prefix length. */
5439 p
.prefixlen
= *pnt
++;
5440 /* afi/safi validity already verified by caller,
5441 * bgp_update_receive */
5442 p
.family
= afi2family(afi
);
5444 /* Prefix length check. */
5445 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
5448 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
5449 peer
->host
, p
.prefixlen
, packet
->afi
);
5450 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH
;
5453 /* Packet size overflow check. */
5454 psize
= PSIZE(p
.prefixlen
);
5456 /* When packet overflow occur return immediately. */
5457 if (pnt
+ psize
> lim
) {
5460 "%s [Error] Update packet error (prefix length %d overflows packet)",
5461 peer
->host
, p
.prefixlen
);
5462 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
5465 /* Defensive coding, double-check the psize fits in a struct
5467 if (psize
> (ssize_t
)sizeof(p
.u
)) {
5470 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
5471 peer
->host
, p
.prefixlen
, sizeof(p
.u
));
5472 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
5475 /* Fetch prefix from NLRI packet. */
5476 memcpy(p
.u
.val
, pnt
, psize
);
5478 /* Check address. */
5479 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
5480 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
5481 /* From RFC4271 Section 6.3:
5483 * If a prefix in the NLRI field is semantically
5485 * (e.g., an unexpected multicast IP address),
5487 * be logged locally, and the prefix SHOULD be
5492 "%s: IPv4 unicast NLRI is multicast address %pI4, ignoring",
5493 peer
->host
, &p
.u
.prefix4
);
5498 /* Check address. */
5499 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
5500 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
5503 "%s: IPv6 unicast NLRI is link-local address %pI6, ignoring",
5504 peer
->host
, &p
.u
.prefix6
);
5508 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
5511 "%s: IPv6 unicast NLRI is multicast address %pI6, ignoring",
5512 peer
->host
, &p
.u
.prefix6
);
5518 /* Normal process. */
5520 ret
= bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
5521 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
5522 NULL
, NULL
, 0, 0, NULL
);
5524 ret
= bgp_withdraw(peer
, &p
, addpath_id
, attr
, afi
,
5525 safi
, ZEBRA_ROUTE_BGP
,
5526 BGP_ROUTE_NORMAL
, NULL
, NULL
, 0,
5529 /* Do not send BGP notification twice when maximum-prefix count
5531 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
))
5532 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW
;
5534 /* Address family configuration mismatch. */
5536 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY
;
5539 /* Packet length consistency check. */
5543 "%s [Error] Update packet error (prefix length mismatch with total length)",
5545 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
5548 return BGP_NLRI_PARSE_OK
;
5551 static struct bgp_static
*bgp_static_new(void)
5553 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
5556 static void bgp_static_free(struct bgp_static
*bgp_static
)
5558 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
5559 route_map_counter_decrement(bgp_static
->rmap
.map
);
5561 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
5562 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
5565 void bgp_static_update(struct bgp
*bgp
, const struct prefix
*p
,
5566 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
5568 struct bgp_dest
*dest
;
5569 struct bgp_path_info
*pi
;
5570 struct bgp_path_info
*new;
5571 struct bgp_path_info rmap_path
;
5573 struct attr
*attr_new
;
5574 route_map_result_t ret
;
5575 #ifdef ENABLE_BGP_VNC
5576 int vnc_implicit_withdraw
= 0;
5581 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
5583 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
5585 attr
.nexthop
= bgp_static
->igpnexthop
;
5586 attr
.med
= bgp_static
->igpmetric
;
5587 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
5589 if (bgp_static
->atomic
)
5590 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
5592 /* Store label index, if required. */
5593 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
5594 attr
.label_index
= bgp_static
->label_index
;
5595 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
5598 /* Apply route-map. */
5599 if (bgp_static
->rmap
.name
) {
5600 struct attr attr_tmp
= attr
;
5602 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
5603 rmap_path
.peer
= bgp
->peer_self
;
5604 rmap_path
.attr
= &attr_tmp
;
5606 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
5608 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, &rmap_path
);
5610 bgp
->peer_self
->rmap_type
= 0;
5612 if (ret
== RMAP_DENYMATCH
) {
5613 /* Free uninterned attribute. */
5614 bgp_attr_flush(&attr_tmp
);
5616 /* Unintern original. */
5617 aspath_unintern(&attr
.aspath
);
5618 bgp_static_withdraw(bgp
, p
, afi
, safi
);
5622 if (bgp_in_graceful_shutdown(bgp
))
5623 bgp_attr_add_gshut_community(&attr_tmp
);
5625 attr_new
= bgp_attr_intern(&attr_tmp
);
5628 if (bgp_in_graceful_shutdown(bgp
))
5629 bgp_attr_add_gshut_community(&attr
);
5631 attr_new
= bgp_attr_intern(&attr
);
5634 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
5635 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5636 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5640 if (attrhash_cmp(pi
->attr
, attr_new
)
5641 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
5642 && !CHECK_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
5643 bgp_dest_unlock_node(dest
);
5644 bgp_attr_unintern(&attr_new
);
5645 aspath_unintern(&attr
.aspath
);
5648 /* The attribute is changed. */
5649 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
5651 /* Rewrite BGP route information. */
5652 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
5653 bgp_path_info_restore(dest
, pi
);
5655 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
5656 #ifdef ENABLE_BGP_VNC
5657 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
5658 && (safi
== SAFI_UNICAST
)) {
5659 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
5661 * Implicit withdraw case.
5662 * We have to do this before pi is
5665 ++vnc_implicit_withdraw
;
5666 vnc_import_bgp_del_route(bgp
, p
, pi
);
5667 vnc_import_bgp_exterior_del_route(
5672 bgp_attr_unintern(&pi
->attr
);
5673 pi
->attr
= attr_new
;
5674 pi
->uptime
= bgp_clock();
5675 #ifdef ENABLE_BGP_VNC
5676 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
5677 && (safi
== SAFI_UNICAST
)) {
5678 if (vnc_implicit_withdraw
) {
5679 vnc_import_bgp_add_route(bgp
, p
, pi
);
5680 vnc_import_bgp_exterior_add_route(
5686 /* Nexthop reachability check. */
5687 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
)
5688 && (safi
== SAFI_UNICAST
5689 || safi
== SAFI_LABELED_UNICAST
)) {
5691 struct bgp
*bgp_nexthop
= bgp
;
5693 if (pi
->extra
&& pi
->extra
->bgp_orig
)
5694 bgp_nexthop
= pi
->extra
->bgp_orig
;
5696 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
,
5697 afi
, safi
, pi
, NULL
,
5699 bgp_path_info_set_flag(dest
, pi
,
5702 if (BGP_DEBUG(nht
, NHT
)) {
5703 char buf1
[INET6_ADDRSTRLEN
];
5704 inet_ntop(p
->family
,
5708 "%s(%s): Route not in table, not advertising",
5711 bgp_path_info_unset_flag(
5712 dest
, pi
, BGP_PATH_VALID
);
5715 /* Delete the NHT structure if any, if we're
5717 * enabling/disabling import check. We
5718 * deregister the route
5719 * from NHT to avoid overloading NHT and the
5720 * process interaction
5722 bgp_unlink_nexthop(pi
);
5723 bgp_path_info_set_flag(dest
, pi
,
5726 /* Process change. */
5727 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
5728 bgp_process(bgp
, dest
, afi
, safi
);
5730 if (SAFI_UNICAST
== safi
5731 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
5733 == BGP_INSTANCE_TYPE_DEFAULT
)) {
5734 vpn_leak_from_vrf_update(bgp_get_default(), bgp
,
5738 bgp_dest_unlock_node(dest
);
5739 aspath_unintern(&attr
.aspath
);
5744 /* Make new BGP info. */
5745 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
5747 /* Nexthop reachability check. */
5748 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
)
5749 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
5750 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, safi
, new, NULL
, 0,
5752 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
5754 if (BGP_DEBUG(nht
, NHT
)) {
5755 char buf1
[INET6_ADDRSTRLEN
];
5756 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
5759 "%s(%s): Route not in table, not advertising",
5762 bgp_path_info_unset_flag(dest
, new, BGP_PATH_VALID
);
5765 /* Delete the NHT structure if any, if we're toggling between
5766 * enabling/disabling import check. We deregister the route
5767 * from NHT to avoid overloading NHT and the process interaction
5769 bgp_unlink_nexthop(new);
5771 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
5774 /* Aggregate address increment. */
5775 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
5777 /* Register new BGP information. */
5778 bgp_path_info_add(dest
, new);
5780 /* route_node_get lock */
5781 bgp_dest_unlock_node(dest
);
5783 /* Process change. */
5784 bgp_process(bgp
, dest
, afi
, safi
);
5786 if (SAFI_UNICAST
== safi
5787 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
5788 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
5789 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
5792 /* Unintern original. */
5793 aspath_unintern(&attr
.aspath
);
5796 void bgp_static_withdraw(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
5799 struct bgp_dest
*dest
;
5800 struct bgp_path_info
*pi
;
5802 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
5804 /* Check selected route and self inserted route. */
5805 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
5806 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5807 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5810 /* Withdraw static BGP route from routing table. */
5812 if (SAFI_UNICAST
== safi
5813 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
5814 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
5815 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
5817 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
5818 bgp_unlink_nexthop(pi
);
5819 bgp_path_info_delete(dest
, pi
);
5820 bgp_process(bgp
, dest
, afi
, safi
);
5823 /* Unlock bgp_node_lookup. */
5824 bgp_dest_unlock_node(dest
);
5828 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
5830 static void bgp_static_withdraw_safi(struct bgp
*bgp
, const struct prefix
*p
,
5831 afi_t afi
, safi_t safi
,
5832 struct prefix_rd
*prd
)
5834 struct bgp_dest
*dest
;
5835 struct bgp_path_info
*pi
;
5837 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
5839 /* Check selected route and self inserted route. */
5840 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
5841 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5842 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5845 /* Withdraw static BGP route from routing table. */
5847 #ifdef ENABLE_BGP_VNC
5848 rfapiProcessWithdraw(
5849 pi
->peer
, NULL
, p
, prd
, pi
->attr
, afi
, safi
, pi
->type
,
5850 1); /* Kill, since it is an administrative change */
5852 if (SAFI_MPLS_VPN
== safi
5853 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5854 vpn_leak_to_vrf_withdraw(bgp
, pi
);
5856 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
5857 bgp_path_info_delete(dest
, pi
);
5858 bgp_process(bgp
, dest
, afi
, safi
);
5861 /* Unlock bgp_node_lookup. */
5862 bgp_dest_unlock_node(dest
);
5865 static void bgp_static_update_safi(struct bgp
*bgp
, const struct prefix
*p
,
5866 struct bgp_static
*bgp_static
, afi_t afi
,
5869 struct bgp_dest
*dest
;
5870 struct bgp_path_info
*new;
5871 struct attr
*attr_new
;
5872 struct attr attr
= {0};
5873 struct bgp_path_info
*pi
;
5874 #ifdef ENABLE_BGP_VNC
5875 mpls_label_t label
= 0;
5877 uint32_t num_labels
= 0;
5882 if (bgp_static
->label
!= MPLS_INVALID_LABEL
)
5884 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
5887 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
5889 attr
.nexthop
= bgp_static
->igpnexthop
;
5890 attr
.med
= bgp_static
->igpmetric
;
5891 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
5893 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
5894 || (safi
== SAFI_ENCAP
)) {
5895 if (afi
== AFI_IP
) {
5896 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
5897 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
5900 if (afi
== AFI_L2VPN
) {
5901 if (bgp_static
->gatewayIp
.family
== AF_INET
)
5903 bgp_static
->gatewayIp
.u
.prefix4
.s_addr
;
5904 else if (bgp_static
->gatewayIp
.family
== AF_INET6
)
5905 memcpy(&(add
.ipv6
), &(bgp_static
->gatewayIp
.u
.prefix6
),
5906 sizeof(struct in6_addr
));
5907 memcpy(&attr
.esi
, bgp_static
->eth_s_id
, sizeof(esi_t
));
5908 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
5909 struct bgp_encap_type_vxlan bet
;
5910 memset(&bet
, 0, sizeof(struct bgp_encap_type_vxlan
));
5911 bet
.vnid
= p
->u
.prefix_evpn
.prefix_addr
.eth_tag
;
5912 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
5914 if (bgp_static
->router_mac
) {
5915 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
5918 /* Apply route-map. */
5919 if (bgp_static
->rmap
.name
) {
5920 struct attr attr_tmp
= attr
;
5921 struct bgp_path_info rmap_path
;
5922 route_map_result_t ret
;
5924 rmap_path
.peer
= bgp
->peer_self
;
5925 rmap_path
.attr
= &attr_tmp
;
5927 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
5929 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, &rmap_path
);
5931 bgp
->peer_self
->rmap_type
= 0;
5933 if (ret
== RMAP_DENYMATCH
) {
5934 /* Free uninterned attribute. */
5935 bgp_attr_flush(&attr_tmp
);
5937 /* Unintern original. */
5938 aspath_unintern(&attr
.aspath
);
5939 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
5944 attr_new
= bgp_attr_intern(&attr_tmp
);
5946 attr_new
= bgp_attr_intern(&attr
);
5949 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
5950 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5951 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5955 memset(&add
, 0, sizeof(union gw_addr
));
5956 if (attrhash_cmp(pi
->attr
, attr_new
)
5957 && overlay_index_equal(afi
, pi
, &add
)
5958 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
5959 bgp_dest_unlock_node(dest
);
5960 bgp_attr_unintern(&attr_new
);
5961 aspath_unintern(&attr
.aspath
);
5964 /* The attribute is changed. */
5965 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
5967 /* Rewrite BGP route information. */
5968 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
5969 bgp_path_info_restore(dest
, pi
);
5971 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
5972 bgp_attr_unintern(&pi
->attr
);
5973 pi
->attr
= attr_new
;
5974 pi
->uptime
= bgp_clock();
5975 #ifdef ENABLE_BGP_VNC
5977 label
= decode_label(&pi
->extra
->label
[0]);
5980 /* Process change. */
5981 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
5982 bgp_process(bgp
, dest
, afi
, safi
);
5984 if (SAFI_MPLS_VPN
== safi
5985 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5986 vpn_leak_to_vrf_update(bgp
, pi
);
5988 #ifdef ENABLE_BGP_VNC
5989 rfapiProcessUpdate(pi
->peer
, NULL
, p
, &bgp_static
->prd
,
5990 pi
->attr
, afi
, safi
, pi
->type
,
5991 pi
->sub_type
, &label
);
5993 bgp_dest_unlock_node(dest
);
5994 aspath_unintern(&attr
.aspath
);
6000 /* Make new BGP info. */
6001 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
6003 SET_FLAG(new->flags
, BGP_PATH_VALID
);
6004 new->extra
= bgp_path_info_extra_new();
6006 new->extra
->label
[0] = bgp_static
->label
;
6007 new->extra
->num_labels
= num_labels
;
6009 #ifdef ENABLE_BGP_VNC
6010 label
= decode_label(&bgp_static
->label
);
6013 /* Aggregate address increment. */
6014 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
6016 /* Register new BGP information. */
6017 bgp_path_info_add(dest
, new);
6018 /* route_node_get lock */
6019 bgp_dest_unlock_node(dest
);
6021 /* Process change. */
6022 bgp_process(bgp
, dest
, afi
, safi
);
6024 if (SAFI_MPLS_VPN
== safi
6025 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
6026 vpn_leak_to_vrf_update(bgp
, new);
6028 #ifdef ENABLE_BGP_VNC
6029 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
6030 safi
, new->type
, new->sub_type
, &label
);
6033 /* Unintern original. */
6034 aspath_unintern(&attr
.aspath
);
6037 /* Configure static BGP network. When user don't run zebra, static
6038 route should be installed as valid. */
6039 static int bgp_static_set(struct vty
*vty
, const char *negate
,
6040 const char *ip_str
, afi_t afi
, safi_t safi
,
6041 const char *rmap
, int backdoor
, uint32_t label_index
)
6043 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6046 struct bgp_static
*bgp_static
;
6047 struct bgp_dest
*dest
;
6048 uint8_t need_update
= 0;
6050 /* Convert IP prefix string to struct prefix. */
6051 ret
= str2prefix(ip_str
, &p
);
6053 vty_out(vty
, "%% Malformed prefix\n");
6054 return CMD_WARNING_CONFIG_FAILED
;
6056 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
6057 vty_out(vty
, "%% Malformed prefix (link-local address)\n");
6058 return CMD_WARNING_CONFIG_FAILED
;
6065 /* Set BGP static route configuration. */
6066 dest
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
6069 vty_out(vty
, "%% Can't find static route specified\n");
6070 return CMD_WARNING_CONFIG_FAILED
;
6073 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6075 if ((label_index
!= BGP_INVALID_LABEL_INDEX
)
6076 && (label_index
!= bgp_static
->label_index
)) {
6078 "%% label-index doesn't match static route\n");
6079 bgp_dest_unlock_node(dest
);
6080 return CMD_WARNING_CONFIG_FAILED
;
6083 if ((rmap
&& bgp_static
->rmap
.name
)
6084 && strcmp(rmap
, bgp_static
->rmap
.name
)) {
6086 "%% route-map name doesn't match static route\n");
6087 bgp_dest_unlock_node(dest
);
6088 return CMD_WARNING_CONFIG_FAILED
;
6091 /* Update BGP RIB. */
6092 if (!bgp_static
->backdoor
)
6093 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
6095 /* Clear configuration. */
6096 bgp_static_free(bgp_static
);
6097 bgp_dest_set_bgp_static_info(dest
, NULL
);
6098 bgp_dest_unlock_node(dest
);
6099 bgp_dest_unlock_node(dest
);
6102 /* Set BGP static route configuration. */
6103 dest
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
6104 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6106 /* Configuration change. */
6107 /* Label index cannot be changed. */
6108 if (bgp_static
->label_index
!= label_index
) {
6109 vty_out(vty
, "%% cannot change label-index\n");
6110 return CMD_WARNING_CONFIG_FAILED
;
6113 /* Check previous routes are installed into BGP. */
6114 if (bgp_static
->valid
6115 && bgp_static
->backdoor
!= backdoor
)
6118 bgp_static
->backdoor
= backdoor
;
6121 XFREE(MTYPE_ROUTE_MAP_NAME
,
6122 bgp_static
->rmap
.name
);
6123 route_map_counter_decrement(
6124 bgp_static
->rmap
.map
);
6125 bgp_static
->rmap
.name
=
6126 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
6127 bgp_static
->rmap
.map
=
6128 route_map_lookup_by_name(rmap
);
6129 route_map_counter_increment(
6130 bgp_static
->rmap
.map
);
6132 XFREE(MTYPE_ROUTE_MAP_NAME
,
6133 bgp_static
->rmap
.name
);
6134 route_map_counter_decrement(
6135 bgp_static
->rmap
.map
);
6136 bgp_static
->rmap
.map
= NULL
;
6137 bgp_static
->valid
= 0;
6139 bgp_dest_unlock_node(dest
);
6141 /* New configuration. */
6142 bgp_static
= bgp_static_new();
6143 bgp_static
->backdoor
= backdoor
;
6144 bgp_static
->valid
= 0;
6145 bgp_static
->igpmetric
= 0;
6146 bgp_static
->igpnexthop
.s_addr
= INADDR_ANY
;
6147 bgp_static
->label_index
= label_index
;
6150 XFREE(MTYPE_ROUTE_MAP_NAME
,
6151 bgp_static
->rmap
.name
);
6152 route_map_counter_decrement(
6153 bgp_static
->rmap
.map
);
6154 bgp_static
->rmap
.name
=
6155 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
6156 bgp_static
->rmap
.map
=
6157 route_map_lookup_by_name(rmap
);
6158 route_map_counter_increment(
6159 bgp_static
->rmap
.map
);
6161 bgp_dest_set_bgp_static_info(dest
, bgp_static
);
6164 bgp_static
->valid
= 1;
6166 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
6168 if (!bgp_static
->backdoor
)
6169 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
6175 void bgp_static_add(struct bgp
*bgp
)
6179 struct bgp_dest
*dest
;
6180 struct bgp_dest
*rm
;
6181 struct bgp_table
*table
;
6182 struct bgp_static
*bgp_static
;
6184 SET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6185 FOREACH_AFI_SAFI (afi
, safi
)
6186 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
6187 dest
= bgp_route_next(dest
)) {
6188 if (!bgp_dest_has_bgp_path_info_data(dest
))
6191 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
6192 || (safi
== SAFI_EVPN
)) {
6193 table
= bgp_dest_get_bgp_table_info(dest
);
6195 for (rm
= bgp_table_top(table
); rm
;
6196 rm
= bgp_route_next(rm
)) {
6198 bgp_dest_get_bgp_static_info(
6200 bgp_static_update_safi(
6201 bgp
, bgp_dest_get_prefix(rm
),
6202 bgp_static
, afi
, safi
);
6206 bgp
, bgp_dest_get_prefix(dest
),
6207 bgp_dest_get_bgp_static_info(dest
), afi
,
6211 UNSET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6214 /* Called from bgp_delete(). Delete all static routes from the BGP
6216 void bgp_static_delete(struct bgp
*bgp
)
6220 struct bgp_dest
*dest
;
6221 struct bgp_dest
*rm
;
6222 struct bgp_table
*table
;
6223 struct bgp_static
*bgp_static
;
6225 FOREACH_AFI_SAFI (afi
, safi
)
6226 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
6227 dest
= bgp_route_next(dest
)) {
6228 if (!bgp_dest_has_bgp_path_info_data(dest
))
6231 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
6232 || (safi
== SAFI_EVPN
)) {
6233 table
= bgp_dest_get_bgp_table_info(dest
);
6235 for (rm
= bgp_table_top(table
); rm
;
6236 rm
= bgp_route_next(rm
)) {
6238 bgp_dest_get_bgp_static_info(
6243 bgp_static_withdraw_safi(
6244 bgp
, bgp_dest_get_prefix(rm
),
6246 (struct prefix_rd
*)
6247 bgp_dest_get_prefix(
6249 bgp_static_free(bgp_static
);
6250 bgp_dest_set_bgp_static_info(rm
,
6252 bgp_dest_unlock_node(rm
);
6255 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6256 bgp_static_withdraw(bgp
,
6257 bgp_dest_get_prefix(dest
),
6259 bgp_static_free(bgp_static
);
6260 bgp_dest_set_bgp_static_info(dest
, NULL
);
6261 bgp_dest_unlock_node(dest
);
6266 void bgp_static_redo_import_check(struct bgp
*bgp
)
6270 struct bgp_dest
*dest
;
6271 struct bgp_dest
*rm
;
6272 struct bgp_table
*table
;
6273 struct bgp_static
*bgp_static
;
6275 /* Use this flag to force reprocessing of the route */
6276 SET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6277 FOREACH_AFI_SAFI (afi
, safi
) {
6278 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
6279 dest
= bgp_route_next(dest
)) {
6280 if (!bgp_dest_has_bgp_path_info_data(dest
))
6283 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
6284 || (safi
== SAFI_EVPN
)) {
6285 table
= bgp_dest_get_bgp_table_info(dest
);
6287 for (rm
= bgp_table_top(table
); rm
;
6288 rm
= bgp_route_next(rm
)) {
6290 bgp_dest_get_bgp_static_info(
6292 bgp_static_update_safi(
6293 bgp
, bgp_dest_get_prefix(rm
),
6294 bgp_static
, afi
, safi
);
6297 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6298 bgp_static_update(bgp
,
6299 bgp_dest_get_prefix(dest
),
6300 bgp_static
, afi
, safi
);
6304 UNSET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6307 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
6310 struct bgp_table
*table
;
6311 struct bgp_dest
*dest
;
6312 struct bgp_path_info
*pi
;
6314 /* Do not install the aggregate route if BGP is in the
6315 * process of termination.
6317 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
6318 || (bgp
->peer_self
== NULL
))
6321 table
= bgp
->rib
[afi
][safi
];
6322 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
6323 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
6324 if (pi
->peer
== bgp
->peer_self
6325 && ((pi
->type
== ZEBRA_ROUTE_BGP
6326 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6327 || (pi
->type
!= ZEBRA_ROUTE_BGP
6329 == BGP_ROUTE_REDISTRIBUTE
))) {
6330 bgp_aggregate_decrement(
6331 bgp
, bgp_dest_get_prefix(dest
), pi
, afi
,
6333 bgp_unlink_nexthop(pi
);
6334 bgp_path_info_delete(dest
, pi
);
6335 bgp_process(bgp
, dest
, afi
, safi
);
6342 * Purge all networks and redistributed routes from routing table.
6343 * Invoked upon the instance going down.
6345 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
6350 FOREACH_AFI_SAFI (afi
, safi
)
6351 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
6356 * Currently this is used to set static routes for VPN and ENCAP.
6357 * I think it can probably be factored with bgp_static_set.
6359 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
6360 const char *ip_str
, const char *rd_str
,
6361 const char *label_str
, const char *rmap_str
,
6362 int evpn_type
, const char *esi
, const char *gwip
,
6363 const char *ethtag
, const char *routermac
)
6365 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6368 struct prefix_rd prd
;
6369 struct bgp_dest
*pdest
;
6370 struct bgp_dest
*dest
;
6371 struct bgp_table
*table
;
6372 struct bgp_static
*bgp_static
;
6373 mpls_label_t label
= MPLS_INVALID_LABEL
;
6374 struct prefix gw_ip
;
6376 /* validate ip prefix */
6377 ret
= str2prefix(ip_str
, &p
);
6379 vty_out(vty
, "%% Malformed prefix\n");
6380 return CMD_WARNING_CONFIG_FAILED
;
6383 if ((afi
== AFI_L2VPN
)
6384 && (bgp_build_evpn_prefix(evpn_type
,
6385 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
6386 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
6387 return CMD_WARNING_CONFIG_FAILED
;
6390 ret
= str2prefix_rd(rd_str
, &prd
);
6392 vty_out(vty
, "%% Malformed rd\n");
6393 return CMD_WARNING_CONFIG_FAILED
;
6397 unsigned long label_val
;
6398 label_val
= strtoul(label_str
, NULL
, 10);
6399 encode_label(label_val
, &label
);
6402 if (safi
== SAFI_EVPN
) {
6403 if (esi
&& str2esi(esi
, NULL
) == 0) {
6404 vty_out(vty
, "%% Malformed ESI\n");
6405 return CMD_WARNING_CONFIG_FAILED
;
6407 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
6408 vty_out(vty
, "%% Malformed Router MAC\n");
6409 return CMD_WARNING_CONFIG_FAILED
;
6412 memset(&gw_ip
, 0, sizeof(struct prefix
));
6413 ret
= str2prefix(gwip
, &gw_ip
);
6415 vty_out(vty
, "%% Malformed GatewayIp\n");
6416 return CMD_WARNING_CONFIG_FAILED
;
6418 if ((gw_ip
.family
== AF_INET
6419 && is_evpn_prefix_ipaddr_v6(
6420 (struct prefix_evpn
*)&p
))
6421 || (gw_ip
.family
== AF_INET6
6422 && is_evpn_prefix_ipaddr_v4(
6423 (struct prefix_evpn
*)&p
))) {
6425 "%% GatewayIp family differs with IP prefix\n");
6426 return CMD_WARNING_CONFIG_FAILED
;
6430 pdest
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
6431 if (!bgp_dest_has_bgp_path_info_data(pdest
))
6432 bgp_dest_set_bgp_table_info(pdest
,
6433 bgp_table_init(bgp
, afi
, safi
));
6434 table
= bgp_dest_get_bgp_table_info(pdest
);
6436 dest
= bgp_node_get(table
, &p
);
6438 if (bgp_dest_has_bgp_path_info_data(dest
)) {
6439 vty_out(vty
, "%% Same network configuration exists\n");
6440 bgp_dest_unlock_node(dest
);
6442 /* New configuration. */
6443 bgp_static
= bgp_static_new();
6444 bgp_static
->backdoor
= 0;
6445 bgp_static
->valid
= 0;
6446 bgp_static
->igpmetric
= 0;
6447 bgp_static
->igpnexthop
.s_addr
= INADDR_ANY
;
6448 bgp_static
->label
= label
;
6449 bgp_static
->prd
= prd
;
6452 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
6453 route_map_counter_decrement(bgp_static
->rmap
.map
);
6454 bgp_static
->rmap
.name
=
6455 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
6456 bgp_static
->rmap
.map
=
6457 route_map_lookup_by_name(rmap_str
);
6458 route_map_counter_increment(bgp_static
->rmap
.map
);
6461 if (safi
== SAFI_EVPN
) {
6463 bgp_static
->eth_s_id
=
6466 str2esi(esi
, bgp_static
->eth_s_id
);
6469 bgp_static
->router_mac
=
6470 XCALLOC(MTYPE_ATTR
, ETH_ALEN
+ 1);
6471 (void)prefix_str2mac(routermac
,
6472 bgp_static
->router_mac
);
6475 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
6477 bgp_dest_set_bgp_static_info(dest
, bgp_static
);
6479 bgp_static
->valid
= 1;
6480 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
6486 /* Configure static BGP network. */
6487 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
6488 const char *ip_str
, const char *rd_str
,
6489 const char *label_str
, int evpn_type
, const char *esi
,
6490 const char *gwip
, const char *ethtag
)
6492 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6495 struct prefix_rd prd
;
6496 struct bgp_dest
*pdest
;
6497 struct bgp_dest
*dest
;
6498 struct bgp_table
*table
;
6499 struct bgp_static
*bgp_static
;
6500 mpls_label_t label
= MPLS_INVALID_LABEL
;
6502 /* Convert IP prefix string to struct prefix. */
6503 ret
= str2prefix(ip_str
, &p
);
6505 vty_out(vty
, "%% Malformed prefix\n");
6506 return CMD_WARNING_CONFIG_FAILED
;
6509 if ((afi
== AFI_L2VPN
)
6510 && (bgp_build_evpn_prefix(evpn_type
,
6511 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
6512 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
6513 return CMD_WARNING_CONFIG_FAILED
;
6515 ret
= str2prefix_rd(rd_str
, &prd
);
6517 vty_out(vty
, "%% Malformed rd\n");
6518 return CMD_WARNING_CONFIG_FAILED
;
6522 unsigned long label_val
;
6523 label_val
= strtoul(label_str
, NULL
, 10);
6524 encode_label(label_val
, &label
);
6527 pdest
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
6528 if (!bgp_dest_has_bgp_path_info_data(pdest
))
6529 bgp_dest_set_bgp_table_info(pdest
,
6530 bgp_table_init(bgp
, afi
, safi
));
6532 bgp_dest_unlock_node(pdest
);
6533 table
= bgp_dest_get_bgp_table_info(pdest
);
6535 dest
= bgp_node_lookup(table
, &p
);
6538 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
6540 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6541 bgp_static_free(bgp_static
);
6542 bgp_dest_set_bgp_static_info(dest
, NULL
);
6543 bgp_dest_unlock_node(dest
);
6544 bgp_dest_unlock_node(dest
);
6546 vty_out(vty
, "%% Can't find the route\n");
6551 static int bgp_table_map_set(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
];
6559 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
6560 route_map_counter_decrement(rmap
->map
);
6561 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
6562 rmap
->map
= route_map_lookup_by_name(rmap_name
);
6563 route_map_counter_increment(rmap
->map
);
6565 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
6566 route_map_counter_decrement(rmap
->map
);
6570 if (bgp_fibupd_safi(safi
))
6571 bgp_zebra_announce_table(bgp
, afi
, safi
);
6576 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
6577 const char *rmap_name
)
6579 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6580 struct bgp_rmap
*rmap
;
6582 rmap
= &bgp
->table_map
[afi
][safi
];
6583 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
6584 route_map_counter_decrement(rmap
->map
);
6587 if (bgp_fibupd_safi(safi
))
6588 bgp_zebra_announce_table(bgp
, afi
, safi
);
6593 void bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
6596 if (bgp
->table_map
[afi
][safi
].name
) {
6597 vty_out(vty
, " table-map %s\n",
6598 bgp
->table_map
[afi
][safi
].name
);
6602 DEFUN (bgp_table_map
,
6605 "BGP table to RIB route download filter\n"
6606 "Name of the route map\n")
6609 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
6610 argv
[idx_word
]->arg
);
6612 DEFUN (no_bgp_table_map
,
6613 no_bgp_table_map_cmd
,
6614 "no table-map WORD",
6616 "BGP table to RIB route download filter\n"
6617 "Name of the route map\n")
6620 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
6621 argv
[idx_word
]->arg
);
6627 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
6628 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
6629 backdoor$backdoor}]",
6631 "Specify a network to announce via BGP\n"
6636 "Route-map to modify the attributes\n"
6637 "Name of the route map\n"
6638 "Label index to associate with the prefix\n"
6639 "Label index value\n"
6640 "Specify a BGP backdoor route\n")
6642 char addr_prefix_str
[BUFSIZ
];
6647 ret
= netmask_str2prefix_str(address_str
, netmask_str
,
6649 sizeof(addr_prefix_str
));
6651 vty_out(vty
, "%% Inconsistent address and mask\n");
6652 return CMD_WARNING_CONFIG_FAILED
;
6656 return bgp_static_set(
6657 vty
, no
, address_str
? addr_prefix_str
: prefix_str
, AFI_IP
,
6658 bgp_node_safi(vty
), map_name
, backdoor
? 1 : 0,
6659 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
6662 DEFPY(ipv6_bgp_network
,
6663 ipv6_bgp_network_cmd
,
6664 "[no] network X:X::X:X/M$prefix \
6665 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
6667 "Specify a network to announce via BGP\n"
6669 "Route-map to modify the attributes\n"
6670 "Name of the route map\n"
6671 "Label index to associate with the prefix\n"
6672 "Label index value\n")
6674 return bgp_static_set(
6675 vty
, no
, prefix_str
, AFI_IP6
, bgp_node_safi(vty
), map_name
, 0,
6676 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
6679 static struct bgp_aggregate
*bgp_aggregate_new(void)
6681 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
6684 static void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
6686 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->suppress_map_name
);
6687 route_map_counter_decrement(aggregate
->suppress_map
);
6688 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
6689 route_map_counter_decrement(aggregate
->rmap
.map
);
6690 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
6694 * Helper function to avoid repeated code: prepare variables for a
6695 * `route_map_apply` call.
6697 * \returns `true` on route map match, otherwise `false`.
6699 static bool aggr_suppress_map_test(struct bgp
*bgp
,
6700 struct bgp_aggregate
*aggregate
,
6701 struct bgp_path_info
*pi
)
6703 const struct prefix
*p
= bgp_dest_get_prefix(pi
->net
);
6704 route_map_result_t rmr
= RMAP_DENYMATCH
;
6705 struct bgp_path_info rmap_path
= {};
6706 struct attr attr
= {};
6708 /* No route map entries created, just don't match. */
6709 if (aggregate
->suppress_map
== NULL
)
6712 /* Call route map matching and return result. */
6713 attr
.aspath
= aspath_empty();
6714 rmap_path
.peer
= bgp
->peer_self
;
6715 rmap_path
.attr
= &attr
;
6717 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_AGGREGATE
);
6718 rmr
= route_map_apply(aggregate
->suppress_map
, p
, &rmap_path
);
6719 bgp
->peer_self
->rmap_type
= 0;
6721 bgp_attr_flush(&attr
);
6723 return rmr
== RMAP_PERMITMATCH
;
6726 /** Test whether the aggregation has suppressed this path or not. */
6727 static bool aggr_suppress_exists(struct bgp_aggregate
*aggregate
,
6728 struct bgp_path_info
*pi
)
6730 if (pi
->extra
== NULL
|| pi
->extra
->aggr_suppressors
== NULL
)
6733 return listnode_lookup(pi
->extra
->aggr_suppressors
, aggregate
) != NULL
;
6737 * Suppress this path and keep the reference.
6739 * \returns `true` if needs processing otherwise `false`.
6741 static bool aggr_suppress_path(struct bgp_aggregate
*aggregate
,
6742 struct bgp_path_info
*pi
)
6744 struct bgp_path_info_extra
*pie
;
6746 /* Path is already suppressed by this aggregation. */
6747 if (aggr_suppress_exists(aggregate
, pi
))
6750 pie
= bgp_path_info_extra_get(pi
);
6752 /* This is the first suppression, allocate memory and list it. */
6753 if (pie
->aggr_suppressors
== NULL
)
6754 pie
->aggr_suppressors
= list_new();
6756 listnode_add(pie
->aggr_suppressors
, aggregate
);
6758 /* Only mark for processing if suppressed. */
6759 if (listcount(pie
->aggr_suppressors
) == 1) {
6760 if (BGP_DEBUG(update
, UPDATE_OUT
))
6761 zlog_debug("aggregate-address suppressing: %pFX",
6762 bgp_dest_get_prefix(pi
->net
));
6764 bgp_path_info_set_flag(pi
->net
, pi
, BGP_PATH_ATTR_CHANGED
);
6772 * Unsuppress this path and remove the reference.
6774 * \returns `true` if needs processing otherwise `false`.
6776 static bool aggr_unsuppress_path(struct bgp_aggregate
*aggregate
,
6777 struct bgp_path_info
*pi
)
6779 /* Path wasn't suppressed. */
6780 if (!aggr_suppress_exists(aggregate
, pi
))
6783 listnode_delete(pi
->extra
->aggr_suppressors
, aggregate
);
6785 /* Unsuppress and free extra memory if last item. */
6786 if (listcount(pi
->extra
->aggr_suppressors
) == 0) {
6787 if (BGP_DEBUG(update
, UPDATE_OUT
))
6788 zlog_debug("aggregate-address unsuppressing: %pFX",
6789 bgp_dest_get_prefix(pi
->net
));
6791 list_delete(&pi
->extra
->aggr_suppressors
);
6792 bgp_path_info_set_flag(pi
->net
, pi
, BGP_PATH_ATTR_CHANGED
);
6799 static bool bgp_aggregate_info_same(struct bgp_path_info
*pi
, uint8_t origin
,
6800 struct aspath
*aspath
,
6801 struct community
*comm
,
6802 struct ecommunity
*ecomm
,
6803 struct lcommunity
*lcomm
)
6805 static struct aspath
*ae
= NULL
;
6808 ae
= aspath_empty();
6813 if (origin
!= pi
->attr
->origin
)
6816 if (!aspath_cmp(pi
->attr
->aspath
, (aspath
) ? aspath
: ae
))
6819 if (!community_cmp(pi
->attr
->community
, comm
))
6822 if (!ecommunity_cmp(pi
->attr
->ecommunity
, ecomm
))
6825 if (!lcommunity_cmp(pi
->attr
->lcommunity
, lcomm
))
6828 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
6834 static void bgp_aggregate_install(
6835 struct bgp
*bgp
, afi_t afi
, safi_t safi
, const struct prefix
*p
,
6836 uint8_t origin
, struct aspath
*aspath
, struct community
*community
,
6837 struct ecommunity
*ecommunity
, struct lcommunity
*lcommunity
,
6838 uint8_t atomic_aggregate
, struct bgp_aggregate
*aggregate
)
6840 struct bgp_dest
*dest
;
6841 struct bgp_table
*table
;
6842 struct bgp_path_info
*pi
, *orig
, *new;
6845 table
= bgp
->rib
[afi
][safi
];
6847 dest
= bgp_node_get(table
, p
);
6849 for (orig
= pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6850 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6851 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6855 * If we have paths with different MEDs, then don't install
6856 * (or uninstall) the aggregate route.
6858 if (aggregate
->match_med
&& aggregate
->med_mismatched
)
6859 goto uninstall_aggregate_route
;
6861 if (aggregate
->count
> 0) {
6863 * If the aggregate information has not changed
6864 * no need to re-install it again.
6866 if (bgp_aggregate_info_same(orig
, origin
, aspath
, community
,
6867 ecommunity
, lcommunity
)) {
6868 bgp_dest_unlock_node(dest
);
6871 aspath_free(aspath
);
6873 community_free(&community
);
6875 ecommunity_free(&ecommunity
);
6877 lcommunity_free(&lcommunity
);
6883 * Mark the old as unusable
6886 bgp_path_info_delete(dest
, pi
);
6888 attr
= bgp_attr_aggregate_intern(
6889 bgp
, origin
, aspath
, community
, ecommunity
, lcommunity
,
6890 aggregate
, atomic_aggregate
, p
);
6893 bgp_aggregate_delete(bgp
, p
, afi
, safi
, aggregate
);
6894 if (BGP_DEBUG(update_groups
, UPDATE_GROUPS
))
6895 zlog_debug("%s: %pFX null attribute", __func__
,
6900 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0,
6901 bgp
->peer_self
, attr
, dest
);
6903 SET_FLAG(new->flags
, BGP_PATH_VALID
);
6905 bgp_path_info_add(dest
, new);
6906 bgp_process(bgp
, dest
, afi
, safi
);
6908 uninstall_aggregate_route
:
6909 for (pi
= orig
; pi
; pi
= pi
->next
)
6910 if (pi
->peer
== bgp
->peer_self
6911 && pi
->type
== ZEBRA_ROUTE_BGP
6912 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6915 /* Withdraw static BGP route from routing table. */
6917 bgp_path_info_delete(dest
, pi
);
6918 bgp_process(bgp
, dest
, afi
, safi
);
6922 bgp_dest_unlock_node(dest
);
6926 * Check if the current path has different MED than other known paths.
6928 * \returns `true` if the MED matched the others else `false`.
6930 static bool bgp_aggregate_med_match(struct bgp_aggregate
*aggregate
,
6931 struct bgp
*bgp
, struct bgp_path_info
*pi
)
6933 uint32_t cur_med
= bgp_med_value(pi
->attr
, bgp
);
6935 /* This is the first route being analyzed. */
6936 if (!aggregate
->med_initialized
) {
6937 aggregate
->med_initialized
= true;
6938 aggregate
->med_mismatched
= false;
6939 aggregate
->med_matched_value
= cur_med
;
6941 /* Check if routes with different MED showed up. */
6942 if (cur_med
!= aggregate
->med_matched_value
)
6943 aggregate
->med_mismatched
= true;
6946 return !aggregate
->med_mismatched
;
6950 * Initializes and tests all routes in the aggregate address path for MED
6953 * \returns `true` if all MEDs are the same otherwise `false`.
6955 static bool bgp_aggregate_test_all_med(struct bgp_aggregate
*aggregate
,
6956 struct bgp
*bgp
, const struct prefix
*p
,
6957 afi_t afi
, safi_t safi
)
6959 struct bgp_table
*table
= bgp
->rib
[afi
][safi
];
6960 const struct prefix
*dest_p
;
6961 struct bgp_dest
*dest
, *top
;
6962 struct bgp_path_info
*pi
;
6963 bool med_matched
= true;
6965 aggregate
->med_initialized
= false;
6967 top
= bgp_node_get(table
, p
);
6968 for (dest
= bgp_node_get(table
, p
); dest
;
6969 dest
= bgp_route_next_until(dest
, top
)) {
6970 dest_p
= bgp_dest_get_prefix(dest
);
6971 if (dest_p
->prefixlen
<= p
->prefixlen
)
6974 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
6975 if (BGP_PATH_HOLDDOWN(pi
))
6977 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6979 if (!bgp_aggregate_med_match(aggregate
, bgp
, pi
)) {
6980 med_matched
= false;
6987 bgp_dest_unlock_node(top
);
6993 * Toggles the route suppression status for this aggregate address
6996 void bgp_aggregate_toggle_suppressed(struct bgp_aggregate
*aggregate
,
6997 struct bgp
*bgp
, const struct prefix
*p
,
6998 afi_t afi
, safi_t safi
, bool suppress
)
7000 struct bgp_table
*table
= bgp
->rib
[afi
][safi
];
7001 const struct prefix
*dest_p
;
7002 struct bgp_dest
*dest
, *top
;
7003 struct bgp_path_info
*pi
;
7004 bool toggle_suppression
;
7006 /* We've found a different MED we must revert any suppressed routes. */
7007 top
= bgp_node_get(table
, p
);
7008 for (dest
= bgp_node_get(table
, p
); dest
;
7009 dest
= bgp_route_next_until(dest
, top
)) {
7010 dest_p
= bgp_dest_get_prefix(dest
);
7011 if (dest_p
->prefixlen
<= p
->prefixlen
)
7014 toggle_suppression
= false;
7015 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7016 if (BGP_PATH_HOLDDOWN(pi
))
7018 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7021 /* We are toggling suppression back. */
7023 /* Suppress route if not suppressed already. */
7024 if (aggr_suppress_path(aggregate
, pi
))
7025 toggle_suppression
= true;
7029 /* Install route if there is no more suppression. */
7030 if (aggr_unsuppress_path(aggregate
, pi
))
7031 toggle_suppression
= true;
7034 if (toggle_suppression
)
7035 bgp_process(bgp
, dest
, afi
, safi
);
7037 bgp_dest_unlock_node(top
);
7041 * Aggregate address MED matching incremental test: this function is called
7042 * when the initial aggregation occurred and we are only testing a single
7045 * In addition to testing and setting the MED validity it also installs back
7046 * suppressed routes (if summary is configured).
7048 * Must not be called in `bgp_aggregate_route`.
7050 static void bgp_aggregate_med_update(struct bgp_aggregate
*aggregate
,
7051 struct bgp
*bgp
, const struct prefix
*p
,
7052 afi_t afi
, safi_t safi
,
7053 struct bgp_path_info
*pi
, bool is_adding
)
7055 /* MED matching disabled. */
7056 if (!aggregate
->match_med
)
7059 /* Aggregation with different MED, nothing to do. */
7060 if (aggregate
->med_mismatched
)
7064 * Test the current entry:
7066 * is_adding == true: if the new entry doesn't match then we must
7067 * install all suppressed routes.
7069 * is_adding == false: if the entry being removed was the last
7070 * unmatching entry then we can suppress all routes.
7073 if (bgp_aggregate_test_all_med(aggregate
, bgp
, p
, afi
, safi
)
7074 && aggregate
->summary_only
)
7075 bgp_aggregate_toggle_suppressed(aggregate
, bgp
, p
, afi
,
7078 bgp_aggregate_med_match(aggregate
, bgp
, pi
);
7080 /* No mismatches, just quit. */
7081 if (!aggregate
->med_mismatched
)
7084 /* Route summarization is disabled. */
7085 if (!aggregate
->summary_only
)
7088 bgp_aggregate_toggle_suppressed(aggregate
, bgp
, p
, afi
, safi
, false);
7091 /* Update an aggregate as routes are added/removed from the BGP table */
7092 void bgp_aggregate_route(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
7093 safi_t safi
, struct bgp_aggregate
*aggregate
)
7095 struct bgp_table
*table
;
7096 struct bgp_dest
*top
;
7097 struct bgp_dest
*dest
;
7099 struct aspath
*aspath
= NULL
;
7100 struct community
*community
= NULL
;
7101 struct ecommunity
*ecommunity
= NULL
;
7102 struct lcommunity
*lcommunity
= NULL
;
7103 struct bgp_path_info
*pi
;
7104 unsigned long match
= 0;
7105 uint8_t atomic_aggregate
= 0;
7107 /* If the bgp instance is being deleted or self peer is deleted
7108 * then do not create aggregate route
7110 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
7111 || (bgp
->peer_self
== NULL
))
7114 /* Initialize and test routes for MED difference. */
7115 if (aggregate
->match_med
)
7116 bgp_aggregate_test_all_med(aggregate
, bgp
, p
, afi
, safi
);
7119 * Reset aggregate count: we might've been called from route map
7120 * update so in that case we must retest all more specific routes.
7122 * \see `bgp_route_map_process_update`.
7124 aggregate
->count
= 0;
7125 aggregate
->incomplete_origin_count
= 0;
7126 aggregate
->incomplete_origin_count
= 0;
7127 aggregate
->egp_origin_count
= 0;
7129 /* ORIGIN attribute: If at least one route among routes that are
7130 aggregated has ORIGIN with the value INCOMPLETE, then the
7131 aggregated route must have the ORIGIN attribute with the value
7132 INCOMPLETE. Otherwise, if at least one route among routes that
7133 are aggregated has ORIGIN with the value EGP, then the aggregated
7134 route must have the origin attribute with the value EGP. In all
7135 other case the value of the ORIGIN attribute of the aggregated
7136 route is INTERNAL. */
7137 origin
= BGP_ORIGIN_IGP
;
7139 table
= bgp
->rib
[afi
][safi
];
7141 top
= bgp_node_get(table
, p
);
7142 for (dest
= bgp_node_get(table
, p
); dest
;
7143 dest
= bgp_route_next_until(dest
, top
)) {
7144 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
7146 if (dest_p
->prefixlen
<= p
->prefixlen
)
7149 /* If suppress fib is enabled and route not installed
7150 * in FIB, skip the route
7152 if (!bgp_check_advertise(bgp
, dest
))
7157 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7158 if (BGP_PATH_HOLDDOWN(pi
))
7162 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
7163 atomic_aggregate
= 1;
7165 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7169 * summary-only aggregate route suppress
7170 * aggregated route announcements.
7173 * Don't create summaries if MED didn't match
7174 * otherwise neither the specific routes and the
7175 * aggregation will be announced.
7177 if (aggregate
->summary_only
7178 && AGGREGATE_MED_VALID(aggregate
)) {
7179 if (aggr_suppress_path(aggregate
, pi
))
7184 * Suppress more specific routes that match the route
7188 * Don't suppress routes if MED matching is enabled and
7189 * it mismatched otherwise we might end up with no
7190 * routes for this path.
7192 if (aggregate
->suppress_map_name
7193 && AGGREGATE_MED_VALID(aggregate
)
7194 && aggr_suppress_map_test(bgp
, aggregate
, pi
)) {
7195 if (aggr_suppress_path(aggregate
, pi
))
7202 * If at least one route among routes that are
7203 * aggregated has ORIGIN with the value INCOMPLETE,
7204 * then the aggregated route MUST have the ORIGIN
7205 * attribute with the value INCOMPLETE. Otherwise, if
7206 * at least one route among routes that are aggregated
7207 * has ORIGIN with the value EGP, then the aggregated
7208 * route MUST have the ORIGIN attribute with the value
7211 switch (pi
->attr
->origin
) {
7212 case BGP_ORIGIN_INCOMPLETE
:
7213 aggregate
->incomplete_origin_count
++;
7215 case BGP_ORIGIN_EGP
:
7216 aggregate
->egp_origin_count
++;
7224 if (!aggregate
->as_set
)
7228 * as-set aggregate route generate origin, as path,
7229 * and community aggregation.
7231 /* Compute aggregate route's as-path.
7233 bgp_compute_aggregate_aspath_hash(aggregate
,
7236 /* Compute aggregate route's community.
7238 if (pi
->attr
->community
)
7239 bgp_compute_aggregate_community_hash(
7241 pi
->attr
->community
);
7243 /* Compute aggregate route's extended community.
7245 if (pi
->attr
->ecommunity
)
7246 bgp_compute_aggregate_ecommunity_hash(
7248 pi
->attr
->ecommunity
);
7250 /* Compute aggregate route's large community.
7252 if (pi
->attr
->lcommunity
)
7253 bgp_compute_aggregate_lcommunity_hash(
7255 pi
->attr
->lcommunity
);
7258 bgp_process(bgp
, dest
, afi
, safi
);
7260 if (aggregate
->as_set
) {
7261 bgp_compute_aggregate_aspath_val(aggregate
);
7262 bgp_compute_aggregate_community_val(aggregate
);
7263 bgp_compute_aggregate_ecommunity_val(aggregate
);
7264 bgp_compute_aggregate_lcommunity_val(aggregate
);
7268 bgp_dest_unlock_node(top
);
7271 if (aggregate
->incomplete_origin_count
> 0)
7272 origin
= BGP_ORIGIN_INCOMPLETE
;
7273 else if (aggregate
->egp_origin_count
> 0)
7274 origin
= BGP_ORIGIN_EGP
;
7276 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
7277 origin
= aggregate
->origin
;
7279 if (aggregate
->as_set
) {
7280 if (aggregate
->aspath
)
7281 /* Retrieve aggregate route's as-path.
7283 aspath
= aspath_dup(aggregate
->aspath
);
7285 if (aggregate
->community
)
7286 /* Retrieve aggregate route's community.
7288 community
= community_dup(aggregate
->community
);
7290 if (aggregate
->ecommunity
)
7291 /* Retrieve aggregate route's ecommunity.
7293 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
7295 if (aggregate
->lcommunity
)
7296 /* Retrieve aggregate route's lcommunity.
7298 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
7301 bgp_aggregate_install(bgp
, afi
, safi
, p
, origin
, aspath
, community
,
7302 ecommunity
, lcommunity
, atomic_aggregate
,
7306 void bgp_aggregate_delete(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
7307 safi_t safi
, struct bgp_aggregate
*aggregate
)
7309 struct bgp_table
*table
;
7310 struct bgp_dest
*top
;
7311 struct bgp_dest
*dest
;
7312 struct bgp_path_info
*pi
;
7313 unsigned long match
;
7315 table
= bgp
->rib
[afi
][safi
];
7317 /* If routes exists below this node, generate aggregate routes. */
7318 top
= bgp_node_get(table
, p
);
7319 for (dest
= bgp_node_get(table
, p
); dest
;
7320 dest
= bgp_route_next_until(dest
, top
)) {
7321 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
7323 if (dest_p
->prefixlen
<= p
->prefixlen
)
7327 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7328 if (BGP_PATH_HOLDDOWN(pi
))
7331 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7334 if (aggregate
->summary_only
&& pi
->extra
7335 && AGGREGATE_MED_VALID(aggregate
)) {
7336 if (aggr_unsuppress_path(aggregate
, pi
))
7340 if (aggregate
->suppress_map_name
7341 && AGGREGATE_MED_VALID(aggregate
)
7342 && aggr_suppress_map_test(bgp
, aggregate
, pi
)) {
7343 if (aggr_unsuppress_path(aggregate
, pi
))
7349 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
7350 aggregate
->incomplete_origin_count
--;
7351 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
7352 aggregate
->egp_origin_count
--;
7354 if (aggregate
->as_set
) {
7355 /* Remove as-path from aggregate.
7357 bgp_remove_aspath_from_aggregate_hash(
7361 if (pi
->attr
->community
)
7362 /* Remove community from aggregate.
7364 bgp_remove_comm_from_aggregate_hash(
7366 pi
->attr
->community
);
7368 if (pi
->attr
->ecommunity
)
7369 /* Remove ecommunity from aggregate.
7371 bgp_remove_ecomm_from_aggregate_hash(
7373 pi
->attr
->ecommunity
);
7375 if (pi
->attr
->lcommunity
)
7376 /* Remove lcommunity from aggregate.
7378 bgp_remove_lcomm_from_aggregate_hash(
7380 pi
->attr
->lcommunity
);
7384 /* If this node was suppressed, process the change. */
7386 bgp_process(bgp
, dest
, afi
, safi
);
7388 if (aggregate
->as_set
) {
7389 aspath_free(aggregate
->aspath
);
7390 aggregate
->aspath
= NULL
;
7391 if (aggregate
->community
)
7392 community_free(&aggregate
->community
);
7393 if (aggregate
->ecommunity
)
7394 ecommunity_free(&aggregate
->ecommunity
);
7395 if (aggregate
->lcommunity
)
7396 lcommunity_free(&aggregate
->lcommunity
);
7399 bgp_dest_unlock_node(top
);
7402 static void bgp_add_route_to_aggregate(struct bgp
*bgp
,
7403 const struct prefix
*aggr_p
,
7404 struct bgp_path_info
*pinew
, afi_t afi
,
7406 struct bgp_aggregate
*aggregate
)
7409 struct aspath
*aspath
= NULL
;
7410 uint8_t atomic_aggregate
= 0;
7411 struct community
*community
= NULL
;
7412 struct ecommunity
*ecommunity
= NULL
;
7413 struct lcommunity
*lcommunity
= NULL
;
7415 /* If the bgp instance is being deleted or self peer is deleted
7416 * then do not create aggregate route
7418 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
7419 || (bgp
->peer_self
== NULL
))
7422 /* ORIGIN attribute: If at least one route among routes that are
7423 * aggregated has ORIGIN with the value INCOMPLETE, then the
7424 * aggregated route must have the ORIGIN attribute with the value
7425 * INCOMPLETE. Otherwise, if at least one route among routes that
7426 * are aggregated has ORIGIN with the value EGP, then the aggregated
7427 * route must have the origin attribute with the value EGP. In all
7428 * other case the value of the ORIGIN attribute of the aggregated
7429 * route is INTERNAL.
7431 origin
= BGP_ORIGIN_IGP
;
7436 * This must be called before `summary` check to avoid
7437 * "suppressing" twice.
7439 if (aggregate
->match_med
)
7440 bgp_aggregate_med_update(aggregate
, bgp
, aggr_p
, afi
, safi
,
7443 if (aggregate
->summary_only
&& AGGREGATE_MED_VALID(aggregate
))
7444 aggr_suppress_path(aggregate
, pinew
);
7446 if (aggregate
->suppress_map_name
&& AGGREGATE_MED_VALID(aggregate
)
7447 && aggr_suppress_map_test(bgp
, aggregate
, pinew
))
7448 aggr_suppress_path(aggregate
, pinew
);
7450 switch (pinew
->attr
->origin
) {
7451 case BGP_ORIGIN_INCOMPLETE
:
7452 aggregate
->incomplete_origin_count
++;
7454 case BGP_ORIGIN_EGP
:
7455 aggregate
->egp_origin_count
++;
7463 if (aggregate
->incomplete_origin_count
> 0)
7464 origin
= BGP_ORIGIN_INCOMPLETE
;
7465 else if (aggregate
->egp_origin_count
> 0)
7466 origin
= BGP_ORIGIN_EGP
;
7468 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
7469 origin
= aggregate
->origin
;
7471 if (aggregate
->as_set
) {
7472 /* Compute aggregate route's as-path.
7474 bgp_compute_aggregate_aspath(aggregate
,
7475 pinew
->attr
->aspath
);
7477 /* Compute aggregate route's community.
7479 if (pinew
->attr
->community
)
7480 bgp_compute_aggregate_community(
7482 pinew
->attr
->community
);
7484 /* Compute aggregate route's extended community.
7486 if (pinew
->attr
->ecommunity
)
7487 bgp_compute_aggregate_ecommunity(
7489 pinew
->attr
->ecommunity
);
7491 /* Compute aggregate route's large community.
7493 if (pinew
->attr
->lcommunity
)
7494 bgp_compute_aggregate_lcommunity(
7496 pinew
->attr
->lcommunity
);
7498 /* Retrieve aggregate route's as-path.
7500 if (aggregate
->aspath
)
7501 aspath
= aspath_dup(aggregate
->aspath
);
7503 /* Retrieve aggregate route's community.
7505 if (aggregate
->community
)
7506 community
= community_dup(aggregate
->community
);
7508 /* Retrieve aggregate route's ecommunity.
7510 if (aggregate
->ecommunity
)
7511 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
7513 /* Retrieve aggregate route's lcommunity.
7515 if (aggregate
->lcommunity
)
7516 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
7519 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
7520 aspath
, community
, ecommunity
,
7521 lcommunity
, atomic_aggregate
, aggregate
);
7524 static void bgp_remove_route_from_aggregate(struct bgp
*bgp
, afi_t afi
,
7526 struct bgp_path_info
*pi
,
7527 struct bgp_aggregate
*aggregate
,
7528 const struct prefix
*aggr_p
)
7531 struct aspath
*aspath
= NULL
;
7532 uint8_t atomic_aggregate
= 0;
7533 struct community
*community
= NULL
;
7534 struct ecommunity
*ecommunity
= NULL
;
7535 struct lcommunity
*lcommunity
= NULL
;
7536 unsigned long match
= 0;
7538 /* If the bgp instance is being deleted or self peer is deleted
7539 * then do not create aggregate route
7541 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
7542 || (bgp
->peer_self
== NULL
))
7545 if (BGP_PATH_HOLDDOWN(pi
))
7548 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7551 if (aggregate
->summary_only
&& AGGREGATE_MED_VALID(aggregate
))
7552 if (aggr_unsuppress_path(aggregate
, pi
))
7555 if (aggregate
->suppress_map_name
&& AGGREGATE_MED_VALID(aggregate
)
7556 && aggr_suppress_map_test(bgp
, aggregate
, pi
))
7557 if (aggr_unsuppress_path(aggregate
, pi
))
7561 * This must be called after `summary`, `suppress-map` check to avoid
7562 * "unsuppressing" twice.
7564 if (aggregate
->match_med
)
7565 bgp_aggregate_med_update(aggregate
, bgp
, aggr_p
, afi
, safi
, pi
,
7568 if (aggregate
->count
> 0)
7571 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
7572 aggregate
->incomplete_origin_count
--;
7573 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
7574 aggregate
->egp_origin_count
--;
7576 if (aggregate
->as_set
) {
7577 /* Remove as-path from aggregate.
7579 bgp_remove_aspath_from_aggregate(aggregate
,
7582 if (pi
->attr
->community
)
7583 /* Remove community from aggregate.
7585 bgp_remove_community_from_aggregate(
7587 pi
->attr
->community
);
7589 if (pi
->attr
->ecommunity
)
7590 /* Remove ecommunity from aggregate.
7592 bgp_remove_ecommunity_from_aggregate(
7594 pi
->attr
->ecommunity
);
7596 if (pi
->attr
->lcommunity
)
7597 /* Remove lcommunity from aggregate.
7599 bgp_remove_lcommunity_from_aggregate(
7601 pi
->attr
->lcommunity
);
7604 /* If this node was suppressed, process the change. */
7606 bgp_process(bgp
, pi
->net
, afi
, safi
);
7608 origin
= BGP_ORIGIN_IGP
;
7609 if (aggregate
->incomplete_origin_count
> 0)
7610 origin
= BGP_ORIGIN_INCOMPLETE
;
7611 else if (aggregate
->egp_origin_count
> 0)
7612 origin
= BGP_ORIGIN_EGP
;
7614 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
7615 origin
= aggregate
->origin
;
7617 if (aggregate
->as_set
) {
7618 /* Retrieve aggregate route's as-path.
7620 if (aggregate
->aspath
)
7621 aspath
= aspath_dup(aggregate
->aspath
);
7623 /* Retrieve aggregate route's community.
7625 if (aggregate
->community
)
7626 community
= community_dup(aggregate
->community
);
7628 /* Retrieve aggregate route's ecommunity.
7630 if (aggregate
->ecommunity
)
7631 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
7633 /* Retrieve aggregate route's lcommunity.
7635 if (aggregate
->lcommunity
)
7636 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
7639 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
7640 aspath
, community
, ecommunity
,
7641 lcommunity
, atomic_aggregate
, aggregate
);
7644 void bgp_aggregate_increment(struct bgp
*bgp
, const struct prefix
*p
,
7645 struct bgp_path_info
*pi
, afi_t afi
, safi_t safi
)
7647 struct bgp_dest
*child
;
7648 struct bgp_dest
*dest
;
7649 struct bgp_aggregate
*aggregate
;
7650 struct bgp_table
*table
;
7652 table
= bgp
->aggregate
[afi
][safi
];
7654 /* No aggregates configured. */
7655 if (bgp_table_top_nolock(table
) == NULL
)
7658 if (p
->prefixlen
== 0)
7661 if (BGP_PATH_HOLDDOWN(pi
))
7664 /* If suppress fib is enabled and route not installed
7665 * in FIB, do not update the aggregate route
7667 if (!bgp_check_advertise(bgp
, pi
->net
))
7670 child
= bgp_node_get(table
, p
);
7672 /* Aggregate address configuration check. */
7673 for (dest
= child
; dest
; dest
= bgp_dest_parent_nolock(dest
)) {
7674 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
7676 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
7677 if (aggregate
!= NULL
&& dest_p
->prefixlen
< p
->prefixlen
) {
7678 bgp_add_route_to_aggregate(bgp
, dest_p
, pi
, afi
, safi
,
7682 bgp_dest_unlock_node(child
);
7685 void bgp_aggregate_decrement(struct bgp
*bgp
, const struct prefix
*p
,
7686 struct bgp_path_info
*del
, afi_t afi
, safi_t safi
)
7688 struct bgp_dest
*child
;
7689 struct bgp_dest
*dest
;
7690 struct bgp_aggregate
*aggregate
;
7691 struct bgp_table
*table
;
7693 table
= bgp
->aggregate
[afi
][safi
];
7695 /* No aggregates configured. */
7696 if (bgp_table_top_nolock(table
) == NULL
)
7699 if (p
->prefixlen
== 0)
7702 child
= bgp_node_get(table
, p
);
7704 /* Aggregate address configuration check. */
7705 for (dest
= child
; dest
; dest
= bgp_dest_parent_nolock(dest
)) {
7706 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
7708 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
7709 if (aggregate
!= NULL
&& dest_p
->prefixlen
< p
->prefixlen
) {
7710 bgp_remove_route_from_aggregate(bgp
, afi
, safi
, del
,
7714 bgp_dest_unlock_node(child
);
7717 /* Aggregate route attribute. */
7718 #define AGGREGATE_SUMMARY_ONLY 1
7719 #define AGGREGATE_AS_SET 1
7720 #define AGGREGATE_AS_UNSET 0
7722 static const char *bgp_origin2str(uint8_t origin
)
7725 case BGP_ORIGIN_IGP
:
7727 case BGP_ORIGIN_EGP
:
7729 case BGP_ORIGIN_INCOMPLETE
:
7730 return "incomplete";
7735 static const char *bgp_rpki_validation2str(enum rpki_states v_state
)
7738 case RPKI_NOT_BEING_USED
:
7748 assert(!"We should never get here this is a dev escape");
7752 static int bgp_aggregate_unset(struct vty
*vty
, const char *prefix_str
,
7753 afi_t afi
, safi_t safi
)
7755 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
7758 struct bgp_dest
*dest
;
7759 struct bgp_aggregate
*aggregate
;
7761 /* Convert string to prefix structure. */
7762 ret
= str2prefix(prefix_str
, &p
);
7764 vty_out(vty
, "Malformed prefix\n");
7765 return CMD_WARNING_CONFIG_FAILED
;
7769 /* Old configuration check. */
7770 dest
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], &p
);
7773 "%% There is no aggregate-address configuration.\n");
7774 return CMD_WARNING_CONFIG_FAILED
;
7777 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
7778 bgp_aggregate_delete(bgp
, &p
, afi
, safi
, aggregate
);
7779 bgp_aggregate_install(bgp
, afi
, safi
, &p
, 0, NULL
, NULL
,
7780 NULL
, NULL
, 0, aggregate
);
7782 /* Unlock aggregate address configuration. */
7783 bgp_dest_set_bgp_aggregate_info(dest
, NULL
);
7785 if (aggregate
->community
)
7786 community_free(&aggregate
->community
);
7788 if (aggregate
->community_hash
) {
7789 /* Delete all communities in the hash.
7791 hash_clean(aggregate
->community_hash
,
7792 bgp_aggr_community_remove
);
7793 /* Free up the community_hash.
7795 hash_free(aggregate
->community_hash
);
7798 if (aggregate
->ecommunity
)
7799 ecommunity_free(&aggregate
->ecommunity
);
7801 if (aggregate
->ecommunity_hash
) {
7802 /* Delete all ecommunities in the hash.
7804 hash_clean(aggregate
->ecommunity_hash
,
7805 bgp_aggr_ecommunity_remove
);
7806 /* Free up the ecommunity_hash.
7808 hash_free(aggregate
->ecommunity_hash
);
7811 if (aggregate
->lcommunity
)
7812 lcommunity_free(&aggregate
->lcommunity
);
7814 if (aggregate
->lcommunity_hash
) {
7815 /* Delete all lcommunities in the hash.
7817 hash_clean(aggregate
->lcommunity_hash
,
7818 bgp_aggr_lcommunity_remove
);
7819 /* Free up the lcommunity_hash.
7821 hash_free(aggregate
->lcommunity_hash
);
7824 if (aggregate
->aspath
)
7825 aspath_free(aggregate
->aspath
);
7827 if (aggregate
->aspath_hash
) {
7828 /* Delete all as-paths in the hash.
7830 hash_clean(aggregate
->aspath_hash
,
7831 bgp_aggr_aspath_remove
);
7832 /* Free up the aspath_hash.
7834 hash_free(aggregate
->aspath_hash
);
7837 bgp_aggregate_free(aggregate
);
7838 bgp_dest_unlock_node(dest
);
7839 bgp_dest_unlock_node(dest
);
7844 static int bgp_aggregate_set(struct vty
*vty
, const char *prefix_str
, afi_t afi
,
7845 safi_t safi
, const char *rmap
,
7846 uint8_t summary_only
, uint8_t as_set
,
7847 uint8_t origin
, bool match_med
,
7848 const char *suppress_map
)
7850 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
7853 struct bgp_dest
*dest
;
7854 struct bgp_aggregate
*aggregate
;
7855 uint8_t as_set_new
= as_set
;
7857 if (suppress_map
&& summary_only
) {
7859 "'summary-only' and 'suppress-map' can't be used at the same time\n");
7860 return CMD_WARNING_CONFIG_FAILED
;
7863 /* Convert string to prefix structure. */
7864 ret
= str2prefix(prefix_str
, &p
);
7866 vty_out(vty
, "Malformed prefix\n");
7867 return CMD_WARNING_CONFIG_FAILED
;
7871 if ((afi
== AFI_IP
&& p
.prefixlen
== IPV4_MAX_BITLEN
) ||
7872 (afi
== AFI_IP6
&& p
.prefixlen
== IPV6_MAX_BITLEN
)) {
7873 vty_out(vty
, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
7875 return CMD_WARNING_CONFIG_FAILED
;
7878 /* Old configuration check. */
7879 dest
= bgp_node_get(bgp
->aggregate
[afi
][safi
], &p
);
7880 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
7883 vty_out(vty
, "There is already same aggregate network.\n");
7884 /* try to remove the old entry */
7885 ret
= bgp_aggregate_unset(vty
, prefix_str
, afi
, safi
);
7887 vty_out(vty
, "Error deleting aggregate.\n");
7888 bgp_dest_unlock_node(dest
);
7889 return CMD_WARNING_CONFIG_FAILED
;
7893 /* Make aggregate address structure. */
7894 aggregate
= bgp_aggregate_new();
7895 aggregate
->summary_only
= summary_only
;
7896 aggregate
->match_med
= match_med
;
7898 /* Network operators MUST NOT locally generate any new
7899 * announcements containing AS_SET or AS_CONFED_SET. If they have
7900 * announced routes with AS_SET or AS_CONFED_SET in them, then they
7901 * SHOULD withdraw those routes and re-announce routes for the
7902 * aggregate or component prefixes (i.e., the more-specific routes
7903 * subsumed by the previously aggregated route) without AS_SET
7904 * or AS_CONFED_SET in the updates.
7906 if (bgp
->reject_as_sets
) {
7907 if (as_set
== AGGREGATE_AS_SET
) {
7908 as_set_new
= AGGREGATE_AS_UNSET
;
7910 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
7913 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
7917 aggregate
->as_set
= as_set_new
;
7918 aggregate
->safi
= safi
;
7919 /* Override ORIGIN attribute if defined.
7920 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
7921 * to IGP which is not what rfc4271 says.
7922 * This enables the same behavior, optionally.
7924 aggregate
->origin
= origin
;
7927 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
7928 route_map_counter_decrement(aggregate
->rmap
.map
);
7929 aggregate
->rmap
.name
=
7930 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
7931 aggregate
->rmap
.map
= route_map_lookup_by_name(rmap
);
7932 route_map_counter_increment(aggregate
->rmap
.map
);
7936 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->suppress_map_name
);
7937 route_map_counter_decrement(aggregate
->suppress_map
);
7939 aggregate
->suppress_map_name
=
7940 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, suppress_map
);
7941 aggregate
->suppress_map
=
7942 route_map_lookup_by_name(aggregate
->suppress_map_name
);
7943 route_map_counter_increment(aggregate
->suppress_map
);
7946 bgp_dest_set_bgp_aggregate_info(dest
, aggregate
);
7948 /* Aggregate address insert into BGP routing table. */
7949 bgp_aggregate_route(bgp
, &p
, afi
, safi
, aggregate
);
7954 DEFPY(aggregate_addressv4
, aggregate_addressv4_cmd
,
7955 "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> [{"
7957 "|summary-only$summary_only"
7958 "|route-map WORD$rmap_name"
7959 "|origin <egp|igp|incomplete>$origin_s"
7960 "|matching-MED-only$match_med"
7961 "|suppress-map WORD$suppress_map"
7964 "Configure BGP aggregate entries\n"
7965 "Aggregate prefix\n" "Aggregate address\n" "Aggregate mask\n"
7966 "Generate AS set path information\n"
7967 "Filter more specific routes from updates\n"
7968 "Apply route map to aggregate network\n"
7973 "Unknown heritage\n"
7974 "Only aggregate routes with matching MED\n"
7975 "Suppress the selected more specific routes\n"
7976 "Route map with the route selectors\n")
7978 const char *prefix_s
= NULL
;
7979 safi_t safi
= bgp_node_safi(vty
);
7980 uint8_t origin
= BGP_ORIGIN_UNSPECIFIED
;
7981 int as_set
= AGGREGATE_AS_UNSET
;
7982 char prefix_buf
[PREFIX2STR_BUFFER
];
7985 if (netmask_str2prefix_str(addr_str
, mask_str
, prefix_buf
,
7988 vty_out(vty
, "%% Inconsistent address and mask\n");
7989 return CMD_WARNING_CONFIG_FAILED
;
7991 prefix_s
= prefix_buf
;
7993 prefix_s
= prefix_str
;
7996 if (strcmp(origin_s
, "egp") == 0)
7997 origin
= BGP_ORIGIN_EGP
;
7998 else if (strcmp(origin_s
, "igp") == 0)
7999 origin
= BGP_ORIGIN_IGP
;
8000 else if (strcmp(origin_s
, "incomplete") == 0)
8001 origin
= BGP_ORIGIN_INCOMPLETE
;
8005 as_set
= AGGREGATE_AS_SET
;
8007 /* Handle configuration removal, otherwise installation. */
8009 return bgp_aggregate_unset(vty
, prefix_s
, AFI_IP
, safi
);
8011 return bgp_aggregate_set(vty
, prefix_s
, AFI_IP
, safi
, rmap_name
,
8012 summary_only
!= NULL
, as_set
, origin
,
8013 match_med
!= NULL
, suppress_map
);
8016 DEFPY(aggregate_addressv6
, aggregate_addressv6_cmd
,
8017 "[no] aggregate-address X:X::X:X/M$prefix [{"
8019 "|summary-only$summary_only"
8020 "|route-map WORD$rmap_name"
8021 "|origin <egp|igp|incomplete>$origin_s"
8022 "|matching-MED-only$match_med"
8023 "|suppress-map WORD$suppress_map"
8026 "Configure BGP aggregate entries\n"
8027 "Aggregate prefix\n"
8028 "Generate AS set path information\n"
8029 "Filter more specific routes from updates\n"
8030 "Apply route map to aggregate network\n"
8035 "Unknown heritage\n"
8036 "Only aggregate routes with matching MED\n"
8037 "Suppress the selected more specific routes\n"
8038 "Route map with the route selectors\n")
8040 uint8_t origin
= BGP_ORIGIN_UNSPECIFIED
;
8041 int as_set
= AGGREGATE_AS_UNSET
;
8044 if (strcmp(origin_s
, "egp") == 0)
8045 origin
= BGP_ORIGIN_EGP
;
8046 else if (strcmp(origin_s
, "igp") == 0)
8047 origin
= BGP_ORIGIN_IGP
;
8048 else if (strcmp(origin_s
, "incomplete") == 0)
8049 origin
= BGP_ORIGIN_INCOMPLETE
;
8053 as_set
= AGGREGATE_AS_SET
;
8055 /* Handle configuration removal, otherwise installation. */
8057 return bgp_aggregate_unset(vty
, prefix_str
, AFI_IP6
,
8060 return bgp_aggregate_set(vty
, prefix_str
, AFI_IP6
, SAFI_UNICAST
,
8061 rmap_name
, summary_only
!= NULL
, as_set
,
8062 origin
, match_med
!= NULL
, suppress_map
);
8065 /* Redistribute route treatment. */
8066 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
8067 const union g_addr
*nexthop
, ifindex_t ifindex
,
8068 enum nexthop_types_t nhtype
, uint8_t distance
,
8069 enum blackhole_type bhtype
, uint32_t metric
,
8070 uint8_t type
, unsigned short instance
,
8073 struct bgp_path_info
*new;
8074 struct bgp_path_info
*bpi
;
8075 struct bgp_path_info rmap_path
;
8076 struct bgp_dest
*bn
;
8078 struct attr
*new_attr
;
8080 route_map_result_t ret
;
8081 struct bgp_redist
*red
;
8083 /* Make default attribute. */
8084 bgp_attr_default_set(&attr
, BGP_ORIGIN_INCOMPLETE
);
8086 * This must not be NULL to satisfy Coverity SA
8088 assert(attr
.aspath
);
8091 case NEXTHOP_TYPE_IFINDEX
:
8093 case NEXTHOP_TYPE_IPV4
:
8094 case NEXTHOP_TYPE_IPV4_IFINDEX
:
8095 attr
.nexthop
= nexthop
->ipv4
;
8097 case NEXTHOP_TYPE_IPV6
:
8098 case NEXTHOP_TYPE_IPV6_IFINDEX
:
8099 attr
.mp_nexthop_global
= nexthop
->ipv6
;
8100 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
8102 case NEXTHOP_TYPE_BLACKHOLE
:
8103 switch (p
->family
) {
8105 attr
.nexthop
.s_addr
= INADDR_ANY
;
8108 memset(&attr
.mp_nexthop_global
, 0,
8109 sizeof(attr
.mp_nexthop_global
));
8110 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
8113 attr
.bh_type
= bhtype
;
8116 attr
.nh_type
= nhtype
;
8117 attr
.nh_ifindex
= ifindex
;
8120 attr
.distance
= distance
;
8121 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
8124 afi
= family2afi(p
->family
);
8126 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
8128 struct attr attr_new
;
8130 /* Copy attribute for modification. */
8133 if (red
->redist_metric_flag
)
8134 attr_new
.med
= red
->redist_metric
;
8136 /* Apply route-map. */
8137 if (red
->rmap
.name
) {
8138 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
8139 rmap_path
.peer
= bgp
->peer_self
;
8140 rmap_path
.attr
= &attr_new
;
8142 SET_FLAG(bgp
->peer_self
->rmap_type
,
8143 PEER_RMAP_TYPE_REDISTRIBUTE
);
8145 ret
= route_map_apply(red
->rmap
.map
, p
, &rmap_path
);
8147 bgp
->peer_self
->rmap_type
= 0;
8149 if (ret
== RMAP_DENYMATCH
) {
8150 /* Free uninterned attribute. */
8151 bgp_attr_flush(&attr_new
);
8153 /* Unintern original. */
8154 aspath_unintern(&attr
.aspath
);
8155 bgp_redistribute_delete(bgp
, p
, type
, instance
);
8160 if (bgp_in_graceful_shutdown(bgp
))
8161 bgp_attr_add_gshut_community(&attr_new
);
8163 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
8164 SAFI_UNICAST
, p
, NULL
);
8166 new_attr
= bgp_attr_intern(&attr_new
);
8168 for (bpi
= bgp_dest_get_bgp_path_info(bn
); bpi
; bpi
= bpi
->next
)
8169 if (bpi
->peer
== bgp
->peer_self
8170 && bpi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
8174 /* Ensure the (source route) type is updated. */
8176 if (attrhash_cmp(bpi
->attr
, new_attr
)
8177 && !CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
)) {
8178 bgp_attr_unintern(&new_attr
);
8179 aspath_unintern(&attr
.aspath
);
8180 bgp_dest_unlock_node(bn
);
8183 /* The attribute is changed. */
8184 bgp_path_info_set_flag(bn
, bpi
,
8185 BGP_PATH_ATTR_CHANGED
);
8187 /* Rewrite BGP route information. */
8188 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
8189 bgp_path_info_restore(bn
, bpi
);
8191 bgp_aggregate_decrement(
8192 bgp
, p
, bpi
, afi
, SAFI_UNICAST
);
8193 bgp_attr_unintern(&bpi
->attr
);
8194 bpi
->attr
= new_attr
;
8195 bpi
->uptime
= bgp_clock();
8197 /* Process change. */
8198 bgp_aggregate_increment(bgp
, p
, bpi
, afi
,
8200 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
8201 bgp_dest_unlock_node(bn
);
8202 aspath_unintern(&attr
.aspath
);
8204 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8206 == BGP_INSTANCE_TYPE_DEFAULT
)) {
8208 vpn_leak_from_vrf_update(
8209 bgp_get_default(), bgp
, bpi
);
8215 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
8216 bgp
->peer_self
, new_attr
, bn
);
8217 SET_FLAG(new->flags
, BGP_PATH_VALID
);
8219 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
8220 bgp_path_info_add(bn
, new);
8221 bgp_dest_unlock_node(bn
);
8222 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
8224 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8225 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8227 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
8231 /* Unintern original. */
8232 aspath_unintern(&attr
.aspath
);
8235 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, uint8_t type
,
8236 unsigned short instance
)
8239 struct bgp_dest
*dest
;
8240 struct bgp_path_info
*pi
;
8241 struct bgp_redist
*red
;
8243 afi
= family2afi(p
->family
);
8245 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
8247 dest
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
8248 SAFI_UNICAST
, p
, NULL
);
8250 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
8251 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
)
8255 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8256 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8258 vpn_leak_from_vrf_withdraw(bgp_get_default(),
8261 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, SAFI_UNICAST
);
8262 bgp_path_info_delete(dest
, pi
);
8263 bgp_process(bgp
, dest
, afi
, SAFI_UNICAST
);
8265 bgp_dest_unlock_node(dest
);
8269 /* Withdraw specified route type's route. */
8270 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
8271 unsigned short instance
)
8273 struct bgp_dest
*dest
;
8274 struct bgp_path_info
*pi
;
8275 struct bgp_table
*table
;
8277 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
8279 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
8280 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
8281 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
8282 && pi
->instance
== instance
)
8286 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8287 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8289 vpn_leak_from_vrf_withdraw(bgp_get_default(),
8292 bgp_aggregate_decrement(bgp
, bgp_dest_get_prefix(dest
),
8293 pi
, afi
, SAFI_UNICAST
);
8294 bgp_path_info_delete(dest
, pi
);
8295 bgp_process(bgp
, dest
, afi
, SAFI_UNICAST
);
8300 /* Static function to display route. */
8301 static void route_vty_out_route(struct bgp_dest
*dest
, const struct prefix
*p
,
8302 struct vty
*vty
, json_object
*json
, bool wide
)
8308 if (p
->family
== AF_INET
) {
8310 len
= vty_out(vty
, "%pFX", p
);
8312 json_object_string_add(json
, "prefix",
8313 inet_ntop(p
->family
,
8316 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
8317 prefix2str(p
, buf2
, PREFIX_STRLEN
);
8318 json_object_string_add(json
, "network", buf2
);
8319 json_object_int_add(json
, "version", dest
->version
);
8321 } else if (p
->family
== AF_ETHERNET
) {
8322 len
= vty_out(vty
, "%pFX", p
);
8323 } else if (p
->family
== AF_EVPN
) {
8325 len
= vty_out(vty
, "%pFX", (struct prefix_evpn
*)p
);
8327 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
8328 } else if (p
->family
== AF_FLOWSPEC
) {
8329 route_vty_out_flowspec(vty
, p
, NULL
,
8331 NLRI_STRING_FORMAT_JSON_SIMPLE
:
8332 NLRI_STRING_FORMAT_MIN
, json
);
8335 len
= vty_out(vty
, "%pFX", p
);
8337 json_object_string_add(json
, "prefix",
8338 inet_ntop(p
->family
,
8341 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
8342 prefix2str(p
, buf2
, PREFIX_STRLEN
);
8343 json_object_string_add(json
, "network", buf2
);
8344 json_object_int_add(json
, "version", dest
->version
);
8349 len
= wide
? (45 - len
) : (17 - len
);
8351 vty_out(vty
, "\n%*s", 20, " ");
8353 vty_out(vty
, "%*s", len
, " ");
8357 enum bgp_display_type
{
8362 bgp_path_selection_reason2str(enum bgp_path_selection_reason reason
)
8365 case bgp_path_selection_none
:
8366 return "Nothing to Select";
8367 case bgp_path_selection_first
:
8368 return "First path received";
8369 case bgp_path_selection_evpn_sticky_mac
:
8370 return "EVPN Sticky Mac";
8371 case bgp_path_selection_evpn_seq
:
8372 return "EVPN sequence number";
8373 case bgp_path_selection_evpn_lower_ip
:
8374 return "EVPN lower IP";
8375 case bgp_path_selection_evpn_local_path
:
8376 return "EVPN local ES path";
8377 case bgp_path_selection_evpn_non_proxy
:
8378 return "EVPN non proxy";
8379 case bgp_path_selection_weight
:
8381 case bgp_path_selection_local_pref
:
8382 return "Local Pref";
8383 case bgp_path_selection_local_route
:
8384 return "Local Route";
8385 case bgp_path_selection_confed_as_path
:
8386 return "Confederation based AS Path";
8387 case bgp_path_selection_as_path
:
8389 case bgp_path_selection_origin
:
8391 case bgp_path_selection_med
:
8393 case bgp_path_selection_peer
:
8395 case bgp_path_selection_confed
:
8396 return "Confed Peer Type";
8397 case bgp_path_selection_igp_metric
:
8398 return "IGP Metric";
8399 case bgp_path_selection_older
:
8400 return "Older Path";
8401 case bgp_path_selection_router_id
:
8403 case bgp_path_selection_cluster_length
:
8404 return "Cluster length";
8405 case bgp_path_selection_stale
:
8406 return "Path Staleness";
8407 case bgp_path_selection_local_configured
:
8408 return "Locally configured route";
8409 case bgp_path_selection_neighbor_ip
:
8410 return "Neighbor IP";
8411 case bgp_path_selection_default
:
8412 return "Nothing left to compare";
8414 return "Invalid (internal error)";
8417 /* Print the short form route status for a bgp_path_info */
8418 static void route_vty_short_status_out(struct vty
*vty
,
8419 struct bgp_path_info
*path
,
8420 const struct prefix
*p
,
8421 json_object
*json_path
)
8423 enum rpki_states rpki_state
= RPKI_NOT_BEING_USED
;
8427 /* Route status display. */
8428 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
8429 json_object_boolean_true_add(json_path
, "removed");
8431 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
8432 json_object_boolean_true_add(json_path
, "stale");
8434 if (path
->extra
&& bgp_path_suppressed(path
))
8435 json_object_boolean_true_add(json_path
, "suppressed");
8437 if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
8438 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
8439 json_object_boolean_true_add(json_path
, "valid");
8442 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
8443 json_object_boolean_true_add(json_path
, "history");
8445 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
8446 json_object_boolean_true_add(json_path
, "damped");
8448 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
8449 json_object_boolean_true_add(json_path
, "bestpath");
8450 json_object_string_add(json_path
, "selectionReason",
8451 bgp_path_selection_reason2str(
8452 path
->net
->reason
));
8455 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
8456 json_object_boolean_true_add(json_path
, "multipath");
8458 /* Internal route. */
8459 if ((path
->peer
->as
)
8460 && (path
->peer
->as
== path
->peer
->local_as
))
8461 json_object_string_add(json_path
, "pathFrom",
8464 json_object_string_add(json_path
, "pathFrom",
8470 /* RPKI validation state */
8472 hook_call(bgp_rpki_prefix_status
, path
->peer
, path
->attr
, p
);
8474 if (rpki_state
== RPKI_VALID
)
8476 else if (rpki_state
== RPKI_INVALID
)
8478 else if (rpki_state
== RPKI_NOTFOUND
)
8481 /* Route status display. */
8482 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
8484 else if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
8486 else if (bgp_path_suppressed(path
))
8488 else if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
8489 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
8495 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
8497 else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
8499 else if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
8501 else if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
8506 /* Internal route. */
8507 if (path
->peer
&& (path
->peer
->as
)
8508 && (path
->peer
->as
== path
->peer
->local_as
))
8514 static char *bgp_nexthop_hostname(struct peer
*peer
,
8515 struct bgp_nexthop_cache
*bnc
)
8518 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME
))
8519 return peer
->hostname
;
8523 /* called from terminal list command */
8524 void route_vty_out(struct vty
*vty
, const struct prefix
*p
,
8525 struct bgp_path_info
*path
, int display
, safi_t safi
,
8526 json_object
*json_paths
, bool wide
)
8529 struct attr
*attr
= path
->attr
;
8530 json_object
*json_path
= NULL
;
8531 json_object
*json_nexthops
= NULL
;
8532 json_object
*json_nexthop_global
= NULL
;
8533 json_object
*json_nexthop_ll
= NULL
;
8534 json_object
*json_ext_community
= NULL
;
8535 char vrf_id_str
[VRF_NAMSIZ
] = {0};
8537 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
8538 bool nexthop_othervrf
= false;
8539 vrf_id_t nexthop_vrfid
= VRF_DEFAULT
;
8540 const char *nexthop_vrfname
= VRF_DEFAULT_NAME
;
8541 char *nexthop_hostname
=
8542 bgp_nexthop_hostname(path
->peer
, path
->nexthop
);
8543 char esi_buf
[ESI_STR_LEN
];
8546 json_path
= json_object_new_object();
8548 /* short status lead text */
8549 route_vty_short_status_out(vty
, path
, p
, json_path
);
8552 /* print prefix and mask */
8554 route_vty_out_route(path
->net
, p
, vty
, json_path
, wide
);
8556 vty_out(vty
, "%*s", (wide
? 45 : 17), " ");
8558 route_vty_out_route(path
->net
, p
, vty
, json_path
, wide
);
8562 * If vrf id of nexthop is different from that of prefix,
8563 * set up printable string to append
8565 if (path
->extra
&& path
->extra
->bgp_orig
) {
8566 const char *self
= "";
8571 nexthop_othervrf
= true;
8572 nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
8574 if (path
->extra
->bgp_orig
->vrf_id
== VRF_UNKNOWN
)
8575 snprintf(vrf_id_str
, sizeof(vrf_id_str
),
8576 "@%s%s", VRFID_NONE_STR
, self
);
8578 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "@%u%s",
8579 path
->extra
->bgp_orig
->vrf_id
, self
);
8581 if (path
->extra
->bgp_orig
->inst_type
8582 != BGP_INSTANCE_TYPE_DEFAULT
)
8584 nexthop_vrfname
= path
->extra
->bgp_orig
->name
;
8586 const char *self
= "";
8591 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "%s", self
);
8595 * For ENCAP and EVPN routes, nexthop address family is not
8596 * neccessarily the same as the prefix address family.
8597 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
8598 * EVPN routes are also exchanged with a MP nexthop. Currently,
8600 * is only IPv4, the value will be present in either
8602 * attr->mp_nexthop_global_in
8604 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
8607 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
8611 snprintf(nexthop
, sizeof(nexthop
), "%s",
8612 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
8616 snprintf(nexthop
, sizeof(nexthop
), "%s",
8617 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
8621 snprintf(nexthop
, sizeof(nexthop
), "?");
8626 json_nexthop_global
= json_object_new_object();
8628 json_object_string_add(json_nexthop_global
, "ip",
8631 if (path
->peer
->hostname
)
8632 json_object_string_add(json_nexthop_global
,
8634 path
->peer
->hostname
);
8636 json_object_string_add(json_nexthop_global
, "afi",
8637 (af
== AF_INET
) ? "ipv4"
8639 json_object_boolean_true_add(json_nexthop_global
,
8642 if (nexthop_hostname
)
8643 len
= vty_out(vty
, "%s(%s)%s", nexthop
,
8644 nexthop_hostname
, vrf_id_str
);
8646 len
= vty_out(vty
, "%s%s", nexthop
, vrf_id_str
);
8648 len
= wide
? (41 - len
) : (16 - len
);
8650 vty_out(vty
, "\n%*s", 36, " ");
8652 vty_out(vty
, "%*s", len
, " ");
8654 } else if (safi
== SAFI_EVPN
) {
8656 char buf
[BUFSIZ
] = {0};
8658 json_nexthop_global
= json_object_new_object();
8660 json_object_string_add(json_nexthop_global
, "ip",
8662 &attr
->nexthop
, buf
,
8665 if (path
->peer
->hostname
)
8666 json_object_string_add(json_nexthop_global
,
8668 path
->peer
->hostname
);
8670 json_object_string_add(json_nexthop_global
, "afi",
8672 json_object_boolean_true_add(json_nexthop_global
,
8675 if (nexthop_hostname
)
8676 len
= vty_out(vty
, "%pI4(%s)%s", &attr
->nexthop
,
8677 nexthop_hostname
, vrf_id_str
);
8679 len
= vty_out(vty
, "%pI4%s", &attr
->nexthop
,
8682 len
= wide
? (41 - len
) : (16 - len
);
8684 vty_out(vty
, "\n%*s", 36, " ");
8686 vty_out(vty
, "%*s", len
, " ");
8688 } else if (safi
== SAFI_FLOWSPEC
) {
8689 if (attr
->nexthop
.s_addr
!= INADDR_ANY
) {
8691 char buf
[BUFSIZ
] = {0};
8693 json_nexthop_global
= json_object_new_object();
8695 json_object_string_add(json_nexthop_global
,
8697 json_object_string_add(
8698 json_nexthop_global
, "ip",
8699 inet_ntop(AF_INET
, &attr
->nexthop
, buf
,
8702 if (path
->peer
->hostname
)
8703 json_object_string_add(
8704 json_nexthop_global
, "hostname",
8705 path
->peer
->hostname
);
8707 json_object_boolean_true_add(
8708 json_nexthop_global
,
8711 if (nexthop_hostname
)
8712 len
= vty_out(vty
, "%pI4(%s)%s",
8717 len
= vty_out(vty
, "%pI4%s",
8721 len
= wide
? (41 - len
) : (16 - len
);
8723 vty_out(vty
, "\n%*s", 36, " ");
8725 vty_out(vty
, "%*s", len
, " ");
8728 } else if (p
->family
== AF_INET
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
8730 char buf
[BUFSIZ
] = {0};
8732 json_nexthop_global
= json_object_new_object();
8734 json_object_string_add(json_nexthop_global
, "ip",
8736 &attr
->nexthop
, buf
,
8739 if (path
->peer
->hostname
)
8740 json_object_string_add(json_nexthop_global
,
8742 path
->peer
->hostname
);
8744 json_object_string_add(json_nexthop_global
, "afi",
8746 json_object_boolean_true_add(json_nexthop_global
,
8749 if (nexthop_hostname
)
8750 len
= vty_out(vty
, "%pI4(%s)%s", &attr
->nexthop
,
8751 nexthop_hostname
, vrf_id_str
);
8753 len
= vty_out(vty
, "%pI4%s", &attr
->nexthop
,
8756 len
= wide
? (41 - len
) : (16 - len
);
8758 vty_out(vty
, "\n%*s", 36, " ");
8760 vty_out(vty
, "%*s", len
, " ");
8765 else if (p
->family
== AF_INET6
|| BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
8769 json_nexthop_global
= json_object_new_object();
8770 json_object_string_add(
8771 json_nexthop_global
, "ip",
8772 inet_ntop(AF_INET6
, &attr
->mp_nexthop_global
,
8775 if (path
->peer
->hostname
)
8776 json_object_string_add(json_nexthop_global
,
8778 path
->peer
->hostname
);
8780 json_object_string_add(json_nexthop_global
, "afi",
8782 json_object_string_add(json_nexthop_global
, "scope",
8785 /* We display both LL & GL if both have been
8787 if ((attr
->mp_nexthop_len
8788 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
8789 || (path
->peer
->conf_if
)) {
8790 json_nexthop_ll
= json_object_new_object();
8791 json_object_string_add(
8792 json_nexthop_ll
, "ip",
8794 &attr
->mp_nexthop_local
, buf
,
8797 if (path
->peer
->hostname
)
8798 json_object_string_add(
8799 json_nexthop_ll
, "hostname",
8800 path
->peer
->hostname
);
8802 json_object_string_add(json_nexthop_ll
, "afi",
8804 json_object_string_add(json_nexthop_ll
, "scope",
8807 if ((IPV6_ADDR_CMP(&attr
->mp_nexthop_global
,
8808 &attr
->mp_nexthop_local
)
8810 && !attr
->mp_nexthop_prefer_global
)
8811 json_object_boolean_true_add(
8812 json_nexthop_ll
, "used");
8814 json_object_boolean_true_add(
8815 json_nexthop_global
, "used");
8817 json_object_boolean_true_add(
8818 json_nexthop_global
, "used");
8820 /* Display LL if LL/Global both in table unless
8821 * prefer-global is set */
8822 if (((attr
->mp_nexthop_len
8823 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
8824 && !attr
->mp_nexthop_prefer_global
)
8825 || (path
->peer
->conf_if
)) {
8826 if (path
->peer
->conf_if
) {
8827 len
= vty_out(vty
, "%s",
8828 path
->peer
->conf_if
);
8829 /* len of IPv6 addr + max len of def
8831 len
= wide
? (41 - len
) : (16 - len
);
8834 vty_out(vty
, "\n%*s", 36, " ");
8836 vty_out(vty
, "%*s", len
, " ");
8838 if (nexthop_hostname
)
8841 &attr
->mp_nexthop_local
,
8847 &attr
->mp_nexthop_local
,
8850 len
= wide
? (41 - len
) : (16 - len
);
8853 vty_out(vty
, "\n%*s", 36, " ");
8855 vty_out(vty
, "%*s", len
, " ");
8858 if (nexthop_hostname
)
8859 len
= vty_out(vty
, "%pI6(%s)%s",
8860 &attr
->mp_nexthop_global
,
8864 len
= vty_out(vty
, "%pI6%s",
8865 &attr
->mp_nexthop_global
,
8868 len
= wide
? (41 - len
) : (16 - len
);
8871 vty_out(vty
, "\n%*s", 36, " ");
8873 vty_out(vty
, "%*s", len
, " ");
8879 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
8881 json_object_int_add(json_path
, "metric", attr
->med
);
8883 vty_out(vty
, "%7u", attr
->med
);
8885 vty_out(vty
, "%10u", attr
->med
);
8886 else if (!json_paths
) {
8888 vty_out(vty
, "%*s", 7, " ");
8890 vty_out(vty
, "%*s", 10, " ");
8894 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
8896 json_object_int_add(json_path
, "locPrf",
8899 vty_out(vty
, "%7u", attr
->local_pref
);
8900 else if (!json_paths
)
8904 json_object_int_add(json_path
, "weight", attr
->weight
);
8906 vty_out(vty
, "%7u ", attr
->weight
);
8910 json_object_string_add(
8911 json_path
, "peerId",
8912 sockunion2str(&path
->peer
->su
, buf
, SU_ADDRSTRLEN
));
8918 json_object_string_add(json_path
, "path",
8921 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
8926 json_object_string_add(json_path
, "origin",
8927 bgp_origin_long_str
[attr
->origin
]);
8929 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
8932 if (bgp_evpn_is_esi_valid(&attr
->esi
)) {
8933 json_object_string_add(json_path
, "esi",
8934 esi_to_str(&attr
->esi
,
8935 esi_buf
, sizeof(esi_buf
)));
8937 if (safi
== SAFI_EVPN
&&
8938 attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
8939 json_ext_community
= json_object_new_object();
8940 json_object_string_add(json_ext_community
,
8942 attr
->ecommunity
->str
);
8943 json_object_object_add(json_path
,
8944 "extendedCommunity",
8945 json_ext_community
);
8949 json_object_boolean_true_add(json_path
,
8950 "announceNexthopSelf");
8951 if (nexthop_othervrf
) {
8952 json_object_string_add(json_path
, "nhVrfName",
8955 json_object_int_add(json_path
, "nhVrfId",
8956 ((nexthop_vrfid
== VRF_UNKNOWN
)
8958 : (int)nexthop_vrfid
));
8963 if (json_nexthop_global
|| json_nexthop_ll
) {
8964 json_nexthops
= json_object_new_array();
8966 if (json_nexthop_global
)
8967 json_object_array_add(json_nexthops
,
8968 json_nexthop_global
);
8970 if (json_nexthop_ll
)
8971 json_object_array_add(json_nexthops
,
8974 json_object_object_add(json_path
, "nexthops",
8978 json_object_array_add(json_paths
, json_path
);
8982 if (safi
== SAFI_EVPN
) {
8983 if (bgp_evpn_is_esi_valid(&attr
->esi
)) {
8984 /* XXX - add these params to the json out */
8985 vty_out(vty
, "%*s", 20, " ");
8986 vty_out(vty
, "ESI:%s",
8987 esi_to_str(&attr
->esi
, esi_buf
,
8993 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
8994 vty_out(vty
, "%*s", 20, " ");
8995 vty_out(vty
, "%s\n", attr
->ecommunity
->str
);
8999 #ifdef ENABLE_BGP_VNC
9000 /* prints an additional line, indented, with VNC info, if
9002 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
9003 rfapi_vty_out_vncinfo(vty
, p
, path
, safi
);
9008 /* called from terminal list command */
9009 void route_vty_out_tmp(struct vty
*vty
, struct bgp_dest
*dest
,
9010 const struct prefix
*p
, struct attr
*attr
, safi_t safi
,
9011 bool use_json
, json_object
*json_ar
, bool wide
)
9013 json_object
*json_status
= NULL
;
9014 json_object
*json_net
= NULL
;
9018 /* Route status display. */
9020 json_status
= json_object_new_object();
9021 json_net
= json_object_new_object();
9028 /* print prefix and mask */
9030 if (safi
== SAFI_EVPN
)
9031 bgp_evpn_route2json((struct prefix_evpn
*)p
, json_net
);
9032 else if (p
->family
== AF_INET
|| p
->family
== AF_INET6
) {
9033 json_object_string_add(
9034 json_net
, "addrPrefix",
9035 inet_ntop(p
->family
, &p
->u
.prefix
, buff
,
9037 json_object_int_add(json_net
, "prefixLen",
9039 prefix2str(p
, buff
, PREFIX_STRLEN
);
9040 json_object_string_add(json_net
, "network", buff
);
9043 route_vty_out_route(dest
, p
, vty
, NULL
, wide
);
9045 /* Print attribute */
9048 char buf
[BUFSIZ
] = {0};
9050 if (p
->family
== AF_INET
9051 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
9052 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
9053 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
9054 json_object_string_add(
9055 json_net
, "nextHop",
9058 &attr
->mp_nexthop_global_in
,
9061 json_object_string_add(
9062 json_net
, "nextHop",
9064 &attr
->nexthop
, buf
,
9066 } else if (p
->family
== AF_INET6
9067 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
9070 json_object_string_add(
9071 json_net
, "nextHopGlobal",
9073 &attr
->mp_nexthop_global
, buf
,
9075 } else if (p
->family
== AF_EVPN
9076 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
9077 char buf
[BUFSIZ
] = {0};
9079 json_object_string_add(
9080 json_net
, "nextHop",
9082 &attr
->mp_nexthop_global_in
,
9087 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
9088 json_object_int_add(json_net
, "metric",
9091 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
9092 json_object_int_add(json_net
, "locPrf",
9095 json_object_int_add(json_net
, "weight", attr
->weight
);
9099 json_object_string_add(json_net
, "path",
9103 json_object_string_add(json_net
, "bgpOriginCode",
9104 bgp_origin_str
[attr
->origin
]);
9106 if (p
->family
== AF_INET
9107 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
9108 || safi
== SAFI_EVPN
9109 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
9110 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
9111 || safi
== SAFI_EVPN
)
9112 vty_out(vty
, "%-16pI4",
9113 &attr
->mp_nexthop_global_in
);
9115 vty_out(vty
, "%-41pI4", &attr
->nexthop
);
9117 vty_out(vty
, "%-16pI4", &attr
->nexthop
);
9118 } else if (p
->family
== AF_INET6
9119 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
9125 &attr
->mp_nexthop_global
, buf
,
9127 len
= wide
? (41 - len
) : (16 - len
);
9129 vty_out(vty
, "\n%*s", 36, " ");
9131 vty_out(vty
, "%*s", len
, " ");
9134 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
9136 vty_out(vty
, "%7u", attr
->med
);
9138 vty_out(vty
, "%10u", attr
->med
);
9144 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
9145 vty_out(vty
, "%7u", attr
->local_pref
);
9149 vty_out(vty
, "%7u ", attr
->weight
);
9153 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
9156 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9160 json_object_boolean_true_add(json_status
, "*");
9161 json_object_boolean_true_add(json_status
, ">");
9162 json_object_object_add(json_net
, "appliedStatusSymbols",
9165 prefix2str(p
, buff
, PREFIX_STRLEN
);
9166 json_object_object_add(json_ar
, buff
, json_net
);
9171 void route_vty_out_tag(struct vty
*vty
, const struct prefix
*p
,
9172 struct bgp_path_info
*path
, int display
, safi_t safi
,
9175 json_object
*json_out
= NULL
;
9177 mpls_label_t label
= MPLS_INVALID_LABEL
;
9183 json_out
= json_object_new_object();
9185 /* short status lead text */
9186 route_vty_short_status_out(vty
, path
, p
, json_out
);
9188 /* print prefix and mask */
9191 route_vty_out_route(path
->net
, p
, vty
, NULL
, false);
9193 vty_out(vty
, "%*s", 17, " ");
9196 /* Print attribute */
9198 if (((p
->family
== AF_INET
)
9199 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
9200 || (safi
== SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
9201 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
9202 char buf
[BUFSIZ
] = {0};
9204 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
9205 || safi
== SAFI_EVPN
) {
9207 json_object_string_add(
9208 json_out
, "mpNexthopGlobalIn",
9210 &attr
->mp_nexthop_global_in
,
9213 vty_out(vty
, "%-16pI4",
9214 &attr
->mp_nexthop_global_in
);
9217 json_object_string_add(
9218 json_out
, "nexthop",
9219 inet_ntop(AF_INET
, &attr
->nexthop
, buf
,
9222 vty_out(vty
, "%-16pI4", &attr
->nexthop
);
9224 } else if (((p
->family
== AF_INET6
)
9225 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
9226 || (safi
== SAFI_EVPN
&& BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
9227 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
9230 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
9232 json_object_string_add(
9233 json_out
, "mpNexthopGlobalIn",
9235 &attr
->mp_nexthop_global
,
9236 buf_a
, sizeof(buf_a
)));
9240 &attr
->mp_nexthop_global
,
9241 buf_a
, sizeof(buf_a
)));
9242 } else if (attr
->mp_nexthop_len
9243 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
9244 snprintfrr(buf_a
, sizeof(buf_a
), "%pI6(%pI6)",
9245 &attr
->mp_nexthop_global
,
9246 &attr
->mp_nexthop_local
);
9248 json_object_string_add(json_out
,
9249 "mpNexthopGlobalLocal",
9252 vty_out(vty
, "%s", buf_a
);
9256 label
= decode_label(&path
->extra
->label
[0]);
9258 if (bgp_is_valid_label(&label
)) {
9260 json_object_int_add(json_out
, "notag", label
);
9261 json_object_array_add(json
, json_out
);
9263 vty_out(vty
, "notag/%d", label
);
9269 void route_vty_out_overlay(struct vty
*vty
, const struct prefix
*p
,
9270 struct bgp_path_info
*path
, int display
,
9271 json_object
*json_paths
)
9274 char buf
[BUFSIZ
] = {0};
9275 json_object
*json_path
= NULL
;
9276 json_object
*json_nexthop
= NULL
;
9277 json_object
*json_overlay
= NULL
;
9283 json_path
= json_object_new_object();
9284 json_overlay
= json_object_new_object();
9285 json_nexthop
= json_object_new_object();
9288 /* short status lead text */
9289 route_vty_short_status_out(vty
, path
, p
, json_path
);
9291 /* print prefix and mask */
9293 route_vty_out_route(path
->net
, p
, vty
, json_path
, false);
9295 vty_out(vty
, "%*s", 17, " ");
9297 /* Print attribute */
9300 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
9304 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
, BUFSIZ
);
9306 vty_out(vty
, "%-16s", buf
);
9308 json_object_string_add(json_nexthop
, "ip", buf
);
9310 json_object_string_add(json_nexthop
, "afi", "ipv4");
9312 json_object_object_add(json_path
, "nexthop",
9317 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
, BUFSIZ
);
9318 inet_ntop(af
, &attr
->mp_nexthop_local
, buf1
, BUFSIZ
);
9320 vty_out(vty
, "%s(%s)", buf
, buf1
);
9322 json_object_string_add(json_nexthop
, "ipv6Global", buf
);
9324 json_object_string_add(json_nexthop
, "ipv6LinkLocal",
9327 json_object_string_add(json_nexthop
, "afi", "ipv6");
9329 json_object_object_add(json_path
, "nexthop",
9337 json_object_string_add(json_nexthop
, "Error",
9338 "Unsupported address-family");
9342 const struct bgp_route_evpn
*eo
= bgp_attr_get_evpn_overlay(attr
);
9344 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn
*)p
))
9345 inet_ntop(AF_INET
, &eo
->gw_ip
.ipv4
, buf
, BUFSIZ
);
9346 else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn
*)p
))
9347 inet_ntop(AF_INET6
, &eo
->gw_ip
.ipv6
, buf
, BUFSIZ
);
9350 vty_out(vty
, "/%s", buf
);
9352 json_object_string_add(json_overlay
, "gw", buf
);
9354 if (attr
->ecommunity
) {
9356 struct ecommunity_val
*routermac
= ecommunity_lookup(
9357 attr
->ecommunity
, ECOMMUNITY_ENCODE_EVPN
,
9358 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
9361 mac
= ecom_mac2str((char *)routermac
->val
);
9364 vty_out(vty
, "/%s", mac
);
9366 json_object_string_add(json_overlay
, "rmac",
9369 XFREE(MTYPE_TMP
, mac
);
9376 json_object_object_add(json_path
, "overlay", json_overlay
);
9378 json_object_array_add(json_paths
, json_path
);
9382 /* dampening route */
9383 static void damp_route_vty_out(struct vty
*vty
, const struct prefix
*p
,
9384 struct bgp_path_info
*path
, int display
,
9385 afi_t afi
, safi_t safi
, bool use_json
,
9386 json_object
*json_paths
)
9388 struct attr
*attr
= path
->attr
;
9390 char timebuf
[BGP_UPTIME_LEN
];
9391 json_object
*json_path
= NULL
;
9394 json_path
= json_object_new_object();
9396 /* short status lead text */
9397 route_vty_short_status_out(vty
, path
, p
, json_path
);
9399 /* print prefix and mask */
9402 route_vty_out_route(path
->net
, p
, vty
, NULL
, false);
9404 vty_out(vty
, "%*s", 17, " ");
9406 len
= vty_out(vty
, "%s", path
->peer
->host
);
9410 vty_out(vty
, "\n%*s", 34, " ");
9412 vty_out(vty
, "%*s", len
, " ");
9415 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
9416 BGP_UPTIME_LEN
, afi
, safi
,
9420 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
9422 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9426 bgp_damp_reuse_time_vty(vty
, path
, timebuf
, BGP_UPTIME_LEN
, afi
,
9427 safi
, use_json
, json_path
);
9430 json_object_string_add(json_path
, "asPath",
9433 json_object_string_add(json_path
, "origin",
9434 bgp_origin_str
[attr
->origin
]);
9435 json_object_string_add(json_path
, "peerHost", path
->peer
->host
);
9437 json_object_array_add(json_paths
, json_path
);
9442 static void flap_route_vty_out(struct vty
*vty
, const struct prefix
*p
,
9443 struct bgp_path_info
*path
, int display
,
9444 afi_t afi
, safi_t safi
, bool use_json
,
9445 json_object
*json_paths
)
9447 struct attr
*attr
= path
->attr
;
9448 struct bgp_damp_info
*bdi
;
9449 char timebuf
[BGP_UPTIME_LEN
];
9451 json_object
*json_path
= NULL
;
9457 json_path
= json_object_new_object();
9459 bdi
= path
->extra
->damp_info
;
9461 /* short status lead text */
9462 route_vty_short_status_out(vty
, path
, p
, json_path
);
9466 route_vty_out_route(path
->net
, p
, vty
, NULL
, false);
9468 vty_out(vty
, "%*s", 17, " ");
9470 len
= vty_out(vty
, "%s", path
->peer
->host
);
9473 vty_out(vty
, "\n%*s", 33, " ");
9475 vty_out(vty
, "%*s", len
, " ");
9477 len
= vty_out(vty
, "%d", bdi
->flap
);
9482 vty_out(vty
, "%*s", len
, " ");
9484 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
9485 BGP_UPTIME_LEN
, 0, NULL
));
9487 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
9488 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
9490 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
9491 BGP_UPTIME_LEN
, afi
,
9492 safi
, use_json
, NULL
));
9494 vty_out(vty
, "%*s ", 8, " ");
9497 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
9499 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9503 json_object_string_add(json_path
, "peerHost", path
->peer
->host
);
9504 json_object_int_add(json_path
, "bdiFlap", bdi
->flap
);
9506 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
9509 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
9510 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
9511 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
9512 BGP_UPTIME_LEN
, afi
, safi
,
9513 use_json
, json_path
);
9516 json_object_string_add(json_path
, "asPath",
9519 json_object_string_add(json_path
, "origin",
9520 bgp_origin_str
[attr
->origin
]);
9522 json_object_array_add(json_paths
, json_path
);
9526 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
9527 int *first
, const char *header
,
9528 json_object
*json_adv_to
)
9530 char buf1
[INET6_ADDRSTRLEN
];
9531 json_object
*json_peer
= NULL
;
9534 /* 'advertised-to' is a dictionary of peers we have advertised
9536 * prefix too. The key is the peer's IP or swpX, the value is
9538 * hostname if we know it and "" if not.
9540 json_peer
= json_object_new_object();
9543 json_object_string_add(json_peer
, "hostname",
9547 json_object_object_add(json_adv_to
, peer
->conf_if
,
9550 json_object_object_add(
9552 sockunion2str(&peer
->su
, buf1
, SU_ADDRSTRLEN
),
9556 vty_out(vty
, "%s", header
);
9561 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_HOSTNAME
)) {
9563 vty_out(vty
, " %s(%s)", peer
->hostname
,
9566 vty_out(vty
, " %s(%s)", peer
->hostname
,
9567 sockunion2str(&peer
->su
, buf1
,
9571 vty_out(vty
, " %s", peer
->conf_if
);
9574 sockunion2str(&peer
->su
, buf1
,
9580 static void route_vty_out_tx_ids(struct vty
*vty
,
9581 struct bgp_addpath_info_data
*d
)
9585 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
9586 vty_out(vty
, "TX-%s %u%s", bgp_addpath_names(i
)->human_name
,
9587 d
->addpath_tx_id
[i
],
9588 i
< BGP_ADDPATH_MAX
- 1 ? " " : "\n");
9592 static void route_vty_out_detail_es_info(struct vty
*vty
,
9593 struct bgp_path_info
*pi
,
9595 json_object
*json_path
)
9597 char esi_buf
[ESI_STR_LEN
];
9598 bool es_local
= !!CHECK_FLAG(attr
->es_flags
, ATTR_ES_IS_LOCAL
);
9599 bool peer_router
= !!CHECK_FLAG(attr
->es_flags
,
9600 ATTR_ES_PEER_ROUTER
);
9601 bool peer_active
= !!CHECK_FLAG(attr
->es_flags
,
9602 ATTR_ES_PEER_ACTIVE
);
9603 bool peer_proxy
= !!CHECK_FLAG(attr
->es_flags
,
9604 ATTR_ES_PEER_PROXY
);
9605 esi_to_str(&attr
->esi
, esi_buf
, sizeof(esi_buf
));
9607 json_object
*json_es_info
= NULL
;
9609 json_object_string_add(
9612 if (es_local
|| bgp_evpn_attr_is_sync(attr
)) {
9613 json_es_info
= json_object_new_object();
9615 json_object_boolean_true_add(
9616 json_es_info
, "localEs");
9618 json_object_boolean_true_add(
9619 json_es_info
, "peerActive");
9621 json_object_boolean_true_add(
9622 json_es_info
, "peerProxy");
9624 json_object_boolean_true_add(
9625 json_es_info
, "peerRouter");
9626 if (attr
->mm_sync_seqnum
)
9627 json_object_int_add(
9628 json_es_info
, "peerSeq",
9629 attr
->mm_sync_seqnum
);
9630 json_object_object_add(
9631 json_path
, "es_info",
9635 if (bgp_evpn_attr_is_sync(attr
))
9637 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
9639 es_local
? "local-es":"",
9640 peer_proxy
? "proxy " : "",
9641 peer_active
? "active ":"",
9642 peer_router
? "router ":"",
9643 attr
->mm_sync_seqnum
);
9645 vty_out(vty
, " ESI %s %s\n",
9647 es_local
? "local-es":"");
9651 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
, struct bgp_dest
*bn
,
9652 struct bgp_path_info
*path
, afi_t afi
, safi_t safi
,
9653 enum rpki_states rpki_curr_state
,
9654 json_object
*json_paths
)
9656 char buf
[INET6_ADDRSTRLEN
];
9658 struct attr
*attr
= path
->attr
;
9659 int sockunion_vty_out(struct vty
*, union sockunion
*);
9661 json_object
*json_bestpath
= NULL
;
9662 json_object
*json_cluster_list
= NULL
;
9663 json_object
*json_cluster_list_list
= NULL
;
9664 json_object
*json_ext_community
= NULL
;
9665 json_object
*json_last_update
= NULL
;
9666 json_object
*json_pmsi
= NULL
;
9667 json_object
*json_nexthop_global
= NULL
;
9668 json_object
*json_nexthop_ll
= NULL
;
9669 json_object
*json_nexthops
= NULL
;
9670 json_object
*json_path
= NULL
;
9671 json_object
*json_peer
= NULL
;
9672 json_object
*json_string
= NULL
;
9673 json_object
*json_adv_to
= NULL
;
9675 struct listnode
*node
, *nnode
;
9677 int addpath_capable
;
9679 unsigned int first_as
;
9681 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
9683 char *nexthop_hostname
=
9684 bgp_nexthop_hostname(path
->peer
, path
->nexthop
);
9687 json_path
= json_object_new_object();
9688 json_peer
= json_object_new_object();
9689 json_nexthop_global
= json_object_new_object();
9692 if (safi
== SAFI_EVPN
) {
9694 vty_out(vty
, " Route %pRN", bn
);
9701 if (path
->extra
&& path
->extra
->num_labels
) {
9702 bgp_evpn_label2str(path
->extra
->label
,
9703 path
->extra
->num_labels
, tag_buf
,
9706 if (safi
== SAFI_EVPN
) {
9708 if (tag_buf
[0] != '\0')
9709 vty_out(vty
, " VNI %s", tag_buf
);
9712 json_object_string_add(json_path
, "VNI",
9717 if (path
->extra
&& path
->extra
->parent
&& !json_paths
) {
9718 struct bgp_path_info
*parent_ri
;
9719 struct bgp_dest
*dest
, *pdest
;
9721 parent_ri
= (struct bgp_path_info
*)path
->extra
->parent
;
9722 dest
= parent_ri
->net
;
9723 if (dest
&& dest
->pdest
) {
9724 pdest
= dest
->pdest
;
9726 (struct prefix_rd
*)bgp_dest_get_prefix(
9728 buf1
, sizeof(buf1
));
9729 if (is_pi_family_evpn(parent_ri
)) {
9731 " Imported from %s:%pFX, VNI %s",
9733 (struct prefix_evpn
*)
9734 bgp_dest_get_prefix(
9737 if (attr
->es_flags
& ATTR_ES_L3_NHG
)
9738 vty_out(vty
, ", L3NHG %s",
9740 & ATTR_ES_L3_NHG_ACTIVE
)
9747 " Imported from %s:%pFX\n",
9749 (struct prefix_evpn
*)
9750 bgp_dest_get_prefix(
9756 if (safi
== SAFI_EVPN
9757 && attr
->evpn_overlay
.type
== OVERLAY_INDEX_GATEWAY_IP
) {
9758 char gwip_buf
[INET6_ADDRSTRLEN
];
9760 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn
*)&bn
->p
))
9761 inet_ntop(AF_INET
, &attr
->evpn_overlay
.gw_ip
.ipv4
,
9762 gwip_buf
, sizeof(gwip_buf
));
9764 inet_ntop(AF_INET6
, &attr
->evpn_overlay
.gw_ip
.ipv6
,
9765 gwip_buf
, sizeof(gwip_buf
));
9768 json_object_string_add(json_path
, "gatewayIP",
9771 vty_out(vty
, " Gateway IP %s", gwip_buf
);
9774 if (safi
== SAFI_EVPN
)
9777 /* Line1 display AS-path, Aggregator */
9780 if (!attr
->aspath
->json
)
9781 aspath_str_update(attr
->aspath
, true);
9782 json_object_lock(attr
->aspath
->json
);
9783 json_object_object_add(json_path
, "aspath",
9784 attr
->aspath
->json
);
9786 if (attr
->aspath
->segments
)
9787 aspath_print_vty(vty
, " %s", attr
->aspath
, "");
9789 vty_out(vty
, " Local");
9793 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
)) {
9795 json_object_boolean_true_add(json_path
, "removed");
9797 vty_out(vty
, ", (removed)");
9800 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
9802 json_object_boolean_true_add(json_path
, "stale");
9804 vty_out(vty
, ", (stale)");
9807 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
9809 char buf
[BUFSIZ
] = {0};
9811 json_object_int_add(json_path
, "aggregatorAs",
9812 attr
->aggregator_as
);
9813 json_object_string_add(json_path
, "aggregatorId",
9815 &attr
->aggregator_addr
,
9818 vty_out(vty
, ", (aggregated by %u %pI4)",
9819 attr
->aggregator_as
, &attr
->aggregator_addr
);
9823 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
9824 PEER_FLAG_REFLECTOR_CLIENT
)) {
9826 json_object_boolean_true_add(json_path
,
9827 "rxedFromRrClient");
9829 vty_out(vty
, ", (Received from a RR-client)");
9832 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
9833 PEER_FLAG_RSERVER_CLIENT
)) {
9835 json_object_boolean_true_add(json_path
,
9836 "rxedFromRsClient");
9838 vty_out(vty
, ", (Received from a RS-client)");
9841 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
9843 json_object_boolean_true_add(json_path
,
9844 "dampeningHistoryEntry");
9846 vty_out(vty
, ", (history entry)");
9847 } else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)) {
9849 json_object_boolean_true_add(json_path
,
9850 "dampeningSuppressed");
9852 vty_out(vty
, ", (suppressed due to dampening)");
9858 /* Line2 display Next-hop, Neighbor, Router-id */
9859 /* Display the nexthop */
9860 const struct prefix
*bn_p
= bgp_dest_get_prefix(bn
);
9862 if ((bn_p
->family
== AF_INET
|| bn_p
->family
== AF_ETHERNET
9863 || bn_p
->family
== AF_EVPN
)
9864 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
9865 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
9866 char buf
[BUFSIZ
] = {0};
9868 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
9869 || safi
== SAFI_EVPN
) {
9871 json_object_string_add(
9872 json_nexthop_global
, "ip",
9874 &attr
->mp_nexthop_global_in
,
9877 if (path
->peer
->hostname
)
9878 json_object_string_add(
9879 json_nexthop_global
, "hostname",
9880 path
->peer
->hostname
);
9882 if (nexthop_hostname
)
9883 vty_out(vty
, " %pI4(%s)",
9884 &attr
->mp_nexthop_global_in
,
9887 vty_out(vty
, " %pI4",
9888 &attr
->mp_nexthop_global_in
);
9892 json_object_string_add(
9893 json_nexthop_global
, "ip",
9894 inet_ntop(AF_INET
, &attr
->nexthop
, buf
,
9897 if (path
->peer
->hostname
)
9898 json_object_string_add(
9899 json_nexthop_global
, "hostname",
9900 path
->peer
->hostname
);
9902 if (nexthop_hostname
)
9903 vty_out(vty
, " %pI4(%s)",
9907 vty_out(vty
, " %pI4",
9913 json_object_string_add(json_nexthop_global
, "afi",
9917 json_object_string_add(
9918 json_nexthop_global
, "ip",
9919 inet_ntop(AF_INET6
, &attr
->mp_nexthop_global
,
9920 buf
, INET6_ADDRSTRLEN
));
9922 if (path
->peer
->hostname
)
9923 json_object_string_add(json_nexthop_global
,
9925 path
->peer
->hostname
);
9927 json_object_string_add(json_nexthop_global
, "afi",
9929 json_object_string_add(json_nexthop_global
, "scope",
9932 if (nexthop_hostname
)
9933 vty_out(vty
, " %pI6(%s)",
9934 &attr
->mp_nexthop_global
,
9937 vty_out(vty
, " %pI6",
9938 &attr
->mp_nexthop_global
);
9942 /* Display the IGP cost or 'inaccessible' */
9943 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
9945 json_object_boolean_false_add(json_nexthop_global
,
9948 vty_out(vty
, " (inaccessible)");
9950 if (path
->extra
&& path
->extra
->igpmetric
) {
9952 json_object_int_add(json_nexthop_global
,
9954 path
->extra
->igpmetric
);
9956 vty_out(vty
, " (metric %u)",
9957 path
->extra
->igpmetric
);
9960 /* IGP cost is 0, display this only for json */
9963 json_object_int_add(json_nexthop_global
,
9968 json_object_boolean_true_add(json_nexthop_global
,
9972 /* Display peer "from" output */
9973 /* This path was originated locally */
9974 if (path
->peer
== bgp
->peer_self
) {
9976 if (safi
== SAFI_EVPN
9977 || (bn_p
->family
== AF_INET
9978 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
9980 json_object_string_add(json_peer
, "peerId",
9983 vty_out(vty
, " from 0.0.0.0 ");
9986 json_object_string_add(json_peer
, "peerId",
9989 vty_out(vty
, " from :: ");
9993 char buf
[BUFSIZ
] = {0};
9995 json_object_string_add(json_peer
, "routerId",
9997 &bgp
->router_id
, buf
,
10000 vty_out(vty
, "(%pI4)", &bgp
->router_id
);
10004 /* We RXed this path from one of our peers */
10008 json_object_string_add(json_peer
, "peerId",
10009 sockunion2str(&path
->peer
->su
,
10012 json_object_string_add(json_peer
, "routerId",
10014 &path
->peer
->remote_id
,
10015 buf1
, sizeof(buf1
)));
10017 if (path
->peer
->hostname
)
10018 json_object_string_add(json_peer
, "hostname",
10019 path
->peer
->hostname
);
10021 if (path
->peer
->domainname
)
10022 json_object_string_add(json_peer
, "domainname",
10023 path
->peer
->domainname
);
10025 if (path
->peer
->conf_if
)
10026 json_object_string_add(json_peer
, "interface",
10027 path
->peer
->conf_if
);
10029 if (path
->peer
->conf_if
) {
10030 if (path
->peer
->hostname
10031 && CHECK_FLAG(path
->peer
->bgp
->flags
,
10032 BGP_FLAG_SHOW_HOSTNAME
))
10033 vty_out(vty
, " from %s(%s)",
10034 path
->peer
->hostname
,
10035 path
->peer
->conf_if
);
10037 vty_out(vty
, " from %s",
10038 path
->peer
->conf_if
);
10040 if (path
->peer
->hostname
10041 && CHECK_FLAG(path
->peer
->bgp
->flags
,
10042 BGP_FLAG_SHOW_HOSTNAME
))
10043 vty_out(vty
, " from %s(%s)",
10044 path
->peer
->hostname
,
10047 vty_out(vty
, " from %s",
10048 sockunion2str(&path
->peer
->su
,
10053 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
10054 vty_out(vty
, " (%pI4)", &attr
->originator_id
);
10056 vty_out(vty
, " (%s)",
10058 &path
->peer
->remote_id
, buf1
,
10064 * Note when vrfid of nexthop is different from that of prefix
10066 if (path
->extra
&& path
->extra
->bgp_orig
) {
10067 vrf_id_t nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
10072 if (path
->extra
->bgp_orig
->inst_type
10073 == BGP_INSTANCE_TYPE_DEFAULT
)
10074 vn
= VRF_DEFAULT_NAME
;
10076 vn
= path
->extra
->bgp_orig
->name
;
10078 json_object_string_add(json_path
, "nhVrfName", vn
);
10080 if (nexthop_vrfid
== VRF_UNKNOWN
) {
10081 json_object_int_add(json_path
, "nhVrfId", -1);
10083 json_object_int_add(json_path
, "nhVrfId",
10084 (int)nexthop_vrfid
);
10087 if (nexthop_vrfid
== VRF_UNKNOWN
)
10088 vty_out(vty
, " vrf ?");
10092 vrf
= vrf_lookup_by_id(nexthop_vrfid
);
10093 vty_out(vty
, " vrf %s(%u)",
10094 VRF_LOGNAME(vrf
), nexthop_vrfid
);
10099 if (nexthop_self
) {
10101 json_object_boolean_true_add(json_path
,
10102 "announceNexthopSelf");
10104 vty_out(vty
, " announce-nh-self");
10109 vty_out(vty
, "\n");
10111 /* display the link-local nexthop */
10112 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
10114 json_nexthop_ll
= json_object_new_object();
10115 json_object_string_add(
10116 json_nexthop_ll
, "ip",
10117 inet_ntop(AF_INET6
, &attr
->mp_nexthop_local
,
10118 buf
, INET6_ADDRSTRLEN
));
10120 if (path
->peer
->hostname
)
10121 json_object_string_add(json_nexthop_ll
,
10123 path
->peer
->hostname
);
10125 json_object_string_add(json_nexthop_ll
, "afi", "ipv6");
10126 json_object_string_add(json_nexthop_ll
, "scope",
10129 json_object_boolean_true_add(json_nexthop_ll
,
10132 if (!attr
->mp_nexthop_prefer_global
)
10133 json_object_boolean_true_add(json_nexthop_ll
,
10136 json_object_boolean_true_add(
10137 json_nexthop_global
, "used");
10139 vty_out(vty
, " (%s) %s\n",
10140 inet_ntop(AF_INET6
, &attr
->mp_nexthop_local
,
10141 buf
, INET6_ADDRSTRLEN
),
10142 attr
->mp_nexthop_prefer_global
10143 ? "(prefer-global)"
10147 /* If we do not have a link-local nexthop then we must flag the
10148 global as "used" */
10151 json_object_boolean_true_add(json_nexthop_global
,
10155 if (safi
== SAFI_EVPN
&&
10156 bgp_evpn_is_esi_valid(&attr
->esi
)) {
10157 route_vty_out_detail_es_info(vty
, path
, attr
, json_path
);
10160 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
10161 * Int/Ext/Local, Atomic, best */
10163 json_object_string_add(json_path
, "origin",
10164 bgp_origin_long_str
[attr
->origin
]);
10166 vty_out(vty
, " Origin %s",
10167 bgp_origin_long_str
[attr
->origin
]);
10169 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
10171 json_object_int_add(json_path
, "metric", attr
->med
);
10173 vty_out(vty
, ", metric %u", attr
->med
);
10176 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
10178 json_object_int_add(json_path
, "locPrf",
10181 vty_out(vty
, ", localpref %u", attr
->local_pref
);
10184 if (attr
->weight
!= 0) {
10186 json_object_int_add(json_path
, "weight", attr
->weight
);
10188 vty_out(vty
, ", weight %u", attr
->weight
);
10191 if (attr
->tag
!= 0) {
10193 json_object_int_add(json_path
, "tag", attr
->tag
);
10195 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
, attr
->tag
);
10198 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
10200 json_object_boolean_false_add(json_path
, "valid");
10202 vty_out(vty
, ", invalid");
10203 } else if (!CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
10205 json_object_boolean_true_add(json_path
, "valid");
10207 vty_out(vty
, ", valid");
10211 json_object_int_add(json_path
, "version", bn
->version
);
10213 if (path
->peer
!= bgp
->peer_self
) {
10214 if (path
->peer
->as
== path
->peer
->local_as
) {
10215 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
10217 json_object_string_add(
10219 "confed-internal");
10221 vty_out(vty
, ", confed-internal");
10224 json_object_string_add(
10225 json_peer
, "type", "internal");
10227 vty_out(vty
, ", internal");
10230 if (bgp_confederation_peers_check(bgp
,
10233 json_object_string_add(
10235 "confed-external");
10237 vty_out(vty
, ", confed-external");
10240 json_object_string_add(
10241 json_peer
, "type", "external");
10243 vty_out(vty
, ", external");
10246 } else if (path
->sub_type
== BGP_ROUTE_AGGREGATE
) {
10248 json_object_boolean_true_add(json_path
, "aggregated");
10249 json_object_boolean_true_add(json_path
, "local");
10251 vty_out(vty
, ", aggregated, local");
10253 } else if (path
->type
!= ZEBRA_ROUTE_BGP
) {
10255 json_object_boolean_true_add(json_path
, "sourced");
10257 vty_out(vty
, ", sourced");
10260 json_object_boolean_true_add(json_path
, "sourced");
10261 json_object_boolean_true_add(json_path
, "local");
10263 vty_out(vty
, ", sourced, local");
10267 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
10269 json_object_boolean_true_add(json_path
,
10270 "atomicAggregate");
10272 vty_out(vty
, ", atomic-aggregate");
10275 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
)
10276 || (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)
10277 && bgp_path_info_mpath_count(path
))) {
10279 json_object_boolean_true_add(json_path
, "multipath");
10281 vty_out(vty
, ", multipath");
10284 // Mark the bestpath(s)
10285 if (CHECK_FLAG(path
->flags
, BGP_PATH_DMED_SELECTED
)) {
10286 first_as
= aspath_get_first_as(attr
->aspath
);
10289 if (!json_bestpath
)
10290 json_bestpath
= json_object_new_object();
10291 json_object_int_add(json_bestpath
, "bestpathFromAs",
10295 vty_out(vty
, ", bestpath-from-AS %u", first_as
);
10297 vty_out(vty
, ", bestpath-from-AS Local");
10301 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
10303 if (!json_bestpath
)
10304 json_bestpath
= json_object_new_object();
10305 json_object_boolean_true_add(json_bestpath
, "overall");
10306 json_object_string_add(
10307 json_bestpath
, "selectionReason",
10308 bgp_path_selection_reason2str(bn
->reason
));
10310 vty_out(vty
, ", best");
10311 vty_out(vty
, " (%s)",
10312 bgp_path_selection_reason2str(bn
->reason
));
10316 if (rpki_curr_state
!= RPKI_NOT_BEING_USED
) {
10318 json_object_string_add(
10319 json_path
, "rpkiValidationState",
10320 bgp_rpki_validation2str(rpki_curr_state
));
10322 vty_out(vty
, ", rpki validation-state: %s",
10323 bgp_rpki_validation2str(rpki_curr_state
));
10327 json_object_object_add(json_path
, "bestpath", json_bestpath
);
10330 vty_out(vty
, "\n");
10332 /* Line 4 display Community */
10333 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
)) {
10335 if (!attr
->community
->json
)
10336 community_str(attr
->community
, true);
10337 json_object_lock(attr
->community
->json
);
10338 json_object_object_add(json_path
, "community",
10339 attr
->community
->json
);
10341 vty_out(vty
, " Community: %s\n",
10342 attr
->community
->str
);
10346 /* Line 5 display Extended-community */
10347 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
10349 json_ext_community
= json_object_new_object();
10350 json_object_string_add(json_ext_community
, "string",
10351 attr
->ecommunity
->str
);
10352 json_object_object_add(json_path
, "extendedCommunity",
10353 json_ext_community
);
10355 vty_out(vty
, " Extended Community: %s\n",
10356 attr
->ecommunity
->str
);
10360 /* Line 6 display Large community */
10361 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
10363 if (!attr
->lcommunity
->json
)
10364 lcommunity_str(attr
->lcommunity
, true);
10365 json_object_lock(attr
->lcommunity
->json
);
10366 json_object_object_add(json_path
, "largeCommunity",
10367 attr
->lcommunity
->json
);
10369 vty_out(vty
, " Large Community: %s\n",
10370 attr
->lcommunity
->str
);
10374 /* Line 7 display Originator, Cluster-id */
10375 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
10376 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
10377 char buf
[BUFSIZ
] = {0};
10379 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
10381 json_object_string_add(
10382 json_path
, "originatorId",
10383 inet_ntop(AF_INET
, &attr
->originator_id
,
10384 buf
, sizeof(buf
)));
10386 vty_out(vty
, " Originator: %pI4",
10387 &attr
->originator_id
);
10390 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
10391 struct cluster_list
*cluster
=
10392 bgp_attr_get_cluster(attr
);
10396 json_cluster_list
= json_object_new_object();
10397 json_cluster_list_list
=
10398 json_object_new_array();
10400 for (i
= 0; i
< cluster
->length
/ 4; i
++) {
10401 json_string
= json_object_new_string(
10404 buf
, sizeof(buf
)));
10405 json_object_array_add(
10406 json_cluster_list_list
,
10411 * struct cluster_list does not have
10412 * "str" variable like aspath and community
10413 * do. Add this someday if someone asks
10415 * json_object_string_add(json_cluster_list,
10416 * "string", cluster->str);
10418 json_object_object_add(json_cluster_list
,
10420 json_cluster_list_list
);
10421 json_object_object_add(json_path
, "clusterList",
10422 json_cluster_list
);
10424 vty_out(vty
, ", Cluster list: ");
10426 for (i
= 0; i
< cluster
->length
/ 4; i
++) {
10427 vty_out(vty
, "%pI4 ",
10428 &cluster
->list
[i
]);
10434 vty_out(vty
, "\n");
10437 if (path
->extra
&& path
->extra
->damp_info
)
10438 bgp_damp_info_vty(vty
, path
, afi
, safi
, json_path
);
10441 if (path
->extra
&& bgp_is_valid_label(&path
->extra
->label
[0])
10442 && (safi
!= SAFI_EVPN
&& !is_route_parent_evpn(path
))) {
10443 mpls_label_t label
= label_pton(&path
->extra
->label
[0]);
10446 json_object_int_add(json_path
, "remoteLabel", label
);
10448 vty_out(vty
, " Remote label: %d\n", label
);
10452 if (path
->extra
&& path
->extra
->num_sids
> 0 && safi
!= SAFI_EVPN
) {
10453 inet_ntop(AF_INET6
, &path
->extra
->sid
, buf
, sizeof(buf
));
10455 json_object_string_add(json_path
, "remoteSid", buf
);
10457 vty_out(vty
, " Remote SID: %s\n", buf
);
10461 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
10463 json_object_int_add(json_path
, "labelIndex",
10464 attr
->label_index
);
10466 vty_out(vty
, " Label Index: %d\n",
10467 attr
->label_index
);
10470 /* Line 8 display Addpath IDs */
10471 if (path
->addpath_rx_id
10472 || bgp_addpath_info_has_ids(&path
->tx_addpath
)) {
10474 json_object_int_add(json_path
, "addpathRxId",
10475 path
->addpath_rx_id
);
10477 /* Keep backwards compatibility with the old API
10478 * by putting TX All's ID in the old field
10480 json_object_int_add(
10481 json_path
, "addpathTxId",
10483 .addpath_tx_id
[BGP_ADDPATH_ALL
]);
10485 /* ... but create a specific field for each
10488 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
10489 json_object_int_add(
10491 bgp_addpath_names(i
)->id_json_name
,
10492 path
->tx_addpath
.addpath_tx_id
[i
]);
10495 vty_out(vty
, " AddPath ID: RX %u, ",
10496 path
->addpath_rx_id
);
10498 route_vty_out_tx_ids(vty
, &path
->tx_addpath
);
10502 /* If we used addpath to TX a non-bestpath we need to display
10503 * "Advertised to" on a path-by-path basis
10505 if (bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
10508 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
10510 bgp_addpath_encode_tx(peer
, afi
, safi
);
10511 has_adj
= bgp_adj_out_lookup(
10513 bgp_addpath_id_for_peer(peer
, afi
, safi
,
10514 &path
->tx_addpath
));
10516 if ((addpath_capable
&& has_adj
)
10517 || (!addpath_capable
&& has_adj
10518 && CHECK_FLAG(path
->flags
,
10519 BGP_PATH_SELECTED
))) {
10520 if (json_path
&& !json_adv_to
)
10521 json_adv_to
= json_object_new_object();
10523 route_vty_out_advertised_to(
10525 " Advertised to:", json_adv_to
);
10531 json_object_object_add(
10532 json_path
, "advertisedTo", json_adv_to
);
10536 vty_out(vty
, "\n");
10541 /* Line 9 display Uptime */
10542 tbuf
= time(NULL
) - (bgp_clock() - path
->uptime
);
10544 json_last_update
= json_object_new_object();
10545 json_object_int_add(json_last_update
, "epoch", tbuf
);
10546 json_object_string_add(json_last_update
, "string",
10548 json_object_object_add(json_path
, "lastUpdate",
10551 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
10553 /* Line 10 display PMSI tunnel attribute, if present */
10554 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
10555 const char *str
= lookup_msg(bgp_pmsi_tnltype_str
,
10556 bgp_attr_get_pmsi_tnl_type(attr
),
10557 PMSI_TNLTYPE_STR_DEFAULT
);
10560 json_pmsi
= json_object_new_object();
10561 json_object_string_add(json_pmsi
, "tunnelType", str
);
10562 json_object_int_add(json_pmsi
, "label",
10563 label2vni(&attr
->label
));
10564 json_object_object_add(json_path
, "pmsi", json_pmsi
);
10566 vty_out(vty
, " PMSI Tunnel Type: %s, label: %d\n",
10567 str
, label2vni(&attr
->label
));
10570 /* Output some debug about internal state of the dest flags */
10572 if (CHECK_FLAG(bn
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
10573 json_object_boolean_true_add(json_path
, "processScheduled");
10574 if (CHECK_FLAG(bn
->flags
, BGP_NODE_USER_CLEAR
))
10575 json_object_boolean_true_add(json_path
, "userCleared");
10576 if (CHECK_FLAG(bn
->flags
, BGP_NODE_LABEL_CHANGED
))
10577 json_object_boolean_true_add(json_path
, "labelChanged");
10578 if (CHECK_FLAG(bn
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
))
10579 json_object_boolean_true_add(json_path
, "registeredForLabel");
10580 if (CHECK_FLAG(bn
->flags
, BGP_NODE_SELECT_DEFER
))
10581 json_object_boolean_true_add(json_path
, "selectDefered");
10582 if (CHECK_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALLED
))
10583 json_object_boolean_true_add(json_path
, "fibInstalled");
10584 if (CHECK_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALL_PENDING
))
10585 json_object_boolean_true_add(json_path
, "fibPending");
10588 /* We've constructed the json object for this path, add it to the json
10592 if (json_nexthop_global
|| json_nexthop_ll
) {
10593 json_nexthops
= json_object_new_array();
10595 if (json_nexthop_global
)
10596 json_object_array_add(json_nexthops
,
10597 json_nexthop_global
);
10599 if (json_nexthop_ll
)
10600 json_object_array_add(json_nexthops
,
10603 json_object_object_add(json_path
, "nexthops",
10607 json_object_object_add(json_path
, "peer", json_peer
);
10608 json_object_array_add(json_paths
, json_path
);
10612 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
10613 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
10614 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
10616 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
10617 const char *prefix_list_str
, afi_t afi
,
10618 safi_t safi
, enum bgp_show_type type
);
10619 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
10620 const char *filter
, afi_t afi
, safi_t safi
,
10621 enum bgp_show_type type
);
10622 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
10623 const char *rmap_str
, afi_t afi
, safi_t safi
,
10624 enum bgp_show_type type
);
10625 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
10626 const char *com
, int exact
, afi_t afi
,
10628 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
10629 const char *prefix
, afi_t afi
, safi_t safi
,
10630 enum bgp_show_type type
);
10631 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
10632 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
10634 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
10635 const char *comstr
, int exact
, afi_t afi
,
10636 safi_t safi
, uint16_t show_flags
);
10638 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
10639 struct bgp_table
*table
, enum bgp_show_type type
,
10640 void *output_arg
, char *rd
, int is_last
,
10641 unsigned long *output_cum
, unsigned long *total_cum
,
10642 unsigned long *json_header_depth
, uint16_t show_flags
,
10643 enum rpki_states rpki_target_state
)
10645 struct bgp_path_info
*pi
;
10646 struct bgp_dest
*dest
;
10649 unsigned long output_count
= 0;
10650 unsigned long total_count
= 0;
10652 json_object
*json_paths
= NULL
;
10654 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
10655 bool wide
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
10656 bool all
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
10658 if (output_cum
&& *output_cum
!= 0)
10661 if (use_json
&& !*json_header_depth
) {
10663 *json_header_depth
= 1;
10665 vty_out(vty
, "{\n");
10666 *json_header_depth
= 2;
10670 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
10671 ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
10672 " \"localAS\": %u,\n \"routes\": { ",
10673 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
10674 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
10677 table
->version
, &bgp
->router_id
,
10678 bgp
->default_local_pref
, bgp
->as
);
10680 vty_out(vty
, " \"routeDistinguishers\" : {");
10681 ++*json_header_depth
;
10685 if (use_json
&& rd
) {
10686 vty_out(vty
, " \"%s\" : { ", rd
);
10689 /* Start processing of routes. */
10690 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
10691 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
10692 enum rpki_states rpki_curr_state
= RPKI_NOT_BEING_USED
;
10694 pi
= bgp_dest_get_bgp_path_info(dest
);
10700 json_paths
= json_object_new_array();
10704 for (; pi
; pi
= pi
->next
) {
10707 if (type
== bgp_show_type_prefix_version
) {
10709 strtoul(output_arg
, NULL
, 10);
10710 if (dest
->version
< version
)
10714 if (type
== bgp_show_type_community_alias
) {
10715 char *alias
= output_arg
;
10716 char **communities
;
10718 bool found
= false;
10720 if (pi
->attr
->community
) {
10721 frrstr_split(pi
->attr
->community
->str
,
10722 " ", &communities
, &num
);
10723 for (int i
= 0; i
< num
; i
++) {
10724 const char *com2alias
=
10725 bgp_community2alias(
10728 && strcmp(alias
, com2alias
)
10734 XFREE(MTYPE_TMP
, communities
);
10737 if (!found
&& pi
->attr
->lcommunity
) {
10738 frrstr_split(pi
->attr
->lcommunity
->str
,
10739 " ", &communities
, &num
);
10740 for (int i
= 0; i
< num
; i
++) {
10741 const char *com2alias
=
10742 bgp_community2alias(
10745 && strcmp(alias
, com2alias
)
10751 XFREE(MTYPE_TMP
, communities
);
10758 if (type
== bgp_show_type_rpki
) {
10759 if (dest_p
->family
== AF_INET
10760 || dest_p
->family
== AF_INET6
)
10761 rpki_curr_state
= hook_call(
10762 bgp_rpki_prefix_status
,
10763 pi
->peer
, pi
->attr
, dest_p
);
10764 if (rpki_target_state
!= RPKI_NOT_BEING_USED
10765 && rpki_curr_state
!= rpki_target_state
)
10769 if (type
== bgp_show_type_flap_statistics
10770 || type
== bgp_show_type_flap_neighbor
10771 || type
== bgp_show_type_dampend_paths
10772 || type
== bgp_show_type_damp_neighbor
) {
10773 if (!(pi
->extra
&& pi
->extra
->damp_info
))
10776 if (type
== bgp_show_type_regexp
) {
10777 regex_t
*regex
= output_arg
;
10779 if (bgp_regexec(regex
, pi
->attr
->aspath
)
10783 if (type
== bgp_show_type_prefix_list
) {
10784 struct prefix_list
*plist
= output_arg
;
10786 if (prefix_list_apply(plist
, dest_p
)
10790 if (type
== bgp_show_type_filter_list
) {
10791 struct as_list
*as_list
= output_arg
;
10793 if (as_list_apply(as_list
, pi
->attr
->aspath
)
10794 != AS_FILTER_PERMIT
)
10797 if (type
== bgp_show_type_route_map
) {
10798 struct route_map
*rmap
= output_arg
;
10799 struct bgp_path_info path
;
10800 struct attr dummy_attr
;
10801 route_map_result_t ret
;
10803 dummy_attr
= *pi
->attr
;
10805 path
.peer
= pi
->peer
;
10806 path
.attr
= &dummy_attr
;
10808 ret
= route_map_apply(rmap
, dest_p
, &path
);
10809 if (ret
== RMAP_DENYMATCH
)
10812 if (type
== bgp_show_type_neighbor
10813 || type
== bgp_show_type_flap_neighbor
10814 || type
== bgp_show_type_damp_neighbor
) {
10815 union sockunion
*su
= output_arg
;
10817 if (pi
->peer
== NULL
10818 || pi
->peer
->su_remote
== NULL
10819 || !sockunion_same(pi
->peer
->su_remote
, su
))
10822 if (type
== bgp_show_type_cidr_only
) {
10823 uint32_t destination
;
10825 destination
= ntohl(dest_p
->u
.prefix4
.s_addr
);
10826 if (IN_CLASSC(destination
)
10827 && dest_p
->prefixlen
== 24)
10829 if (IN_CLASSB(destination
)
10830 && dest_p
->prefixlen
== 16)
10832 if (IN_CLASSA(destination
)
10833 && dest_p
->prefixlen
== 8)
10836 if (type
== bgp_show_type_prefix_longer
) {
10838 if (!prefix_match(p
, dest_p
))
10841 if (type
== bgp_show_type_community_all
) {
10842 if (!pi
->attr
->community
)
10845 if (type
== bgp_show_type_community
) {
10846 struct community
*com
= output_arg
;
10848 if (!pi
->attr
->community
10849 || !community_match(pi
->attr
->community
,
10853 if (type
== bgp_show_type_community_exact
) {
10854 struct community
*com
= output_arg
;
10856 if (!pi
->attr
->community
10857 || !community_cmp(pi
->attr
->community
, com
))
10860 if (type
== bgp_show_type_community_list
) {
10861 struct community_list
*list
= output_arg
;
10863 if (!community_list_match(pi
->attr
->community
,
10867 if (type
== bgp_show_type_community_list_exact
) {
10868 struct community_list
*list
= output_arg
;
10870 if (!community_list_exact_match(
10871 pi
->attr
->community
, list
))
10874 if (type
== bgp_show_type_lcommunity
) {
10875 struct lcommunity
*lcom
= output_arg
;
10877 if (!pi
->attr
->lcommunity
10878 || !lcommunity_match(pi
->attr
->lcommunity
,
10883 if (type
== bgp_show_type_lcommunity_exact
) {
10884 struct lcommunity
*lcom
= output_arg
;
10886 if (!pi
->attr
->lcommunity
10887 || !lcommunity_cmp(pi
->attr
->lcommunity
,
10891 if (type
== bgp_show_type_lcommunity_list
) {
10892 struct community_list
*list
= output_arg
;
10894 if (!lcommunity_list_match(pi
->attr
->lcommunity
,
10899 == bgp_show_type_lcommunity_list_exact
) {
10900 struct community_list
*list
= output_arg
;
10902 if (!lcommunity_list_exact_match(
10903 pi
->attr
->lcommunity
, list
))
10906 if (type
== bgp_show_type_lcommunity_all
) {
10907 if (!pi
->attr
->lcommunity
)
10910 if (type
== bgp_show_type_dampend_paths
10911 || type
== bgp_show_type_damp_neighbor
) {
10912 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
)
10913 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
10917 if (!use_json
&& header
) {
10919 "BGP table version is %" PRIu64
10920 ", local router ID is %pI4, vrf id ",
10921 table
->version
, &bgp
->router_id
);
10922 if (bgp
->vrf_id
== VRF_UNKNOWN
)
10923 vty_out(vty
, "%s", VRFID_NONE_STR
);
10925 vty_out(vty
, "%u", bgp
->vrf_id
);
10926 vty_out(vty
, "\n");
10927 vty_out(vty
, "Default local pref %u, ",
10928 bgp
->default_local_pref
);
10929 vty_out(vty
, "local AS %u\n", bgp
->as
);
10930 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
10931 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
10932 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
10933 vty_out(vty
, BGP_SHOW_RPKI_HEADER
);
10934 if (type
== bgp_show_type_dampend_paths
10935 || type
== bgp_show_type_damp_neighbor
)
10936 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
10937 else if (type
== bgp_show_type_flap_statistics
10938 || type
== bgp_show_type_flap_neighbor
)
10939 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
10941 vty_out(vty
, (wide
? BGP_SHOW_HEADER_WIDE
10942 : BGP_SHOW_HEADER
));
10945 if (rd
!= NULL
&& !display
&& !output_count
) {
10948 "Route Distinguisher: %s\n",
10951 if (type
== bgp_show_type_dampend_paths
10952 || type
== bgp_show_type_damp_neighbor
)
10953 damp_route_vty_out(vty
, dest_p
, pi
, display
,
10954 AFI_IP
, safi
, use_json
,
10956 else if (type
== bgp_show_type_flap_statistics
10957 || type
== bgp_show_type_flap_neighbor
)
10958 flap_route_vty_out(vty
, dest_p
, pi
, display
,
10959 AFI_IP
, safi
, use_json
,
10962 if (CHECK_FLAG(show_flags
, BGP_SHOW_OPT_DETAIL
))
10963 route_vty_out_detail(
10964 vty
, bgp
, dest
, pi
,
10965 family2afi(dest_p
->family
),
10966 safi
, RPKI_NOT_BEING_USED
,
10969 route_vty_out(vty
, dest_p
, pi
, display
,
10970 safi
, json_paths
, wide
);
10980 /* encode prefix */
10981 if (dest_p
->family
== AF_FLOWSPEC
) {
10982 char retstr
[BGP_FLOWSPEC_STRING_DISPLAY_MAX
];
10985 bgp_fs_nlri_get_string(
10987 dest_p
->u
.prefix_flowspec
.ptr
,
10988 dest_p
->u
.prefix_flowspec
.prefixlen
,
10989 retstr
, NLRI_STRING_FORMAT_MIN
, NULL
,
10990 family2afi(dest_p
->u
10991 .prefix_flowspec
.family
));
10993 vty_out(vty
, "\"%s/%d\": ", retstr
,
10994 dest_p
->u
.prefix_flowspec
10997 vty_out(vty
, ",\"%s/%d\": ", retstr
,
10998 dest_p
->u
.prefix_flowspec
11002 vty_out(vty
, "\"%pFX\": ", dest_p
);
11004 vty_out(vty
, ",\"%pFX\": ", dest_p
);
11007 json_object_to_json_string_ext(
11008 json_paths
, JSON_C_TO_STRING_PRETTY
));
11009 json_object_free(json_paths
);
11013 json_object_free(json_paths
);
11017 output_count
+= *output_cum
;
11018 *output_cum
= output_count
;
11021 total_count
+= *total_cum
;
11022 *total_cum
= total_count
;
11026 vty_out(vty
, " }%s ", (is_last
? "" : ","));
11030 for (i
= 0; i
< *json_header_depth
; ++i
)
11031 vty_out(vty
, " } ");
11033 vty_out(vty
, "\n");
11037 /* No route is displayed */
11038 if (output_count
== 0) {
11039 if (type
== bgp_show_type_normal
)
11041 "No BGP prefixes displayed, %ld exist\n",
11045 "\nDisplayed %ld routes and %ld total paths\n",
11046 output_count
, total_count
);
11050 return CMD_SUCCESS
;
11053 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
11054 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
11055 enum bgp_show_type type
, void *output_arg
, bool use_json
)
11057 struct bgp_dest
*dest
, *next
;
11058 unsigned long output_cum
= 0;
11059 unsigned long total_cum
= 0;
11060 unsigned long json_header_depth
= 0;
11061 struct bgp_table
*itable
;
11063 uint16_t show_flags
= 0;
11065 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
11068 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11070 for (dest
= bgp_table_top(table
); dest
; dest
= next
) {
11071 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11073 next
= bgp_route_next(dest
);
11074 if (prd_match
&& memcmp(dest_p
->u
.val
, prd_match
->val
, 8) != 0)
11077 itable
= bgp_dest_get_bgp_table_info(dest
);
11078 if (itable
!= NULL
) {
11079 struct prefix_rd prd
;
11080 char rd
[RD_ADDRSTRLEN
];
11082 memcpy(&prd
, dest_p
, sizeof(struct prefix_rd
));
11083 prefix_rd2str(&prd
, rd
, sizeof(rd
));
11084 bgp_show_table(vty
, bgp
, safi
, itable
, type
, output_arg
,
11085 rd
, next
== NULL
, &output_cum
,
11086 &total_cum
, &json_header_depth
,
11087 show_flags
, RPKI_NOT_BEING_USED
);
11093 if (output_cum
== 0)
11094 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
11098 "\nDisplayed %ld routes and %ld total paths\n",
11099 output_cum
, total_cum
);
11101 return CMD_SUCCESS
;
11103 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
11104 enum bgp_show_type type
, void *output_arg
,
11105 uint16_t show_flags
, enum rpki_states rpki_target_state
)
11107 struct bgp_table
*table
;
11108 unsigned long json_header_depth
= 0;
11109 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11112 bgp
= bgp_get_default();
11117 vty_out(vty
, "No BGP process is configured\n");
11119 vty_out(vty
, "{}\n");
11120 return CMD_WARNING
;
11123 table
= bgp
->rib
[afi
][safi
];
11124 /* use MPLS and ENCAP specific shows until they are merged */
11125 if (safi
== SAFI_MPLS_VPN
) {
11126 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
11127 output_arg
, use_json
);
11130 if (safi
== SAFI_FLOWSPEC
&& type
== bgp_show_type_detail
) {
11131 return bgp_show_table_flowspec(vty
, bgp
, afi
, table
, type
,
11132 output_arg
, use_json
,
11135 /* labeled-unicast routes live in the unicast table */
11136 else if (safi
== SAFI_LABELED_UNICAST
)
11137 safi
= SAFI_UNICAST
;
11139 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, NULL
, 1,
11140 NULL
, NULL
, &json_header_depth
, show_flags
,
11141 rpki_target_state
);
11144 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
11145 safi_t safi
, uint16_t show_flags
)
11147 struct listnode
*node
, *nnode
;
11150 bool route_output
= false;
11151 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11154 vty_out(vty
, "{\n");
11156 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
11157 route_output
= true;
11160 vty_out(vty
, ",\n");
11164 vty_out(vty
, "\"%s\":",
11165 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
11169 vty_out(vty
, "\nInstance %s:\n",
11170 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
11174 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
11175 show_flags
, RPKI_NOT_BEING_USED
);
11179 vty_out(vty
, "}\n");
11180 else if (!route_output
)
11181 vty_out(vty
, "%% BGP instance not found\n");
11184 /* Header of detailed BGP route information */
11185 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
11186 struct bgp_dest
*dest
, struct prefix_rd
*prd
,
11187 afi_t afi
, safi_t safi
, json_object
*json
)
11189 struct bgp_path_info
*pi
;
11190 const struct prefix
*p
;
11192 struct listnode
*node
, *nnode
;
11193 char buf1
[RD_ADDRSTRLEN
];
11194 char prefix_str
[BUFSIZ
];
11198 int accept_own
= 0;
11199 int route_filter_translated_v4
= 0;
11200 int route_filter_v4
= 0;
11201 int route_filter_translated_v6
= 0;
11202 int route_filter_v6
= 0;
11203 int llgr_stale
= 0;
11205 int accept_own_nexthop
= 0;
11208 int no_advertise
= 0;
11212 int has_valid_label
= 0;
11213 mpls_label_t label
= 0;
11214 json_object
*json_adv_to
= NULL
;
11216 p
= bgp_dest_get_prefix(dest
);
11217 has_valid_label
= bgp_is_valid_label(&dest
->local_label
);
11219 if (has_valid_label
)
11220 label
= label_pton(&dest
->local_label
);
11222 if (safi
== SAFI_EVPN
) {
11225 vty_out(vty
, "BGP routing table entry for %s%s%pFX\n",
11226 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
))
11228 prd
? ":" : "", (struct prefix_evpn
*)p
);
11230 json_object_string_add(json
, "rd",
11231 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
)) :
11233 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
11238 "BGP routing table entry for %s%s%pFX, version %" PRIu64
11240 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
11241 ? prefix_rd2str(prd
, buf1
,
11244 safi
== SAFI_MPLS_VPN
? ":" : "", p
,
11248 json_object_string_add(json
, "prefix",
11249 prefix2str(p
, prefix_str
, sizeof(prefix_str
)));
11250 json_object_int_add(json
, "version", dest
->version
);
11255 if (has_valid_label
) {
11257 json_object_int_add(json
, "localLabel", label
);
11259 vty_out(vty
, "Local label: %d\n", label
);
11263 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
11264 vty_out(vty
, "not allocated\n");
11266 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
11268 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
11270 if (bgp_path_suppressed(pi
))
11273 if (pi
->attr
->community
== NULL
)
11276 no_advertise
+= community_include(
11277 pi
->attr
->community
, COMMUNITY_NO_ADVERTISE
);
11278 no_export
+= community_include(pi
->attr
->community
,
11279 COMMUNITY_NO_EXPORT
);
11280 local_as
+= community_include(pi
->attr
->community
,
11281 COMMUNITY_LOCAL_AS
);
11282 accept_own
+= community_include(pi
->attr
->community
,
11283 COMMUNITY_ACCEPT_OWN
);
11284 route_filter_translated_v4
+= community_include(
11285 pi
->attr
->community
,
11286 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4
);
11287 route_filter_translated_v6
+= community_include(
11288 pi
->attr
->community
,
11289 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6
);
11290 route_filter_v4
+= community_include(
11291 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v4
);
11292 route_filter_v6
+= community_include(
11293 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v6
);
11294 llgr_stale
+= community_include(pi
->attr
->community
,
11295 COMMUNITY_LLGR_STALE
);
11296 no_llgr
+= community_include(pi
->attr
->community
,
11297 COMMUNITY_NO_LLGR
);
11298 accept_own_nexthop
+=
11299 community_include(pi
->attr
->community
,
11300 COMMUNITY_ACCEPT_OWN_NEXTHOP
);
11301 blackhole
+= community_include(pi
->attr
->community
,
11302 COMMUNITY_BLACKHOLE
);
11303 no_peer
+= community_include(pi
->attr
->community
,
11304 COMMUNITY_NO_PEER
);
11309 vty_out(vty
, "Paths: (%d available", count
);
11311 vty_out(vty
, ", best #%d", best
);
11312 if (safi
== SAFI_UNICAST
) {
11313 if (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
11314 vty_out(vty
, ", table %s",
11317 vty_out(vty
, ", vrf %s",
11321 vty_out(vty
, ", no best path");
11325 ", accept own local route exported and imported in different VRF");
11326 else if (route_filter_translated_v4
)
11328 ", mark translated RTs for VPNv4 route filtering");
11329 else if (route_filter_v4
)
11331 ", attach RT as-is for VPNv4 route filtering");
11332 else if (route_filter_translated_v6
)
11334 ", mark translated RTs for VPNv6 route filtering");
11335 else if (route_filter_v6
)
11337 ", attach RT as-is for VPNv6 route filtering");
11338 else if (llgr_stale
)
11340 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
11343 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
11344 else if (accept_own_nexthop
)
11346 ", accept local nexthop");
11347 else if (blackhole
)
11348 vty_out(vty
, ", inform peer to blackhole prefix");
11349 else if (no_export
)
11350 vty_out(vty
, ", not advertised to EBGP peer");
11351 else if (no_advertise
)
11352 vty_out(vty
, ", not advertised to any peer");
11354 vty_out(vty
, ", not advertised outside local AS");
11357 ", inform EBGP peer not to advertise to their EBGP peers");
11361 ", Advertisements suppressed by an aggregate.");
11362 vty_out(vty
, ")\n");
11365 /* If we are not using addpath then we can display Advertised to and
11367 * show what peers we advertised the bestpath to. If we are using
11369 * though then we must display Advertised to on a path-by-path basis. */
11370 if (!bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
11371 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
11372 if (bgp_adj_out_lookup(peer
, dest
, 0)) {
11373 if (json
&& !json_adv_to
)
11374 json_adv_to
= json_object_new_object();
11376 route_vty_out_advertised_to(
11378 " Advertised to non peer-group peers:\n ",
11385 json_object_object_add(json
, "advertisedTo",
11390 vty_out(vty
, " Not advertised to any peer");
11391 vty_out(vty
, "\n");
11396 static void bgp_show_path_info(struct prefix_rd
*pfx_rd
,
11397 struct bgp_dest
*bgp_node
, struct vty
*vty
,
11398 struct bgp
*bgp
, afi_t afi
, safi_t safi
,
11399 json_object
*json
, enum bgp_path_type pathtype
,
11400 int *display
, enum rpki_states rpki_target_state
)
11402 struct bgp_path_info
*pi
;
11404 char rdbuf
[RD_ADDRSTRLEN
];
11405 json_object
*json_header
= NULL
;
11406 json_object
*json_paths
= NULL
;
11407 const struct prefix
*p
= bgp_dest_get_prefix(bgp_node
);
11409 for (pi
= bgp_dest_get_bgp_path_info(bgp_node
); pi
; pi
= pi
->next
) {
11410 enum rpki_states rpki_curr_state
= RPKI_NOT_BEING_USED
;
11412 if (p
->family
== AF_INET
|| p
->family
== AF_INET6
)
11413 rpki_curr_state
= hook_call(bgp_rpki_prefix_status
,
11414 pi
->peer
, pi
->attr
, p
);
11416 if (rpki_target_state
!= RPKI_NOT_BEING_USED
11417 && rpki_curr_state
!= rpki_target_state
)
11420 if (json
&& !json_paths
) {
11421 /* Instantiate json_paths only if path is valid */
11422 json_paths
= json_object_new_array();
11424 prefix_rd2str(pfx_rd
, rdbuf
, sizeof(rdbuf
));
11425 json_header
= json_object_new_object();
11427 json_header
= json
;
11431 route_vty_out_detail_header(
11432 vty
, bgp
, bgp_node
, pfx_rd
,
11433 AFI_IP
, safi
, json_header
);
11438 if (pathtype
== BGP_PATH_SHOW_ALL
11439 || (pathtype
== BGP_PATH_SHOW_BESTPATH
11440 && CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
11441 || (pathtype
== BGP_PATH_SHOW_MULTIPATH
11442 && (CHECK_FLAG(pi
->flags
, BGP_PATH_MULTIPATH
)
11443 || CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))))
11444 route_vty_out_detail(vty
, bgp
, bgp_node
, pi
, AFI_IP
,
11445 safi
, rpki_curr_state
, json_paths
);
11448 if (json
&& json_paths
) {
11449 json_object_object_add(json_header
, "paths", json_paths
);
11452 json_object_object_add(json
, rdbuf
, json_header
);
11456 /* Display specified route of BGP table. */
11457 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
11458 struct bgp_table
*rib
, const char *ip_str
,
11459 afi_t afi
, safi_t safi
,
11460 enum rpki_states rpki_target_state
,
11461 struct prefix_rd
*prd
, int prefix_check
,
11462 enum bgp_path_type pathtype
, bool use_json
)
11466 struct prefix match
;
11467 struct bgp_dest
*dest
;
11468 struct bgp_dest
*rm
;
11469 struct bgp_table
*table
;
11470 json_object
*json
= NULL
;
11471 json_object
*json_paths
= NULL
;
11473 /* Check IP address argument. */
11474 ret
= str2prefix(ip_str
, &match
);
11476 vty_out(vty
, "address is malformed\n");
11477 return CMD_WARNING
;
11480 match
.family
= afi2family(afi
);
11483 json
= json_object_new_object();
11485 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
) {
11486 for (dest
= bgp_table_top(rib
); dest
;
11487 dest
= bgp_route_next(dest
)) {
11488 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11490 if (prd
&& memcmp(dest_p
->u
.val
, prd
->val
, 8) != 0)
11492 table
= bgp_dest_get_bgp_table_info(dest
);
11496 rm
= bgp_node_match(table
, &match
);
11500 const struct prefix
*rm_p
= bgp_dest_get_prefix(rm
);
11502 && rm_p
->prefixlen
!= match
.prefixlen
) {
11503 bgp_dest_unlock_node(rm
);
11507 bgp_show_path_info((struct prefix_rd
*)dest_p
, rm
, vty
,
11508 bgp
, afi
, safi
, json
, pathtype
,
11509 &display
, rpki_target_state
);
11511 bgp_dest_unlock_node(rm
);
11513 } else if (safi
== SAFI_EVPN
) {
11514 struct bgp_dest
*longest_pfx
;
11515 bool is_exact_pfxlen_match
= false;
11517 for (dest
= bgp_table_top(rib
); dest
;
11518 dest
= bgp_route_next(dest
)) {
11519 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11521 if (prd
&& memcmp(&dest_p
->u
.val
, prd
->val
, 8) != 0)
11523 table
= bgp_dest_get_bgp_table_info(dest
);
11527 longest_pfx
= NULL
;
11528 is_exact_pfxlen_match
= false;
11530 * Search through all the prefixes for a match. The
11531 * pfx's are enumerated in ascending order of pfxlens.
11532 * So, the last pfx match is the longest match. Set
11533 * is_exact_pfxlen_match when we get exact pfxlen match
11535 for (rm
= bgp_table_top(table
); rm
;
11536 rm
= bgp_route_next(rm
)) {
11537 const struct prefix
*rm_p
=
11538 bgp_dest_get_prefix(rm
);
11540 * Get prefixlen of the ip-prefix within type5
11543 if (evpn_type5_prefix_match(rm_p
, &match
)
11547 bgp_evpn_get_type5_prefixlen(
11549 if (type5_pfxlen
== match
.prefixlen
) {
11550 is_exact_pfxlen_match
= true;
11551 bgp_dest_unlock_node(rm
);
11560 if (prefix_check
&& !is_exact_pfxlen_match
)
11564 bgp_dest_lock_node(rm
);
11566 bgp_show_path_info((struct prefix_rd
*)dest_p
, rm
, vty
,
11567 bgp
, afi
, safi
, json
, pathtype
,
11568 &display
, rpki_target_state
);
11570 bgp_dest_unlock_node(rm
);
11572 } else if (safi
== SAFI_FLOWSPEC
) {
11574 json_paths
= json_object_new_array();
11576 display
= bgp_flowspec_display_match_per_ip(afi
, rib
,
11577 &match
, prefix_check
,
11583 json_object_object_add(json
, "paths",
11586 json_object_free(json_paths
);
11589 dest
= bgp_node_match(rib
, &match
);
11590 if (dest
!= NULL
) {
11591 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11593 || dest_p
->prefixlen
== match
.prefixlen
) {
11594 bgp_show_path_info(NULL
, dest
, vty
, bgp
, afi
,
11595 safi
, json
, pathtype
,
11596 &display
, rpki_target_state
);
11599 bgp_dest_unlock_node(dest
);
11604 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
11605 json
, JSON_C_TO_STRING_PRETTY
|
11606 JSON_C_TO_STRING_NOSLASHESCAPE
));
11607 json_object_free(json
);
11610 vty_out(vty
, "%% Network not in table\n");
11611 return CMD_WARNING
;
11615 return CMD_SUCCESS
;
11618 /* Display specified route of Main RIB */
11619 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
11620 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
11621 int prefix_check
, enum bgp_path_type pathtype
,
11622 enum rpki_states rpki_target_state
, bool use_json
)
11625 bgp
= bgp_get_default();
11628 vty_out(vty
, "No BGP process is configured\n");
11630 vty_out(vty
, "{}\n");
11631 return CMD_WARNING
;
11635 /* labeled-unicast routes live in the unicast table */
11636 if (safi
== SAFI_LABELED_UNICAST
)
11637 safi
= SAFI_UNICAST
;
11639 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
11640 afi
, safi
, rpki_target_state
, prd
,
11641 prefix_check
, pathtype
, use_json
);
11644 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
11645 struct cmd_token
**argv
, bool exact
, afi_t afi
,
11646 safi_t safi
, bool uj
)
11648 struct lcommunity
*lcom
;
11653 uint16_t show_flags
= 0;
11657 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11659 b
= buffer_new(1024);
11660 for (i
= 0; i
< argc
; i
++) {
11662 buffer_putc(b
, ' ');
11664 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
11666 buffer_putstr(b
, argv
[i
]->arg
);
11670 buffer_putc(b
, '\0');
11672 str
= buffer_getstr(b
);
11675 lcom
= lcommunity_str2com(str
);
11676 XFREE(MTYPE_TMP
, str
);
11678 vty_out(vty
, "%% Large-community malformed\n");
11679 return CMD_WARNING
;
11682 ret
= bgp_show(vty
, bgp
, afi
, safi
,
11683 (exact
? bgp_show_type_lcommunity_exact
11684 : bgp_show_type_lcommunity
),
11685 lcom
, show_flags
, RPKI_NOT_BEING_USED
);
11687 lcommunity_free(&lcom
);
11691 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
11692 const char *lcom
, bool exact
, afi_t afi
,
11693 safi_t safi
, bool uj
)
11695 struct community_list
*list
;
11696 uint16_t show_flags
= 0;
11699 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11702 list
= community_list_lookup(bgp_clist
, lcom
, 0,
11703 LARGE_COMMUNITY_LIST_MASTER
);
11704 if (list
== NULL
) {
11705 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
11707 return CMD_WARNING
;
11710 return bgp_show(vty
, bgp
, afi
, safi
,
11711 (exact
? bgp_show_type_lcommunity_list_exact
11712 : bgp_show_type_lcommunity_list
),
11713 list
, show_flags
, RPKI_NOT_BEING_USED
);
11716 DEFUN (show_ip_bgp_large_community_list
,
11717 show_ip_bgp_large_community_list_cmd
,
11718 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community-list <(1-500)|LCOMMUNITY_LIST_NAME> [exact-match] [json]",
11722 BGP_INSTANCE_HELP_STR
11724 BGP_SAFI_WITH_LABEL_HELP_STR
11725 "Display routes matching the large-community-list\n"
11726 "large-community-list number\n"
11727 "large-community-list name\n"
11728 "Exact match of the large-communities\n"
11731 afi_t afi
= AFI_IP6
;
11732 safi_t safi
= SAFI_UNICAST
;
11734 bool exact_match
= 0;
11735 struct bgp
*bgp
= NULL
;
11736 bool uj
= use_json(argc
, argv
);
11741 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11744 return CMD_WARNING
;
11746 argv_find(argv
, argc
, "large-community-list", &idx
);
11748 const char *clist_number_or_name
= argv
[++idx
]->arg
;
11750 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
11753 return bgp_show_lcommunity_list(vty
, bgp
, clist_number_or_name
,
11754 exact_match
, afi
, safi
, uj
);
11756 DEFUN (show_ip_bgp_large_community
,
11757 show_ip_bgp_large_community_cmd
,
11758 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [<AA:BB:CC> [exact-match]] [json]",
11762 BGP_INSTANCE_HELP_STR
11764 BGP_SAFI_WITH_LABEL_HELP_STR
11765 "Display routes matching the large-communities\n"
11766 "List of large-community numbers\n"
11767 "Exact match of the large-communities\n"
11770 afi_t afi
= AFI_IP6
;
11771 safi_t safi
= SAFI_UNICAST
;
11773 bool exact_match
= 0;
11774 struct bgp
*bgp
= NULL
;
11775 bool uj
= use_json(argc
, argv
);
11776 uint16_t show_flags
= 0;
11780 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11783 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11786 return CMD_WARNING
;
11788 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
)) {
11789 if (argv_find(argv
, argc
, "exact-match", &idx
))
11791 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
,
11792 exact_match
, afi
, safi
, uj
);
11794 return bgp_show(vty
, bgp
, afi
, safi
,
11795 bgp_show_type_lcommunity_all
, NULL
, show_flags
,
11796 RPKI_NOT_BEING_USED
);
11799 static int bgp_table_stats_single(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11800 safi_t safi
, struct json_object
*json_array
);
11801 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11802 safi_t safi
, struct json_object
*json
);
11805 DEFUN(show_ip_bgp_statistics_all
, show_ip_bgp_statistics_all_cmd
,
11806 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
11807 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
11808 "Display number of prefixes for all afi/safi\n" JSON_STR
)
11810 bool uj
= use_json(argc
, argv
);
11811 struct bgp
*bgp
= NULL
;
11812 safi_t safi
= SAFI_UNICAST
;
11813 afi_t afi
= AFI_IP6
;
11815 struct json_object
*json_all
= NULL
;
11816 struct json_object
*json_afi_safi
= NULL
;
11818 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11821 return CMD_WARNING
;
11824 json_all
= json_object_new_object();
11826 FOREACH_AFI_SAFI (afi
, safi
) {
11828 * So limit output to those afi/safi pairs that
11829 * actually have something interesting in them
11831 if (strmatch(get_afi_safi_str(afi
, safi
, true),
11836 json_afi_safi
= json_object_new_array();
11837 json_object_object_add(
11839 get_afi_safi_str(afi
, safi
, true),
11842 json_afi_safi
= NULL
;
11845 bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
11850 json_object_to_json_string_ext(
11851 json_all
, JSON_C_TO_STRING_PRETTY
));
11852 json_object_free(json_all
);
11855 return CMD_SUCCESS
;
11858 /* BGP route print out function without JSON */
11859 DEFUN (show_ip_bgp_l2vpn_evpn_statistics
,
11860 show_ip_bgp_l2vpn_evpn_statistics_cmd
,
11861 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
11865 BGP_INSTANCE_HELP_STR
11868 "BGP RIB advertisement statistics\n"
11871 afi_t afi
= AFI_IP6
;
11872 safi_t safi
= SAFI_UNICAST
;
11873 struct bgp
*bgp
= NULL
;
11875 bool uj
= use_json(argc
, argv
);
11876 struct json_object
*json_afi_safi
= NULL
, *json
= NULL
;
11878 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11881 return CMD_WARNING
;
11884 json_afi_safi
= json_object_new_array();
11886 json_afi_safi
= NULL
;
11888 ret
= bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
11891 json
= json_object_new_object();
11892 json_object_object_add(json
, get_afi_safi_str(afi
, safi
, true),
11894 vty_out(vty
, "%s", json_object_to_json_string_ext(
11895 json
, JSON_C_TO_STRING_PRETTY
));
11896 json_object_free(json
);
11901 /* BGP route print out function without JSON */
11902 DEFUN(show_ip_bgp_afi_safi_statistics
, show_ip_bgp_afi_safi_statistics_cmd
,
11903 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
11904 " [" BGP_SAFI_WITH_LABEL_CMD_STR
11906 statistics [json]",
11907 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
11908 BGP_SAFI_WITH_LABEL_HELP_STR
11909 "BGP RIB advertisement statistics\n" JSON_STR
)
11911 afi_t afi
= AFI_IP6
;
11912 safi_t safi
= SAFI_UNICAST
;
11913 struct bgp
*bgp
= NULL
;
11915 bool uj
= use_json(argc
, argv
);
11916 struct json_object
*json_afi_safi
= NULL
, *json
= NULL
;
11918 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11921 return CMD_WARNING
;
11924 json_afi_safi
= json_object_new_array();
11926 json_afi_safi
= NULL
;
11928 ret
= bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
11931 json
= json_object_new_object();
11932 json_object_object_add(json
, get_afi_safi_str(afi
, safi
, true),
11935 json_object_to_json_string_ext(
11936 json
, JSON_C_TO_STRING_PRETTY
));
11937 json_object_free(json
);
11942 /* BGP route print out function without JSON */
11943 DEFPY(show_ip_bgp
, show_ip_bgp_cmd
,
11944 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
11945 " [" BGP_SAFI_WITH_LABEL_CMD_STR
11947 <[all$all] dampening <parameters>\
11951 |community-list <(1-500)|COMMUNITY_LIST_NAME> [exact-match]\
11952 |A.B.C.D/M longer-prefixes\
11953 |X:X::X:X/M longer-prefixes\
11955 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
11956 BGP_SAFI_WITH_LABEL_HELP_STR
11957 "Display the entries for all address families\n"
11958 "Display detailed information about dampening\n"
11959 "Display detail of configured dampening parameters\n"
11960 "Display routes matching the route-map\n"
11961 "A route-map to match on\n"
11962 "Display routes conforming to the prefix-list\n"
11963 "Prefix-list name\n"
11964 "Display routes conforming to the filter-list\n"
11965 "Regular expression access list name\n"
11966 "Display routes matching the community-list\n"
11967 "community-list number\n"
11968 "community-list name\n"
11969 "Exact match of the communities\n"
11971 "Display route and more specific routes\n"
11973 "Display route and more specific routes\n")
11975 afi_t afi
= AFI_IP6
;
11976 safi_t safi
= SAFI_UNICAST
;
11977 int exact_match
= 0;
11978 struct bgp
*bgp
= NULL
;
11980 uint16_t show_flags
= 0;
11982 /* [<ipv4|ipv6> [all]] */
11984 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
11985 if (argv_find(argv
, argc
, "ipv4", &idx
))
11986 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
11988 if (argv_find(argv
, argc
, "ipv6", &idx
))
11989 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
11992 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11995 return CMD_WARNING
;
11997 if (argv_find(argv
, argc
, "dampening", &idx
)) {
11998 if (argv_find(argv
, argc
, "parameters", &idx
))
11999 return bgp_show_dampening_parameters(vty
, afi
, safi
,
12003 if (argv_find(argv
, argc
, "prefix-list", &idx
))
12004 return bgp_show_prefix_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
12005 safi
, bgp_show_type_prefix_list
);
12007 if (argv_find(argv
, argc
, "filter-list", &idx
))
12008 return bgp_show_filter_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
12009 safi
, bgp_show_type_filter_list
);
12011 if (argv_find(argv
, argc
, "route-map", &idx
))
12012 return bgp_show_route_map(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
12013 safi
, bgp_show_type_route_map
);
12015 if (argv_find(argv
, argc
, "community-list", &idx
)) {
12016 const char *clist_number_or_name
= argv
[++idx
]->arg
;
12017 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
12019 return bgp_show_community_list(vty
, bgp
, clist_number_or_name
,
12020 exact_match
, afi
, safi
);
12022 /* prefix-longer */
12023 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
12024 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
12025 return bgp_show_prefix_longer(vty
, bgp
, argv
[idx
]->arg
, afi
,
12027 bgp_show_type_prefix_longer
);
12029 return CMD_WARNING
;
12032 /* BGP route print out function with JSON */
12033 DEFPY(show_ip_bgp_json
, show_ip_bgp_json_cmd
,
12034 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12035 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12039 |dampening <flap-statistics|dampened-paths>\
12040 |community [AA:NN|local-AS|no-advertise|no-export\
12041 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
12042 |accept-own|accept-own-nexthop|route-filter-v6\
12043 |route-filter-v4|route-filter-translated-v6\
12044 |route-filter-translated-v4] [exact-match]\
12045 |rpki <invalid|valid|notfound>\
12046 |version (1-4294967295)\
12048 ] [json$uj [detail$detail] | wide$wide]",
12049 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12050 BGP_SAFI_WITH_LABEL_HELP_STR
12051 "Display the entries for all address families\n"
12052 "Display only routes with non-natural netmasks\n"
12053 "Display detailed information about dampening\n"
12054 "Display flap statistics of routes\n"
12055 "Display paths suppressed due to dampening\n"
12056 "Display routes matching the communities\n" COMMUNITY_AANN_STR
12057 "Do not send outside local AS (well-known community)\n"
12058 "Do not advertise to any peer (well-known community)\n"
12059 "Do not export to next AS (well-known community)\n"
12060 "Graceful shutdown (well-known community)\n"
12061 "Do not export to any peer (well-known community)\n"
12062 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
12063 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
12064 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
12065 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
12066 "Should accept VPN route with local nexthop (well-known community)\n"
12067 "RT VPNv6 route filtering (well-known community)\n"
12068 "RT VPNv4 route filtering (well-known community)\n"
12069 "RT translated VPNv6 route filtering (well-known community)\n"
12070 "RT translated VPNv4 route filtering (well-known community)\n"
12071 "Exact match of the communities\n"
12072 "RPKI route types\n"
12073 "A valid path as determined by rpki\n"
12074 "A invalid path as determined by rpki\n"
12075 "A path that has no rpki data\n"
12076 "Display prefixes with matching version numbers\n"
12077 "Version number and above\n"
12078 "Display prefixes with matching BGP community alias\n"
12079 "BGP community alias\n" JSON_STR
12080 "Display detailed version of JSON output\n"
12081 "Increase table width for longer prefixes\n")
12083 afi_t afi
= AFI_IP6
;
12084 safi_t safi
= SAFI_UNICAST
;
12085 enum bgp_show_type sh_type
= bgp_show_type_normal
;
12086 struct bgp
*bgp
= NULL
;
12088 int exact_match
= 0;
12089 char *community
= NULL
;
12090 char *prefix_version
= NULL
;
12091 char *bgp_community_alias
= NULL
;
12093 uint16_t show_flags
= 0;
12094 enum rpki_states rpki_target_state
= RPKI_NOT_BEING_USED
;
12098 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12102 SET_FLAG(show_flags
, BGP_SHOW_OPT_DETAIL
);
12104 /* [<ipv4|ipv6> [all]] */
12106 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
12108 if (argv_find(argv
, argc
, "ipv4", &idx
))
12109 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
12111 if (argv_find(argv
, argc
, "ipv6", &idx
))
12112 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
12116 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
12118 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12121 return CMD_WARNING
;
12123 if (argv_find(argv
, argc
, "cidr-only", &idx
))
12124 sh_type
= bgp_show_type_cidr_only
;
12126 if (argv_find(argv
, argc
, "dampening", &idx
)) {
12127 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
12128 sh_type
= bgp_show_type_dampend_paths
;
12129 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
12130 sh_type
= bgp_show_type_flap_statistics
;
12133 if (argv_find(argv
, argc
, "community", &idx
)) {
12134 char *maybecomm
= NULL
;
12136 if (idx
+ 1 < argc
) {
12137 if (argv
[idx
+ 1]->type
== VARIABLE_TKN
)
12138 maybecomm
= argv
[idx
+ 1]->arg
;
12140 maybecomm
= argv
[idx
+ 1]->text
;
12143 if (maybecomm
&& !strmatch(maybecomm
, "json")
12144 && !strmatch(maybecomm
, "exact-match"))
12145 community
= maybecomm
;
12147 if (argv_find(argv
, argc
, "exact-match", &idx
))
12151 sh_type
= bgp_show_type_community_all
;
12154 if (argv_find(argv
, argc
, "rpki", &idx
)) {
12155 sh_type
= bgp_show_type_rpki
;
12156 if (argv_find(argv
, argc
, "valid", &idx
))
12157 rpki_target_state
= RPKI_VALID
;
12158 else if (argv_find(argv
, argc
, "invalid", &idx
))
12159 rpki_target_state
= RPKI_INVALID
;
12162 /* Display prefixes with matching version numbers */
12163 if (argv_find(argv
, argc
, "version", &idx
)) {
12164 sh_type
= bgp_show_type_prefix_version
;
12165 prefix_version
= argv
[idx
+ 1]->arg
;
12168 /* Display prefixes with matching BGP community alias */
12169 if (argv_find(argv
, argc
, "alias", &idx
)) {
12170 sh_type
= bgp_show_type_community_alias
;
12171 bgp_community_alias
= argv
[idx
+ 1]->arg
;
12175 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
12177 return bgp_show_community(vty
, bgp
, community
,
12178 exact_match
, afi
, safi
,
12180 else if (prefix_version
)
12181 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
,
12182 prefix_version
, show_flags
,
12183 rpki_target_state
);
12184 else if (bgp_community_alias
)
12185 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
,
12186 bgp_community_alias
, show_flags
,
12187 rpki_target_state
);
12189 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
, NULL
,
12190 show_flags
, rpki_target_state
);
12192 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
12196 vty_out(vty
, "{\n");
12198 if (CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
12199 || CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
)) {
12200 afi
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
12203 FOREACH_SAFI (safi
) {
12204 if (!bgp_afi_safi_peer_exists(bgp
, afi
, safi
))
12211 vty_out(vty
, ",\n");
12212 vty_out(vty
, "\"%s\":{\n",
12213 get_afi_safi_str(afi
, safi
,
12217 "\nFor address family: %s\n",
12218 get_afi_safi_str(afi
, safi
,
12222 bgp_show_community(vty
, bgp
, community
,
12225 else if (prefix_version
)
12226 return bgp_show(vty
, bgp
, afi
, safi
,
12227 sh_type
, prefix_version
,
12229 rpki_target_state
);
12230 else if (bgp_community_alias
)
12232 vty
, bgp
, afi
, safi
, sh_type
,
12233 bgp_community_alias
, show_flags
,
12234 rpki_target_state
);
12236 bgp_show(vty
, bgp
, afi
, safi
, sh_type
,
12238 rpki_target_state
);
12240 vty_out(vty
, "}\n");
12243 /* show <ip> bgp all: for each AFI and SAFI*/
12244 FOREACH_AFI_SAFI (afi
, safi
) {
12245 if (!bgp_afi_safi_peer_exists(bgp
, afi
, safi
))
12252 vty_out(vty
, ",\n");
12254 vty_out(vty
, "\"%s\":{\n",
12255 get_afi_safi_str(afi
, safi
,
12259 "\nFor address family: %s\n",
12260 get_afi_safi_str(afi
, safi
,
12264 bgp_show_community(vty
, bgp
, community
,
12267 else if (prefix_version
)
12268 return bgp_show(vty
, bgp
, afi
, safi
,
12269 sh_type
, prefix_version
,
12271 rpki_target_state
);
12273 bgp_show(vty
, bgp
, afi
, safi
, sh_type
,
12275 rpki_target_state
);
12277 vty_out(vty
, "}\n");
12281 vty_out(vty
, "}\n");
12283 return CMD_SUCCESS
;
12286 DEFUN (show_ip_bgp_route
,
12287 show_ip_bgp_route_cmd
,
12288 "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]",
12292 BGP_INSTANCE_HELP_STR
12294 BGP_SAFI_WITH_LABEL_HELP_STR
12295 "Network in the BGP routing table to display\n"
12297 "Network in the BGP routing table to display\n"
12299 "Display only the bestpath\n"
12300 "Display only multipaths\n"
12301 "Display only paths that match the specified rpki state\n"
12302 "A valid path as determined by rpki\n"
12303 "A invalid path as determined by rpki\n"
12304 "A path that has no rpki data\n"
12307 int prefix_check
= 0;
12309 afi_t afi
= AFI_IP6
;
12310 safi_t safi
= SAFI_UNICAST
;
12311 char *prefix
= NULL
;
12312 struct bgp
*bgp
= NULL
;
12313 enum bgp_path_type path_type
;
12314 bool uj
= use_json(argc
, argv
);
12318 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12321 return CMD_WARNING
;
12325 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
12326 return CMD_WARNING
;
12329 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
12330 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
12331 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
12333 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
12334 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
12337 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
12338 && afi
!= AFI_IP6
) {
12340 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
12341 return CMD_WARNING
;
12343 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
12344 && afi
!= AFI_IP
) {
12346 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
12347 return CMD_WARNING
;
12350 prefix
= argv
[idx
]->arg
;
12352 /* [<bestpath|multipath>] */
12353 if (argv_find(argv
, argc
, "bestpath", &idx
))
12354 path_type
= BGP_PATH_SHOW_BESTPATH
;
12355 else if (argv_find(argv
, argc
, "multipath", &idx
))
12356 path_type
= BGP_PATH_SHOW_MULTIPATH
;
12358 path_type
= BGP_PATH_SHOW_ALL
;
12360 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
12361 path_type
, RPKI_NOT_BEING_USED
, uj
);
12364 DEFUN (show_ip_bgp_regexp
,
12365 show_ip_bgp_regexp_cmd
,
12366 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX [json]",
12370 BGP_INSTANCE_HELP_STR
12372 BGP_SAFI_WITH_LABEL_HELP_STR
12373 "Display routes matching the AS path regular expression\n"
12374 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
12377 afi_t afi
= AFI_IP6
;
12378 safi_t safi
= SAFI_UNICAST
;
12379 struct bgp
*bgp
= NULL
;
12380 bool uj
= use_json(argc
, argv
);
12381 char *regstr
= NULL
;
12384 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12387 return CMD_WARNING
;
12389 // get index of regex
12390 if (argv_find(argv
, argc
, "REGEX", &idx
))
12391 regstr
= argv
[idx
]->arg
;
12394 return bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
12395 bgp_show_type_regexp
, uj
);
12398 DEFPY (show_ip_bgp_instance_all
,
12399 show_ip_bgp_instance_all_cmd
,
12400 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json$uj | wide$wide]",
12404 BGP_INSTANCE_ALL_HELP_STR
12406 BGP_SAFI_WITH_LABEL_HELP_STR
12408 "Increase table width for longer prefixes\n")
12410 afi_t afi
= AFI_IP
;
12411 safi_t safi
= SAFI_UNICAST
;
12412 struct bgp
*bgp
= NULL
;
12414 uint16_t show_flags
= 0;
12418 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12422 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
12424 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12427 return CMD_WARNING
;
12429 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, show_flags
);
12430 return CMD_SUCCESS
;
12433 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
12434 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
12439 uint16_t show_flags
= 0;
12442 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12444 if (!config_bgp_aspath_validate(regstr
)) {
12445 vty_out(vty
, "Invalid character in REGEX %s\n",
12447 return CMD_WARNING_CONFIG_FAILED
;
12450 regex
= bgp_regcomp(regstr
);
12452 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
12453 return CMD_WARNING
;
12456 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, show_flags
,
12457 RPKI_NOT_BEING_USED
);
12458 bgp_regex_free(regex
);
12462 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
12463 const char *prefix_list_str
, afi_t afi
,
12464 safi_t safi
, enum bgp_show_type type
)
12466 struct prefix_list
*plist
;
12467 uint16_t show_flags
= 0;
12469 plist
= prefix_list_lookup(afi
, prefix_list_str
);
12470 if (plist
== NULL
) {
12471 vty_out(vty
, "%% %s is not a valid prefix-list name\n",
12473 return CMD_WARNING
;
12476 return bgp_show(vty
, bgp
, afi
, safi
, type
, plist
, show_flags
,
12477 RPKI_NOT_BEING_USED
);
12480 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
12481 const char *filter
, afi_t afi
, safi_t safi
,
12482 enum bgp_show_type type
)
12484 struct as_list
*as_list
;
12485 uint16_t show_flags
= 0;
12487 as_list
= as_list_lookup(filter
);
12488 if (as_list
== NULL
) {
12489 vty_out(vty
, "%% %s is not a valid AS-path access-list name\n",
12491 return CMD_WARNING
;
12494 return bgp_show(vty
, bgp
, afi
, safi
, type
, as_list
, show_flags
,
12495 RPKI_NOT_BEING_USED
);
12498 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
12499 const char *rmap_str
, afi_t afi
, safi_t safi
,
12500 enum bgp_show_type type
)
12502 struct route_map
*rmap
;
12503 uint16_t show_flags
= 0;
12505 rmap
= route_map_lookup_by_name(rmap_str
);
12507 vty_out(vty
, "%% %s is not a valid route-map name\n", rmap_str
);
12508 return CMD_WARNING
;
12511 return bgp_show(vty
, bgp
, afi
, safi
, type
, rmap
, show_flags
,
12512 RPKI_NOT_BEING_USED
);
12515 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
12516 const char *comstr
, int exact
, afi_t afi
,
12517 safi_t safi
, uint16_t show_flags
)
12519 struct community
*com
;
12522 com
= community_str2com(comstr
);
12524 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
12525 return CMD_WARNING
;
12528 ret
= bgp_show(vty
, bgp
, afi
, safi
,
12529 (exact
? bgp_show_type_community_exact
12530 : bgp_show_type_community
),
12531 com
, show_flags
, RPKI_NOT_BEING_USED
);
12532 community_free(&com
);
12537 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
12538 const char *com
, int exact
, afi_t afi
,
12541 struct community_list
*list
;
12542 uint16_t show_flags
= 0;
12544 list
= community_list_lookup(bgp_clist
, com
, 0, COMMUNITY_LIST_MASTER
);
12545 if (list
== NULL
) {
12546 vty_out(vty
, "%% %s is not a valid community-list name\n", com
);
12547 return CMD_WARNING
;
12550 return bgp_show(vty
, bgp
, afi
, safi
,
12551 (exact
? bgp_show_type_community_list_exact
12552 : bgp_show_type_community_list
),
12553 list
, show_flags
, RPKI_NOT_BEING_USED
);
12556 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
12557 const char *prefix
, afi_t afi
, safi_t safi
,
12558 enum bgp_show_type type
)
12562 uint16_t show_flags
= 0;
12566 ret
= str2prefix(prefix
, p
);
12568 vty_out(vty
, "%% Malformed Prefix\n");
12569 return CMD_WARNING
;
12572 ret
= bgp_show(vty
, bgp
, afi
, safi
, type
, p
, show_flags
,
12573 RPKI_NOT_BEING_USED
);
12579 BGP_STATS_MAXBITLEN
= 0,
12581 BGP_STATS_PREFIXES
,
12583 BGP_STATS_UNAGGREGATEABLE
,
12584 BGP_STATS_MAX_AGGREGATEABLE
,
12585 BGP_STATS_AGGREGATES
,
12587 BGP_STATS_ASPATH_COUNT
,
12588 BGP_STATS_ASPATH_MAXHOPS
,
12589 BGP_STATS_ASPATH_TOTHOPS
,
12590 BGP_STATS_ASPATH_MAXSIZE
,
12591 BGP_STATS_ASPATH_TOTSIZE
,
12592 BGP_STATS_ASN_HIGHEST
,
12596 #define TABLE_STATS_IDX_VTY 0
12597 #define TABLE_STATS_IDX_JSON 1
12599 static const char *table_stats_strs
[][2] = {
12600 [BGP_STATS_PREFIXES
] = {"Total Prefixes", "totalPrefixes"},
12601 [BGP_STATS_TOTPLEN
] = {"Average prefix length", "averagePrefixLength"},
12602 [BGP_STATS_RIB
] = {"Total Advertisements", "totalAdvertisements"},
12603 [BGP_STATS_UNAGGREGATEABLE
] = {"Unaggregateable prefixes",
12604 "unaggregateablePrefixes"},
12605 [BGP_STATS_MAX_AGGREGATEABLE
] = {"Maximum aggregateable prefixes",
12606 "maximumAggregateablePrefixes"},
12607 [BGP_STATS_AGGREGATES
] = {"BGP Aggregate advertisements",
12608 "bgpAggregateAdvertisements"},
12609 [BGP_STATS_SPACE
] = {"Address space advertised",
12610 "addressSpaceAdvertised"},
12611 [BGP_STATS_ASPATH_COUNT
] = {"Advertisements with paths",
12612 "advertisementsWithPaths"},
12613 [BGP_STATS_ASPATH_MAXHOPS
] = {"Longest AS-Path (hops)",
12615 [BGP_STATS_ASPATH_MAXSIZE
] = {"Largest AS-Path (bytes)",
12617 [BGP_STATS_ASPATH_TOTHOPS
] = {"Average AS-Path length (hops)",
12618 "averageAsPathLengthHops"},
12619 [BGP_STATS_ASPATH_TOTSIZE
] = {"Average AS-Path size (bytes)",
12620 "averageAsPathSizeBytes"},
12621 [BGP_STATS_ASN_HIGHEST
] = {"Highest public ASN", "highestPublicAsn"},
12622 [BGP_STATS_MAX
] = {NULL
, NULL
}
12625 struct bgp_table_stats
{
12626 struct bgp_table
*table
;
12627 unsigned long long counts
[BGP_STATS_MAX
];
12628 double total_space
;
12631 static void bgp_table_stats_rn(struct bgp_dest
*dest
, struct bgp_dest
*top
,
12632 struct bgp_table_stats
*ts
, unsigned int space
)
12634 struct bgp_dest
*pdest
= bgp_dest_parent_nolock(dest
);
12635 struct bgp_path_info
*pi
;
12636 const struct prefix
*rn_p
;
12638 if (!bgp_dest_has_bgp_path_info_data(dest
))
12641 rn_p
= bgp_dest_get_prefix(dest
);
12642 ts
->counts
[BGP_STATS_PREFIXES
]++;
12643 ts
->counts
[BGP_STATS_TOTPLEN
] += rn_p
->prefixlen
;
12645 /* check if the prefix is included by any other announcements */
12646 while (pdest
&& !bgp_dest_has_bgp_path_info_data(pdest
))
12647 pdest
= bgp_dest_parent_nolock(pdest
);
12649 if (pdest
== NULL
|| pdest
== top
) {
12650 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
12651 /* announced address space */
12653 ts
->total_space
+= pow(2.0, space
- rn_p
->prefixlen
);
12654 } else if (bgp_dest_has_bgp_path_info_data(pdest
))
12655 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
12658 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
12659 ts
->counts
[BGP_STATS_RIB
]++;
12661 if (CHECK_FLAG(pi
->attr
->flag
,
12662 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)))
12663 ts
->counts
[BGP_STATS_AGGREGATES
]++;
12665 /* as-path stats */
12666 if (pi
->attr
->aspath
) {
12667 unsigned int hops
= aspath_count_hops(pi
->attr
->aspath
);
12668 unsigned int size
= aspath_size(pi
->attr
->aspath
);
12669 as_t highest
= aspath_highest(pi
->attr
->aspath
);
12671 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
12673 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
12674 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] = hops
;
12676 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
12677 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] = size
;
12679 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
12680 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
12681 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
12682 ts
->counts
[BGP_STATS_ASN_HIGHEST
] = highest
;
12687 static int bgp_table_stats_walker(struct thread
*t
)
12689 struct bgp_dest
*dest
, *ndest
;
12690 struct bgp_dest
*top
;
12691 struct bgp_table_stats
*ts
= THREAD_ARG(t
);
12692 unsigned int space
= 0;
12694 if (!(top
= bgp_table_top(ts
->table
)))
12697 switch (ts
->table
->afi
) {
12699 space
= IPV4_MAX_BITLEN
;
12702 space
= IPV6_MAX_BITLEN
;
12705 space
= EVPN_ROUTE_PREFIXLEN
;
12711 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
12713 for (dest
= top
; dest
; dest
= bgp_route_next(dest
)) {
12714 if (ts
->table
->safi
== SAFI_MPLS_VPN
12715 || ts
->table
->safi
== SAFI_ENCAP
12716 || ts
->table
->safi
== SAFI_EVPN
) {
12717 struct bgp_table
*table
;
12719 table
= bgp_dest_get_bgp_table_info(dest
);
12723 top
= bgp_table_top(table
);
12724 for (ndest
= bgp_table_top(table
); ndest
;
12725 ndest
= bgp_route_next(ndest
))
12726 bgp_table_stats_rn(ndest
, top
, ts
, space
);
12728 bgp_table_stats_rn(dest
, top
, ts
, space
);
12735 static void bgp_table_stats_all(struct vty
*vty
, afi_t afi
, safi_t safi
,
12736 struct json_object
*json_array
)
12738 struct listnode
*node
, *nnode
;
12741 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
))
12742 bgp_table_stats_single(vty
, bgp
, afi
, safi
, json_array
);
12745 static int bgp_table_stats_single(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12746 safi_t safi
, struct json_object
*json_array
)
12748 struct bgp_table_stats ts
;
12750 int ret
= CMD_SUCCESS
;
12752 struct json_object
*json
= NULL
;
12755 json
= json_object_new_object();
12757 if (!bgp
->rib
[afi
][safi
]) {
12758 char warning_msg
[50];
12760 snprintf(warning_msg
, sizeof(warning_msg
),
12761 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi
,
12765 vty_out(vty
, "%s\n", warning_msg
);
12767 json_object_string_add(json
, "warning", warning_msg
);
12770 goto end_table_stats
;
12774 vty_out(vty
, "BGP %s RIB statistics (%s)\n",
12775 get_afi_safi_str(afi
, safi
, false), bgp
->name_pretty
);
12777 json_object_string_add(json
, "instance", bgp
->name_pretty
);
12779 /* labeled-unicast routes live in the unicast table */
12780 if (safi
== SAFI_LABELED_UNICAST
)
12781 safi
= SAFI_UNICAST
;
12783 memset(&ts
, 0, sizeof(ts
));
12784 ts
.table
= bgp
->rib
[afi
][safi
];
12785 thread_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
12787 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
12788 if ((!json
&& !table_stats_strs
[i
][TABLE_STATS_IDX_VTY
])
12789 || (json
&& !table_stats_strs
[i
][TABLE_STATS_IDX_JSON
]))
12793 case BGP_STATS_ASPATH_TOTHOPS
:
12794 case BGP_STATS_ASPATH_TOTSIZE
:
12797 temp_buf
, sizeof(temp_buf
), "%12.2f",
12799 ? (float)ts
.counts
[i
]
12801 [BGP_STATS_ASPATH_COUNT
]
12803 vty_out(vty
, "%-30s: %s",
12804 table_stats_strs
[i
]
12805 [TABLE_STATS_IDX_VTY
],
12808 json_object_double_add(
12810 table_stats_strs
[i
]
12811 [TABLE_STATS_IDX_JSON
],
12813 ? (double)ts
.counts
[i
]
12814 / (double)ts
.counts
12815 [BGP_STATS_ASPATH_COUNT
]
12819 case BGP_STATS_TOTPLEN
:
12822 temp_buf
, sizeof(temp_buf
), "%12.2f",
12824 ? (float)ts
.counts
[i
]
12826 [BGP_STATS_PREFIXES
]
12828 vty_out(vty
, "%-30s: %s",
12829 table_stats_strs
[i
]
12830 [TABLE_STATS_IDX_VTY
],
12833 json_object_double_add(
12835 table_stats_strs
[i
]
12836 [TABLE_STATS_IDX_JSON
],
12838 ? (double)ts
.counts
[i
]
12839 / (double)ts
.counts
12840 [BGP_STATS_PREFIXES
]
12844 case BGP_STATS_SPACE
:
12846 snprintf(temp_buf
, sizeof(temp_buf
), "%12g",
12848 vty_out(vty
, "%-30s: %s\n",
12849 table_stats_strs
[i
]
12850 [TABLE_STATS_IDX_VTY
],
12853 json_object_double_add(
12855 table_stats_strs
[i
]
12856 [TABLE_STATS_IDX_JSON
],
12857 (double)ts
.total_space
);
12859 if (afi
== AFI_IP6
) {
12861 snprintf(temp_buf
, sizeof(temp_buf
),
12864 * pow(2.0, -128 + 32));
12865 vty_out(vty
, "%30s: %s\n",
12866 "/32 equivalent %s\n",
12869 json_object_double_add(
12870 json
, "/32equivalent",
12871 (double)(ts
.total_space
12876 snprintf(temp_buf
, sizeof(temp_buf
),
12879 * pow(2.0, -128 + 48));
12880 vty_out(vty
, "%30s: %s\n",
12881 "/48 equivalent %s\n",
12884 json_object_double_add(
12885 json
, "/48equivalent",
12886 (double)(ts
.total_space
12892 snprintf(temp_buf
, sizeof(temp_buf
),
12894 ts
.total_space
* 100.
12896 vty_out(vty
, "%30s: %s\n",
12897 "% announced ", temp_buf
);
12899 json_object_double_add(
12900 json
, "%announced",
12901 (double)(ts
.total_space
* 100.
12905 snprintf(temp_buf
, sizeof(temp_buf
),
12908 * pow(2.0, -32 + 8));
12909 vty_out(vty
, "%30s: %s\n",
12910 "/8 equivalent ", temp_buf
);
12912 json_object_double_add(
12913 json
, "/8equivalent",
12914 (double)(ts
.total_space
12915 * pow(2.0, -32 + 8)));
12918 snprintf(temp_buf
, sizeof(temp_buf
),
12921 * pow(2.0, -32 + 24));
12922 vty_out(vty
, "%30s: %s\n",
12923 "/24 equivalent ", temp_buf
);
12925 json_object_double_add(
12926 json
, "/24equivalent",
12927 (double)(ts
.total_space
12928 * pow(2.0, -32 + 24)));
12934 snprintf(temp_buf
, sizeof(temp_buf
), "%12llu",
12936 vty_out(vty
, "%-30s: %s",
12937 table_stats_strs
[i
]
12938 [TABLE_STATS_IDX_VTY
],
12941 json_object_int_add(
12943 table_stats_strs
[i
]
12944 [TABLE_STATS_IDX_JSON
],
12949 vty_out(vty
, "\n");
12953 json_object_array_add(json_array
, json
);
12957 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12958 safi_t safi
, struct json_object
*json_array
)
12961 bgp_table_stats_all(vty
, afi
, safi
, json_array
);
12962 return CMD_SUCCESS
;
12965 return bgp_table_stats_single(vty
, bgp
, afi
, safi
, json_array
);
12977 PCOUNT_BPATH_SELECTED
,
12978 PCOUNT_PFCNT
, /* the figure we display to users */
12982 static const char *const pcount_strs
[] = {
12983 [PCOUNT_ADJ_IN
] = "Adj-in",
12984 [PCOUNT_DAMPED
] = "Damped",
12985 [PCOUNT_REMOVED
] = "Removed",
12986 [PCOUNT_HISTORY
] = "History",
12987 [PCOUNT_STALE
] = "Stale",
12988 [PCOUNT_VALID
] = "Valid",
12989 [PCOUNT_ALL
] = "All RIB",
12990 [PCOUNT_COUNTED
] = "PfxCt counted",
12991 [PCOUNT_BPATH_SELECTED
] = "PfxCt Best Selected",
12992 [PCOUNT_PFCNT
] = "Useable",
12993 [PCOUNT_MAX
] = NULL
,
12996 struct peer_pcounts
{
12997 unsigned int count
[PCOUNT_MAX
];
12998 const struct peer
*peer
;
12999 const struct bgp_table
*table
;
13003 static void bgp_peer_count_proc(struct bgp_dest
*rn
, struct peer_pcounts
*pc
)
13005 const struct bgp_adj_in
*ain
;
13006 const struct bgp_path_info
*pi
;
13007 const struct peer
*peer
= pc
->peer
;
13009 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
13010 if (ain
->peer
== peer
)
13011 pc
->count
[PCOUNT_ADJ_IN
]++;
13013 for (pi
= bgp_dest_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
13015 if (pi
->peer
!= peer
)
13018 pc
->count
[PCOUNT_ALL
]++;
13020 if (CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
))
13021 pc
->count
[PCOUNT_DAMPED
]++;
13022 if (CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
13023 pc
->count
[PCOUNT_HISTORY
]++;
13024 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
13025 pc
->count
[PCOUNT_REMOVED
]++;
13026 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
13027 pc
->count
[PCOUNT_STALE
]++;
13028 if (CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
13029 pc
->count
[PCOUNT_VALID
]++;
13030 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
13031 pc
->count
[PCOUNT_PFCNT
]++;
13032 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
13033 pc
->count
[PCOUNT_BPATH_SELECTED
]++;
13035 if (CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
13036 pc
->count
[PCOUNT_COUNTED
]++;
13037 if (CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
13039 EC_LIB_DEVELOPMENT
,
13040 "Attempting to count but flags say it is unusable");
13042 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
13044 EC_LIB_DEVELOPMENT
,
13045 "Not counted but flags say we should");
13050 static int bgp_peer_count_walker(struct thread
*t
)
13052 struct bgp_dest
*rn
, *rm
;
13053 const struct bgp_table
*table
;
13054 struct peer_pcounts
*pc
= THREAD_ARG(t
);
13056 if (pc
->safi
== SAFI_MPLS_VPN
|| pc
->safi
== SAFI_ENCAP
13057 || pc
->safi
== SAFI_EVPN
) {
13058 /* Special handling for 2-level routing tables. */
13059 for (rn
= bgp_table_top(pc
->table
); rn
;
13060 rn
= bgp_route_next(rn
)) {
13061 table
= bgp_dest_get_bgp_table_info(rn
);
13063 for (rm
= bgp_table_top(table
); rm
;
13064 rm
= bgp_route_next(rm
))
13065 bgp_peer_count_proc(rm
, pc
);
13068 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
))
13069 bgp_peer_count_proc(rn
, pc
);
13074 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
13075 safi_t safi
, bool use_json
)
13077 struct peer_pcounts pcounts
= {.peer
= peer
};
13079 json_object
*json
= NULL
;
13080 json_object
*json_loop
= NULL
;
13083 json
= json_object_new_object();
13084 json_loop
= json_object_new_object();
13087 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
13088 || !peer
->bgp
->rib
[afi
][safi
]) {
13090 json_object_string_add(
13092 "No such neighbor or address family");
13093 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
13094 json_object_free(json
);
13095 json_object_free(json_loop
);
13097 vty_out(vty
, "%% No such neighbor or address family\n");
13099 return CMD_WARNING
;
13102 memset(&pcounts
, 0, sizeof(pcounts
));
13103 pcounts
.peer
= peer
;
13104 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
13105 pcounts
.safi
= safi
;
13107 /* in-place call via thread subsystem so as to record execution time
13108 * stats for the thread-walk (i.e. ensure this can't be blamed on
13109 * on just vty_read()).
13111 thread_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
13114 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
13115 json_object_string_add(json
, "multiProtocol",
13116 get_afi_safi_str(afi
, safi
, true));
13117 json_object_int_add(json
, "pfxCounter",
13118 peer
->pcount
[afi
][safi
]);
13120 for (i
= 0; i
< PCOUNT_MAX
; i
++)
13121 json_object_int_add(json_loop
, pcount_strs
[i
],
13124 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
13126 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
13127 json_object_string_add(json
, "pfxctDriftFor",
13129 json_object_string_add(
13130 json
, "recommended",
13131 "Please report this bug, with the above command output");
13133 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
13134 json
, JSON_C_TO_STRING_PRETTY
));
13135 json_object_free(json
);
13139 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_HOSTNAME
)) {
13140 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
13141 peer
->hostname
, peer
->host
,
13142 get_afi_safi_str(afi
, safi
, false));
13144 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
13145 get_afi_safi_str(afi
, safi
, false));
13148 vty_out(vty
, "PfxCt: %u\n", peer
->pcount
[afi
][safi
]);
13149 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
13151 for (i
= 0; i
< PCOUNT_MAX
; i
++)
13152 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
13155 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
13156 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
13158 "Please report this bug, with the above command output\n");
13162 return CMD_SUCCESS
;
13165 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
13166 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
13167 "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]",
13171 BGP_INSTANCE_HELP_STR
13174 "Detailed information on TCP and BGP neighbor connections\n"
13175 "Neighbor to display information about\n"
13176 "Neighbor to display information about\n"
13177 "Neighbor on BGP configured interface\n"
13178 "Display detailed prefix count information\n"
13181 afi_t afi
= AFI_IP6
;
13182 safi_t safi
= SAFI_UNICAST
;
13185 struct bgp
*bgp
= NULL
;
13186 bool uj
= use_json(argc
, argv
);
13191 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13194 return CMD_WARNING
;
13196 argv_find(argv
, argc
, "neighbors", &idx
);
13197 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
13199 return CMD_WARNING
;
13201 return bgp_peer_counts(vty
, peer
, afi
, safi
, uj
);
13204 #ifdef KEEP_OLD_VPN_COMMANDS
13205 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
13206 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
13207 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
13212 "Display information about all VPNv4 NLRIs\n"
13213 "Detailed information on TCP and BGP neighbor connections\n"
13214 "Neighbor to display information about\n"
13215 "Neighbor to display information about\n"
13216 "Neighbor on BGP configured interface\n"
13217 "Display detailed prefix count information\n"
13222 bool uj
= use_json(argc
, argv
);
13224 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
13226 return CMD_WARNING
;
13228 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
13231 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
13232 show_ip_bgp_vpn_all_route_prefix_cmd
,
13233 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
13238 "Display information about all VPNv4 NLRIs\n"
13239 "Network in the BGP routing table to display\n"
13240 "Network in the BGP routing table to display\n"
13244 char *network
= NULL
;
13245 struct bgp
*bgp
= bgp_get_default();
13247 vty_out(vty
, "Can't find default instance\n");
13248 return CMD_WARNING
;
13251 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
13252 network
= argv
[idx
]->arg
;
13253 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
13254 network
= argv
[idx
]->arg
;
13256 vty_out(vty
, "Unable to figure out Network\n");
13257 return CMD_WARNING
;
13260 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
13261 BGP_PATH_SHOW_ALL
, RPKI_NOT_BEING_USED
,
13262 use_json(argc
, argv
));
13264 #endif /* KEEP_OLD_VPN_COMMANDS */
13266 DEFUN (show_bgp_l2vpn_evpn_route_prefix
,
13267 show_bgp_l2vpn_evpn_route_prefix_cmd
,
13268 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
13273 "Network in the BGP routing table to display\n"
13274 "Network in the BGP routing table to display\n"
13275 "Network in the BGP routing table to display\n"
13276 "Network in the BGP routing table to display\n"
13280 char *network
= NULL
;
13281 int prefix_check
= 0;
13283 if (argv_find(argv
, argc
, "A.B.C.D", &idx
) ||
13284 argv_find(argv
, argc
, "X:X::X:X", &idx
))
13285 network
= argv
[idx
]->arg
;
13286 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
) ||
13287 argv_find(argv
, argc
, "X:X::X:X/M", &idx
)) {
13288 network
= argv
[idx
]->arg
;
13291 vty_out(vty
, "Unable to figure out Network\n");
13292 return CMD_WARNING
;
13294 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
,
13295 prefix_check
, BGP_PATH_SHOW_ALL
,
13296 RPKI_NOT_BEING_USED
, use_json(argc
, argv
));
13299 static void show_adj_route_header(struct vty
*vty
, struct bgp
*bgp
,
13300 struct bgp_table
*table
, int *header1
,
13301 int *header2
, json_object
*json
,
13302 json_object
*json_scode
,
13303 json_object
*json_ocode
, bool wide
)
13305 uint64_t version
= table
? table
->version
: 0;
13306 char buf
[BUFSIZ
] = {0};
13310 json_object_int_add(json
, "bgpTableVersion", version
);
13311 json_object_string_add(json
, "bgpLocalRouterId",
13313 &bgp
->router_id
, buf
,
13315 json_object_int_add(json
, "defaultLocPrf",
13316 bgp
->default_local_pref
);
13317 json_object_int_add(json
, "localAS", bgp
->as
);
13318 json_object_object_add(json
, "bgpStatusCodes",
13320 json_object_object_add(json
, "bgpOriginCodes",
13324 "BGP table version is %" PRIu64
13325 ", local router ID is %pI4, vrf id ",
13326 version
, &bgp
->router_id
);
13327 if (bgp
->vrf_id
== VRF_UNKNOWN
)
13328 vty_out(vty
, "%s", VRFID_NONE_STR
);
13330 vty_out(vty
, "%u", bgp
->vrf_id
);
13331 vty_out(vty
, "\n");
13332 vty_out(vty
, "Default local pref %u, ",
13333 bgp
->default_local_pref
);
13334 vty_out(vty
, "local AS %u\n", bgp
->as
);
13335 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
13336 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
13337 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
13338 vty_out(vty
, BGP_SHOW_RPKI_HEADER
);
13344 vty_out(vty
, (wide
? BGP_SHOW_HEADER_WIDE
13345 : BGP_SHOW_HEADER
));
13351 show_adj_route(struct vty
*vty
, struct peer
*peer
, struct bgp_table
*table
,
13352 afi_t afi
, safi_t safi
, enum bgp_show_adj_route_type type
,
13353 const char *rmap_name
, json_object
*json
, json_object
*json_ar
,
13354 json_object
*json_scode
, json_object
*json_ocode
,
13355 uint16_t show_flags
, int *header1
, int *header2
, char *rd_str
,
13356 unsigned long *output_count
, unsigned long *filtered_count
)
13358 struct bgp_adj_in
*ain
;
13359 struct bgp_adj_out
*adj
;
13360 struct bgp_dest
*dest
;
13364 struct update_subgroup
*subgrp
;
13365 struct peer_af
*paf
;
13366 bool route_filtered
;
13367 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13368 bool wide
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
13369 bool show_rd
= ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
13370 || (safi
== SAFI_EVPN
))
13378 json_object_string_add(json
, "alert", "no BGP");
13379 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
13380 json_object_free(json
);
13382 vty_out(vty
, "%% No bgp\n");
13386 subgrp
= peer_subgroup(peer
, afi
, safi
);
13388 if (type
== bgp_show_adj_route_advertised
&& subgrp
13389 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
13390 char buf
[BUFSIZ
] = {0};
13393 json_object_int_add(json
, "bgpTableVersion",
13395 json_object_string_add(json
, "bgpLocalRouterId",
13397 &bgp
->router_id
, buf
,
13399 json_object_int_add(json
, "defaultLocPrf",
13400 bgp
->default_local_pref
);
13401 json_object_int_add(json
, "localAS", bgp
->as
);
13402 json_object_object_add(json
, "bgpStatusCodes",
13404 json_object_object_add(json
, "bgpOriginCodes",
13406 json_object_string_add(
13407 json
, "bgpOriginatingDefaultNetwork",
13408 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
13411 "BGP table version is %" PRIu64
13412 ", local router ID is %pI4, vrf id ",
13413 table
->version
, &bgp
->router_id
);
13414 if (bgp
->vrf_id
== VRF_UNKNOWN
)
13415 vty_out(vty
, "%s", VRFID_NONE_STR
);
13417 vty_out(vty
, "%u", bgp
->vrf_id
);
13418 vty_out(vty
, "\n");
13419 vty_out(vty
, "Default local pref %u, ",
13420 bgp
->default_local_pref
);
13421 vty_out(vty
, "local AS %u\n", bgp
->as
);
13422 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
13423 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
13424 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
13425 vty_out(vty
, BGP_SHOW_RPKI_HEADER
);
13427 vty_out(vty
, "Originating default network %s\n\n",
13428 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
13433 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
13434 if (type
== bgp_show_adj_route_received
13435 || type
== bgp_show_adj_route_filtered
) {
13436 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
13437 if (ain
->peer
!= peer
)
13440 show_adj_route_header(vty
, bgp
, table
, header1
,
13441 header2
, json
, json_scode
,
13444 if ((safi
== SAFI_MPLS_VPN
)
13445 || (safi
== SAFI_ENCAP
)
13446 || (safi
== SAFI_EVPN
)) {
13448 json_object_string_add(
13449 json_ar
, "rd", rd_str
);
13450 else if (show_rd
&& rd_str
) {
13452 "Route Distinguisher: %s\n",
13459 route_filtered
= false;
13461 /* Filter prefix using distribute list,
13462 * filter list or prefix list
13464 const struct prefix
*rn_p
=
13465 bgp_dest_get_prefix(dest
);
13466 if ((bgp_input_filter(peer
, rn_p
, &attr
, afi
,
13469 route_filtered
= true;
13471 /* Filter prefix using route-map */
13472 ret
= bgp_input_modifier(peer
, rn_p
, &attr
, afi
,
13473 safi
, rmap_name
, NULL
,
13476 if (type
== bgp_show_adj_route_filtered
&&
13477 !route_filtered
&& ret
!= RMAP_DENY
) {
13478 bgp_attr_undup(&attr
, ain
->attr
);
13482 if (type
== bgp_show_adj_route_received
13483 && (route_filtered
|| ret
== RMAP_DENY
))
13484 (*filtered_count
)++;
13486 route_vty_out_tmp(vty
, dest
, rn_p
, &attr
, safi
,
13487 use_json
, json_ar
, wide
);
13488 bgp_attr_undup(&attr
, ain
->attr
);
13491 } else if (type
== bgp_show_adj_route_advertised
) {
13492 RB_FOREACH (adj
, bgp_adj_out_rb
, &dest
->adj_out
)
13493 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
13494 if (paf
->peer
!= peer
|| !adj
->attr
)
13497 show_adj_route_header(vty
, bgp
, table
,
13502 const struct prefix
*rn_p
=
13503 bgp_dest_get_prefix(dest
);
13506 ret
= bgp_output_modifier(
13507 peer
, rn_p
, &attr
, afi
, safi
,
13510 if (ret
!= RMAP_DENY
) {
13511 if ((safi
== SAFI_MPLS_VPN
)
13512 || (safi
== SAFI_ENCAP
)
13513 || (safi
== SAFI_EVPN
)) {
13515 json_object_string_add(
13522 "Route Distinguisher: %s\n",
13528 vty
, dest
, rn_p
, &attr
,
13529 safi
, use_json
, json_ar
,
13533 (*filtered_count
)++;
13536 bgp_attr_undup(&attr
, adj
->attr
);
13538 } else if (type
== bgp_show_adj_route_bestpath
) {
13539 struct bgp_path_info
*pi
;
13541 show_adj_route_header(vty
, bgp
, table
, header1
, header2
,
13542 json
, json_scode
, json_ocode
,
13545 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
13547 if (pi
->peer
!= peer
)
13550 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
13553 route_vty_out_tmp(vty
, dest
,
13554 bgp_dest_get_prefix(dest
),
13555 pi
->attr
, safi
, use_json
,
13563 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
13564 safi_t safi
, enum bgp_show_adj_route_type type
,
13565 const char *rmap_name
, uint16_t show_flags
)
13568 struct bgp_table
*table
;
13569 json_object
*json
= NULL
;
13570 json_object
*json_scode
= NULL
;
13571 json_object
*json_ocode
= NULL
;
13572 json_object
*json_ar
= NULL
;
13573 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13575 /* Init BGP headers here so they're only displayed once
13576 * even if 'table' is 2-tier (MPLS_VPN, ENCAP, EVPN).
13582 * Initialize variables for each RD
13583 * All prefixes under an RD is aggregated within "json_routes"
13585 char rd_str
[BUFSIZ
] = {0};
13586 json_object
*json_routes
= NULL
;
13589 /* For 2-tier tables, prefix counts need to be
13590 * maintained across multiple runs of show_adj_route()
13592 unsigned long output_count_per_rd
;
13593 unsigned long filtered_count_per_rd
;
13594 unsigned long output_count
= 0;
13595 unsigned long filtered_count
= 0;
13598 json
= json_object_new_object();
13599 json_ar
= json_object_new_object();
13600 json_scode
= json_object_new_object();
13601 json_ocode
= json_object_new_object();
13603 json_object_string_add(json_scode
, "suppressed", "s");
13604 json_object_string_add(json_scode
, "damped", "d");
13605 json_object_string_add(json_scode
, "history", "h");
13606 json_object_string_add(json_scode
, "valid", "*");
13607 json_object_string_add(json_scode
, "best", ">");
13608 json_object_string_add(json_scode
, "multipath", "=");
13609 json_object_string_add(json_scode
, "internal", "i");
13610 json_object_string_add(json_scode
, "ribFailure", "r");
13611 json_object_string_add(json_scode
, "stale", "S");
13612 json_object_string_add(json_scode
, "removed", "R");
13614 json_object_string_add(json_ocode
, "igp", "i");
13615 json_object_string_add(json_ocode
, "egp", "e");
13616 json_object_string_add(json_ocode
, "incomplete", "?");
13619 if (!peer
|| !peer
->afc
[afi
][safi
]) {
13621 json_object_string_add(
13623 "No such neighbor or address family");
13624 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
13625 json_object_free(json
);
13627 vty_out(vty
, "%% No such neighbor or address family\n");
13629 return CMD_WARNING
;
13632 if ((type
== bgp_show_adj_route_received
13633 || type
== bgp_show_adj_route_filtered
)
13634 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
13635 PEER_FLAG_SOFT_RECONFIG
)) {
13637 json_object_string_add(
13639 "Inbound soft reconfiguration not enabled");
13640 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
13641 json_object_free(json
);
13644 "%% Inbound soft reconfiguration not enabled\n");
13646 return CMD_WARNING
;
13651 /* labeled-unicast routes live in the unicast table */
13652 if (safi
== SAFI_LABELED_UNICAST
)
13653 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
13655 table
= bgp
->rib
[afi
][safi
];
13657 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
13658 || (safi
== SAFI_EVPN
)) {
13660 struct bgp_dest
*dest
;
13662 for (dest
= bgp_table_top(table
); dest
;
13663 dest
= bgp_route_next(dest
)) {
13664 table
= bgp_dest_get_bgp_table_info(dest
);
13668 output_count_per_rd
= 0;
13669 filtered_count_per_rd
= 0;
13672 json_routes
= json_object_new_object();
13674 const struct prefix_rd
*prd
;
13675 prd
= (const struct prefix_rd
*)bgp_dest_get_prefix(
13678 prefix_rd2str(prd
, rd_str
, sizeof(rd_str
));
13680 show_adj_route(vty
, peer
, table
, afi
, safi
, type
,
13681 rmap_name
, json
, json_routes
, json_scode
,
13682 json_ocode
, show_flags
, &header1
,
13683 &header2
, rd_str
, &output_count_per_rd
,
13684 &filtered_count_per_rd
);
13686 /* Don't include an empty RD in the output! */
13687 if (json_routes
&& (output_count_per_rd
> 0))
13688 json_object_object_add(json_ar
, rd_str
,
13691 output_count
+= output_count_per_rd
;
13692 filtered_count
+= filtered_count_per_rd
;
13695 show_adj_route(vty
, peer
, table
, afi
, safi
, type
, rmap_name
,
13696 json
, json_ar
, json_scode
, json_ocode
,
13697 show_flags
, &header1
, &header2
, rd_str
,
13698 &output_count
, &filtered_count
);
13701 json_object_object_add(json
, "advertisedRoutes", json_ar
);
13702 json_object_int_add(json
, "totalPrefixCounter", output_count
);
13703 json_object_int_add(json
, "filteredPrefixCounter",
13706 vty_out(vty
, "%s\n",
13707 json_object_to_json_string_ext(
13708 json
, JSON_C_TO_STRING_PRETTY
));
13710 if (!output_count
&& !filtered_count
) {
13711 json_object_free(json_scode
);
13712 json_object_free(json_ocode
);
13716 json_object_free(json
);
13718 } else if (output_count
> 0) {
13719 if (filtered_count
> 0)
13721 "\nTotal number of prefixes %ld (%ld filtered)\n",
13722 output_count
, filtered_count
);
13724 vty_out(vty
, "\nTotal number of prefixes %ld\n",
13728 return CMD_SUCCESS
;
13731 DEFPY (show_ip_bgp_instance_neighbor_bestpath_route
,
13732 show_ip_bgp_instance_neighbor_bestpath_route_cmd
,
13733 "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]",
13737 BGP_INSTANCE_HELP_STR
13739 BGP_SAFI_WITH_LABEL_HELP_STR
13740 "Detailed information on TCP and BGP neighbor connections\n"
13741 "Neighbor to display information about\n"
13742 "Neighbor to display information about\n"
13743 "Neighbor on BGP configured interface\n"
13744 "Display the routes selected by best path\n"
13746 "Increase table width for longer prefixes\n")
13748 afi_t afi
= AFI_IP6
;
13749 safi_t safi
= SAFI_UNICAST
;
13750 char *rmap_name
= NULL
;
13751 char *peerstr
= NULL
;
13752 struct bgp
*bgp
= NULL
;
13754 enum bgp_show_adj_route_type type
= bgp_show_adj_route_bestpath
;
13756 uint16_t show_flags
= 0;
13759 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13762 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
13764 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13768 return CMD_WARNING
;
13770 argv_find(argv
, argc
, "neighbors", &idx
);
13771 peerstr
= argv
[++idx
]->arg
;
13773 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
13775 return CMD_WARNING
;
13777 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
,
13781 DEFPY (show_ip_bgp_instance_neighbor_advertised_route
,
13782 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
13783 "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]",
13787 BGP_INSTANCE_HELP_STR
13789 BGP_SAFI_WITH_LABEL_HELP_STR
13790 "Display the entries for all address families\n"
13791 "Detailed information on TCP and BGP neighbor connections\n"
13792 "Neighbor to display information about\n"
13793 "Neighbor to display information about\n"
13794 "Neighbor on BGP configured interface\n"
13795 "Display the routes advertised to a BGP neighbor\n"
13796 "Display the received routes from neighbor\n"
13797 "Display the filtered routes received from neighbor\n"
13798 "Route-map to modify the attributes\n"
13799 "Name of the route map\n"
13801 "Increase table width for longer prefixes\n")
13803 afi_t afi
= AFI_IP6
;
13804 safi_t safi
= SAFI_UNICAST
;
13805 char *rmap_name
= NULL
;
13806 char *peerstr
= NULL
;
13807 struct bgp
*bgp
= NULL
;
13809 enum bgp_show_adj_route_type type
= bgp_show_adj_route_advertised
;
13812 uint16_t show_flags
= 0;
13816 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13820 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
13821 if (argv_find(argv
, argc
, "ipv4", &idx
))
13822 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
13824 if (argv_find(argv
, argc
, "ipv6", &idx
))
13825 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
13829 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
13831 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13834 return CMD_WARNING
;
13836 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13837 argv_find(argv
, argc
, "neighbors", &idx
);
13838 peerstr
= argv
[++idx
]->arg
;
13840 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
13842 return CMD_WARNING
;
13844 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
13845 type
= bgp_show_adj_route_advertised
;
13846 else if (argv_find(argv
, argc
, "received-routes", &idx
))
13847 type
= bgp_show_adj_route_received
;
13848 else if (argv_find(argv
, argc
, "filtered-routes", &idx
))
13849 type
= bgp_show_adj_route_filtered
;
13851 if (argv_find(argv
, argc
, "route-map", &idx
))
13852 rmap_name
= argv
[++idx
]->arg
;
13855 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
,
13858 vty_out(vty
, "{\n");
13860 if (CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
13861 || CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
)) {
13862 afi
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
) ? AFI_IP
13864 FOREACH_SAFI (safi
) {
13865 if (!bgp_afi_safi_peer_exists(bgp
, afi
, safi
))
13872 vty_out(vty
, ",\n");
13873 vty_out(vty
, "\"%s\":",
13874 get_afi_safi_str(afi
, safi
, true));
13876 vty_out(vty
, "\nFor address family: %s\n",
13877 get_afi_safi_str(afi
, safi
, false));
13879 peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
,
13883 FOREACH_AFI_SAFI (afi
, safi
) {
13884 if (!bgp_afi_safi_peer_exists(bgp
, afi
, safi
))
13891 vty_out(vty
, ",\n");
13892 vty_out(vty
, "\"%s\":",
13893 get_afi_safi_str(afi
, safi
, true));
13895 vty_out(vty
, "\nFor address family: %s\n",
13896 get_afi_safi_str(afi
, safi
, false));
13898 peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
,
13903 vty_out(vty
, "}\n");
13905 return CMD_SUCCESS
;
13908 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
13909 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
13910 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
13916 "Address Family modifier\n"
13917 "Detailed information on TCP and BGP neighbor connections\n"
13918 "Neighbor to display information about\n"
13919 "Neighbor to display information about\n"
13920 "Neighbor on BGP configured interface\n"
13921 "Display information received from a BGP neighbor\n"
13922 "Display the prefixlist filter\n"
13925 afi_t afi
= AFI_IP6
;
13926 safi_t safi
= SAFI_UNICAST
;
13927 char *peerstr
= NULL
;
13930 union sockunion su
;
13936 /* show [ip] bgp */
13937 if (argv_find(argv
, argc
, "ip", &idx
))
13939 /* [<ipv4|ipv6> [unicast]] */
13940 if (argv_find(argv
, argc
, "ipv4", &idx
))
13942 if (argv_find(argv
, argc
, "ipv6", &idx
))
13944 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13945 argv_find(argv
, argc
, "neighbors", &idx
);
13946 peerstr
= argv
[++idx
]->arg
;
13948 bool uj
= use_json(argc
, argv
);
13950 ret
= str2sockunion(peerstr
, &su
);
13952 peer
= peer_lookup_by_conf_if(NULL
, peerstr
);
13955 vty_out(vty
, "{}\n");
13958 "%% Malformed address or name: %s\n",
13960 return CMD_WARNING
;
13963 peer
= peer_lookup(NULL
, &su
);
13966 vty_out(vty
, "{}\n");
13968 vty_out(vty
, "No peer\n");
13969 return CMD_WARNING
;
13973 snprintf(name
, sizeof(name
), "%s.%d.%d", peer
->host
, afi
, safi
);
13974 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
13977 vty_out(vty
, "Address Family: %s\n",
13978 get_afi_safi_str(afi
, safi
, false));
13979 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
13982 vty_out(vty
, "{}\n");
13984 vty_out(vty
, "No functional output\n");
13987 return CMD_SUCCESS
;
13990 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
13991 afi_t afi
, safi_t safi
,
13992 enum bgp_show_type type
, bool use_json
)
13994 uint16_t show_flags
= 0;
13997 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13999 if (!peer
|| !peer
->afc
[afi
][safi
]) {
14001 json_object
*json_no
= NULL
;
14002 json_no
= json_object_new_object();
14003 json_object_string_add(
14004 json_no
, "warning",
14005 "No such neighbor or address family");
14006 vty_out(vty
, "%s\n",
14007 json_object_to_json_string(json_no
));
14008 json_object_free(json_no
);
14010 vty_out(vty
, "%% No such neighbor or address family\n");
14011 return CMD_WARNING
;
14014 /* labeled-unicast routes live in the unicast table */
14015 if (safi
== SAFI_LABELED_UNICAST
)
14016 safi
= SAFI_UNICAST
;
14018 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, show_flags
,
14019 RPKI_NOT_BEING_USED
);
14022 DEFUN (show_ip_bgp_flowspec_routes_detailed
,
14023 show_ip_bgp_flowspec_routes_detailed_cmd
,
14024 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" flowspec] detail [json]",
14028 BGP_INSTANCE_HELP_STR
14031 "Detailed information on flowspec entries\n"
14034 afi_t afi
= AFI_IP
;
14035 safi_t safi
= SAFI_UNICAST
;
14036 struct bgp
*bgp
= NULL
;
14038 bool uj
= use_json(argc
, argv
);
14039 uint16_t show_flags
= 0;
14043 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14046 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14049 return CMD_WARNING
;
14051 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_detail
, NULL
,
14052 show_flags
, RPKI_NOT_BEING_USED
);
14055 DEFUN (show_ip_bgp_neighbor_routes
,
14056 show_ip_bgp_neighbor_routes_cmd
,
14057 "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]",
14061 BGP_INSTANCE_HELP_STR
14063 BGP_SAFI_WITH_LABEL_HELP_STR
14064 "Detailed information on TCP and BGP neighbor connections\n"
14065 "Neighbor to display information about\n"
14066 "Neighbor to display information about\n"
14067 "Neighbor on BGP configured interface\n"
14068 "Display flap statistics of the routes learned from neighbor\n"
14069 "Display the dampened routes received from neighbor\n"
14070 "Display routes learned from neighbor\n"
14073 char *peerstr
= NULL
;
14074 struct bgp
*bgp
= NULL
;
14075 afi_t afi
= AFI_IP6
;
14076 safi_t safi
= SAFI_UNICAST
;
14078 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
14080 bool uj
= use_json(argc
, argv
);
14085 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14088 return CMD_WARNING
;
14090 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14091 argv_find(argv
, argc
, "neighbors", &idx
);
14092 peerstr
= argv
[++idx
]->arg
;
14094 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14096 return CMD_WARNING
;
14098 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
14099 sh_type
= bgp_show_type_flap_neighbor
;
14100 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
14101 sh_type
= bgp_show_type_damp_neighbor
;
14102 else if (argv_find(argv
, argc
, "routes", &idx
))
14103 sh_type
= bgp_show_type_neighbor
;
14105 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
14108 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
14110 struct bgp_distance
{
14111 /* Distance value for the IP source prefix. */
14114 /* Name of the access-list to be matched. */
14118 DEFUN (show_bgp_afi_vpn_rd_route
,
14119 show_bgp_afi_vpn_rd_route_cmd
,
14120 "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]",
14124 "Address Family modifier\n"
14125 "Display information for a route distinguisher\n"
14126 "Route Distinguisher\n"
14127 "All Route Distinguishers\n"
14128 "Network in the BGP routing table to display\n"
14129 "Network in the BGP routing table to display\n"
14133 struct prefix_rd prd
;
14134 afi_t afi
= AFI_MAX
;
14137 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
14138 vty_out(vty
, "%% Malformed Address Family\n");
14139 return CMD_WARNING
;
14142 if (!strcmp(argv
[5]->arg
, "all"))
14143 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
,
14144 SAFI_MPLS_VPN
, NULL
, 0, BGP_PATH_SHOW_ALL
,
14145 RPKI_NOT_BEING_USED
,
14146 use_json(argc
, argv
));
14148 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
14150 vty_out(vty
, "%% Malformed Route Distinguisher\n");
14151 return CMD_WARNING
;
14154 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
14155 0, BGP_PATH_SHOW_ALL
, RPKI_NOT_BEING_USED
,
14156 use_json(argc
, argv
));
14159 static struct bgp_distance
*bgp_distance_new(void)
14161 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
14164 static void bgp_distance_free(struct bgp_distance
*bdistance
)
14166 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
14169 static int bgp_distance_set(struct vty
*vty
, const char *distance_str
,
14170 const char *ip_str
, const char *access_list_str
)
14177 struct bgp_dest
*dest
;
14178 struct bgp_distance
*bdistance
;
14180 afi
= bgp_node_afi(vty
);
14181 safi
= bgp_node_safi(vty
);
14183 ret
= str2prefix(ip_str
, &p
);
14185 vty_out(vty
, "Malformed prefix\n");
14186 return CMD_WARNING_CONFIG_FAILED
;
14189 distance
= atoi(distance_str
);
14191 /* Get BGP distance node. */
14192 dest
= bgp_node_get(bgp_distance_table
[afi
][safi
], &p
);
14193 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
14195 bgp_dest_unlock_node(dest
);
14197 bdistance
= bgp_distance_new();
14198 bgp_dest_set_bgp_distance_info(dest
, bdistance
);
14201 /* Set distance value. */
14202 bdistance
->distance
= distance
;
14204 /* Reset access-list configuration. */
14205 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
14206 if (access_list_str
)
14207 bdistance
->access_list
=
14208 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
14210 return CMD_SUCCESS
;
14213 static int bgp_distance_unset(struct vty
*vty
, const char *distance_str
,
14214 const char *ip_str
, const char *access_list_str
)
14221 struct bgp_dest
*dest
;
14222 struct bgp_distance
*bdistance
;
14224 afi
= bgp_node_afi(vty
);
14225 safi
= bgp_node_safi(vty
);
14227 ret
= str2prefix(ip_str
, &p
);
14229 vty_out(vty
, "Malformed prefix\n");
14230 return CMD_WARNING_CONFIG_FAILED
;
14233 dest
= bgp_node_lookup(bgp_distance_table
[afi
][safi
], &p
);
14235 vty_out(vty
, "Can't find specified prefix\n");
14236 return CMD_WARNING_CONFIG_FAILED
;
14239 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
14240 distance
= atoi(distance_str
);
14242 if (bdistance
->distance
!= distance
) {
14243 vty_out(vty
, "Distance does not match configured\n");
14244 bgp_dest_unlock_node(dest
);
14245 return CMD_WARNING_CONFIG_FAILED
;
14248 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
14249 bgp_distance_free(bdistance
);
14251 bgp_dest_set_bgp_path_info(dest
, NULL
);
14252 bgp_dest_unlock_node(dest
);
14253 bgp_dest_unlock_node(dest
);
14255 return CMD_SUCCESS
;
14258 /* Apply BGP information to distance method. */
14259 uint8_t bgp_distance_apply(const struct prefix
*p
, struct bgp_path_info
*pinfo
,
14260 afi_t afi
, safi_t safi
, struct bgp
*bgp
)
14262 struct bgp_dest
*dest
;
14263 struct prefix q
= {0};
14265 struct bgp_distance
*bdistance
;
14266 struct access_list
*alist
;
14267 struct bgp_static
*bgp_static
;
14272 peer
= pinfo
->peer
;
14274 if (pinfo
->attr
->distance
)
14275 return pinfo
->attr
->distance
;
14277 /* Check source address.
14278 * Note: for aggregate route, peer can have unspec af type.
14280 if (pinfo
->sub_type
!= BGP_ROUTE_AGGREGATE
14281 && !sockunion2hostprefix(&peer
->su
, &q
))
14284 dest
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
14286 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
14287 bgp_dest_unlock_node(dest
);
14289 if (bdistance
->access_list
) {
14290 alist
= access_list_lookup(afi
, bdistance
->access_list
);
14292 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
14293 return bdistance
->distance
;
14295 return bdistance
->distance
;
14298 /* Backdoor check. */
14299 dest
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
14301 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
14302 bgp_dest_unlock_node(dest
);
14304 if (bgp_static
->backdoor
) {
14305 if (bgp
->distance_local
[afi
][safi
])
14306 return bgp
->distance_local
[afi
][safi
];
14308 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
14312 if (peer
->sort
== BGP_PEER_EBGP
) {
14313 if (bgp
->distance_ebgp
[afi
][safi
])
14314 return bgp
->distance_ebgp
[afi
][safi
];
14315 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
14316 } else if (peer
->sort
== BGP_PEER_IBGP
) {
14317 if (bgp
->distance_ibgp
[afi
][safi
])
14318 return bgp
->distance_ibgp
[afi
][safi
];
14319 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
14321 if (bgp
->distance_local
[afi
][safi
])
14322 return bgp
->distance_local
[afi
][safi
];
14323 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
14327 /* If we enter `distance bgp (1-255) (1-255) (1-255)`,
14328 * we should tell ZEBRA update the routes for a specific
14329 * AFI/SAFI to reflect changes in RIB.
14331 static void bgp_announce_routes_distance_update(struct bgp
*bgp
,
14333 safi_t update_safi
)
14338 FOREACH_AFI_SAFI (afi
, safi
) {
14339 if (!bgp_fibupd_safi(safi
))
14342 if (afi
!= update_afi
&& safi
!= update_safi
)
14345 if (BGP_DEBUG(zebra
, ZEBRA
))
14347 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
14348 __func__
, afi
, safi
);
14349 bgp_zebra_announce_table(bgp
, afi
, safi
);
14353 DEFUN (bgp_distance
,
14355 "distance bgp (1-255) (1-255) (1-255)",
14356 "Define an administrative distance\n"
14358 "Distance for routes external to the AS\n"
14359 "Distance for routes internal to the AS\n"
14360 "Distance for local routes\n")
14362 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
14363 int idx_number
= 2;
14364 int idx_number_2
= 3;
14365 int idx_number_3
= 4;
14366 int distance_ebgp
= atoi(argv
[idx_number
]->arg
);
14367 int distance_ibgp
= atoi(argv
[idx_number_2
]->arg
);
14368 int distance_local
= atoi(argv
[idx_number_3
]->arg
);
14372 afi
= bgp_node_afi(vty
);
14373 safi
= bgp_node_safi(vty
);
14375 if (bgp
->distance_ebgp
[afi
][safi
] != distance_ebgp
14376 || bgp
->distance_ibgp
[afi
][safi
] != distance_ibgp
14377 || bgp
->distance_local
[afi
][safi
] != distance_local
) {
14378 bgp
->distance_ebgp
[afi
][safi
] = distance_ebgp
;
14379 bgp
->distance_ibgp
[afi
][safi
] = distance_ibgp
;
14380 bgp
->distance_local
[afi
][safi
] = distance_local
;
14381 bgp_announce_routes_distance_update(bgp
, afi
, safi
);
14383 return CMD_SUCCESS
;
14386 DEFUN (no_bgp_distance
,
14387 no_bgp_distance_cmd
,
14388 "no distance bgp [(1-255) (1-255) (1-255)]",
14390 "Define an administrative distance\n"
14392 "Distance for routes external to the AS\n"
14393 "Distance for routes internal to the AS\n"
14394 "Distance for local routes\n")
14396 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
14400 afi
= bgp_node_afi(vty
);
14401 safi
= bgp_node_safi(vty
);
14403 if (bgp
->distance_ebgp
[afi
][safi
] != 0
14404 || bgp
->distance_ibgp
[afi
][safi
] != 0
14405 || bgp
->distance_local
[afi
][safi
] != 0) {
14406 bgp
->distance_ebgp
[afi
][safi
] = 0;
14407 bgp
->distance_ibgp
[afi
][safi
] = 0;
14408 bgp
->distance_local
[afi
][safi
] = 0;
14409 bgp_announce_routes_distance_update(bgp
, afi
, safi
);
14411 return CMD_SUCCESS
;
14415 DEFUN (bgp_distance_source
,
14416 bgp_distance_source_cmd
,
14417 "distance (1-255) A.B.C.D/M",
14418 "Define an administrative distance\n"
14419 "Administrative distance\n"
14420 "IP source prefix\n")
14422 int idx_number
= 1;
14423 int idx_ipv4_prefixlen
= 2;
14424 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
14425 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
14426 return CMD_SUCCESS
;
14429 DEFUN (no_bgp_distance_source
,
14430 no_bgp_distance_source_cmd
,
14431 "no distance (1-255) A.B.C.D/M",
14433 "Define an administrative distance\n"
14434 "Administrative distance\n"
14435 "IP source prefix\n")
14437 int idx_number
= 2;
14438 int idx_ipv4_prefixlen
= 3;
14439 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
14440 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
14441 return CMD_SUCCESS
;
14444 DEFUN (bgp_distance_source_access_list
,
14445 bgp_distance_source_access_list_cmd
,
14446 "distance (1-255) A.B.C.D/M WORD",
14447 "Define an administrative distance\n"
14448 "Administrative distance\n"
14449 "IP source prefix\n"
14450 "Access list name\n")
14452 int idx_number
= 1;
14453 int idx_ipv4_prefixlen
= 2;
14455 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
14456 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
14457 return CMD_SUCCESS
;
14460 DEFUN (no_bgp_distance_source_access_list
,
14461 no_bgp_distance_source_access_list_cmd
,
14462 "no distance (1-255) A.B.C.D/M WORD",
14464 "Define an administrative distance\n"
14465 "Administrative distance\n"
14466 "IP source prefix\n"
14467 "Access list name\n")
14469 int idx_number
= 2;
14470 int idx_ipv4_prefixlen
= 3;
14472 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
14473 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
14474 return CMD_SUCCESS
;
14477 DEFUN (ipv6_bgp_distance_source
,
14478 ipv6_bgp_distance_source_cmd
,
14479 "distance (1-255) X:X::X:X/M",
14480 "Define an administrative distance\n"
14481 "Administrative distance\n"
14482 "IP source prefix\n")
14484 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, NULL
);
14485 return CMD_SUCCESS
;
14488 DEFUN (no_ipv6_bgp_distance_source
,
14489 no_ipv6_bgp_distance_source_cmd
,
14490 "no distance (1-255) X:X::X:X/M",
14492 "Define an administrative distance\n"
14493 "Administrative distance\n"
14494 "IP source prefix\n")
14496 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, NULL
);
14497 return CMD_SUCCESS
;
14500 DEFUN (ipv6_bgp_distance_source_access_list
,
14501 ipv6_bgp_distance_source_access_list_cmd
,
14502 "distance (1-255) X:X::X:X/M WORD",
14503 "Define an administrative distance\n"
14504 "Administrative distance\n"
14505 "IP source prefix\n"
14506 "Access list name\n")
14508 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, argv
[3]->arg
);
14509 return CMD_SUCCESS
;
14512 DEFUN (no_ipv6_bgp_distance_source_access_list
,
14513 no_ipv6_bgp_distance_source_access_list_cmd
,
14514 "no distance (1-255) X:X::X:X/M WORD",
14516 "Define an administrative distance\n"
14517 "Administrative distance\n"
14518 "IP source prefix\n"
14519 "Access list name\n")
14521 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, argv
[4]->arg
);
14522 return CMD_SUCCESS
;
14525 DEFUN (bgp_damp_set
,
14527 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
14528 "BGP Specific commands\n"
14529 "Enable route-flap dampening\n"
14530 "Half-life time for the penalty\n"
14531 "Value to start reusing a route\n"
14532 "Value to start suppressing a route\n"
14533 "Maximum duration to suppress a stable route\n")
14535 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
14536 int idx_half_life
= 2;
14538 int idx_suppress
= 4;
14539 int idx_max_suppress
= 5;
14540 int half
= DEFAULT_HALF_LIFE
* 60;
14541 int reuse
= DEFAULT_REUSE
;
14542 int suppress
= DEFAULT_SUPPRESS
;
14543 int max
= 4 * half
;
14546 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
14547 reuse
= atoi(argv
[idx_reuse
]->arg
);
14548 suppress
= atoi(argv
[idx_suppress
]->arg
);
14549 max
= atoi(argv
[idx_max_suppress
]->arg
) * 60;
14550 } else if (argc
== 3) {
14551 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
14556 * These can't be 0 but our SA doesn't understand the
14557 * way our cli is constructed
14561 if (suppress
< reuse
) {
14563 "Suppress value cannot be less than reuse value \n");
14567 return bgp_damp_enable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
), half
,
14568 reuse
, suppress
, max
);
14571 DEFUN (bgp_damp_unset
,
14572 bgp_damp_unset_cmd
,
14573 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
14575 "BGP Specific commands\n"
14576 "Enable route-flap dampening\n"
14577 "Half-life time for the penalty\n"
14578 "Value to start reusing a route\n"
14579 "Value to start suppressing a route\n"
14580 "Maximum duration to suppress a stable route\n")
14582 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
14583 return bgp_damp_disable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
));
14586 /* Display specified route of BGP table. */
14587 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
14588 const char *ip_str
, afi_t afi
, safi_t safi
,
14589 struct prefix_rd
*prd
, int prefix_check
)
14592 struct prefix match
;
14593 struct bgp_dest
*dest
;
14594 struct bgp_dest
*rm
;
14595 struct bgp_path_info
*pi
;
14596 struct bgp_path_info
*pi_temp
;
14598 struct bgp_table
*table
;
14600 /* BGP structure lookup. */
14602 bgp
= bgp_lookup_by_name(view_name
);
14604 vty_out(vty
, "%% Can't find BGP instance %s\n",
14606 return CMD_WARNING
;
14609 bgp
= bgp_get_default();
14611 vty_out(vty
, "%% No BGP process is configured\n");
14612 return CMD_WARNING
;
14616 /* Check IP address argument. */
14617 ret
= str2prefix(ip_str
, &match
);
14619 vty_out(vty
, "%% address is malformed\n");
14620 return CMD_WARNING
;
14623 match
.family
= afi2family(afi
);
14625 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
14626 || (safi
== SAFI_EVPN
)) {
14627 for (dest
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); dest
;
14628 dest
= bgp_route_next(dest
)) {
14629 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
14631 if (prd
&& memcmp(dest_p
->u
.val
, prd
->val
, 8) != 0)
14633 table
= bgp_dest_get_bgp_table_info(dest
);
14636 rm
= bgp_node_match(table
, &match
);
14640 const struct prefix
*rm_p
= bgp_dest_get_prefix(dest
);
14643 || rm_p
->prefixlen
== match
.prefixlen
) {
14644 pi
= bgp_dest_get_bgp_path_info(rm
);
14646 if (pi
->extra
&& pi
->extra
->damp_info
) {
14647 pi_temp
= pi
->next
;
14648 bgp_damp_info_free(
14649 pi
->extra
->damp_info
,
14657 bgp_dest_unlock_node(rm
);
14660 dest
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
);
14661 if (dest
!= NULL
) {
14662 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
14665 || dest_p
->prefixlen
== match
.prefixlen
) {
14666 pi
= bgp_dest_get_bgp_path_info(dest
);
14668 if (pi
->extra
&& pi
->extra
->damp_info
) {
14669 pi_temp
= pi
->next
;
14670 bgp_damp_info_free(
14671 pi
->extra
->damp_info
,
14679 bgp_dest_unlock_node(dest
);
14683 return CMD_SUCCESS
;
14686 DEFUN (clear_ip_bgp_dampening
,
14687 clear_ip_bgp_dampening_cmd
,
14688 "clear ip bgp dampening",
14692 "Clear route flap dampening information\n")
14694 bgp_damp_info_clean(AFI_IP
, SAFI_UNICAST
);
14695 return CMD_SUCCESS
;
14698 DEFUN (clear_ip_bgp_dampening_prefix
,
14699 clear_ip_bgp_dampening_prefix_cmd
,
14700 "clear ip bgp dampening A.B.C.D/M",
14704 "Clear route flap dampening information\n"
14707 int idx_ipv4_prefixlen
= 4;
14708 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
14709 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
14712 DEFUN (clear_ip_bgp_dampening_address
,
14713 clear_ip_bgp_dampening_address_cmd
,
14714 "clear ip bgp dampening A.B.C.D",
14718 "Clear route flap dampening information\n"
14719 "Network to clear damping information\n")
14722 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
14723 SAFI_UNICAST
, NULL
, 0);
14726 DEFUN (clear_ip_bgp_dampening_address_mask
,
14727 clear_ip_bgp_dampening_address_mask_cmd
,
14728 "clear ip bgp dampening A.B.C.D A.B.C.D",
14732 "Clear route flap dampening information\n"
14733 "Network to clear damping information\n"
14737 int idx_ipv4_2
= 5;
14739 char prefix_str
[BUFSIZ
];
14741 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
14742 prefix_str
, sizeof(prefix_str
));
14744 vty_out(vty
, "%% Inconsistent address and mask\n");
14745 return CMD_WARNING
;
14748 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
14752 static void show_bgp_peerhash_entry(struct hash_bucket
*bucket
, void *arg
)
14754 struct vty
*vty
= arg
;
14755 struct peer
*peer
= bucket
->data
;
14756 char buf
[SU_ADDRSTRLEN
];
14758 vty_out(vty
, "\tPeer: %s %s\n", peer
->host
,
14759 sockunion2str(&peer
->su
, buf
, sizeof(buf
)));
14762 DEFUN (show_bgp_listeners
,
14763 show_bgp_listeners_cmd
,
14764 "show bgp listeners",
14767 "Display Listen Sockets and who created them\n")
14769 bgp_dump_listener_info(vty
);
14771 return CMD_SUCCESS
;
14774 DEFUN (show_bgp_peerhash
,
14775 show_bgp_peerhash_cmd
,
14776 "show bgp peerhash",
14779 "Display information about the BGP peerhash\n")
14781 struct list
*instances
= bm
->bgp
;
14782 struct listnode
*node
;
14785 for (ALL_LIST_ELEMENTS_RO(instances
, node
, bgp
)) {
14786 vty_out(vty
, "BGP: %s\n", bgp
->name
);
14787 hash_iterate(bgp
->peerhash
, show_bgp_peerhash_entry
,
14791 return CMD_SUCCESS
;
14794 /* also used for encap safi */
14795 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
14796 afi_t afi
, safi_t safi
)
14798 struct bgp_dest
*pdest
;
14799 struct bgp_dest
*dest
;
14800 struct bgp_table
*table
;
14801 const struct prefix
*p
;
14802 const struct prefix_rd
*prd
;
14803 struct bgp_static
*bgp_static
;
14804 mpls_label_t label
;
14805 char rdbuf
[RD_ADDRSTRLEN
];
14807 /* Network configuration. */
14808 for (pdest
= bgp_table_top(bgp
->route
[afi
][safi
]); pdest
;
14809 pdest
= bgp_route_next(pdest
)) {
14810 table
= bgp_dest_get_bgp_table_info(pdest
);
14814 for (dest
= bgp_table_top(table
); dest
;
14815 dest
= bgp_route_next(dest
)) {
14816 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
14817 if (bgp_static
== NULL
)
14820 p
= bgp_dest_get_prefix(dest
);
14821 prd
= (const struct prefix_rd
*)bgp_dest_get_prefix(
14824 /* "network" configuration display. */
14825 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
14826 label
= decode_label(&bgp_static
->label
);
14828 vty_out(vty
, " network %pFX rd %s", p
, rdbuf
);
14829 if (safi
== SAFI_MPLS_VPN
)
14830 vty_out(vty
, " label %u", label
);
14832 if (bgp_static
->rmap
.name
)
14833 vty_out(vty
, " route-map %s",
14834 bgp_static
->rmap
.name
);
14836 if (bgp_static
->backdoor
)
14837 vty_out(vty
, " backdoor");
14839 vty_out(vty
, "\n");
14844 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
14845 afi_t afi
, safi_t safi
)
14847 struct bgp_dest
*pdest
;
14848 struct bgp_dest
*dest
;
14849 struct bgp_table
*table
;
14850 const struct prefix
*p
;
14851 const struct prefix_rd
*prd
;
14852 struct bgp_static
*bgp_static
;
14853 char buf
[PREFIX_STRLEN
* 2];
14854 char buf2
[SU_ADDRSTRLEN
];
14855 char rdbuf
[RD_ADDRSTRLEN
];
14856 char esi_buf
[ESI_BYTES
];
14858 /* Network configuration. */
14859 for (pdest
= bgp_table_top(bgp
->route
[afi
][safi
]); pdest
;
14860 pdest
= bgp_route_next(pdest
)) {
14861 table
= bgp_dest_get_bgp_table_info(pdest
);
14865 for (dest
= bgp_table_top(table
); dest
;
14866 dest
= bgp_route_next(dest
)) {
14867 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
14868 if (bgp_static
== NULL
)
14871 char *macrouter
= NULL
;
14873 if (bgp_static
->router_mac
)
14874 macrouter
= prefix_mac2str(
14875 bgp_static
->router_mac
, NULL
, 0);
14876 if (bgp_static
->eth_s_id
)
14877 esi_to_str(bgp_static
->eth_s_id
,
14878 esi_buf
, sizeof(esi_buf
));
14879 p
= bgp_dest_get_prefix(dest
);
14880 prd
= (struct prefix_rd
*)bgp_dest_get_prefix(pdest
);
14882 /* "network" configuration display. */
14883 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
14884 if (p
->u
.prefix_evpn
.route_type
== 5) {
14885 char local_buf
[PREFIX_STRLEN
];
14886 uint8_t family
= is_evpn_prefix_ipaddr_v4((
14887 struct prefix_evpn
*)p
)
14891 &p
->u
.prefix_evpn
.prefix_addr
.ip
.ip
.addr
,
14892 local_buf
, PREFIX_STRLEN
);
14893 snprintf(buf
, sizeof(buf
), "%s/%u", local_buf
,
14894 p
->u
.prefix_evpn
.prefix_addr
14895 .ip_prefix_length
);
14897 prefix2str(p
, buf
, sizeof(buf
));
14900 if (bgp_static
->gatewayIp
.family
== AF_INET
14901 || bgp_static
->gatewayIp
.family
== AF_INET6
)
14902 inet_ntop(bgp_static
->gatewayIp
.family
,
14903 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
14906 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
14908 p
->u
.prefix_evpn
.prefix_addr
.eth_tag
,
14909 decode_label(&bgp_static
->label
), esi_buf
, buf2
,
14912 XFREE(MTYPE_TMP
, macrouter
);
14917 /* Configuration of static route announcement and aggregate
14919 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
14922 struct bgp_dest
*dest
;
14923 const struct prefix
*p
;
14924 struct bgp_static
*bgp_static
;
14925 struct bgp_aggregate
*bgp_aggregate
;
14927 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
14928 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
14932 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
14933 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
14937 /* Network configuration. */
14938 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
14939 dest
= bgp_route_next(dest
)) {
14940 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
14941 if (bgp_static
== NULL
)
14944 p
= bgp_dest_get_prefix(dest
);
14946 vty_out(vty
, " network %pFX", p
);
14948 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
14949 vty_out(vty
, " label-index %u",
14950 bgp_static
->label_index
);
14952 if (bgp_static
->rmap
.name
)
14953 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
14955 if (bgp_static
->backdoor
)
14956 vty_out(vty
, " backdoor");
14958 vty_out(vty
, "\n");
14961 /* Aggregate-address configuration. */
14962 for (dest
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); dest
;
14963 dest
= bgp_route_next(dest
)) {
14964 bgp_aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
14965 if (bgp_aggregate
== NULL
)
14968 p
= bgp_dest_get_prefix(dest
);
14970 vty_out(vty
, " aggregate-address %pFX", p
);
14972 if (bgp_aggregate
->as_set
)
14973 vty_out(vty
, " as-set");
14975 if (bgp_aggregate
->summary_only
)
14976 vty_out(vty
, " summary-only");
14978 if (bgp_aggregate
->rmap
.name
)
14979 vty_out(vty
, " route-map %s", bgp_aggregate
->rmap
.name
);
14981 if (bgp_aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
14982 vty_out(vty
, " origin %s",
14983 bgp_origin2str(bgp_aggregate
->origin
));
14985 if (bgp_aggregate
->match_med
)
14986 vty_out(vty
, " matching-MED-only");
14988 if (bgp_aggregate
->suppress_map_name
)
14989 vty_out(vty
, " suppress-map %s",
14990 bgp_aggregate
->suppress_map_name
);
14992 vty_out(vty
, "\n");
14996 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
14999 struct bgp_dest
*dest
;
15000 struct bgp_distance
*bdistance
;
15002 /* Distance configuration. */
15003 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
15004 && bgp
->distance_local
[afi
][safi
]
15005 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
15006 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
15007 || bgp
->distance_local
[afi
][safi
]
15008 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
15009 vty_out(vty
, " distance bgp %d %d %d\n",
15010 bgp
->distance_ebgp
[afi
][safi
],
15011 bgp
->distance_ibgp
[afi
][safi
],
15012 bgp
->distance_local
[afi
][safi
]);
15015 for (dest
= bgp_table_top(bgp_distance_table
[afi
][safi
]); dest
;
15016 dest
= bgp_route_next(dest
)) {
15017 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
15018 if (bdistance
!= NULL
)
15019 vty_out(vty
, " distance %d %pBD %s\n",
15020 bdistance
->distance
, dest
,
15021 bdistance
->access_list
? bdistance
->access_list
15026 /* Allocate routing table structure and install commands. */
15027 void bgp_route_init(void)
15032 /* Init BGP distance table. */
15033 FOREACH_AFI_SAFI (afi
, safi
)
15034 bgp_distance_table
[afi
][safi
] = bgp_table_init(NULL
, afi
, safi
);
15036 /* IPv4 BGP commands. */
15037 install_element(BGP_NODE
, &bgp_table_map_cmd
);
15038 install_element(BGP_NODE
, &bgp_network_cmd
);
15039 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
15041 install_element(BGP_NODE
, &aggregate_addressv4_cmd
);
15043 /* IPv4 unicast configuration. */
15044 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
15045 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
15046 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
15048 install_element(BGP_IPV4_NODE
, &aggregate_addressv4_cmd
);
15050 /* IPv4 multicast configuration. */
15051 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
15052 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
15053 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
15054 install_element(BGP_IPV4M_NODE
, &aggregate_addressv4_cmd
);
15056 /* IPv4 labeled-unicast configuration. */
15057 install_element(BGP_IPV4L_NODE
, &bgp_network_cmd
);
15058 install_element(BGP_IPV4L_NODE
, &aggregate_addressv4_cmd
);
15060 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
15061 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
15062 install_element(VIEW_NODE
, &show_ip_bgp_afi_safi_statistics_cmd
);
15063 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_statistics_cmd
);
15064 install_element(VIEW_NODE
, &show_ip_bgp_json_cmd
);
15065 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
15066 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
15067 install_element(VIEW_NODE
, &show_ip_bgp_statistics_all_cmd
);
15069 install_element(VIEW_NODE
,
15070 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
15071 install_element(VIEW_NODE
,
15072 &show_ip_bgp_instance_neighbor_bestpath_route_cmd
);
15073 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
15074 install_element(VIEW_NODE
,
15075 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
15076 #ifdef KEEP_OLD_VPN_COMMANDS
15077 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
15078 #endif /* KEEP_OLD_VPN_COMMANDS */
15079 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
15080 install_element(VIEW_NODE
,
15081 &show_bgp_l2vpn_evpn_route_prefix_cmd
);
15083 /* BGP dampening clear commands */
15084 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
15085 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
15087 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
15088 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
15091 install_element(ENABLE_NODE
,
15092 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
15093 #ifdef KEEP_OLD_VPN_COMMANDS
15094 install_element(ENABLE_NODE
,
15095 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
15096 #endif /* KEEP_OLD_VPN_COMMANDS */
15098 /* New config IPv6 BGP commands. */
15099 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
15100 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
15101 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
15103 install_element(BGP_IPV6_NODE
, &aggregate_addressv6_cmd
);
15105 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
15107 /* IPv6 labeled unicast address family. */
15108 install_element(BGP_IPV6L_NODE
, &ipv6_bgp_network_cmd
);
15109 install_element(BGP_IPV6L_NODE
, &aggregate_addressv6_cmd
);
15111 install_element(BGP_NODE
, &bgp_distance_cmd
);
15112 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
15113 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
15114 install_element(BGP_NODE
, &no_bgp_distance_source_cmd
);
15115 install_element(BGP_NODE
, &bgp_distance_source_access_list_cmd
);
15116 install_element(BGP_NODE
, &no_bgp_distance_source_access_list_cmd
);
15117 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
15118 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
15119 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
15120 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_cmd
);
15121 install_element(BGP_IPV4_NODE
, &bgp_distance_source_access_list_cmd
);
15122 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_access_list_cmd
);
15123 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
15124 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
15125 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
15126 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_source_cmd
);
15127 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_access_list_cmd
);
15128 install_element(BGP_IPV4M_NODE
,
15129 &no_bgp_distance_source_access_list_cmd
);
15130 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
15131 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
15132 install_element(BGP_IPV6_NODE
, &ipv6_bgp_distance_source_cmd
);
15133 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_distance_source_cmd
);
15134 install_element(BGP_IPV6_NODE
,
15135 &ipv6_bgp_distance_source_access_list_cmd
);
15136 install_element(BGP_IPV6_NODE
,
15137 &no_ipv6_bgp_distance_source_access_list_cmd
);
15138 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
15139 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
15140 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_distance_source_cmd
);
15141 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_distance_source_cmd
);
15142 install_element(BGP_IPV6M_NODE
,
15143 &ipv6_bgp_distance_source_access_list_cmd
);
15144 install_element(BGP_IPV6M_NODE
,
15145 &no_ipv6_bgp_distance_source_access_list_cmd
);
15147 /* BGP dampening */
15148 install_element(BGP_NODE
, &bgp_damp_set_cmd
);
15149 install_element(BGP_NODE
, &bgp_damp_unset_cmd
);
15150 install_element(BGP_IPV4_NODE
, &bgp_damp_set_cmd
);
15151 install_element(BGP_IPV4_NODE
, &bgp_damp_unset_cmd
);
15152 install_element(BGP_IPV4M_NODE
, &bgp_damp_set_cmd
);
15153 install_element(BGP_IPV4M_NODE
, &bgp_damp_unset_cmd
);
15154 install_element(BGP_IPV4L_NODE
, &bgp_damp_set_cmd
);
15155 install_element(BGP_IPV4L_NODE
, &bgp_damp_unset_cmd
);
15156 install_element(BGP_IPV6_NODE
, &bgp_damp_set_cmd
);
15157 install_element(BGP_IPV6_NODE
, &bgp_damp_unset_cmd
);
15158 install_element(BGP_IPV6M_NODE
, &bgp_damp_set_cmd
);
15159 install_element(BGP_IPV6M_NODE
, &bgp_damp_unset_cmd
);
15160 install_element(BGP_IPV6L_NODE
, &bgp_damp_set_cmd
);
15161 install_element(BGP_IPV6L_NODE
, &bgp_damp_unset_cmd
);
15163 /* Large Communities */
15164 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
15165 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
15167 /* show bgp ipv4 flowspec detailed */
15168 install_element(VIEW_NODE
, &show_ip_bgp_flowspec_routes_detailed_cmd
);
15170 install_element(VIEW_NODE
, &show_bgp_listeners_cmd
);
15171 install_element(VIEW_NODE
, &show_bgp_peerhash_cmd
);
15174 void bgp_route_finish(void)
15179 FOREACH_AFI_SAFI (afi
, safi
) {
15180 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
15181 bgp_distance_table
[afi
][safi
] = NULL
;