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
35 #include "sockunion.h"
38 #include "workqueue.h"
43 #include "lib_errors.h"
45 #include "bgpd/bgpd.h"
46 #include "bgpd/bgp_table.h"
47 #include "bgpd/bgp_route.h"
48 #include "bgpd/bgp_attr.h"
49 #include "bgpd/bgp_debug.h"
50 #include "bgpd/bgp_errors.h"
51 #include "bgpd/bgp_aspath.h"
52 #include "bgpd/bgp_regex.h"
53 #include "bgpd/bgp_community.h"
54 #include "bgpd/bgp_ecommunity.h"
55 #include "bgpd/bgp_lcommunity.h"
56 #include "bgpd/bgp_clist.h"
57 #include "bgpd/bgp_packet.h"
58 #include "bgpd/bgp_filter.h"
59 #include "bgpd/bgp_fsm.h"
60 #include "bgpd/bgp_mplsvpn.h"
61 #include "bgpd/bgp_nexthop.h"
62 #include "bgpd/bgp_damp.h"
63 #include "bgpd/bgp_advertise.h"
64 #include "bgpd/bgp_zebra.h"
65 #include "bgpd/bgp_vty.h"
66 #include "bgpd/bgp_mpath.h"
67 #include "bgpd/bgp_nht.h"
68 #include "bgpd/bgp_updgrp.h"
69 #include "bgpd/bgp_label.h"
70 #include "bgpd/bgp_addpath.h"
71 #include "bgpd/bgp_mac.h"
74 #include "bgpd/rfapi/rfapi_backend.h"
75 #include "bgpd/rfapi/vnc_import_bgp.h"
76 #include "bgpd/rfapi/vnc_export_bgp.h"
78 #include "bgpd/bgp_encap_types.h"
79 #include "bgpd/bgp_encap_tlv.h"
80 #include "bgpd/bgp_evpn.h"
81 #include "bgpd/bgp_evpn_vty.h"
82 #include "bgpd/bgp_flowspec.h"
83 #include "bgpd/bgp_flowspec_util.h"
84 #include "bgpd/bgp_pbr.h"
86 #ifndef VTYSH_EXTRACT_PL
87 #include "bgpd/bgp_route_clippy.c"
90 /* Extern from bgp_dump.c */
91 extern const char *bgp_origin_str
[];
92 extern const char *bgp_origin_long_str
[];
93 const char *get_afi_safi_str(afi_t afi
, safi_t safi
, bool for_json
);
95 #define PMSI_TNLTYPE_STR_NO_INFO "No info"
96 #define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
97 static const struct message bgp_pmsi_tnltype_str
[] = {
98 {PMSI_TNLTYPE_NO_INFO
, PMSI_TNLTYPE_STR_NO_INFO
},
99 {PMSI_TNLTYPE_RSVP_TE_P2MP
, "RSVP-TE P2MP"},
100 {PMSI_TNLTYPE_MLDP_P2MP
, "mLDP P2MP"},
101 {PMSI_TNLTYPE_PIM_SSM
, "PIM-SSM"},
102 {PMSI_TNLTYPE_PIM_SM
, "PIM-SM"},
103 {PMSI_TNLTYPE_PIM_BIDIR
, "PIM-BIDIR"},
104 {PMSI_TNLTYPE_INGR_REPL
, "Ingress Replication"},
105 {PMSI_TNLTYPE_MLDP_MP2MP
, "mLDP MP2MP"},
109 #define VRFID_NONE_STR "-"
111 DEFINE_HOOK(bgp_process
,
112 (struct bgp
*bgp
, afi_t afi
, safi_t safi
,
113 struct bgp_node
*bn
, struct peer
*peer
, bool withdraw
),
114 (bgp
, afi
, safi
, bn
, peer
, withdraw
))
117 struct bgp_node
*bgp_afi_node_get(struct bgp_table
*table
, afi_t afi
,
118 safi_t safi
, struct prefix
*p
,
119 struct prefix_rd
*prd
)
122 struct bgp_node
*prn
= NULL
;
128 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
129 || (safi
== SAFI_EVPN
)) {
130 prn
= bgp_node_get(table
, (struct prefix
*)prd
);
132 if (!bgp_node_has_bgp_path_info_data(prn
))
133 bgp_node_set_bgp_table_info(
134 prn
, bgp_table_init(table
->bgp
, afi
, safi
));
136 bgp_unlock_node(prn
);
137 table
= bgp_node_get_bgp_table_info(prn
);
140 rn
= bgp_node_get(table
, p
);
142 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
143 || (safi
== SAFI_EVPN
))
149 struct bgp_node
*bgp_afi_node_lookup(struct bgp_table
*table
, afi_t afi
,
150 safi_t safi
, struct prefix
*p
,
151 struct prefix_rd
*prd
)
154 struct bgp_node
*prn
= NULL
;
159 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
160 || (safi
== SAFI_EVPN
)) {
161 prn
= bgp_node_lookup(table
, (struct prefix
*)prd
);
165 if (!bgp_node_has_bgp_path_info_data(prn
)) {
166 bgp_unlock_node(prn
);
170 table
= bgp_node_get_bgp_table_info(prn
);
173 rn
= bgp_node_lookup(table
, p
);
178 /* Allocate bgp_path_info_extra */
179 static struct bgp_path_info_extra
*bgp_path_info_extra_new(void)
181 struct bgp_path_info_extra
*new;
182 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA
,
183 sizeof(struct bgp_path_info_extra
));
184 new->label
[0] = MPLS_INVALID_LABEL
;
186 new->bgp_fs_pbr
= NULL
;
187 new->bgp_fs_iprule
= NULL
;
191 void bgp_path_info_extra_free(struct bgp_path_info_extra
**extra
)
193 struct bgp_path_info_extra
*e
;
195 if (!extra
|| !*extra
)
200 bgp_damp_info_free(e
->damp_info
, 0, e
->damp_info
->afi
,
205 struct bgp_path_info
*bpi
= (struct bgp_path_info
*)e
->parent
;
208 /* FIXME: since multiple e may have the same e->parent
209 * and e->parent->net is holding a refcount for each
210 * of them, we need to do some fudging here.
212 * WARNING: if bpi->net->lock drops to 0, bpi may be
213 * freed as well (because bpi->net was holding the
214 * last reference to bpi) => write after free!
218 bpi
= bgp_path_info_lock(bpi
);
219 refcount
= bpi
->net
->lock
- 1;
220 bgp_unlock_node((struct bgp_node
*)bpi
->net
);
223 bgp_path_info_unlock(bpi
);
225 bgp_path_info_unlock(e
->parent
);
230 bgp_unlock(e
->bgp_orig
);
232 if ((*extra
)->bgp_fs_iprule
)
233 list_delete(&((*extra
)->bgp_fs_iprule
));
234 if ((*extra
)->bgp_fs_pbr
)
235 list_delete(&((*extra
)->bgp_fs_pbr
));
236 XFREE(MTYPE_BGP_ROUTE_EXTRA
, *extra
);
239 /* Get bgp_path_info extra information for the given bgp_path_info, lazy
240 * allocated if required.
242 struct bgp_path_info_extra
*bgp_path_info_extra_get(struct bgp_path_info
*pi
)
245 pi
->extra
= bgp_path_info_extra_new();
249 /* Free bgp route information. */
250 static void bgp_path_info_free(struct bgp_path_info
*path
)
252 bgp_attr_unintern(&path
->attr
);
254 bgp_unlink_nexthop(path
);
255 bgp_path_info_extra_free(&path
->extra
);
256 bgp_path_info_mpath_free(&path
->mpath
);
258 bgp_addpath_free_info_data(&path
->tx_addpath
,
259 &path
->net
->tx_addpath
);
261 peer_unlock(path
->peer
); /* bgp_path_info peer reference */
263 XFREE(MTYPE_BGP_ROUTE
, path
);
266 struct bgp_path_info
*bgp_path_info_lock(struct bgp_path_info
*path
)
272 struct bgp_path_info
*bgp_path_info_unlock(struct bgp_path_info
*path
)
274 assert(path
&& path
->lock
> 0);
277 if (path
->lock
== 0) {
279 zlog_debug ("%s: unlocked and freeing", __func__
);
280 zlog_backtrace (LOG_DEBUG
);
282 bgp_path_info_free(path
);
289 zlog_debug ("%s: unlocked to 1", __func__
);
290 zlog_backtrace (LOG_DEBUG
);
297 /* This function sets flag BGP_NODE_SELECT_DEFER based on condition */
298 static int bgp_node_set_defer_flag(struct bgp_node
*rn
, bool delete)
301 struct bgp_path_info
*old_pi
, *nextpi
;
303 struct bgp
*bgp
= NULL
;
304 struct bgp_table
*table
= NULL
;
307 char buf
[PREFIX2STR_BUFFER
];
309 /* If the flag BGP_NODE_SELECT_DEFER is set and new path is added
310 * then the route selection is deferred
312 if (CHECK_FLAG(rn
->flags
, BGP_NODE_SELECT_DEFER
) && (!delete))
315 if (CHECK_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
)) {
316 if (BGP_DEBUG(update
, UPDATE_OUT
)) {
317 prefix2str(&rn
->p
, buf
, PREFIX2STR_BUFFER
);
319 "Route %s is in workqueue and being processed, not deferred.",
325 table
= bgp_node_table(rn
);
332 for (old_pi
= bgp_node_get_bgp_path_info(rn
);
333 (old_pi
!= NULL
) && (nextpi
= old_pi
->next
, 1); old_pi
= nextpi
) {
334 if (CHECK_FLAG(old_pi
->flags
, BGP_PATH_SELECTED
))
337 /* Route selection is deferred if there is a stale path which
338 * which indicates peer is in restart mode
340 if (CHECK_FLAG(old_pi
->flags
, BGP_PATH_STALE
)
341 && (old_pi
->sub_type
== BGP_ROUTE_NORMAL
)) {
344 /* If the peer is graceful restart capable and peer is
345 * restarting mode, set the flag BGP_NODE_SELECT_DEFER
348 if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer
)
349 && BGP_PEER_RESTARTING_MODE(peer
)
351 && old_pi
->sub_type
== BGP_ROUTE_NORMAL
)) {
359 /* Set the flag BGP_NODE_SELECT_DEFER if route selection deferral timer
362 if (set_flag
&& table
) {
363 if (bgp
&& (bgp
->gr_info
[afi
][safi
].t_select_deferral
)) {
364 SET_FLAG(rn
->flags
, BGP_NODE_SELECT_DEFER
);
365 prefix2str(&rn
->p
, buf
, PREFIX2STR_BUFFER
);
366 if (rn
->rt_node
== NULL
)
367 rn
->rt_node
= listnode_add(
368 bgp
->gr_info
[afi
][safi
].route_list
, rn
);
369 if (BGP_DEBUG(update
, UPDATE_OUT
))
370 zlog_debug("DEFER route %s, rn %p, node %p",
371 buf
, rn
, rn
->rt_node
);
378 void bgp_path_info_add(struct bgp_node
*rn
, struct bgp_path_info
*pi
)
380 struct bgp_path_info
*top
;
382 top
= bgp_node_get_bgp_path_info(rn
);
388 bgp_node_set_bgp_path_info(rn
, pi
);
390 bgp_path_info_lock(pi
);
392 peer_lock(pi
->peer
); /* bgp_path_info peer reference */
393 bgp_node_set_defer_flag(rn
, false);
396 /* Do the actual removal of info from RIB, for use by bgp_process
397 completion callback *only* */
398 void bgp_path_info_reap(struct bgp_node
*rn
, struct bgp_path_info
*pi
)
401 pi
->next
->prev
= pi
->prev
;
403 pi
->prev
->next
= pi
->next
;
405 bgp_node_set_bgp_path_info(rn
, pi
->next
);
407 bgp_path_info_mpath_dequeue(pi
);
408 bgp_path_info_unlock(pi
);
412 void bgp_path_info_delete(struct bgp_node
*rn
, struct bgp_path_info
*pi
)
414 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_REMOVED
);
415 /* set of previous already took care of pcount */
416 UNSET_FLAG(pi
->flags
, BGP_PATH_VALID
);
419 /* undo the effects of a previous call to bgp_path_info_delete; typically
420 called when a route is deleted and then quickly re-added before the
421 deletion has been processed */
422 void bgp_path_info_restore(struct bgp_node
*rn
, struct bgp_path_info
*pi
)
424 bgp_path_info_unset_flag(rn
, pi
, BGP_PATH_REMOVED
);
425 /* unset of previous already took care of pcount */
426 SET_FLAG(pi
->flags
, BGP_PATH_VALID
);
429 /* Adjust pcount as required */
430 static void bgp_pcount_adjust(struct bgp_node
*rn
, struct bgp_path_info
*pi
)
432 struct bgp_table
*table
;
434 assert(rn
&& bgp_node_table(rn
));
435 assert(pi
&& pi
->peer
&& pi
->peer
->bgp
);
437 table
= bgp_node_table(rn
);
439 if (pi
->peer
== pi
->peer
->bgp
->peer_self
)
442 if (!BGP_PATH_COUNTABLE(pi
)
443 && CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
445 UNSET_FLAG(pi
->flags
, BGP_PATH_COUNTED
);
447 /* slight hack, but more robust against errors. */
448 if (pi
->peer
->pcount
[table
->afi
][table
->safi
])
449 pi
->peer
->pcount
[table
->afi
][table
->safi
]--;
451 flog_err(EC_LIB_DEVELOPMENT
,
452 "Asked to decrement 0 prefix count for peer");
453 } else if (BGP_PATH_COUNTABLE(pi
)
454 && !CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
455 SET_FLAG(pi
->flags
, BGP_PATH_COUNTED
);
456 pi
->peer
->pcount
[table
->afi
][table
->safi
]++;
460 static int bgp_label_index_differs(struct bgp_path_info
*pi1
,
461 struct bgp_path_info
*pi2
)
463 return (!(pi1
->attr
->label_index
== pi2
->attr
->label_index
));
466 /* Set/unset bgp_path_info flags, adjusting any other state as needed.
467 * This is here primarily to keep prefix-count in check.
469 void bgp_path_info_set_flag(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
472 SET_FLAG(pi
->flags
, flag
);
474 /* early bath if we know it's not a flag that changes countability state
476 if (!CHECK_FLAG(flag
,
477 BGP_PATH_VALID
| BGP_PATH_HISTORY
| BGP_PATH_REMOVED
))
480 bgp_pcount_adjust(rn
, pi
);
483 void bgp_path_info_unset_flag(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
486 UNSET_FLAG(pi
->flags
, flag
);
488 /* early bath if we know it's not a flag that changes countability state
490 if (!CHECK_FLAG(flag
,
491 BGP_PATH_VALID
| BGP_PATH_HISTORY
| BGP_PATH_REMOVED
))
494 bgp_pcount_adjust(rn
, pi
);
497 /* Get MED value. If MED value is missing and "bgp bestpath
498 missing-as-worst" is specified, treat it as the worst value. */
499 static uint32_t bgp_med_value(struct attr
*attr
, struct bgp
*bgp
)
501 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
504 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_MED_MISSING_AS_WORST
))
511 void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info
*pi
, char *buf
)
513 if (pi
->addpath_rx_id
)
514 sprintf(buf
, "path %s (addpath rxid %d)", pi
->peer
->host
,
517 sprintf(buf
, "path %s", pi
->peer
->host
);
520 /* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
522 static int bgp_path_info_cmp(struct bgp
*bgp
, struct bgp_path_info
*new,
523 struct bgp_path_info
*exist
, int *paths_eq
,
524 struct bgp_maxpaths_cfg
*mpath_cfg
, int debug
,
525 char *pfx_buf
, afi_t afi
, safi_t safi
,
526 enum bgp_path_selection_reason
*reason
)
528 struct attr
*newattr
, *existattr
;
529 bgp_peer_sort_t new_sort
;
530 bgp_peer_sort_t exist_sort
;
536 uint32_t exist_weight
;
537 uint32_t newm
, existm
;
538 struct in_addr new_id
;
539 struct in_addr exist_id
;
542 int internal_as_route
;
545 char new_buf
[PATH_ADDPATH_STR_BUFFER
];
546 char exist_buf
[PATH_ADDPATH_STR_BUFFER
];
548 uint32_t exist_mm_seq
;
555 *reason
= bgp_path_selection_none
;
557 zlog_debug("%s: new is NULL", pfx_buf
);
562 bgp_path_info_path_with_addpath_rx_str(new, new_buf
);
565 *reason
= bgp_path_selection_first
;
567 zlog_debug("%s: %s is the initial bestpath", pfx_buf
,
573 bgp_path_info_path_with_addpath_rx_str(exist
, exist_buf
);
574 zlog_debug("%s: Comparing %s flags 0x%x with %s flags 0x%x",
575 pfx_buf
, new_buf
, new->flags
, exist_buf
,
580 existattr
= exist
->attr
;
582 /* For EVPN routes, we cannot just go by local vs remote, we have to
583 * look at the MAC mobility sequence number, if present.
585 if (safi
== SAFI_EVPN
) {
586 /* This is an error condition described in RFC 7432 Section
588 * states that in this scenario "the PE MUST alert the operator"
590 * does not state what other action to take. In order to provide
592 * consistency in this scenario we are going to prefer the path
596 if (newattr
->sticky
!= existattr
->sticky
) {
598 prefix2str(&new->net
->p
, pfx_buf
,
600 * PREFIX2STR_BUFFER
);
601 bgp_path_info_path_with_addpath_rx_str(new,
603 bgp_path_info_path_with_addpath_rx_str(
607 if (newattr
->sticky
&& !existattr
->sticky
) {
608 *reason
= bgp_path_selection_evpn_sticky_mac
;
611 "%s: %s wins over %s due to sticky MAC flag",
612 pfx_buf
, new_buf
, exist_buf
);
616 if (!newattr
->sticky
&& existattr
->sticky
) {
617 *reason
= bgp_path_selection_evpn_sticky_mac
;
620 "%s: %s loses to %s due to sticky MAC flag",
621 pfx_buf
, new_buf
, exist_buf
);
626 new_mm_seq
= mac_mobility_seqnum(newattr
);
627 exist_mm_seq
= mac_mobility_seqnum(existattr
);
629 if (new_mm_seq
> exist_mm_seq
) {
630 *reason
= bgp_path_selection_evpn_seq
;
633 "%s: %s wins over %s due to MM seq %u > %u",
634 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
639 if (new_mm_seq
< exist_mm_seq
) {
640 *reason
= bgp_path_selection_evpn_seq
;
643 "%s: %s loses to %s due to MM seq %u < %u",
644 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
650 * if sequence numbers are the same path with the lowest IP
653 nh_cmp
= bgp_path_info_nexthop_cmp(new, exist
);
655 *reason
= bgp_path_selection_evpn_lower_ip
;
658 "%s: %s wins over %s due to same MM seq %u and lower IP %s",
659 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
660 inet_ntoa(new->attr
->nexthop
));
664 *reason
= bgp_path_selection_evpn_lower_ip
;
667 "%s: %s loses to %s due to same MM seq %u and higher IP %s",
668 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
669 inet_ntoa(new->attr
->nexthop
));
674 /* 1. Weight check. */
675 new_weight
= newattr
->weight
;
676 exist_weight
= existattr
->weight
;
678 if (new_weight
> exist_weight
) {
679 *reason
= bgp_path_selection_weight
;
681 zlog_debug("%s: %s wins over %s due to weight %d > %d",
682 pfx_buf
, new_buf
, exist_buf
, new_weight
,
687 if (new_weight
< exist_weight
) {
688 *reason
= bgp_path_selection_weight
;
690 zlog_debug("%s: %s loses to %s due to weight %d < %d",
691 pfx_buf
, new_buf
, exist_buf
, new_weight
,
696 /* 2. Local preference check. */
697 new_pref
= exist_pref
= bgp
->default_local_pref
;
699 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
700 new_pref
= newattr
->local_pref
;
701 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
702 exist_pref
= existattr
->local_pref
;
704 if (new_pref
> exist_pref
) {
705 *reason
= bgp_path_selection_local_pref
;
708 "%s: %s wins over %s due to localpref %d > %d",
709 pfx_buf
, new_buf
, exist_buf
, new_pref
,
714 if (new_pref
< exist_pref
) {
715 *reason
= bgp_path_selection_local_pref
;
718 "%s: %s loses to %s due to localpref %d < %d",
719 pfx_buf
, new_buf
, exist_buf
, new_pref
,
724 /* 3. Local route check. We prefer:
726 * - BGP_ROUTE_AGGREGATE
727 * - BGP_ROUTE_REDISTRIBUTE
729 if (!(new->sub_type
== BGP_ROUTE_NORMAL
||
730 new->sub_type
== BGP_ROUTE_IMPORTED
)) {
731 *reason
= bgp_path_selection_local_route
;
734 "%s: %s wins over %s due to preferred BGP_ROUTE type",
735 pfx_buf
, new_buf
, exist_buf
);
739 if (!(exist
->sub_type
== BGP_ROUTE_NORMAL
||
740 exist
->sub_type
== BGP_ROUTE_IMPORTED
)) {
741 *reason
= bgp_path_selection_local_route
;
744 "%s: %s loses to %s due to preferred BGP_ROUTE type",
745 pfx_buf
, new_buf
, exist_buf
);
749 /* 4. AS path length check. */
750 if (!CHECK_FLAG(bgp
->flags
, BGP_FLAG_ASPATH_IGNORE
)) {
751 int exist_hops
= aspath_count_hops(existattr
->aspath
);
752 int exist_confeds
= aspath_count_confeds(existattr
->aspath
);
754 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_ASPATH_CONFED
)) {
757 aspath_hops
= aspath_count_hops(newattr
->aspath
);
758 aspath_hops
+= aspath_count_confeds(newattr
->aspath
);
760 if (aspath_hops
< (exist_hops
+ exist_confeds
)) {
761 *reason
= bgp_path_selection_confed_as_path
;
764 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
765 pfx_buf
, new_buf
, exist_buf
,
767 (exist_hops
+ exist_confeds
));
771 if (aspath_hops
> (exist_hops
+ exist_confeds
)) {
772 *reason
= bgp_path_selection_confed_as_path
;
775 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
776 pfx_buf
, new_buf
, exist_buf
,
778 (exist_hops
+ exist_confeds
));
782 int newhops
= aspath_count_hops(newattr
->aspath
);
784 if (newhops
< exist_hops
) {
785 *reason
= bgp_path_selection_as_path
;
788 "%s: %s wins over %s due to aspath hopcount %d < %d",
789 pfx_buf
, new_buf
, exist_buf
,
790 newhops
, exist_hops
);
794 if (newhops
> exist_hops
) {
795 *reason
= bgp_path_selection_as_path
;
798 "%s: %s loses to %s due to aspath hopcount %d > %d",
799 pfx_buf
, new_buf
, exist_buf
,
800 newhops
, exist_hops
);
806 /* 5. Origin check. */
807 if (newattr
->origin
< existattr
->origin
) {
808 *reason
= bgp_path_selection_origin
;
810 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
811 pfx_buf
, new_buf
, exist_buf
,
812 bgp_origin_long_str
[newattr
->origin
],
813 bgp_origin_long_str
[existattr
->origin
]);
817 if (newattr
->origin
> existattr
->origin
) {
818 *reason
= bgp_path_selection_origin
;
820 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
821 pfx_buf
, new_buf
, exist_buf
,
822 bgp_origin_long_str
[newattr
->origin
],
823 bgp_origin_long_str
[existattr
->origin
]);
828 internal_as_route
= (aspath_count_hops(newattr
->aspath
) == 0
829 && aspath_count_hops(existattr
->aspath
) == 0);
830 confed_as_route
= (aspath_count_confeds(newattr
->aspath
) > 0
831 && aspath_count_confeds(existattr
->aspath
) > 0
832 && aspath_count_hops(newattr
->aspath
) == 0
833 && aspath_count_hops(existattr
->aspath
) == 0);
835 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_ALWAYS_COMPARE_MED
)
836 || (CHECK_FLAG(bgp
->flags
, BGP_FLAG_MED_CONFED
) && confed_as_route
)
837 || aspath_cmp_left(newattr
->aspath
, existattr
->aspath
)
838 || aspath_cmp_left_confed(newattr
->aspath
, existattr
->aspath
)
839 || internal_as_route
) {
840 new_med
= bgp_med_value(new->attr
, bgp
);
841 exist_med
= bgp_med_value(exist
->attr
, bgp
);
843 if (new_med
< exist_med
) {
844 *reason
= bgp_path_selection_med
;
847 "%s: %s wins over %s due to MED %d < %d",
848 pfx_buf
, new_buf
, exist_buf
, new_med
,
853 if (new_med
> exist_med
) {
854 *reason
= bgp_path_selection_med
;
857 "%s: %s loses to %s due to MED %d > %d",
858 pfx_buf
, new_buf
, exist_buf
, new_med
,
864 /* 7. Peer type check. */
865 new_sort
= new->peer
->sort
;
866 exist_sort
= exist
->peer
->sort
;
868 if (new_sort
== BGP_PEER_EBGP
869 && (exist_sort
== BGP_PEER_IBGP
|| exist_sort
== BGP_PEER_CONFED
)) {
870 *reason
= bgp_path_selection_peer
;
873 "%s: %s wins over %s due to eBGP peer > iBGP peer",
874 pfx_buf
, new_buf
, exist_buf
);
878 if (exist_sort
== BGP_PEER_EBGP
879 && (new_sort
== BGP_PEER_IBGP
|| new_sort
== BGP_PEER_CONFED
)) {
880 *reason
= bgp_path_selection_peer
;
883 "%s: %s loses to %s due to iBGP peer < eBGP peer",
884 pfx_buf
, new_buf
, exist_buf
);
888 /* 8. IGP metric check. */
892 newm
= new->extra
->igpmetric
;
894 existm
= exist
->extra
->igpmetric
;
899 "%s: %s wins over %s due to IGP metric %d < %d",
900 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
907 "%s: %s loses to %s due to IGP metric %d > %d",
908 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
912 /* 9. Same IGP metric. Compare the cluster list length as
913 representative of IGP hops metric. Rewrite the metric value
914 pair (newm, existm) with the cluster list length. Prefer the
915 path with smaller cluster list length. */
916 if (newm
== existm
) {
917 if (peer_sort_lookup(new->peer
) == BGP_PEER_IBGP
918 && peer_sort_lookup(exist
->peer
) == BGP_PEER_IBGP
919 && (mpath_cfg
== NULL
921 mpath_cfg
->ibgp_flags
,
922 BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN
))) {
923 newm
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
924 existm
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
929 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
930 pfx_buf
, new_buf
, exist_buf
,
938 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
939 pfx_buf
, new_buf
, exist_buf
,
946 /* 10. confed-external vs. confed-internal */
947 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
948 if (new_sort
== BGP_PEER_CONFED
949 && exist_sort
== BGP_PEER_IBGP
) {
950 *reason
= bgp_path_selection_confed
;
953 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
954 pfx_buf
, new_buf
, exist_buf
);
958 if (exist_sort
== BGP_PEER_CONFED
959 && new_sort
== BGP_PEER_IBGP
) {
960 *reason
= bgp_path_selection_confed
;
963 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
964 pfx_buf
, new_buf
, exist_buf
);
969 /* 11. Maximum path check. */
970 if (newm
== existm
) {
971 /* If one path has a label but the other does not, do not treat
972 * them as equals for multipath
974 if ((new->extra
&&bgp_is_valid_label(&new->extra
->label
[0]))
976 && bgp_is_valid_label(&exist
->extra
->label
[0]))) {
979 "%s: %s and %s cannot be multipath, one has a label while the other does not",
980 pfx_buf
, new_buf
, exist_buf
);
981 } else if (CHECK_FLAG(bgp
->flags
,
982 BGP_FLAG_ASPATH_MULTIPATH_RELAX
)) {
985 * For the two paths, all comparison steps till IGP
987 * have succeeded - including AS_PATH hop count. Since
989 * bestpath as-path multipath-relax' knob is on, we
991 * an exact match of AS_PATH. Thus, mark the paths are
993 * That will trigger both these paths to get into the
1001 "%s: %s and %s are equal via multipath-relax",
1002 pfx_buf
, new_buf
, exist_buf
);
1003 } else if (new->peer
->sort
== BGP_PEER_IBGP
) {
1004 if (aspath_cmp(new->attr
->aspath
,
1005 exist
->attr
->aspath
)) {
1010 "%s: %s and %s are equal via matching aspaths",
1011 pfx_buf
, new_buf
, exist_buf
);
1013 } else if (new->peer
->as
== exist
->peer
->as
) {
1018 "%s: %s and %s are equal via same remote-as",
1019 pfx_buf
, new_buf
, exist_buf
);
1023 * TODO: If unequal cost ibgp multipath is enabled we can
1024 * mark the paths as equal here instead of returning
1029 "%s: %s wins over %s after IGP metric comparison",
1030 pfx_buf
, new_buf
, exist_buf
);
1033 "%s: %s loses to %s after IGP metric comparison",
1034 pfx_buf
, new_buf
, exist_buf
);
1036 *reason
= bgp_path_selection_igp_metric
;
1040 /* 12. If both paths are external, prefer the path that was received
1041 first (the oldest one). This step minimizes route-flap, since a
1042 newer path won't displace an older one, even if it was the
1043 preferred route based on the additional decision criteria below. */
1044 if (!CHECK_FLAG(bgp
->flags
, BGP_FLAG_COMPARE_ROUTER_ID
)
1045 && new_sort
== BGP_PEER_EBGP
&& exist_sort
== BGP_PEER_EBGP
) {
1046 if (CHECK_FLAG(new->flags
, BGP_PATH_SELECTED
)) {
1047 *reason
= bgp_path_selection_older
;
1050 "%s: %s wins over %s due to oldest external",
1051 pfx_buf
, new_buf
, exist_buf
);
1055 if (CHECK_FLAG(exist
->flags
, BGP_PATH_SELECTED
)) {
1056 *reason
= bgp_path_selection_older
;
1059 "%s: %s loses to %s due to oldest external",
1060 pfx_buf
, new_buf
, exist_buf
);
1065 /* 13. Router-ID comparision. */
1066 /* If one of the paths is "stale", the corresponding peer router-id will
1067 * be 0 and would always win over the other path. If originator id is
1068 * used for the comparision, it will decide which path is better.
1070 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
1071 new_id
.s_addr
= newattr
->originator_id
.s_addr
;
1073 new_id
.s_addr
= new->peer
->remote_id
.s_addr
;
1074 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
1075 exist_id
.s_addr
= existattr
->originator_id
.s_addr
;
1077 exist_id
.s_addr
= exist
->peer
->remote_id
.s_addr
;
1079 if (ntohl(new_id
.s_addr
) < ntohl(exist_id
.s_addr
)) {
1080 *reason
= bgp_path_selection_router_id
;
1083 "%s: %s wins over %s due to Router-ID comparison",
1084 pfx_buf
, new_buf
, exist_buf
);
1088 if (ntohl(new_id
.s_addr
) > ntohl(exist_id
.s_addr
)) {
1089 *reason
= bgp_path_selection_router_id
;
1092 "%s: %s loses to %s due to Router-ID comparison",
1093 pfx_buf
, new_buf
, exist_buf
);
1097 /* 14. Cluster length comparision. */
1098 new_cluster
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
1099 exist_cluster
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
1101 if (new_cluster
< exist_cluster
) {
1102 *reason
= bgp_path_selection_cluster_length
;
1105 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1106 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
1111 if (new_cluster
> exist_cluster
) {
1112 *reason
= bgp_path_selection_cluster_length
;
1115 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1116 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
1121 /* 15. Neighbor address comparision. */
1122 /* Do this only if neither path is "stale" as stale paths do not have
1123 * valid peer information (as the connection may or may not be up).
1125 if (CHECK_FLAG(exist
->flags
, BGP_PATH_STALE
)) {
1126 *reason
= bgp_path_selection_stale
;
1129 "%s: %s wins over %s due to latter path being STALE",
1130 pfx_buf
, new_buf
, exist_buf
);
1134 if (CHECK_FLAG(new->flags
, BGP_PATH_STALE
)) {
1135 *reason
= bgp_path_selection_stale
;
1138 "%s: %s loses to %s due to former path being STALE",
1139 pfx_buf
, new_buf
, exist_buf
);
1143 /* locally configured routes to advertise do not have su_remote */
1144 if (new->peer
->su_remote
== NULL
) {
1145 *reason
= bgp_path_selection_local_configured
;
1148 if (exist
->peer
->su_remote
== NULL
) {
1149 *reason
= bgp_path_selection_local_configured
;
1153 ret
= sockunion_cmp(new->peer
->su_remote
, exist
->peer
->su_remote
);
1156 *reason
= bgp_path_selection_neighbor_ip
;
1159 "%s: %s loses to %s due to Neighor IP comparison",
1160 pfx_buf
, new_buf
, exist_buf
);
1165 *reason
= bgp_path_selection_neighbor_ip
;
1168 "%s: %s wins over %s due to Neighor IP comparison",
1169 pfx_buf
, new_buf
, exist_buf
);
1173 *reason
= bgp_path_selection_default
;
1175 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1176 pfx_buf
, new_buf
, exist_buf
);
1181 /* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1182 * is preferred, or 0 if they are the same (usually will only occur if
1183 * multipath is enabled
1184 * This version is compatible with */
1185 int bgp_path_info_cmp_compatible(struct bgp
*bgp
, struct bgp_path_info
*new,
1186 struct bgp_path_info
*exist
, char *pfx_buf
,
1187 afi_t afi
, safi_t safi
,
1188 enum bgp_path_selection_reason
*reason
)
1192 ret
= bgp_path_info_cmp(bgp
, new, exist
, &paths_eq
, NULL
, 0, pfx_buf
,
1206 static enum filter_type
bgp_input_filter(struct peer
*peer
, struct prefix
*p
,
1207 struct attr
*attr
, afi_t afi
,
1210 struct bgp_filter
*filter
;
1212 filter
= &peer
->filter
[afi
][safi
];
1214 #define FILTER_EXIST_WARN(F, f, filter) \
1215 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
1216 zlog_debug("%s: Could not find configured input %s-list %s!", \
1217 peer->host, #f, F##_IN_NAME(filter));
1219 if (DISTRIBUTE_IN_NAME(filter
)) {
1220 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1222 if (access_list_apply(DISTRIBUTE_IN(filter
), p
) == FILTER_DENY
)
1226 if (PREFIX_LIST_IN_NAME(filter
)) {
1227 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1229 if (prefix_list_apply(PREFIX_LIST_IN(filter
), p
) == PREFIX_DENY
)
1233 if (FILTER_LIST_IN_NAME(filter
)) {
1234 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1236 if (as_list_apply(FILTER_LIST_IN(filter
), attr
->aspath
)
1241 return FILTER_PERMIT
;
1242 #undef FILTER_EXIST_WARN
1245 static enum filter_type
bgp_output_filter(struct peer
*peer
, struct prefix
*p
,
1246 struct attr
*attr
, afi_t afi
,
1249 struct bgp_filter
*filter
;
1251 filter
= &peer
->filter
[afi
][safi
];
1253 #define FILTER_EXIST_WARN(F, f, filter) \
1254 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
1255 zlog_debug("%s: Could not find configured output %s-list %s!", \
1256 peer->host, #f, F##_OUT_NAME(filter));
1258 if (DISTRIBUTE_OUT_NAME(filter
)) {
1259 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1261 if (access_list_apply(DISTRIBUTE_OUT(filter
), p
) == FILTER_DENY
)
1265 if (PREFIX_LIST_OUT_NAME(filter
)) {
1266 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1268 if (prefix_list_apply(PREFIX_LIST_OUT(filter
), p
)
1273 if (FILTER_LIST_OUT_NAME(filter
)) {
1274 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1276 if (as_list_apply(FILTER_LIST_OUT(filter
), attr
->aspath
)
1281 return FILTER_PERMIT
;
1282 #undef FILTER_EXIST_WARN
1285 /* If community attribute includes no_export then return 1. */
1286 static int bgp_community_filter(struct peer
*peer
, struct attr
*attr
)
1288 if (attr
->community
) {
1289 /* NO_ADVERTISE check. */
1290 if (community_include(attr
->community
, COMMUNITY_NO_ADVERTISE
))
1293 /* NO_EXPORT check. */
1294 if (peer
->sort
== BGP_PEER_EBGP
1295 && community_include(attr
->community
, COMMUNITY_NO_EXPORT
))
1298 /* NO_EXPORT_SUBCONFED check. */
1299 if (peer
->sort
== BGP_PEER_EBGP
1300 || peer
->sort
== BGP_PEER_CONFED
)
1301 if (community_include(attr
->community
,
1302 COMMUNITY_NO_EXPORT_SUBCONFED
))
1308 /* Route reflection loop check. */
1309 static int bgp_cluster_filter(struct peer
*peer
, struct attr
*attr
)
1311 struct in_addr cluster_id
;
1313 if (attr
->cluster
) {
1314 if (peer
->bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
1315 cluster_id
= peer
->bgp
->cluster_id
;
1317 cluster_id
= peer
->bgp
->router_id
;
1319 if (cluster_loop_check(attr
->cluster
, cluster_id
))
1325 static int bgp_input_modifier(struct peer
*peer
, struct prefix
*p
,
1326 struct attr
*attr
, afi_t afi
, safi_t safi
,
1327 const char *rmap_name
, mpls_label_t
*label
,
1328 uint32_t num_labels
, struct bgp_node
*rn
)
1330 struct bgp_filter
*filter
;
1331 struct bgp_path_info rmap_path
= { 0 };
1332 struct bgp_path_info_extra extra
= { 0 };
1333 route_map_result_t ret
;
1334 struct route_map
*rmap
= NULL
;
1336 filter
= &peer
->filter
[afi
][safi
];
1338 /* Apply default weight value. */
1339 if (peer
->weight
[afi
][safi
])
1340 attr
->weight
= peer
->weight
[afi
][safi
];
1343 rmap
= route_map_lookup_by_name(rmap_name
);
1348 if (ROUTE_MAP_IN_NAME(filter
)) {
1349 rmap
= ROUTE_MAP_IN(filter
);
1356 /* Route map apply. */
1358 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
1359 /* Duplicate current value to new strucutre for modification. */
1360 rmap_path
.peer
= peer
;
1361 rmap_path
.attr
= attr
;
1362 rmap_path
.extra
= &extra
;
1365 extra
.num_labels
= num_labels
;
1366 if (label
&& num_labels
&& num_labels
<= BGP_MAX_LABELS
)
1367 memcpy(extra
.label
, label
,
1368 num_labels
* sizeof(mpls_label_t
));
1370 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_IN
);
1372 /* Apply BGP route map to the attribute. */
1373 ret
= route_map_apply(rmap
, p
, RMAP_BGP
, &rmap_path
);
1375 peer
->rmap_type
= 0;
1377 if (ret
== RMAP_DENYMATCH
)
1383 static int bgp_output_modifier(struct peer
*peer
, struct prefix
*p
,
1384 struct attr
*attr
, afi_t afi
, safi_t safi
,
1385 const char *rmap_name
)
1387 struct bgp_path_info rmap_path
;
1388 route_map_result_t ret
;
1389 struct route_map
*rmap
= NULL
;
1393 * So if we get to this point and have no rmap_name
1394 * we want to just show the output as it currently
1400 /* Apply default weight value. */
1401 if (peer
->weight
[afi
][safi
])
1402 attr
->weight
= peer
->weight
[afi
][safi
];
1404 rmap
= route_map_lookup_by_name(rmap_name
);
1407 * If we have a route map name and we do not find
1408 * the routemap that means we have an implicit
1414 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
1415 /* Route map apply. */
1416 /* Duplicate current value to new strucutre for modification. */
1417 rmap_path
.peer
= peer
;
1418 rmap_path
.attr
= attr
;
1420 rmap_type
= peer
->rmap_type
;
1421 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1423 /* Apply BGP route map to the attribute. */
1424 ret
= route_map_apply(rmap
, p
, RMAP_BGP
, &rmap_path
);
1426 peer
->rmap_type
= rmap_type
;
1428 if (ret
== RMAP_DENYMATCH
)
1430 * caller has multiple error paths with bgp_attr_flush()
1437 /* If this is an EBGP peer with remove-private-AS */
1438 static void bgp_peer_remove_private_as(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1439 struct peer
*peer
, struct attr
*attr
)
1441 if (peer
->sort
== BGP_PEER_EBGP
1442 && (peer_af_flag_check(peer
, afi
, safi
,
1443 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1444 || peer_af_flag_check(peer
, afi
, safi
,
1445 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
)
1446 || peer_af_flag_check(peer
, afi
, safi
,
1447 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)
1448 || peer_af_flag_check(peer
, afi
, safi
,
1449 PEER_FLAG_REMOVE_PRIVATE_AS
))) {
1450 // Take action on the entire aspath
1451 if (peer_af_flag_check(peer
, afi
, safi
,
1452 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1453 || peer_af_flag_check(peer
, afi
, safi
,
1454 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)) {
1455 if (peer_af_flag_check(
1457 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
))
1458 attr
->aspath
= aspath_replace_private_asns(
1459 attr
->aspath
, bgp
->as
, peer
->as
);
1461 // The entire aspath consists of private ASNs so create
1463 else if (aspath_private_as_check(attr
->aspath
))
1464 attr
->aspath
= aspath_empty_get();
1466 // There are some public and some private ASNs, remove
1469 attr
->aspath
= aspath_remove_private_asns(
1470 attr
->aspath
, peer
->as
);
1473 // 'all' was not specified so the entire aspath must be private
1475 // for us to do anything
1476 else if (aspath_private_as_check(attr
->aspath
)) {
1477 if (peer_af_flag_check(
1479 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
))
1480 attr
->aspath
= aspath_replace_private_asns(
1481 attr
->aspath
, bgp
->as
, peer
->as
);
1483 attr
->aspath
= aspath_empty_get();
1488 /* If this is an EBGP peer with as-override */
1489 static void bgp_peer_as_override(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1490 struct peer
*peer
, struct attr
*attr
)
1492 if (peer
->sort
== BGP_PEER_EBGP
1493 && peer_af_flag_check(peer
, afi
, safi
, PEER_FLAG_AS_OVERRIDE
)) {
1494 if (aspath_single_asn_check(attr
->aspath
, peer
->as
))
1495 attr
->aspath
= aspath_replace_specific_asn(
1496 attr
->aspath
, peer
->as
, bgp
->as
);
1500 void bgp_attr_add_gshut_community(struct attr
*attr
)
1502 struct community
*old
;
1503 struct community
*new;
1504 struct community
*merge
;
1505 struct community
*gshut
;
1507 old
= attr
->community
;
1508 gshut
= community_str2com("graceful-shutdown");
1513 merge
= community_merge(community_dup(old
), gshut
);
1515 if (old
->refcnt
== 0)
1516 community_free(&old
);
1518 new = community_uniq_sort(merge
);
1519 community_free(&merge
);
1521 new = community_dup(gshut
);
1524 community_free(&gshut
);
1525 attr
->community
= new;
1526 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
1528 /* When we add the graceful-shutdown community we must also
1529 * lower the local-preference */
1530 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1531 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1535 static void subgroup_announce_reset_nhop(uint8_t family
, struct attr
*attr
)
1537 if (family
== AF_INET
) {
1538 attr
->nexthop
.s_addr
= INADDR_ANY
;
1539 attr
->mp_nexthop_global_in
.s_addr
= INADDR_ANY
;
1541 if (family
== AF_INET6
)
1542 memset(&attr
->mp_nexthop_global
, 0, IPV6_MAX_BYTELEN
);
1543 if (family
== AF_EVPN
)
1544 memset(&attr
->mp_nexthop_global_in
, 0, BGP_ATTR_NHLEN_IPV4
);
1547 int subgroup_announce_check(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
1548 struct update_subgroup
*subgrp
, struct prefix
*p
,
1551 struct bgp_filter
*filter
;
1554 struct peer
*onlypeer
;
1556 struct attr
*piattr
;
1557 char buf
[PREFIX_STRLEN
];
1558 route_map_result_t ret
;
1563 int samepeer_safe
= 0; /* for synthetic mplsvpns routes */
1565 if (DISABLE_BGP_ANNOUNCE
)
1568 afi
= SUBGRP_AFI(subgrp
);
1569 safi
= SUBGRP_SAFI(subgrp
);
1570 peer
= SUBGRP_PEER(subgrp
);
1572 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_LONESOUL
))
1573 onlypeer
= SUBGRP_PFIRST(subgrp
)->peer
;
1576 filter
= &peer
->filter
[afi
][safi
];
1577 bgp
= SUBGRP_INST(subgrp
);
1578 piattr
= bgp_path_info_mpath_count(pi
) ? bgp_path_info_mpath_attr(pi
)
1582 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
)) && (safi
== SAFI_MPLS_VPN
)
1583 && ((pi
->type
== ZEBRA_ROUTE_BGP_DIRECT
)
1584 || (pi
->type
== ZEBRA_ROUTE_BGP_DIRECT_EXT
))) {
1587 * direct and direct_ext type routes originate internally even
1588 * though they can have peer pointers that reference other
1591 prefix2str(p
, buf
, PREFIX_STRLEN
);
1592 zlog_debug("%s: pfx %s bgp_direct->vpn route peer safe",
1598 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
))
1599 && ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_UNICAST
))
1600 && (pi
->type
== ZEBRA_ROUTE_BGP
)
1601 && (pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
1603 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1608 /* With addpath we may be asked to TX all kinds of paths so make sure
1610 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
)
1611 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)
1612 || CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
1616 /* If this is not the bestpath then check to see if there is an enabled
1618 * feature that requires us to advertise it */
1619 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
1620 if (!bgp_addpath_tx_path(peer
->addpath_type
[afi
][safi
], pi
)) {
1625 /* Aggregate-address suppress check. */
1626 if (pi
->extra
&& pi
->extra
->suppress
)
1627 if (!UNSUPPRESS_MAP_NAME(filter
)) {
1632 * If we are doing VRF 2 VRF leaking via the import
1633 * statement, we want to prevent the route going
1634 * off box as that the RT and RD created are localy
1635 * significant and globaly useless.
1637 if (safi
== SAFI_MPLS_VPN
&& pi
->extra
&& pi
->extra
->num_labels
1638 && pi
->extra
->label
[0] == BGP_PREVENT_VRF_2_VRF_LEAK
)
1641 /* If it's labeled safi, make sure the route has a valid label. */
1642 if (safi
== SAFI_LABELED_UNICAST
) {
1643 mpls_label_t label
= bgp_adv_label(rn
, pi
, peer
, afi
, safi
);
1644 if (!bgp_is_valid_label(&label
)) {
1645 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1646 zlog_debug("u%" PRIu64
":s%" PRIu64
1647 " %s/%d is filtered - no label (%p)",
1648 subgrp
->update_group
->id
, subgrp
->id
,
1649 inet_ntop(p
->family
, &p
->u
.prefix
,
1650 buf
, SU_ADDRSTRLEN
),
1651 p
->prefixlen
, &label
);
1656 /* Do not send back route to sender. */
1657 if (onlypeer
&& from
== onlypeer
) {
1661 /* Do not send the default route in the BGP table if the neighbor is
1662 * configured for default-originate */
1663 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1664 PEER_FLAG_DEFAULT_ORIGINATE
)) {
1665 if (p
->family
== AF_INET
&& p
->u
.prefix4
.s_addr
== INADDR_ANY
)
1667 else if (p
->family
== AF_INET6
&& p
->prefixlen
== 0)
1671 /* Transparency check. */
1672 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
)
1673 && CHECK_FLAG(from
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
))
1678 /* If community is not disabled check the no-export and local. */
1679 if (!transparent
&& bgp_community_filter(peer
, piattr
)) {
1680 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1682 "subgrpannouncecheck: community filter check fail");
1686 /* If the attribute has originator-id and it is same as remote
1688 if (onlypeer
&& piattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
1689 && (IPV4_ADDR_SAME(&onlypeer
->remote_id
, &piattr
->originator_id
))) {
1690 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1692 "%s [Update:SEND] %s originator-id is same as "
1695 prefix2str(p
, buf
, sizeof(buf
)));
1699 /* ORF prefix-list filter check */
1700 if (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_RM_ADV
)
1701 && (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_SM_RCV
)
1702 || CHECK_FLAG(peer
->af_cap
[afi
][safi
],
1703 PEER_CAP_ORF_PREFIX_SM_OLD_RCV
)))
1704 if (peer
->orf_plist
[afi
][safi
]) {
1705 if (prefix_list_apply(peer
->orf_plist
[afi
][safi
], p
)
1707 if (bgp_debug_update(NULL
, p
,
1708 subgrp
->update_group
, 0))
1710 "%s [Update:SEND] %s is filtered via ORF",
1718 /* Output filter check. */
1719 if (bgp_output_filter(peer
, p
, piattr
, afi
, safi
) == FILTER_DENY
) {
1720 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1721 zlog_debug("%s [Update:SEND] %s is filtered",
1722 peer
->host
, prefix2str(p
, buf
, sizeof(buf
)));
1726 /* AS path loop check. */
1727 if (onlypeer
&& onlypeer
->as_path_loop_detection
1728 && aspath_loop_check(piattr
->aspath
, onlypeer
->as
)) {
1729 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1731 "%s [Update:SEND] suppress announcement to peer AS %u "
1732 "that is part of AS path.",
1733 onlypeer
->host
, onlypeer
->as
);
1737 /* If we're a CONFED we need to loop check the CONFED ID too */
1738 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
1739 if (aspath_loop_check(piattr
->aspath
, bgp
->confed_id
)) {
1740 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1742 "%s [Update:SEND] suppress announcement to peer AS %u"
1744 peer
->host
, bgp
->confed_id
);
1749 /* Route-Reflect check. */
1750 if (from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1755 /* IBGP reflection check. */
1756 if (reflect
&& !samepeer_safe
) {
1757 /* A route from a Client peer. */
1758 if (CHECK_FLAG(from
->af_flags
[afi
][safi
],
1759 PEER_FLAG_REFLECTOR_CLIENT
)) {
1760 /* Reflect to all the Non-Client peers and also to the
1761 Client peers other than the originator. Originator
1763 is already done. So there is noting to do. */
1764 /* no bgp client-to-client reflection check. */
1765 if (CHECK_FLAG(bgp
->flags
,
1766 BGP_FLAG_NO_CLIENT_TO_CLIENT
))
1767 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1768 PEER_FLAG_REFLECTOR_CLIENT
))
1771 /* A route from a Non-client peer. Reflect to all other
1773 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1774 PEER_FLAG_REFLECTOR_CLIENT
))
1779 /* For modify attribute, copy it to temporary structure. */
1782 /* If local-preference is not set. */
1783 if ((peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
)
1784 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))) {
1785 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1786 attr
->local_pref
= bgp
->default_local_pref
;
1789 /* If originator-id is not set and the route is to be reflected,
1790 set the originator id */
1792 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)))) {
1793 IPV4_ADDR_COPY(&(attr
->originator_id
), &(from
->remote_id
));
1794 SET_FLAG(attr
->flag
, BGP_ATTR_ORIGINATOR_ID
);
1797 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
1799 if (peer
->sort
== BGP_PEER_EBGP
1800 && attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
1801 if (from
!= bgp
->peer_self
&& !transparent
1802 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1803 PEER_FLAG_MED_UNCHANGED
))
1805 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
));
1808 /* Since the nexthop attribute can vary per peer, it is not explicitly
1810 * in announce check, only certain flags and length (or number of
1812 * -- for IPv6/MP_REACH) are set here in order to guide the update
1814 * code in setting the nexthop(s) on a per peer basis in
1816 * Typically, the source nexthop in the attribute is preserved but in
1818 * scenarios where we know it will always be overwritten, we reset the
1819 * nexthop to "0" in an attempt to achieve better Update packing. An
1820 * example of this is when a prefix from each of 2 IBGP peers needs to
1822 * announced to an EBGP peer (and they have the same attributes barring
1826 SET_FLAG(attr
->rmap_change_flags
, BATTR_REFLECTED
);
1828 #define NEXTHOP_IS_V6 \
1829 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
1830 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
1831 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
1832 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
1834 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
1836 * the peer (group) is configured to receive link-local nexthop
1838 * and it is available in the prefix OR we're not reflecting the route,
1839 * link-local nexthop address is valid and
1840 * the peer (group) to whom we're going to announce is on a shared
1842 * and this is either a self-originated route or the peer is EBGP.
1843 * By checking if nexthop LL address is valid we are sure that
1844 * we do not announce LL address as `::`.
1846 if (NEXTHOP_IS_V6
) {
1847 attr
->mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
1848 if ((CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1849 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)
1850 && IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
))
1852 && IN6_IS_ADDR_LINKLOCAL(&peer
->nexthop
.v6_local
)
1853 && peer
->shared_network
1854 && (from
== bgp
->peer_self
1855 || peer
->sort
== BGP_PEER_EBGP
))) {
1856 attr
->mp_nexthop_len
=
1857 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
;
1860 /* Clear off link-local nexthop in source, whenever it is not
1862 * ensure more prefixes share the same attribute for
1865 if (!(CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1866 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)))
1867 memset(&attr
->mp_nexthop_local
, 0, IPV6_MAX_BYTELEN
);
1870 bgp_peer_remove_private_as(bgp
, afi
, safi
, peer
, attr
);
1871 bgp_peer_as_override(bgp
, afi
, safi
, peer
, attr
);
1873 /* Route map & unsuppress-map apply. */
1874 if (ROUTE_MAP_OUT_NAME(filter
) || (pi
->extra
&& pi
->extra
->suppress
)) {
1875 struct bgp_path_info rmap_path
= {0};
1876 struct bgp_path_info_extra dummy_rmap_path_extra
= {0};
1877 struct attr dummy_attr
= {0};
1879 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
1880 rmap_path
.peer
= peer
;
1881 rmap_path
.attr
= attr
;
1885 memcpy(&dummy_rmap_path_extra
, pi
->extra
,
1886 sizeof(struct bgp_path_info_extra
));
1887 rmap_path
.extra
= &dummy_rmap_path_extra
;
1890 /* don't confuse inbound and outbound setting */
1891 RESET_FLAG(attr
->rmap_change_flags
);
1894 * The route reflector is not allowed to modify the attributes
1895 * of the reflected IBGP routes unless explicitly allowed.
1897 if ((from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1898 && !CHECK_FLAG(bgp
->flags
,
1899 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY
)) {
1901 rmap_path
.attr
= &dummy_attr
;
1904 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1906 if (pi
->extra
&& pi
->extra
->suppress
)
1907 ret
= route_map_apply(UNSUPPRESS_MAP(filter
), p
,
1908 RMAP_BGP
, &rmap_path
);
1910 ret
= route_map_apply(ROUTE_MAP_OUT(filter
), p
,
1911 RMAP_BGP
, &rmap_path
);
1913 peer
->rmap_type
= 0;
1915 if (ret
== RMAP_DENYMATCH
) {
1916 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1917 zlog_debug("%s [Update:SEND] %s is filtered by route-map",
1918 peer
->host
, prefix2str(p
, buf
, sizeof(buf
)));
1920 bgp_attr_flush(attr
);
1925 /* RFC 8212 to prevent route leaks.
1926 * This specification intends to improve this situation by requiring the
1927 * explicit configuration of both BGP Import and Export Policies for any
1928 * External BGP (EBGP) session such as customers, peers, or
1929 * confederation boundaries for all enabled address families. Through
1930 * codification of the aforementioned requirement, operators will
1931 * benefit from consistent behavior across different BGP
1934 if (peer
->bgp
->ebgp_requires_policy
1935 == DEFAULT_EBGP_POLICY_ENABLED
)
1936 if (!bgp_outbound_policy_exists(peer
, filter
))
1939 /* draft-ietf-idr-deprecate-as-set-confed-set
1940 * Filter routes having AS_SET or AS_CONFED_SET in the path.
1941 * Eventually, This document (if approved) updates RFC 4271
1942 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
1943 * and obsoletes RFC 6472.
1945 if (peer
->bgp
->reject_as_sets
== BGP_REJECT_AS_SETS_ENABLED
)
1946 if (aspath_check_as_sets(attr
->aspath
))
1949 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
1950 if (peer
->sort
== BGP_PEER_IBGP
1951 || peer
->sort
== BGP_PEER_CONFED
) {
1952 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1953 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1955 bgp_attr_add_gshut_community(attr
);
1959 /* After route-map has been applied, we check to see if the nexthop to
1960 * be carried in the attribute (that is used for the announcement) can
1961 * be cleared off or not. We do this in all cases where we would be
1962 * setting the nexthop to "ourselves". For IPv6, we only need to
1964 * the global nexthop here; the link-local nexthop would have been
1966 * already, and if not, it is required by the update formation code.
1967 * Also see earlier comments in this function.
1970 * If route-map has performed some operation on the nexthop or the peer
1971 * configuration says to pass it unchanged, we cannot reset the nexthop
1972 * here, so only attempt to do it if these aren't true. Note that the
1973 * route-map handler itself might have cleared the nexthop, if for
1975 * it is configured as 'peer-address'.
1977 if (!bgp_rmap_nhop_changed(attr
->rmap_change_flags
,
1978 piattr
->rmap_change_flags
)
1980 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1981 PEER_FLAG_NEXTHOP_UNCHANGED
)) {
1982 /* We can reset the nexthop, if setting (or forcing) it to
1984 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1985 PEER_FLAG_NEXTHOP_SELF
)
1986 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1987 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
1989 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1990 PEER_FLAG_FORCE_NEXTHOP_SELF
))
1991 subgroup_announce_reset_nhop(
1992 (peer_cap_enhe(peer
, afi
, safi
)
1996 } else if (peer
->sort
== BGP_PEER_EBGP
) {
1997 /* Can also reset the nexthop if announcing to EBGP, but
1999 * no peer in the subgroup is on a shared subnet.
2000 * Note: 3rd party nexthop currently implemented for
2003 if ((p
->family
== AF_INET
) &&
2004 (!bgp_subgrp_multiaccess_check_v4(
2007 subgroup_announce_reset_nhop(
2008 (peer_cap_enhe(peer
, afi
, safi
)
2013 if ((p
->family
== AF_INET6
) &&
2014 (!bgp_subgrp_multiaccess_check_v6(
2015 piattr
->mp_nexthop_global
,
2017 subgroup_announce_reset_nhop(
2018 (peer_cap_enhe(peer
, afi
, safi
)
2025 } else if (CHECK_FLAG(pi
->flags
, BGP_PATH_ANNC_NH_SELF
)) {
2027 * This flag is used for leaked vpn-vrf routes
2029 int family
= p
->family
;
2031 if (peer_cap_enhe(peer
, afi
, safi
))
2034 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2036 "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
2037 __func__
, family2str(family
));
2038 subgroup_announce_reset_nhop(family
, attr
);
2042 /* If IPv6/MP and nexthop does not have any override and happens
2044 * be a link-local address, reset it so that we don't pass along
2046 * source's link-local IPv6 address to recipients who may not be
2048 * the same interface.
2050 if (p
->family
== AF_INET6
|| peer_cap_enhe(peer
, afi
, safi
)) {
2051 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
))
2052 subgroup_announce_reset_nhop(AF_INET6
, attr
);
2058 static int bgp_route_select_timer_expire(struct thread
*thread
)
2060 struct afi_safi_info
*info
;
2065 info
= THREAD_ARG(thread
);
2070 if (BGP_DEBUG(update
, UPDATE_OUT
))
2071 zlog_debug("afi %d, safi %d : route select timer expired", afi
,
2074 bgp
->gr_info
[afi
][safi
].t_route_select
= NULL
;
2076 XFREE(MTYPE_TMP
, info
);
2078 /* Best path selection */
2079 return bgp_best_path_select_defer(bgp
, afi
, safi
);
2082 void bgp_best_selection(struct bgp
*bgp
, struct bgp_node
*rn
,
2083 struct bgp_maxpaths_cfg
*mpath_cfg
,
2084 struct bgp_path_info_pair
*result
, afi_t afi
,
2087 struct bgp_path_info
*new_select
;
2088 struct bgp_path_info
*old_select
;
2089 struct bgp_path_info
*pi
;
2090 struct bgp_path_info
*pi1
;
2091 struct bgp_path_info
*pi2
;
2092 struct bgp_path_info
*nextpi
= NULL
;
2093 int paths_eq
, do_mpath
, debug
;
2094 struct list mp_list
;
2095 char pfx_buf
[PREFIX2STR_BUFFER
];
2096 char path_buf
[PATH_ADDPATH_STR_BUFFER
];
2098 bgp_mp_list_init(&mp_list
);
2100 (mpath_cfg
->maxpaths_ebgp
> 1 || mpath_cfg
->maxpaths_ibgp
> 1);
2102 debug
= bgp_debug_bestpath(&rn
->p
);
2105 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
2107 /* bgp deterministic-med */
2109 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DETERMINISTIC_MED
)) {
2111 /* Clear BGP_PATH_DMED_SELECTED for all paths */
2112 for (pi1
= bgp_node_get_bgp_path_info(rn
); pi1
;
2114 bgp_path_info_unset_flag(rn
, pi1
,
2115 BGP_PATH_DMED_SELECTED
);
2117 for (pi1
= bgp_node_get_bgp_path_info(rn
); pi1
;
2119 if (CHECK_FLAG(pi1
->flags
, BGP_PATH_DMED_CHECK
))
2121 if (BGP_PATH_HOLDDOWN(pi1
))
2123 if (pi1
->peer
!= bgp
->peer_self
)
2124 if (pi1
->peer
->status
!= Established
)
2129 for (pi2
= pi1
->next
; pi2
; pi2
= pi2
->next
) {
2130 if (CHECK_FLAG(pi2
->flags
,
2131 BGP_PATH_DMED_CHECK
))
2133 if (BGP_PATH_HOLDDOWN(pi2
))
2135 if (pi2
->peer
!= bgp
->peer_self
2138 PEER_STATUS_NSF_WAIT
))
2139 if (pi2
->peer
->status
2143 if (!aspath_cmp_left(pi1
->attr
->aspath
,
2145 && !aspath_cmp_left_confed(
2150 if (bgp_path_info_cmp(
2151 bgp
, pi2
, new_select
,
2152 &paths_eq
, mpath_cfg
, debug
,
2155 bgp_path_info_unset_flag(
2157 BGP_PATH_DMED_SELECTED
);
2161 bgp_path_info_set_flag(
2162 rn
, pi2
, BGP_PATH_DMED_CHECK
);
2165 bgp_path_info_set_flag(rn
, new_select
,
2166 BGP_PATH_DMED_CHECK
);
2167 bgp_path_info_set_flag(rn
, new_select
,
2168 BGP_PATH_DMED_SELECTED
);
2171 bgp_path_info_path_with_addpath_rx_str(
2172 new_select
, path_buf
);
2173 zlog_debug("%s: %s is the bestpath from AS %u",
2175 aspath_get_first_as(
2176 new_select
->attr
->aspath
));
2181 /* Check old selected route and new selected route. */
2184 for (pi
= bgp_node_get_bgp_path_info(rn
);
2185 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2186 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
2189 if (BGP_PATH_HOLDDOWN(pi
)) {
2190 /* reap REMOVED routes, if needs be
2191 * selected route must stay for a while longer though
2193 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
2194 && (pi
!= old_select
))
2195 bgp_path_info_reap(rn
, pi
);
2198 zlog_debug("%s: pi %p in holddown", __func__
,
2204 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2205 && !CHECK_FLAG(pi
->peer
->sflags
, PEER_STATUS_NSF_WAIT
))
2206 if (pi
->peer
->status
!= Established
) {
2210 "%s: pi %p non self peer %s not estab state",
2211 __func__
, pi
, pi
->peer
->host
);
2216 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DETERMINISTIC_MED
)
2217 && (!CHECK_FLAG(pi
->flags
, BGP_PATH_DMED_SELECTED
))) {
2218 bgp_path_info_unset_flag(rn
, pi
, BGP_PATH_DMED_CHECK
);
2220 zlog_debug("%s: pi %p dmed", __func__
, pi
);
2224 bgp_path_info_unset_flag(rn
, pi
, BGP_PATH_DMED_CHECK
);
2226 if (bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
, mpath_cfg
,
2227 debug
, pfx_buf
, afi
, safi
, &rn
->reason
)) {
2232 /* Now that we know which path is the bestpath see if any of the other
2234 * qualify as multipaths
2238 bgp_path_info_path_with_addpath_rx_str(new_select
,
2241 sprintf(path_buf
, "NONE");
2243 "%s: After path selection, newbest is %s oldbest was %s",
2245 old_select
? old_select
->peer
->host
: "NONE");
2248 if (do_mpath
&& new_select
) {
2249 for (pi
= bgp_node_get_bgp_path_info(rn
);
2250 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2253 bgp_path_info_path_with_addpath_rx_str(
2256 if (pi
== new_select
) {
2259 "%s: %s is the bestpath, add to the multipath list",
2261 bgp_mp_list_add(&mp_list
, pi
);
2265 if (BGP_PATH_HOLDDOWN(pi
))
2268 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2269 && !CHECK_FLAG(pi
->peer
->sflags
,
2270 PEER_STATUS_NSF_WAIT
))
2271 if (pi
->peer
->status
!= Established
)
2274 if (!bgp_path_info_nexthop_cmp(pi
, new_select
)) {
2277 "%s: %s has the same nexthop as the bestpath, skip it",
2282 bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
,
2283 mpath_cfg
, debug
, pfx_buf
, afi
, safi
,
2289 "%s: %s is equivalent to the bestpath, add to the multipath list",
2291 bgp_mp_list_add(&mp_list
, pi
);
2296 bgp_path_info_mpath_update(rn
, new_select
, old_select
, &mp_list
,
2298 bgp_path_info_mpath_aggregate_update(new_select
, old_select
);
2299 bgp_mp_list_clear(&mp_list
);
2301 bgp_addpath_update_ids(bgp
, rn
, afi
, safi
);
2303 result
->old
= old_select
;
2304 result
->new = new_select
;
2310 * A new route/change in bestpath of an existing route. Evaluate the path
2311 * for advertisement to the subgroup.
2313 int subgroup_process_announce_selected(struct update_subgroup
*subgrp
,
2314 struct bgp_path_info
*selected
,
2315 struct bgp_node
*rn
,
2316 uint32_t addpath_tx_id
)
2319 struct peer
*onlypeer
;
2325 afi
= SUBGRP_AFI(subgrp
);
2326 safi
= SUBGRP_SAFI(subgrp
);
2327 onlypeer
= ((SUBGRP_PCOUNT(subgrp
) == 1) ? (SUBGRP_PFIRST(subgrp
))->peer
2330 if (BGP_DEBUG(update
, UPDATE_OUT
)) {
2331 char buf_prefix
[PREFIX_STRLEN
];
2332 prefix2str(p
, buf_prefix
, sizeof(buf_prefix
));
2333 zlog_debug("%s: p=%s, selected=%p", __func__
, buf_prefix
,
2337 /* First update is deferred until ORF or ROUTE-REFRESH is received */
2338 if (onlypeer
&& CHECK_FLAG(onlypeer
->af_sflags
[afi
][safi
],
2339 PEER_STATUS_ORF_WAIT_REFRESH
))
2342 memset(&attr
, 0, sizeof(struct attr
));
2343 /* It's initialized in bgp_announce_check() */
2345 /* Announcement to the subgroup. If the route is filtered withdraw it.
2348 if (subgroup_announce_check(rn
, selected
, subgrp
, p
, &attr
))
2349 bgp_adj_out_set_subgroup(rn
, subgrp
, &attr
, selected
);
2351 bgp_adj_out_unset_subgroup(rn
, subgrp
, 1,
2355 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2357 bgp_adj_out_unset_subgroup(rn
, subgrp
, 1, addpath_tx_id
);
2364 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2365 * This is called at the end of route processing.
2367 void bgp_zebra_clear_route_change_flags(struct bgp_node
*rn
)
2369 struct bgp_path_info
*pi
;
2371 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
2372 if (BGP_PATH_HOLDDOWN(pi
))
2374 UNSET_FLAG(pi
->flags
, BGP_PATH_IGP_CHANGED
);
2375 UNSET_FLAG(pi
->flags
, BGP_PATH_ATTR_CHANGED
);
2380 * Has the route changed from the RIB's perspective? This is invoked only
2381 * if the route selection returns the same best route as earlier - to
2382 * determine if we need to update zebra or not.
2384 int bgp_zebra_has_route_changed(struct bgp_node
*rn
,
2385 struct bgp_path_info
*selected
)
2387 struct bgp_path_info
*mpinfo
;
2389 /* If this is multipath, check all selected paths for any nexthop
2390 * change or attribute change. Some attribute changes (e.g., community)
2391 * aren't of relevance to the RIB, but we'll update zebra to ensure
2392 * we handle the case of BGP nexthop change. This is the behavior
2393 * when the best path has an attribute change anyway.
2395 if (CHECK_FLAG(selected
->flags
, BGP_PATH_IGP_CHANGED
)
2396 || CHECK_FLAG(selected
->flags
, BGP_PATH_MULTIPATH_CHG
))
2400 * If this is multipath, check all selected paths for any nexthop change
2402 for (mpinfo
= bgp_path_info_mpath_first(selected
); mpinfo
;
2403 mpinfo
= bgp_path_info_mpath_next(mpinfo
)) {
2404 if (CHECK_FLAG(mpinfo
->flags
, BGP_PATH_IGP_CHANGED
)
2405 || CHECK_FLAG(mpinfo
->flags
, BGP_PATH_ATTR_CHANGED
))
2409 /* Nothing has changed from the RIB's perspective. */
2413 struct bgp_process_queue
{
2415 STAILQ_HEAD(, bgp_node
) pqueue
;
2416 #define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2418 unsigned int queued
;
2422 * old_select = The old best path
2423 * new_select = the new best path
2425 * if (!old_select && new_select)
2426 * We are sending new information on.
2428 * if (old_select && new_select) {
2429 * if (new_select != old_select)
2430 * We have a new best path send a change
2432 * We've received a update with new attributes that needs
2436 * if (old_select && !new_select)
2437 * We have no eligible route that we can announce or the rn
2440 static void bgp_process_main_one(struct bgp
*bgp
, struct bgp_node
*rn
,
2441 afi_t afi
, safi_t safi
)
2443 struct bgp_path_info
*new_select
;
2444 struct bgp_path_info
*old_select
;
2445 struct bgp_path_info_pair old_and_new
;
2446 char pfx_buf
[PREFIX2STR_BUFFER
];
2449 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)) {
2451 debug
= bgp_debug_bestpath(&rn
->p
);
2453 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
2455 "%s: bgp delete in progress, ignoring event, p=%s",
2460 /* Is it end of initial update? (after startup) */
2462 quagga_timestamp(3, bgp
->update_delay_zebra_resume_time
,
2463 sizeof(bgp
->update_delay_zebra_resume_time
));
2465 bgp
->main_zebra_update_hold
= 0;
2466 FOREACH_AFI_SAFI (afi
, safi
) {
2467 if (bgp_fibupd_safi(safi
))
2468 bgp_zebra_announce_table(bgp
, afi
, safi
);
2470 bgp
->main_peers_update_hold
= 0;
2472 bgp_start_routeadv(bgp
);
2476 struct prefix
*p
= &rn
->p
;
2478 debug
= bgp_debug_bestpath(&rn
->p
);
2480 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
2481 zlog_debug("%s: p=%s afi=%s, safi=%s start", __func__
, pfx_buf
,
2482 afi2str(afi
), safi2str(safi
));
2485 /* The best path calculation for the route is deferred if
2486 * BGP_NODE_SELECT_DEFER is set
2488 if (CHECK_FLAG(rn
->flags
, BGP_NODE_SELECT_DEFER
)) {
2489 if (BGP_DEBUG(update
, UPDATE_OUT
))
2490 zlog_debug("SELECT_DEFER falg set for route %p", rn
);
2494 /* Best path selection. */
2495 bgp_best_selection(bgp
, rn
, &bgp
->maxpaths
[afi
][safi
], &old_and_new
,
2497 old_select
= old_and_new
.old
;
2498 new_select
= old_and_new
.new;
2500 /* Do we need to allocate or free labels?
2501 * Right now, since we only deal with per-prefix labels, it is not
2502 * necessary to do this upon changes to best path. Exceptions:
2503 * - label index has changed -> recalculate resulting label
2504 * - path_info sub_type changed -> switch to/from implicit-null
2505 * - no valid label (due to removed static label binding) -> get new one
2507 if (bgp
->allocate_mpls_labels
[afi
][safi
]) {
2510 || bgp_label_index_differs(new_select
, old_select
)
2511 || new_select
->sub_type
!= old_select
->sub_type
2512 || !bgp_is_valid_label(&rn
->local_label
)) {
2513 /* Enforced penultimate hop popping:
2514 * implicit-null for local routes, aggregate
2515 * and redistributed routes
2517 if (new_select
->sub_type
== BGP_ROUTE_STATIC
2518 || new_select
->sub_type
2519 == BGP_ROUTE_AGGREGATE
2520 || new_select
->sub_type
2521 == BGP_ROUTE_REDISTRIBUTE
) {
2524 BGP_NODE_REGISTERED_FOR_LABEL
))
2525 bgp_unregister_for_label(rn
);
2526 label_ntop(MPLS_LABEL_IMPLICIT_NULL
, 1,
2528 bgp_set_valid_label(&rn
->local_label
);
2530 bgp_register_for_label(rn
, new_select
);
2532 } else if (CHECK_FLAG(rn
->flags
,
2533 BGP_NODE_REGISTERED_FOR_LABEL
)) {
2534 bgp_unregister_for_label(rn
);
2536 } else if (CHECK_FLAG(rn
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
)) {
2537 bgp_unregister_for_label(rn
);
2541 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
2543 "%s: p=%s afi=%s, safi=%s, old_select=%p, new_select=%p",
2544 __func__
, pfx_buf
, afi2str(afi
), safi2str(safi
),
2545 old_select
, new_select
);
2548 /* If best route remains the same and this is not due to user-initiated
2549 * clear, see exactly what needs to be done.
2551 if (old_select
&& old_select
== new_select
2552 && !CHECK_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
)
2553 && !CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
2554 && !bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
2555 if (bgp_zebra_has_route_changed(rn
, old_select
)) {
2557 vnc_import_bgp_add_route(bgp
, p
, old_select
);
2558 vnc_import_bgp_exterior_add_route(bgp
, p
, old_select
);
2560 if (bgp_fibupd_safi(safi
)
2561 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2563 if (new_select
->type
== ZEBRA_ROUTE_BGP
2564 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2565 || new_select
->sub_type
2566 == BGP_ROUTE_IMPORTED
))
2568 bgp_zebra_announce(rn
, p
, old_select
,
2572 UNSET_FLAG(old_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
2573 bgp_zebra_clear_route_change_flags(rn
);
2575 /* If there is a change of interest to peers, reannounce the
2577 if (CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
2578 || CHECK_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
)) {
2579 group_announce_route(bgp
, afi
, safi
, rn
, new_select
);
2581 /* unicast routes must also be annouced to
2582 * labeled-unicast update-groups */
2583 if (safi
== SAFI_UNICAST
)
2584 group_announce_route(bgp
, afi
,
2585 SAFI_LABELED_UNICAST
, rn
,
2588 UNSET_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
);
2589 UNSET_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
);
2592 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2596 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2598 UNSET_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
);
2600 /* bestpath has changed; bump version */
2601 if (old_select
|| new_select
) {
2602 bgp_bump_version(rn
);
2604 if (!bgp
->t_rmap_def_originate_eval
) {
2608 update_group_refresh_default_originate_route_map
,
2609 bgp
, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER
,
2610 &bgp
->t_rmap_def_originate_eval
);
2615 bgp_path_info_unset_flag(rn
, old_select
, BGP_PATH_SELECTED
);
2618 zlog_debug("%s: setting SELECTED flag", __func__
);
2619 bgp_path_info_set_flag(rn
, new_select
, BGP_PATH_SELECTED
);
2620 bgp_path_info_unset_flag(rn
, new_select
, BGP_PATH_ATTR_CHANGED
);
2621 UNSET_FLAG(new_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
2625 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2626 if (old_select
!= new_select
) {
2628 vnc_import_bgp_exterior_del_route(bgp
, p
,
2630 vnc_import_bgp_del_route(bgp
, p
, old_select
);
2633 vnc_import_bgp_exterior_add_route(bgp
, p
,
2635 vnc_import_bgp_add_route(bgp
, p
, new_select
);
2641 group_announce_route(bgp
, afi
, safi
, rn
, new_select
);
2643 /* unicast routes must also be annouced to labeled-unicast update-groups
2645 if (safi
== SAFI_UNICAST
)
2646 group_announce_route(bgp
, afi
, SAFI_LABELED_UNICAST
, rn
,
2650 if (bgp_fibupd_safi(safi
) && (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VIEW
)
2651 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2652 if (new_select
&& new_select
->type
== ZEBRA_ROUTE_BGP
2653 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2654 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
2655 || new_select
->sub_type
== BGP_ROUTE_IMPORTED
)) {
2657 /* if this is an evpn imported type-5 prefix,
2658 * we need to withdraw the route first to clear
2659 * the nh neigh and the RMAC entry.
2662 is_route_parent_evpn(old_select
))
2663 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2665 bgp_zebra_announce(rn
, p
, new_select
, bgp
, afi
, safi
);
2667 /* Withdraw the route from the kernel. */
2668 if (old_select
&& old_select
->type
== ZEBRA_ROUTE_BGP
2669 && (old_select
->sub_type
== BGP_ROUTE_NORMAL
2670 || old_select
->sub_type
== BGP_ROUTE_AGGREGATE
2671 || old_select
->sub_type
== BGP_ROUTE_IMPORTED
))
2673 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2677 /* advertise/withdraw type-5 routes */
2678 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2679 if (advertise_type5_routes(bgp
, afi
) &&
2681 is_route_injectable_into_evpn(new_select
)) {
2683 /* apply the route-map */
2684 if (bgp
->adv_cmd_rmap
[afi
][safi
].map
) {
2685 route_map_result_t ret
;
2687 ret
= route_map_apply(
2688 bgp
->adv_cmd_rmap
[afi
][safi
].map
,
2689 &rn
->p
, RMAP_BGP
, new_select
);
2690 if (ret
== RMAP_PERMITMATCH
)
2691 bgp_evpn_advertise_type5_route(
2692 bgp
, &rn
->p
, new_select
->attr
,
2695 bgp_evpn_withdraw_type5_route(
2696 bgp
, &rn
->p
, afi
, safi
);
2698 bgp_evpn_advertise_type5_route(bgp
,
2704 } else if (advertise_type5_routes(bgp
, afi
) &&
2706 is_route_injectable_into_evpn(old_select
))
2707 bgp_evpn_withdraw_type5_route(bgp
, &rn
->p
, afi
, safi
);
2710 /* Clear any route change flags. */
2711 bgp_zebra_clear_route_change_flags(rn
);
2713 /* Reap old select bgp_path_info, if it has been removed */
2714 if (old_select
&& CHECK_FLAG(old_select
->flags
, BGP_PATH_REMOVED
))
2715 bgp_path_info_reap(rn
, old_select
);
2717 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2721 /* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
2722 int bgp_best_path_select_defer(struct bgp
*bgp
, afi_t afi
, safi_t safi
)
2724 struct bgp_node
*rn
;
2726 struct afi_safi_info
*thread_info
;
2727 struct listnode
*node
= NULL
, *nnode
= NULL
;
2729 if (bgp
->gr_info
[afi
][safi
].t_route_select
)
2730 BGP_TIMER_OFF(bgp
->gr_info
[afi
][safi
].t_route_select
);
2732 if (BGP_DEBUG(update
, UPDATE_OUT
)) {
2733 zlog_debug("%s: processing route for %s : cnt %d", __func__
,
2734 get_afi_safi_str(afi
, safi
, false),
2735 listcount(bgp
->gr_info
[afi
][safi
].route_list
));
2738 /* Process the route list */
2739 node
= listhead(bgp
->gr_info
[afi
][safi
].route_list
);
2741 rn
= listgetdata(node
);
2743 list_delete_node(bgp
->gr_info
[afi
][safi
].route_list
, node
);
2746 if (CHECK_FLAG(rn
->flags
, BGP_NODE_SELECT_DEFER
)) {
2747 UNSET_FLAG(rn
->flags
, BGP_NODE_SELECT_DEFER
);
2748 bgp_process_main_one(bgp
, rn
, afi
, safi
);
2750 if (cnt
>= BGP_MAX_BEST_ROUTE_SELECT
)
2756 /* Send EOR message when all routes are processed */
2757 if (list_isempty(bgp
->gr_info
[afi
][safi
].route_list
)) {
2758 bgp_send_delayed_eor(bgp
);
2759 /* Send route processing complete message to RIB */
2760 bgp_zebra_update(afi
, safi
, bgp
->vrf_id
,
2761 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE
);
2765 thread_info
= XMALLOC(MTYPE_TMP
, sizeof(struct afi_safi_info
));
2767 thread_info
->afi
= afi
;
2768 thread_info
->safi
= safi
;
2769 thread_info
->bgp
= bgp
;
2771 /* If there are more routes to be processed, start the
2774 thread_add_timer(bm
->master
, bgp_route_select_timer_expire
, thread_info
,
2775 BGP_ROUTE_SELECT_DELAY
,
2776 &bgp
->gr_info
[afi
][safi
].t_route_select
);
2780 static wq_item_status
bgp_process_wq(struct work_queue
*wq
, void *data
)
2782 struct bgp_process_queue
*pqnode
= data
;
2783 struct bgp
*bgp
= pqnode
->bgp
;
2784 struct bgp_table
*table
;
2785 struct bgp_node
*rn
;
2788 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)) {
2789 bgp_process_main_one(bgp
, NULL
, 0, 0);
2790 /* should always have dedicated wq call */
2791 assert(STAILQ_FIRST(&pqnode
->pqueue
) == NULL
);
2795 while (!STAILQ_EMPTY(&pqnode
->pqueue
)) {
2796 rn
= STAILQ_FIRST(&pqnode
->pqueue
);
2797 STAILQ_REMOVE_HEAD(&pqnode
->pqueue
, pq
);
2798 STAILQ_NEXT(rn
, pq
) = NULL
; /* complete unlink */
2799 table
= bgp_node_table(rn
);
2800 /* note, new RNs may be added as part of processing */
2801 bgp_process_main_one(bgp
, rn
, table
->afi
, table
->safi
);
2803 bgp_unlock_node(rn
);
2804 bgp_table_unlock(table
);
2810 static void bgp_processq_del(struct work_queue
*wq
, void *data
)
2812 struct bgp_process_queue
*pqnode
= data
;
2814 bgp_unlock(pqnode
->bgp
);
2816 XFREE(MTYPE_BGP_PROCESS_QUEUE
, pqnode
);
2819 void bgp_process_queue_init(void)
2821 if (!bm
->process_main_queue
)
2822 bm
->process_main_queue
=
2823 work_queue_new(bm
->master
, "process_main_queue");
2825 bm
->process_main_queue
->spec
.workfunc
= &bgp_process_wq
;
2826 bm
->process_main_queue
->spec
.del_item_data
= &bgp_processq_del
;
2827 bm
->process_main_queue
->spec
.max_retries
= 0;
2828 bm
->process_main_queue
->spec
.hold
= 50;
2829 /* Use a higher yield value of 50ms for main queue processing */
2830 bm
->process_main_queue
->spec
.yield
= 50 * 1000L;
2833 static struct bgp_process_queue
*bgp_processq_alloc(struct bgp
*bgp
)
2835 struct bgp_process_queue
*pqnode
;
2837 pqnode
= XCALLOC(MTYPE_BGP_PROCESS_QUEUE
,
2838 sizeof(struct bgp_process_queue
));
2840 /* unlocked in bgp_processq_del */
2841 pqnode
->bgp
= bgp_lock(bgp
);
2842 STAILQ_INIT(&pqnode
->pqueue
);
2847 void bgp_process(struct bgp
*bgp
, struct bgp_node
*rn
, afi_t afi
, safi_t safi
)
2849 #define ARBITRARY_PROCESS_QLEN 10000
2850 struct work_queue
*wq
= bm
->process_main_queue
;
2851 struct bgp_process_queue
*pqnode
;
2852 int pqnode_reuse
= 0;
2854 /* already scheduled for processing? */
2855 if (CHECK_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
2858 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
2861 if (CHECK_FLAG(rn
->flags
, BGP_NODE_SELECT_DEFER
)) {
2862 if (BGP_DEBUG(update
, UPDATE_OUT
))
2863 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
2871 /* Add route nodes to an existing work queue item until reaching the
2872 limit only if is from the same BGP view and it's not an EOIU marker
2874 if (work_queue_item_count(wq
)) {
2875 struct work_queue_item
*item
= work_queue_last_item(wq
);
2876 pqnode
= item
->data
;
2878 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)
2879 || pqnode
->bgp
!= bgp
2880 || pqnode
->queued
>= ARBITRARY_PROCESS_QLEN
)
2881 pqnode
= bgp_processq_alloc(bgp
);
2885 pqnode
= bgp_processq_alloc(bgp
);
2886 /* all unlocked in bgp_process_wq */
2887 bgp_table_lock(bgp_node_table(rn
));
2889 SET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2892 /* can't be enqueued twice */
2893 assert(STAILQ_NEXT(rn
, pq
) == NULL
);
2894 STAILQ_INSERT_TAIL(&pqnode
->pqueue
, rn
, pq
);
2898 work_queue_add(wq
, pqnode
);
2903 void bgp_add_eoiu_mark(struct bgp
*bgp
)
2905 struct bgp_process_queue
*pqnode
;
2907 if (bm
->process_main_queue
== NULL
)
2910 pqnode
= bgp_processq_alloc(bgp
);
2912 SET_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
);
2913 work_queue_add(bm
->process_main_queue
, pqnode
);
2916 static int bgp_maximum_prefix_restart_timer(struct thread
*thread
)
2920 peer
= THREAD_ARG(thread
);
2921 peer
->t_pmax_restart
= NULL
;
2923 if (bgp_debug_neighbor_events(peer
))
2925 "%s Maximum-prefix restart timer expired, restore peering",
2928 if ((peer_clear(peer
, NULL
) < 0) && bgp_debug_neighbor_events(peer
))
2929 zlog_debug("%s: %s peer_clear failed",
2930 __PRETTY_FUNCTION__
, peer
->host
);
2935 int bgp_maximum_prefix_overflow(struct peer
*peer
, afi_t afi
, safi_t safi
,
2939 iana_safi_t pkt_safi
;
2941 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX
))
2944 if (peer
->pcount
[afi
][safi
] > peer
->pmax
[afi
][safi
]) {
2945 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2946 PEER_STATUS_PREFIX_LIMIT
)
2951 "%%MAXPFXEXCEED: No. of %s prefix received from %s %" PRIu32
2952 " exceed, limit %" PRIu32
,
2953 get_afi_safi_str(afi
, safi
, false), peer
->host
,
2954 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2955 SET_FLAG(peer
->af_sflags
[afi
][safi
], PEER_STATUS_PREFIX_LIMIT
);
2957 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2958 PEER_FLAG_MAX_PREFIX_WARNING
))
2961 /* Convert AFI, SAFI to values for packet. */
2962 pkt_afi
= afi_int2iana(afi
);
2963 pkt_safi
= safi_int2iana(safi
);
2967 ndata
[0] = (pkt_afi
>> 8);
2969 ndata
[2] = pkt_safi
;
2970 ndata
[3] = (peer
->pmax
[afi
][safi
] >> 24);
2971 ndata
[4] = (peer
->pmax
[afi
][safi
] >> 16);
2972 ndata
[5] = (peer
->pmax
[afi
][safi
] >> 8);
2973 ndata
[6] = (peer
->pmax
[afi
][safi
]);
2975 SET_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
);
2976 bgp_notify_send_with_data(peer
, BGP_NOTIFY_CEASE
,
2977 BGP_NOTIFY_CEASE_MAX_PREFIX
,
2981 /* Dynamic peers will just close their connection. */
2982 if (peer_dynamic_neighbor(peer
))
2985 /* restart timer start */
2986 if (peer
->pmax_restart
[afi
][safi
]) {
2987 peer
->v_pmax_restart
=
2988 peer
->pmax_restart
[afi
][safi
] * 60;
2990 if (bgp_debug_neighbor_events(peer
))
2992 "%s Maximum-prefix restart timer started for %d secs",
2993 peer
->host
, peer
->v_pmax_restart
);
2995 BGP_TIMER_ON(peer
->t_pmax_restart
,
2996 bgp_maximum_prefix_restart_timer
,
2997 peer
->v_pmax_restart
);
3002 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
3003 PEER_STATUS_PREFIX_LIMIT
);
3005 if (peer
->pcount
[afi
][safi
]
3006 > (peer
->pmax
[afi
][safi
] * peer
->pmax_threshold
[afi
][safi
] / 100)) {
3007 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
3008 PEER_STATUS_PREFIX_THRESHOLD
)
3013 "%%MAXPFX: No. of %s prefix received from %s reaches %" PRIu32
3015 get_afi_safi_str(afi
, safi
, false), peer
->host
,
3016 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
3017 SET_FLAG(peer
->af_sflags
[afi
][safi
],
3018 PEER_STATUS_PREFIX_THRESHOLD
);
3020 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
3021 PEER_STATUS_PREFIX_THRESHOLD
);
3025 /* Unconditionally remove the route from the RIB, without taking
3026 * damping into consideration (eg, because the session went down)
3028 void bgp_rib_remove(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
3029 struct peer
*peer
, afi_t afi
, safi_t safi
)
3032 struct bgp
*bgp
= NULL
;
3033 bool delete_route
= false;
3035 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, pi
, afi
, safi
);
3037 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3038 bgp_path_info_delete(rn
, pi
); /* keep historical info */
3040 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3043 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
3044 delete_route
= true;
3045 else if (bgp_node_set_defer_flag(rn
, true) < 0)
3046 delete_route
= true;
3048 if (CHECK_FLAG(rn
->flags
, BGP_NODE_SELECT_DEFER
)) {
3049 UNSET_FLAG(rn
->flags
, BGP_NODE_SELECT_DEFER
);
3050 bgp
= pi
->peer
->bgp
;
3052 && (bgp
->gr_info
[afi
][safi
].route_list
)) {
3053 list_delete_node(bgp
->gr_info
[afi
][safi
]
3062 hook_call(bgp_process
, peer
->bgp
, afi
, safi
, rn
, peer
, true);
3063 bgp_process(peer
->bgp
, rn
, afi
, safi
);
3066 static void bgp_rib_withdraw(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
3067 struct peer
*peer
, afi_t afi
, safi_t safi
,
3068 struct prefix_rd
*prd
)
3070 /* apply dampening, if result is suppressed, we'll be retaining
3071 * the bgp_path_info in the RIB for historical reference.
3073 if (CHECK_FLAG(peer
->bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3074 && peer
->sort
== BGP_PEER_EBGP
)
3075 if ((bgp_damp_withdraw(pi
, rn
, afi
, safi
, 0))
3076 == BGP_DAMP_SUPPRESSED
) {
3077 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, pi
, afi
,
3083 if (safi
== SAFI_MPLS_VPN
) {
3084 struct bgp_node
*prn
= NULL
;
3085 struct bgp_table
*table
= NULL
;
3087 prn
= bgp_node_get(peer
->bgp
->rib
[afi
][safi
],
3088 (struct prefix
*)prd
);
3089 if (bgp_node_has_bgp_path_info_data(prn
)) {
3090 table
= bgp_node_get_bgp_table_info(prn
);
3092 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3093 peer
->bgp
, prd
, table
, &rn
->p
, pi
);
3095 bgp_unlock_node(prn
);
3097 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
3098 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
3100 vnc_import_bgp_del_route(peer
->bgp
, &rn
->p
, pi
);
3101 vnc_import_bgp_exterior_del_route(peer
->bgp
, &rn
->p
,
3107 /* If this is an EVPN route, process for un-import. */
3108 if (safi
== SAFI_EVPN
)
3109 bgp_evpn_unimport_route(peer
->bgp
, afi
, safi
, &rn
->p
, pi
);
3111 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
3114 struct bgp_path_info
*info_make(int type
, int sub_type
, unsigned short instance
,
3115 struct peer
*peer
, struct attr
*attr
,
3116 struct bgp_node
*rn
)
3118 struct bgp_path_info
*new;
3120 /* Make new BGP info. */
3121 new = XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_path_info
));
3123 new->instance
= instance
;
3124 new->sub_type
= sub_type
;
3127 new->uptime
= bgp_clock();
3132 static void overlay_index_update(struct attr
*attr
,
3133 struct eth_segment_id
*eth_s_id
,
3134 union gw_addr
*gw_ip
)
3139 if (eth_s_id
== NULL
) {
3140 memset(&(attr
->evpn_overlay
.eth_s_id
), 0,
3141 sizeof(struct eth_segment_id
));
3143 memcpy(&(attr
->evpn_overlay
.eth_s_id
), eth_s_id
,
3144 sizeof(struct eth_segment_id
));
3146 if (gw_ip
== NULL
) {
3147 memset(&(attr
->evpn_overlay
.gw_ip
), 0, sizeof(union gw_addr
));
3149 memcpy(&(attr
->evpn_overlay
.gw_ip
), gw_ip
,
3150 sizeof(union gw_addr
));
3154 static bool overlay_index_equal(afi_t afi
, struct bgp_path_info
*path
,
3155 struct eth_segment_id
*eth_s_id
,
3156 union gw_addr
*gw_ip
)
3158 struct eth_segment_id
*path_eth_s_id
, *path_eth_s_id_remote
;
3159 union gw_addr
*path_gw_ip
, *path_gw_ip_remote
;
3161 struct eth_segment_id esi
;
3165 if (afi
!= AFI_L2VPN
)
3168 path_eth_s_id
= &(path
->attr
->evpn_overlay
.eth_s_id
);
3169 path_gw_ip
= &(path
->attr
->evpn_overlay
.gw_ip
);
3171 if (gw_ip
== NULL
) {
3172 memset(&temp
, 0, sizeof(temp
));
3173 path_gw_ip_remote
= &temp
.ip
;
3175 path_gw_ip_remote
= gw_ip
;
3177 if (eth_s_id
== NULL
) {
3178 memset(&temp
, 0, sizeof(temp
));
3179 path_eth_s_id_remote
= &temp
.esi
;
3181 path_eth_s_id_remote
= eth_s_id
;
3183 if (!memcmp(path_gw_ip
, path_gw_ip_remote
, sizeof(union gw_addr
)))
3186 return !memcmp(path_eth_s_id
, path_eth_s_id_remote
,
3187 sizeof(struct eth_segment_id
));
3190 /* Check if received nexthop is valid or not. */
3191 static int bgp_update_martian_nexthop(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
3192 uint8_t type
, uint8_t stype
,
3193 struct attr
*attr
, struct bgp_node
*rn
)
3197 /* Only validated for unicast and multicast currently. */
3198 /* Also valid for EVPN where the nexthop is an IP address. */
3199 if (safi
!= SAFI_UNICAST
&& safi
!= SAFI_MULTICAST
&& safi
!= SAFI_EVPN
)
3202 /* If NEXT_HOP is present, validate it. */
3203 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
3204 if (attr
->nexthop
.s_addr
== INADDR_ANY
3205 || IPV4_CLASS_DE(ntohl(attr
->nexthop
.s_addr
))
3206 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
, rn
))
3210 /* If MP_NEXTHOP is present, validate it. */
3211 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3212 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3213 * it is not an IPv6 link-local address.
3215 if (attr
->mp_nexthop_len
) {
3216 switch (attr
->mp_nexthop_len
) {
3217 case BGP_ATTR_NHLEN_IPV4
:
3218 case BGP_ATTR_NHLEN_VPNV4
:
3219 ret
= (attr
->mp_nexthop_global_in
.s_addr
== INADDR_ANY
3221 ntohl(attr
->mp_nexthop_global_in
.s_addr
))
3222 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3226 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
3227 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
3228 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
3229 ret
= (IN6_IS_ADDR_UNSPECIFIED(&attr
->mp_nexthop_global
)
3230 || IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
3231 || IN6_IS_ADDR_MULTICAST(
3232 &attr
->mp_nexthop_global
)
3233 || bgp_nexthop_self(bgp
, afi
, type
, stype
,
3246 int bgp_update(struct peer
*peer
, struct prefix
*p
, uint32_t addpath_id
,
3247 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
3248 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
3249 uint32_t num_labels
, int soft_reconfig
,
3250 struct bgp_route_evpn
*evpn
)
3253 int aspath_loop_count
= 0;
3254 struct bgp_node
*rn
;
3256 struct attr new_attr
;
3257 struct attr
*attr_new
;
3258 struct bgp_path_info
*pi
;
3259 struct bgp_path_info
*new;
3260 struct bgp_path_info_extra
*extra
;
3262 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
3264 int do_loop_check
= 1;
3265 int has_valid_label
= 0;
3267 uint8_t pi_type
= 0;
3268 uint8_t pi_sub_type
= 0;
3271 int vnc_implicit_withdraw
= 0;
3275 memset(&new_attr
, 0, sizeof(struct attr
));
3276 new_attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
3277 new_attr
.label
= MPLS_INVALID_LABEL
;
3280 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
3281 /* TODO: Check to see if we can get rid of "is_valid_label" */
3282 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
3283 has_valid_label
= (num_labels
> 0) ? 1 : 0;
3285 has_valid_label
= bgp_is_valid_label(label
);
3287 /* When peer's soft reconfiguration enabled. Record input packet in
3290 && CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
3291 && peer
!= bgp
->peer_self
)
3292 bgp_adj_in_set(rn
, peer
, attr
, addpath_id
);
3294 /* Check previously received route. */
3295 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
3296 if (pi
->peer
== peer
&& pi
->type
== type
3297 && pi
->sub_type
== sub_type
3298 && pi
->addpath_rx_id
== addpath_id
)
3301 /* AS path local-as loop check. */
3302 if (peer
->change_local_as
) {
3303 if (peer
->allowas_in
[afi
][safi
])
3304 aspath_loop_count
= peer
->allowas_in
[afi
][safi
];
3305 else if (!CHECK_FLAG(peer
->flags
,
3306 PEER_FLAG_LOCAL_AS_NO_PREPEND
))
3307 aspath_loop_count
= 1;
3309 if (aspath_loop_check(attr
->aspath
, peer
->change_local_as
)
3310 > aspath_loop_count
) {
3311 peer
->stat_pfx_aspath_loop
++;
3312 reason
= "as-path contains our own AS;";
3317 /* If the peer is configured for "allowas-in origin" and the last ASN in
3319 * as-path is our ASN then we do not need to call aspath_loop_check
3321 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN_ORIGIN
))
3322 if (aspath_get_last_as(attr
->aspath
) == bgp
->as
)
3325 /* AS path loop check. */
3326 if (do_loop_check
) {
3327 if (aspath_loop_check(attr
->aspath
, bgp
->as
)
3328 > peer
->allowas_in
[afi
][safi
]
3329 || (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)
3330 && aspath_loop_check(attr
->aspath
, bgp
->confed_id
)
3331 > peer
->allowas_in
[afi
][safi
])) {
3332 peer
->stat_pfx_aspath_loop
++;
3333 reason
= "as-path contains our own AS;";
3338 /* Route reflector originator ID check. */
3339 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
3340 && IPV4_ADDR_SAME(&bgp
->router_id
, &attr
->originator_id
)) {
3341 peer
->stat_pfx_originator_loop
++;
3342 reason
= "originator is us;";
3346 /* Route reflector cluster ID check. */
3347 if (bgp_cluster_filter(peer
, attr
)) {
3348 peer
->stat_pfx_cluster_loop
++;
3349 reason
= "reflected from the same cluster;";
3353 /* Apply incoming filter. */
3354 if (bgp_input_filter(peer
, p
, attr
, afi
, safi
) == FILTER_DENY
) {
3355 peer
->stat_pfx_filter
++;
3360 /* RFC 8212 to prevent route leaks.
3361 * This specification intends to improve this situation by requiring the
3362 * explicit configuration of both BGP Import and Export Policies for any
3363 * External BGP (EBGP) session such as customers, peers, or
3364 * confederation boundaries for all enabled address families. Through
3365 * codification of the aforementioned requirement, operators will
3366 * benefit from consistent behavior across different BGP
3369 if (peer
->bgp
->ebgp_requires_policy
== DEFAULT_EBGP_POLICY_ENABLED
)
3370 if (!bgp_inbound_policy_exists(peer
,
3371 &peer
->filter
[afi
][safi
])) {
3372 reason
= "inbound policy missing";
3376 /* draft-ietf-idr-deprecate-as-set-confed-set
3377 * Filter routes having AS_SET or AS_CONFED_SET in the path.
3378 * Eventually, This document (if approved) updates RFC 4271
3379 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
3380 * and obsoletes RFC 6472.
3382 if (peer
->bgp
->reject_as_sets
== BGP_REJECT_AS_SETS_ENABLED
)
3383 if (aspath_check_as_sets(attr
->aspath
)) {
3385 "as-path contains AS_SET or AS_CONFED_SET type;";
3391 /* Apply incoming route-map.
3392 * NB: new_attr may now contain newly allocated values from route-map
3394 * commands, so we need bgp_attr_flush in the error paths, until we
3396 * the attr (which takes over the memory references) */
3397 if (bgp_input_modifier(peer
, p
, &new_attr
, afi
, safi
, NULL
,
3398 label
, num_labels
, rn
) == RMAP_DENY
) {
3399 peer
->stat_pfx_filter
++;
3400 reason
= "route-map;";
3401 bgp_attr_flush(&new_attr
);
3405 if (pi
&& pi
->attr
->rmap_table_id
!= new_attr
.rmap_table_id
) {
3406 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
3407 /* remove from RIB previous entry */
3408 bgp_zebra_withdraw(p
, pi
, bgp
, safi
);
3411 if (peer
->sort
== BGP_PEER_EBGP
) {
3413 /* If we receive the graceful-shutdown community from an eBGP
3414 * peer we must lower local-preference */
3415 if (new_attr
.community
3416 && community_include(new_attr
.community
, COMMUNITY_GSHUT
)) {
3417 new_attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
3418 new_attr
.local_pref
= BGP_GSHUT_LOCAL_PREF
;
3420 /* If graceful-shutdown is configured then add the GSHUT
3421 * community to all paths received from eBGP peers */
3422 } else if (CHECK_FLAG(peer
->bgp
->flags
,
3423 BGP_FLAG_GRACEFUL_SHUTDOWN
))
3424 bgp_attr_add_gshut_community(&new_attr
);
3429 pi_sub_type
= pi
->sub_type
;
3432 /* next hop check. */
3433 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
)
3434 && bgp_update_martian_nexthop(bgp
, afi
, safi
, pi_type
,
3435 pi_sub_type
, &new_attr
, rn
)) {
3436 peer
->stat_pfx_nh_invalid
++;
3437 reason
= "martian or self next-hop;";
3438 bgp_attr_flush(&new_attr
);
3442 if (bgp_mac_entry_exists(p
) || bgp_mac_exist(&attr
->rmac
)) {
3443 peer
->stat_pfx_nh_invalid
++;
3444 reason
= "self mac;";
3448 attr_new
= bgp_attr_intern(&new_attr
);
3450 /* If the update is implicit withdraw. */
3452 pi
->uptime
= bgp_clock();
3453 same_attr
= attrhash_cmp(pi
->attr
, attr_new
);
3455 hook_call(bgp_process
, bgp
, afi
, safi
, rn
, peer
, true);
3457 /* Same attribute comes in. */
3458 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
3459 && attrhash_cmp(pi
->attr
, attr_new
)
3460 && (!has_valid_label
3461 || memcmp(&(bgp_path_info_extra_get(pi
))->label
, label
,
3462 num_labels
* sizeof(mpls_label_t
))
3464 && (overlay_index_equal(
3465 afi
, pi
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3466 evpn
== NULL
? NULL
: &evpn
->gw_ip
))) {
3467 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
3468 BGP_CONFIG_DAMPENING
)
3469 && peer
->sort
== BGP_PEER_EBGP
3470 && CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3471 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3472 bgp_debug_rdpfxpath2str(
3473 afi
, safi
, prd
, p
, label
,
3474 num_labels
, addpath_id
? 1 : 0,
3475 addpath_id
, pfx_buf
,
3477 zlog_debug("%s rcvd %s", peer
->host
,
3481 if (bgp_damp_update(pi
, rn
, afi
, safi
)
3482 != BGP_DAMP_SUPPRESSED
) {
3483 bgp_aggregate_increment(bgp
, p
, pi
, afi
,
3485 bgp_process(bgp
, rn
, afi
, safi
);
3487 } else /* Duplicate - odd */
3489 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3490 if (!peer
->rcvd_attr_printed
) {
3492 "%s rcvd UPDATE w/ attr: %s",
3494 peer
->rcvd_attr_str
);
3495 peer
->rcvd_attr_printed
= 1;
3498 bgp_debug_rdpfxpath2str(
3499 afi
, safi
, prd
, p
, label
,
3500 num_labels
, addpath_id
? 1 : 0,
3501 addpath_id
, pfx_buf
,
3504 "%s rcvd %s...duplicate ignored",
3505 peer
->host
, pfx_buf
);
3508 /* graceful restart STALE flag unset. */
3509 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
3510 bgp_path_info_unset_flag(
3511 rn
, pi
, BGP_PATH_STALE
);
3512 bgp_node_set_defer_flag(rn
, false);
3513 bgp_process(bgp
, rn
, afi
, safi
);
3517 bgp_unlock_node(rn
);
3518 bgp_attr_unintern(&attr_new
);
3523 /* Withdraw/Announce before we fully processed the withdraw */
3524 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
3525 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3526 bgp_debug_rdpfxpath2str(
3527 afi
, safi
, prd
, p
, label
, num_labels
,
3528 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3531 "%s rcvd %s, flapped quicker than processing",
3532 peer
->host
, pfx_buf
);
3535 bgp_path_info_restore(rn
, pi
);
3538 /* Received Logging. */
3539 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3540 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
3541 num_labels
, addpath_id
? 1 : 0,
3542 addpath_id
, pfx_buf
,
3544 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3547 /* graceful restart STALE flag unset. */
3548 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
3549 bgp_path_info_unset_flag(rn
, pi
, BGP_PATH_STALE
);
3550 bgp_node_set_defer_flag(rn
, false);
3553 /* The attribute is changed. */
3554 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_ATTR_CHANGED
);
3556 /* implicit withdraw, decrement aggregate and pcount here.
3557 * only if update is accepted, they'll increment below.
3559 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
3561 /* Update bgp route dampening information. */
3562 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3563 && peer
->sort
== BGP_PEER_EBGP
) {
3564 /* This is implicit withdraw so we should update
3567 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
3568 bgp_damp_withdraw(pi
, rn
, afi
, safi
, 1);
3571 if (safi
== SAFI_MPLS_VPN
) {
3572 struct bgp_node
*prn
= NULL
;
3573 struct bgp_table
*table
= NULL
;
3575 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3576 (struct prefix
*)prd
);
3577 if (bgp_node_has_bgp_path_info_data(prn
)) {
3578 table
= bgp_node_get_bgp_table_info(prn
);
3580 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3581 bgp
, prd
, table
, p
, pi
);
3583 bgp_unlock_node(prn
);
3585 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3586 && (safi
== SAFI_UNICAST
)) {
3587 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
3589 * Implicit withdraw case.
3591 ++vnc_implicit_withdraw
;
3592 vnc_import_bgp_del_route(bgp
, p
, pi
);
3593 vnc_import_bgp_exterior_del_route(bgp
, p
, pi
);
3598 /* Special handling for EVPN update of an existing route. If the
3599 * extended community attribute has changed, we need to
3601 * the route using its existing extended community. It will be
3602 * subsequently processed for import with the new extended
3605 if (safi
== SAFI_EVPN
&& !same_attr
) {
3607 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))
3609 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
3612 cmp
= ecommunity_cmp(pi
->attr
->ecommunity
,
3613 attr_new
->ecommunity
);
3615 if (bgp_debug_update(peer
, p
, NULL
, 1))
3617 "Change in EXT-COMM, existing %s new %s",
3619 pi
->attr
->ecommunity
),
3621 attr_new
->ecommunity
));
3622 bgp_evpn_unimport_route(bgp
, afi
, safi
,
3628 /* Update to new attribute. */
3629 bgp_attr_unintern(&pi
->attr
);
3630 pi
->attr
= attr_new
;
3632 /* Update MPLS label */
3633 if (has_valid_label
) {
3634 extra
= bgp_path_info_extra_get(pi
);
3635 if (extra
->label
!= label
) {
3636 memcpy(&extra
->label
, label
,
3637 num_labels
* sizeof(mpls_label_t
));
3638 extra
->num_labels
= num_labels
;
3640 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3641 bgp_set_valid_label(&extra
->label
[0]);
3644 /* Update SRv6 SID */
3645 if (attr
->srv6_l3vpn
) {
3646 extra
= bgp_path_info_extra_get(pi
);
3647 if (sid_diff(&extra
->sid
[0], &attr
->srv6_l3vpn
->sid
)) {
3648 sid_copy(&extra
->sid
[0],
3649 &attr
->srv6_l3vpn
->sid
);
3650 extra
->num_sids
= 1;
3652 } else if (attr
->srv6_vpn
) {
3653 extra
= bgp_path_info_extra_get(pi
);
3654 if (sid_diff(&extra
->sid
[0], &attr
->srv6_vpn
->sid
)) {
3655 sid_copy(&extra
->sid
[0], &attr
->srv6_vpn
->sid
);
3656 extra
->num_sids
= 1;
3661 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3662 && (safi
== SAFI_UNICAST
)) {
3663 if (vnc_implicit_withdraw
) {
3665 * Add back the route with its new attributes
3667 * The route is still selected, until the route
3669 * queued by bgp_process actually runs. We have
3671 * update to the VNC side immediately to avoid
3673 * configuration changes (e.g., route-map
3675 * trigger re-importation of the entire RIB.
3677 vnc_import_bgp_add_route(bgp
, p
, pi
);
3678 vnc_import_bgp_exterior_add_route(bgp
, p
, pi
);
3682 /* Update Overlay Index */
3683 if (afi
== AFI_L2VPN
) {
3684 overlay_index_update(
3685 pi
->attr
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3686 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3689 /* Update bgp route dampening information. */
3690 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3691 && peer
->sort
== BGP_PEER_EBGP
) {
3692 /* Now we do normal update dampening. */
3693 ret
= bgp_damp_update(pi
, rn
, afi
, safi
);
3694 if (ret
== BGP_DAMP_SUPPRESSED
) {
3695 bgp_unlock_node(rn
);
3700 /* Nexthop reachability check - for unicast and
3701 * labeled-unicast.. */
3702 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
3703 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
3704 || (safi
== SAFI_EVPN
&&
3705 bgp_evpn_is_prefix_nht_supported(p
))) {
3706 if (safi
!= SAFI_EVPN
&& peer
->sort
== BGP_PEER_EBGP
3707 && peer
->ttl
== BGP_DEFAULT_TTL
3708 && !CHECK_FLAG(peer
->flags
,
3709 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3710 && !CHECK_FLAG(bgp
->flags
,
3711 BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3716 struct bgp
*bgp_nexthop
= bgp
;
3718 if (pi
->extra
&& pi
->extra
->bgp_orig
)
3719 bgp_nexthop
= pi
->extra
->bgp_orig
;
3721 nh_afi
= BGP_ATTR_NH_AFI(afi
, pi
->attr
);
3723 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
, nh_afi
,
3724 pi
, NULL
, connected
)
3725 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3726 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_VALID
);
3728 if (BGP_DEBUG(nht
, NHT
)) {
3729 char buf1
[INET6_ADDRSTRLEN
];
3731 (const void *)&attr_new
3733 buf1
, INET6_ADDRSTRLEN
);
3734 zlog_debug("%s(%s): NH unresolved",
3735 __FUNCTION__
, buf1
);
3737 bgp_path_info_unset_flag(rn
, pi
,
3741 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_VALID
);
3744 if (safi
== SAFI_MPLS_VPN
) {
3745 struct bgp_node
*prn
= NULL
;
3746 struct bgp_table
*table
= NULL
;
3748 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3749 (struct prefix
*)prd
);
3750 if (bgp_node_has_bgp_path_info_data(prn
)) {
3751 table
= bgp_node_get_bgp_table_info(prn
);
3753 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3754 bgp
, prd
, table
, p
, pi
);
3756 bgp_unlock_node(prn
);
3760 /* If this is an EVPN route and some attribute has changed,
3762 * route for import. If the extended community has changed, we
3764 * have done the un-import earlier and the import would result
3766 * route getting injected into appropriate L2 VNIs. If it is
3768 * some other attribute change, the import will result in
3770 * the attributes for the route in the VNI(s).
3772 if (safi
== SAFI_EVPN
&& !same_attr
&&
3773 CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
3774 bgp_evpn_import_route(bgp
, afi
, safi
, p
, pi
);
3776 /* Process change. */
3777 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
3779 bgp_process(bgp
, rn
, afi
, safi
);
3780 bgp_unlock_node(rn
);
3782 if (SAFI_UNICAST
== safi
3783 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3784 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3786 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, pi
);
3788 if ((SAFI_MPLS_VPN
== safi
)
3789 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3791 vpn_leak_to_vrf_update(bgp
, pi
);
3795 if (SAFI_MPLS_VPN
== safi
) {
3796 mpls_label_t label_decoded
= decode_label(label
);
3798 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3799 type
, sub_type
, &label_decoded
);
3801 if (SAFI_ENCAP
== safi
) {
3802 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3803 type
, sub_type
, NULL
);
3808 } // End of implicit withdraw
3810 /* Received Logging. */
3811 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3812 if (!peer
->rcvd_attr_printed
) {
3813 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3814 peer
->rcvd_attr_str
);
3815 peer
->rcvd_attr_printed
= 1;
3818 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3819 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3821 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3824 /* Make new BGP info. */
3825 new = info_make(type
, sub_type
, 0, peer
, attr_new
, rn
);
3827 /* Update MPLS label */
3828 if (has_valid_label
) {
3829 extra
= bgp_path_info_extra_get(new);
3830 if (extra
->label
!= label
) {
3831 memcpy(&extra
->label
, label
,
3832 num_labels
* sizeof(mpls_label_t
));
3833 extra
->num_labels
= num_labels
;
3835 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3836 bgp_set_valid_label(&extra
->label
[0]);
3839 /* Update SRv6 SID */
3840 if (safi
== SAFI_MPLS_VPN
) {
3841 extra
= bgp_path_info_extra_get(new);
3842 if (attr
->srv6_l3vpn
) {
3843 sid_copy(&extra
->sid
[0], &attr
->srv6_l3vpn
->sid
);
3844 extra
->num_sids
= 1;
3845 } else if (attr
->srv6_vpn
) {
3846 sid_copy(&extra
->sid
[0], &attr
->srv6_vpn
->sid
);
3847 extra
->num_sids
= 1;
3851 /* Update Overlay Index */
3852 if (afi
== AFI_L2VPN
) {
3853 overlay_index_update(new->attr
,
3854 evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3855 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3857 /* Nexthop reachability check. */
3858 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
3859 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
3860 || (safi
== SAFI_EVPN
&& bgp_evpn_is_prefix_nht_supported(p
))) {
3861 if (safi
!= SAFI_EVPN
&& peer
->sort
== BGP_PEER_EBGP
3862 && peer
->ttl
== BGP_DEFAULT_TTL
3863 && !CHECK_FLAG(peer
->flags
,
3864 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3865 && !CHECK_FLAG(bgp
->flags
,
3866 BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3871 nh_afi
= BGP_ATTR_NH_AFI(afi
, new->attr
);
3873 if (bgp_find_or_add_nexthop(bgp
, bgp
, nh_afi
, new, NULL
,
3875 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3876 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
3878 if (BGP_DEBUG(nht
, NHT
)) {
3879 char buf1
[INET6_ADDRSTRLEN
];
3881 (const void *)&attr_new
->nexthop
,
3882 buf1
, INET6_ADDRSTRLEN
);
3883 zlog_debug("%s(%s): NH unresolved",
3884 __FUNCTION__
, buf1
);
3886 bgp_path_info_unset_flag(rn
, new, BGP_PATH_VALID
);
3889 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
3892 new->addpath_rx_id
= addpath_id
;
3894 /* Increment prefix */
3895 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
3897 /* Register new BGP information. */
3898 bgp_path_info_add(rn
, new);
3900 /* route_node_get lock */
3901 bgp_unlock_node(rn
);
3904 if (safi
== SAFI_MPLS_VPN
) {
3905 struct bgp_node
*prn
= NULL
;
3906 struct bgp_table
*table
= NULL
;
3908 prn
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
3909 if (bgp_node_has_bgp_path_info_data(prn
)) {
3910 table
= bgp_node_get_bgp_table_info(prn
);
3912 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3913 bgp
, prd
, table
, p
, new);
3915 bgp_unlock_node(prn
);
3919 /* If maximum prefix count is configured and current prefix
3921 if (bgp_maximum_prefix_overflow(peer
, afi
, safi
, 0))
3924 /* If this is an EVPN route, process for import. */
3925 if (safi
== SAFI_EVPN
&& CHECK_FLAG(new->flags
, BGP_PATH_VALID
))
3926 bgp_evpn_import_route(bgp
, afi
, safi
, p
, new);
3928 hook_call(bgp_process
, bgp
, afi
, safi
, rn
, peer
, false);
3930 /* Process change. */
3931 bgp_process(bgp
, rn
, afi
, safi
);
3933 if (SAFI_UNICAST
== safi
3934 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3935 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3936 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
3938 if ((SAFI_MPLS_VPN
== safi
)
3939 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3941 vpn_leak_to_vrf_update(bgp
, new);
3944 if (SAFI_MPLS_VPN
== safi
) {
3945 mpls_label_t label_decoded
= decode_label(label
);
3947 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3948 sub_type
, &label_decoded
);
3950 if (SAFI_ENCAP
== safi
) {
3951 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3958 /* This BGP update is filtered. Log the reason then update BGP
3961 hook_call(bgp_process
, bgp
, afi
, safi
, rn
, peer
, true);
3963 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3964 if (!peer
->rcvd_attr_printed
) {
3965 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3966 peer
->rcvd_attr_str
);
3967 peer
->rcvd_attr_printed
= 1;
3970 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3971 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3973 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
3974 peer
->host
, pfx_buf
, reason
);
3978 /* If this is an EVPN route, un-import it as it is now filtered.
3980 if (safi
== SAFI_EVPN
)
3981 bgp_evpn_unimport_route(bgp
, afi
, safi
, p
, pi
);
3983 if (SAFI_UNICAST
== safi
3984 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3985 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3987 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
3989 if ((SAFI_MPLS_VPN
== safi
)
3990 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3992 vpn_leak_to_vrf_withdraw(bgp
, pi
);
3995 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
3998 bgp_unlock_node(rn
);
4002 * Filtered update is treated as an implicit withdrawal (see
4004 * a few lines above)
4006 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
4007 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
4015 int bgp_withdraw(struct peer
*peer
, struct prefix
*p
, uint32_t addpath_id
,
4016 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
4017 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
4018 uint32_t num_labels
, struct bgp_route_evpn
*evpn
)
4021 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
4022 struct bgp_node
*rn
;
4023 struct bgp_path_info
*pi
;
4026 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
4027 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
4035 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4037 /* If peer is soft reconfiguration enabled. Record input packet for
4038 * further calculation.
4040 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4041 * routes that are filtered. This tanks out Quagga RS pretty badly due
4043 * the iteration over all RS clients.
4044 * Since we need to remove the entry from adj_in anyway, do that first
4046 * if there was no entry, we don't need to do anything more.
4048 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
4049 && peer
!= bgp
->peer_self
)
4050 if (!bgp_adj_in_unset(rn
, peer
, addpath_id
)) {
4051 peer
->stat_pfx_dup_withdraw
++;
4053 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4054 bgp_debug_rdpfxpath2str(
4055 afi
, safi
, prd
, p
, label
, num_labels
,
4056 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
4059 "%s withdrawing route %s not in adj-in",
4060 peer
->host
, pfx_buf
);
4062 bgp_unlock_node(rn
);
4066 /* Lookup withdrawn route. */
4067 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4068 if (pi
->peer
== peer
&& pi
->type
== type
4069 && pi
->sub_type
== sub_type
4070 && pi
->addpath_rx_id
== addpath_id
)
4074 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4075 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4076 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
4078 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer
->host
,
4082 /* Withdraw specified route from routing table. */
4083 if (pi
&& !CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
4084 bgp_rib_withdraw(rn
, pi
, peer
, afi
, safi
, prd
);
4085 if (SAFI_UNICAST
== safi
4086 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4087 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4088 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
4090 if ((SAFI_MPLS_VPN
== safi
)
4091 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4093 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4095 } else if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4096 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4097 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
4099 zlog_debug("%s Can't find the route %s", peer
->host
, pfx_buf
);
4102 /* Unlock bgp_node_get() lock. */
4103 bgp_unlock_node(rn
);
4108 void bgp_default_originate(struct peer
*peer
, afi_t afi
, safi_t safi
,
4111 struct update_subgroup
*subgrp
;
4112 subgrp
= peer_subgroup(peer
, afi
, safi
);
4113 subgroup_default_originate(subgrp
, withdraw
);
4118 * bgp_stop_announce_route_timer
4120 void bgp_stop_announce_route_timer(struct peer_af
*paf
)
4122 if (!paf
->t_announce_route
)
4125 THREAD_TIMER_OFF(paf
->t_announce_route
);
4129 * bgp_announce_route_timer_expired
4131 * Callback that is invoked when the route announcement timer for a
4134 static int bgp_announce_route_timer_expired(struct thread
*t
)
4136 struct peer_af
*paf
;
4139 paf
= THREAD_ARG(t
);
4142 if (peer
->status
!= Established
)
4145 if (!peer
->afc_nego
[paf
->afi
][paf
->safi
])
4148 peer_af_announce_route(paf
, 1);
4153 * bgp_announce_route
4155 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
4157 void bgp_announce_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4159 struct peer_af
*paf
;
4160 struct update_subgroup
*subgrp
;
4162 paf
= peer_af_find(peer
, afi
, safi
);
4165 subgrp
= PAF_SUBGRP(paf
);
4168 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
4169 * or a refresh has already been triggered.
4171 if (!subgrp
|| paf
->t_announce_route
)
4175 * Start a timer to stagger/delay the announce. This serves
4176 * two purposes - announcement can potentially be combined for
4177 * multiple peers and the announcement doesn't happen in the
4180 thread_add_timer_msec(bm
->master
, bgp_announce_route_timer_expired
, paf
,
4181 (subgrp
->peer_count
== 1)
4182 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
4183 : BGP_ANNOUNCE_ROUTE_DELAY_MS
,
4184 &paf
->t_announce_route
);
4188 * Announce routes from all AF tables to a peer.
4190 * This should ONLY be called when there is a need to refresh the
4191 * routes to the peer based on a policy change for this peer alone
4192 * or a route refresh request received from the peer.
4193 * The operation will result in splitting the peer from its existing
4194 * subgroups and putting it in new subgroups.
4196 void bgp_announce_route_all(struct peer
*peer
)
4201 FOREACH_AFI_SAFI (afi
, safi
)
4202 bgp_announce_route(peer
, afi
, safi
);
4205 static void bgp_soft_reconfig_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
4206 struct bgp_table
*table
,
4207 struct prefix_rd
*prd
)
4210 struct bgp_node
*rn
;
4211 struct bgp_adj_in
*ain
;
4214 table
= peer
->bgp
->rib
[afi
][safi
];
4216 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
4217 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
4218 if (ain
->peer
!= peer
)
4221 struct bgp_path_info
*pi
;
4222 uint32_t num_labels
= 0;
4223 mpls_label_t
*label_pnt
= NULL
;
4224 struct bgp_route_evpn evpn
;
4226 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
;
4228 if (pi
->peer
== peer
)
4231 if (pi
&& pi
->extra
)
4232 num_labels
= pi
->extra
->num_labels
;
4234 label_pnt
= &pi
->extra
->label
[0];
4236 memcpy(&evpn
, &pi
->attr
->evpn_overlay
,
4239 memset(&evpn
, 0, sizeof(evpn
));
4241 ret
= bgp_update(peer
, &rn
->p
, ain
->addpath_rx_id
,
4242 ain
->attr
, afi
, safi
, ZEBRA_ROUTE_BGP
,
4243 BGP_ROUTE_NORMAL
, prd
, label_pnt
,
4244 num_labels
, 1, &evpn
);
4247 bgp_unlock_node(rn
);
4253 void bgp_soft_reconfig_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
4255 struct bgp_node
*rn
;
4256 struct bgp_table
*table
;
4258 if (peer
->status
!= Established
)
4261 if ((safi
!= SAFI_MPLS_VPN
) && (safi
!= SAFI_ENCAP
)
4262 && (safi
!= SAFI_EVPN
))
4263 bgp_soft_reconfig_table(peer
, afi
, safi
, NULL
, NULL
);
4265 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4266 rn
= bgp_route_next(rn
)) {
4267 table
= bgp_node_get_bgp_table_info(rn
);
4268 if (table
!= NULL
) {
4269 struct prefix_rd prd
;
4271 prd
.family
= AF_UNSPEC
;
4273 memcpy(&prd
.val
, rn
->p
.u
.val
, 8);
4275 bgp_soft_reconfig_table(peer
, afi
, safi
, table
,
4282 struct bgp_clear_node_queue
{
4283 struct bgp_node
*rn
;
4286 static wq_item_status
bgp_clear_route_node(struct work_queue
*wq
, void *data
)
4288 struct bgp_clear_node_queue
*cnq
= data
;
4289 struct bgp_node
*rn
= cnq
->rn
;
4290 struct peer
*peer
= wq
->spec
.data
;
4291 struct bgp_path_info
*pi
;
4293 afi_t afi
= bgp_node_table(rn
)->afi
;
4294 safi_t safi
= bgp_node_table(rn
)->safi
;
4299 /* It is possible that we have multiple paths for a prefix from a peer
4300 * if that peer is using AddPath.
4302 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
4303 if (pi
->peer
!= peer
)
4306 /* graceful restart STALE flag set. */
4307 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_NSF_WAIT
)
4308 && peer
->nsf
[afi
][safi
]
4309 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
4310 && !CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
4311 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_STALE
);
4313 /* If this is an EVPN route, process for
4315 if (safi
== SAFI_EVPN
)
4316 bgp_evpn_unimport_route(bgp
, afi
, safi
, &rn
->p
,
4318 /* Handle withdraw for VRF route-leaking and L3VPN */
4319 if (SAFI_UNICAST
== safi
4320 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
||
4321 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4322 vpn_leak_from_vrf_withdraw(bgp_get_default(),
4325 if (SAFI_MPLS_VPN
== safi
&&
4326 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4327 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4330 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
4336 static void bgp_clear_node_queue_del(struct work_queue
*wq
, void *data
)
4338 struct bgp_clear_node_queue
*cnq
= data
;
4339 struct bgp_node
*rn
= cnq
->rn
;
4340 struct bgp_table
*table
= bgp_node_table(rn
);
4342 bgp_unlock_node(rn
);
4343 bgp_table_unlock(table
);
4344 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE
, cnq
);
4347 static void bgp_clear_node_complete(struct work_queue
*wq
)
4349 struct peer
*peer
= wq
->spec
.data
;
4351 /* Tickle FSM to start moving again */
4352 BGP_EVENT_ADD(peer
, Clearing_Completed
);
4354 peer_unlock(peer
); /* bgp_clear_route */
4357 static void bgp_clear_node_queue_init(struct peer
*peer
)
4359 char wname
[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
4361 snprintf(wname
, sizeof(wname
), "clear %s", peer
->host
);
4362 #undef CLEAR_QUEUE_NAME_LEN
4364 peer
->clear_node_queue
= work_queue_new(bm
->master
, wname
);
4365 peer
->clear_node_queue
->spec
.hold
= 10;
4366 peer
->clear_node_queue
->spec
.workfunc
= &bgp_clear_route_node
;
4367 peer
->clear_node_queue
->spec
.del_item_data
= &bgp_clear_node_queue_del
;
4368 peer
->clear_node_queue
->spec
.completion_func
= &bgp_clear_node_complete
;
4369 peer
->clear_node_queue
->spec
.max_retries
= 0;
4371 /* we only 'lock' this peer reference when the queue is actually active
4373 peer
->clear_node_queue
->spec
.data
= peer
;
4376 static void bgp_clear_route_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
4377 struct bgp_table
*table
)
4379 struct bgp_node
*rn
;
4380 int force
= bm
->process_main_queue
? 0 : 1;
4383 table
= peer
->bgp
->rib
[afi
][safi
];
4385 /* If still no table => afi/safi isn't configured at all or smth. */
4389 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
4390 struct bgp_path_info
*pi
, *next
;
4391 struct bgp_adj_in
*ain
;
4392 struct bgp_adj_in
*ain_next
;
4394 /* XXX:TODO: This is suboptimal, every non-empty route_node is
4395 * queued for every clearing peer, regardless of whether it is
4396 * relevant to the peer at hand.
4398 * Overview: There are 3 different indices which need to be
4399 * scrubbed, potentially, when a peer is removed:
4401 * 1 peer's routes visible via the RIB (ie accepted routes)
4402 * 2 peer's routes visible by the (optional) peer's adj-in index
4403 * 3 other routes visible by the peer's adj-out index
4405 * 3 there is no hurry in scrubbing, once the struct peer is
4406 * removed from bgp->peer, we could just GC such deleted peer's
4407 * adj-outs at our leisure.
4409 * 1 and 2 must be 'scrubbed' in some way, at least made
4410 * invisible via RIB index before peer session is allowed to be
4411 * brought back up. So one needs to know when such a 'search' is
4416 * - there'd be a single global queue or a single RIB walker
4417 * - rather than tracking which route_nodes still need to be
4418 * examined on a peer basis, we'd track which peers still
4421 * Given that our per-peer prefix-counts now should be reliable,
4422 * this may actually be achievable. It doesn't seem to be a huge
4423 * problem at this time,
4425 * It is possible that we have multiple paths for a prefix from
4427 * if that peer is using AddPath.
4431 ain_next
= ain
->next
;
4433 if (ain
->peer
== peer
) {
4434 bgp_adj_in_remove(rn
, ain
);
4435 bgp_unlock_node(rn
);
4441 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= next
) {
4443 if (pi
->peer
!= peer
)
4447 bgp_path_info_reap(rn
, pi
);
4449 struct bgp_clear_node_queue
*cnq
;
4451 /* both unlocked in bgp_clear_node_queue_del */
4452 bgp_table_lock(bgp_node_table(rn
));
4455 MTYPE_BGP_CLEAR_NODE_QUEUE
,
4456 sizeof(struct bgp_clear_node_queue
));
4458 work_queue_add(peer
->clear_node_queue
, cnq
);
4466 void bgp_clear_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4468 struct bgp_node
*rn
;
4469 struct bgp_table
*table
;
4471 if (peer
->clear_node_queue
== NULL
)
4472 bgp_clear_node_queue_init(peer
);
4474 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
4475 * Idle until it receives a Clearing_Completed event. This protects
4476 * against peers which flap faster than we can we clear, which could
4479 * a) race with routes from the new session being installed before
4480 * clear_route_node visits the node (to delete the route of that
4482 * b) resource exhaustion, clear_route_node likely leads to an entry
4483 * on the process_main queue. Fast-flapping could cause that queue
4487 /* lock peer in assumption that clear-node-queue will get nodes; if so,
4488 * the unlock will happen upon work-queue completion; other wise, the
4489 * unlock happens at the end of this function.
4491 if (!peer
->clear_node_queue
->thread
)
4494 if (safi
!= SAFI_MPLS_VPN
&& safi
!= SAFI_ENCAP
&& safi
!= SAFI_EVPN
)
4495 bgp_clear_route_table(peer
, afi
, safi
, NULL
);
4497 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4498 rn
= bgp_route_next(rn
)) {
4499 table
= bgp_node_get_bgp_table_info(rn
);
4503 bgp_clear_route_table(peer
, afi
, safi
, table
);
4506 /* unlock if no nodes got added to the clear-node-queue. */
4507 if (!peer
->clear_node_queue
->thread
)
4511 void bgp_clear_route_all(struct peer
*peer
)
4516 FOREACH_AFI_SAFI (afi
, safi
)
4517 bgp_clear_route(peer
, afi
, safi
);
4520 rfapiProcessPeerDown(peer
);
4524 void bgp_clear_adj_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
4526 struct bgp_table
*table
;
4527 struct bgp_node
*rn
;
4528 struct bgp_adj_in
*ain
;
4529 struct bgp_adj_in
*ain_next
;
4531 table
= peer
->bgp
->rib
[afi
][safi
];
4533 /* It is possible that we have multiple paths for a prefix from a peer
4534 * if that peer is using AddPath.
4536 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
4540 ain_next
= ain
->next
;
4542 if (ain
->peer
== peer
) {
4543 bgp_adj_in_remove(rn
, ain
);
4544 bgp_unlock_node(rn
);
4552 void bgp_clear_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4554 struct bgp_node
*rn
;
4555 struct bgp_path_info
*pi
;
4556 struct bgp_table
*table
;
4558 if (safi
== SAFI_MPLS_VPN
) {
4559 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4560 rn
= bgp_route_next(rn
)) {
4561 struct bgp_node
*rm
;
4563 /* look for neighbor in tables */
4564 table
= bgp_node_get_bgp_table_info(rn
);
4568 for (rm
= bgp_table_top(table
); rm
;
4569 rm
= bgp_route_next(rm
))
4570 for (pi
= bgp_node_get_bgp_path_info(rm
); pi
;
4572 if (pi
->peer
!= peer
)
4574 if (!CHECK_FLAG(pi
->flags
,
4578 bgp_rib_remove(rm
, pi
, peer
, afi
, safi
);
4583 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4584 rn
= bgp_route_next(rn
))
4585 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
;
4587 if (pi
->peer
!= peer
)
4589 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
4591 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
4597 int bgp_outbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
4599 if (peer
->sort
== BGP_PEER_IBGP
)
4602 if (peer
->sort
== BGP_PEER_EBGP
4603 && (ROUTE_MAP_OUT_NAME(filter
) || PREFIX_LIST_OUT_NAME(filter
)
4604 || FILTER_LIST_OUT_NAME(filter
)
4605 || DISTRIBUTE_OUT_NAME(filter
)))
4610 int bgp_inbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
4612 if (peer
->sort
== BGP_PEER_IBGP
)
4615 if (peer
->sort
== BGP_PEER_EBGP
4616 && (ROUTE_MAP_IN_NAME(filter
) || PREFIX_LIST_IN_NAME(filter
)
4617 || FILTER_LIST_IN_NAME(filter
)
4618 || DISTRIBUTE_IN_NAME(filter
)))
4623 static void bgp_cleanup_table(struct bgp
*bgp
, struct bgp_table
*table
,
4626 struct bgp_node
*rn
;
4627 struct bgp_path_info
*pi
;
4628 struct bgp_path_info
*next
;
4630 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
4631 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= next
) {
4634 /* Unimport EVPN routes from VRFs */
4635 if (safi
== SAFI_EVPN
)
4636 bgp_evpn_unimport_route(bgp
, AFI_L2VPN
,
4640 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)
4641 && pi
->type
== ZEBRA_ROUTE_BGP
4642 && (pi
->sub_type
== BGP_ROUTE_NORMAL
4643 || pi
->sub_type
== BGP_ROUTE_AGGREGATE
4644 || pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
4646 if (bgp_fibupd_safi(safi
))
4647 bgp_zebra_withdraw(&rn
->p
, pi
, bgp
,
4649 bgp_path_info_reap(rn
, pi
);
4654 /* Delete all kernel routes. */
4655 void bgp_cleanup_routes(struct bgp
*bgp
)
4658 struct bgp_node
*rn
;
4659 struct bgp_table
*table
;
4661 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
4662 if (afi
== AFI_L2VPN
)
4664 bgp_cleanup_table(bgp
, bgp
->rib
[afi
][SAFI_UNICAST
],
4667 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
4669 if (afi
!= AFI_L2VPN
) {
4671 safi
= SAFI_MPLS_VPN
;
4672 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4673 rn
= bgp_route_next(rn
)) {
4674 table
= bgp_node_get_bgp_table_info(rn
);
4675 if (table
!= NULL
) {
4676 bgp_cleanup_table(bgp
, table
, safi
);
4677 bgp_table_finish(&table
);
4678 bgp_node_set_bgp_table_info(rn
, NULL
);
4679 bgp_unlock_node(rn
);
4683 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4684 rn
= bgp_route_next(rn
)) {
4685 table
= bgp_node_get_bgp_table_info(rn
);
4686 if (table
!= NULL
) {
4687 bgp_cleanup_table(bgp
, table
, safi
);
4688 bgp_table_finish(&table
);
4689 bgp_node_set_bgp_table_info(rn
, NULL
);
4690 bgp_unlock_node(rn
);
4695 for (rn
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); rn
;
4696 rn
= bgp_route_next(rn
)) {
4697 table
= bgp_node_get_bgp_table_info(rn
);
4698 if (table
!= NULL
) {
4699 bgp_cleanup_table(bgp
, table
, SAFI_EVPN
);
4700 bgp_table_finish(&table
);
4701 bgp_node_set_bgp_table_info(rn
, NULL
);
4702 bgp_unlock_node(rn
);
4707 void bgp_reset(void)
4710 bgp_zclient_reset();
4711 access_list_reset();
4712 prefix_list_reset();
4715 static int bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
4717 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
4718 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
4719 PEER_CAP_ADDPATH_AF_TX_RCV
));
4722 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
4724 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
4725 struct bgp_nlri
*packet
)
4734 int addpath_encoded
;
4735 uint32_t addpath_id
;
4738 lim
= pnt
+ packet
->length
;
4740 safi
= packet
->safi
;
4742 addpath_encoded
= bgp_addpath_encode_rx(peer
, afi
, safi
);
4744 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
4745 syntactic validity. If the field is syntactically incorrect,
4746 then the Error Subcode is set to Invalid Network Field. */
4747 for (; pnt
< lim
; pnt
+= psize
) {
4748 /* Clear prefix structure. */
4749 memset(&p
, 0, sizeof(struct prefix
));
4751 if (addpath_encoded
) {
4753 /* When packet overflow occurs return immediately. */
4754 if (pnt
+ BGP_ADDPATH_ID_LEN
>= lim
)
4755 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
4757 memcpy(&addpath_id
, pnt
, BGP_ADDPATH_ID_LEN
);
4758 addpath_id
= ntohl(addpath_id
);
4759 pnt
+= BGP_ADDPATH_ID_LEN
;
4762 /* Fetch prefix length. */
4763 p
.prefixlen
= *pnt
++;
4764 /* afi/safi validity already verified by caller,
4765 * bgp_update_receive */
4766 p
.family
= afi2family(afi
);
4768 /* Prefix length check. */
4769 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
4772 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
4773 peer
->host
, p
.prefixlen
, packet
->afi
);
4774 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH
;
4777 /* Packet size overflow check. */
4778 psize
= PSIZE(p
.prefixlen
);
4780 /* When packet overflow occur return immediately. */
4781 if (pnt
+ psize
> lim
) {
4784 "%s [Error] Update packet error (prefix length %d overflows packet)",
4785 peer
->host
, p
.prefixlen
);
4786 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
4789 /* Defensive coding, double-check the psize fits in a struct
4791 if (psize
> (ssize_t
)sizeof(p
.u
)) {
4794 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
4795 peer
->host
, p
.prefixlen
, sizeof(p
.u
));
4796 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
4799 /* Fetch prefix from NLRI packet. */
4800 memcpy(p
.u
.val
, pnt
, psize
);
4802 /* Check address. */
4803 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
4804 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
4805 /* From RFC4271 Section 6.3:
4807 * If a prefix in the NLRI field is semantically
4809 * (e.g., an unexpected multicast IP address),
4811 * be logged locally, and the prefix SHOULD be
4816 "%s: IPv4 unicast NLRI is multicast address %s, ignoring",
4817 peer
->host
, inet_ntoa(p
.u
.prefix4
));
4822 /* Check address. */
4823 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
4824 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4829 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
4831 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4836 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
4841 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
4843 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4850 /* Normal process. */
4852 ret
= bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
4853 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
4854 NULL
, NULL
, 0, 0, NULL
);
4856 ret
= bgp_withdraw(peer
, &p
, addpath_id
, attr
, afi
,
4857 safi
, ZEBRA_ROUTE_BGP
,
4858 BGP_ROUTE_NORMAL
, NULL
, NULL
, 0,
4861 /* Do not send BGP notification twice when maximum-prefix count
4863 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
))
4864 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW
;
4866 /* Address family configuration mismatch. */
4868 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY
;
4871 /* Packet length consistency check. */
4875 "%s [Error] Update packet error (prefix length mismatch with total length)",
4877 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
4880 return BGP_NLRI_PARSE_OK
;
4883 static struct bgp_static
*bgp_static_new(void)
4885 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
4888 static void bgp_static_free(struct bgp_static
*bgp_static
)
4890 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
4891 route_map_counter_decrement(bgp_static
->rmap
.map
);
4893 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
4894 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
4897 void bgp_static_update(struct bgp
*bgp
, struct prefix
*p
,
4898 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
4900 struct bgp_node
*rn
;
4901 struct bgp_path_info
*pi
;
4902 struct bgp_path_info
*new;
4903 struct bgp_path_info rmap_path
;
4905 struct attr
*attr_new
;
4906 route_map_result_t ret
;
4908 int vnc_implicit_withdraw
= 0;
4915 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4917 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4919 attr
.nexthop
= bgp_static
->igpnexthop
;
4920 attr
.med
= bgp_static
->igpmetric
;
4921 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4923 if (bgp_static
->atomic
)
4924 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
4926 /* Store label index, if required. */
4927 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
4928 attr
.label_index
= bgp_static
->label_index
;
4929 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
4932 /* Apply route-map. */
4933 if (bgp_static
->rmap
.name
) {
4934 struct attr attr_tmp
= attr
;
4936 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
4937 rmap_path
.peer
= bgp
->peer_self
;
4938 rmap_path
.attr
= &attr_tmp
;
4940 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4942 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
,
4945 bgp
->peer_self
->rmap_type
= 0;
4947 if (ret
== RMAP_DENYMATCH
) {
4948 /* Free uninterned attribute. */
4949 bgp_attr_flush(&attr_tmp
);
4951 /* Unintern original. */
4952 aspath_unintern(&attr
.aspath
);
4953 bgp_static_withdraw(bgp
, p
, afi
, safi
);
4957 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4958 bgp_attr_add_gshut_community(&attr_tmp
);
4960 attr_new
= bgp_attr_intern(&attr_tmp
);
4963 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4964 bgp_attr_add_gshut_community(&attr
);
4966 attr_new
= bgp_attr_intern(&attr
);
4969 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4970 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4971 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4975 if (attrhash_cmp(pi
->attr
, attr_new
)
4976 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
4977 && !CHECK_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
4978 bgp_unlock_node(rn
);
4979 bgp_attr_unintern(&attr_new
);
4980 aspath_unintern(&attr
.aspath
);
4983 /* The attribute is changed. */
4984 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_ATTR_CHANGED
);
4986 /* Rewrite BGP route information. */
4987 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
4988 bgp_path_info_restore(rn
, pi
);
4990 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4992 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4993 && (safi
== SAFI_UNICAST
)) {
4994 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
4996 * Implicit withdraw case.
4997 * We have to do this before pi is
5000 ++vnc_implicit_withdraw
;
5001 vnc_import_bgp_del_route(bgp
, p
, pi
);
5002 vnc_import_bgp_exterior_del_route(
5007 bgp_attr_unintern(&pi
->attr
);
5008 pi
->attr
= attr_new
;
5009 pi
->uptime
= bgp_clock();
5011 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
5012 && (safi
== SAFI_UNICAST
)) {
5013 if (vnc_implicit_withdraw
) {
5014 vnc_import_bgp_add_route(bgp
, p
, pi
);
5015 vnc_import_bgp_exterior_add_route(
5021 /* Nexthop reachability check. */
5022 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
)
5023 && (safi
== SAFI_UNICAST
5024 || safi
== SAFI_LABELED_UNICAST
)) {
5026 struct bgp
*bgp_nexthop
= bgp
;
5028 if (pi
->extra
&& pi
->extra
->bgp_orig
)
5029 bgp_nexthop
= pi
->extra
->bgp_orig
;
5031 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
,
5033 bgp_path_info_set_flag(rn
, pi
,
5036 if (BGP_DEBUG(nht
, NHT
)) {
5037 char buf1
[INET6_ADDRSTRLEN
];
5038 inet_ntop(p
->family
,
5042 "%s(%s): Route not in table, not advertising",
5043 __FUNCTION__
, buf1
);
5045 bgp_path_info_unset_flag(
5046 rn
, pi
, BGP_PATH_VALID
);
5049 /* Delete the NHT structure if any, if we're
5051 * enabling/disabling import check. We
5052 * deregister the route
5053 * from NHT to avoid overloading NHT and the
5054 * process interaction
5056 bgp_unlink_nexthop(pi
);
5057 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_VALID
);
5059 /* Process change. */
5060 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
5061 bgp_process(bgp
, rn
, afi
, safi
);
5063 if (SAFI_UNICAST
== safi
5064 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
5066 == BGP_INSTANCE_TYPE_DEFAULT
)) {
5067 vpn_leak_from_vrf_update(bgp_get_default(), bgp
,
5071 bgp_unlock_node(rn
);
5072 aspath_unintern(&attr
.aspath
);
5077 /* Make new BGP info. */
5078 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
5080 /* Nexthop reachability check. */
5081 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
)
5082 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
5083 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, new, NULL
, 0))
5084 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
5086 if (BGP_DEBUG(nht
, NHT
)) {
5087 char buf1
[INET6_ADDRSTRLEN
];
5088 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
5091 "%s(%s): Route not in table, not advertising",
5092 __FUNCTION__
, buf1
);
5094 bgp_path_info_unset_flag(rn
, new, BGP_PATH_VALID
);
5097 /* Delete the NHT structure if any, if we're toggling between
5098 * enabling/disabling import check. We deregister the route
5099 * from NHT to avoid overloading NHT and the process interaction
5101 bgp_unlink_nexthop(new);
5103 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
5106 /* Aggregate address increment. */
5107 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
5109 /* Register new BGP information. */
5110 bgp_path_info_add(rn
, new);
5112 /* route_node_get lock */
5113 bgp_unlock_node(rn
);
5115 /* Process change. */
5116 bgp_process(bgp
, rn
, afi
, safi
);
5118 if (SAFI_UNICAST
== safi
5119 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
5120 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
5121 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
5124 /* Unintern original. */
5125 aspath_unintern(&attr
.aspath
);
5128 void bgp_static_withdraw(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
5131 struct bgp_node
*rn
;
5132 struct bgp_path_info
*pi
;
5134 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
5136 /* Check selected route and self inserted route. */
5137 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
5138 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5139 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5142 /* Withdraw static BGP route from routing table. */
5144 if (SAFI_UNICAST
== safi
5145 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
5146 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
5147 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
5149 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
5150 bgp_unlink_nexthop(pi
);
5151 bgp_path_info_delete(rn
, pi
);
5152 bgp_process(bgp
, rn
, afi
, safi
);
5155 /* Unlock bgp_node_lookup. */
5156 bgp_unlock_node(rn
);
5160 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
5162 static void bgp_static_withdraw_safi(struct bgp
*bgp
, struct prefix
*p
,
5163 afi_t afi
, safi_t safi
,
5164 struct prefix_rd
*prd
)
5166 struct bgp_node
*rn
;
5167 struct bgp_path_info
*pi
;
5169 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
5171 /* Check selected route and self inserted route. */
5172 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
5173 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5174 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5177 /* Withdraw static BGP route from routing table. */
5180 rfapiProcessWithdraw(
5181 pi
->peer
, NULL
, p
, prd
, pi
->attr
, afi
, safi
, pi
->type
,
5182 1); /* Kill, since it is an administrative change */
5184 if (SAFI_MPLS_VPN
== safi
5185 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5186 vpn_leak_to_vrf_withdraw(bgp
, pi
);
5188 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
5189 bgp_path_info_delete(rn
, pi
);
5190 bgp_process(bgp
, rn
, afi
, safi
);
5193 /* Unlock bgp_node_lookup. */
5194 bgp_unlock_node(rn
);
5197 static void bgp_static_update_safi(struct bgp
*bgp
, struct prefix
*p
,
5198 struct bgp_static
*bgp_static
, afi_t afi
,
5201 struct bgp_node
*rn
;
5202 struct bgp_path_info
*new;
5203 struct attr
*attr_new
;
5204 struct attr attr
= {0};
5205 struct bgp_path_info
*pi
;
5207 mpls_label_t label
= 0;
5209 uint32_t num_labels
= 0;
5214 if (bgp_static
->label
!= MPLS_INVALID_LABEL
)
5216 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
5219 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
5221 attr
.nexthop
= bgp_static
->igpnexthop
;
5222 attr
.med
= bgp_static
->igpmetric
;
5223 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
5225 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
5226 || (safi
== SAFI_ENCAP
)) {
5227 if (afi
== AFI_IP
) {
5228 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
5229 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
5232 if (afi
== AFI_L2VPN
) {
5233 if (bgp_static
->gatewayIp
.family
== AF_INET
)
5235 bgp_static
->gatewayIp
.u
.prefix4
.s_addr
;
5236 else if (bgp_static
->gatewayIp
.family
== AF_INET6
)
5237 memcpy(&(add
.ipv6
), &(bgp_static
->gatewayIp
.u
.prefix6
),
5238 sizeof(struct in6_addr
));
5239 overlay_index_update(&attr
, bgp_static
->eth_s_id
, &add
);
5240 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
5241 struct bgp_encap_type_vxlan bet
;
5242 memset(&bet
, 0, sizeof(struct bgp_encap_type_vxlan
));
5243 bet
.vnid
= p
->u
.prefix_evpn
.prefix_addr
.eth_tag
;
5244 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
5246 if (bgp_static
->router_mac
) {
5247 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
5250 /* Apply route-map. */
5251 if (bgp_static
->rmap
.name
) {
5252 struct attr attr_tmp
= attr
;
5253 struct bgp_path_info rmap_path
;
5254 route_map_result_t ret
;
5256 rmap_path
.peer
= bgp
->peer_self
;
5257 rmap_path
.attr
= &attr_tmp
;
5259 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
5261 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
,
5264 bgp
->peer_self
->rmap_type
= 0;
5266 if (ret
== RMAP_DENYMATCH
) {
5267 /* Free uninterned attribute. */
5268 bgp_attr_flush(&attr_tmp
);
5270 /* Unintern original. */
5271 aspath_unintern(&attr
.aspath
);
5272 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
5277 attr_new
= bgp_attr_intern(&attr_tmp
);
5279 attr_new
= bgp_attr_intern(&attr
);
5282 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
5283 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5284 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5288 memset(&add
, 0, sizeof(union gw_addr
));
5289 if (attrhash_cmp(pi
->attr
, attr_new
)
5290 && overlay_index_equal(afi
, pi
, bgp_static
->eth_s_id
, &add
)
5291 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
5292 bgp_unlock_node(rn
);
5293 bgp_attr_unintern(&attr_new
);
5294 aspath_unintern(&attr
.aspath
);
5297 /* The attribute is changed. */
5298 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_ATTR_CHANGED
);
5300 /* Rewrite BGP route information. */
5301 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
5302 bgp_path_info_restore(rn
, pi
);
5304 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
5305 bgp_attr_unintern(&pi
->attr
);
5306 pi
->attr
= attr_new
;
5307 pi
->uptime
= bgp_clock();
5310 label
= decode_label(&pi
->extra
->label
[0]);
5313 /* Process change. */
5314 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
5315 bgp_process(bgp
, rn
, afi
, safi
);
5317 if (SAFI_MPLS_VPN
== safi
5318 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5319 vpn_leak_to_vrf_update(bgp
, pi
);
5322 rfapiProcessUpdate(pi
->peer
, NULL
, p
, &bgp_static
->prd
,
5323 pi
->attr
, afi
, safi
, pi
->type
,
5324 pi
->sub_type
, &label
);
5326 bgp_unlock_node(rn
);
5327 aspath_unintern(&attr
.aspath
);
5333 /* Make new BGP info. */
5334 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
5336 SET_FLAG(new->flags
, BGP_PATH_VALID
);
5337 new->extra
= bgp_path_info_extra_new();
5339 new->extra
->label
[0] = bgp_static
->label
;
5340 new->extra
->num_labels
= num_labels
;
5343 label
= decode_label(&bgp_static
->label
);
5346 /* Aggregate address increment. */
5347 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
5349 /* Register new BGP information. */
5350 bgp_path_info_add(rn
, new);
5351 /* route_node_get lock */
5352 bgp_unlock_node(rn
);
5354 /* Process change. */
5355 bgp_process(bgp
, rn
, afi
, safi
);
5357 if (SAFI_MPLS_VPN
== safi
5358 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5359 vpn_leak_to_vrf_update(bgp
, new);
5362 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
5363 safi
, new->type
, new->sub_type
, &label
);
5366 /* Unintern original. */
5367 aspath_unintern(&attr
.aspath
);
5370 /* Configure static BGP network. When user don't run zebra, static
5371 route should be installed as valid. */
5372 static int bgp_static_set(struct vty
*vty
, const char *negate
,
5373 const char *ip_str
, afi_t afi
, safi_t safi
,
5374 const char *rmap
, int backdoor
, uint32_t label_index
)
5376 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5379 struct bgp_static
*bgp_static
;
5380 struct bgp_node
*rn
;
5381 uint8_t need_update
= 0;
5383 /* Convert IP prefix string to struct prefix. */
5384 ret
= str2prefix(ip_str
, &p
);
5386 vty_out(vty
, "%% Malformed prefix\n");
5387 return CMD_WARNING_CONFIG_FAILED
;
5389 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
5390 vty_out(vty
, "%% Malformed prefix (link-local address)\n");
5391 return CMD_WARNING_CONFIG_FAILED
;
5398 /* Set BGP static route configuration. */
5399 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
5402 vty_out(vty
, "%% Can't find static route specified\n");
5403 return CMD_WARNING_CONFIG_FAILED
;
5406 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5408 if ((label_index
!= BGP_INVALID_LABEL_INDEX
)
5409 && (label_index
!= bgp_static
->label_index
)) {
5411 "%% label-index doesn't match static route\n");
5412 return CMD_WARNING_CONFIG_FAILED
;
5415 if ((rmap
&& bgp_static
->rmap
.name
)
5416 && strcmp(rmap
, bgp_static
->rmap
.name
)) {
5418 "%% route-map name doesn't match static route\n");
5419 return CMD_WARNING_CONFIG_FAILED
;
5422 /* Update BGP RIB. */
5423 if (!bgp_static
->backdoor
)
5424 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
5426 /* Clear configuration. */
5427 bgp_static_free(bgp_static
);
5428 bgp_node_set_bgp_static_info(rn
, NULL
);
5429 bgp_unlock_node(rn
);
5430 bgp_unlock_node(rn
);
5433 /* Set BGP static route configuration. */
5434 rn
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
5436 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5438 /* Configuration change. */
5439 /* Label index cannot be changed. */
5440 if (bgp_static
->label_index
!= label_index
) {
5441 vty_out(vty
, "%% cannot change label-index\n");
5442 return CMD_WARNING_CONFIG_FAILED
;
5445 /* Check previous routes are installed into BGP. */
5446 if (bgp_static
->valid
5447 && bgp_static
->backdoor
!= backdoor
)
5450 bgp_static
->backdoor
= backdoor
;
5453 XFREE(MTYPE_ROUTE_MAP_NAME
,
5454 bgp_static
->rmap
.name
);
5455 route_map_counter_decrement(
5456 bgp_static
->rmap
.map
);
5457 bgp_static
->rmap
.name
=
5458 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
5459 bgp_static
->rmap
.map
=
5460 route_map_lookup_by_name(rmap
);
5461 route_map_counter_increment(
5462 bgp_static
->rmap
.map
);
5464 XFREE(MTYPE_ROUTE_MAP_NAME
,
5465 bgp_static
->rmap
.name
);
5466 route_map_counter_decrement(
5467 bgp_static
->rmap
.map
);
5468 bgp_static
->rmap
.map
= NULL
;
5469 bgp_static
->valid
= 0;
5471 bgp_unlock_node(rn
);
5473 /* New configuration. */
5474 bgp_static
= bgp_static_new();
5475 bgp_static
->backdoor
= backdoor
;
5476 bgp_static
->valid
= 0;
5477 bgp_static
->igpmetric
= 0;
5478 bgp_static
->igpnexthop
.s_addr
= INADDR_ANY
;
5479 bgp_static
->label_index
= label_index
;
5482 XFREE(MTYPE_ROUTE_MAP_NAME
,
5483 bgp_static
->rmap
.name
);
5484 route_map_counter_decrement(
5485 bgp_static
->rmap
.map
);
5486 bgp_static
->rmap
.name
=
5487 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
5488 bgp_static
->rmap
.map
=
5489 route_map_lookup_by_name(rmap
);
5490 route_map_counter_increment(
5491 bgp_static
->rmap
.map
);
5493 bgp_node_set_bgp_static_info(rn
, bgp_static
);
5496 bgp_static
->valid
= 1;
5498 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
5500 if (!bgp_static
->backdoor
)
5501 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
5507 void bgp_static_add(struct bgp
*bgp
)
5511 struct bgp_node
*rn
;
5512 struct bgp_node
*rm
;
5513 struct bgp_table
*table
;
5514 struct bgp_static
*bgp_static
;
5516 FOREACH_AFI_SAFI (afi
, safi
)
5517 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5518 rn
= bgp_route_next(rn
)) {
5519 if (!bgp_node_has_bgp_path_info_data(rn
))
5522 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5523 || (safi
== SAFI_EVPN
)) {
5524 table
= bgp_node_get_bgp_table_info(rn
);
5526 for (rm
= bgp_table_top(table
); rm
;
5527 rm
= bgp_route_next(rm
)) {
5529 bgp_node_get_bgp_static_info(
5531 bgp_static_update_safi(bgp
, &rm
->p
,
5538 bgp_node_get_bgp_static_info(rn
), afi
,
5544 /* Called from bgp_delete(). Delete all static routes from the BGP
5546 void bgp_static_delete(struct bgp
*bgp
)
5550 struct bgp_node
*rn
;
5551 struct bgp_node
*rm
;
5552 struct bgp_table
*table
;
5553 struct bgp_static
*bgp_static
;
5555 FOREACH_AFI_SAFI (afi
, safi
)
5556 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5557 rn
= bgp_route_next(rn
)) {
5558 if (!bgp_node_has_bgp_path_info_data(rn
))
5561 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5562 || (safi
== SAFI_EVPN
)) {
5563 table
= bgp_node_get_bgp_table_info(rn
);
5565 for (rm
= bgp_table_top(table
); rm
;
5566 rm
= bgp_route_next(rm
)) {
5568 bgp_node_get_bgp_static_info(
5573 bgp_static_withdraw_safi(
5574 bgp
, &rm
->p
, AFI_IP
, safi
,
5575 (struct prefix_rd
*)&rn
->p
);
5576 bgp_static_free(bgp_static
);
5577 bgp_node_set_bgp_static_info(rn
, NULL
);
5578 bgp_unlock_node(rn
);
5581 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5582 bgp_static_withdraw(bgp
, &rn
->p
, afi
, safi
);
5583 bgp_static_free(bgp_static
);
5584 bgp_node_set_bgp_static_info(rn
, NULL
);
5585 bgp_unlock_node(rn
);
5590 void bgp_static_redo_import_check(struct bgp
*bgp
)
5594 struct bgp_node
*rn
;
5595 struct bgp_node
*rm
;
5596 struct bgp_table
*table
;
5597 struct bgp_static
*bgp_static
;
5599 /* Use this flag to force reprocessing of the route */
5600 SET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5601 FOREACH_AFI_SAFI (afi
, safi
) {
5602 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5603 rn
= bgp_route_next(rn
)) {
5604 if (!bgp_node_has_bgp_path_info_data(rn
))
5607 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5608 || (safi
== SAFI_EVPN
)) {
5609 table
= bgp_node_get_bgp_table_info(rn
);
5611 for (rm
= bgp_table_top(table
); rm
;
5612 rm
= bgp_route_next(rm
)) {
5614 bgp_node_get_bgp_static_info(
5616 bgp_static_update_safi(bgp
, &rm
->p
,
5621 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5622 bgp_static_update(bgp
, &rn
->p
, bgp_static
, afi
,
5627 UNSET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5630 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
5633 struct bgp_table
*table
;
5634 struct bgp_node
*rn
;
5635 struct bgp_path_info
*pi
;
5637 /* Do not install the aggregate route if BGP is in the
5638 * process of termination.
5640 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
5641 || (bgp
->peer_self
== NULL
))
5644 table
= bgp
->rib
[afi
][safi
];
5645 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
5646 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
5647 if (pi
->peer
== bgp
->peer_self
5648 && ((pi
->type
== ZEBRA_ROUTE_BGP
5649 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5650 || (pi
->type
!= ZEBRA_ROUTE_BGP
5652 == BGP_ROUTE_REDISTRIBUTE
))) {
5653 bgp_aggregate_decrement(bgp
, &rn
->p
, pi
, afi
,
5655 bgp_unlink_nexthop(pi
);
5656 bgp_path_info_delete(rn
, pi
);
5657 bgp_process(bgp
, rn
, afi
, safi
);
5664 * Purge all networks and redistributed routes from routing table.
5665 * Invoked upon the instance going down.
5667 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
5672 FOREACH_AFI_SAFI (afi
, safi
)
5673 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
5678 * Currently this is used to set static routes for VPN and ENCAP.
5679 * I think it can probably be factored with bgp_static_set.
5681 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5682 const char *ip_str
, const char *rd_str
,
5683 const char *label_str
, const char *rmap_str
,
5684 int evpn_type
, const char *esi
, const char *gwip
,
5685 const char *ethtag
, const char *routermac
)
5687 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5690 struct prefix_rd prd
;
5691 struct bgp_node
*prn
;
5692 struct bgp_node
*rn
;
5693 struct bgp_table
*table
;
5694 struct bgp_static
*bgp_static
;
5695 mpls_label_t label
= MPLS_INVALID_LABEL
;
5696 struct prefix gw_ip
;
5698 /* validate ip prefix */
5699 ret
= str2prefix(ip_str
, &p
);
5701 vty_out(vty
, "%% Malformed prefix\n");
5702 return CMD_WARNING_CONFIG_FAILED
;
5705 if ((afi
== AFI_L2VPN
)
5706 && (bgp_build_evpn_prefix(evpn_type
,
5707 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5708 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5709 return CMD_WARNING_CONFIG_FAILED
;
5712 ret
= str2prefix_rd(rd_str
, &prd
);
5714 vty_out(vty
, "%% Malformed rd\n");
5715 return CMD_WARNING_CONFIG_FAILED
;
5719 unsigned long label_val
;
5720 label_val
= strtoul(label_str
, NULL
, 10);
5721 encode_label(label_val
, &label
);
5724 if (safi
== SAFI_EVPN
) {
5725 if (esi
&& str2esi(esi
, NULL
) == 0) {
5726 vty_out(vty
, "%% Malformed ESI\n");
5727 return CMD_WARNING_CONFIG_FAILED
;
5729 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
5730 vty_out(vty
, "%% Malformed Router MAC\n");
5731 return CMD_WARNING_CONFIG_FAILED
;
5734 memset(&gw_ip
, 0, sizeof(struct prefix
));
5735 ret
= str2prefix(gwip
, &gw_ip
);
5737 vty_out(vty
, "%% Malformed GatewayIp\n");
5738 return CMD_WARNING_CONFIG_FAILED
;
5740 if ((gw_ip
.family
== AF_INET
5741 && is_evpn_prefix_ipaddr_v6(
5742 (struct prefix_evpn
*)&p
))
5743 || (gw_ip
.family
== AF_INET6
5744 && is_evpn_prefix_ipaddr_v4(
5745 (struct prefix_evpn
*)&p
))) {
5747 "%% GatewayIp family differs with IP prefix\n");
5748 return CMD_WARNING_CONFIG_FAILED
;
5752 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5753 if (!bgp_node_has_bgp_path_info_data(prn
))
5754 bgp_node_set_bgp_table_info(prn
,
5755 bgp_table_init(bgp
, afi
, safi
));
5756 table
= bgp_node_get_bgp_table_info(prn
);
5758 rn
= bgp_node_get(table
, &p
);
5760 if (bgp_node_has_bgp_path_info_data(rn
)) {
5761 vty_out(vty
, "%% Same network configuration exists\n");
5762 bgp_unlock_node(rn
);
5764 /* New configuration. */
5765 bgp_static
= bgp_static_new();
5766 bgp_static
->backdoor
= 0;
5767 bgp_static
->valid
= 0;
5768 bgp_static
->igpmetric
= 0;
5769 bgp_static
->igpnexthop
.s_addr
= INADDR_ANY
;
5770 bgp_static
->label
= label
;
5771 bgp_static
->prd
= prd
;
5774 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
5775 route_map_counter_decrement(bgp_static
->rmap
.map
);
5776 bgp_static
->rmap
.name
=
5777 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
5778 bgp_static
->rmap
.map
=
5779 route_map_lookup_by_name(rmap_str
);
5780 route_map_counter_increment(bgp_static
->rmap
.map
);
5783 if (safi
== SAFI_EVPN
) {
5785 bgp_static
->eth_s_id
=
5787 sizeof(struct eth_segment_id
));
5788 str2esi(esi
, bgp_static
->eth_s_id
);
5791 bgp_static
->router_mac
=
5792 XCALLOC(MTYPE_ATTR
, ETH_ALEN
+ 1);
5793 (void)prefix_str2mac(routermac
,
5794 bgp_static
->router_mac
);
5797 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
5799 bgp_node_set_bgp_static_info(rn
, bgp_static
);
5801 bgp_static
->valid
= 1;
5802 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
5808 /* Configure static BGP network. */
5809 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5810 const char *ip_str
, const char *rd_str
,
5811 const char *label_str
, int evpn_type
, const char *esi
,
5812 const char *gwip
, const char *ethtag
)
5814 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5817 struct prefix_rd prd
;
5818 struct bgp_node
*prn
;
5819 struct bgp_node
*rn
;
5820 struct bgp_table
*table
;
5821 struct bgp_static
*bgp_static
;
5822 mpls_label_t label
= MPLS_INVALID_LABEL
;
5824 /* Convert IP prefix string to struct prefix. */
5825 ret
= str2prefix(ip_str
, &p
);
5827 vty_out(vty
, "%% Malformed prefix\n");
5828 return CMD_WARNING_CONFIG_FAILED
;
5831 if ((afi
== AFI_L2VPN
)
5832 && (bgp_build_evpn_prefix(evpn_type
,
5833 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5834 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5835 return CMD_WARNING_CONFIG_FAILED
;
5837 ret
= str2prefix_rd(rd_str
, &prd
);
5839 vty_out(vty
, "%% Malformed rd\n");
5840 return CMD_WARNING_CONFIG_FAILED
;
5844 unsigned long label_val
;
5845 label_val
= strtoul(label_str
, NULL
, 10);
5846 encode_label(label_val
, &label
);
5849 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5850 if (!bgp_node_has_bgp_path_info_data(prn
))
5851 bgp_node_set_bgp_table_info(prn
,
5852 bgp_table_init(bgp
, afi
, safi
));
5854 bgp_unlock_node(prn
);
5855 table
= bgp_node_get_bgp_table_info(prn
);
5857 rn
= bgp_node_lookup(table
, &p
);
5860 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
5862 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5863 bgp_static_free(bgp_static
);
5864 bgp_node_set_bgp_static_info(rn
, NULL
);
5865 bgp_unlock_node(rn
);
5866 bgp_unlock_node(rn
);
5868 vty_out(vty
, "%% Can't find the route\n");
5873 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
5874 const char *rmap_name
)
5876 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5877 struct bgp_rmap
*rmap
;
5879 rmap
= &bgp
->table_map
[afi
][safi
];
5881 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5882 route_map_counter_decrement(rmap
->map
);
5883 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
5884 rmap
->map
= route_map_lookup_by_name(rmap_name
);
5885 route_map_counter_increment(rmap
->map
);
5887 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5888 route_map_counter_decrement(rmap
->map
);
5892 if (bgp_fibupd_safi(safi
))
5893 bgp_zebra_announce_table(bgp
, afi
, safi
);
5898 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
5899 const char *rmap_name
)
5901 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5902 struct bgp_rmap
*rmap
;
5904 rmap
= &bgp
->table_map
[afi
][safi
];
5905 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5906 route_map_counter_decrement(rmap
->map
);
5909 if (bgp_fibupd_safi(safi
))
5910 bgp_zebra_announce_table(bgp
, afi
, safi
);
5915 void bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
5918 if (bgp
->table_map
[afi
][safi
].name
) {
5919 vty_out(vty
, " table-map %s\n",
5920 bgp
->table_map
[afi
][safi
].name
);
5924 DEFUN (bgp_table_map
,
5927 "BGP table to RIB route download filter\n"
5928 "Name of the route map\n")
5931 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5932 argv
[idx_word
]->arg
);
5934 DEFUN (no_bgp_table_map
,
5935 no_bgp_table_map_cmd
,
5936 "no table-map WORD",
5938 "BGP table to RIB route download filter\n"
5939 "Name of the route map\n")
5942 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5943 argv
[idx_word
]->arg
);
5949 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
5950 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
5951 backdoor$backdoor}]",
5953 "Specify a network to announce via BGP\n"
5958 "Route-map to modify the attributes\n"
5959 "Name of the route map\n"
5960 "Label index to associate with the prefix\n"
5961 "Label index value\n"
5962 "Specify a BGP backdoor route\n")
5964 char addr_prefix_str
[BUFSIZ
];
5969 ret
= netmask_str2prefix_str(address_str
, netmask_str
,
5972 vty_out(vty
, "%% Inconsistent address and mask\n");
5973 return CMD_WARNING_CONFIG_FAILED
;
5977 return bgp_static_set(
5978 vty
, no
, address_str
? addr_prefix_str
: prefix_str
, AFI_IP
,
5979 bgp_node_safi(vty
), map_name
, backdoor
? 1 : 0,
5980 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5983 DEFPY(ipv6_bgp_network
,
5984 ipv6_bgp_network_cmd
,
5985 "[no] network X:X::X:X/M$prefix \
5986 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
5988 "Specify a network to announce via BGP\n"
5990 "Route-map to modify the attributes\n"
5991 "Name of the route map\n"
5992 "Label index to associate with the prefix\n"
5993 "Label index value\n")
5995 return bgp_static_set(
5996 vty
, no
, prefix_str
, AFI_IP6
, bgp_node_safi(vty
), map_name
, 0,
5997 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
6000 static struct bgp_aggregate
*bgp_aggregate_new(void)
6002 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
6005 static void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
6007 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
6008 route_map_counter_decrement(aggregate
->rmap
.map
);
6009 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
6012 static int bgp_aggregate_info_same(struct bgp_path_info
*pi
, uint8_t origin
,
6013 struct aspath
*aspath
,
6014 struct community
*comm
,
6015 struct ecommunity
*ecomm
,
6016 struct lcommunity
*lcomm
)
6018 static struct aspath
*ae
= NULL
;
6021 ae
= aspath_empty();
6026 if (origin
!= pi
->attr
->origin
)
6029 if (!aspath_cmp(pi
->attr
->aspath
, (aspath
) ? aspath
: ae
))
6032 if (!community_cmp(pi
->attr
->community
, comm
))
6035 if (!ecommunity_cmp(pi
->attr
->ecommunity
, ecomm
))
6038 if (!lcommunity_cmp(pi
->attr
->lcommunity
, lcomm
))
6041 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
6047 static void bgp_aggregate_install(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
6048 struct prefix
*p
, uint8_t origin
,
6049 struct aspath
*aspath
,
6050 struct community
*community
,
6051 struct ecommunity
*ecommunity
,
6052 struct lcommunity
*lcommunity
,
6053 uint8_t atomic_aggregate
,
6054 struct bgp_aggregate
*aggregate
)
6056 struct bgp_node
*rn
;
6057 struct bgp_table
*table
;
6058 struct bgp_path_info
*pi
, *orig
, *new;
6061 table
= bgp
->rib
[afi
][safi
];
6063 rn
= bgp_node_get(table
, p
);
6065 for (orig
= pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
6066 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6067 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6070 if (aggregate
->count
> 0) {
6072 * If the aggregate information has not changed
6073 * no need to re-install it again.
6075 if (bgp_aggregate_info_same(orig
, origin
, aspath
, community
,
6076 ecommunity
, lcommunity
)) {
6077 bgp_unlock_node(rn
);
6080 aspath_free(aspath
);
6082 community_free(&community
);
6084 ecommunity_free(&ecommunity
);
6086 lcommunity_free(&lcommunity
);
6092 * Mark the old as unusable
6095 bgp_path_info_delete(rn
, pi
);
6097 attr
= bgp_attr_aggregate_intern(
6098 bgp
, origin
, aspath
, community
, ecommunity
, lcommunity
,
6099 aggregate
, atomic_aggregate
, p
);
6102 bgp_aggregate_delete(bgp
, p
, afi
, safi
, aggregate
);
6106 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0,
6107 bgp
->peer_self
, attr
, rn
);
6109 SET_FLAG(new->flags
, BGP_PATH_VALID
);
6111 bgp_path_info_add(rn
, new);
6112 bgp_process(bgp
, rn
, afi
, safi
);
6114 for (pi
= orig
; pi
; pi
= pi
->next
)
6115 if (pi
->peer
== bgp
->peer_self
6116 && pi
->type
== ZEBRA_ROUTE_BGP
6117 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6120 /* Withdraw static BGP route from routing table. */
6122 bgp_path_info_delete(rn
, pi
);
6123 bgp_process(bgp
, rn
, afi
, safi
);
6127 bgp_unlock_node(rn
);
6130 /* Update an aggregate as routes are added/removed from the BGP table */
6131 void bgp_aggregate_route(struct bgp
*bgp
, struct prefix
*p
,
6132 afi_t afi
, safi_t safi
,
6133 struct bgp_aggregate
*aggregate
)
6135 struct bgp_table
*table
;
6136 struct bgp_node
*top
;
6137 struct bgp_node
*rn
;
6139 struct aspath
*aspath
= NULL
;
6140 struct community
*community
= NULL
;
6141 struct ecommunity
*ecommunity
= NULL
;
6142 struct lcommunity
*lcommunity
= NULL
;
6143 struct bgp_path_info
*pi
;
6144 unsigned long match
= 0;
6145 uint8_t atomic_aggregate
= 0;
6147 /* If the bgp instance is being deleted or self peer is deleted
6148 * then do not create aggregate route
6150 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
6151 || (bgp
->peer_self
== NULL
))
6154 /* ORIGIN attribute: If at least one route among routes that are
6155 aggregated has ORIGIN with the value INCOMPLETE, then the
6156 aggregated route must have the ORIGIN attribute with the value
6157 INCOMPLETE. Otherwise, if at least one route among routes that
6158 are aggregated has ORIGIN with the value EGP, then the aggregated
6159 route must have the origin attribute with the value EGP. In all
6160 other case the value of the ORIGIN attribute of the aggregated
6161 route is INTERNAL. */
6162 origin
= BGP_ORIGIN_IGP
;
6164 table
= bgp
->rib
[afi
][safi
];
6166 top
= bgp_node_get(table
, p
);
6167 for (rn
= bgp_node_get(table
, p
); rn
;
6168 rn
= bgp_route_next_until(rn
, top
)) {
6169 if (rn
->p
.prefixlen
<= p
->prefixlen
)
6174 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
6175 if (BGP_PATH_HOLDDOWN(pi
))
6179 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
6180 atomic_aggregate
= 1;
6182 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6186 * summary-only aggregate route suppress
6187 * aggregated route announcements.
6189 if (aggregate
->summary_only
) {
6190 (bgp_path_info_extra_get(pi
))->suppress
++;
6191 bgp_path_info_set_flag(rn
, pi
,
6192 BGP_PATH_ATTR_CHANGED
);
6199 * If at least one route among routes that are
6200 * aggregated has ORIGIN with the value INCOMPLETE,
6201 * then the aggregated route MUST have the ORIGIN
6202 * attribute with the value INCOMPLETE. Otherwise, if
6203 * at least one route among routes that are aggregated
6204 * has ORIGIN with the value EGP, then the aggregated
6205 * route MUST have the ORIGIN attribute with the value
6208 switch (pi
->attr
->origin
) {
6209 case BGP_ORIGIN_INCOMPLETE
:
6210 aggregate
->incomplete_origin_count
++;
6212 case BGP_ORIGIN_EGP
:
6213 aggregate
->egp_origin_count
++;
6221 if (!aggregate
->as_set
)
6225 * as-set aggregate route generate origin, as path,
6226 * and community aggregation.
6228 /* Compute aggregate route's as-path.
6230 bgp_compute_aggregate_aspath_hash(aggregate
,
6233 /* Compute aggregate route's community.
6235 if (pi
->attr
->community
)
6236 bgp_compute_aggregate_community_hash(
6238 pi
->attr
->community
);
6240 /* Compute aggregate route's extended community.
6242 if (pi
->attr
->ecommunity
)
6243 bgp_compute_aggregate_ecommunity_hash(
6245 pi
->attr
->ecommunity
);
6247 /* Compute aggregate route's large community.
6249 if (pi
->attr
->lcommunity
)
6250 bgp_compute_aggregate_lcommunity_hash(
6252 pi
->attr
->lcommunity
);
6255 bgp_process(bgp
, rn
, afi
, safi
);
6257 if (aggregate
->as_set
) {
6258 bgp_compute_aggregate_aspath_val(aggregate
);
6259 bgp_compute_aggregate_community_val(aggregate
);
6260 bgp_compute_aggregate_ecommunity_val(aggregate
);
6261 bgp_compute_aggregate_lcommunity_val(aggregate
);
6265 bgp_unlock_node(top
);
6268 if (aggregate
->incomplete_origin_count
> 0)
6269 origin
= BGP_ORIGIN_INCOMPLETE
;
6270 else if (aggregate
->egp_origin_count
> 0)
6271 origin
= BGP_ORIGIN_EGP
;
6273 if (aggregate
->as_set
) {
6274 if (aggregate
->aspath
)
6275 /* Retrieve aggregate route's as-path.
6277 aspath
= aspath_dup(aggregate
->aspath
);
6279 if (aggregate
->community
)
6280 /* Retrieve aggregate route's community.
6282 community
= community_dup(aggregate
->community
);
6284 if (aggregate
->ecommunity
)
6285 /* Retrieve aggregate route's ecommunity.
6287 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
6289 if (aggregate
->lcommunity
)
6290 /* Retrieve aggregate route's lcommunity.
6292 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
6295 bgp_aggregate_install(bgp
, afi
, safi
, p
, origin
, aspath
, community
,
6296 ecommunity
, lcommunity
, atomic_aggregate
,
6300 void bgp_aggregate_delete(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
6301 safi_t safi
, struct bgp_aggregate
*aggregate
)
6303 struct bgp_table
*table
;
6304 struct bgp_node
*top
;
6305 struct bgp_node
*rn
;
6306 struct bgp_path_info
*pi
;
6307 unsigned long match
;
6309 table
= bgp
->rib
[afi
][safi
];
6311 /* If routes exists below this node, generate aggregate routes. */
6312 top
= bgp_node_get(table
, p
);
6313 for (rn
= bgp_node_get(table
, p
); rn
;
6314 rn
= bgp_route_next_until(rn
, top
)) {
6315 if (rn
->p
.prefixlen
<= p
->prefixlen
)
6319 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
6320 if (BGP_PATH_HOLDDOWN(pi
))
6323 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6326 if (aggregate
->summary_only
&& pi
->extra
) {
6327 pi
->extra
->suppress
--;
6329 if (pi
->extra
->suppress
== 0) {
6330 bgp_path_info_set_flag(
6331 rn
, pi
, BGP_PATH_ATTR_CHANGED
);
6337 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
6338 aggregate
->incomplete_origin_count
--;
6339 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
6340 aggregate
->egp_origin_count
--;
6342 if (aggregate
->as_set
) {
6343 /* Remove as-path from aggregate.
6345 bgp_remove_aspath_from_aggregate_hash(
6349 if (pi
->attr
->community
)
6350 /* Remove community from aggregate.
6352 bgp_remove_comm_from_aggregate_hash(
6354 pi
->attr
->community
);
6356 if (pi
->attr
->ecommunity
)
6357 /* Remove ecommunity from aggregate.
6359 bgp_remove_ecomm_from_aggregate_hash(
6361 pi
->attr
->ecommunity
);
6363 if (pi
->attr
->lcommunity
)
6364 /* Remove lcommunity from aggregate.
6366 bgp_remove_lcomm_from_aggregate_hash(
6368 pi
->attr
->lcommunity
);
6373 /* If this node was suppressed, process the change. */
6375 bgp_process(bgp
, rn
, afi
, safi
);
6377 if (aggregate
->as_set
) {
6378 aspath_free(aggregate
->aspath
);
6379 aggregate
->aspath
= NULL
;
6380 if (aggregate
->community
)
6381 community_free(&aggregate
->community
);
6382 if (aggregate
->ecommunity
)
6383 ecommunity_free(&aggregate
->ecommunity
);
6384 if (aggregate
->lcommunity
)
6385 lcommunity_free(&aggregate
->lcommunity
);
6388 bgp_unlock_node(top
);
6391 static void bgp_add_route_to_aggregate(struct bgp
*bgp
, struct prefix
*aggr_p
,
6392 struct bgp_path_info
*pinew
, afi_t afi
,
6394 struct bgp_aggregate
*aggregate
)
6397 struct aspath
*aspath
= NULL
;
6398 uint8_t atomic_aggregate
= 0;
6399 struct community
*community
= NULL
;
6400 struct ecommunity
*ecommunity
= NULL
;
6401 struct lcommunity
*lcommunity
= NULL
;
6403 /* ORIGIN attribute: If at least one route among routes that are
6404 * aggregated has ORIGIN with the value INCOMPLETE, then the
6405 * aggregated route must have the ORIGIN attribute with the value
6406 * INCOMPLETE. Otherwise, if at least one route among routes that
6407 * are aggregated has ORIGIN with the value EGP, then the aggregated
6408 * route must have the origin attribute with the value EGP. In all
6409 * other case the value of the ORIGIN attribute of the aggregated
6410 * route is INTERNAL.
6412 origin
= BGP_ORIGIN_IGP
;
6416 if (aggregate
->summary_only
)
6417 (bgp_path_info_extra_get(pinew
))->suppress
++;
6419 switch (pinew
->attr
->origin
) {
6420 case BGP_ORIGIN_INCOMPLETE
:
6421 aggregate
->incomplete_origin_count
++;
6423 case BGP_ORIGIN_EGP
:
6424 aggregate
->egp_origin_count
++;
6432 if (aggregate
->incomplete_origin_count
> 0)
6433 origin
= BGP_ORIGIN_INCOMPLETE
;
6434 else if (aggregate
->egp_origin_count
> 0)
6435 origin
= BGP_ORIGIN_EGP
;
6437 if (aggregate
->as_set
) {
6438 /* Compute aggregate route's as-path.
6440 bgp_compute_aggregate_aspath(aggregate
,
6441 pinew
->attr
->aspath
);
6443 /* Compute aggregate route's community.
6445 if (pinew
->attr
->community
)
6446 bgp_compute_aggregate_community(
6448 pinew
->attr
->community
);
6450 /* Compute aggregate route's extended community.
6452 if (pinew
->attr
->ecommunity
)
6453 bgp_compute_aggregate_ecommunity(
6455 pinew
->attr
->ecommunity
);
6457 /* Compute aggregate route's large community.
6459 if (pinew
->attr
->lcommunity
)
6460 bgp_compute_aggregate_lcommunity(
6462 pinew
->attr
->lcommunity
);
6464 /* Retrieve aggregate route's as-path.
6466 if (aggregate
->aspath
)
6467 aspath
= aspath_dup(aggregate
->aspath
);
6469 /* Retrieve aggregate route's community.
6471 if (aggregate
->community
)
6472 community
= community_dup(aggregate
->community
);
6474 /* Retrieve aggregate route's ecommunity.
6476 if (aggregate
->ecommunity
)
6477 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
6479 /* Retrieve aggregate route's lcommunity.
6481 if (aggregate
->lcommunity
)
6482 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
6485 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
6486 aspath
, community
, ecommunity
,
6487 lcommunity
, atomic_aggregate
, aggregate
);
6490 static void bgp_remove_route_from_aggregate(struct bgp
*bgp
, afi_t afi
,
6492 struct bgp_path_info
*pi
,
6493 struct bgp_aggregate
*aggregate
,
6494 struct prefix
*aggr_p
)
6497 struct aspath
*aspath
= NULL
;
6498 uint8_t atomic_aggregate
= 0;
6499 struct community
*community
= NULL
;
6500 struct ecommunity
*ecommunity
= NULL
;
6501 struct lcommunity
*lcommunity
= NULL
;
6502 unsigned long match
= 0;
6504 if (BGP_PATH_HOLDDOWN(pi
))
6507 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6510 if (aggregate
->summary_only
6512 && pi
->extra
->suppress
> 0) {
6513 pi
->extra
->suppress
--;
6515 if (pi
->extra
->suppress
== 0) {
6516 bgp_path_info_set_flag(pi
->net
, pi
,
6517 BGP_PATH_ATTR_CHANGED
);
6522 if (aggregate
->count
> 0)
6525 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
6526 aggregate
->incomplete_origin_count
--;
6527 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
6528 aggregate
->egp_origin_count
--;
6530 if (aggregate
->as_set
) {
6531 /* Remove as-path from aggregate.
6533 bgp_remove_aspath_from_aggregate(aggregate
,
6536 if (pi
->attr
->community
)
6537 /* Remove community from aggregate.
6539 bgp_remove_community_from_aggregate(
6541 pi
->attr
->community
);
6543 if (pi
->attr
->ecommunity
)
6544 /* Remove ecommunity from aggregate.
6546 bgp_remove_ecommunity_from_aggregate(
6548 pi
->attr
->ecommunity
);
6550 if (pi
->attr
->lcommunity
)
6551 /* Remove lcommunity from aggregate.
6553 bgp_remove_lcommunity_from_aggregate(
6555 pi
->attr
->lcommunity
);
6558 /* If this node was suppressed, process the change. */
6560 bgp_process(bgp
, pi
->net
, afi
, safi
);
6562 origin
= BGP_ORIGIN_IGP
;
6563 if (aggregate
->incomplete_origin_count
> 0)
6564 origin
= BGP_ORIGIN_INCOMPLETE
;
6565 else if (aggregate
->egp_origin_count
> 0)
6566 origin
= BGP_ORIGIN_EGP
;
6568 if (aggregate
->as_set
) {
6569 /* Retrieve aggregate route's as-path.
6571 if (aggregate
->aspath
)
6572 aspath
= aspath_dup(aggregate
->aspath
);
6574 /* Retrieve aggregate route's community.
6576 if (aggregate
->community
)
6577 community
= community_dup(aggregate
->community
);
6579 /* Retrieve aggregate route's ecommunity.
6581 if (aggregate
->ecommunity
)
6582 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
6584 /* Retrieve aggregate route's lcommunity.
6586 if (aggregate
->lcommunity
)
6587 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
6590 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
6591 aspath
, community
, ecommunity
,
6592 lcommunity
, atomic_aggregate
, aggregate
);
6595 void bgp_aggregate_increment(struct bgp
*bgp
, struct prefix
*p
,
6596 struct bgp_path_info
*pi
, afi_t afi
, safi_t safi
)
6598 struct bgp_node
*child
;
6599 struct bgp_node
*rn
;
6600 struct bgp_aggregate
*aggregate
;
6601 struct bgp_table
*table
;
6603 table
= bgp
->aggregate
[afi
][safi
];
6605 /* No aggregates configured. */
6606 if (bgp_table_top_nolock(table
) == NULL
)
6609 if (p
->prefixlen
== 0)
6612 if (BGP_PATH_HOLDDOWN(pi
))
6615 child
= bgp_node_get(table
, p
);
6617 /* Aggregate address configuration check. */
6618 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
)) {
6619 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6620 if (aggregate
!= NULL
&& rn
->p
.prefixlen
< p
->prefixlen
) {
6621 bgp_add_route_to_aggregate(bgp
, &rn
->p
, pi
, afi
,
6625 bgp_unlock_node(child
);
6628 void bgp_aggregate_decrement(struct bgp
*bgp
, struct prefix
*p
,
6629 struct bgp_path_info
*del
, afi_t afi
, safi_t safi
)
6631 struct bgp_node
*child
;
6632 struct bgp_node
*rn
;
6633 struct bgp_aggregate
*aggregate
;
6634 struct bgp_table
*table
;
6636 table
= bgp
->aggregate
[afi
][safi
];
6638 /* No aggregates configured. */
6639 if (bgp_table_top_nolock(table
) == NULL
)
6642 if (p
->prefixlen
== 0)
6645 child
= bgp_node_get(table
, p
);
6647 /* Aggregate address configuration check. */
6648 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
)) {
6649 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6650 if (aggregate
!= NULL
&& rn
->p
.prefixlen
< p
->prefixlen
) {
6651 bgp_remove_route_from_aggregate(bgp
, afi
, safi
,
6652 del
, aggregate
, &rn
->p
);
6655 bgp_unlock_node(child
);
6658 /* Aggregate route attribute. */
6659 #define AGGREGATE_SUMMARY_ONLY 1
6660 #define AGGREGATE_AS_SET 1
6661 #define AGGREGATE_AS_UNSET 0
6663 static int bgp_aggregate_unset(struct vty
*vty
, const char *prefix_str
,
6664 afi_t afi
, safi_t safi
)
6666 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6669 struct bgp_node
*rn
;
6670 struct bgp_aggregate
*aggregate
;
6672 /* Convert string to prefix structure. */
6673 ret
= str2prefix(prefix_str
, &p
);
6675 vty_out(vty
, "Malformed prefix\n");
6676 return CMD_WARNING_CONFIG_FAILED
;
6680 /* Old configuration check. */
6681 rn
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], &p
);
6684 "%% There is no aggregate-address configuration.\n");
6685 return CMD_WARNING_CONFIG_FAILED
;
6688 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6689 bgp_aggregate_delete(bgp
, &p
, afi
, safi
, aggregate
);
6690 bgp_aggregate_install(bgp
, afi
, safi
, &p
, 0, NULL
, NULL
,
6691 NULL
, NULL
, 0, aggregate
);
6693 /* Unlock aggregate address configuration. */
6694 bgp_node_set_bgp_aggregate_info(rn
, NULL
);
6696 if (aggregate
->community
)
6697 community_free(&aggregate
->community
);
6699 if (aggregate
->community_hash
) {
6700 /* Delete all communities in the hash.
6702 hash_clean(aggregate
->community_hash
,
6703 bgp_aggr_community_remove
);
6704 /* Free up the community_hash.
6706 hash_free(aggregate
->community_hash
);
6709 if (aggregate
->ecommunity
)
6710 ecommunity_free(&aggregate
->ecommunity
);
6712 if (aggregate
->ecommunity_hash
) {
6713 /* Delete all ecommunities in the hash.
6715 hash_clean(aggregate
->ecommunity_hash
,
6716 bgp_aggr_ecommunity_remove
);
6717 /* Free up the ecommunity_hash.
6719 hash_free(aggregate
->ecommunity_hash
);
6722 if (aggregate
->lcommunity
)
6723 lcommunity_free(&aggregate
->lcommunity
);
6725 if (aggregate
->lcommunity_hash
) {
6726 /* Delete all lcommunities in the hash.
6728 hash_clean(aggregate
->lcommunity_hash
,
6729 bgp_aggr_lcommunity_remove
);
6730 /* Free up the lcommunity_hash.
6732 hash_free(aggregate
->lcommunity_hash
);
6735 if (aggregate
->aspath
)
6736 aspath_free(aggregate
->aspath
);
6738 if (aggregate
->aspath_hash
) {
6739 /* Delete all as-paths in the hash.
6741 hash_clean(aggregate
->aspath_hash
,
6742 bgp_aggr_aspath_remove
);
6743 /* Free up the aspath_hash.
6745 hash_free(aggregate
->aspath_hash
);
6748 bgp_aggregate_free(aggregate
);
6749 bgp_unlock_node(rn
);
6750 bgp_unlock_node(rn
);
6755 static int bgp_aggregate_set(struct vty
*vty
, const char *prefix_str
, afi_t afi
,
6756 safi_t safi
, const char *rmap
, uint8_t summary_only
,
6759 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6762 struct bgp_node
*rn
;
6763 struct bgp_aggregate
*aggregate
;
6764 uint8_t as_set_new
= as_set
;
6766 /* Convert string to prefix structure. */
6767 ret
= str2prefix(prefix_str
, &p
);
6769 vty_out(vty
, "Malformed prefix\n");
6770 return CMD_WARNING_CONFIG_FAILED
;
6774 if ((afi
== AFI_IP
&& p
.prefixlen
== IPV4_MAX_BITLEN
) ||
6775 (afi
== AFI_IP6
&& p
.prefixlen
== IPV6_MAX_BITLEN
)) {
6776 vty_out(vty
, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
6778 return CMD_WARNING_CONFIG_FAILED
;
6781 /* Old configuration check. */
6782 rn
= bgp_node_get(bgp
->aggregate
[afi
][safi
], &p
);
6783 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6786 vty_out(vty
, "There is already same aggregate network.\n");
6787 /* try to remove the old entry */
6788 ret
= bgp_aggregate_unset(vty
, prefix_str
, afi
, safi
);
6790 vty_out(vty
, "Error deleting aggregate.\n");
6791 bgp_unlock_node(rn
);
6792 return CMD_WARNING_CONFIG_FAILED
;
6796 /* Make aggregate address structure. */
6797 aggregate
= bgp_aggregate_new();
6798 aggregate
->summary_only
= summary_only
;
6800 /* Network operators MUST NOT locally generate any new
6801 * announcements containing AS_SET or AS_CONFED_SET. If they have
6802 * announced routes with AS_SET or AS_CONFED_SET in them, then they
6803 * SHOULD withdraw those routes and re-announce routes for the
6804 * aggregate or component prefixes (i.e., the more-specific routes
6805 * subsumed by the previously aggregated route) without AS_SET
6806 * or AS_CONFED_SET in the updates.
6808 if (bgp
->reject_as_sets
== BGP_REJECT_AS_SETS_ENABLED
) {
6809 if (as_set
== AGGREGATE_AS_SET
) {
6810 as_set_new
= AGGREGATE_AS_UNSET
;
6812 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.\n",
6815 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
6819 aggregate
->as_set
= as_set_new
;
6820 aggregate
->safi
= safi
;
6823 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
6824 route_map_counter_decrement(aggregate
->rmap
.map
);
6825 aggregate
->rmap
.name
=
6826 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
6827 aggregate
->rmap
.map
= route_map_lookup_by_name(rmap
);
6828 route_map_counter_increment(aggregate
->rmap
.map
);
6830 bgp_node_set_bgp_aggregate_info(rn
, aggregate
);
6832 /* Aggregate address insert into BGP routing table. */
6833 bgp_aggregate_route(bgp
, &p
, afi
, safi
, aggregate
);
6838 DEFUN (aggregate_address
,
6839 aggregate_address_cmd
,
6840 "aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
6841 "Configure BGP aggregate entries\n"
6842 "Aggregate prefix\n"
6843 "Generate AS set path information\n"
6844 "Filter more specific routes from updates\n"
6845 "Filter more specific routes from updates\n"
6846 "Generate AS set path information\n"
6847 "Apply route map to aggregate network\n"
6848 "Name of route map\n")
6851 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
6852 char *prefix
= argv
[idx
]->arg
;
6854 int as_set
= argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
6855 : AGGREGATE_AS_UNSET
;
6857 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6858 ? AGGREGATE_SUMMARY_ONLY
6862 argv_find(argv
, argc
, "WORD", &idx
);
6864 rmap
= argv
[idx
]->arg
;
6866 return bgp_aggregate_set(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
),
6867 rmap
, summary_only
, as_set
);
6870 DEFUN (aggregate_address_mask
,
6871 aggregate_address_mask_cmd
,
6872 "aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
6873 "Configure BGP aggregate entries\n"
6874 "Aggregate address\n"
6876 "Generate AS set path information\n"
6877 "Filter more specific routes from updates\n"
6878 "Filter more specific routes from updates\n"
6879 "Generate AS set path information\n"
6880 "Apply route map to aggregate network\n"
6881 "Name of route map\n")
6884 argv_find(argv
, argc
, "A.B.C.D", &idx
);
6885 char *prefix
= argv
[idx
]->arg
;
6886 char *mask
= argv
[idx
+ 1]->arg
;
6889 int as_set
= argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
6890 : AGGREGATE_AS_UNSET
;
6892 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6893 ? AGGREGATE_SUMMARY_ONLY
6896 rmap_found
= argv_find(argv
, argc
, "WORD", &idx
);
6898 rmap
= argv
[idx
]->arg
;
6900 char prefix_str
[BUFSIZ
];
6901 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
6904 vty_out(vty
, "%% Inconsistent address and mask\n");
6905 return CMD_WARNING_CONFIG_FAILED
;
6908 return bgp_aggregate_set(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
),
6909 rmap
, summary_only
, as_set
);
6912 DEFUN (no_aggregate_address
,
6913 no_aggregate_address_cmd
,
6914 "no aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
6916 "Configure BGP aggregate entries\n"
6917 "Aggregate prefix\n"
6918 "Generate AS set path information\n"
6919 "Filter more specific routes from updates\n"
6920 "Filter more specific routes from updates\n"
6921 "Generate AS set path information\n"
6922 "Apply route map to aggregate network\n"
6923 "Name of route map\n")
6926 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
6927 char *prefix
= argv
[idx
]->arg
;
6928 return bgp_aggregate_unset(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
));
6931 DEFUN (no_aggregate_address_mask
,
6932 no_aggregate_address_mask_cmd
,
6933 "no aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
6935 "Configure BGP aggregate entries\n"
6936 "Aggregate address\n"
6938 "Generate AS set path information\n"
6939 "Filter more specific routes from updates\n"
6940 "Filter more specific routes from updates\n"
6941 "Generate AS set path information\n"
6942 "Apply route map to aggregate network\n"
6943 "Name of route map\n")
6946 argv_find(argv
, argc
, "A.B.C.D", &idx
);
6947 char *prefix
= argv
[idx
]->arg
;
6948 char *mask
= argv
[idx
+ 1]->arg
;
6950 char prefix_str
[BUFSIZ
];
6951 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
6954 vty_out(vty
, "%% Inconsistent address and mask\n");
6955 return CMD_WARNING_CONFIG_FAILED
;
6958 return bgp_aggregate_unset(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
));
6961 DEFUN (ipv6_aggregate_address
,
6962 ipv6_aggregate_address_cmd
,
6963 "aggregate-address X:X::X:X/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
6964 "Configure BGP aggregate entries\n"
6965 "Aggregate prefix\n"
6966 "Generate AS set path information\n"
6967 "Filter more specific routes from updates\n"
6968 "Filter more specific routes from updates\n"
6969 "Generate AS set path information\n"
6970 "Apply route map to aggregate network\n"
6971 "Name of route map\n")
6974 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6975 char *prefix
= argv
[idx
]->arg
;
6978 int as_set
= argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
6979 : AGGREGATE_AS_UNSET
;
6982 int sum_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6983 ? AGGREGATE_SUMMARY_ONLY
6986 rmap_found
= argv_find(argv
, argc
, "WORD", &idx
);
6988 rmap
= argv
[idx
]->arg
;
6990 return bgp_aggregate_set(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
, rmap
,
6994 DEFUN (no_ipv6_aggregate_address
,
6995 no_ipv6_aggregate_address_cmd
,
6996 "no aggregate-address X:X::X:X/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
6998 "Configure BGP aggregate entries\n"
6999 "Aggregate prefix\n"
7000 "Generate AS set path information\n"
7001 "Filter more specific routes from updates\n"
7002 "Filter more specific routes from updates\n"
7003 "Generate AS set path information\n"
7004 "Apply route map to aggregate network\n"
7005 "Name of route map\n")
7008 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
7009 char *prefix
= argv
[idx
]->arg
;
7010 return bgp_aggregate_unset(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
);
7013 /* Redistribute route treatment. */
7014 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
7015 const union g_addr
*nexthop
, ifindex_t ifindex
,
7016 enum nexthop_types_t nhtype
, uint32_t metric
,
7017 uint8_t type
, unsigned short instance
,
7020 struct bgp_path_info
*new;
7021 struct bgp_path_info
*bpi
;
7022 struct bgp_path_info rmap_path
;
7023 struct bgp_node
*bn
;
7025 struct attr
*new_attr
;
7027 route_map_result_t ret
;
7028 struct bgp_redist
*red
;
7030 /* Make default attribute. */
7031 bgp_attr_default_set(&attr
, BGP_ORIGIN_INCOMPLETE
);
7033 * This must not be NULL to satisfy Coverity SA
7035 assert(attr
.aspath
);
7038 case NEXTHOP_TYPE_IFINDEX
:
7040 case NEXTHOP_TYPE_IPV4
:
7041 case NEXTHOP_TYPE_IPV4_IFINDEX
:
7042 attr
.nexthop
= nexthop
->ipv4
;
7044 case NEXTHOP_TYPE_IPV6
:
7045 case NEXTHOP_TYPE_IPV6_IFINDEX
:
7046 attr
.mp_nexthop_global
= nexthop
->ipv6
;
7047 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
7049 case NEXTHOP_TYPE_BLACKHOLE
:
7050 switch (p
->family
) {
7052 attr
.nexthop
.s_addr
= INADDR_ANY
;
7055 memset(&attr
.mp_nexthop_global
, 0,
7056 sizeof(attr
.mp_nexthop_global
));
7057 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
7062 attr
.nh_ifindex
= ifindex
;
7065 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
7068 afi
= family2afi(p
->family
);
7070 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
7072 struct attr attr_new
;
7074 /* Copy attribute for modification. */
7077 if (red
->redist_metric_flag
)
7078 attr_new
.med
= red
->redist_metric
;
7080 /* Apply route-map. */
7081 if (red
->rmap
.name
) {
7082 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
7083 rmap_path
.peer
= bgp
->peer_self
;
7084 rmap_path
.attr
= &attr_new
;
7086 SET_FLAG(bgp
->peer_self
->rmap_type
,
7087 PEER_RMAP_TYPE_REDISTRIBUTE
);
7089 ret
= route_map_apply(red
->rmap
.map
, p
, RMAP_BGP
,
7092 bgp
->peer_self
->rmap_type
= 0;
7094 if (ret
== RMAP_DENYMATCH
) {
7095 /* Free uninterned attribute. */
7096 bgp_attr_flush(&attr_new
);
7098 /* Unintern original. */
7099 aspath_unintern(&attr
.aspath
);
7100 bgp_redistribute_delete(bgp
, p
, type
, instance
);
7105 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
7106 bgp_attr_add_gshut_community(&attr_new
);
7108 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
7109 SAFI_UNICAST
, p
, NULL
);
7111 new_attr
= bgp_attr_intern(&attr_new
);
7113 for (bpi
= bgp_node_get_bgp_path_info(bn
); bpi
;
7115 if (bpi
->peer
== bgp
->peer_self
7116 && bpi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
7120 /* Ensure the (source route) type is updated. */
7122 if (attrhash_cmp(bpi
->attr
, new_attr
)
7123 && !CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
)) {
7124 bgp_attr_unintern(&new_attr
);
7125 aspath_unintern(&attr
.aspath
);
7126 bgp_unlock_node(bn
);
7129 /* The attribute is changed. */
7130 bgp_path_info_set_flag(bn
, bpi
,
7131 BGP_PATH_ATTR_CHANGED
);
7133 /* Rewrite BGP route information. */
7134 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
7135 bgp_path_info_restore(bn
, bpi
);
7137 bgp_aggregate_decrement(
7138 bgp
, p
, bpi
, afi
, SAFI_UNICAST
);
7139 bgp_attr_unintern(&bpi
->attr
);
7140 bpi
->attr
= new_attr
;
7141 bpi
->uptime
= bgp_clock();
7143 /* Process change. */
7144 bgp_aggregate_increment(bgp
, p
, bpi
, afi
,
7146 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
7147 bgp_unlock_node(bn
);
7148 aspath_unintern(&attr
.aspath
);
7150 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
7152 == BGP_INSTANCE_TYPE_DEFAULT
)) {
7154 vpn_leak_from_vrf_update(
7155 bgp_get_default(), bgp
, bpi
);
7161 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
7162 bgp
->peer_self
, new_attr
, bn
);
7163 SET_FLAG(new->flags
, BGP_PATH_VALID
);
7165 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
7166 bgp_path_info_add(bn
, new);
7167 bgp_unlock_node(bn
);
7168 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
7170 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
7171 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
7173 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
7177 /* Unintern original. */
7178 aspath_unintern(&attr
.aspath
);
7181 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, uint8_t type
,
7182 unsigned short instance
)
7185 struct bgp_node
*rn
;
7186 struct bgp_path_info
*pi
;
7187 struct bgp_redist
*red
;
7189 afi
= family2afi(p
->family
);
7191 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
7193 rn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
7194 SAFI_UNICAST
, p
, NULL
);
7196 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
7197 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
)
7201 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
7202 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
7204 vpn_leak_from_vrf_withdraw(bgp_get_default(),
7207 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, SAFI_UNICAST
);
7208 bgp_path_info_delete(rn
, pi
);
7209 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
7211 bgp_unlock_node(rn
);
7215 /* Withdraw specified route type's route. */
7216 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
7217 unsigned short instance
)
7219 struct bgp_node
*rn
;
7220 struct bgp_path_info
*pi
;
7221 struct bgp_table
*table
;
7223 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
7225 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
7226 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
7227 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
7228 && pi
->instance
== instance
)
7232 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
7233 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
7235 vpn_leak_from_vrf_withdraw(bgp_get_default(),
7238 bgp_aggregate_decrement(bgp
, &rn
->p
, pi
, afi
,
7240 bgp_path_info_delete(rn
, pi
);
7241 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
7246 /* Static function to display route. */
7247 static void route_vty_out_route(struct prefix
*p
, struct vty
*vty
,
7254 if (p
->family
== AF_INET
) {
7258 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
7261 json_object_string_add(json
, "prefix",
7262 inet_ntop(p
->family
,
7265 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
7266 prefix2str(p
, buf2
, PREFIX_STRLEN
);
7267 json_object_string_add(json
, "network", buf2
);
7269 } else if (p
->family
== AF_ETHERNET
) {
7270 prefix2str(p
, buf
, PREFIX_STRLEN
);
7271 len
= vty_out(vty
, "%s", buf
);
7272 } else if (p
->family
== AF_EVPN
) {
7276 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf
,
7279 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
7280 } else if (p
->family
== AF_FLOWSPEC
) {
7281 route_vty_out_flowspec(vty
, p
, NULL
,
7283 NLRI_STRING_FORMAT_JSON_SIMPLE
:
7284 NLRI_STRING_FORMAT_MIN
, json
);
7289 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
7292 json_object_string_add(json
, "prefix",
7293 inet_ntop(p
->family
,
7296 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
7297 prefix2str(p
, buf2
, PREFIX_STRLEN
);
7298 json_object_string_add(json
, "network", buf2
);
7305 vty_out(vty
, "\n%*s", 20, " ");
7307 vty_out(vty
, "%*s", len
, " ");
7311 enum bgp_display_type
{
7315 /* Print the short form route status for a bgp_path_info */
7316 static void route_vty_short_status_out(struct vty
*vty
,
7317 struct bgp_path_info
*path
,
7318 json_object
*json_path
)
7322 /* Route status display. */
7323 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
7324 json_object_boolean_true_add(json_path
, "removed");
7326 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
7327 json_object_boolean_true_add(json_path
, "stale");
7329 if (path
->extra
&& path
->extra
->suppress
)
7330 json_object_boolean_true_add(json_path
, "suppressed");
7332 if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
7333 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
7334 json_object_boolean_true_add(json_path
, "valid");
7337 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
7338 json_object_boolean_true_add(json_path
, "history");
7340 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
7341 json_object_boolean_true_add(json_path
, "damped");
7343 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
7344 json_object_boolean_true_add(json_path
, "bestpath");
7346 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
7347 json_object_boolean_true_add(json_path
, "multipath");
7349 /* Internal route. */
7350 if ((path
->peer
->as
)
7351 && (path
->peer
->as
== path
->peer
->local_as
))
7352 json_object_string_add(json_path
, "pathFrom",
7355 json_object_string_add(json_path
, "pathFrom",
7361 /* Route status display. */
7362 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
7364 else if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
7366 else if (path
->extra
&& path
->extra
->suppress
)
7368 else if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
7369 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
7375 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
7377 else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
7379 else if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
7381 else if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
7386 /* Internal route. */
7387 if (path
->peer
&& (path
->peer
->as
)
7388 && (path
->peer
->as
== path
->peer
->local_as
))
7394 static char *bgp_nexthop_hostname(struct peer
*peer
, struct attr
*attr
)
7397 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_HOSTNAME
)
7398 && !(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)))
7399 return peer
->hostname
;
7403 /* called from terminal list command */
7404 void route_vty_out(struct vty
*vty
, struct prefix
*p
,
7405 struct bgp_path_info
*path
, int display
, safi_t safi
,
7406 json_object
*json_paths
)
7408 struct attr
*attr
= path
->attr
;
7409 json_object
*json_path
= NULL
;
7410 json_object
*json_nexthops
= NULL
;
7411 json_object
*json_nexthop_global
= NULL
;
7412 json_object
*json_nexthop_ll
= NULL
;
7413 json_object
*json_ext_community
= NULL
;
7414 char vrf_id_str
[VRF_NAMSIZ
] = {0};
7416 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
7417 bool nexthop_othervrf
= false;
7418 vrf_id_t nexthop_vrfid
= VRF_DEFAULT
;
7419 const char *nexthop_vrfname
= VRF_DEFAULT_NAME
;
7420 char *nexthop_hostname
= bgp_nexthop_hostname(path
->peer
, attr
);
7423 json_path
= json_object_new_object();
7425 /* short status lead text */
7426 route_vty_short_status_out(vty
, path
, json_path
);
7429 /* print prefix and mask */
7431 route_vty_out_route(p
, vty
, json_path
);
7433 vty_out(vty
, "%*s", 17, " ");
7435 route_vty_out_route(p
, vty
, json_path
);
7439 * If vrf id of nexthop is different from that of prefix,
7440 * set up printable string to append
7442 if (path
->extra
&& path
->extra
->bgp_orig
) {
7443 const char *self
= "";
7448 nexthop_othervrf
= true;
7449 nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
7451 if (path
->extra
->bgp_orig
->vrf_id
== VRF_UNKNOWN
)
7452 snprintf(vrf_id_str
, sizeof(vrf_id_str
),
7453 "@%s%s", VRFID_NONE_STR
, self
);
7455 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "@%u%s",
7456 path
->extra
->bgp_orig
->vrf_id
, self
);
7458 if (path
->extra
->bgp_orig
->inst_type
7459 != BGP_INSTANCE_TYPE_DEFAULT
)
7461 nexthop_vrfname
= path
->extra
->bgp_orig
->name
;
7463 const char *self
= "";
7468 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "%s", self
);
7472 * For ENCAP and EVPN routes, nexthop address family is not
7473 * neccessarily the same as the prefix address family.
7474 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
7475 * EVPN routes are also exchanged with a MP nexthop. Currently,
7477 * is only IPv4, the value will be present in either
7479 * attr->mp_nexthop_global_in
7481 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
7484 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
7488 sprintf(nexthop
, "%s",
7489 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
7493 sprintf(nexthop
, "%s",
7494 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
7498 sprintf(nexthop
, "?");
7503 json_nexthop_global
= json_object_new_object();
7505 json_object_string_add(json_nexthop_global
, "ip",
7508 if (nexthop_hostname
)
7509 json_object_string_add(json_nexthop_global
,
7513 json_object_string_add(json_nexthop_global
, "afi",
7514 (af
== AF_INET
) ? "ipv4"
7516 json_object_boolean_true_add(json_nexthop_global
,
7519 vty_out(vty
, "%s%s",
7520 nexthop_hostname
? nexthop_hostname
: nexthop
,
7522 } else if (safi
== SAFI_EVPN
) {
7524 json_nexthop_global
= json_object_new_object();
7526 json_object_string_add(json_nexthop_global
, "ip",
7527 inet_ntoa(attr
->nexthop
));
7529 if (nexthop_hostname
)
7530 json_object_string_add(json_nexthop_global
,
7534 json_object_string_add(json_nexthop_global
, "afi",
7536 json_object_boolean_true_add(json_nexthop_global
,
7539 vty_out(vty
, "%-16s%s",
7540 nexthop_hostname
? nexthop_hostname
7541 : inet_ntoa(attr
->nexthop
),
7543 } else if (safi
== SAFI_FLOWSPEC
) {
7544 if (attr
->nexthop
.s_addr
!= INADDR_ANY
) {
7546 json_nexthop_global
= json_object_new_object();
7548 json_object_string_add(json_nexthop_global
,
7550 json_object_string_add(
7551 json_nexthop_global
, "ip",
7552 inet_ntoa(attr
->nexthop
));
7554 if (nexthop_hostname
)
7555 json_object_string_add(
7556 json_nexthop_global
, "hostname",
7559 json_object_boolean_true_add(
7560 json_nexthop_global
,
7563 vty_out(vty
, "%-16s",
7566 : inet_ntoa(attr
->nexthop
));
7569 } else if (p
->family
== AF_INET
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7571 json_nexthop_global
= json_object_new_object();
7573 json_object_string_add(json_nexthop_global
, "ip",
7574 inet_ntoa(attr
->nexthop
));
7576 if (nexthop_hostname
)
7577 json_object_string_add(json_nexthop_global
,
7581 json_object_string_add(json_nexthop_global
, "afi",
7583 json_object_boolean_true_add(json_nexthop_global
,
7588 snprintf(buf
, sizeof(buf
), "%s%s",
7589 nexthop_hostname
? nexthop_hostname
7590 : inet_ntoa(attr
->nexthop
),
7592 vty_out(vty
, "%-16s", buf
);
7597 else if (p
->family
== AF_INET6
|| BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7602 json_nexthop_global
= json_object_new_object();
7603 json_object_string_add(
7604 json_nexthop_global
, "ip",
7605 inet_ntop(AF_INET6
, &attr
->mp_nexthop_global
,
7608 if (nexthop_hostname
)
7609 json_object_string_add(json_nexthop_global
,
7613 json_object_string_add(json_nexthop_global
, "afi",
7615 json_object_string_add(json_nexthop_global
, "scope",
7618 /* We display both LL & GL if both have been
7620 if ((attr
->mp_nexthop_len
7621 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
7622 || (path
->peer
->conf_if
)) {
7623 json_nexthop_ll
= json_object_new_object();
7624 json_object_string_add(
7625 json_nexthop_ll
, "ip",
7627 &attr
->mp_nexthop_local
, buf
,
7630 if (nexthop_hostname
)
7631 json_object_string_add(
7632 json_nexthop_ll
, "hostname",
7635 json_object_string_add(json_nexthop_ll
, "afi",
7637 json_object_string_add(json_nexthop_ll
, "scope",
7640 if ((IPV6_ADDR_CMP(&attr
->mp_nexthop_global
,
7641 &attr
->mp_nexthop_local
)
7643 && !attr
->mp_nexthop_prefer_global
)
7644 json_object_boolean_true_add(
7645 json_nexthop_ll
, "used");
7647 json_object_boolean_true_add(
7648 json_nexthop_global
, "used");
7650 json_object_boolean_true_add(
7651 json_nexthop_global
, "used");
7653 /* Display LL if LL/Global both in table unless
7654 * prefer-global is set */
7655 if (((attr
->mp_nexthop_len
7656 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
7657 && !attr
->mp_nexthop_prefer_global
)
7658 || (path
->peer
->conf_if
)) {
7659 if (path
->peer
->conf_if
) {
7660 len
= vty_out(vty
, "%s",
7661 path
->peer
->conf_if
);
7662 len
= 16 - len
; /* len of IPv6
7668 vty_out(vty
, "\n%*s", 36, " ");
7670 vty_out(vty
, "%*s", len
, " ");
7678 &attr
->mp_nexthop_local
,
7684 vty_out(vty
, "\n%*s", 36, " ");
7686 vty_out(vty
, "%*s", len
, " ");
7695 &attr
->mp_nexthop_global
,
7701 vty_out(vty
, "\n%*s", 36, " ");
7703 vty_out(vty
, "%*s", len
, " ");
7709 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
7713 * Adding "metric" field to match with corresponding
7714 * CLI. "med" will be deprecated in future.
7716 json_object_int_add(json_path
, "med", attr
->med
);
7717 json_object_int_add(json_path
, "metric", attr
->med
);
7719 vty_out(vty
, "%10u", attr
->med
);
7720 else if (!json_paths
)
7724 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
7728 * Adding "locPrf" field to match with corresponding
7729 * CLI. "localPref" will be deprecated in future.
7731 json_object_int_add(json_path
, "localpref",
7733 json_object_int_add(json_path
, "locPrf",
7736 vty_out(vty
, "%7u", attr
->local_pref
);
7737 else if (!json_paths
)
7741 json_object_int_add(json_path
, "weight", attr
->weight
);
7743 vty_out(vty
, "%7u ", attr
->weight
);
7747 json_object_string_add(
7748 json_path
, "peerId",
7749 sockunion2str(&path
->peer
->su
, buf
, SU_ADDRSTRLEN
));
7757 * Adding "path" field to match with corresponding
7758 * CLI. "aspath" will be deprecated in future.
7760 json_object_string_add(json_path
, "aspath",
7762 json_object_string_add(json_path
, "path",
7765 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7770 json_object_string_add(json_path
, "origin",
7771 bgp_origin_long_str
[attr
->origin
]);
7773 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7776 if (safi
== SAFI_EVPN
&&
7777 attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
7778 json_ext_community
= json_object_new_object();
7779 json_object_string_add(json_ext_community
,
7781 attr
->ecommunity
->str
);
7782 json_object_object_add(json_path
,
7783 "extendedCommunity",
7784 json_ext_community
);
7788 json_object_boolean_true_add(json_path
,
7789 "announceNexthopSelf");
7790 if (nexthop_othervrf
) {
7791 json_object_string_add(json_path
, "nhVrfName",
7794 json_object_int_add(json_path
, "nhVrfId",
7795 ((nexthop_vrfid
== VRF_UNKNOWN
)
7797 : (int)nexthop_vrfid
));
7802 if (json_nexthop_global
|| json_nexthop_ll
) {
7803 json_nexthops
= json_object_new_array();
7805 if (json_nexthop_global
)
7806 json_object_array_add(json_nexthops
,
7807 json_nexthop_global
);
7809 if (json_nexthop_ll
)
7810 json_object_array_add(json_nexthops
,
7813 json_object_object_add(json_path
, "nexthops",
7817 json_object_array_add(json_paths
, json_path
);
7821 if (safi
== SAFI_EVPN
&&
7822 attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
7823 vty_out(vty
, "%*s", 20, " ");
7824 vty_out(vty
, "%s\n", attr
->ecommunity
->str
);
7828 /* prints an additional line, indented, with VNC info, if
7830 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
7831 rfapi_vty_out_vncinfo(vty
, p
, path
, safi
);
7836 /* called from terminal list command */
7837 void route_vty_out_tmp(struct vty
*vty
, struct prefix
*p
, struct attr
*attr
,
7838 safi_t safi
, bool use_json
, json_object
*json_ar
)
7840 json_object
*json_status
= NULL
;
7841 json_object
*json_net
= NULL
;
7844 /* Route status display. */
7846 json_status
= json_object_new_object();
7847 json_net
= json_object_new_object();
7854 /* print prefix and mask */
7856 if (safi
== SAFI_EVPN
)
7857 bgp_evpn_route2json((struct prefix_evpn
*)p
, json_net
);
7858 else if (p
->family
== AF_INET
|| p
->family
== AF_INET6
) {
7859 json_object_string_add(
7860 json_net
, "addrPrefix",
7861 inet_ntop(p
->family
, &p
->u
.prefix
, buff
,
7863 json_object_int_add(json_net
, "prefixLen",
7865 prefix2str(p
, buff
, PREFIX_STRLEN
);
7866 json_object_string_add(json_net
, "network", buff
);
7869 route_vty_out_route(p
, vty
, NULL
);
7871 /* Print attribute */
7874 if (p
->family
== AF_INET
7875 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7876 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7877 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
7878 json_object_string_add(
7879 json_net
, "nextHop",
7881 attr
->mp_nexthop_global_in
));
7883 json_object_string_add(
7884 json_net
, "nextHop",
7885 inet_ntoa(attr
->nexthop
));
7886 } else if (p
->family
== AF_INET6
7887 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7890 json_object_string_add(
7891 json_net
, "nextHopGlobal",
7893 &attr
->mp_nexthop_global
, buf
,
7895 } else if (p
->family
== AF_EVPN
&&
7896 !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
7897 json_object_string_add(json_net
,
7898 "nextHop", inet_ntoa(
7899 attr
->mp_nexthop_global_in
));
7902 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
7903 json_object_int_add(json_net
, "metric",
7906 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
7909 * Adding "locPrf" field to match with
7910 * corresponding CLI. "localPref" will be
7911 * deprecated in future.
7913 json_object_int_add(json_net
, "localPref",
7915 json_object_int_add(json_net
, "locPrf",
7919 json_object_int_add(json_net
, "weight", attr
->weight
);
7925 * Adding "path" field to match with
7926 * corresponding CLI. "localPref" will be
7927 * deprecated in future.
7929 json_object_string_add(json_net
, "asPath",
7931 json_object_string_add(json_net
, "path",
7936 json_object_string_add(json_net
, "bgpOriginCode",
7937 bgp_origin_str
[attr
->origin
]);
7939 if (p
->family
== AF_INET
7940 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7941 || safi
== SAFI_EVPN
7942 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7943 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7944 || safi
== SAFI_EVPN
)
7945 vty_out(vty
, "%-16s",
7947 attr
->mp_nexthop_global_in
));
7949 vty_out(vty
, "%-16s",
7950 inet_ntoa(attr
->nexthop
));
7951 } else if (p
->family
== AF_INET6
7952 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7959 &attr
->mp_nexthop_global
, buf
,
7963 vty_out(vty
, "\n%*s", 36, " ");
7965 vty_out(vty
, "%*s", len
, " ");
7968 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
7969 vty_out(vty
, "%10u", attr
->med
);
7973 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
7974 vty_out(vty
, "%7u", attr
->local_pref
);
7978 vty_out(vty
, "%7u ", attr
->weight
);
7982 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7985 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7989 json_object_boolean_true_add(json_status
, "*");
7990 json_object_boolean_true_add(json_status
, ">");
7991 json_object_object_add(json_net
, "appliedStatusSymbols",
7994 prefix2str(p
, buff
, PREFIX_STRLEN
);
7995 json_object_object_add(json_ar
, buff
, json_net
);
8000 void route_vty_out_tag(struct vty
*vty
, struct prefix
*p
,
8001 struct bgp_path_info
*path
, int display
, safi_t safi
,
8004 json_object
*json_out
= NULL
;
8006 mpls_label_t label
= MPLS_INVALID_LABEL
;
8012 json_out
= json_object_new_object();
8014 /* short status lead text */
8015 route_vty_short_status_out(vty
, path
, json_out
);
8017 /* print prefix and mask */
8020 route_vty_out_route(p
, vty
, NULL
);
8022 vty_out(vty
, "%*s", 17, " ");
8025 /* Print attribute */
8027 if (((p
->family
== AF_INET
)
8028 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
8029 || (safi
== SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
8030 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
8031 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
8032 || safi
== SAFI_EVPN
) {
8034 json_object_string_add(
8035 json_out
, "mpNexthopGlobalIn",
8036 inet_ntoa(attr
->mp_nexthop_global_in
));
8038 vty_out(vty
, "%-16s",
8039 inet_ntoa(attr
->mp_nexthop_global_in
));
8042 json_object_string_add(
8043 json_out
, "nexthop",
8044 inet_ntoa(attr
->nexthop
));
8046 vty_out(vty
, "%-16s", inet_ntoa(attr
->nexthop
));
8048 } else if (((p
->family
== AF_INET6
)
8049 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
8050 || (safi
== SAFI_EVPN
&& BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
8051 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
8054 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
8056 json_object_string_add(
8057 json_out
, "mpNexthopGlobalIn",
8059 &attr
->mp_nexthop_global
,
8060 buf_a
, sizeof(buf_a
)));
8064 &attr
->mp_nexthop_global
,
8065 buf_a
, sizeof(buf_a
)));
8066 } else if (attr
->mp_nexthop_len
8067 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
8068 snprintfrr(buf_a
, sizeof(buf_a
), "%pI6(%pI6)",
8069 &attr
->mp_nexthop_global
,
8070 &attr
->mp_nexthop_local
);
8072 json_object_string_add(json_out
,
8073 "mpNexthopGlobalLocal",
8076 vty_out(vty
, "%s", buf_a
);
8080 label
= decode_label(&path
->extra
->label
[0]);
8082 if (bgp_is_valid_label(&label
)) {
8084 json_object_int_add(json_out
, "notag", label
);
8085 json_object_array_add(json
, json_out
);
8087 vty_out(vty
, "notag/%d", label
);
8093 void route_vty_out_overlay(struct vty
*vty
, struct prefix
*p
,
8094 struct bgp_path_info
*path
, int display
,
8095 json_object
*json_paths
)
8098 char buf
[BUFSIZ
] = {0};
8099 json_object
*json_path
= NULL
;
8100 json_object
*json_nexthop
= NULL
;
8101 json_object
*json_overlay
= NULL
;
8107 json_path
= json_object_new_object();
8108 json_overlay
= json_object_new_object();
8109 json_nexthop
= json_object_new_object();
8112 /* short status lead text */
8113 route_vty_short_status_out(vty
, path
, json_path
);
8115 /* print prefix and mask */
8117 route_vty_out_route(p
, vty
, json_path
);
8119 vty_out(vty
, "%*s", 17, " ");
8121 /* Print attribute */
8124 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
8128 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
, BUFSIZ
);
8130 vty_out(vty
, "%-16s", buf
);
8132 json_object_string_add(json_nexthop
, "ip", buf
);
8134 json_object_string_add(json_nexthop
, "afi", "ipv4");
8136 json_object_object_add(json_path
, "nexthop",
8141 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
, BUFSIZ
);
8142 inet_ntop(af
, &attr
->mp_nexthop_local
, buf1
, BUFSIZ
);
8144 vty_out(vty
, "%s(%s)", buf
, buf1
);
8146 json_object_string_add(json_nexthop
, "ipv6Global", buf
);
8148 json_object_string_add(json_nexthop
, "ipv6LinkLocal",
8151 json_object_string_add(json_nexthop
, "afi", "ipv6");
8153 json_object_object_add(json_path
, "nexthop",
8161 json_object_string_add(json_nexthop
, "Error",
8162 "Unsupported address-family");
8166 char *str
= esi2str(&(attr
->evpn_overlay
.eth_s_id
));
8169 vty_out(vty
, "%s", str
);
8171 json_object_string_add(json_overlay
, "esi", str
);
8173 XFREE(MTYPE_TMP
, str
);
8175 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn
*)p
)) {
8176 inet_ntop(AF_INET
, &(attr
->evpn_overlay
.gw_ip
.ipv4
), buf
,
8178 } else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn
*)p
)) {
8179 inet_ntop(AF_INET6
, &(attr
->evpn_overlay
.gw_ip
.ipv6
), buf
,
8184 vty_out(vty
, "/%s", buf
);
8186 json_object_string_add(json_overlay
, "gw", buf
);
8188 if (attr
->ecommunity
) {
8190 struct ecommunity_val
*routermac
= ecommunity_lookup(
8191 attr
->ecommunity
, ECOMMUNITY_ENCODE_EVPN
,
8192 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
8195 mac
= ecom_mac2str((char *)routermac
->val
);
8198 vty_out(vty
, "/%s", (char *)mac
);
8200 json_object_string_add(json_overlay
, "rmac",
8203 XFREE(MTYPE_TMP
, mac
);
8210 json_object_object_add(json_path
, "overlay", json_overlay
);
8212 json_object_array_add(json_paths
, json_path
);
8216 /* dampening route */
8217 static void damp_route_vty_out(struct vty
*vty
, struct prefix
*p
,
8218 struct bgp_path_info
*path
, int display
, afi_t afi
,
8219 safi_t safi
, bool use_json
, json_object
*json
)
8223 char timebuf
[BGP_UPTIME_LEN
];
8225 /* short status lead text */
8226 route_vty_short_status_out(vty
, path
, json
);
8228 /* print prefix and mask */
8231 route_vty_out_route(p
, vty
, NULL
);
8233 vty_out(vty
, "%*s", 17, " ");
8236 len
= vty_out(vty
, "%s", path
->peer
->host
);
8240 vty_out(vty
, "\n%*s", 34, " ");
8243 json_object_int_add(json
, "peerHost", len
);
8245 vty_out(vty
, "%*s", len
, " ");
8249 bgp_damp_reuse_time_vty(vty
, path
, timebuf
, BGP_UPTIME_LEN
, afi
,
8250 safi
, use_json
, json
);
8253 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
8254 BGP_UPTIME_LEN
, afi
, safi
,
8257 /* Print attribute */
8263 json_object_string_add(json
, "asPath",
8266 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
8271 json_object_string_add(json
, "origin",
8272 bgp_origin_str
[attr
->origin
]);
8274 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
8281 static void flap_route_vty_out(struct vty
*vty
, struct prefix
*p
,
8282 struct bgp_path_info
*path
, int display
, afi_t afi
,
8283 safi_t safi
, bool use_json
, json_object
*json
)
8286 struct bgp_damp_info
*bdi
;
8287 char timebuf
[BGP_UPTIME_LEN
];
8293 bdi
= path
->extra
->damp_info
;
8295 /* short status lead text */
8296 route_vty_short_status_out(vty
, path
, json
);
8298 /* print prefix and mask */
8301 route_vty_out_route(p
, vty
, NULL
);
8303 vty_out(vty
, "%*s", 17, " ");
8306 len
= vty_out(vty
, "%s", path
->peer
->host
);
8310 vty_out(vty
, "\n%*s", 33, " ");
8313 json_object_int_add(json
, "peerHost", len
);
8315 vty_out(vty
, "%*s", len
, " ");
8318 len
= vty_out(vty
, "%d", bdi
->flap
);
8325 json_object_int_add(json
, "bdiFlap", len
);
8327 vty_out(vty
, "%*s", len
, " ");
8331 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
8334 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
8335 BGP_UPTIME_LEN
, 0, NULL
));
8337 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
8338 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
8340 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
8341 BGP_UPTIME_LEN
, afi
, safi
,
8345 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
8346 BGP_UPTIME_LEN
, afi
,
8347 safi
, use_json
, json
));
8350 vty_out(vty
, "%*s ", 8, " ");
8353 /* Print attribute */
8359 json_object_string_add(json
, "asPath",
8362 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
8367 json_object_string_add(json
, "origin",
8368 bgp_origin_str
[attr
->origin
]);
8370 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
8376 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
8377 int *first
, const char *header
,
8378 json_object
*json_adv_to
)
8380 char buf1
[INET6_ADDRSTRLEN
];
8381 json_object
*json_peer
= NULL
;
8384 /* 'advertised-to' is a dictionary of peers we have advertised
8386 * prefix too. The key is the peer's IP or swpX, the value is
8388 * hostname if we know it and "" if not.
8390 json_peer
= json_object_new_object();
8393 json_object_string_add(json_peer
, "hostname",
8397 json_object_object_add(json_adv_to
, peer
->conf_if
,
8400 json_object_object_add(
8402 sockunion2str(&peer
->su
, buf1
, SU_ADDRSTRLEN
),
8406 vty_out(vty
, "%s", header
);
8411 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_HOSTNAME
)) {
8413 vty_out(vty
, " %s(%s)", peer
->hostname
,
8416 vty_out(vty
, " %s(%s)", peer
->hostname
,
8417 sockunion2str(&peer
->su
, buf1
,
8421 vty_out(vty
, " %s", peer
->conf_if
);
8424 sockunion2str(&peer
->su
, buf1
,
8430 static void route_vty_out_tx_ids(struct vty
*vty
,
8431 struct bgp_addpath_info_data
*d
)
8435 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
8436 vty_out(vty
, "TX-%s %u%s", bgp_addpath_names(i
)->human_name
,
8437 d
->addpath_tx_id
[i
],
8438 i
< BGP_ADDPATH_MAX
- 1 ? " " : "\n");
8442 static const char *bgp_path_selection_reason2str(
8443 enum bgp_path_selection_reason reason
)
8446 case bgp_path_selection_none
:
8447 return "Nothing to Select";
8448 case bgp_path_selection_first
:
8449 return "First path received";
8450 case bgp_path_selection_evpn_sticky_mac
:
8451 return "EVPN Sticky Mac";
8452 case bgp_path_selection_evpn_seq
:
8453 return "EVPN sequence number";
8454 case bgp_path_selection_evpn_lower_ip
:
8455 return "EVPN lower IP";
8456 case bgp_path_selection_weight
:
8458 case bgp_path_selection_local_pref
:
8459 return "Local Pref";
8460 case bgp_path_selection_local_route
:
8461 return "Local Route";
8462 case bgp_path_selection_confed_as_path
:
8463 return "Confederation based AS Path";
8464 case bgp_path_selection_as_path
:
8466 case bgp_path_selection_origin
:
8468 case bgp_path_selection_med
:
8470 case bgp_path_selection_peer
:
8472 case bgp_path_selection_confed
:
8473 return "Confed Peer Type";
8474 case bgp_path_selection_igp_metric
:
8475 return "IGP Metric";
8476 case bgp_path_selection_older
:
8477 return "Older Path";
8478 case bgp_path_selection_router_id
:
8480 case bgp_path_selection_cluster_length
:
8481 return "Cluser length";
8482 case bgp_path_selection_stale
:
8483 return "Path Staleness";
8484 case bgp_path_selection_local_configured
:
8485 return "Locally configured route";
8486 case bgp_path_selection_neighbor_ip
:
8487 return "Neighbor IP";
8488 case bgp_path_selection_default
:
8489 return "Nothing left to compare";
8491 return "Invalid (internal error)";
8494 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
,
8495 struct bgp_node
*bn
, struct bgp_path_info
*path
,
8496 afi_t afi
, safi_t safi
, json_object
*json_paths
)
8498 char buf
[INET6_ADDRSTRLEN
];
8500 char buf2
[EVPN_ROUTE_STRLEN
];
8501 struct attr
*attr
= path
->attr
;
8502 int sockunion_vty_out(struct vty
*, union sockunion
*);
8504 json_object
*json_bestpath
= NULL
;
8505 json_object
*json_cluster_list
= NULL
;
8506 json_object
*json_cluster_list_list
= NULL
;
8507 json_object
*json_ext_community
= NULL
;
8508 json_object
*json_last_update
= NULL
;
8509 json_object
*json_pmsi
= NULL
;
8510 json_object
*json_nexthop_global
= NULL
;
8511 json_object
*json_nexthop_ll
= NULL
;
8512 json_object
*json_nexthops
= NULL
;
8513 json_object
*json_path
= NULL
;
8514 json_object
*json_peer
= NULL
;
8515 json_object
*json_string
= NULL
;
8516 json_object
*json_adv_to
= NULL
;
8518 struct listnode
*node
, *nnode
;
8520 int addpath_capable
;
8522 unsigned int first_as
;
8524 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
8526 char *nexthop_hostname
= bgp_nexthop_hostname(path
->peer
, attr
);
8529 json_path
= json_object_new_object();
8530 json_peer
= json_object_new_object();
8531 json_nexthop_global
= json_object_new_object();
8539 if (path
->extra
&& path
->extra
->num_labels
) {
8540 bgp_evpn_label2str(path
->extra
->label
,
8541 path
->extra
->num_labels
, tag_buf
,
8544 if (safi
== SAFI_EVPN
) {
8546 bgp_evpn_route2str((struct prefix_evpn
*)&bn
->p
,
8547 buf2
, sizeof(buf2
));
8548 vty_out(vty
, " Route %s", buf2
);
8549 if (tag_buf
[0] != '\0')
8550 vty_out(vty
, " VNI %s", tag_buf
);
8554 json_object_string_add(json_path
, "VNI",
8559 if (path
->extra
&& path
->extra
->parent
&& !json_paths
) {
8560 struct bgp_path_info
*parent_ri
;
8561 struct bgp_node
*rn
, *prn
;
8563 parent_ri
= (struct bgp_path_info
*)path
->extra
->parent
;
8564 rn
= parent_ri
->net
;
8565 if (rn
&& rn
->prn
) {
8567 prefix_rd2str((struct prefix_rd
*)&prn
->p
,
8568 buf1
, sizeof(buf1
));
8569 if (is_pi_family_evpn(parent_ri
)) {
8570 bgp_evpn_route2str((struct prefix_evpn
*)&rn
->p
,
8571 buf2
, sizeof(buf2
));
8572 vty_out(vty
, " Imported from %s:%s, VNI %s\n", buf1
, buf2
, tag_buf
);
8574 vty_out(vty
, " Imported from %s:%s\n", buf1
, buf2
);
8579 /* Line1 display AS-path, Aggregator */
8582 if (!attr
->aspath
->json
)
8583 aspath_str_update(attr
->aspath
, true);
8584 json_object_lock(attr
->aspath
->json
);
8585 json_object_object_add(json_path
, "aspath",
8586 attr
->aspath
->json
);
8588 if (attr
->aspath
->segments
)
8589 aspath_print_vty(vty
, " %s", attr
->aspath
, "");
8591 vty_out(vty
, " Local");
8595 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
)) {
8597 json_object_boolean_true_add(json_path
, "removed");
8599 vty_out(vty
, ", (removed)");
8602 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
8604 json_object_boolean_true_add(json_path
, "stale");
8606 vty_out(vty
, ", (stale)");
8609 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
8611 json_object_int_add(json_path
, "aggregatorAs",
8612 attr
->aggregator_as
);
8613 json_object_string_add(
8614 json_path
, "aggregatorId",
8615 inet_ntoa(attr
->aggregator_addr
));
8617 vty_out(vty
, ", (aggregated by %u %s)",
8618 attr
->aggregator_as
,
8619 inet_ntoa(attr
->aggregator_addr
));
8623 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
8624 PEER_FLAG_REFLECTOR_CLIENT
)) {
8626 json_object_boolean_true_add(json_path
,
8627 "rxedFromRrClient");
8629 vty_out(vty
, ", (Received from a RR-client)");
8632 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
8633 PEER_FLAG_RSERVER_CLIENT
)) {
8635 json_object_boolean_true_add(json_path
,
8636 "rxedFromRsClient");
8638 vty_out(vty
, ", (Received from a RS-client)");
8641 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
8643 json_object_boolean_true_add(json_path
,
8644 "dampeningHistoryEntry");
8646 vty_out(vty
, ", (history entry)");
8647 } else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)) {
8649 json_object_boolean_true_add(json_path
,
8650 "dampeningSuppressed");
8652 vty_out(vty
, ", (suppressed due to dampening)");
8658 /* Line2 display Next-hop, Neighbor, Router-id */
8659 /* Display the nexthop */
8660 if ((bn
->p
.family
== AF_INET
|| bn
->p
.family
== AF_ETHERNET
8661 || bn
->p
.family
== AF_EVPN
)
8662 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
8663 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
8664 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
8665 || safi
== SAFI_EVPN
) {
8667 json_object_string_add(
8668 json_nexthop_global
, "ip",
8669 inet_ntoa(attr
->mp_nexthop_global_in
));
8671 if (nexthop_hostname
)
8672 json_object_string_add(
8673 json_nexthop_global
, "hostname",
8680 attr
->mp_nexthop_global_in
));
8683 json_object_string_add(
8684 json_nexthop_global
, "ip",
8685 inet_ntoa(attr
->nexthop
));
8687 if (nexthop_hostname
)
8688 json_object_string_add(
8689 json_nexthop_global
, "hostname",
8695 : inet_ntoa(attr
->nexthop
));
8699 json_object_string_add(json_nexthop_global
, "afi",
8703 json_object_string_add(
8704 json_nexthop_global
, "ip",
8705 inet_ntop(AF_INET6
, &attr
->mp_nexthop_global
,
8706 buf
, INET6_ADDRSTRLEN
));
8708 if (nexthop_hostname
)
8709 json_object_string_add(json_nexthop_global
,
8713 json_object_string_add(json_nexthop_global
, "afi",
8715 json_object_string_add(json_nexthop_global
, "scope",
8721 : inet_ntop(AF_INET6
,
8722 &attr
->mp_nexthop_global
,
8723 buf
, INET6_ADDRSTRLEN
));
8727 /* Display the IGP cost or 'inaccessible' */
8728 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
8730 json_object_boolean_false_add(json_nexthop_global
,
8733 vty_out(vty
, " (inaccessible)");
8735 if (path
->extra
&& path
->extra
->igpmetric
) {
8737 json_object_int_add(json_nexthop_global
,
8739 path
->extra
->igpmetric
);
8741 vty_out(vty
, " (metric %u)",
8742 path
->extra
->igpmetric
);
8745 /* IGP cost is 0, display this only for json */
8748 json_object_int_add(json_nexthop_global
,
8753 json_object_boolean_true_add(json_nexthop_global
,
8757 /* Display peer "from" output */
8758 /* This path was originated locally */
8759 if (path
->peer
== bgp
->peer_self
) {
8761 if (safi
== SAFI_EVPN
8762 || (bn
->p
.family
== AF_INET
8763 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
8765 json_object_string_add(json_peer
, "peerId",
8768 vty_out(vty
, " from 0.0.0.0 ");
8771 json_object_string_add(json_peer
, "peerId",
8774 vty_out(vty
, " from :: ");
8778 json_object_string_add(json_peer
, "routerId",
8779 inet_ntoa(bgp
->router_id
));
8781 vty_out(vty
, "(%s)", inet_ntoa(bgp
->router_id
));
8784 /* We RXed this path from one of our peers */
8788 json_object_string_add(json_peer
, "peerId",
8789 sockunion2str(&path
->peer
->su
,
8792 json_object_string_add(json_peer
, "routerId",
8794 &path
->peer
->remote_id
,
8795 buf1
, sizeof(buf1
)));
8797 if (path
->peer
->hostname
)
8798 json_object_string_add(json_peer
, "hostname",
8799 path
->peer
->hostname
);
8801 if (path
->peer
->domainname
)
8802 json_object_string_add(json_peer
, "domainname",
8803 path
->peer
->domainname
);
8805 if (path
->peer
->conf_if
)
8806 json_object_string_add(json_peer
, "interface",
8807 path
->peer
->conf_if
);
8809 if (path
->peer
->conf_if
) {
8810 if (path
->peer
->hostname
8811 && CHECK_FLAG(path
->peer
->bgp
->flags
,
8812 BGP_FLAG_SHOW_HOSTNAME
))
8813 vty_out(vty
, " from %s(%s)",
8814 path
->peer
->hostname
,
8815 path
->peer
->conf_if
);
8817 vty_out(vty
, " from %s",
8818 path
->peer
->conf_if
);
8820 if (path
->peer
->hostname
8821 && CHECK_FLAG(path
->peer
->bgp
->flags
,
8822 BGP_FLAG_SHOW_HOSTNAME
))
8823 vty_out(vty
, " from %s(%s)",
8824 path
->peer
->hostname
,
8827 vty_out(vty
, " from %s",
8828 sockunion2str(&path
->peer
->su
,
8833 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
8834 vty_out(vty
, " (%s)",
8835 inet_ntoa(attr
->originator_id
));
8837 vty_out(vty
, " (%s)",
8839 &path
->peer
->remote_id
, buf1
,
8845 * Note when vrfid of nexthop is different from that of prefix
8847 if (path
->extra
&& path
->extra
->bgp_orig
) {
8848 vrf_id_t nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
8853 if (path
->extra
->bgp_orig
->inst_type
8854 == BGP_INSTANCE_TYPE_DEFAULT
)
8855 vn
= VRF_DEFAULT_NAME
;
8857 vn
= path
->extra
->bgp_orig
->name
;
8859 json_object_string_add(json_path
, "nhVrfName", vn
);
8861 if (nexthop_vrfid
== VRF_UNKNOWN
) {
8862 json_object_int_add(json_path
, "nhVrfId", -1);
8864 json_object_int_add(json_path
, "nhVrfId",
8865 (int)nexthop_vrfid
);
8868 if (nexthop_vrfid
== VRF_UNKNOWN
)
8869 vty_out(vty
, " vrf ?");
8873 vrf
= vrf_lookup_by_id(nexthop_vrfid
);
8874 vty_out(vty
, " vrf %s(%u)",
8875 VRF_LOGNAME(vrf
), nexthop_vrfid
);
8882 json_object_boolean_true_add(json_path
,
8883 "announceNexthopSelf");
8885 vty_out(vty
, " announce-nh-self");
8892 /* display the link-local nexthop */
8893 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
8895 json_nexthop_ll
= json_object_new_object();
8896 json_object_string_add(
8897 json_nexthop_ll
, "ip",
8898 inet_ntop(AF_INET6
, &attr
->mp_nexthop_local
,
8899 buf
, INET6_ADDRSTRLEN
));
8901 if (nexthop_hostname
)
8902 json_object_string_add(json_nexthop_ll
,
8906 json_object_string_add(json_nexthop_ll
, "afi", "ipv6");
8907 json_object_string_add(json_nexthop_ll
, "scope",
8910 json_object_boolean_true_add(json_nexthop_ll
,
8913 if (!attr
->mp_nexthop_prefer_global
)
8914 json_object_boolean_true_add(json_nexthop_ll
,
8917 json_object_boolean_true_add(
8918 json_nexthop_global
, "used");
8920 vty_out(vty
, " (%s) %s\n",
8921 inet_ntop(AF_INET6
, &attr
->mp_nexthop_local
,
8922 buf
, INET6_ADDRSTRLEN
),
8923 attr
->mp_nexthop_prefer_global
8928 /* If we do not have a link-local nexthop then we must flag the
8932 json_object_boolean_true_add(json_nexthop_global
,
8936 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
8937 * Int/Ext/Local, Atomic, best */
8939 json_object_string_add(json_path
, "origin",
8940 bgp_origin_long_str
[attr
->origin
]);
8942 vty_out(vty
, " Origin %s",
8943 bgp_origin_long_str
[attr
->origin
]);
8945 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
8948 * Adding "metric" field to match with
8949 * corresponding CLI. "med" will be
8950 * deprecated in future.
8952 json_object_int_add(json_path
, "med", attr
->med
);
8953 json_object_int_add(json_path
, "metric", attr
->med
);
8955 vty_out(vty
, ", metric %u", attr
->med
);
8958 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
8960 json_object_int_add(json_path
, "localpref",
8963 vty_out(vty
, ", localpref %u", attr
->local_pref
);
8966 if (attr
->weight
!= 0) {
8968 json_object_int_add(json_path
, "weight", attr
->weight
);
8970 vty_out(vty
, ", weight %u", attr
->weight
);
8973 if (attr
->tag
!= 0) {
8975 json_object_int_add(json_path
, "tag", attr
->tag
);
8977 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
, attr
->tag
);
8980 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
8982 json_object_boolean_false_add(json_path
, "valid");
8984 vty_out(vty
, ", invalid");
8985 } else if (!CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
8987 json_object_boolean_true_add(json_path
, "valid");
8989 vty_out(vty
, ", valid");
8992 if (path
->peer
!= bgp
->peer_self
) {
8993 if (path
->peer
->as
== path
->peer
->local_as
) {
8994 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
8996 json_object_string_add(
9000 vty_out(vty
, ", confed-internal");
9003 json_object_string_add(
9004 json_peer
, "type", "internal");
9006 vty_out(vty
, ", internal");
9009 if (bgp_confederation_peers_check(bgp
,
9012 json_object_string_add(
9016 vty_out(vty
, ", confed-external");
9019 json_object_string_add(
9020 json_peer
, "type", "external");
9022 vty_out(vty
, ", external");
9025 } else if (path
->sub_type
== BGP_ROUTE_AGGREGATE
) {
9027 json_object_boolean_true_add(json_path
, "aggregated");
9028 json_object_boolean_true_add(json_path
, "local");
9030 vty_out(vty
, ", aggregated, local");
9032 } else if (path
->type
!= ZEBRA_ROUTE_BGP
) {
9034 json_object_boolean_true_add(json_path
, "sourced");
9036 vty_out(vty
, ", sourced");
9039 json_object_boolean_true_add(json_path
, "sourced");
9040 json_object_boolean_true_add(json_path
, "local");
9042 vty_out(vty
, ", sourced, local");
9046 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
9048 json_object_boolean_true_add(json_path
,
9051 vty_out(vty
, ", atomic-aggregate");
9054 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
)
9055 || (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)
9056 && bgp_path_info_mpath_count(path
))) {
9058 json_object_boolean_true_add(json_path
, "multipath");
9060 vty_out(vty
, ", multipath");
9063 // Mark the bestpath(s)
9064 if (CHECK_FLAG(path
->flags
, BGP_PATH_DMED_SELECTED
)) {
9065 first_as
= aspath_get_first_as(attr
->aspath
);
9069 json_bestpath
= json_object_new_object();
9070 json_object_int_add(json_bestpath
, "bestpathFromAs",
9074 vty_out(vty
, ", bestpath-from-AS %u", first_as
);
9076 vty_out(vty
, ", bestpath-from-AS Local");
9080 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
9083 json_bestpath
= json_object_new_object();
9084 json_object_boolean_true_add(json_bestpath
, "overall");
9085 json_object_string_add(
9086 json_bestpath
, "selectionReason",
9087 bgp_path_selection_reason2str(bn
->reason
));
9089 vty_out(vty
, ", best");
9090 vty_out(vty
, " (%s)",
9091 bgp_path_selection_reason2str(bn
->reason
));
9096 json_object_object_add(json_path
, "bestpath", json_bestpath
);
9101 /* Line 4 display Community */
9102 if (attr
->community
) {
9104 if (!attr
->community
->json
)
9105 community_str(attr
->community
, true);
9106 json_object_lock(attr
->community
->json
);
9107 json_object_object_add(json_path
, "community",
9108 attr
->community
->json
);
9110 vty_out(vty
, " Community: %s\n",
9111 attr
->community
->str
);
9115 /* Line 5 display Extended-community */
9116 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
9118 json_ext_community
= json_object_new_object();
9119 json_object_string_add(json_ext_community
, "string",
9120 attr
->ecommunity
->str
);
9121 json_object_object_add(json_path
, "extendedCommunity",
9122 json_ext_community
);
9124 vty_out(vty
, " Extended Community: %s\n",
9125 attr
->ecommunity
->str
);
9129 /* Line 6 display Large community */
9130 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
9132 if (!attr
->lcommunity
->json
)
9133 lcommunity_str(attr
->lcommunity
, true);
9134 json_object_lock(attr
->lcommunity
->json
);
9135 json_object_object_add(json_path
, "largeCommunity",
9136 attr
->lcommunity
->json
);
9138 vty_out(vty
, " Large Community: %s\n",
9139 attr
->lcommunity
->str
);
9143 /* Line 7 display Originator, Cluster-id */
9144 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
9145 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
9146 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
9148 json_object_string_add(
9149 json_path
, "originatorId",
9150 inet_ntoa(attr
->originator_id
));
9152 vty_out(vty
, " Originator: %s",
9153 inet_ntoa(attr
->originator_id
));
9156 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
9160 json_cluster_list
= json_object_new_object();
9161 json_cluster_list_list
=
9162 json_object_new_array();
9164 for (i
= 0; i
< attr
->cluster
->length
/ 4;
9166 json_string
= json_object_new_string(
9167 inet_ntoa(attr
->cluster
9169 json_object_array_add(
9170 json_cluster_list_list
,
9175 * struct cluster_list does not have
9176 * "str" variable like aspath and community
9177 * do. Add this someday if someone asks
9179 * json_object_string_add(json_cluster_list,
9180 * "string", attr->cluster->str);
9182 json_object_object_add(json_cluster_list
,
9184 json_cluster_list_list
);
9185 json_object_object_add(json_path
, "clusterList",
9188 vty_out(vty
, ", Cluster list: ");
9190 for (i
= 0; i
< attr
->cluster
->length
/ 4;
9193 inet_ntoa(attr
->cluster
9203 if (path
->extra
&& path
->extra
->damp_info
)
9204 bgp_damp_info_vty(vty
, path
, afi
, safi
, json_path
);
9207 if (path
->extra
&& bgp_is_valid_label(&path
->extra
->label
[0])
9208 && (safi
!= SAFI_EVPN
&& !is_route_parent_evpn(path
))) {
9209 mpls_label_t label
= label_pton(&path
->extra
->label
[0]);
9212 json_object_int_add(json_path
, "remoteLabel", label
);
9214 vty_out(vty
, " Remote label: %d\n", label
);
9218 if (path
->extra
&& path
->extra
->num_sids
> 0 && safi
!= SAFI_EVPN
) {
9219 inet_ntop(AF_INET6
, &path
->extra
->sid
, buf
, sizeof(buf
));
9221 json_object_string_add(json_path
, "remoteSid", buf
);
9223 vty_out(vty
, " Remote SID: %s\n", buf
);
9227 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
9229 json_object_int_add(json_path
, "labelIndex",
9232 vty_out(vty
, " Label Index: %d\n",
9236 /* Line 8 display Addpath IDs */
9237 if (path
->addpath_rx_id
9238 || bgp_addpath_info_has_ids(&path
->tx_addpath
)) {
9240 json_object_int_add(json_path
, "addpathRxId",
9241 path
->addpath_rx_id
);
9243 /* Keep backwards compatibility with the old API
9244 * by putting TX All's ID in the old field
9246 json_object_int_add(
9247 json_path
, "addpathTxId",
9249 .addpath_tx_id
[BGP_ADDPATH_ALL
]);
9251 /* ... but create a specific field for each
9254 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
9255 json_object_int_add(
9257 bgp_addpath_names(i
)->id_json_name
,
9258 path
->tx_addpath
.addpath_tx_id
[i
]);
9261 vty_out(vty
, " AddPath ID: RX %u, ",
9262 path
->addpath_rx_id
);
9264 route_vty_out_tx_ids(vty
, &path
->tx_addpath
);
9268 /* If we used addpath to TX a non-bestpath we need to display
9269 * "Advertised to" on a path-by-path basis
9271 if (bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
9274 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
9276 bgp_addpath_encode_tx(peer
, afi
, safi
);
9277 has_adj
= bgp_adj_out_lookup(
9279 bgp_addpath_id_for_peer(peer
, afi
, safi
,
9280 &path
->tx_addpath
));
9282 if ((addpath_capable
&& has_adj
)
9283 || (!addpath_capable
&& has_adj
9284 && CHECK_FLAG(path
->flags
,
9285 BGP_PATH_SELECTED
))) {
9286 if (json_path
&& !json_adv_to
)
9287 json_adv_to
= json_object_new_object();
9289 route_vty_out_advertised_to(
9291 " Advertised to:", json_adv_to
);
9297 json_object_object_add(
9298 json_path
, "advertisedTo", json_adv_to
);
9307 /* Line 9 display Uptime */
9308 tbuf
= time(NULL
) - (bgp_clock() - path
->uptime
);
9310 json_last_update
= json_object_new_object();
9311 json_object_int_add(json_last_update
, "epoch", tbuf
);
9312 json_object_string_add(json_last_update
, "string",
9314 json_object_object_add(json_path
, "lastUpdate",
9317 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
9319 /* Line 10 display PMSI tunnel attribute, if present */
9320 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
9322 lookup_msg(bgp_pmsi_tnltype_str
, attr
->pmsi_tnl_type
,
9323 PMSI_TNLTYPE_STR_DEFAULT
);
9326 json_pmsi
= json_object_new_object();
9327 json_object_string_add(json_pmsi
, "tunnelType", str
);
9328 json_object_int_add(json_pmsi
, "label",
9329 label2vni(&attr
->label
));
9330 json_object_object_add(json_path
, "pmsi", json_pmsi
);
9332 vty_out(vty
, " PMSI Tunnel Type: %s, label: %d\n",
9333 str
, label2vni(&attr
->label
));
9336 /* We've constructed the json object for this path, add it to the json
9340 if (json_nexthop_global
|| json_nexthop_ll
) {
9341 json_nexthops
= json_object_new_array();
9343 if (json_nexthop_global
)
9344 json_object_array_add(json_nexthops
,
9345 json_nexthop_global
);
9347 if (json_nexthop_ll
)
9348 json_object_array_add(json_nexthops
,
9351 json_object_object_add(json_path
, "nexthops",
9355 json_object_object_add(json_path
, "peer", json_peer
);
9356 json_object_array_add(json_paths
, json_path
);
9360 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
9361 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
9362 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
9364 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
9365 const char *prefix_list_str
, afi_t afi
,
9366 safi_t safi
, enum bgp_show_type type
);
9367 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
9368 const char *filter
, afi_t afi
, safi_t safi
,
9369 enum bgp_show_type type
);
9370 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
9371 const char *rmap_str
, afi_t afi
, safi_t safi
,
9372 enum bgp_show_type type
);
9373 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
9374 const char *com
, int exact
, afi_t afi
,
9376 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
9377 const char *prefix
, afi_t afi
, safi_t safi
,
9378 enum bgp_show_type type
);
9379 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
9380 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
9382 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
9383 const char *comstr
, int exact
, afi_t afi
,
9384 safi_t safi
, bool use_json
);
9387 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
9388 struct bgp_table
*table
, enum bgp_show_type type
,
9389 void *output_arg
, bool use_json
, char *rd
,
9390 int is_last
, unsigned long *output_cum
,
9391 unsigned long *total_cum
,
9392 unsigned long *json_header_depth
)
9394 struct bgp_path_info
*pi
;
9395 struct bgp_node
*rn
;
9398 unsigned long output_count
= 0;
9399 unsigned long total_count
= 0;
9402 json_object
*json_paths
= NULL
;
9405 if (output_cum
&& *output_cum
!= 0)
9408 if (use_json
&& !*json_header_depth
) {
9410 "{\n \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
9411 ",\n \"routerId\": \"%s\",\n \"defaultLocPrf\": %u,\n"
9412 " \"localAS\": %u,\n \"routes\": { ",
9413 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
9414 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
9417 table
->version
, inet_ntoa(bgp
->router_id
),
9418 bgp
->default_local_pref
, bgp
->as
);
9419 *json_header_depth
= 2;
9421 vty_out(vty
, " \"routeDistinguishers\" : {");
9422 ++*json_header_depth
;
9426 if (use_json
&& rd
) {
9427 vty_out(vty
, " \"%s\" : { ", rd
);
9430 /* Start processing of routes. */
9431 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
9432 pi
= bgp_node_get_bgp_path_info(rn
);
9438 json_paths
= json_object_new_array();
9442 for (; pi
; pi
= pi
->next
) {
9444 if (type
== bgp_show_type_flap_statistics
9445 || type
== bgp_show_type_flap_neighbor
9446 || type
== bgp_show_type_dampend_paths
9447 || type
== bgp_show_type_damp_neighbor
) {
9448 if (!(pi
->extra
&& pi
->extra
->damp_info
))
9451 if (type
== bgp_show_type_regexp
) {
9452 regex_t
*regex
= output_arg
;
9454 if (bgp_regexec(regex
, pi
->attr
->aspath
)
9458 if (type
== bgp_show_type_prefix_list
) {
9459 struct prefix_list
*plist
= output_arg
;
9461 if (prefix_list_apply(plist
, &rn
->p
)
9465 if (type
== bgp_show_type_filter_list
) {
9466 struct as_list
*as_list
= output_arg
;
9468 if (as_list_apply(as_list
, pi
->attr
->aspath
)
9469 != AS_FILTER_PERMIT
)
9472 if (type
== bgp_show_type_route_map
) {
9473 struct route_map
*rmap
= output_arg
;
9474 struct bgp_path_info path
;
9475 struct attr dummy_attr
;
9476 route_map_result_t ret
;
9478 dummy_attr
= *pi
->attr
;
9480 path
.peer
= pi
->peer
;
9481 path
.attr
= &dummy_attr
;
9483 ret
= route_map_apply(rmap
, &rn
->p
, RMAP_BGP
,
9485 if (ret
== RMAP_DENYMATCH
)
9488 if (type
== bgp_show_type_neighbor
9489 || type
== bgp_show_type_flap_neighbor
9490 || type
== bgp_show_type_damp_neighbor
) {
9491 union sockunion
*su
= output_arg
;
9493 if (pi
->peer
== NULL
9494 || pi
->peer
->su_remote
== NULL
9495 || !sockunion_same(pi
->peer
->su_remote
, su
))
9498 if (type
== bgp_show_type_cidr_only
) {
9499 uint32_t destination
;
9501 destination
= ntohl(rn
->p
.u
.prefix4
.s_addr
);
9502 if (IN_CLASSC(destination
)
9503 && rn
->p
.prefixlen
== 24)
9505 if (IN_CLASSB(destination
)
9506 && rn
->p
.prefixlen
== 16)
9508 if (IN_CLASSA(destination
)
9509 && rn
->p
.prefixlen
== 8)
9512 if (type
== bgp_show_type_prefix_longer
) {
9514 if (!prefix_match(p
, &rn
->p
))
9517 if (type
== bgp_show_type_community_all
) {
9518 if (!pi
->attr
->community
)
9521 if (type
== bgp_show_type_community
) {
9522 struct community
*com
= output_arg
;
9524 if (!pi
->attr
->community
9525 || !community_match(pi
->attr
->community
,
9529 if (type
== bgp_show_type_community_exact
) {
9530 struct community
*com
= output_arg
;
9532 if (!pi
->attr
->community
9533 || !community_cmp(pi
->attr
->community
, com
))
9536 if (type
== bgp_show_type_community_list
) {
9537 struct community_list
*list
= output_arg
;
9539 if (!community_list_match(pi
->attr
->community
,
9543 if (type
== bgp_show_type_community_list_exact
) {
9544 struct community_list
*list
= output_arg
;
9546 if (!community_list_exact_match(
9547 pi
->attr
->community
, list
))
9550 if (type
== bgp_show_type_lcommunity
) {
9551 struct lcommunity
*lcom
= output_arg
;
9553 if (!pi
->attr
->lcommunity
9554 || !lcommunity_match(pi
->attr
->lcommunity
,
9559 if (type
== bgp_show_type_lcommunity_exact
) {
9560 struct lcommunity
*lcom
= output_arg
;
9562 if (!pi
->attr
->lcommunity
9563 || !lcommunity_cmp(pi
->attr
->lcommunity
,
9567 if (type
== bgp_show_type_lcommunity_list
) {
9568 struct community_list
*list
= output_arg
;
9570 if (!lcommunity_list_match(pi
->attr
->lcommunity
,
9575 == bgp_show_type_lcommunity_list_exact
) {
9576 struct community_list
*list
= output_arg
;
9578 if (!lcommunity_list_exact_match(
9579 pi
->attr
->lcommunity
, list
))
9582 if (type
== bgp_show_type_lcommunity_all
) {
9583 if (!pi
->attr
->lcommunity
)
9586 if (type
== bgp_show_type_dampend_paths
9587 || type
== bgp_show_type_damp_neighbor
) {
9588 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
)
9589 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
9593 if (!use_json
&& header
) {
9594 vty_out(vty
, "BGP table version is %" PRIu64
9595 ", local router ID is %s, vrf id ",
9597 inet_ntoa(bgp
->router_id
));
9598 if (bgp
->vrf_id
== VRF_UNKNOWN
)
9599 vty_out(vty
, "%s", VRFID_NONE_STR
);
9601 vty_out(vty
, "%u", bgp
->vrf_id
);
9603 vty_out(vty
, "Default local pref %u, ",
9604 bgp
->default_local_pref
);
9605 vty_out(vty
, "local AS %u\n", bgp
->as
);
9606 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
9607 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
9608 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
9609 if (type
== bgp_show_type_dampend_paths
9610 || type
== bgp_show_type_damp_neighbor
)
9611 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
9612 else if (type
== bgp_show_type_flap_statistics
9613 || type
== bgp_show_type_flap_neighbor
)
9614 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
9616 vty_out(vty
, BGP_SHOW_HEADER
);
9619 if (rd
!= NULL
&& !display
&& !output_count
) {
9622 "Route Distinguisher: %s\n",
9625 if (type
== bgp_show_type_dampend_paths
9626 || type
== bgp_show_type_damp_neighbor
)
9627 damp_route_vty_out(vty
, &rn
->p
, pi
, display
, AFI_IP
,
9628 safi
, use_json
, json_paths
);
9629 else if (type
== bgp_show_type_flap_statistics
9630 || type
== bgp_show_type_flap_neighbor
)
9631 flap_route_vty_out(vty
, &rn
->p
, pi
, display
, AFI_IP
,
9632 safi
, use_json
, json_paths
);
9634 route_vty_out(vty
, &rn
->p
, pi
, display
, safi
,
9646 if (p
->family
== AF_FLOWSPEC
) {
9647 char retstr
[BGP_FLOWSPEC_STRING_DISPLAY_MAX
];
9649 bgp_fs_nlri_get_string((unsigned char *)
9650 p
->u
.prefix_flowspec
.ptr
,
9651 p
->u
.prefix_flowspec
9654 NLRI_STRING_FORMAT_MIN
,
9657 vty_out(vty
, "\"%s/%d\": ",
9659 p
->u
.prefix_flowspec
.prefixlen
);
9661 vty_out(vty
, ",\"%s/%d\": ",
9663 p
->u
.prefix_flowspec
.prefixlen
);
9665 prefix2str(p
, buf2
, sizeof(buf2
));
9667 vty_out(vty
, "\"%s\": ", buf2
);
9669 vty_out(vty
, ",\"%s\": ", buf2
);
9672 json_object_to_json_string_ext(
9673 json_paths
, JSON_C_TO_STRING_PRETTY
));
9674 json_object_free(json_paths
);
9678 json_object_free(json_paths
);
9682 output_count
+= *output_cum
;
9683 *output_cum
= output_count
;
9686 total_count
+= *total_cum
;
9687 *total_cum
= total_count
;
9691 vty_out(vty
, " }%s ", (is_last
? "" : ","));
9695 for (i
= 0; i
< *json_header_depth
; ++i
)
9696 vty_out(vty
, " } ");
9701 /* No route is displayed */
9702 if (output_count
== 0) {
9703 if (type
== bgp_show_type_normal
)
9705 "No BGP prefixes displayed, %ld exist\n",
9709 "\nDisplayed %ld routes and %ld total paths\n",
9710 output_count
, total_count
);
9717 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
9718 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
9719 enum bgp_show_type type
, void *output_arg
, bool use_json
)
9721 struct bgp_node
*rn
, *next
;
9722 unsigned long output_cum
= 0;
9723 unsigned long total_cum
= 0;
9724 unsigned long json_header_depth
= 0;
9725 struct bgp_table
*itable
;
9728 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
9730 for (rn
= bgp_table_top(table
); rn
; rn
= next
) {
9731 next
= bgp_route_next(rn
);
9732 if (prd_match
&& memcmp(rn
->p
.u
.val
, prd_match
->val
, 8) != 0)
9735 itable
= bgp_node_get_bgp_table_info(rn
);
9736 if (itable
!= NULL
) {
9737 struct prefix_rd prd
;
9738 char rd
[RD_ADDRSTRLEN
];
9740 memcpy(&prd
, &(rn
->p
), sizeof(struct prefix_rd
));
9741 prefix_rd2str(&prd
, rd
, sizeof(rd
));
9742 bgp_show_table(vty
, bgp
, safi
, itable
, type
, output_arg
,
9743 use_json
, rd
, next
== NULL
, &output_cum
,
9744 &total_cum
, &json_header_depth
);
9750 if (output_cum
== 0)
9751 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
9755 "\nDisplayed %ld routes and %ld total paths\n",
9756 output_cum
, total_cum
);
9760 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
9761 enum bgp_show_type type
, void *output_arg
, bool use_json
)
9763 struct bgp_table
*table
;
9764 unsigned long json_header_depth
= 0;
9767 bgp
= bgp_get_default();
9772 vty_out(vty
, "No BGP process is configured\n");
9774 vty_out(vty
, "{}\n");
9778 table
= bgp
->rib
[afi
][safi
];
9779 /* use MPLS and ENCAP specific shows until they are merged */
9780 if (safi
== SAFI_MPLS_VPN
) {
9781 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
9782 output_arg
, use_json
);
9785 if (safi
== SAFI_FLOWSPEC
&& type
== bgp_show_type_detail
) {
9786 return bgp_show_table_flowspec(vty
, bgp
, afi
, table
, type
,
9787 output_arg
, use_json
,
9790 /* labeled-unicast routes live in the unicast table */
9791 else if (safi
== SAFI_LABELED_UNICAST
)
9792 safi
= SAFI_UNICAST
;
9794 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, use_json
,
9795 NULL
, 1, NULL
, NULL
, &json_header_depth
);
9798 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
9799 safi_t safi
, bool use_json
)
9801 struct listnode
*node
, *nnode
;
9804 bool route_output
= false;
9807 vty_out(vty
, "{\n");
9809 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
9810 route_output
= true;
9813 vty_out(vty
, ",\n");
9817 vty_out(vty
, "\"%s\":",
9818 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
9822 vty_out(vty
, "\nInstance %s:\n",
9823 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
9827 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
9832 vty_out(vty
, "}\n");
9833 else if (!route_output
)
9834 vty_out(vty
, "%% BGP instance not found\n");
9837 /* Header of detailed BGP route information */
9838 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
9839 struct bgp_node
*rn
, struct prefix_rd
*prd
,
9840 afi_t afi
, safi_t safi
, json_object
*json
)
9842 struct bgp_path_info
*pi
;
9845 struct listnode
*node
, *nnode
;
9846 char buf1
[RD_ADDRSTRLEN
];
9847 char buf2
[INET6_ADDRSTRLEN
];
9848 char buf3
[EVPN_ROUTE_STRLEN
];
9849 char prefix_str
[BUFSIZ
];
9854 int route_filter_translated_v4
= 0;
9855 int route_filter_v4
= 0;
9856 int route_filter_translated_v6
= 0;
9857 int route_filter_v6
= 0;
9860 int accept_own_nexthop
= 0;
9863 int no_advertise
= 0;
9867 int has_valid_label
= 0;
9868 mpls_label_t label
= 0;
9869 json_object
*json_adv_to
= NULL
;
9872 has_valid_label
= bgp_is_valid_label(&rn
->local_label
);
9874 if (has_valid_label
)
9875 label
= label_pton(&rn
->local_label
);
9877 if (safi
== SAFI_EVPN
) {
9880 vty_out(vty
, "BGP routing table entry for %s%s%s\n",
9881 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
))
9882 : "", prd
? ":" : "",
9883 bgp_evpn_route2str((struct prefix_evpn
*)p
,
9884 buf3
, sizeof(buf3
)));
9886 json_object_string_add(json
, "rd",
9887 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
)) :
9889 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
9893 vty_out(vty
, "BGP routing table entry for %s%s%s/%d\n",
9894 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
9895 ? prefix_rd2str(prd
, buf1
,
9898 safi
== SAFI_MPLS_VPN
? ":" : "",
9899 inet_ntop(p
->family
, &p
->u
.prefix
, buf2
,
9904 json_object_string_add(json
, "prefix",
9905 prefix2str(p
, prefix_str
, sizeof(prefix_str
)));
9908 if (has_valid_label
) {
9910 json_object_int_add(json
, "localLabel", label
);
9912 vty_out(vty
, "Local label: %d\n", label
);
9916 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
9917 vty_out(vty
, "not allocated\n");
9919 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
9921 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
9923 if (pi
->extra
&& pi
->extra
->suppress
)
9926 if (pi
->attr
->community
== NULL
)
9929 no_advertise
+= community_include(
9930 pi
->attr
->community
, COMMUNITY_NO_ADVERTISE
);
9931 no_export
+= community_include(pi
->attr
->community
,
9932 COMMUNITY_NO_EXPORT
);
9933 local_as
+= community_include(pi
->attr
->community
,
9934 COMMUNITY_LOCAL_AS
);
9935 accept_own
+= community_include(pi
->attr
->community
,
9936 COMMUNITY_ACCEPT_OWN
);
9937 route_filter_translated_v4
+= community_include(
9938 pi
->attr
->community
,
9939 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4
);
9940 route_filter_translated_v6
+= community_include(
9941 pi
->attr
->community
,
9942 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6
);
9943 route_filter_v4
+= community_include(
9944 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v4
);
9945 route_filter_v6
+= community_include(
9946 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v6
);
9947 llgr_stale
+= community_include(pi
->attr
->community
,
9948 COMMUNITY_LLGR_STALE
);
9949 no_llgr
+= community_include(pi
->attr
->community
,
9951 accept_own_nexthop
+=
9952 community_include(pi
->attr
->community
,
9953 COMMUNITY_ACCEPT_OWN_NEXTHOP
);
9954 blackhole
+= community_include(pi
->attr
->community
,
9955 COMMUNITY_BLACKHOLE
);
9956 no_peer
+= community_include(pi
->attr
->community
,
9962 vty_out(vty
, "Paths: (%d available", count
);
9964 vty_out(vty
, ", best #%d", best
);
9965 if (safi
== SAFI_UNICAST
) {
9966 if (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
9967 vty_out(vty
, ", table %s",
9970 vty_out(vty
, ", vrf %s",
9974 vty_out(vty
, ", no best path");
9978 ", accept own local route exported and imported in different VRF");
9979 else if (route_filter_translated_v4
)
9981 ", mark translated RTs for VPNv4 route filtering");
9982 else if (route_filter_v4
)
9984 ", attach RT as-is for VPNv4 route filtering");
9985 else if (route_filter_translated_v6
)
9987 ", mark translated RTs for VPNv6 route filtering");
9988 else if (route_filter_v6
)
9990 ", attach RT as-is for VPNv6 route filtering");
9991 else if (llgr_stale
)
9993 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
9996 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
9997 else if (accept_own_nexthop
)
9999 ", accept local nexthop");
10000 else if (blackhole
)
10001 vty_out(vty
, ", inform peer to blackhole prefix");
10002 else if (no_export
)
10003 vty_out(vty
, ", not advertised to EBGP peer");
10004 else if (no_advertise
)
10005 vty_out(vty
, ", not advertised to any peer");
10007 vty_out(vty
, ", not advertised outside local AS");
10010 ", inform EBGP peer not to advertise to their EBGP peers");
10014 ", Advertisements suppressed by an aggregate.");
10015 vty_out(vty
, ")\n");
10018 /* If we are not using addpath then we can display Advertised to and
10020 * show what peers we advertised the bestpath to. If we are using
10022 * though then we must display Advertised to on a path-by-path basis. */
10023 if (!bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
10024 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
10025 if (bgp_adj_out_lookup(peer
, rn
, 0)) {
10026 if (json
&& !json_adv_to
)
10027 json_adv_to
= json_object_new_object();
10029 route_vty_out_advertised_to(
10031 " Advertised to non peer-group peers:\n ",
10038 json_object_object_add(json
, "advertisedTo",
10043 vty_out(vty
, " Not advertised to any peer");
10044 vty_out(vty
, "\n");
10049 static void bgp_show_path_info(struct prefix_rd
*pfx_rd
,
10050 struct bgp_node
*bgp_node
, struct vty
*vty
,
10051 struct bgp
*bgp
, afi_t afi
,
10052 safi_t safi
, json_object
*json
,
10053 enum bgp_path_type pathtype
, int *display
)
10055 struct bgp_path_info
*pi
;
10057 char rdbuf
[RD_ADDRSTRLEN
];
10058 json_object
*json_header
= NULL
;
10059 json_object
*json_paths
= NULL
;
10061 for (pi
= bgp_node_get_bgp_path_info(bgp_node
); pi
;
10064 if (json
&& !json_paths
) {
10065 /* Instantiate json_paths only if path is valid */
10066 json_paths
= json_object_new_array();
10068 prefix_rd2str(pfx_rd
, rdbuf
, sizeof(rdbuf
));
10069 json_header
= json_object_new_object();
10071 json_header
= json
;
10075 route_vty_out_detail_header(
10076 vty
, bgp
, bgp_node
, pfx_rd
,
10077 AFI_IP
, safi
, json_header
);
10082 if (pathtype
== BGP_PATH_SHOW_ALL
10083 || (pathtype
== BGP_PATH_SHOW_BESTPATH
10084 && CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
10085 || (pathtype
== BGP_PATH_SHOW_MULTIPATH
10086 && (CHECK_FLAG(pi
->flags
, BGP_PATH_MULTIPATH
)
10087 || CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))))
10088 route_vty_out_detail(vty
, bgp
, bgp_node
,
10093 if (json
&& json_paths
) {
10094 json_object_object_add(json_header
, "paths", json_paths
);
10097 json_object_object_add(json
, rdbuf
, json_header
);
10101 /* Display specified route of BGP table. */
10102 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
10103 struct bgp_table
*rib
, const char *ip_str
,
10104 afi_t afi
, safi_t safi
,
10105 struct prefix_rd
*prd
, int prefix_check
,
10106 enum bgp_path_type pathtype
, bool use_json
)
10110 struct prefix match
;
10111 struct bgp_node
*rn
;
10112 struct bgp_node
*rm
;
10113 struct bgp_table
*table
;
10114 json_object
*json
= NULL
;
10115 json_object
*json_paths
= NULL
;
10117 /* Check IP address argument. */
10118 ret
= str2prefix(ip_str
, &match
);
10120 vty_out(vty
, "address is malformed\n");
10121 return CMD_WARNING
;
10124 match
.family
= afi2family(afi
);
10127 json
= json_object_new_object();
10129 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
) {
10130 for (rn
= bgp_table_top(rib
); rn
; rn
= bgp_route_next(rn
)) {
10131 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
10133 table
= bgp_node_get_bgp_table_info(rn
);
10137 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
10141 && rm
->p
.prefixlen
!= match
.prefixlen
) {
10142 bgp_unlock_node(rm
);
10146 bgp_show_path_info((struct prefix_rd
*)&rn
->p
, rm
,
10147 vty
, bgp
, afi
, safi
, json
,
10148 pathtype
, &display
);
10150 bgp_unlock_node(rm
);
10152 } else if (safi
== SAFI_EVPN
) {
10153 struct bgp_node
*longest_pfx
;
10154 bool is_exact_pfxlen_match
= FALSE
;
10156 for (rn
= bgp_table_top(rib
); rn
; rn
= bgp_route_next(rn
)) {
10157 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
10159 table
= bgp_node_get_bgp_table_info(rn
);
10163 longest_pfx
= NULL
;
10164 is_exact_pfxlen_match
= FALSE
;
10166 * Search through all the prefixes for a match. The
10167 * pfx's are enumerated in ascending order of pfxlens.
10168 * So, the last pfx match is the longest match. Set
10169 * is_exact_pfxlen_match when we get exact pfxlen match
10171 for (rm
= bgp_table_top(table
); rm
;
10172 rm
= bgp_route_next(rm
)) {
10174 * Get prefixlen of the ip-prefix within type5
10177 if (evpn_type5_prefix_match(&rm
->p
,
10178 &match
) && rm
->info
) {
10181 bgp_evpn_get_type5_prefixlen(&rm
->p
);
10182 if (type5_pfxlen
== match
.prefixlen
) {
10183 is_exact_pfxlen_match
= TRUE
;
10184 bgp_unlock_node(rm
);
10193 if (prefix_check
&& !is_exact_pfxlen_match
)
10199 bgp_show_path_info((struct prefix_rd
*)&rn
->p
, rm
,
10200 vty
, bgp
, afi
, safi
, json
,
10201 pathtype
, &display
);
10203 bgp_unlock_node(rm
);
10205 } else if (safi
== SAFI_FLOWSPEC
) {
10207 json_paths
= json_object_new_array();
10209 display
= bgp_flowspec_display_match_per_ip(afi
, rib
,
10210 &match
, prefix_check
,
10214 if (use_json
&& display
)
10215 json_object_object_add(json
, "paths", json_paths
);
10217 if ((rn
= bgp_node_match(rib
, &match
)) != NULL
) {
10219 || rn
->p
.prefixlen
== match
.prefixlen
) {
10220 bgp_show_path_info(NULL
, rn
, vty
, bgp
, afi
,
10222 pathtype
, &display
);
10225 bgp_unlock_node(rn
);
10230 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
10231 json
, JSON_C_TO_STRING_PRETTY
|
10232 JSON_C_TO_STRING_NOSLASHESCAPE
));
10233 json_object_free(json
);
10236 vty_out(vty
, "%% Network not in table\n");
10237 return CMD_WARNING
;
10241 return CMD_SUCCESS
;
10244 /* Display specified route of Main RIB */
10245 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
10246 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
10247 int prefix_check
, enum bgp_path_type pathtype
,
10251 bgp
= bgp_get_default();
10254 vty_out(vty
, "No BGP process is configured\n");
10256 vty_out(vty
, "{}\n");
10257 return CMD_WARNING
;
10261 /* labeled-unicast routes live in the unicast table */
10262 if (safi
== SAFI_LABELED_UNICAST
)
10263 safi
= SAFI_UNICAST
;
10265 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
10266 afi
, safi
, prd
, prefix_check
, pathtype
,
10270 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
10271 struct cmd_token
**argv
, bool exact
, afi_t afi
,
10272 safi_t safi
, bool uj
)
10274 struct lcommunity
*lcom
;
10280 b
= buffer_new(1024);
10281 for (i
= 0; i
< argc
; i
++) {
10283 buffer_putc(b
, ' ');
10285 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
10287 buffer_putstr(b
, argv
[i
]->arg
);
10291 buffer_putc(b
, '\0');
10293 str
= buffer_getstr(b
);
10296 lcom
= lcommunity_str2com(str
);
10297 XFREE(MTYPE_TMP
, str
);
10299 vty_out(vty
, "%% Large-community malformed\n");
10300 return CMD_WARNING
;
10303 return bgp_show(vty
, bgp
, afi
, safi
,
10304 (exact
? bgp_show_type_lcommunity_exact
10305 : bgp_show_type_lcommunity
),
10309 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
10310 const char *lcom
, bool exact
, afi_t afi
,
10311 safi_t safi
, bool uj
)
10313 struct community_list
*list
;
10315 list
= community_list_lookup(bgp_clist
, lcom
, 0,
10316 LARGE_COMMUNITY_LIST_MASTER
);
10317 if (list
== NULL
) {
10318 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
10320 return CMD_WARNING
;
10323 return bgp_show(vty
, bgp
, afi
, safi
,
10324 (exact
? bgp_show_type_lcommunity_list_exact
10325 : bgp_show_type_lcommunity_list
),
10329 DEFUN (show_ip_bgp_large_community_list
,
10330 show_ip_bgp_large_community_list_cmd
,
10331 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community-list <(1-500)|WORD> [exact-match] [json]",
10335 BGP_INSTANCE_HELP_STR
10337 BGP_SAFI_WITH_LABEL_HELP_STR
10338 "Display routes matching the large-community-list\n"
10339 "large-community-list number\n"
10340 "large-community-list name\n"
10341 "Exact match of the large-communities\n"
10345 afi_t afi
= AFI_IP6
;
10346 safi_t safi
= SAFI_UNICAST
;
10348 bool exact_match
= 0;
10350 if (argv_find(argv
, argc
, "ip", &idx
))
10352 if (argv_find(argv
, argc
, "view", &idx
)
10353 || argv_find(argv
, argc
, "vrf", &idx
))
10354 vrf
= argv
[++idx
]->arg
;
10355 if (argv_find(argv
, argc
, "ipv4", &idx
)
10356 || argv_find(argv
, argc
, "ipv6", &idx
)) {
10357 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
10358 if (argv_find(argv
, argc
, "unicast", &idx
)
10359 || argv_find(argv
, argc
, "multicast", &idx
))
10360 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
10363 bool uj
= use_json(argc
, argv
);
10365 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
10367 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
10368 return CMD_WARNING
;
10371 argv_find(argv
, argc
, "large-community-list", &idx
);
10373 const char *clist_number_or_name
= argv
[++idx
]->arg
;
10375 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
10378 return bgp_show_lcommunity_list(vty
, bgp
, clist_number_or_name
,
10379 exact_match
, afi
, safi
, uj
);
10381 DEFUN (show_ip_bgp_large_community
,
10382 show_ip_bgp_large_community_cmd
,
10383 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [<AA:BB:CC> [exact-match]] [json]",
10387 BGP_INSTANCE_HELP_STR
10389 BGP_SAFI_WITH_LABEL_HELP_STR
10390 "Display routes matching the large-communities\n"
10391 "List of large-community numbers\n"
10392 "Exact match of the large-communities\n"
10396 afi_t afi
= AFI_IP6
;
10397 safi_t safi
= SAFI_UNICAST
;
10399 bool exact_match
= 0;
10401 if (argv_find(argv
, argc
, "ip", &idx
))
10403 if (argv_find(argv
, argc
, "view", &idx
)
10404 || argv_find(argv
, argc
, "vrf", &idx
))
10405 vrf
= argv
[++idx
]->arg
;
10406 if (argv_find(argv
, argc
, "ipv4", &idx
)
10407 || argv_find(argv
, argc
, "ipv6", &idx
)) {
10408 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
10409 if (argv_find(argv
, argc
, "unicast", &idx
)
10410 || argv_find(argv
, argc
, "multicast", &idx
))
10411 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
10414 bool uj
= use_json(argc
, argv
);
10416 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
10418 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
10419 return CMD_WARNING
;
10422 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
)) {
10423 if (argv_find(argv
, argc
, "exact-match", &idx
))
10425 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
,
10426 exact_match
, afi
, safi
, uj
);
10428 return bgp_show(vty
, bgp
, afi
, safi
,
10429 bgp_show_type_lcommunity_all
, NULL
, uj
);
10432 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
10436 /* BGP route print out function without JSON */
10437 DEFUN (show_ip_bgp
,
10439 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
10440 <dampening <parameters>\
10445 |community-list <(1-500)|WORD> [exact-match]\
10446 |A.B.C.D/M longer-prefixes\
10447 |X:X::X:X/M longer-prefixes\
10452 BGP_INSTANCE_HELP_STR
10454 BGP_SAFI_WITH_LABEL_HELP_STR
10455 "Display detailed information about dampening\n"
10456 "Display detail of configured dampening parameters\n"
10457 "Display routes matching the route-map\n"
10458 "A route-map to match on\n"
10459 "Display routes conforming to the prefix-list\n"
10460 "Prefix-list name\n"
10461 "Display routes conforming to the filter-list\n"
10462 "Regular expression access list name\n"
10463 "BGP RIB advertisement statistics\n"
10464 "Display routes matching the community-list\n"
10465 "community-list number\n"
10466 "community-list name\n"
10467 "Exact match of the communities\n"
10469 "Display route and more specific routes\n"
10471 "Display route and more specific routes\n")
10473 afi_t afi
= AFI_IP6
;
10474 safi_t safi
= SAFI_UNICAST
;
10475 int exact_match
= 0;
10476 struct bgp
*bgp
= NULL
;
10479 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10482 return CMD_WARNING
;
10484 if (argv_find(argv
, argc
, "dampening", &idx
)) {
10485 if (argv_find(argv
, argc
, "parameters", &idx
))
10486 return bgp_show_dampening_parameters(vty
, afi
, safi
);
10489 if (argv_find(argv
, argc
, "prefix-list", &idx
))
10490 return bgp_show_prefix_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
10491 safi
, bgp_show_type_prefix_list
);
10493 if (argv_find(argv
, argc
, "filter-list", &idx
))
10494 return bgp_show_filter_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
10495 safi
, bgp_show_type_filter_list
);
10497 if (argv_find(argv
, argc
, "statistics", &idx
))
10498 return bgp_table_stats(vty
, bgp
, afi
, safi
);
10500 if (argv_find(argv
, argc
, "route-map", &idx
))
10501 return bgp_show_route_map(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
10502 safi
, bgp_show_type_route_map
);
10504 if (argv_find(argv
, argc
, "community-list", &idx
)) {
10505 const char *clist_number_or_name
= argv
[++idx
]->arg
;
10506 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
10508 return bgp_show_community_list(vty
, bgp
, clist_number_or_name
,
10509 exact_match
, afi
, safi
);
10511 /* prefix-longer */
10512 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
10513 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
10514 return bgp_show_prefix_longer(vty
, bgp
, argv
[idx
]->arg
, afi
,
10516 bgp_show_type_prefix_longer
);
10518 return CMD_WARNING
;
10521 /* BGP route print out function with JSON */
10522 DEFUN (show_ip_bgp_json
,
10523 show_ip_bgp_json_cmd
,
10524 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
10526 |dampening <flap-statistics|dampened-paths>\
10527 |community [AA:NN|local-AS|no-advertise|no-export\
10528 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
10529 |accept-own|accept-own-nexthop|route-filter-v6\
10530 |route-filter-v4|route-filter-translated-v6\
10531 |route-filter-translated-v4] [exact-match]\
10536 BGP_INSTANCE_HELP_STR
10538 BGP_SAFI_WITH_LABEL_HELP_STR
10539 "Display only routes with non-natural netmasks\n"
10540 "Display detailed information about dampening\n"
10541 "Display flap statistics of routes\n"
10542 "Display paths suppressed due to dampening\n"
10543 "Display routes matching the communities\n"
10545 "Do not send outside local AS (well-known community)\n"
10546 "Do not advertise to any peer (well-known community)\n"
10547 "Do not export to next AS (well-known community)\n"
10548 "Graceful shutdown (well-known community)\n"
10549 "Do not export to any peer (well-known community)\n"
10550 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
10551 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
10552 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
10553 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
10554 "Should accept VPN route with local nexthop (well-known community)\n"
10555 "RT VPNv6 route filtering (well-known community)\n"
10556 "RT VPNv4 route filtering (well-known community)\n"
10557 "RT translated VPNv6 route filtering (well-known community)\n"
10558 "RT translated VPNv4 route filtering (well-known community)\n"
10559 "Exact match of the communities\n"
10562 afi_t afi
= AFI_IP6
;
10563 safi_t safi
= SAFI_UNICAST
;
10564 enum bgp_show_type sh_type
= bgp_show_type_normal
;
10565 struct bgp
*bgp
= NULL
;
10567 int exact_match
= 0;
10568 bool uj
= use_json(argc
, argv
);
10573 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10576 return CMD_WARNING
;
10578 if (argv_find(argv
, argc
, "cidr-only", &idx
))
10579 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_cidr_only
,
10582 if (argv_find(argv
, argc
, "dampening", &idx
)) {
10583 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
10584 return bgp_show(vty
, bgp
, afi
, safi
,
10585 bgp_show_type_dampend_paths
, NULL
, uj
);
10586 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
10587 return bgp_show(vty
, bgp
, afi
, safi
,
10588 bgp_show_type_flap_statistics
, NULL
,
10592 if (argv_find(argv
, argc
, "community", &idx
)) {
10593 char *maybecomm
= NULL
;
10594 char *community
= NULL
;
10596 if (idx
+ 1 < argc
) {
10597 if (argv
[idx
+ 1]->type
== VARIABLE_TKN
)
10598 maybecomm
= argv
[idx
+ 1]->arg
;
10600 maybecomm
= argv
[idx
+ 1]->text
;
10603 if (maybecomm
&& !strmatch(maybecomm
, "json")
10604 && !strmatch(maybecomm
, "exact-match"))
10605 community
= maybecomm
;
10607 if (argv_find(argv
, argc
, "exact-match", &idx
))
10611 return bgp_show_community(vty
, bgp
, community
,
10612 exact_match
, afi
, safi
, uj
);
10614 return (bgp_show(vty
, bgp
, afi
, safi
,
10615 bgp_show_type_community_all
, NULL
,
10619 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
, NULL
, uj
);
10622 DEFUN (show_ip_bgp_route
,
10623 show_ip_bgp_route_cmd
,
10624 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]"
10625 "<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [json]",
10629 BGP_INSTANCE_HELP_STR
10631 BGP_SAFI_WITH_LABEL_HELP_STR
10632 "Network in the BGP routing table to display\n"
10634 "Network in the BGP routing table to display\n"
10636 "Display only the bestpath\n"
10637 "Display only multipaths\n"
10640 int prefix_check
= 0;
10642 afi_t afi
= AFI_IP6
;
10643 safi_t safi
= SAFI_UNICAST
;
10644 char *prefix
= NULL
;
10645 struct bgp
*bgp
= NULL
;
10646 enum bgp_path_type path_type
;
10647 bool uj
= use_json(argc
, argv
);
10651 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10654 return CMD_WARNING
;
10658 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
10659 return CMD_WARNING
;
10662 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
10663 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
10664 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
10666 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
10667 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
10670 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
10671 && afi
!= AFI_IP6
) {
10673 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
10674 return CMD_WARNING
;
10676 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
10677 && afi
!= AFI_IP
) {
10679 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
10680 return CMD_WARNING
;
10683 prefix
= argv
[idx
]->arg
;
10685 /* [<bestpath|multipath>] */
10686 if (argv_find(argv
, argc
, "bestpath", &idx
))
10687 path_type
= BGP_PATH_SHOW_BESTPATH
;
10688 else if (argv_find(argv
, argc
, "multipath", &idx
))
10689 path_type
= BGP_PATH_SHOW_MULTIPATH
;
10691 path_type
= BGP_PATH_SHOW_ALL
;
10693 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
10697 DEFUN (show_ip_bgp_regexp
,
10698 show_ip_bgp_regexp_cmd
,
10699 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX [json]",
10703 BGP_INSTANCE_HELP_STR
10705 BGP_SAFI_WITH_LABEL_HELP_STR
10706 "Display routes matching the AS path regular expression\n"
10707 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
10710 afi_t afi
= AFI_IP6
;
10711 safi_t safi
= SAFI_UNICAST
;
10712 struct bgp
*bgp
= NULL
;
10713 bool uj
= use_json(argc
, argv
);
10714 char *regstr
= NULL
;
10717 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10720 return CMD_WARNING
;
10722 // get index of regex
10723 if (argv_find(argv
, argc
, "REGEX", &idx
))
10724 regstr
= argv
[idx
]->arg
;
10727 return bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
10728 bgp_show_type_regexp
, uj
);
10731 DEFUN (show_ip_bgp_instance_all
,
10732 show_ip_bgp_instance_all_cmd
,
10733 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json]",
10737 BGP_INSTANCE_ALL_HELP_STR
10739 BGP_SAFI_WITH_LABEL_HELP_STR
10742 afi_t afi
= AFI_IP
;
10743 safi_t safi
= SAFI_UNICAST
;
10744 struct bgp
*bgp
= NULL
;
10746 bool uj
= use_json(argc
, argv
);
10751 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10754 return CMD_WARNING
;
10756 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, uj
);
10757 return CMD_SUCCESS
;
10760 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
10761 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
10767 if (!config_bgp_aspath_validate(regstr
)) {
10768 vty_out(vty
, "Invalid character in REGEX %s\n",
10770 return CMD_WARNING_CONFIG_FAILED
;
10773 regex
= bgp_regcomp(regstr
);
10775 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
10776 return CMD_WARNING
;
10779 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, use_json
);
10780 bgp_regex_free(regex
);
10784 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
10785 const char *prefix_list_str
, afi_t afi
,
10786 safi_t safi
, enum bgp_show_type type
)
10788 struct prefix_list
*plist
;
10790 plist
= prefix_list_lookup(afi
, prefix_list_str
);
10791 if (plist
== NULL
) {
10792 vty_out(vty
, "%% %s is not a valid prefix-list name\n",
10794 return CMD_WARNING
;
10797 return bgp_show(vty
, bgp
, afi
, safi
, type
, plist
, 0);
10800 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
10801 const char *filter
, afi_t afi
, safi_t safi
,
10802 enum bgp_show_type type
)
10804 struct as_list
*as_list
;
10806 as_list
= as_list_lookup(filter
);
10807 if (as_list
== NULL
) {
10808 vty_out(vty
, "%% %s is not a valid AS-path access-list name\n",
10810 return CMD_WARNING
;
10813 return bgp_show(vty
, bgp
, afi
, safi
, type
, as_list
, 0);
10816 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
10817 const char *rmap_str
, afi_t afi
, safi_t safi
,
10818 enum bgp_show_type type
)
10820 struct route_map
*rmap
;
10822 rmap
= route_map_lookup_by_name(rmap_str
);
10824 vty_out(vty
, "%% %s is not a valid route-map name\n", rmap_str
);
10825 return CMD_WARNING
;
10828 return bgp_show(vty
, bgp
, afi
, safi
, type
, rmap
, 0);
10831 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
10832 const char *comstr
, int exact
, afi_t afi
,
10833 safi_t safi
, bool use_json
)
10835 struct community
*com
;
10838 com
= community_str2com(comstr
);
10840 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
10841 return CMD_WARNING
;
10844 ret
= bgp_show(vty
, bgp
, afi
, safi
,
10845 (exact
? bgp_show_type_community_exact
10846 : bgp_show_type_community
),
10848 community_free(&com
);
10853 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
10854 const char *com
, int exact
, afi_t afi
,
10857 struct community_list
*list
;
10859 list
= community_list_lookup(bgp_clist
, com
, 0, COMMUNITY_LIST_MASTER
);
10860 if (list
== NULL
) {
10861 vty_out(vty
, "%% %s is not a valid community-list name\n", com
);
10862 return CMD_WARNING
;
10865 return bgp_show(vty
, bgp
, afi
, safi
,
10866 (exact
? bgp_show_type_community_list_exact
10867 : bgp_show_type_community_list
),
10871 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
10872 const char *prefix
, afi_t afi
, safi_t safi
,
10873 enum bgp_show_type type
)
10880 ret
= str2prefix(prefix
, p
);
10882 vty_out(vty
, "%% Malformed Prefix\n");
10883 return CMD_WARNING
;
10886 ret
= bgp_show(vty
, bgp
, afi
, safi
, type
, p
, 0);
10892 BGP_STATS_MAXBITLEN
= 0,
10894 BGP_STATS_PREFIXES
,
10896 BGP_STATS_UNAGGREGATEABLE
,
10897 BGP_STATS_MAX_AGGREGATEABLE
,
10898 BGP_STATS_AGGREGATES
,
10900 BGP_STATS_ASPATH_COUNT
,
10901 BGP_STATS_ASPATH_MAXHOPS
,
10902 BGP_STATS_ASPATH_TOTHOPS
,
10903 BGP_STATS_ASPATH_MAXSIZE
,
10904 BGP_STATS_ASPATH_TOTSIZE
,
10905 BGP_STATS_ASN_HIGHEST
,
10909 static const char *const table_stats_strs
[] = {
10910 [BGP_STATS_PREFIXES
] = "Total Prefixes",
10911 [BGP_STATS_TOTPLEN
] = "Average prefix length",
10912 [BGP_STATS_RIB
] = "Total Advertisements",
10913 [BGP_STATS_UNAGGREGATEABLE
] = "Unaggregateable prefixes",
10914 [BGP_STATS_MAX_AGGREGATEABLE
] =
10915 "Maximum aggregateable prefixes",
10916 [BGP_STATS_AGGREGATES
] = "BGP Aggregate advertisements",
10917 [BGP_STATS_SPACE
] = "Address space advertised",
10918 [BGP_STATS_ASPATH_COUNT
] = "Advertisements with paths",
10919 [BGP_STATS_ASPATH_MAXHOPS
] = "Longest AS-Path (hops)",
10920 [BGP_STATS_ASPATH_MAXSIZE
] = "Largest AS-Path (bytes)",
10921 [BGP_STATS_ASPATH_TOTHOPS
] = "Average AS-Path length (hops)",
10922 [BGP_STATS_ASPATH_TOTSIZE
] = "Average AS-Path size (bytes)",
10923 [BGP_STATS_ASN_HIGHEST
] = "Highest public ASN",
10924 [BGP_STATS_MAX
] = NULL
,
10927 struct bgp_table_stats
{
10928 struct bgp_table
*table
;
10929 unsigned long long counts
[BGP_STATS_MAX
];
10930 double total_space
;
10934 #define TALLY_SIGFIG 100000
10935 static unsigned long
10936 ravg_tally (unsigned long count
, unsigned long oldavg
, unsigned long newval
)
10938 unsigned long newtot
= (count
-1) * oldavg
+ (newval
* TALLY_SIGFIG
);
10939 unsigned long res
= (newtot
* TALLY_SIGFIG
) / count
;
10940 unsigned long ret
= newtot
/ count
;
10942 if ((res
% TALLY_SIGFIG
) > (TALLY_SIGFIG
/2))
10949 static void bgp_table_stats_rn(struct bgp_node
*rn
, struct bgp_node
*top
,
10950 struct bgp_table_stats
*ts
, unsigned int space
)
10952 struct bgp_node
*prn
= bgp_node_parent_nolock(rn
);
10953 struct bgp_path_info
*pi
;
10958 if (!bgp_node_has_bgp_path_info_data(rn
))
10961 ts
->counts
[BGP_STATS_PREFIXES
]++;
10962 ts
->counts
[BGP_STATS_TOTPLEN
] += rn
->p
.prefixlen
;
10965 ts
->counts
[BGP_STATS_AVGPLEN
]
10966 = ravg_tally (ts
->counts
[BGP_STATS_PREFIXES
],
10967 ts
->counts
[BGP_STATS_AVGPLEN
],
10971 /* check if the prefix is included by any other announcements */
10972 while (prn
&& !bgp_node_has_bgp_path_info_data(prn
))
10973 prn
= bgp_node_parent_nolock(prn
);
10975 if (prn
== NULL
|| prn
== top
) {
10976 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
10977 /* announced address space */
10979 ts
->total_space
+= pow(2.0, space
- rn
->p
.prefixlen
);
10980 } else if (bgp_node_has_bgp_path_info_data(prn
))
10981 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
10984 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
10985 ts
->counts
[BGP_STATS_RIB
]++;
10987 if (CHECK_FLAG(pi
->attr
->flag
,
10988 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)))
10989 ts
->counts
[BGP_STATS_AGGREGATES
]++;
10991 /* as-path stats */
10992 if (pi
->attr
->aspath
) {
10993 unsigned int hops
= aspath_count_hops(pi
->attr
->aspath
);
10994 unsigned int size
= aspath_size(pi
->attr
->aspath
);
10995 as_t highest
= aspath_highest(pi
->attr
->aspath
);
10997 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
10999 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
11000 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] = hops
;
11002 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
11003 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] = size
;
11005 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
11006 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
11008 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
]
11009 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
11010 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
],
11012 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
]
11013 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
11014 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
],
11017 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
11018 ts
->counts
[BGP_STATS_ASN_HIGHEST
] = highest
;
11023 static int bgp_table_stats_walker(struct thread
*t
)
11025 struct bgp_node
*rn
, *nrn
;
11026 struct bgp_node
*top
;
11027 struct bgp_table_stats
*ts
= THREAD_ARG(t
);
11028 unsigned int space
= 0;
11030 if (!(top
= bgp_table_top(ts
->table
)))
11033 switch (ts
->table
->afi
) {
11035 space
= IPV4_MAX_BITLEN
;
11038 space
= IPV6_MAX_BITLEN
;
11044 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
11046 for (rn
= top
; rn
; rn
= bgp_route_next(rn
)) {
11047 if (ts
->table
->safi
== SAFI_MPLS_VPN
) {
11048 struct bgp_table
*table
;
11050 table
= bgp_node_get_bgp_table_info(rn
);
11054 top
= bgp_table_top(table
);
11055 for (nrn
= bgp_table_top(table
); nrn
;
11056 nrn
= bgp_route_next(nrn
))
11057 bgp_table_stats_rn(nrn
, top
, ts
, space
);
11059 bgp_table_stats_rn(rn
, top
, ts
, space
);
11066 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11069 struct bgp_table_stats ts
;
11072 if (!bgp
->rib
[afi
][safi
]) {
11073 vty_out(vty
, "%% No RIB exist's for the AFI(%d)/SAFI(%d)\n",
11075 return CMD_WARNING
;
11078 vty_out(vty
, "BGP %s RIB statistics\n", get_afi_safi_str(afi
, safi
, false));
11080 /* labeled-unicast routes live in the unicast table */
11081 if (safi
== SAFI_LABELED_UNICAST
)
11082 safi
= SAFI_UNICAST
;
11084 memset(&ts
, 0, sizeof(ts
));
11085 ts
.table
= bgp
->rib
[afi
][safi
];
11086 thread_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
11088 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
11089 if (!table_stats_strs
[i
])
11094 case BGP_STATS_ASPATH_AVGHOPS
:
11095 case BGP_STATS_ASPATH_AVGSIZE
:
11096 case BGP_STATS_AVGPLEN
:
11097 vty_out (vty
, "%-30s: ", table_stats_strs
[i
]);
11098 vty_out (vty
, "%12.2f",
11099 (float)ts
.counts
[i
] / (float)TALLY_SIGFIG
);
11102 case BGP_STATS_ASPATH_TOTHOPS
:
11103 case BGP_STATS_ASPATH_TOTSIZE
:
11104 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
11105 vty_out(vty
, "%12.2f",
11107 ? (float)ts
.counts
[i
]
11109 [BGP_STATS_ASPATH_COUNT
]
11112 case BGP_STATS_TOTPLEN
:
11113 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
11114 vty_out(vty
, "%12.2f",
11116 ? (float)ts
.counts
[i
]
11118 [BGP_STATS_PREFIXES
]
11121 case BGP_STATS_SPACE
:
11122 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
11123 vty_out(vty
, "%12g\n", ts
.total_space
);
11125 if (afi
== AFI_IP6
) {
11126 vty_out(vty
, "%30s: ", "/32 equivalent ");
11127 vty_out(vty
, "%12g\n",
11128 ts
.total_space
* pow(2.0, -128 + 32));
11129 vty_out(vty
, "%30s: ", "/48 equivalent ");
11130 vty_out(vty
, "%12g\n",
11131 ts
.total_space
* pow(2.0, -128 + 48));
11133 vty_out(vty
, "%30s: ", "% announced ");
11134 vty_out(vty
, "%12.2f\n",
11135 ts
.total_space
* 100. * pow(2.0, -32));
11136 vty_out(vty
, "%30s: ", "/8 equivalent ");
11137 vty_out(vty
, "%12.2f\n",
11138 ts
.total_space
* pow(2.0, -32 + 8));
11139 vty_out(vty
, "%30s: ", "/24 equivalent ");
11140 vty_out(vty
, "%12.2f\n",
11141 ts
.total_space
* pow(2.0, -32 + 24));
11145 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
11146 vty_out(vty
, "%12llu", ts
.counts
[i
]);
11149 vty_out(vty
, "\n");
11151 return CMD_SUCCESS
;
11163 PCOUNT_PFCNT
, /* the figure we display to users */
11167 static const char *const pcount_strs
[] = {
11168 [PCOUNT_ADJ_IN
] = "Adj-in",
11169 [PCOUNT_DAMPED
] = "Damped",
11170 [PCOUNT_REMOVED
] = "Removed",
11171 [PCOUNT_HISTORY
] = "History",
11172 [PCOUNT_STALE
] = "Stale",
11173 [PCOUNT_VALID
] = "Valid",
11174 [PCOUNT_ALL
] = "All RIB",
11175 [PCOUNT_COUNTED
] = "PfxCt counted",
11176 [PCOUNT_PFCNT
] = "Useable",
11177 [PCOUNT_MAX
] = NULL
,
11180 struct peer_pcounts
{
11181 unsigned int count
[PCOUNT_MAX
];
11182 const struct peer
*peer
;
11183 const struct bgp_table
*table
;
11187 static void bgp_peer_count_proc(struct bgp_node
*rn
,
11188 struct peer_pcounts
*pc
)
11190 const struct bgp_adj_in
*ain
;
11191 const struct bgp_path_info
*pi
;
11192 const struct peer
*peer
= pc
->peer
;
11194 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
11195 if (ain
->peer
== peer
)
11196 pc
->count
[PCOUNT_ADJ_IN
]++;
11198 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
11200 if (pi
->peer
!= peer
)
11203 pc
->count
[PCOUNT_ALL
]++;
11205 if (CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
))
11206 pc
->count
[PCOUNT_DAMPED
]++;
11207 if (CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
11208 pc
->count
[PCOUNT_HISTORY
]++;
11209 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
11210 pc
->count
[PCOUNT_REMOVED
]++;
11211 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
11212 pc
->count
[PCOUNT_STALE
]++;
11213 if (CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
11214 pc
->count
[PCOUNT_VALID
]++;
11215 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
11216 pc
->count
[PCOUNT_PFCNT
]++;
11218 if (CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
11219 pc
->count
[PCOUNT_COUNTED
]++;
11220 if (CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
11222 EC_LIB_DEVELOPMENT
,
11223 "Attempting to count but flags say it is unusable");
11225 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
11227 EC_LIB_DEVELOPMENT
,
11228 "Not counted but flags say we should");
11233 static int bgp_peer_count_walker(struct thread
*t
)
11235 struct bgp_node
*rn
, *rm
;
11236 const struct bgp_table
*table
;
11237 struct peer_pcounts
*pc
= THREAD_ARG(t
);
11239 if (pc
->safi
== SAFI_MPLS_VPN
|| pc
->safi
== SAFI_ENCAP
11240 || pc
->safi
== SAFI_EVPN
) {
11241 /* Special handling for 2-level routing tables. */
11242 for (rn
= bgp_table_top(pc
->table
); rn
;
11243 rn
= bgp_route_next(rn
)) {
11244 table
= bgp_node_get_bgp_table_info(rn
);
11246 for (rm
= bgp_table_top(table
); rm
;
11247 rm
= bgp_route_next(rm
))
11248 bgp_peer_count_proc(rm
, pc
);
11251 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
))
11252 bgp_peer_count_proc(rn
, pc
);
11257 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
11258 safi_t safi
, bool use_json
)
11260 struct peer_pcounts pcounts
= {.peer
= peer
};
11262 json_object
*json
= NULL
;
11263 json_object
*json_loop
= NULL
;
11266 json
= json_object_new_object();
11267 json_loop
= json_object_new_object();
11270 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
11271 || !peer
->bgp
->rib
[afi
][safi
]) {
11273 json_object_string_add(
11275 "No such neighbor or address family");
11276 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
11277 json_object_free(json
);
11279 vty_out(vty
, "%% No such neighbor or address family\n");
11281 return CMD_WARNING
;
11284 memset(&pcounts
, 0, sizeof(pcounts
));
11285 pcounts
.peer
= peer
;
11286 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
11287 pcounts
.safi
= safi
;
11289 /* in-place call via thread subsystem so as to record execution time
11290 * stats for the thread-walk (i.e. ensure this can't be blamed on
11291 * on just vty_read()).
11293 thread_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
11296 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
11297 json_object_string_add(json
, "multiProtocol",
11298 get_afi_safi_str(afi
, safi
, true));
11299 json_object_int_add(json
, "pfxCounter",
11300 peer
->pcount
[afi
][safi
]);
11302 for (i
= 0; i
< PCOUNT_MAX
; i
++)
11303 json_object_int_add(json_loop
, pcount_strs
[i
],
11306 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
11308 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
11309 json_object_string_add(json
, "pfxctDriftFor",
11311 json_object_string_add(
11312 json
, "recommended",
11313 "Please report this bug, with the above command output");
11315 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
11316 json
, JSON_C_TO_STRING_PRETTY
));
11317 json_object_free(json
);
11321 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_HOSTNAME
)) {
11322 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
11323 peer
->hostname
, peer
->host
,
11324 get_afi_safi_str(afi
, safi
, false));
11326 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
11327 get_afi_safi_str(afi
, safi
, false));
11330 vty_out(vty
, "PfxCt: %" PRIu32
"\n", peer
->pcount
[afi
][safi
]);
11331 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
11333 for (i
= 0; i
< PCOUNT_MAX
; i
++)
11334 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
11337 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
11338 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
11340 "Please report this bug, with the above command output\n");
11344 return CMD_SUCCESS
;
11347 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
11348 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
11349 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_CMD_STR
"]] "
11350 "neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
11354 BGP_INSTANCE_HELP_STR
11357 "Detailed information on TCP and BGP neighbor connections\n"
11358 "Neighbor to display information about\n"
11359 "Neighbor to display information about\n"
11360 "Neighbor on BGP configured interface\n"
11361 "Display detailed prefix count information\n"
11364 afi_t afi
= AFI_IP6
;
11365 safi_t safi
= SAFI_UNICAST
;
11368 struct bgp
*bgp
= NULL
;
11369 bool uj
= use_json(argc
, argv
);
11374 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11377 return CMD_WARNING
;
11379 argv_find(argv
, argc
, "neighbors", &idx
);
11380 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
11382 return CMD_WARNING
;
11384 return bgp_peer_counts(vty
, peer
, afi
, safi
, uj
);
11387 #ifdef KEEP_OLD_VPN_COMMANDS
11388 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
11389 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
11390 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
11395 "Display information about all VPNv4 NLRIs\n"
11396 "Detailed information on TCP and BGP neighbor connections\n"
11397 "Neighbor to display information about\n"
11398 "Neighbor to display information about\n"
11399 "Neighbor on BGP configured interface\n"
11400 "Display detailed prefix count information\n"
11405 bool uj
= use_json(argc
, argv
);
11407 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
11409 return CMD_WARNING
;
11411 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
11414 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
11415 show_ip_bgp_vpn_all_route_prefix_cmd
,
11416 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
11421 "Display information about all VPNv4 NLRIs\n"
11422 "Network in the BGP routing table to display\n"
11423 "Network in the BGP routing table to display\n"
11427 char *network
= NULL
;
11428 struct bgp
*bgp
= bgp_get_default();
11430 vty_out(vty
, "Can't find default instance\n");
11431 return CMD_WARNING
;
11434 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
11435 network
= argv
[idx
]->arg
;
11436 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
11437 network
= argv
[idx
]->arg
;
11439 vty_out(vty
, "Unable to figure out Network\n");
11440 return CMD_WARNING
;
11443 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
11444 BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
11446 #endif /* KEEP_OLD_VPN_COMMANDS */
11448 DEFUN (show_bgp_l2vpn_evpn_route_prefix
,
11449 show_bgp_l2vpn_evpn_route_prefix_cmd
,
11450 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
11455 "Network in the BGP routing table to display\n"
11456 "Network in the BGP routing table to display\n"
11457 "Network in the BGP routing table to display\n"
11458 "Network in the BGP routing table to display\n"
11462 char *network
= NULL
;
11463 int prefix_check
= 0;
11465 if (argv_find(argv
, argc
, "A.B.C.D", &idx
) ||
11466 argv_find(argv
, argc
, "X:X::X:X", &idx
))
11467 network
= argv
[idx
]->arg
;
11468 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
) ||
11469 argv_find(argv
, argc
, "X:X::X:X/M", &idx
)) {
11470 network
= argv
[idx
]->arg
;
11473 vty_out(vty
, "Unable to figure out Network\n");
11474 return CMD_WARNING
;
11476 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
,
11477 prefix_check
, BGP_PATH_SHOW_ALL
,
11478 use_json(argc
, argv
));
11481 static void show_adj_route(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
11482 safi_t safi
, enum bgp_show_adj_route_type type
,
11483 const char *rmap_name
, bool use_json
,
11486 struct bgp_table
*table
;
11487 struct bgp_adj_in
*ain
;
11488 struct bgp_adj_out
*adj
;
11489 unsigned long output_count
;
11490 unsigned long filtered_count
;
11491 struct bgp_node
*rn
;
11497 struct update_subgroup
*subgrp
;
11498 json_object
*json_scode
= NULL
;
11499 json_object
*json_ocode
= NULL
;
11500 json_object
*json_ar
= NULL
;
11501 struct peer_af
*paf
;
11502 bool route_filtered
;
11505 json_scode
= json_object_new_object();
11506 json_ocode
= json_object_new_object();
11507 json_ar
= json_object_new_object();
11509 json_object_string_add(json_scode
, "suppressed", "s");
11510 json_object_string_add(json_scode
, "damped", "d");
11511 json_object_string_add(json_scode
, "history", "h");
11512 json_object_string_add(json_scode
, "valid", "*");
11513 json_object_string_add(json_scode
, "best", ">");
11514 json_object_string_add(json_scode
, "multipath", "=");
11515 json_object_string_add(json_scode
, "internal", "i");
11516 json_object_string_add(json_scode
, "ribFailure", "r");
11517 json_object_string_add(json_scode
, "stale", "S");
11518 json_object_string_add(json_scode
, "removed", "R");
11520 json_object_string_add(json_ocode
, "igp", "i");
11521 json_object_string_add(json_ocode
, "egp", "e");
11522 json_object_string_add(json_ocode
, "incomplete", "?");
11529 json_object_string_add(json
, "alert", "no BGP");
11530 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
11531 json_object_free(json
);
11533 vty_out(vty
, "%% No bgp\n");
11537 /* labeled-unicast routes live in the unicast table */
11538 if (safi
== SAFI_LABELED_UNICAST
)
11539 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
11541 table
= bgp
->rib
[afi
][safi
];
11543 output_count
= filtered_count
= 0;
11544 subgrp
= peer_subgroup(peer
, afi
, safi
);
11546 if (type
== bgp_show_adj_route_advertised
&& subgrp
11547 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
11549 json_object_int_add(json
, "bgpTableVersion",
11551 json_object_string_add(json
, "bgpLocalRouterId",
11552 inet_ntoa(bgp
->router_id
));
11553 json_object_int_add(json
, "defaultLocPrf",
11554 bgp
->default_local_pref
);
11555 json_object_int_add(json
, "localAS", bgp
->as
);
11556 json_object_object_add(json
, "bgpStatusCodes",
11558 json_object_object_add(json
, "bgpOriginCodes",
11560 json_object_string_add(
11561 json
, "bgpOriginatingDefaultNetwork",
11562 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
11564 vty_out(vty
, "BGP table version is %" PRIu64
11565 ", local router ID is %s, vrf id ",
11566 table
->version
, inet_ntoa(bgp
->router_id
));
11567 if (bgp
->vrf_id
== VRF_UNKNOWN
)
11568 vty_out(vty
, "%s", VRFID_NONE_STR
);
11570 vty_out(vty
, "%u", bgp
->vrf_id
);
11571 vty_out(vty
, "\n");
11572 vty_out(vty
, "Default local pref %u, ",
11573 bgp
->default_local_pref
);
11574 vty_out(vty
, "local AS %u\n", bgp
->as
);
11575 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
11576 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
11577 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
11579 vty_out(vty
, "Originating default network %s\n\n",
11580 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
11585 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
11586 if (type
== bgp_show_adj_route_received
11587 || type
== bgp_show_adj_route_filtered
) {
11588 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
11589 if (ain
->peer
!= peer
)
11594 json_object_int_add(
11595 json
, "bgpTableVersion",
11597 json_object_string_add(
11599 "bgpLocalRouterId",
11602 json_object_int_add(json
,
11604 bgp
->default_local_pref
);
11605 json_object_int_add(json
,
11606 "localAS", bgp
->as
);
11607 json_object_object_add(
11608 json
, "bgpStatusCodes",
11610 json_object_object_add(
11611 json
, "bgpOriginCodes",
11615 "BGP table version is 0, local router ID is %s, vrf id ",
11618 if (bgp
->vrf_id
== VRF_UNKNOWN
)
11624 vty_out(vty
, "\n");
11626 "Default local pref %u, ",
11627 bgp
->default_local_pref
);
11628 vty_out(vty
, "local AS %u\n",
11631 BGP_SHOW_SCODE_HEADER
);
11633 BGP_SHOW_NCODE_HEADER
);
11635 BGP_SHOW_OCODE_HEADER
);
11641 vty_out(vty
, BGP_SHOW_HEADER
);
11646 route_filtered
= false;
11648 /* Filter prefix using distribute list,
11649 * filter list or prefix list
11651 if ((bgp_input_filter(peer
, &rn
->p
, &attr
, afi
,
11652 safi
)) == FILTER_DENY
)
11653 route_filtered
= true;
11655 /* Filter prefix using route-map */
11656 ret
= bgp_input_modifier(peer
, &rn
->p
, &attr
,
11657 afi
, safi
, rmap_name
, NULL
, 0,
11660 if (type
== bgp_show_adj_route_filtered
&&
11661 !route_filtered
&& ret
!= RMAP_DENY
) {
11662 bgp_attr_undup(&attr
, ain
->attr
);
11666 if (type
== bgp_show_adj_route_received
&&
11667 (route_filtered
|| ret
== RMAP_DENY
))
11670 route_vty_out_tmp(vty
, &rn
->p
, &attr
, safi
,
11671 use_json
, json_ar
);
11672 bgp_attr_undup(&attr
, ain
->attr
);
11675 } else if (type
== bgp_show_adj_route_advertised
) {
11676 RB_FOREACH (adj
, bgp_adj_out_rb
, &rn
->adj_out
)
11677 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
11678 if (paf
->peer
!= peer
|| !adj
->attr
)
11683 json_object_int_add(
11687 json_object_string_add(
11689 "bgpLocalRouterId",
11692 json_object_int_add(
11693 json
, "defaultLocPrf",
11694 bgp
->default_local_pref
11696 json_object_int_add(
11699 json_object_object_add(
11703 json_object_object_add(
11709 "BGP table version is %" PRIu64
11710 ", local router ID is %s, vrf id ",
11723 vty_out(vty
, "\n");
11725 "Default local pref %u, ",
11726 bgp
->default_local_pref
11732 BGP_SHOW_SCODE_HEADER
);
11734 BGP_SHOW_NCODE_HEADER
);
11736 BGP_SHOW_OCODE_HEADER
);
11748 ret
= bgp_output_modifier(
11749 peer
, &rn
->p
, &attr
, afi
, safi
,
11752 if (ret
!= RMAP_DENY
) {
11753 route_vty_out_tmp(vty
, &rn
->p
,
11762 bgp_attr_undup(&attr
, adj
->attr
);
11768 json_object_object_add(json
, "advertisedRoutes", json_ar
);
11769 json_object_int_add(json
, "totalPrefixCounter", output_count
);
11770 json_object_int_add(json
, "filteredPrefixCounter",
11773 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
11774 json
, JSON_C_TO_STRING_PRETTY
));
11775 json_object_free(json
);
11776 } else if (output_count
> 0) {
11777 if (filtered_count
> 0)
11779 "\nTotal number of prefixes %ld (%ld filtered)\n",
11780 output_count
, filtered_count
);
11782 vty_out(vty
, "\nTotal number of prefixes %ld\n",
11787 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
11788 safi_t safi
, enum bgp_show_adj_route_type type
,
11789 const char *rmap_name
, bool use_json
)
11791 json_object
*json
= NULL
;
11794 json
= json_object_new_object();
11796 if (!peer
|| !peer
->afc
[afi
][safi
]) {
11798 json_object_string_add(
11800 "No such neighbor or address family");
11801 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
11802 json_object_free(json
);
11804 vty_out(vty
, "%% No such neighbor or address family\n");
11806 return CMD_WARNING
;
11809 if ((type
== bgp_show_adj_route_received
11810 || type
== bgp_show_adj_route_filtered
)
11811 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
11812 PEER_FLAG_SOFT_RECONFIG
)) {
11814 json_object_string_add(
11816 "Inbound soft reconfiguration not enabled");
11817 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
11818 json_object_free(json
);
11821 "%% Inbound soft reconfiguration not enabled\n");
11823 return CMD_WARNING
;
11826 show_adj_route(vty
, peer
, afi
, safi
, type
, rmap_name
, use_json
, json
);
11828 return CMD_SUCCESS
;
11831 DEFUN (show_ip_bgp_instance_neighbor_advertised_route
,
11832 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
11833 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
11834 "neighbors <A.B.C.D|X:X::X:X|WORD> <advertised-routes|received-routes|filtered-routes> [route-map WORD] [json]",
11838 BGP_INSTANCE_HELP_STR
11840 BGP_SAFI_WITH_LABEL_HELP_STR
11841 "Detailed information on TCP and BGP neighbor connections\n"
11842 "Neighbor to display information about\n"
11843 "Neighbor to display information about\n"
11844 "Neighbor on BGP configured interface\n"
11845 "Display the routes advertised to a BGP neighbor\n"
11846 "Display the received routes from neighbor\n"
11847 "Display the filtered routes received from neighbor\n"
11848 "Route-map to modify the attributes\n"
11849 "Name of the route map\n"
11852 afi_t afi
= AFI_IP6
;
11853 safi_t safi
= SAFI_UNICAST
;
11854 char *rmap_name
= NULL
;
11855 char *peerstr
= NULL
;
11856 struct bgp
*bgp
= NULL
;
11858 enum bgp_show_adj_route_type type
= bgp_show_adj_route_advertised
;
11860 bool uj
= use_json(argc
, argv
);
11865 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11868 return CMD_WARNING
;
11870 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11871 argv_find(argv
, argc
, "neighbors", &idx
);
11872 peerstr
= argv
[++idx
]->arg
;
11874 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
11876 return CMD_WARNING
;
11878 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
11879 type
= bgp_show_adj_route_advertised
;
11880 else if (argv_find(argv
, argc
, "received-routes", &idx
))
11881 type
= bgp_show_adj_route_received
;
11882 else if (argv_find(argv
, argc
, "filtered-routes", &idx
))
11883 type
= bgp_show_adj_route_filtered
;
11885 if (argv_find(argv
, argc
, "route-map", &idx
))
11886 rmap_name
= argv
[++idx
]->arg
;
11888 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
, uj
);
11891 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
11892 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
11893 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
11899 "Address Family modifier\n"
11900 "Detailed information on TCP and BGP neighbor connections\n"
11901 "Neighbor to display information about\n"
11902 "Neighbor to display information about\n"
11903 "Neighbor on BGP configured interface\n"
11904 "Display information received from a BGP neighbor\n"
11905 "Display the prefixlist filter\n"
11908 afi_t afi
= AFI_IP6
;
11909 safi_t safi
= SAFI_UNICAST
;
11910 char *peerstr
= NULL
;
11913 union sockunion su
;
11919 /* show [ip] bgp */
11920 if (argv_find(argv
, argc
, "ip", &idx
))
11922 /* [<ipv4|ipv6> [unicast]] */
11923 if (argv_find(argv
, argc
, "ipv4", &idx
))
11925 if (argv_find(argv
, argc
, "ipv6", &idx
))
11927 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11928 argv_find(argv
, argc
, "neighbors", &idx
);
11929 peerstr
= argv
[++idx
]->arg
;
11931 bool uj
= use_json(argc
, argv
);
11933 ret
= str2sockunion(peerstr
, &su
);
11935 peer
= peer_lookup_by_conf_if(NULL
, peerstr
);
11938 vty_out(vty
, "{}\n");
11941 "%% Malformed address or name: %s\n",
11943 return CMD_WARNING
;
11946 peer
= peer_lookup(NULL
, &su
);
11949 vty_out(vty
, "{}\n");
11951 vty_out(vty
, "No peer\n");
11952 return CMD_WARNING
;
11956 sprintf(name
, "%s.%d.%d", peer
->host
, afi
, safi
);
11957 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
11960 vty_out(vty
, "Address Family: %s\n",
11961 get_afi_safi_str(afi
, safi
, false));
11962 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
11965 vty_out(vty
, "{}\n");
11967 vty_out(vty
, "No functional output\n");
11970 return CMD_SUCCESS
;
11973 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
11974 afi_t afi
, safi_t safi
,
11975 enum bgp_show_type type
, bool use_json
)
11977 /* labeled-unicast routes live in the unicast table */
11978 if (safi
== SAFI_LABELED_UNICAST
)
11979 safi
= SAFI_UNICAST
;
11981 if (!peer
|| !peer
->afc
[afi
][safi
]) {
11983 json_object
*json_no
= NULL
;
11984 json_no
= json_object_new_object();
11985 json_object_string_add(
11986 json_no
, "warning",
11987 "No such neighbor or address family");
11988 vty_out(vty
, "%s\n",
11989 json_object_to_json_string(json_no
));
11990 json_object_free(json_no
);
11992 vty_out(vty
, "%% No such neighbor or address family\n");
11993 return CMD_WARNING
;
11996 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, use_json
);
11999 DEFUN (show_ip_bgp_flowspec_routes_detailed
,
12000 show_ip_bgp_flowspec_routes_detailed_cmd
,
12001 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" flowspec] detail [json]",
12005 BGP_INSTANCE_HELP_STR
12008 "Detailed information on flowspec entries\n"
12011 afi_t afi
= AFI_IP
;
12012 safi_t safi
= SAFI_UNICAST
;
12013 struct bgp
*bgp
= NULL
;
12015 bool uj
= use_json(argc
, argv
);
12020 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12023 return CMD_WARNING
;
12025 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_detail
, NULL
, uj
);
12028 DEFUN (show_ip_bgp_neighbor_routes
,
12029 show_ip_bgp_neighbor_routes_cmd
,
12030 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
12031 "neighbors <A.B.C.D|X:X::X:X|WORD> <flap-statistics|dampened-routes|routes> [json]",
12035 BGP_INSTANCE_HELP_STR
12037 BGP_SAFI_WITH_LABEL_HELP_STR
12038 "Detailed information on TCP and BGP neighbor connections\n"
12039 "Neighbor to display information about\n"
12040 "Neighbor to display information about\n"
12041 "Neighbor on BGP configured interface\n"
12042 "Display flap statistics of the routes learned from neighbor\n"
12043 "Display the dampened routes received from neighbor\n"
12044 "Display routes learned from neighbor\n"
12047 char *peerstr
= NULL
;
12048 struct bgp
*bgp
= NULL
;
12049 afi_t afi
= AFI_IP6
;
12050 safi_t safi
= SAFI_UNICAST
;
12052 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
12054 bool uj
= use_json(argc
, argv
);
12059 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12062 return CMD_WARNING
;
12064 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
12065 argv_find(argv
, argc
, "neighbors", &idx
);
12066 peerstr
= argv
[++idx
]->arg
;
12068 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
12070 return CMD_WARNING
;
12072 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
12073 sh_type
= bgp_show_type_flap_neighbor
;
12074 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
12075 sh_type
= bgp_show_type_damp_neighbor
;
12076 else if (argv_find(argv
, argc
, "routes", &idx
))
12077 sh_type
= bgp_show_type_neighbor
;
12079 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
12082 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
12084 struct bgp_distance
{
12085 /* Distance value for the IP source prefix. */
12088 /* Name of the access-list to be matched. */
12092 DEFUN (show_bgp_afi_vpn_rd_route
,
12093 show_bgp_afi_vpn_rd_route_cmd
,
12094 "show bgp "BGP_AFI_CMD_STR
" vpn rd ASN:NN_OR_IP-ADDRESS:NN <A.B.C.D/M|X:X::X:X/M> [json]",
12098 "Address Family modifier\n"
12099 "Display information for a route distinguisher\n"
12100 "Route Distinguisher\n"
12101 "Network in the BGP routing table to display\n"
12102 "Network in the BGP routing table to display\n"
12106 struct prefix_rd prd
;
12107 afi_t afi
= AFI_MAX
;
12110 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
12111 vty_out(vty
, "%% Malformed Address Family\n");
12112 return CMD_WARNING
;
12115 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
12117 vty_out(vty
, "%% Malformed Route Distinguisher\n");
12118 return CMD_WARNING
;
12121 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
12122 0, BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
12125 static struct bgp_distance
*bgp_distance_new(void)
12127 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
12130 static void bgp_distance_free(struct bgp_distance
*bdistance
)
12132 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
12135 static int bgp_distance_set(struct vty
*vty
, const char *distance_str
,
12136 const char *ip_str
, const char *access_list_str
)
12143 struct bgp_node
*rn
;
12144 struct bgp_distance
*bdistance
;
12146 afi
= bgp_node_afi(vty
);
12147 safi
= bgp_node_safi(vty
);
12149 ret
= str2prefix(ip_str
, &p
);
12151 vty_out(vty
, "Malformed prefix\n");
12152 return CMD_WARNING_CONFIG_FAILED
;
12155 distance
= atoi(distance_str
);
12157 /* Get BGP distance node. */
12158 rn
= bgp_node_get(bgp_distance_table
[afi
][safi
], (struct prefix
*)&p
);
12159 bdistance
= bgp_node_get_bgp_distance_info(rn
);
12161 bgp_unlock_node(rn
);
12163 bdistance
= bgp_distance_new();
12164 bgp_node_set_bgp_distance_info(rn
, bdistance
);
12167 /* Set distance value. */
12168 bdistance
->distance
= distance
;
12170 /* Reset access-list configuration. */
12171 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
12172 if (access_list_str
)
12173 bdistance
->access_list
=
12174 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
12176 return CMD_SUCCESS
;
12179 static int bgp_distance_unset(struct vty
*vty
, const char *distance_str
,
12180 const char *ip_str
, const char *access_list_str
)
12187 struct bgp_node
*rn
;
12188 struct bgp_distance
*bdistance
;
12190 afi
= bgp_node_afi(vty
);
12191 safi
= bgp_node_safi(vty
);
12193 ret
= str2prefix(ip_str
, &p
);
12195 vty_out(vty
, "Malformed prefix\n");
12196 return CMD_WARNING_CONFIG_FAILED
;
12199 rn
= bgp_node_lookup(bgp_distance_table
[afi
][safi
],
12200 (struct prefix
*)&p
);
12202 vty_out(vty
, "Can't find specified prefix\n");
12203 return CMD_WARNING_CONFIG_FAILED
;
12206 bdistance
= bgp_node_get_bgp_distance_info(rn
);
12207 distance
= atoi(distance_str
);
12209 if (bdistance
->distance
!= distance
) {
12210 vty_out(vty
, "Distance does not match configured\n");
12211 return CMD_WARNING_CONFIG_FAILED
;
12214 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
12215 bgp_distance_free(bdistance
);
12217 bgp_node_set_bgp_path_info(rn
, NULL
);
12218 bgp_unlock_node(rn
);
12219 bgp_unlock_node(rn
);
12221 return CMD_SUCCESS
;
12224 /* Apply BGP information to distance method. */
12225 uint8_t bgp_distance_apply(struct prefix
*p
, struct bgp_path_info
*pinfo
,
12226 afi_t afi
, safi_t safi
, struct bgp
*bgp
)
12228 struct bgp_node
*rn
;
12231 struct bgp_distance
*bdistance
;
12232 struct access_list
*alist
;
12233 struct bgp_static
*bgp_static
;
12238 peer
= pinfo
->peer
;
12240 if (pinfo
->attr
->distance
)
12241 return pinfo
->attr
->distance
;
12243 /* Check source address. */
12244 sockunion2hostprefix(&peer
->su
, &q
);
12245 rn
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
12247 bdistance
= bgp_node_get_bgp_distance_info(rn
);
12248 bgp_unlock_node(rn
);
12250 if (bdistance
->access_list
) {
12251 alist
= access_list_lookup(afi
, bdistance
->access_list
);
12253 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
12254 return bdistance
->distance
;
12256 return bdistance
->distance
;
12259 /* Backdoor check. */
12260 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
12262 bgp_static
= bgp_node_get_bgp_static_info(rn
);
12263 bgp_unlock_node(rn
);
12265 if (bgp_static
->backdoor
) {
12266 if (bgp
->distance_local
[afi
][safi
])
12267 return bgp
->distance_local
[afi
][safi
];
12269 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
12273 if (peer
->sort
== BGP_PEER_EBGP
) {
12274 if (bgp
->distance_ebgp
[afi
][safi
])
12275 return bgp
->distance_ebgp
[afi
][safi
];
12276 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
12278 if (bgp
->distance_ibgp
[afi
][safi
])
12279 return bgp
->distance_ibgp
[afi
][safi
];
12280 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
12284 /* If we enter `distance bgp (1-255) (1-255) (1-255)`,
12285 * we should tell ZEBRA update the routes for a specific
12286 * AFI/SAFI to reflect changes in RIB.
12288 static void bgp_announce_routes_distance_update(struct bgp
*bgp
,
12290 safi_t update_safi
)
12295 FOREACH_AFI_SAFI (afi
, safi
) {
12296 if (!bgp_fibupd_safi(safi
))
12299 if (afi
!= update_afi
&& safi
!= update_safi
)
12302 if (BGP_DEBUG(zebra
, ZEBRA
))
12304 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
12305 __func__
, afi
, safi
);
12306 bgp_zebra_announce_table(bgp
, afi
, safi
);
12310 DEFUN (bgp_distance
,
12312 "distance bgp (1-255) (1-255) (1-255)",
12313 "Define an administrative distance\n"
12315 "Distance for routes external to the AS\n"
12316 "Distance for routes internal to the AS\n"
12317 "Distance for local routes\n")
12319 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
12320 int idx_number
= 2;
12321 int idx_number_2
= 3;
12322 int idx_number_3
= 4;
12323 int distance_ebgp
= atoi(argv
[idx_number
]->arg
);
12324 int distance_ibgp
= atoi(argv
[idx_number_2
]->arg
);
12325 int distance_local
= atoi(argv
[idx_number_3
]->arg
);
12329 afi
= bgp_node_afi(vty
);
12330 safi
= bgp_node_safi(vty
);
12332 if (bgp
->distance_ebgp
[afi
][safi
] != distance_ebgp
12333 || bgp
->distance_ibgp
[afi
][safi
] != distance_ibgp
12334 || bgp
->distance_local
[afi
][safi
] != distance_local
) {
12335 bgp
->distance_ebgp
[afi
][safi
] = distance_ebgp
;
12336 bgp
->distance_ibgp
[afi
][safi
] = distance_ibgp
;
12337 bgp
->distance_local
[afi
][safi
] = distance_local
;
12338 bgp_announce_routes_distance_update(bgp
, afi
, safi
);
12340 return CMD_SUCCESS
;
12343 DEFUN (no_bgp_distance
,
12344 no_bgp_distance_cmd
,
12345 "no distance bgp [(1-255) (1-255) (1-255)]",
12347 "Define an administrative distance\n"
12349 "Distance for routes external to the AS\n"
12350 "Distance for routes internal to the AS\n"
12351 "Distance for local routes\n")
12353 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
12357 afi
= bgp_node_afi(vty
);
12358 safi
= bgp_node_safi(vty
);
12360 if (bgp
->distance_ebgp
[afi
][safi
] != 0
12361 || bgp
->distance_ibgp
[afi
][safi
] != 0
12362 || bgp
->distance_local
[afi
][safi
] != 0) {
12363 bgp
->distance_ebgp
[afi
][safi
] = 0;
12364 bgp
->distance_ibgp
[afi
][safi
] = 0;
12365 bgp
->distance_local
[afi
][safi
] = 0;
12366 bgp_announce_routes_distance_update(bgp
, afi
, safi
);
12368 return CMD_SUCCESS
;
12372 DEFUN (bgp_distance_source
,
12373 bgp_distance_source_cmd
,
12374 "distance (1-255) A.B.C.D/M",
12375 "Define an administrative distance\n"
12376 "Administrative distance\n"
12377 "IP source prefix\n")
12379 int idx_number
= 1;
12380 int idx_ipv4_prefixlen
= 2;
12381 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
12382 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
12383 return CMD_SUCCESS
;
12386 DEFUN (no_bgp_distance_source
,
12387 no_bgp_distance_source_cmd
,
12388 "no distance (1-255) A.B.C.D/M",
12390 "Define an administrative distance\n"
12391 "Administrative distance\n"
12392 "IP source prefix\n")
12394 int idx_number
= 2;
12395 int idx_ipv4_prefixlen
= 3;
12396 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
12397 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
12398 return CMD_SUCCESS
;
12401 DEFUN (bgp_distance_source_access_list
,
12402 bgp_distance_source_access_list_cmd
,
12403 "distance (1-255) A.B.C.D/M WORD",
12404 "Define an administrative distance\n"
12405 "Administrative distance\n"
12406 "IP source prefix\n"
12407 "Access list name\n")
12409 int idx_number
= 1;
12410 int idx_ipv4_prefixlen
= 2;
12412 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
12413 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
12414 return CMD_SUCCESS
;
12417 DEFUN (no_bgp_distance_source_access_list
,
12418 no_bgp_distance_source_access_list_cmd
,
12419 "no distance (1-255) A.B.C.D/M WORD",
12421 "Define an administrative distance\n"
12422 "Administrative distance\n"
12423 "IP source prefix\n"
12424 "Access list name\n")
12426 int idx_number
= 2;
12427 int idx_ipv4_prefixlen
= 3;
12429 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
12430 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
12431 return CMD_SUCCESS
;
12434 DEFUN (ipv6_bgp_distance_source
,
12435 ipv6_bgp_distance_source_cmd
,
12436 "distance (1-255) X:X::X:X/M",
12437 "Define an administrative distance\n"
12438 "Administrative distance\n"
12439 "IP source prefix\n")
12441 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, NULL
);
12442 return CMD_SUCCESS
;
12445 DEFUN (no_ipv6_bgp_distance_source
,
12446 no_ipv6_bgp_distance_source_cmd
,
12447 "no distance (1-255) X:X::X:X/M",
12449 "Define an administrative distance\n"
12450 "Administrative distance\n"
12451 "IP source prefix\n")
12453 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, NULL
);
12454 return CMD_SUCCESS
;
12457 DEFUN (ipv6_bgp_distance_source_access_list
,
12458 ipv6_bgp_distance_source_access_list_cmd
,
12459 "distance (1-255) X:X::X:X/M WORD",
12460 "Define an administrative distance\n"
12461 "Administrative distance\n"
12462 "IP source prefix\n"
12463 "Access list name\n")
12465 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, argv
[3]->arg
);
12466 return CMD_SUCCESS
;
12469 DEFUN (no_ipv6_bgp_distance_source_access_list
,
12470 no_ipv6_bgp_distance_source_access_list_cmd
,
12471 "no distance (1-255) X:X::X:X/M WORD",
12473 "Define an administrative distance\n"
12474 "Administrative distance\n"
12475 "IP source prefix\n"
12476 "Access list name\n")
12478 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, argv
[4]->arg
);
12479 return CMD_SUCCESS
;
12482 DEFUN (bgp_damp_set
,
12484 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
12485 "BGP Specific commands\n"
12486 "Enable route-flap dampening\n"
12487 "Half-life time for the penalty\n"
12488 "Value to start reusing a route\n"
12489 "Value to start suppressing a route\n"
12490 "Maximum duration to suppress a stable route\n")
12492 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
12493 int idx_half_life
= 2;
12495 int idx_suppress
= 4;
12496 int idx_max_suppress
= 5;
12497 int half
= DEFAULT_HALF_LIFE
* 60;
12498 int reuse
= DEFAULT_REUSE
;
12499 int suppress
= DEFAULT_SUPPRESS
;
12500 int max
= 4 * half
;
12503 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
12504 reuse
= atoi(argv
[idx_reuse
]->arg
);
12505 suppress
= atoi(argv
[idx_suppress
]->arg
);
12506 max
= atoi(argv
[idx_max_suppress
]->arg
) * 60;
12507 } else if (argc
== 3) {
12508 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
12513 * These can't be 0 but our SA doesn't understand the
12514 * way our cli is constructed
12518 if (suppress
< reuse
) {
12520 "Suppress value cannot be less than reuse value \n");
12524 return bgp_damp_enable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
), half
,
12525 reuse
, suppress
, max
);
12528 DEFUN (bgp_damp_unset
,
12529 bgp_damp_unset_cmd
,
12530 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
12532 "BGP Specific commands\n"
12533 "Enable route-flap dampening\n"
12534 "Half-life time for the penalty\n"
12535 "Value to start reusing a route\n"
12536 "Value to start suppressing a route\n"
12537 "Maximum duration to suppress a stable route\n")
12539 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
12540 return bgp_damp_disable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
));
12543 /* Display specified route of BGP table. */
12544 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
12545 const char *ip_str
, afi_t afi
, safi_t safi
,
12546 struct prefix_rd
*prd
, int prefix_check
)
12549 struct prefix match
;
12550 struct bgp_node
*rn
;
12551 struct bgp_node
*rm
;
12552 struct bgp_path_info
*pi
;
12553 struct bgp_path_info
*pi_temp
;
12555 struct bgp_table
*table
;
12557 /* BGP structure lookup. */
12559 bgp
= bgp_lookup_by_name(view_name
);
12561 vty_out(vty
, "%% Can't find BGP instance %s\n",
12563 return CMD_WARNING
;
12566 bgp
= bgp_get_default();
12568 vty_out(vty
, "%% No BGP process is configured\n");
12569 return CMD_WARNING
;
12573 /* Check IP address argument. */
12574 ret
= str2prefix(ip_str
, &match
);
12576 vty_out(vty
, "%% address is malformed\n");
12577 return CMD_WARNING
;
12580 match
.family
= afi2family(afi
);
12582 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
12583 || (safi
== SAFI_EVPN
)) {
12584 for (rn
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); rn
;
12585 rn
= bgp_route_next(rn
)) {
12586 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
12588 table
= bgp_node_get_bgp_table_info(rn
);
12591 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
12595 || rm
->p
.prefixlen
== match
.prefixlen
) {
12596 pi
= bgp_node_get_bgp_path_info(rm
);
12598 if (pi
->extra
&& pi
->extra
->damp_info
) {
12599 pi_temp
= pi
->next
;
12600 bgp_damp_info_free(
12601 pi
->extra
->damp_info
,
12609 bgp_unlock_node(rm
);
12612 if ((rn
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
))
12615 || rn
->p
.prefixlen
== match
.prefixlen
) {
12616 pi
= bgp_node_get_bgp_path_info(rn
);
12618 if (pi
->extra
&& pi
->extra
->damp_info
) {
12619 pi_temp
= pi
->next
;
12620 bgp_damp_info_free(
12621 pi
->extra
->damp_info
,
12629 bgp_unlock_node(rn
);
12633 return CMD_SUCCESS
;
12636 DEFUN (clear_ip_bgp_dampening
,
12637 clear_ip_bgp_dampening_cmd
,
12638 "clear ip bgp dampening",
12642 "Clear route flap dampening information\n")
12644 bgp_damp_info_clean(AFI_IP
, SAFI_UNICAST
);
12645 return CMD_SUCCESS
;
12648 DEFUN (clear_ip_bgp_dampening_prefix
,
12649 clear_ip_bgp_dampening_prefix_cmd
,
12650 "clear ip bgp dampening A.B.C.D/M",
12654 "Clear route flap dampening information\n"
12657 int idx_ipv4_prefixlen
= 4;
12658 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
12659 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
12662 DEFUN (clear_ip_bgp_dampening_address
,
12663 clear_ip_bgp_dampening_address_cmd
,
12664 "clear ip bgp dampening A.B.C.D",
12668 "Clear route flap dampening information\n"
12669 "Network to clear damping information\n")
12672 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
12673 SAFI_UNICAST
, NULL
, 0);
12676 DEFUN (clear_ip_bgp_dampening_address_mask
,
12677 clear_ip_bgp_dampening_address_mask_cmd
,
12678 "clear ip bgp dampening A.B.C.D A.B.C.D",
12682 "Clear route flap dampening information\n"
12683 "Network to clear damping information\n"
12687 int idx_ipv4_2
= 5;
12689 char prefix_str
[BUFSIZ
];
12691 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
12694 vty_out(vty
, "%% Inconsistent address and mask\n");
12695 return CMD_WARNING
;
12698 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
12702 static void show_bgp_peerhash_entry(struct hash_bucket
*bucket
, void *arg
)
12704 struct vty
*vty
= arg
;
12705 struct peer
*peer
= bucket
->data
;
12706 char buf
[SU_ADDRSTRLEN
];
12708 vty_out(vty
, "\tPeer: %s %s\n", peer
->host
,
12709 sockunion2str(&peer
->su
, buf
, sizeof(buf
)));
12712 DEFUN (show_bgp_peerhash
,
12713 show_bgp_peerhash_cmd
,
12714 "show bgp peerhash",
12717 "Display information about the BGP peerhash\n")
12719 struct list
*instances
= bm
->bgp
;
12720 struct listnode
*node
;
12723 for (ALL_LIST_ELEMENTS_RO(instances
, node
, bgp
)) {
12724 vty_out(vty
, "BGP: %s\n", bgp
->name
);
12725 hash_iterate(bgp
->peerhash
, show_bgp_peerhash_entry
,
12729 return CMD_SUCCESS
;
12732 /* also used for encap safi */
12733 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
12734 afi_t afi
, safi_t safi
)
12736 struct bgp_node
*prn
;
12737 struct bgp_node
*rn
;
12738 struct bgp_table
*table
;
12740 struct prefix_rd
*prd
;
12741 struct bgp_static
*bgp_static
;
12742 mpls_label_t label
;
12743 char buf
[SU_ADDRSTRLEN
];
12744 char rdbuf
[RD_ADDRSTRLEN
];
12746 /* Network configuration. */
12747 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
12748 prn
= bgp_route_next(prn
)) {
12749 table
= bgp_node_get_bgp_table_info(prn
);
12753 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
12754 bgp_static
= bgp_node_get_bgp_static_info(rn
);
12755 if (bgp_static
== NULL
)
12759 prd
= (struct prefix_rd
*)&prn
->p
;
12761 /* "network" configuration display. */
12762 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
12763 label
= decode_label(&bgp_static
->label
);
12765 vty_out(vty
, " network %s/%d rd %s",
12766 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
12768 p
->prefixlen
, rdbuf
);
12769 if (safi
== SAFI_MPLS_VPN
)
12770 vty_out(vty
, " label %u", label
);
12772 if (bgp_static
->rmap
.name
)
12773 vty_out(vty
, " route-map %s",
12774 bgp_static
->rmap
.name
);
12776 if (bgp_static
->backdoor
)
12777 vty_out(vty
, " backdoor");
12779 vty_out(vty
, "\n");
12784 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
12785 afi_t afi
, safi_t safi
)
12787 struct bgp_node
*prn
;
12788 struct bgp_node
*rn
;
12789 struct bgp_table
*table
;
12791 struct prefix_rd
*prd
;
12792 struct bgp_static
*bgp_static
;
12793 char buf
[PREFIX_STRLEN
* 2];
12794 char buf2
[SU_ADDRSTRLEN
];
12795 char rdbuf
[RD_ADDRSTRLEN
];
12797 /* Network configuration. */
12798 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
12799 prn
= bgp_route_next(prn
)) {
12800 table
= bgp_node_get_bgp_table_info(prn
);
12804 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
12805 bgp_static
= bgp_node_get_bgp_static_info(rn
);
12806 if (bgp_static
== NULL
)
12809 char *macrouter
= NULL
;
12812 if (bgp_static
->router_mac
)
12813 macrouter
= prefix_mac2str(
12814 bgp_static
->router_mac
, NULL
, 0);
12815 if (bgp_static
->eth_s_id
)
12816 esi
= esi2str(bgp_static
->eth_s_id
);
12818 prd
= (struct prefix_rd
*)&prn
->p
;
12820 /* "network" configuration display. */
12821 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
12822 if (p
->u
.prefix_evpn
.route_type
== 5) {
12823 char local_buf
[PREFIX_STRLEN
];
12824 uint8_t family
= is_evpn_prefix_ipaddr_v4((
12825 struct prefix_evpn
*)p
)
12829 &p
->u
.prefix_evpn
.prefix_addr
.ip
.ip
.addr
,
12830 local_buf
, PREFIX_STRLEN
);
12831 sprintf(buf
, "%s/%u", local_buf
,
12832 p
->u
.prefix_evpn
.prefix_addr
.ip_prefix_length
);
12834 prefix2str(p
, buf
, sizeof(buf
));
12837 if (bgp_static
->gatewayIp
.family
== AF_INET
12838 || bgp_static
->gatewayIp
.family
== AF_INET6
)
12839 inet_ntop(bgp_static
->gatewayIp
.family
,
12840 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
12843 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
12845 p
->u
.prefix_evpn
.prefix_addr
.eth_tag
,
12846 decode_label(&bgp_static
->label
), esi
, buf2
,
12849 XFREE(MTYPE_TMP
, macrouter
);
12850 XFREE(MTYPE_TMP
, esi
);
12855 /* Configuration of static route announcement and aggregate
12857 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12860 struct bgp_node
*rn
;
12862 struct bgp_static
*bgp_static
;
12863 struct bgp_aggregate
*bgp_aggregate
;
12864 char buf
[SU_ADDRSTRLEN
];
12866 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
12867 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
12871 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
12872 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
12876 /* Network configuration. */
12877 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
12878 rn
= bgp_route_next(rn
)) {
12879 bgp_static
= bgp_node_get_bgp_static_info(rn
);
12880 if (bgp_static
== NULL
)
12885 vty_out(vty
, " network %s/%d",
12886 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, SU_ADDRSTRLEN
),
12889 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
12890 vty_out(vty
, " label-index %u",
12891 bgp_static
->label_index
);
12893 if (bgp_static
->rmap
.name
)
12894 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
12896 if (bgp_static
->backdoor
)
12897 vty_out(vty
, " backdoor");
12899 vty_out(vty
, "\n");
12902 /* Aggregate-address configuration. */
12903 for (rn
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); rn
;
12904 rn
= bgp_route_next(rn
)) {
12905 bgp_aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
12906 if (bgp_aggregate
== NULL
)
12911 vty_out(vty
, " aggregate-address %s/%d",
12912 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, SU_ADDRSTRLEN
),
12915 if (bgp_aggregate
->as_set
)
12916 vty_out(vty
, " as-set");
12918 if (bgp_aggregate
->summary_only
)
12919 vty_out(vty
, " summary-only");
12921 if (bgp_aggregate
->rmap
.name
)
12922 vty_out(vty
, " route-map %s", bgp_aggregate
->rmap
.name
);
12924 vty_out(vty
, "\n");
12928 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12931 struct bgp_node
*rn
;
12932 struct bgp_distance
*bdistance
;
12934 /* Distance configuration. */
12935 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
12936 && bgp
->distance_local
[afi
][safi
]
12937 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
12938 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
12939 || bgp
->distance_local
[afi
][safi
]
12940 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
12941 vty_out(vty
, " distance bgp %d %d %d\n",
12942 bgp
->distance_ebgp
[afi
][safi
],
12943 bgp
->distance_ibgp
[afi
][safi
],
12944 bgp
->distance_local
[afi
][safi
]);
12947 for (rn
= bgp_table_top(bgp_distance_table
[afi
][safi
]); rn
;
12948 rn
= bgp_route_next(rn
)) {
12949 bdistance
= bgp_node_get_bgp_distance_info(rn
);
12950 if (bdistance
!= NULL
) {
12951 char buf
[PREFIX_STRLEN
];
12953 vty_out(vty
, " distance %d %s %s\n",
12954 bdistance
->distance
,
12955 prefix2str(&rn
->p
, buf
, sizeof(buf
)),
12956 bdistance
->access_list
? bdistance
->access_list
12962 /* Allocate routing table structure and install commands. */
12963 void bgp_route_init(void)
12968 /* Init BGP distance table. */
12969 FOREACH_AFI_SAFI (afi
, safi
)
12970 bgp_distance_table
[afi
][safi
] = bgp_table_init(NULL
, afi
, safi
);
12972 /* IPv4 BGP commands. */
12973 install_element(BGP_NODE
, &bgp_table_map_cmd
);
12974 install_element(BGP_NODE
, &bgp_network_cmd
);
12975 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
12977 install_element(BGP_NODE
, &aggregate_address_cmd
);
12978 install_element(BGP_NODE
, &aggregate_address_mask_cmd
);
12979 install_element(BGP_NODE
, &no_aggregate_address_cmd
);
12980 install_element(BGP_NODE
, &no_aggregate_address_mask_cmd
);
12982 /* IPv4 unicast configuration. */
12983 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
12984 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
12985 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
12987 install_element(BGP_IPV4_NODE
, &aggregate_address_cmd
);
12988 install_element(BGP_IPV4_NODE
, &aggregate_address_mask_cmd
);
12989 install_element(BGP_IPV4_NODE
, &no_aggregate_address_cmd
);
12990 install_element(BGP_IPV4_NODE
, &no_aggregate_address_mask_cmd
);
12992 /* IPv4 multicast configuration. */
12993 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
12994 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
12995 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
12996 install_element(BGP_IPV4M_NODE
, &aggregate_address_cmd
);
12997 install_element(BGP_IPV4M_NODE
, &aggregate_address_mask_cmd
);
12998 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_cmd
);
12999 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_mask_cmd
);
13001 /* IPv4 labeled-unicast configuration. */
13002 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
13003 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
13004 install_element(VIEW_NODE
, &show_ip_bgp_json_cmd
);
13005 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
13006 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
13008 install_element(VIEW_NODE
,
13009 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
13010 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
13011 install_element(VIEW_NODE
,
13012 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
13013 #ifdef KEEP_OLD_VPN_COMMANDS
13014 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
13015 #endif /* KEEP_OLD_VPN_COMMANDS */
13016 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
13017 install_element(VIEW_NODE
,
13018 &show_bgp_l2vpn_evpn_route_prefix_cmd
);
13020 /* BGP dampening clear commands */
13021 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
13022 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
13024 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
13025 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
13028 install_element(ENABLE_NODE
,
13029 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
13030 #ifdef KEEP_OLD_VPN_COMMANDS
13031 install_element(ENABLE_NODE
,
13032 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
13033 #endif /* KEEP_OLD_VPN_COMMANDS */
13035 /* New config IPv6 BGP commands. */
13036 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
13037 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
13038 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
13040 install_element(BGP_IPV6_NODE
, &ipv6_aggregate_address_cmd
);
13041 install_element(BGP_IPV6_NODE
, &no_ipv6_aggregate_address_cmd
);
13043 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
13045 install_element(BGP_NODE
, &bgp_distance_cmd
);
13046 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
13047 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
13048 install_element(BGP_NODE
, &no_bgp_distance_source_cmd
);
13049 install_element(BGP_NODE
, &bgp_distance_source_access_list_cmd
);
13050 install_element(BGP_NODE
, &no_bgp_distance_source_access_list_cmd
);
13051 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
13052 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
13053 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
13054 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_cmd
);
13055 install_element(BGP_IPV4_NODE
, &bgp_distance_source_access_list_cmd
);
13056 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_access_list_cmd
);
13057 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
13058 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
13059 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
13060 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_source_cmd
);
13061 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_access_list_cmd
);
13062 install_element(BGP_IPV4M_NODE
,
13063 &no_bgp_distance_source_access_list_cmd
);
13064 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
13065 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
13066 install_element(BGP_IPV6_NODE
, &ipv6_bgp_distance_source_cmd
);
13067 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_distance_source_cmd
);
13068 install_element(BGP_IPV6_NODE
,
13069 &ipv6_bgp_distance_source_access_list_cmd
);
13070 install_element(BGP_IPV6_NODE
,
13071 &no_ipv6_bgp_distance_source_access_list_cmd
);
13072 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
13073 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
13074 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_distance_source_cmd
);
13075 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_distance_source_cmd
);
13076 install_element(BGP_IPV6M_NODE
,
13077 &ipv6_bgp_distance_source_access_list_cmd
);
13078 install_element(BGP_IPV6M_NODE
,
13079 &no_ipv6_bgp_distance_source_access_list_cmd
);
13081 install_element(BGP_NODE
, &bgp_damp_set_cmd
);
13082 install_element(BGP_NODE
, &bgp_damp_unset_cmd
);
13083 install_element(BGP_IPV4_NODE
, &bgp_damp_set_cmd
);
13084 install_element(BGP_IPV4_NODE
, &bgp_damp_unset_cmd
);
13086 /* IPv4 Multicast Mode */
13087 install_element(BGP_IPV4M_NODE
, &bgp_damp_set_cmd
);
13088 install_element(BGP_IPV4M_NODE
, &bgp_damp_unset_cmd
);
13090 /* Large Communities */
13091 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
13092 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
13094 /* show bgp ipv4 flowspec detailed */
13095 install_element(VIEW_NODE
, &show_ip_bgp_flowspec_routes_detailed_cmd
);
13097 install_element(VIEW_NODE
, &show_bgp_peerhash_cmd
);
13100 void bgp_route_finish(void)
13105 FOREACH_AFI_SAFI (afi
, safi
) {
13106 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
13107 bgp_distance_table
[afi
][safi
] = NULL
;