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
34 #include "sockunion.h"
37 #include "workqueue.h"
41 #include "lib_errors.h"
43 #include "bgpd/bgpd.h"
44 #include "bgpd/bgp_table.h"
45 #include "bgpd/bgp_route.h"
46 #include "bgpd/bgp_attr.h"
47 #include "bgpd/bgp_debug.h"
48 #include "bgpd/bgp_errors.h"
49 #include "bgpd/bgp_aspath.h"
50 #include "bgpd/bgp_regex.h"
51 #include "bgpd/bgp_community.h"
52 #include "bgpd/bgp_ecommunity.h"
53 #include "bgpd/bgp_lcommunity.h"
54 #include "bgpd/bgp_clist.h"
55 #include "bgpd/bgp_packet.h"
56 #include "bgpd/bgp_filter.h"
57 #include "bgpd/bgp_fsm.h"
58 #include "bgpd/bgp_mplsvpn.h"
59 #include "bgpd/bgp_nexthop.h"
60 #include "bgpd/bgp_damp.h"
61 #include "bgpd/bgp_advertise.h"
62 #include "bgpd/bgp_zebra.h"
63 #include "bgpd/bgp_vty.h"
64 #include "bgpd/bgp_mpath.h"
65 #include "bgpd/bgp_nht.h"
66 #include "bgpd/bgp_updgrp.h"
67 #include "bgpd/bgp_label.h"
68 #include "bgpd/bgp_addpath.h"
69 #include "bgpd/bgp_mac.h"
72 #include "bgpd/rfapi/rfapi_backend.h"
73 #include "bgpd/rfapi/vnc_import_bgp.h"
74 #include "bgpd/rfapi/vnc_export_bgp.h"
76 #include "bgpd/bgp_encap_types.h"
77 #include "bgpd/bgp_encap_tlv.h"
78 #include "bgpd/bgp_evpn.h"
79 #include "bgpd/bgp_evpn_vty.h"
80 #include "bgpd/bgp_flowspec.h"
81 #include "bgpd/bgp_flowspec_util.h"
82 #include "bgpd/bgp_pbr.h"
84 #ifndef VTYSH_EXTRACT_PL
85 #include "bgpd/bgp_route_clippy.c"
88 /* Extern from bgp_dump.c */
89 extern const char *bgp_origin_str
[];
90 extern const char *bgp_origin_long_str
[];
93 #define PMSI_TNLTYPE_STR_NO_INFO "No info"
94 #define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
95 static const struct message bgp_pmsi_tnltype_str
[] = {
96 {PMSI_TNLTYPE_NO_INFO
, PMSI_TNLTYPE_STR_NO_INFO
},
97 {PMSI_TNLTYPE_RSVP_TE_P2MP
, "RSVP-TE P2MP"},
98 {PMSI_TNLTYPE_MLDP_P2MP
, "mLDP P2MP"},
99 {PMSI_TNLTYPE_PIM_SSM
, "PIM-SSM"},
100 {PMSI_TNLTYPE_PIM_SM
, "PIM-SM"},
101 {PMSI_TNLTYPE_PIM_BIDIR
, "PIM-BIDIR"},
102 {PMSI_TNLTYPE_INGR_REPL
, "Ingress Replication"},
103 {PMSI_TNLTYPE_MLDP_MP2MP
, "mLDP MP2MP"},
107 #define VRFID_NONE_STR "-"
109 struct bgp_node
*bgp_afi_node_get(struct bgp_table
*table
, afi_t afi
,
110 safi_t safi
, struct prefix
*p
,
111 struct prefix_rd
*prd
)
114 struct bgp_node
*prn
= NULL
;
120 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
121 || (safi
== SAFI_EVPN
)) {
122 prn
= bgp_node_get(table
, (struct prefix
*)prd
);
124 if (!bgp_node_has_bgp_path_info_data(prn
))
125 bgp_node_set_bgp_table_info(
126 prn
, bgp_table_init(table
->bgp
, afi
, safi
));
128 bgp_unlock_node(prn
);
129 table
= bgp_node_get_bgp_table_info(prn
);
132 rn
= bgp_node_get(table
, p
);
134 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
135 || (safi
== SAFI_EVPN
))
141 struct bgp_node
*bgp_afi_node_lookup(struct bgp_table
*table
, afi_t afi
,
142 safi_t safi
, struct prefix
*p
,
143 struct prefix_rd
*prd
)
146 struct bgp_node
*prn
= NULL
;
151 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
152 || (safi
== SAFI_EVPN
)) {
153 prn
= bgp_node_lookup(table
, (struct prefix
*)prd
);
157 if (!bgp_node_has_bgp_path_info_data(prn
)) {
158 bgp_unlock_node(prn
);
162 table
= bgp_node_get_bgp_table_info(prn
);
165 rn
= bgp_node_lookup(table
, p
);
170 /* Allocate bgp_path_info_extra */
171 static struct bgp_path_info_extra
*bgp_path_info_extra_new(void)
173 struct bgp_path_info_extra
*new;
174 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA
,
175 sizeof(struct bgp_path_info_extra
));
176 new->label
[0] = MPLS_INVALID_LABEL
;
178 new->bgp_fs_pbr
= list_new();
179 new->bgp_fs_iprule
= list_new();
183 void bgp_path_info_extra_free(struct bgp_path_info_extra
**extra
)
185 struct bgp_path_info_extra
*e
;
187 if (!extra
|| !*extra
)
192 bgp_damp_info_free(e
->damp_info
, 0);
196 struct bgp_path_info
*bpi
= (struct bgp_path_info
*)e
->parent
;
199 /* FIXME: since multiple e may have the same e->parent
200 * and e->parent->net is holding a refcount for each
201 * of them, we need to do some fudging here.
203 * WARNING: if bpi->net->lock drops to 0, bpi may be
204 * freed as well (because bpi->net was holding the
205 * last reference to bpi) => write after free!
209 bpi
= bgp_path_info_lock(bpi
);
210 refcount
= bpi
->net
->lock
- 1;
211 bgp_unlock_node((struct bgp_node
*)bpi
->net
);
214 bgp_path_info_unlock(bpi
);
216 bgp_path_info_unlock(e
->parent
);
221 bgp_unlock(e
->bgp_orig
);
223 if ((*extra
)->bgp_fs_iprule
)
224 list_delete(&((*extra
)->bgp_fs_iprule
));
225 if ((*extra
)->bgp_fs_pbr
)
226 list_delete(&((*extra
)->bgp_fs_pbr
));
227 XFREE(MTYPE_BGP_ROUTE_EXTRA
, *extra
);
232 /* Get bgp_path_info extra information for the given bgp_path_info, lazy
233 * allocated if required.
235 struct bgp_path_info_extra
*bgp_path_info_extra_get(struct bgp_path_info
*pi
)
238 pi
->extra
= bgp_path_info_extra_new();
242 /* Allocate new bgp info structure. */
243 struct bgp_path_info
*bgp_path_info_new(void)
245 return XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_path_info
));
248 /* Free bgp route information. */
249 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
);
257 bgp_addpath_free_info_data(&path
->tx_addpath
,
258 path
->net
? &path
->net
->tx_addpath
: NULL
);
260 peer_unlock(path
->peer
); /* bgp_path_info peer reference */
262 XFREE(MTYPE_BGP_ROUTE
, path
);
265 struct bgp_path_info
*bgp_path_info_lock(struct bgp_path_info
*path
)
271 struct bgp_path_info
*bgp_path_info_unlock(struct bgp_path_info
*path
)
273 assert(path
&& path
->lock
> 0);
276 if (path
->lock
== 0) {
278 zlog_debug ("%s: unlocked and freeing", __func__
);
279 zlog_backtrace (LOG_DEBUG
);
281 bgp_path_info_free(path
);
288 zlog_debug ("%s: unlocked to 1", __func__
);
289 zlog_backtrace (LOG_DEBUG
);
296 void bgp_path_info_add(struct bgp_node
*rn
, struct bgp_path_info
*pi
)
298 struct bgp_path_info
*top
;
300 top
= bgp_node_get_bgp_path_info(rn
);
306 bgp_node_set_bgp_path_info(rn
, pi
);
308 bgp_path_info_lock(pi
);
310 peer_lock(pi
->peer
); /* bgp_path_info peer reference */
313 /* Do the actual removal of info from RIB, for use by bgp_process
314 completion callback *only* */
315 void bgp_path_info_reap(struct bgp_node
*rn
, struct bgp_path_info
*pi
)
318 pi
->next
->prev
= pi
->prev
;
320 pi
->prev
->next
= pi
->next
;
322 bgp_node_set_bgp_path_info(rn
, pi
->next
);
324 bgp_path_info_mpath_dequeue(pi
);
325 bgp_path_info_unlock(pi
);
329 void bgp_path_info_delete(struct bgp_node
*rn
, struct bgp_path_info
*pi
)
331 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_REMOVED
);
332 /* set of previous already took care of pcount */
333 UNSET_FLAG(pi
->flags
, BGP_PATH_VALID
);
336 /* undo the effects of a previous call to bgp_path_info_delete; typically
337 called when a route is deleted and then quickly re-added before the
338 deletion has been processed */
339 void bgp_path_info_restore(struct bgp_node
*rn
, struct bgp_path_info
*pi
)
341 bgp_path_info_unset_flag(rn
, pi
, BGP_PATH_REMOVED
);
342 /* unset of previous already took care of pcount */
343 SET_FLAG(pi
->flags
, BGP_PATH_VALID
);
346 /* Adjust pcount as required */
347 static void bgp_pcount_adjust(struct bgp_node
*rn
, struct bgp_path_info
*pi
)
349 struct bgp_table
*table
;
351 assert(rn
&& bgp_node_table(rn
));
352 assert(pi
&& pi
->peer
&& pi
->peer
->bgp
);
354 table
= bgp_node_table(rn
);
356 if (pi
->peer
== pi
->peer
->bgp
->peer_self
)
359 if (!BGP_PATH_COUNTABLE(pi
)
360 && CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
362 UNSET_FLAG(pi
->flags
, BGP_PATH_COUNTED
);
364 /* slight hack, but more robust against errors. */
365 if (pi
->peer
->pcount
[table
->afi
][table
->safi
])
366 pi
->peer
->pcount
[table
->afi
][table
->safi
]--;
368 flog_err(EC_LIB_DEVELOPMENT
,
369 "Asked to decrement 0 prefix count for peer");
370 } else if (BGP_PATH_COUNTABLE(pi
)
371 && !CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
372 SET_FLAG(pi
->flags
, BGP_PATH_COUNTED
);
373 pi
->peer
->pcount
[table
->afi
][table
->safi
]++;
377 static int bgp_label_index_differs(struct bgp_path_info
*pi1
,
378 struct bgp_path_info
*pi2
)
380 return (!(pi1
->attr
->label_index
== pi2
->attr
->label_index
));
383 /* Set/unset bgp_path_info flags, adjusting any other state as needed.
384 * This is here primarily to keep prefix-count in check.
386 void bgp_path_info_set_flag(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
389 SET_FLAG(pi
->flags
, flag
);
391 /* early bath if we know it's not a flag that changes countability state
393 if (!CHECK_FLAG(flag
,
394 BGP_PATH_VALID
| BGP_PATH_HISTORY
| BGP_PATH_REMOVED
))
397 bgp_pcount_adjust(rn
, pi
);
400 void bgp_path_info_unset_flag(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
403 UNSET_FLAG(pi
->flags
, flag
);
405 /* early bath if we know it's not a flag that changes countability state
407 if (!CHECK_FLAG(flag
,
408 BGP_PATH_VALID
| BGP_PATH_HISTORY
| BGP_PATH_REMOVED
))
411 bgp_pcount_adjust(rn
, pi
);
414 /* Get MED value. If MED value is missing and "bgp bestpath
415 missing-as-worst" is specified, treat it as the worst value. */
416 static uint32_t bgp_med_value(struct attr
*attr
, struct bgp
*bgp
)
418 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
421 if (bgp_flag_check(bgp
, BGP_FLAG_MED_MISSING_AS_WORST
))
428 void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info
*pi
, char *buf
)
430 if (pi
->addpath_rx_id
)
431 sprintf(buf
, "path %s (addpath rxid %d)", pi
->peer
->host
,
434 sprintf(buf
, "path %s", pi
->peer
->host
);
437 /* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
439 static int bgp_path_info_cmp(struct bgp
*bgp
, struct bgp_path_info
*new,
440 struct bgp_path_info
*exist
, int *paths_eq
,
441 struct bgp_maxpaths_cfg
*mpath_cfg
, int debug
,
442 char *pfx_buf
, afi_t afi
, safi_t safi
)
444 struct attr
*newattr
, *existattr
;
445 bgp_peer_sort_t new_sort
;
446 bgp_peer_sort_t exist_sort
;
452 uint32_t exist_weight
;
453 uint32_t newm
, existm
;
454 struct in_addr new_id
;
455 struct in_addr exist_id
;
458 int internal_as_route
;
461 char new_buf
[PATH_ADDPATH_STR_BUFFER
];
462 char exist_buf
[PATH_ADDPATH_STR_BUFFER
];
464 uint32_t exist_mm_seq
;
472 zlog_debug("%s: new is NULL", pfx_buf
);
477 bgp_path_info_path_with_addpath_rx_str(new, new_buf
);
481 zlog_debug("%s: %s is the initial bestpath", pfx_buf
,
487 bgp_path_info_path_with_addpath_rx_str(exist
, exist_buf
);
488 zlog_debug("%s: Comparing %s flags 0x%x with %s flags 0x%x",
489 pfx_buf
, new_buf
, new->flags
, exist_buf
,
494 existattr
= exist
->attr
;
496 /* For EVPN routes, we cannot just go by local vs remote, we have to
497 * look at the MAC mobility sequence number, if present.
499 if (safi
== SAFI_EVPN
) {
500 /* This is an error condition described in RFC 7432 Section
502 * states that in this scenario "the PE MUST alert the operator"
504 * does not state what other action to take. In order to provide
506 * consistency in this scenario we are going to prefer the path
510 if (newattr
->sticky
!= existattr
->sticky
) {
512 prefix2str(&new->net
->p
, pfx_buf
,
514 * PREFIX2STR_BUFFER
);
515 bgp_path_info_path_with_addpath_rx_str(new,
517 bgp_path_info_path_with_addpath_rx_str(
521 if (newattr
->sticky
&& !existattr
->sticky
) {
524 "%s: %s wins over %s due to sticky MAC flag",
525 pfx_buf
, new_buf
, exist_buf
);
529 if (!newattr
->sticky
&& existattr
->sticky
) {
532 "%s: %s loses to %s due to sticky MAC flag",
533 pfx_buf
, new_buf
, exist_buf
);
538 new_mm_seq
= mac_mobility_seqnum(newattr
);
539 exist_mm_seq
= mac_mobility_seqnum(existattr
);
541 if (new_mm_seq
> exist_mm_seq
) {
544 "%s: %s wins over %s due to MM seq %u > %u",
545 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
550 if (new_mm_seq
< exist_mm_seq
) {
553 "%s: %s loses to %s due to MM seq %u < %u",
554 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
560 * if sequence numbers are the same path with the lowest IP
563 nh_cmp
= bgp_path_info_nexthop_cmp(new, exist
);
567 "%s: %s wins over %s due to same MM seq %u and lower IP %s",
568 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
569 inet_ntoa(new->attr
->nexthop
));
575 "%s: %s loses to %s due to same MM seq %u and higher IP %s",
576 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
577 inet_ntoa(new->attr
->nexthop
));
582 /* 1. Weight check. */
583 new_weight
= newattr
->weight
;
584 exist_weight
= existattr
->weight
;
586 if (new_weight
> exist_weight
) {
588 zlog_debug("%s: %s wins over %s due to weight %d > %d",
589 pfx_buf
, new_buf
, exist_buf
, new_weight
,
594 if (new_weight
< exist_weight
) {
596 zlog_debug("%s: %s loses to %s due to weight %d < %d",
597 pfx_buf
, new_buf
, exist_buf
, new_weight
,
602 /* 2. Local preference check. */
603 new_pref
= exist_pref
= bgp
->default_local_pref
;
605 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
606 new_pref
= newattr
->local_pref
;
607 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
608 exist_pref
= existattr
->local_pref
;
610 if (new_pref
> exist_pref
) {
613 "%s: %s wins over %s due to localpref %d > %d",
614 pfx_buf
, new_buf
, exist_buf
, new_pref
,
619 if (new_pref
< exist_pref
) {
622 "%s: %s loses to %s due to localpref %d < %d",
623 pfx_buf
, new_buf
, exist_buf
, new_pref
,
628 /* 3. Local route check. We prefer:
630 * - BGP_ROUTE_AGGREGATE
631 * - BGP_ROUTE_REDISTRIBUTE
633 if (!(new->sub_type
== BGP_ROUTE_NORMAL
||
634 new->sub_type
== BGP_ROUTE_IMPORTED
)) {
637 "%s: %s wins over %s due to preferred BGP_ROUTE type",
638 pfx_buf
, new_buf
, exist_buf
);
642 if (!(exist
->sub_type
== BGP_ROUTE_NORMAL
||
643 exist
->sub_type
== BGP_ROUTE_IMPORTED
)) {
646 "%s: %s loses to %s due to preferred BGP_ROUTE type",
647 pfx_buf
, new_buf
, exist_buf
);
651 /* 4. AS path length check. */
652 if (!bgp_flag_check(bgp
, BGP_FLAG_ASPATH_IGNORE
)) {
653 int exist_hops
= aspath_count_hops(existattr
->aspath
);
654 int exist_confeds
= aspath_count_confeds(existattr
->aspath
);
656 if (bgp_flag_check(bgp
, BGP_FLAG_ASPATH_CONFED
)) {
659 aspath_hops
= aspath_count_hops(newattr
->aspath
);
660 aspath_hops
+= aspath_count_confeds(newattr
->aspath
);
662 if (aspath_hops
< (exist_hops
+ exist_confeds
)) {
665 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
666 pfx_buf
, new_buf
, exist_buf
,
668 (exist_hops
+ exist_confeds
));
672 if (aspath_hops
> (exist_hops
+ exist_confeds
)) {
675 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
676 pfx_buf
, new_buf
, exist_buf
,
678 (exist_hops
+ exist_confeds
));
682 int newhops
= aspath_count_hops(newattr
->aspath
);
684 if (newhops
< exist_hops
) {
687 "%s: %s wins over %s due to aspath hopcount %d < %d",
688 pfx_buf
, new_buf
, exist_buf
,
689 newhops
, exist_hops
);
693 if (newhops
> exist_hops
) {
696 "%s: %s loses to %s due to aspath hopcount %d > %d",
697 pfx_buf
, new_buf
, exist_buf
,
698 newhops
, exist_hops
);
704 /* 5. Origin check. */
705 if (newattr
->origin
< existattr
->origin
) {
707 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
708 pfx_buf
, new_buf
, exist_buf
,
709 bgp_origin_long_str
[newattr
->origin
],
710 bgp_origin_long_str
[existattr
->origin
]);
714 if (newattr
->origin
> existattr
->origin
) {
716 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
717 pfx_buf
, new_buf
, exist_buf
,
718 bgp_origin_long_str
[newattr
->origin
],
719 bgp_origin_long_str
[existattr
->origin
]);
724 internal_as_route
= (aspath_count_hops(newattr
->aspath
) == 0
725 && aspath_count_hops(existattr
->aspath
) == 0);
726 confed_as_route
= (aspath_count_confeds(newattr
->aspath
) > 0
727 && aspath_count_confeds(existattr
->aspath
) > 0
728 && aspath_count_hops(newattr
->aspath
) == 0
729 && aspath_count_hops(existattr
->aspath
) == 0);
731 if (bgp_flag_check(bgp
, BGP_FLAG_ALWAYS_COMPARE_MED
)
732 || (bgp_flag_check(bgp
, BGP_FLAG_MED_CONFED
) && confed_as_route
)
733 || aspath_cmp_left(newattr
->aspath
, existattr
->aspath
)
734 || aspath_cmp_left_confed(newattr
->aspath
, existattr
->aspath
)
735 || internal_as_route
) {
736 new_med
= bgp_med_value(new->attr
, bgp
);
737 exist_med
= bgp_med_value(exist
->attr
, bgp
);
739 if (new_med
< exist_med
) {
742 "%s: %s wins over %s due to MED %d < %d",
743 pfx_buf
, new_buf
, exist_buf
, new_med
,
748 if (new_med
> exist_med
) {
751 "%s: %s loses to %s due to MED %d > %d",
752 pfx_buf
, new_buf
, exist_buf
, new_med
,
758 /* 7. Peer type check. */
759 new_sort
= new->peer
->sort
;
760 exist_sort
= exist
->peer
->sort
;
762 if (new_sort
== BGP_PEER_EBGP
763 && (exist_sort
== BGP_PEER_IBGP
|| exist_sort
== BGP_PEER_CONFED
)) {
766 "%s: %s wins over %s due to eBGP peer > iBGP peer",
767 pfx_buf
, new_buf
, exist_buf
);
771 if (exist_sort
== BGP_PEER_EBGP
772 && (new_sort
== BGP_PEER_IBGP
|| new_sort
== BGP_PEER_CONFED
)) {
775 "%s: %s loses to %s due to iBGP peer < eBGP peer",
776 pfx_buf
, new_buf
, exist_buf
);
780 /* 8. IGP metric check. */
784 newm
= new->extra
->igpmetric
;
786 existm
= exist
->extra
->igpmetric
;
791 "%s: %s wins over %s due to IGP metric %d < %d",
792 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
799 "%s: %s loses to %s due to IGP metric %d > %d",
800 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
804 /* 9. Same IGP metric. Compare the cluster list length as
805 representative of IGP hops metric. Rewrite the metric value
806 pair (newm, existm) with the cluster list length. Prefer the
807 path with smaller cluster list length. */
808 if (newm
== existm
) {
809 if (peer_sort(new->peer
) == BGP_PEER_IBGP
810 && peer_sort(exist
->peer
) == BGP_PEER_IBGP
811 && (mpath_cfg
== NULL
813 mpath_cfg
->ibgp_flags
,
814 BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN
))) {
815 newm
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
816 existm
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
821 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
822 pfx_buf
, new_buf
, exist_buf
,
830 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
831 pfx_buf
, new_buf
, exist_buf
,
838 /* 10. confed-external vs. confed-internal */
839 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
840 if (new_sort
== BGP_PEER_CONFED
841 && exist_sort
== BGP_PEER_IBGP
) {
844 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
845 pfx_buf
, new_buf
, exist_buf
);
849 if (exist_sort
== BGP_PEER_CONFED
850 && new_sort
== BGP_PEER_IBGP
) {
853 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
854 pfx_buf
, new_buf
, exist_buf
);
859 /* 11. Maximum path check. */
860 if (newm
== existm
) {
861 /* If one path has a label but the other does not, do not treat
862 * them as equals for multipath
864 if ((new->extra
&&bgp_is_valid_label(&new->extra
->label
[0]))
866 && bgp_is_valid_label(&exist
->extra
->label
[0]))) {
869 "%s: %s and %s cannot be multipath, one has a label while the other does not",
870 pfx_buf
, new_buf
, exist_buf
);
871 } else if (bgp_flag_check(bgp
,
872 BGP_FLAG_ASPATH_MULTIPATH_RELAX
)) {
875 * For the two paths, all comparison steps till IGP
877 * have succeeded - including AS_PATH hop count. Since
879 * bestpath as-path multipath-relax' knob is on, we
881 * an exact match of AS_PATH. Thus, mark the paths are
883 * That will trigger both these paths to get into the
891 "%s: %s and %s are equal via multipath-relax",
892 pfx_buf
, new_buf
, exist_buf
);
893 } else if (new->peer
->sort
== BGP_PEER_IBGP
) {
894 if (aspath_cmp(new->attr
->aspath
,
895 exist
->attr
->aspath
)) {
900 "%s: %s and %s are equal via matching aspaths",
901 pfx_buf
, new_buf
, exist_buf
);
903 } else if (new->peer
->as
== exist
->peer
->as
) {
908 "%s: %s and %s are equal via same remote-as",
909 pfx_buf
, new_buf
, exist_buf
);
913 * TODO: If unequal cost ibgp multipath is enabled we can
914 * mark the paths as equal here instead of returning
919 "%s: %s wins over %s after IGP metric comparison",
920 pfx_buf
, new_buf
, exist_buf
);
923 "%s: %s loses to %s after IGP metric comparison",
924 pfx_buf
, new_buf
, exist_buf
);
929 /* 12. If both paths are external, prefer the path that was received
930 first (the oldest one). This step minimizes route-flap, since a
931 newer path won't displace an older one, even if it was the
932 preferred route based on the additional decision criteria below. */
933 if (!bgp_flag_check(bgp
, BGP_FLAG_COMPARE_ROUTER_ID
)
934 && new_sort
== BGP_PEER_EBGP
&& exist_sort
== BGP_PEER_EBGP
) {
935 if (CHECK_FLAG(new->flags
, BGP_PATH_SELECTED
)) {
938 "%s: %s wins over %s due to oldest external",
939 pfx_buf
, new_buf
, exist_buf
);
943 if (CHECK_FLAG(exist
->flags
, BGP_PATH_SELECTED
)) {
946 "%s: %s loses to %s due to oldest external",
947 pfx_buf
, new_buf
, exist_buf
);
952 /* 13. Router-ID comparision. */
953 /* If one of the paths is "stale", the corresponding peer router-id will
954 * be 0 and would always win over the other path. If originator id is
955 * used for the comparision, it will decide which path is better.
957 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
958 new_id
.s_addr
= newattr
->originator_id
.s_addr
;
960 new_id
.s_addr
= new->peer
->remote_id
.s_addr
;
961 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
962 exist_id
.s_addr
= existattr
->originator_id
.s_addr
;
964 exist_id
.s_addr
= exist
->peer
->remote_id
.s_addr
;
966 if (ntohl(new_id
.s_addr
) < ntohl(exist_id
.s_addr
)) {
969 "%s: %s wins over %s due to Router-ID comparison",
970 pfx_buf
, new_buf
, exist_buf
);
974 if (ntohl(new_id
.s_addr
) > ntohl(exist_id
.s_addr
)) {
977 "%s: %s loses to %s due to Router-ID comparison",
978 pfx_buf
, new_buf
, exist_buf
);
982 /* 14. Cluster length comparision. */
983 new_cluster
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
984 exist_cluster
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
986 if (new_cluster
< exist_cluster
) {
989 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
990 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
995 if (new_cluster
> exist_cluster
) {
998 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
999 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
1004 /* 15. Neighbor address comparision. */
1005 /* Do this only if neither path is "stale" as stale paths do not have
1006 * valid peer information (as the connection may or may not be up).
1008 if (CHECK_FLAG(exist
->flags
, BGP_PATH_STALE
)) {
1011 "%s: %s wins over %s due to latter path being STALE",
1012 pfx_buf
, new_buf
, exist_buf
);
1016 if (CHECK_FLAG(new->flags
, BGP_PATH_STALE
)) {
1019 "%s: %s loses to %s due to former path being STALE",
1020 pfx_buf
, new_buf
, exist_buf
);
1024 /* locally configured routes to advertise do not have su_remote */
1025 if (new->peer
->su_remote
== NULL
)
1027 if (exist
->peer
->su_remote
== NULL
)
1030 ret
= sockunion_cmp(new->peer
->su_remote
, exist
->peer
->su_remote
);
1035 "%s: %s loses to %s due to Neighor IP comparison",
1036 pfx_buf
, new_buf
, exist_buf
);
1043 "%s: %s wins over %s due to Neighor IP comparison",
1044 pfx_buf
, new_buf
, exist_buf
);
1049 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1050 pfx_buf
, new_buf
, exist_buf
);
1055 /* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1056 * is preferred, or 0 if they are the same (usually will only occur if
1057 * multipath is enabled
1058 * This version is compatible with */
1059 int bgp_path_info_cmp_compatible(struct bgp
*bgp
, struct bgp_path_info
*new,
1060 struct bgp_path_info
*exist
, char *pfx_buf
,
1061 afi_t afi
, safi_t safi
)
1065 ret
= bgp_path_info_cmp(bgp
, new, exist
, &paths_eq
, NULL
, 0, pfx_buf
,
1079 static enum filter_type
bgp_input_filter(struct peer
*peer
, struct prefix
*p
,
1080 struct attr
*attr
, afi_t afi
,
1083 struct bgp_filter
*filter
;
1085 filter
= &peer
->filter
[afi
][safi
];
1087 #define FILTER_EXIST_WARN(F, f, filter) \
1088 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
1089 zlog_debug("%s: Could not find configured input %s-list %s!", \
1090 peer->host, #f, F##_IN_NAME(filter));
1092 if (DISTRIBUTE_IN_NAME(filter
)) {
1093 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1095 if (access_list_apply(DISTRIBUTE_IN(filter
), p
) == FILTER_DENY
)
1099 if (PREFIX_LIST_IN_NAME(filter
)) {
1100 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1102 if (prefix_list_apply(PREFIX_LIST_IN(filter
), p
) == PREFIX_DENY
)
1106 if (FILTER_LIST_IN_NAME(filter
)) {
1107 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1109 if (as_list_apply(FILTER_LIST_IN(filter
), attr
->aspath
)
1114 return FILTER_PERMIT
;
1115 #undef FILTER_EXIST_WARN
1118 static enum filter_type
bgp_output_filter(struct peer
*peer
, struct prefix
*p
,
1119 struct attr
*attr
, afi_t afi
,
1122 struct bgp_filter
*filter
;
1124 filter
= &peer
->filter
[afi
][safi
];
1126 #define FILTER_EXIST_WARN(F, f, filter) \
1127 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
1128 zlog_debug("%s: Could not find configured output %s-list %s!", \
1129 peer->host, #f, F##_OUT_NAME(filter));
1131 if (DISTRIBUTE_OUT_NAME(filter
)) {
1132 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1134 if (access_list_apply(DISTRIBUTE_OUT(filter
), p
) == FILTER_DENY
)
1138 if (PREFIX_LIST_OUT_NAME(filter
)) {
1139 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1141 if (prefix_list_apply(PREFIX_LIST_OUT(filter
), p
)
1146 if (FILTER_LIST_OUT_NAME(filter
)) {
1147 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1149 if (as_list_apply(FILTER_LIST_OUT(filter
), attr
->aspath
)
1154 return FILTER_PERMIT
;
1155 #undef FILTER_EXIST_WARN
1158 /* If community attribute includes no_export then return 1. */
1159 static int bgp_community_filter(struct peer
*peer
, struct attr
*attr
)
1161 if (attr
->community
) {
1162 /* NO_ADVERTISE check. */
1163 if (community_include(attr
->community
, COMMUNITY_NO_ADVERTISE
))
1166 /* NO_EXPORT check. */
1167 if (peer
->sort
== BGP_PEER_EBGP
1168 && community_include(attr
->community
, COMMUNITY_NO_EXPORT
))
1171 /* NO_EXPORT_SUBCONFED check. */
1172 if (peer
->sort
== BGP_PEER_EBGP
1173 || peer
->sort
== BGP_PEER_CONFED
)
1174 if (community_include(attr
->community
,
1175 COMMUNITY_NO_EXPORT_SUBCONFED
))
1181 /* Route reflection loop check. */
1182 static int bgp_cluster_filter(struct peer
*peer
, struct attr
*attr
)
1184 struct in_addr cluster_id
;
1186 if (attr
->cluster
) {
1187 if (peer
->bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
1188 cluster_id
= peer
->bgp
->cluster_id
;
1190 cluster_id
= peer
->bgp
->router_id
;
1192 if (cluster_loop_check(attr
->cluster
, cluster_id
))
1198 static int bgp_input_modifier(struct peer
*peer
, struct prefix
*p
,
1199 struct attr
*attr
, afi_t afi
, safi_t safi
,
1200 const char *rmap_name
)
1202 struct bgp_filter
*filter
;
1203 struct bgp_path_info rmap_path
;
1204 route_map_result_t ret
;
1205 struct route_map
*rmap
= NULL
;
1207 filter
= &peer
->filter
[afi
][safi
];
1209 /* Apply default weight value. */
1210 if (peer
->weight
[afi
][safi
])
1211 attr
->weight
= peer
->weight
[afi
][safi
];
1214 rmap
= route_map_lookup_by_name(rmap_name
);
1219 if (ROUTE_MAP_IN_NAME(filter
)) {
1220 rmap
= ROUTE_MAP_IN(filter
);
1227 /* RFC 8212 to prevent route leaks.
1228 * This specification intends to improve this situation by requiring the
1229 * explicit configuration of both BGP Import and Export Policies for any
1230 * External BGP (EBGP) session such as customers, peers, or
1231 * confederation boundaries for all enabled address families. Through
1232 * codification of the aforementioned requirement, operators will
1233 * benefit from consistent behavior across different BGP
1236 if (peer
->bgp
->ebgp_requires_policy
1237 == DEFAULT_EBGP_POLICY_ENABLED
)
1238 if (!bgp_inbound_policy_exists(peer
, filter
))
1241 /* Route map apply. */
1243 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
1244 /* Duplicate current value to new strucutre for modification. */
1245 rmap_path
.peer
= peer
;
1246 rmap_path
.attr
= attr
;
1248 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_IN
);
1250 /* Apply BGP route map to the attribute. */
1251 ret
= route_map_apply(rmap
, p
, RMAP_BGP
, &rmap_path
);
1253 peer
->rmap_type
= 0;
1255 if (ret
== RMAP_DENYMATCH
)
1261 static int bgp_output_modifier(struct peer
*peer
, struct prefix
*p
,
1262 struct attr
*attr
, afi_t afi
, safi_t safi
,
1263 const char *rmap_name
)
1265 struct bgp_path_info rmap_path
;
1266 route_map_result_t ret
;
1267 struct route_map
*rmap
= NULL
;
1271 * So if we get to this point and have no rmap_name
1272 * we want to just show the output as it currently
1278 /* Apply default weight value. */
1279 if (peer
->weight
[afi
][safi
])
1280 attr
->weight
= peer
->weight
[afi
][safi
];
1282 rmap
= route_map_lookup_by_name(rmap_name
);
1285 * If we have a route map name and we do not find
1286 * the routemap that means we have an implicit
1292 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
1293 /* Route map apply. */
1294 /* Duplicate current value to new strucutre for modification. */
1295 rmap_path
.peer
= peer
;
1296 rmap_path
.attr
= attr
;
1298 rmap_type
= peer
->rmap_type
;
1299 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1301 /* Apply BGP route map to the attribute. */
1302 ret
= route_map_apply(rmap
, p
, RMAP_BGP
, &rmap_path
);
1304 peer
->rmap_type
= rmap_type
;
1306 if (ret
== RMAP_DENYMATCH
)
1308 * caller has multiple error paths with bgp_attr_flush()
1315 /* If this is an EBGP peer with remove-private-AS */
1316 static void bgp_peer_remove_private_as(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1317 struct peer
*peer
, struct attr
*attr
)
1319 if (peer
->sort
== BGP_PEER_EBGP
1320 && (peer_af_flag_check(peer
, afi
, safi
,
1321 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1322 || peer_af_flag_check(peer
, afi
, safi
,
1323 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
)
1324 || peer_af_flag_check(peer
, afi
, safi
,
1325 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)
1326 || peer_af_flag_check(peer
, afi
, safi
,
1327 PEER_FLAG_REMOVE_PRIVATE_AS
))) {
1328 // Take action on the entire aspath
1329 if (peer_af_flag_check(peer
, afi
, safi
,
1330 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1331 || peer_af_flag_check(peer
, afi
, safi
,
1332 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)) {
1333 if (peer_af_flag_check(
1335 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
))
1336 attr
->aspath
= aspath_replace_private_asns(
1337 attr
->aspath
, bgp
->as
);
1339 // The entire aspath consists of private ASNs so create
1341 else if (aspath_private_as_check(attr
->aspath
))
1342 attr
->aspath
= aspath_empty_get();
1344 // There are some public and some private ASNs, remove
1347 attr
->aspath
= aspath_remove_private_asns(
1351 // 'all' was not specified so the entire aspath must be private
1353 // for us to do anything
1354 else if (aspath_private_as_check(attr
->aspath
)) {
1355 if (peer_af_flag_check(
1357 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
))
1358 attr
->aspath
= aspath_replace_private_asns(
1359 attr
->aspath
, bgp
->as
);
1361 attr
->aspath
= aspath_empty_get();
1366 /* If this is an EBGP peer with as-override */
1367 static void bgp_peer_as_override(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1368 struct peer
*peer
, struct attr
*attr
)
1370 if (peer
->sort
== BGP_PEER_EBGP
1371 && peer_af_flag_check(peer
, afi
, safi
, PEER_FLAG_AS_OVERRIDE
)) {
1372 if (aspath_single_asn_check(attr
->aspath
, peer
->as
))
1373 attr
->aspath
= aspath_replace_specific_asn(
1374 attr
->aspath
, peer
->as
, bgp
->as
);
1378 void bgp_attr_add_gshut_community(struct attr
*attr
)
1380 struct community
*old
;
1381 struct community
*new;
1382 struct community
*merge
;
1383 struct community
*gshut
;
1385 old
= attr
->community
;
1386 gshut
= community_str2com("graceful-shutdown");
1391 merge
= community_merge(community_dup(old
), gshut
);
1393 if (old
->refcnt
== 0)
1394 community_free(&old
);
1396 new = community_uniq_sort(merge
);
1397 community_free(&merge
);
1399 new = community_dup(gshut
);
1402 community_free(&gshut
);
1403 attr
->community
= new;
1404 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
1406 /* When we add the graceful-shutdown community we must also
1407 * lower the local-preference */
1408 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1409 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1413 static void subgroup_announce_reset_nhop(uint8_t family
, struct attr
*attr
)
1415 if (family
== AF_INET
) {
1416 attr
->nexthop
.s_addr
= 0;
1417 attr
->mp_nexthop_global_in
.s_addr
= 0;
1419 if (family
== AF_INET6
)
1420 memset(&attr
->mp_nexthop_global
, 0, IPV6_MAX_BYTELEN
);
1421 if (family
== AF_EVPN
)
1422 memset(&attr
->mp_nexthop_global_in
, 0, BGP_ATTR_NHLEN_IPV4
);
1425 int subgroup_announce_check(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
1426 struct update_subgroup
*subgrp
, struct prefix
*p
,
1429 struct bgp_filter
*filter
;
1432 struct peer
*onlypeer
;
1434 struct attr
*piattr
;
1435 char buf
[PREFIX_STRLEN
];
1441 int samepeer_safe
= 0; /* for synthetic mplsvpns routes */
1443 if (DISABLE_BGP_ANNOUNCE
)
1446 afi
= SUBGRP_AFI(subgrp
);
1447 safi
= SUBGRP_SAFI(subgrp
);
1448 peer
= SUBGRP_PEER(subgrp
);
1450 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_LONESOUL
))
1451 onlypeer
= SUBGRP_PFIRST(subgrp
)->peer
;
1454 filter
= &peer
->filter
[afi
][safi
];
1455 bgp
= SUBGRP_INST(subgrp
);
1456 piattr
= bgp_path_info_mpath_count(pi
) ? bgp_path_info_mpath_attr(pi
)
1460 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
)) && (safi
== SAFI_MPLS_VPN
)
1461 && ((pi
->type
== ZEBRA_ROUTE_BGP_DIRECT
)
1462 || (pi
->type
== ZEBRA_ROUTE_BGP_DIRECT_EXT
))) {
1465 * direct and direct_ext type routes originate internally even
1466 * though they can have peer pointers that reference other
1469 prefix2str(p
, buf
, PREFIX_STRLEN
);
1470 zlog_debug("%s: pfx %s bgp_direct->vpn route peer safe",
1476 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
))
1477 && ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_UNICAST
))
1478 && (pi
->type
== ZEBRA_ROUTE_BGP
)
1479 && (pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
1481 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1486 /* With addpath we may be asked to TX all kinds of paths so make sure
1488 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
)
1489 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)
1490 || CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
1494 /* If this is not the bestpath then check to see if there is an enabled
1496 * feature that requires us to advertise it */
1497 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
1498 if (!bgp_addpath_tx_path(peer
->addpath_type
[afi
][safi
], pi
)) {
1503 /* Aggregate-address suppress check. */
1504 if (pi
->extra
&& pi
->extra
->suppress
)
1505 if (!UNSUPPRESS_MAP_NAME(filter
)) {
1510 * If we are doing VRF 2 VRF leaking via the import
1511 * statement, we want to prevent the route going
1512 * off box as that the RT and RD created are localy
1513 * significant and globaly useless.
1515 if (safi
== SAFI_MPLS_VPN
&& pi
->extra
&& pi
->extra
->num_labels
1516 && pi
->extra
->label
[0] == BGP_PREVENT_VRF_2_VRF_LEAK
)
1519 /* If it's labeled safi, make sure the route has a valid label. */
1520 if (safi
== SAFI_LABELED_UNICAST
) {
1521 mpls_label_t label
= bgp_adv_label(rn
, pi
, peer
, afi
, safi
);
1522 if (!bgp_is_valid_label(&label
)) {
1523 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1524 zlog_debug("u%" PRIu64
":s%" PRIu64
1525 " %s/%d is filtered - no label (%p)",
1526 subgrp
->update_group
->id
, subgrp
->id
,
1527 inet_ntop(p
->family
, &p
->u
.prefix
,
1528 buf
, SU_ADDRSTRLEN
),
1529 p
->prefixlen
, &label
);
1534 /* Do not send back route to sender. */
1535 if (onlypeer
&& from
== onlypeer
) {
1539 /* Do not send the default route in the BGP table if the neighbor is
1540 * configured for default-originate */
1541 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1542 PEER_FLAG_DEFAULT_ORIGINATE
)) {
1543 if (p
->family
== AF_INET
&& p
->u
.prefix4
.s_addr
== INADDR_ANY
)
1545 else if (p
->family
== AF_INET6
&& p
->prefixlen
== 0)
1549 /* Transparency check. */
1550 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
)
1551 && CHECK_FLAG(from
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
))
1556 /* If community is not disabled check the no-export and local. */
1557 if (!transparent
&& bgp_community_filter(peer
, piattr
)) {
1558 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1560 "subgrpannouncecheck: community filter check fail");
1564 /* If the attribute has originator-id and it is same as remote
1566 if (onlypeer
&& piattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
1567 && (IPV4_ADDR_SAME(&onlypeer
->remote_id
, &piattr
->originator_id
))) {
1568 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1570 "%s [Update:SEND] %s originator-id is same as "
1573 prefix2str(p
, buf
, sizeof(buf
)));
1577 /* ORF prefix-list filter check */
1578 if (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_RM_ADV
)
1579 && (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_SM_RCV
)
1580 || CHECK_FLAG(peer
->af_cap
[afi
][safi
],
1581 PEER_CAP_ORF_PREFIX_SM_OLD_RCV
)))
1582 if (peer
->orf_plist
[afi
][safi
]) {
1583 if (prefix_list_apply(peer
->orf_plist
[afi
][safi
], p
)
1585 if (bgp_debug_update(NULL
, p
,
1586 subgrp
->update_group
, 0))
1588 "%s [Update:SEND] %s is filtered via ORF",
1596 /* Output filter check. */
1597 if (bgp_output_filter(peer
, p
, piattr
, afi
, safi
) == FILTER_DENY
) {
1598 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1599 zlog_debug("%s [Update:SEND] %s is filtered",
1600 peer
->host
, prefix2str(p
, buf
, sizeof(buf
)));
1604 #ifdef BGP_SEND_ASPATH_CHECK
1605 /* AS path loop check. */
1606 if (onlypeer
&& aspath_loop_check(piattr
->aspath
, onlypeer
->as
)) {
1607 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1609 "%s [Update:SEND] suppress announcement to peer AS %u "
1610 "that is part of AS path.",
1611 onlypeer
->host
, onlypeer
->as
);
1614 #endif /* BGP_SEND_ASPATH_CHECK */
1616 /* If we're a CONFED we need to loop check the CONFED ID too */
1617 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
1618 if (aspath_loop_check(piattr
->aspath
, bgp
->confed_id
)) {
1619 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1621 "%s [Update:SEND] suppress announcement to peer AS %u"
1623 peer
->host
, bgp
->confed_id
);
1628 /* Route-Reflect check. */
1629 if (from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1634 /* IBGP reflection check. */
1635 if (reflect
&& !samepeer_safe
) {
1636 /* A route from a Client peer. */
1637 if (CHECK_FLAG(from
->af_flags
[afi
][safi
],
1638 PEER_FLAG_REFLECTOR_CLIENT
)) {
1639 /* Reflect to all the Non-Client peers and also to the
1640 Client peers other than the originator. Originator
1642 is already done. So there is noting to do. */
1643 /* no bgp client-to-client reflection check. */
1644 if (bgp_flag_check(bgp
, BGP_FLAG_NO_CLIENT_TO_CLIENT
))
1645 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1646 PEER_FLAG_REFLECTOR_CLIENT
))
1649 /* A route from a Non-client peer. Reflect to all other
1651 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1652 PEER_FLAG_REFLECTOR_CLIENT
))
1657 /* For modify attribute, copy it to temporary structure. */
1658 bgp_attr_dup(attr
, piattr
);
1660 /* If local-preference is not set. */
1661 if ((peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
)
1662 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))) {
1663 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1664 attr
->local_pref
= bgp
->default_local_pref
;
1667 /* If originator-id is not set and the route is to be reflected,
1668 set the originator id */
1670 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)))) {
1671 IPV4_ADDR_COPY(&(attr
->originator_id
), &(from
->remote_id
));
1672 SET_FLAG(attr
->flag
, BGP_ATTR_ORIGINATOR_ID
);
1675 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
1677 if (peer
->sort
== BGP_PEER_EBGP
1678 && attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
1679 if (from
!= bgp
->peer_self
&& !transparent
1680 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1681 PEER_FLAG_MED_UNCHANGED
))
1683 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
));
1686 /* Since the nexthop attribute can vary per peer, it is not explicitly
1688 * in announce check, only certain flags and length (or number of
1690 * -- for IPv6/MP_REACH) are set here in order to guide the update
1692 * code in setting the nexthop(s) on a per peer basis in
1694 * Typically, the source nexthop in the attribute is preserved but in
1696 * scenarios where we know it will always be overwritten, we reset the
1697 * nexthop to "0" in an attempt to achieve better Update packing. An
1698 * example of this is when a prefix from each of 2 IBGP peers needs to
1700 * announced to an EBGP peer (and they have the same attributes barring
1704 SET_FLAG(attr
->rmap_change_flags
, BATTR_REFLECTED
);
1706 #define NEXTHOP_IS_V6 \
1707 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
1708 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
1709 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
1710 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
1712 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
1714 * the peer (group) is configured to receive link-local nexthop
1716 * and it is available in the prefix OR we're not reflecting the route
1718 * the peer (group) to whom we're going to announce is on a shared
1720 * and this is either a self-originated route or the peer is EBGP.
1722 if (NEXTHOP_IS_V6
) {
1723 attr
->mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
1724 if ((CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1725 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)
1726 && IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
))
1727 || (!reflect
&& peer
->shared_network
1728 && (from
== bgp
->peer_self
1729 || peer
->sort
== BGP_PEER_EBGP
))) {
1730 attr
->mp_nexthop_len
=
1731 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
;
1734 /* Clear off link-local nexthop in source, whenever it is not
1736 * ensure more prefixes share the same attribute for
1739 if (!(CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1740 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)))
1741 memset(&attr
->mp_nexthop_local
, 0, IPV6_MAX_BYTELEN
);
1744 bgp_peer_remove_private_as(bgp
, afi
, safi
, peer
, attr
);
1745 bgp_peer_as_override(bgp
, afi
, safi
, peer
, attr
);
1747 /* Route map & unsuppress-map apply. */
1748 if (ROUTE_MAP_OUT_NAME(filter
) || (pi
->extra
&& pi
->extra
->suppress
)) {
1749 struct bgp_path_info rmap_path
;
1750 struct bgp_path_info_extra dummy_rmap_path_extra
;
1751 struct attr dummy_attr
;
1753 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
1754 rmap_path
.peer
= peer
;
1755 rmap_path
.attr
= attr
;
1758 memcpy(&dummy_rmap_path_extra
, pi
->extra
,
1759 sizeof(struct bgp_path_info_extra
));
1760 rmap_path
.extra
= &dummy_rmap_path_extra
;
1763 /* don't confuse inbound and outbound setting */
1764 RESET_FLAG(attr
->rmap_change_flags
);
1767 * The route reflector is not allowed to modify the attributes
1768 * of the reflected IBGP routes unless explicitly allowed.
1770 if ((from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1771 && !bgp_flag_check(bgp
,
1772 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY
)) {
1773 bgp_attr_dup(&dummy_attr
, attr
);
1774 rmap_path
.attr
= &dummy_attr
;
1777 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1779 if (pi
->extra
&& pi
->extra
->suppress
)
1780 ret
= route_map_apply(UNSUPPRESS_MAP(filter
), p
,
1781 RMAP_BGP
, &rmap_path
);
1783 ret
= route_map_apply(ROUTE_MAP_OUT(filter
), p
,
1784 RMAP_BGP
, &rmap_path
);
1786 peer
->rmap_type
= 0;
1788 if (ret
== RMAP_DENYMATCH
) {
1789 bgp_attr_flush(attr
);
1794 /* RFC 8212 to prevent route leaks.
1795 * This specification intends to improve this situation by requiring the
1796 * explicit configuration of both BGP Import and Export Policies for any
1797 * External BGP (EBGP) session such as customers, peers, or
1798 * confederation boundaries for all enabled address families. Through
1799 * codification of the aforementioned requirement, operators will
1800 * benefit from consistent behavior across different BGP
1803 if (peer
->bgp
->ebgp_requires_policy
1804 == DEFAULT_EBGP_POLICY_ENABLED
)
1805 if (!bgp_outbound_policy_exists(peer
, filter
))
1808 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
1809 if (peer
->sort
== BGP_PEER_IBGP
1810 || peer
->sort
== BGP_PEER_CONFED
) {
1811 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1812 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1814 bgp_attr_add_gshut_community(attr
);
1818 /* After route-map has been applied, we check to see if the nexthop to
1819 * be carried in the attribute (that is used for the announcement) can
1820 * be cleared off or not. We do this in all cases where we would be
1821 * setting the nexthop to "ourselves". For IPv6, we only need to
1823 * the global nexthop here; the link-local nexthop would have been
1825 * already, and if not, it is required by the update formation code.
1826 * Also see earlier comments in this function.
1829 * If route-map has performed some operation on the nexthop or the peer
1830 * configuration says to pass it unchanged, we cannot reset the nexthop
1831 * here, so only attempt to do it if these aren't true. Note that the
1832 * route-map handler itself might have cleared the nexthop, if for
1834 * it is configured as 'peer-address'.
1836 if (!bgp_rmap_nhop_changed(attr
->rmap_change_flags
,
1837 piattr
->rmap_change_flags
)
1839 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1840 PEER_FLAG_NEXTHOP_UNCHANGED
)) {
1841 /* We can reset the nexthop, if setting (or forcing) it to
1843 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1844 PEER_FLAG_NEXTHOP_SELF
)
1845 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1846 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
1848 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1849 PEER_FLAG_FORCE_NEXTHOP_SELF
))
1850 subgroup_announce_reset_nhop(
1851 (peer_cap_enhe(peer
, afi
, safi
)
1855 } else if (peer
->sort
== BGP_PEER_EBGP
) {
1856 /* Can also reset the nexthop if announcing to EBGP, but
1858 * no peer in the subgroup is on a shared subnet.
1859 * Note: 3rd party nexthop currently implemented for
1862 if (!bgp_subgrp_multiaccess_check_v4(piattr
->nexthop
,
1864 subgroup_announce_reset_nhop(
1865 (peer_cap_enhe(peer
, afi
, safi
)
1869 } else if (CHECK_FLAG(pi
->flags
, BGP_PATH_ANNC_NH_SELF
)) {
1871 * This flag is used for leaked vpn-vrf routes
1873 int family
= p
->family
;
1875 if (peer_cap_enhe(peer
, afi
, safi
))
1878 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1880 "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
1881 __func__
, family2str(family
));
1882 subgroup_announce_reset_nhop(family
, attr
);
1885 /* If IPv6/MP and nexthop does not have any override and happens
1887 * be a link-local address, reset it so that we don't pass along
1889 * source's link-local IPv6 address to recipients who may not be
1891 * the same interface.
1893 if (p
->family
== AF_INET6
|| peer_cap_enhe(peer
, afi
, safi
)) {
1894 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
))
1895 subgroup_announce_reset_nhop(AF_INET6
, attr
);
1902 void bgp_best_selection(struct bgp
*bgp
, struct bgp_node
*rn
,
1903 struct bgp_maxpaths_cfg
*mpath_cfg
,
1904 struct bgp_path_info_pair
*result
, afi_t afi
,
1907 struct bgp_path_info
*new_select
;
1908 struct bgp_path_info
*old_select
;
1909 struct bgp_path_info
*pi
;
1910 struct bgp_path_info
*pi1
;
1911 struct bgp_path_info
*pi2
;
1912 struct bgp_path_info
*nextpi
= NULL
;
1913 int paths_eq
, do_mpath
, debug
;
1914 struct list mp_list
;
1915 char pfx_buf
[PREFIX2STR_BUFFER
];
1916 char path_buf
[PATH_ADDPATH_STR_BUFFER
];
1918 bgp_mp_list_init(&mp_list
);
1920 (mpath_cfg
->maxpaths_ebgp
> 1 || mpath_cfg
->maxpaths_ibgp
> 1);
1922 debug
= bgp_debug_bestpath(&rn
->p
);
1925 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
1927 /* bgp deterministic-med */
1929 if (bgp_flag_check(bgp
, BGP_FLAG_DETERMINISTIC_MED
)) {
1931 /* Clear BGP_PATH_DMED_SELECTED for all paths */
1932 for (pi1
= bgp_node_get_bgp_path_info(rn
); pi1
;
1934 bgp_path_info_unset_flag(rn
, pi1
,
1935 BGP_PATH_DMED_SELECTED
);
1937 for (pi1
= bgp_node_get_bgp_path_info(rn
); pi1
;
1939 if (CHECK_FLAG(pi1
->flags
, BGP_PATH_DMED_CHECK
))
1941 if (BGP_PATH_HOLDDOWN(pi1
))
1943 if (pi1
->peer
&& pi1
->peer
!= bgp
->peer_self
)
1944 if (pi1
->peer
->status
!= Established
)
1949 for (pi2
= pi1
->next
; pi2
; pi2
= pi2
->next
) {
1950 if (CHECK_FLAG(pi2
->flags
,
1951 BGP_PATH_DMED_CHECK
))
1953 if (BGP_PATH_HOLDDOWN(pi2
))
1956 && pi2
->peer
!= bgp
->peer_self
1959 PEER_STATUS_NSF_WAIT
))
1960 if (pi2
->peer
->status
1964 if (!aspath_cmp_left(pi1
->attr
->aspath
,
1966 && !aspath_cmp_left_confed(
1971 if (bgp_path_info_cmp(
1972 bgp
, pi2
, new_select
,
1973 &paths_eq
, mpath_cfg
, debug
,
1974 pfx_buf
, afi
, safi
)) {
1975 bgp_path_info_unset_flag(
1977 BGP_PATH_DMED_SELECTED
);
1981 bgp_path_info_set_flag(
1982 rn
, pi2
, BGP_PATH_DMED_CHECK
);
1985 bgp_path_info_set_flag(rn
, new_select
,
1986 BGP_PATH_DMED_CHECK
);
1987 bgp_path_info_set_flag(rn
, new_select
,
1988 BGP_PATH_DMED_SELECTED
);
1991 bgp_path_info_path_with_addpath_rx_str(
1992 new_select
, path_buf
);
1993 zlog_debug("%s: %s is the bestpath from AS %u",
1995 aspath_get_first_as(
1996 new_select
->attr
->aspath
));
2001 /* Check old selected route and new selected route. */
2004 for (pi
= bgp_node_get_bgp_path_info(rn
);
2005 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2006 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
2009 if (BGP_PATH_HOLDDOWN(pi
)) {
2010 /* reap REMOVED routes, if needs be
2011 * selected route must stay for a while longer though
2013 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
2014 && (pi
!= old_select
))
2015 bgp_path_info_reap(rn
, pi
);
2018 zlog_debug("%s: pi %p in holddown", __func__
,
2024 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2025 && !CHECK_FLAG(pi
->peer
->sflags
, PEER_STATUS_NSF_WAIT
))
2026 if (pi
->peer
->status
!= Established
) {
2030 "%s: pi %p non self peer %s not estab state",
2031 __func__
, pi
, pi
->peer
->host
);
2036 if (bgp_flag_check(bgp
, BGP_FLAG_DETERMINISTIC_MED
)
2037 && (!CHECK_FLAG(pi
->flags
, BGP_PATH_DMED_SELECTED
))) {
2038 bgp_path_info_unset_flag(rn
, pi
, BGP_PATH_DMED_CHECK
);
2040 zlog_debug("%s: pi %p dmed", __func__
, pi
);
2044 bgp_path_info_unset_flag(rn
, pi
, BGP_PATH_DMED_CHECK
);
2046 if (bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
, mpath_cfg
,
2047 debug
, pfx_buf
, afi
, safi
)) {
2052 /* Now that we know which path is the bestpath see if any of the other
2054 * qualify as multipaths
2058 bgp_path_info_path_with_addpath_rx_str(new_select
,
2061 sprintf(path_buf
, "NONE");
2063 "%s: After path selection, newbest is %s oldbest was %s",
2065 old_select
? old_select
->peer
->host
: "NONE");
2068 if (do_mpath
&& new_select
) {
2069 for (pi
= bgp_node_get_bgp_path_info(rn
);
2070 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2073 bgp_path_info_path_with_addpath_rx_str(
2076 if (pi
== new_select
) {
2079 "%s: %s is the bestpath, add to the multipath list",
2081 bgp_mp_list_add(&mp_list
, pi
);
2085 if (BGP_PATH_HOLDDOWN(pi
))
2088 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2089 && !CHECK_FLAG(pi
->peer
->sflags
,
2090 PEER_STATUS_NSF_WAIT
))
2091 if (pi
->peer
->status
!= Established
)
2094 if (!bgp_path_info_nexthop_cmp(pi
, new_select
)) {
2097 "%s: %s has the same nexthop as the bestpath, skip it",
2102 bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
,
2103 mpath_cfg
, debug
, pfx_buf
, afi
, safi
);
2108 "%s: %s is equivalent to the bestpath, add to the multipath list",
2110 bgp_mp_list_add(&mp_list
, pi
);
2115 bgp_path_info_mpath_update(rn
, new_select
, old_select
, &mp_list
,
2117 bgp_path_info_mpath_aggregate_update(new_select
, old_select
);
2118 bgp_mp_list_clear(&mp_list
);
2120 bgp_addpath_update_ids(bgp
, rn
, afi
, safi
);
2122 result
->old
= old_select
;
2123 result
->new = new_select
;
2129 * A new route/change in bestpath of an existing route. Evaluate the path
2130 * for advertisement to the subgroup.
2132 int subgroup_process_announce_selected(struct update_subgroup
*subgrp
,
2133 struct bgp_path_info
*selected
,
2134 struct bgp_node
*rn
,
2135 uint32_t addpath_tx_id
)
2138 struct peer
*onlypeer
;
2144 afi
= SUBGRP_AFI(subgrp
);
2145 safi
= SUBGRP_SAFI(subgrp
);
2146 onlypeer
= ((SUBGRP_PCOUNT(subgrp
) == 1) ? (SUBGRP_PFIRST(subgrp
))->peer
2149 if (BGP_DEBUG(update
, UPDATE_OUT
)) {
2150 char buf_prefix
[PREFIX_STRLEN
];
2151 prefix2str(p
, buf_prefix
, sizeof(buf_prefix
));
2152 zlog_debug("%s: p=%s, selected=%p", __func__
, buf_prefix
,
2156 /* First update is deferred until ORF or ROUTE-REFRESH is received */
2157 if (onlypeer
&& CHECK_FLAG(onlypeer
->af_sflags
[afi
][safi
],
2158 PEER_STATUS_ORF_WAIT_REFRESH
))
2161 memset(&attr
, 0, sizeof(struct attr
));
2162 /* It's initialized in bgp_announce_check() */
2164 /* Announcement to the subgroup. If the route is filtered withdraw it.
2167 if (subgroup_announce_check(rn
, selected
, subgrp
, p
, &attr
))
2168 bgp_adj_out_set_subgroup(rn
, subgrp
, &attr
, selected
);
2170 bgp_adj_out_unset_subgroup(rn
, subgrp
, 1,
2174 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2176 bgp_adj_out_unset_subgroup(rn
, subgrp
, 1, addpath_tx_id
);
2183 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2184 * This is called at the end of route processing.
2186 void bgp_zebra_clear_route_change_flags(struct bgp_node
*rn
)
2188 struct bgp_path_info
*pi
;
2190 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
2191 if (BGP_PATH_HOLDDOWN(pi
))
2193 UNSET_FLAG(pi
->flags
, BGP_PATH_IGP_CHANGED
);
2194 UNSET_FLAG(pi
->flags
, BGP_PATH_ATTR_CHANGED
);
2199 * Has the route changed from the RIB's perspective? This is invoked only
2200 * if the route selection returns the same best route as earlier - to
2201 * determine if we need to update zebra or not.
2203 int bgp_zebra_has_route_changed(struct bgp_node
*rn
,
2204 struct bgp_path_info
*selected
)
2206 struct bgp_path_info
*mpinfo
;
2208 /* If this is multipath, check all selected paths for any nexthop
2209 * change or attribute change. Some attribute changes (e.g., community)
2210 * aren't of relevance to the RIB, but we'll update zebra to ensure
2211 * we handle the case of BGP nexthop change. This is the behavior
2212 * when the best path has an attribute change anyway.
2214 if (CHECK_FLAG(selected
->flags
, BGP_PATH_IGP_CHANGED
)
2215 || CHECK_FLAG(selected
->flags
, BGP_PATH_MULTIPATH_CHG
))
2219 * If this is multipath, check all selected paths for any nexthop change
2221 for (mpinfo
= bgp_path_info_mpath_first(selected
); mpinfo
;
2222 mpinfo
= bgp_path_info_mpath_next(mpinfo
)) {
2223 if (CHECK_FLAG(mpinfo
->flags
, BGP_PATH_IGP_CHANGED
)
2224 || CHECK_FLAG(mpinfo
->flags
, BGP_PATH_ATTR_CHANGED
))
2228 /* Nothing has changed from the RIB's perspective. */
2232 struct bgp_process_queue
{
2234 STAILQ_HEAD(, bgp_node
) pqueue
;
2235 #define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2237 unsigned int queued
;
2241 * old_select = The old best path
2242 * new_select = the new best path
2244 * if (!old_select && new_select)
2245 * We are sending new information on.
2247 * if (old_select && new_select) {
2248 * if (new_select != old_select)
2249 * We have a new best path send a change
2251 * We've received a update with new attributes that needs
2255 * if (old_select && !new_select)
2256 * We have no eligible route that we can announce or the rn
2259 static void bgp_process_main_one(struct bgp
*bgp
, struct bgp_node
*rn
,
2260 afi_t afi
, safi_t safi
)
2262 struct bgp_path_info
*new_select
;
2263 struct bgp_path_info
*old_select
;
2264 struct bgp_path_info_pair old_and_new
;
2265 char pfx_buf
[PREFIX2STR_BUFFER
];
2268 /* Is it end of initial update? (after startup) */
2270 quagga_timestamp(3, bgp
->update_delay_zebra_resume_time
,
2271 sizeof(bgp
->update_delay_zebra_resume_time
));
2273 bgp
->main_zebra_update_hold
= 0;
2274 FOREACH_AFI_SAFI (afi
, safi
) {
2275 if (bgp_fibupd_safi(safi
))
2276 bgp_zebra_announce_table(bgp
, afi
, safi
);
2278 bgp
->main_peers_update_hold
= 0;
2280 bgp_start_routeadv(bgp
);
2284 struct prefix
*p
= &rn
->p
;
2286 debug
= bgp_debug_bestpath(&rn
->p
);
2288 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
2289 zlog_debug("%s: p=%s afi=%s, safi=%s start", __func__
, pfx_buf
,
2290 afi2str(afi
), safi2str(safi
));
2293 /* Best path selection. */
2294 bgp_best_selection(bgp
, rn
, &bgp
->maxpaths
[afi
][safi
], &old_and_new
,
2296 old_select
= old_and_new
.old
;
2297 new_select
= old_and_new
.new;
2299 /* Do we need to allocate or free labels?
2300 * Right now, since we only deal with per-prefix labels, it is not
2301 * necessary to do this upon changes to best path. Exceptions:
2302 * - label index has changed -> recalculate resulting label
2303 * - path_info sub_type changed -> switch to/from implicit-null
2304 * - no valid label (due to removed static label binding) -> get new one
2306 if (bgp
->allocate_mpls_labels
[afi
][safi
]) {
2309 || bgp_label_index_differs(new_select
, old_select
)
2310 || new_select
->sub_type
!= old_select
->sub_type
2311 || !bgp_is_valid_label(&rn
->local_label
)) {
2312 /* Enforced penultimate hop popping:
2313 * implicit-null for local routes, aggregate
2314 * and redistributed routes
2316 if (new_select
->sub_type
== BGP_ROUTE_STATIC
2317 || new_select
->sub_type
2318 == BGP_ROUTE_AGGREGATE
2319 || new_select
->sub_type
2320 == BGP_ROUTE_REDISTRIBUTE
) {
2323 BGP_NODE_REGISTERED_FOR_LABEL
))
2324 bgp_unregister_for_label(rn
);
2325 label_ntop(MPLS_LABEL_IMPLICIT_NULL
, 1,
2327 bgp_set_valid_label(&rn
->local_label
);
2329 bgp_register_for_label(rn
, new_select
);
2331 } else if (CHECK_FLAG(rn
->flags
,
2332 BGP_NODE_REGISTERED_FOR_LABEL
)) {
2333 bgp_unregister_for_label(rn
);
2335 } else if (CHECK_FLAG(rn
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
)) {
2336 bgp_unregister_for_label(rn
);
2340 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
2342 "%s: p=%s afi=%s, safi=%s, old_select=%p, new_select=%p",
2343 __func__
, pfx_buf
, afi2str(afi
), safi2str(safi
),
2344 old_select
, new_select
);
2347 /* If best route remains the same and this is not due to user-initiated
2348 * clear, see exactly what needs to be done.
2350 if (old_select
&& old_select
== new_select
2351 && !CHECK_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
)
2352 && !CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
2353 && !bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
2354 if (bgp_zebra_has_route_changed(rn
, old_select
)) {
2356 vnc_import_bgp_add_route(bgp
, p
, old_select
);
2357 vnc_import_bgp_exterior_add_route(bgp
, p
, old_select
);
2359 if (bgp_fibupd_safi(safi
)
2360 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2362 if (new_select
->type
== ZEBRA_ROUTE_BGP
2363 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2364 || new_select
->sub_type
2365 == BGP_ROUTE_IMPORTED
))
2367 bgp_zebra_announce(rn
, p
, old_select
,
2371 UNSET_FLAG(old_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
2372 bgp_zebra_clear_route_change_flags(rn
);
2374 /* If there is a change of interest to peers, reannounce the
2376 if (CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
2377 || CHECK_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
)) {
2378 group_announce_route(bgp
, afi
, safi
, rn
, new_select
);
2380 /* unicast routes must also be annouced to
2381 * labeled-unicast update-groups */
2382 if (safi
== SAFI_UNICAST
)
2383 group_announce_route(bgp
, afi
,
2384 SAFI_LABELED_UNICAST
, rn
,
2387 UNSET_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
);
2388 UNSET_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
);
2391 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2395 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2397 UNSET_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
);
2399 /* bestpath has changed; bump version */
2400 if (old_select
|| new_select
) {
2401 bgp_bump_version(rn
);
2403 if (!bgp
->t_rmap_def_originate_eval
) {
2407 update_group_refresh_default_originate_route_map
,
2408 bgp
, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER
,
2409 &bgp
->t_rmap_def_originate_eval
);
2414 bgp_path_info_unset_flag(rn
, old_select
, BGP_PATH_SELECTED
);
2417 zlog_debug("%s: setting SELECTED flag", __func__
);
2418 bgp_path_info_set_flag(rn
, new_select
, BGP_PATH_SELECTED
);
2419 bgp_path_info_unset_flag(rn
, new_select
, BGP_PATH_ATTR_CHANGED
);
2420 UNSET_FLAG(new_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
2424 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2425 if (old_select
!= new_select
) {
2427 vnc_import_bgp_exterior_del_route(bgp
, p
,
2429 vnc_import_bgp_del_route(bgp
, p
, old_select
);
2432 vnc_import_bgp_exterior_add_route(bgp
, p
,
2434 vnc_import_bgp_add_route(bgp
, p
, new_select
);
2440 group_announce_route(bgp
, afi
, safi
, rn
, new_select
);
2442 /* unicast routes must also be annouced to labeled-unicast update-groups
2444 if (safi
== SAFI_UNICAST
)
2445 group_announce_route(bgp
, afi
, SAFI_LABELED_UNICAST
, rn
,
2449 if (bgp_fibupd_safi(safi
) && (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VIEW
)
2450 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2451 if (new_select
&& new_select
->type
== ZEBRA_ROUTE_BGP
2452 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2453 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
2454 || new_select
->sub_type
== BGP_ROUTE_IMPORTED
)) {
2456 /* if this is an evpn imported type-5 prefix,
2457 * we need to withdraw the route first to clear
2458 * the nh neigh and the RMAC entry.
2461 is_route_parent_evpn(old_select
))
2462 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2464 bgp_zebra_announce(rn
, p
, new_select
, bgp
, afi
, safi
);
2466 /* Withdraw the route from the kernel. */
2467 if (old_select
&& old_select
->type
== ZEBRA_ROUTE_BGP
2468 && (old_select
->sub_type
== BGP_ROUTE_NORMAL
2469 || old_select
->sub_type
== BGP_ROUTE_AGGREGATE
2470 || old_select
->sub_type
== BGP_ROUTE_IMPORTED
))
2472 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2476 /* advertise/withdraw type-5 routes */
2477 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2478 if (advertise_type5_routes(bgp
, afi
) && new_select
&&
2479 (!new_select
->extra
|| !new_select
->extra
->parent
)) {
2481 /* apply the route-map */
2482 if (bgp
->adv_cmd_rmap
[afi
][safi
].map
) {
2485 ret
= route_map_apply(
2486 bgp
->adv_cmd_rmap
[afi
][safi
].map
,
2487 &rn
->p
, RMAP_BGP
, new_select
);
2488 if (ret
== RMAP_MATCH
)
2489 bgp_evpn_advertise_type5_route(
2490 bgp
, &rn
->p
, new_select
->attr
,
2493 bgp_evpn_advertise_type5_route(bgp
,
2499 } else if (advertise_type5_routes(bgp
, afi
) && old_select
&&
2500 (!old_select
->extra
|| !old_select
->extra
->parent
))
2501 bgp_evpn_withdraw_type5_route(bgp
, &rn
->p
, afi
, safi
);
2504 /* Clear any route change flags. */
2505 bgp_zebra_clear_route_change_flags(rn
);
2507 /* Reap old select bgp_path_info, if it has been removed */
2508 if (old_select
&& CHECK_FLAG(old_select
->flags
, BGP_PATH_REMOVED
))
2509 bgp_path_info_reap(rn
, old_select
);
2511 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2515 static wq_item_status
bgp_process_wq(struct work_queue
*wq
, void *data
)
2517 struct bgp_process_queue
*pqnode
= data
;
2518 struct bgp
*bgp
= pqnode
->bgp
;
2519 struct bgp_table
*table
;
2520 struct bgp_node
*rn
;
2523 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)) {
2524 bgp_process_main_one(bgp
, NULL
, 0, 0);
2525 /* should always have dedicated wq call */
2526 assert(STAILQ_FIRST(&pqnode
->pqueue
) == NULL
);
2530 while (!STAILQ_EMPTY(&pqnode
->pqueue
)) {
2531 rn
= STAILQ_FIRST(&pqnode
->pqueue
);
2532 STAILQ_REMOVE_HEAD(&pqnode
->pqueue
, pq
);
2533 STAILQ_NEXT(rn
, pq
) = NULL
; /* complete unlink */
2534 table
= bgp_node_table(rn
);
2535 /* note, new RNs may be added as part of processing */
2536 bgp_process_main_one(bgp
, rn
, table
->afi
, table
->safi
);
2538 bgp_unlock_node(rn
);
2539 bgp_table_unlock(table
);
2545 static void bgp_processq_del(struct work_queue
*wq
, void *data
)
2547 struct bgp_process_queue
*pqnode
= data
;
2549 bgp_unlock(pqnode
->bgp
);
2551 XFREE(MTYPE_BGP_PROCESS_QUEUE
, pqnode
);
2554 void bgp_process_queue_init(void)
2556 if (!bm
->process_main_queue
)
2557 bm
->process_main_queue
=
2558 work_queue_new(bm
->master
, "process_main_queue");
2560 bm
->process_main_queue
->spec
.workfunc
= &bgp_process_wq
;
2561 bm
->process_main_queue
->spec
.del_item_data
= &bgp_processq_del
;
2562 bm
->process_main_queue
->spec
.max_retries
= 0;
2563 bm
->process_main_queue
->spec
.hold
= 50;
2564 /* Use a higher yield value of 50ms for main queue processing */
2565 bm
->process_main_queue
->spec
.yield
= 50 * 1000L;
2568 static struct bgp_process_queue
*bgp_processq_alloc(struct bgp
*bgp
)
2570 struct bgp_process_queue
*pqnode
;
2572 pqnode
= XCALLOC(MTYPE_BGP_PROCESS_QUEUE
,
2573 sizeof(struct bgp_process_queue
));
2575 /* unlocked in bgp_processq_del */
2576 pqnode
->bgp
= bgp_lock(bgp
);
2577 STAILQ_INIT(&pqnode
->pqueue
);
2582 void bgp_process(struct bgp
*bgp
, struct bgp_node
*rn
, afi_t afi
, safi_t safi
)
2584 #define ARBITRARY_PROCESS_QLEN 10000
2585 struct work_queue
*wq
= bm
->process_main_queue
;
2586 struct bgp_process_queue
*pqnode
;
2587 int pqnode_reuse
= 0;
2589 /* already scheduled for processing? */
2590 if (CHECK_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
2596 /* Add route nodes to an existing work queue item until reaching the
2597 limit only if is from the same BGP view and it's not an EOIU marker
2599 if (work_queue_item_count(wq
)) {
2600 struct work_queue_item
*item
= work_queue_last_item(wq
);
2601 pqnode
= item
->data
;
2603 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)
2604 || pqnode
->bgp
!= bgp
2605 || pqnode
->queued
>= ARBITRARY_PROCESS_QLEN
)
2606 pqnode
= bgp_processq_alloc(bgp
);
2610 pqnode
= bgp_processq_alloc(bgp
);
2611 /* all unlocked in bgp_process_wq */
2612 bgp_table_lock(bgp_node_table(rn
));
2614 SET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2617 /* can't be enqueued twice */
2618 assert(STAILQ_NEXT(rn
, pq
) == NULL
);
2619 STAILQ_INSERT_TAIL(&pqnode
->pqueue
, rn
, pq
);
2623 work_queue_add(wq
, pqnode
);
2628 void bgp_add_eoiu_mark(struct bgp
*bgp
)
2630 struct bgp_process_queue
*pqnode
;
2632 if (bm
->process_main_queue
== NULL
)
2635 pqnode
= bgp_processq_alloc(bgp
);
2637 SET_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
);
2638 work_queue_add(bm
->process_main_queue
, pqnode
);
2641 static int bgp_maximum_prefix_restart_timer(struct thread
*thread
)
2645 peer
= THREAD_ARG(thread
);
2646 peer
->t_pmax_restart
= NULL
;
2648 if (bgp_debug_neighbor_events(peer
))
2650 "%s Maximum-prefix restart timer expired, restore peering",
2653 if ((peer_clear(peer
, NULL
) < 0) && bgp_debug_neighbor_events(peer
))
2654 zlog_debug("%s: %s peer_clear failed",
2655 __PRETTY_FUNCTION__
, peer
->host
);
2660 int bgp_maximum_prefix_overflow(struct peer
*peer
, afi_t afi
, safi_t safi
,
2664 iana_safi_t pkt_safi
;
2666 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX
))
2669 if (peer
->pcount
[afi
][safi
] > peer
->pmax
[afi
][safi
]) {
2670 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2671 PEER_STATUS_PREFIX_LIMIT
)
2676 "%%MAXPFXEXCEED: No. of %s prefix received from %s %ld exceed, "
2678 afi_safi_print(afi
, safi
), peer
->host
,
2679 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2680 SET_FLAG(peer
->af_sflags
[afi
][safi
], PEER_STATUS_PREFIX_LIMIT
);
2682 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2683 PEER_FLAG_MAX_PREFIX_WARNING
))
2686 /* Convert AFI, SAFI to values for packet. */
2687 pkt_afi
= afi_int2iana(afi
);
2688 pkt_safi
= safi_int2iana(safi
);
2692 ndata
[0] = (pkt_afi
>> 8);
2694 ndata
[2] = pkt_safi
;
2695 ndata
[3] = (peer
->pmax
[afi
][safi
] >> 24);
2696 ndata
[4] = (peer
->pmax
[afi
][safi
] >> 16);
2697 ndata
[5] = (peer
->pmax
[afi
][safi
] >> 8);
2698 ndata
[6] = (peer
->pmax
[afi
][safi
]);
2700 SET_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
);
2701 bgp_notify_send_with_data(peer
, BGP_NOTIFY_CEASE
,
2702 BGP_NOTIFY_CEASE_MAX_PREFIX
,
2706 /* Dynamic peers will just close their connection. */
2707 if (peer_dynamic_neighbor(peer
))
2710 /* restart timer start */
2711 if (peer
->pmax_restart
[afi
][safi
]) {
2712 peer
->v_pmax_restart
=
2713 peer
->pmax_restart
[afi
][safi
] * 60;
2715 if (bgp_debug_neighbor_events(peer
))
2717 "%s Maximum-prefix restart timer started for %d secs",
2718 peer
->host
, peer
->v_pmax_restart
);
2720 BGP_TIMER_ON(peer
->t_pmax_restart
,
2721 bgp_maximum_prefix_restart_timer
,
2722 peer
->v_pmax_restart
);
2727 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
2728 PEER_STATUS_PREFIX_LIMIT
);
2730 if (peer
->pcount
[afi
][safi
]
2731 > (peer
->pmax
[afi
][safi
] * peer
->pmax_threshold
[afi
][safi
] / 100)) {
2732 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2733 PEER_STATUS_PREFIX_THRESHOLD
)
2738 "%%MAXPFX: No. of %s prefix received from %s reaches %ld, max %ld",
2739 afi_safi_print(afi
, safi
), peer
->host
,
2740 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2741 SET_FLAG(peer
->af_sflags
[afi
][safi
],
2742 PEER_STATUS_PREFIX_THRESHOLD
);
2744 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
2745 PEER_STATUS_PREFIX_THRESHOLD
);
2749 /* Unconditionally remove the route from the RIB, without taking
2750 * damping into consideration (eg, because the session went down)
2752 void bgp_rib_remove(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
2753 struct peer
*peer
, afi_t afi
, safi_t safi
)
2755 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, pi
, afi
, safi
);
2757 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
2758 bgp_path_info_delete(rn
, pi
); /* keep historical info */
2760 bgp_process(peer
->bgp
, rn
, afi
, safi
);
2763 static void bgp_rib_withdraw(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
2764 struct peer
*peer
, afi_t afi
, safi_t safi
,
2765 struct prefix_rd
*prd
)
2767 /* apply dampening, if result is suppressed, we'll be retaining
2768 * the bgp_path_info in the RIB for historical reference.
2770 if (CHECK_FLAG(peer
->bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
2771 && peer
->sort
== BGP_PEER_EBGP
)
2772 if ((bgp_damp_withdraw(pi
, rn
, afi
, safi
, 0))
2773 == BGP_DAMP_SUPPRESSED
) {
2774 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, pi
, afi
,
2780 if (safi
== SAFI_MPLS_VPN
) {
2781 struct bgp_node
*prn
= NULL
;
2782 struct bgp_table
*table
= NULL
;
2784 prn
= bgp_node_get(peer
->bgp
->rib
[afi
][safi
],
2785 (struct prefix
*)prd
);
2786 if (bgp_node_has_bgp_path_info_data(prn
)) {
2787 table
= bgp_node_get_bgp_table_info(prn
);
2789 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
2790 peer
->bgp
, prd
, table
, &rn
->p
, pi
);
2792 bgp_unlock_node(prn
);
2794 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2795 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
2797 vnc_import_bgp_del_route(peer
->bgp
, &rn
->p
, pi
);
2798 vnc_import_bgp_exterior_del_route(peer
->bgp
, &rn
->p
,
2804 /* If this is an EVPN route, process for un-import. */
2805 if (safi
== SAFI_EVPN
)
2806 bgp_evpn_unimport_route(peer
->bgp
, afi
, safi
, &rn
->p
, pi
);
2808 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
2811 struct bgp_path_info
*info_make(int type
, int sub_type
, unsigned short instance
,
2812 struct peer
*peer
, struct attr
*attr
,
2813 struct bgp_node
*rn
)
2815 struct bgp_path_info
*new;
2817 /* Make new BGP info. */
2818 new = XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_path_info
));
2820 new->instance
= instance
;
2821 new->sub_type
= sub_type
;
2824 new->uptime
= bgp_clock();
2829 static void overlay_index_update(struct attr
*attr
,
2830 struct eth_segment_id
*eth_s_id
,
2831 union gw_addr
*gw_ip
)
2836 if (eth_s_id
== NULL
) {
2837 memset(&(attr
->evpn_overlay
.eth_s_id
), 0,
2838 sizeof(struct eth_segment_id
));
2840 memcpy(&(attr
->evpn_overlay
.eth_s_id
), eth_s_id
,
2841 sizeof(struct eth_segment_id
));
2843 if (gw_ip
== NULL
) {
2844 memset(&(attr
->evpn_overlay
.gw_ip
), 0, sizeof(union gw_addr
));
2846 memcpy(&(attr
->evpn_overlay
.gw_ip
), gw_ip
,
2847 sizeof(union gw_addr
));
2851 static bool overlay_index_equal(afi_t afi
, struct bgp_path_info
*path
,
2852 struct eth_segment_id
*eth_s_id
,
2853 union gw_addr
*gw_ip
)
2855 struct eth_segment_id
*path_eth_s_id
, *path_eth_s_id_remote
;
2856 union gw_addr
*path_gw_ip
, *path_gw_ip_remote
;
2858 struct eth_segment_id esi
;
2862 if (afi
!= AFI_L2VPN
)
2865 memset(&temp
, 0, sizeof(temp
));
2866 path_eth_s_id
= &temp
.esi
;
2867 path_gw_ip
= &temp
.ip
;
2869 if (eth_s_id
== NULL
&& gw_ip
== NULL
)
2872 path_eth_s_id
= &(path
->attr
->evpn_overlay
.eth_s_id
);
2873 path_gw_ip
= &(path
->attr
->evpn_overlay
.gw_ip
);
2876 if (gw_ip
== NULL
) {
2877 memset(&temp
, 0, sizeof(temp
));
2878 path_gw_ip_remote
= &temp
.ip
;
2880 path_gw_ip_remote
= gw_ip
;
2882 if (eth_s_id
== NULL
) {
2883 memset(&temp
, 0, sizeof(temp
));
2884 path_eth_s_id_remote
= &temp
.esi
;
2886 path_eth_s_id_remote
= eth_s_id
;
2888 if (!memcmp(path_gw_ip
, path_gw_ip_remote
, sizeof(union gw_addr
)))
2891 return !memcmp(path_eth_s_id
, path_eth_s_id_remote
,
2892 sizeof(struct eth_segment_id
));
2895 /* Check if received nexthop is valid or not. */
2896 static int bgp_update_martian_nexthop(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
2901 /* Only validated for unicast and multicast currently. */
2902 /* Also valid for EVPN where the nexthop is an IP address. */
2903 if (safi
!= SAFI_UNICAST
&& safi
!= SAFI_MULTICAST
&& safi
!= SAFI_EVPN
)
2906 /* If NEXT_HOP is present, validate it. */
2907 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
2908 if (attr
->nexthop
.s_addr
== 0
2909 || IPV4_CLASS_DE(ntohl(attr
->nexthop
.s_addr
))
2910 || bgp_nexthop_self(bgp
, attr
->nexthop
))
2914 /* If MP_NEXTHOP is present, validate it. */
2915 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
2916 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
2917 * it is not an IPv6 link-local address.
2919 if (attr
->mp_nexthop_len
) {
2920 switch (attr
->mp_nexthop_len
) {
2921 case BGP_ATTR_NHLEN_IPV4
:
2922 case BGP_ATTR_NHLEN_VPNV4
:
2923 ret
= (attr
->mp_nexthop_global_in
.s_addr
== 0
2924 || IPV4_CLASS_DE(ntohl(
2925 attr
->mp_nexthop_global_in
.s_addr
))
2926 || bgp_nexthop_self(bgp
,
2927 attr
->mp_nexthop_global_in
));
2930 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
2931 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
2932 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
2933 ret
= (IN6_IS_ADDR_UNSPECIFIED(&attr
->mp_nexthop_global
)
2934 || IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
2935 || IN6_IS_ADDR_MULTICAST(
2936 &attr
->mp_nexthop_global
));
2948 int bgp_update(struct peer
*peer
, struct prefix
*p
, uint32_t addpath_id
,
2949 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
2950 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
2951 uint32_t num_labels
, int soft_reconfig
,
2952 struct bgp_route_evpn
*evpn
)
2955 int aspath_loop_count
= 0;
2956 struct bgp_node
*rn
;
2958 struct attr new_attr
;
2959 struct attr
*attr_new
;
2960 struct bgp_path_info
*pi
;
2961 struct bgp_path_info
*new;
2962 struct bgp_path_info_extra
*extra
;
2964 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
2966 int do_loop_check
= 1;
2967 int has_valid_label
= 0;
2969 int vnc_implicit_withdraw
= 0;
2973 memset(&new_attr
, 0, sizeof(struct attr
));
2974 new_attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
2975 new_attr
.label
= MPLS_INVALID_LABEL
;
2978 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
2979 /* TODO: Check to see if we can get rid of "is_valid_label" */
2980 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
2981 has_valid_label
= (num_labels
> 0) ? 1 : 0;
2983 has_valid_label
= bgp_is_valid_label(label
);
2985 /* When peer's soft reconfiguration enabled. Record input packet in
2988 && CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
2989 && peer
!= bgp
->peer_self
)
2990 bgp_adj_in_set(rn
, peer
, attr
, addpath_id
);
2992 /* Check previously received route. */
2993 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
2994 if (pi
->peer
== peer
&& pi
->type
== type
2995 && pi
->sub_type
== sub_type
2996 && pi
->addpath_rx_id
== addpath_id
)
2999 /* AS path local-as loop check. */
3000 if (peer
->change_local_as
) {
3001 if (peer
->allowas_in
[afi
][safi
])
3002 aspath_loop_count
= peer
->allowas_in
[afi
][safi
];
3003 else if (!CHECK_FLAG(peer
->flags
,
3004 PEER_FLAG_LOCAL_AS_NO_PREPEND
))
3005 aspath_loop_count
= 1;
3007 if (aspath_loop_check(attr
->aspath
, peer
->change_local_as
)
3008 > aspath_loop_count
) {
3009 reason
= "as-path contains our own AS;";
3014 /* If the peer is configured for "allowas-in origin" and the last ASN in
3016 * as-path is our ASN then we do not need to call aspath_loop_check
3018 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN_ORIGIN
))
3019 if (aspath_get_last_as(attr
->aspath
) == bgp
->as
)
3022 /* AS path loop check. */
3023 if (do_loop_check
) {
3024 if (aspath_loop_check(attr
->aspath
, bgp
->as
)
3025 > peer
->allowas_in
[afi
][safi
]
3026 || (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)
3027 && aspath_loop_check(attr
->aspath
, bgp
->confed_id
)
3028 > peer
->allowas_in
[afi
][safi
])) {
3029 reason
= "as-path contains our own AS;";
3034 /* Route reflector originator ID check. */
3035 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
3036 && IPV4_ADDR_SAME(&bgp
->router_id
, &attr
->originator_id
)) {
3037 reason
= "originator is us;";
3041 /* Route reflector cluster ID check. */
3042 if (bgp_cluster_filter(peer
, attr
)) {
3043 reason
= "reflected from the same cluster;";
3047 /* Apply incoming filter. */
3048 if (bgp_input_filter(peer
, p
, attr
, afi
, safi
) == FILTER_DENY
) {
3053 bgp_attr_dup(&new_attr
, attr
);
3055 /* Apply incoming route-map.
3056 * NB: new_attr may now contain newly allocated values from route-map
3058 * commands, so we need bgp_attr_flush in the error paths, until we
3060 * the attr (which takes over the memory references) */
3061 if (bgp_input_modifier(peer
, p
, &new_attr
, afi
, safi
, NULL
)
3063 reason
= "route-map;";
3064 bgp_attr_flush(&new_attr
);
3068 if (peer
->sort
== BGP_PEER_EBGP
) {
3070 /* If we receive the graceful-shutdown community from an eBGP
3071 * peer we must lower local-preference */
3072 if (new_attr
.community
3073 && community_include(new_attr
.community
, COMMUNITY_GSHUT
)) {
3074 new_attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
3075 new_attr
.local_pref
= BGP_GSHUT_LOCAL_PREF
;
3077 /* If graceful-shutdown is configured then add the GSHUT
3078 * community to all paths received from eBGP peers */
3079 } else if (bgp_flag_check(peer
->bgp
,
3080 BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
3081 bgp_attr_add_gshut_community(&new_attr
);
3085 /* next hop check. */
3086 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
)
3087 && bgp_update_martian_nexthop(bgp
, afi
, safi
, &new_attr
)) {
3088 reason
= "martian or self next-hop;";
3089 bgp_attr_flush(&new_attr
);
3093 if (bgp_mac_entry_exists(p
)) {
3094 reason
= "self mac;";
3098 attr_new
= bgp_attr_intern(&new_attr
);
3100 /* If the update is implicit withdraw. */
3102 pi
->uptime
= bgp_clock();
3103 same_attr
= attrhash_cmp(pi
->attr
, attr_new
);
3105 /* Same attribute comes in. */
3106 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
3107 && attrhash_cmp(pi
->attr
, attr_new
)
3108 && (!has_valid_label
3109 || memcmp(&(bgp_path_info_extra_get(pi
))->label
, label
,
3110 num_labels
* sizeof(mpls_label_t
))
3112 && (overlay_index_equal(
3113 afi
, pi
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3114 evpn
== NULL
? NULL
: &evpn
->gw_ip
))) {
3115 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
3116 BGP_CONFIG_DAMPENING
)
3117 && peer
->sort
== BGP_PEER_EBGP
3118 && CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3119 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3120 bgp_debug_rdpfxpath2str(
3121 afi
, safi
, prd
, p
, label
,
3122 num_labels
, addpath_id
? 1 : 0,
3123 addpath_id
, pfx_buf
,
3125 zlog_debug("%s rcvd %s", peer
->host
,
3129 if (bgp_damp_update(pi
, rn
, afi
, safi
)
3130 != BGP_DAMP_SUPPRESSED
) {
3131 bgp_aggregate_increment(bgp
, p
, pi
, afi
,
3133 bgp_process(bgp
, rn
, afi
, safi
);
3135 } else /* Duplicate - odd */
3137 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3138 if (!peer
->rcvd_attr_printed
) {
3140 "%s rcvd UPDATE w/ attr: %s",
3142 peer
->rcvd_attr_str
);
3143 peer
->rcvd_attr_printed
= 1;
3146 bgp_debug_rdpfxpath2str(
3147 afi
, safi
, prd
, p
, label
,
3148 num_labels
, addpath_id
? 1 : 0,
3149 addpath_id
, pfx_buf
,
3152 "%s rcvd %s...duplicate ignored",
3153 peer
->host
, pfx_buf
);
3156 /* graceful restart STALE flag unset. */
3157 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
3158 bgp_path_info_unset_flag(
3159 rn
, pi
, BGP_PATH_STALE
);
3160 bgp_process(bgp
, rn
, afi
, safi
);
3164 bgp_unlock_node(rn
);
3165 bgp_attr_unintern(&attr_new
);
3170 /* Withdraw/Announce before we fully processed the withdraw */
3171 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
3172 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3173 bgp_debug_rdpfxpath2str(
3174 afi
, safi
, prd
, p
, label
, num_labels
,
3175 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3178 "%s rcvd %s, flapped quicker than processing",
3179 peer
->host
, pfx_buf
);
3182 bgp_path_info_restore(rn
, pi
);
3185 /* Received Logging. */
3186 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3187 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
3188 num_labels
, addpath_id
? 1 : 0,
3189 addpath_id
, pfx_buf
,
3191 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3194 /* graceful restart STALE flag unset. */
3195 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
3196 bgp_path_info_unset_flag(rn
, pi
, BGP_PATH_STALE
);
3198 /* The attribute is changed. */
3199 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_ATTR_CHANGED
);
3201 /* implicit withdraw, decrement aggregate and pcount here.
3202 * only if update is accepted, they'll increment below.
3204 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
3206 /* Update bgp route dampening information. */
3207 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3208 && peer
->sort
== BGP_PEER_EBGP
) {
3209 /* This is implicit withdraw so we should update
3212 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
3213 bgp_damp_withdraw(pi
, rn
, afi
, safi
, 1);
3216 if (safi
== SAFI_MPLS_VPN
) {
3217 struct bgp_node
*prn
= NULL
;
3218 struct bgp_table
*table
= NULL
;
3220 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3221 (struct prefix
*)prd
);
3222 if (bgp_node_has_bgp_path_info_data(prn
)) {
3223 table
= bgp_node_get_bgp_table_info(prn
);
3225 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3226 bgp
, prd
, table
, p
, pi
);
3228 bgp_unlock_node(prn
);
3230 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3231 && (safi
== SAFI_UNICAST
)) {
3232 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
3234 * Implicit withdraw case.
3236 ++vnc_implicit_withdraw
;
3237 vnc_import_bgp_del_route(bgp
, p
, pi
);
3238 vnc_import_bgp_exterior_del_route(bgp
, p
, pi
);
3243 /* Special handling for EVPN update of an existing route. If the
3244 * extended community attribute has changed, we need to
3246 * the route using its existing extended community. It will be
3247 * subsequently processed for import with the new extended
3250 if (safi
== SAFI_EVPN
&& !same_attr
) {
3252 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))
3254 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
3257 cmp
= ecommunity_cmp(pi
->attr
->ecommunity
,
3258 attr_new
->ecommunity
);
3260 if (bgp_debug_update(peer
, p
, NULL
, 1))
3262 "Change in EXT-COMM, existing %s new %s",
3264 pi
->attr
->ecommunity
),
3266 attr_new
->ecommunity
));
3267 bgp_evpn_unimport_route(bgp
, afi
, safi
,
3273 /* Update to new attribute. */
3274 bgp_attr_unintern(&pi
->attr
);
3275 pi
->attr
= attr_new
;
3277 /* Update MPLS label */
3278 if (has_valid_label
) {
3279 extra
= bgp_path_info_extra_get(pi
);
3280 if (extra
->label
!= label
) {
3281 memcpy(&extra
->label
, label
,
3282 num_labels
* sizeof(mpls_label_t
));
3283 extra
->num_labels
= num_labels
;
3285 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3286 bgp_set_valid_label(&extra
->label
[0]);
3290 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3291 && (safi
== SAFI_UNICAST
)) {
3292 if (vnc_implicit_withdraw
) {
3294 * Add back the route with its new attributes
3296 * The route is still selected, until the route
3298 * queued by bgp_process actually runs. We have
3300 * update to the VNC side immediately to avoid
3302 * configuration changes (e.g., route-map
3304 * trigger re-importation of the entire RIB.
3306 vnc_import_bgp_add_route(bgp
, p
, pi
);
3307 vnc_import_bgp_exterior_add_route(bgp
, p
, pi
);
3311 /* Update Overlay Index */
3312 if (afi
== AFI_L2VPN
) {
3313 overlay_index_update(
3314 pi
->attr
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3315 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3318 /* Update bgp route dampening information. */
3319 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3320 && peer
->sort
== BGP_PEER_EBGP
) {
3321 /* Now we do normal update dampening. */
3322 ret
= bgp_damp_update(pi
, rn
, afi
, safi
);
3323 if (ret
== BGP_DAMP_SUPPRESSED
) {
3324 bgp_unlock_node(rn
);
3329 /* Nexthop reachability check - for unicast and
3330 * labeled-unicast.. */
3331 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3332 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
3333 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
3334 && !CHECK_FLAG(peer
->flags
,
3335 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3337 bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3342 struct bgp
*bgp_nexthop
= bgp
;
3344 if (pi
->extra
&& pi
->extra
->bgp_orig
)
3345 bgp_nexthop
= pi
->extra
->bgp_orig
;
3347 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
, afi
, pi
,
3349 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3350 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_VALID
);
3352 if (BGP_DEBUG(nht
, NHT
)) {
3353 char buf1
[INET6_ADDRSTRLEN
];
3355 (const void *)&attr_new
3357 buf1
, INET6_ADDRSTRLEN
);
3358 zlog_debug("%s(%s): NH unresolved",
3359 __FUNCTION__
, buf1
);
3361 bgp_path_info_unset_flag(rn
, pi
,
3365 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_VALID
);
3368 if (safi
== SAFI_MPLS_VPN
) {
3369 struct bgp_node
*prn
= NULL
;
3370 struct bgp_table
*table
= NULL
;
3372 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3373 (struct prefix
*)prd
);
3374 if (bgp_node_has_bgp_path_info_data(prn
)) {
3375 table
= bgp_node_get_bgp_table_info(prn
);
3377 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3378 bgp
, prd
, table
, p
, pi
);
3380 bgp_unlock_node(prn
);
3384 /* If this is an EVPN route and some attribute has changed,
3386 * route for import. If the extended community has changed, we
3388 * have done the un-import earlier and the import would result
3390 * route getting injected into appropriate L2 VNIs. If it is
3392 * some other attribute change, the import will result in
3394 * the attributes for the route in the VNI(s).
3396 if (safi
== SAFI_EVPN
&& !same_attr
)
3397 bgp_evpn_import_route(bgp
, afi
, safi
, p
, pi
);
3399 /* Process change. */
3400 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
3402 bgp_process(bgp
, rn
, afi
, safi
);
3403 bgp_unlock_node(rn
);
3405 if (SAFI_UNICAST
== safi
3406 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3407 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3409 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, pi
);
3411 if ((SAFI_MPLS_VPN
== safi
)
3412 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3414 vpn_leak_to_vrf_update(bgp
, pi
);
3418 if (SAFI_MPLS_VPN
== safi
) {
3419 mpls_label_t label_decoded
= decode_label(label
);
3421 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3422 type
, sub_type
, &label_decoded
);
3424 if (SAFI_ENCAP
== safi
) {
3425 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3426 type
, sub_type
, NULL
);
3431 } // End of implicit withdraw
3433 /* Received Logging. */
3434 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3435 if (!peer
->rcvd_attr_printed
) {
3436 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3437 peer
->rcvd_attr_str
);
3438 peer
->rcvd_attr_printed
= 1;
3441 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3442 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3444 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3447 /* Make new BGP info. */
3448 new = info_make(type
, sub_type
, 0, peer
, attr_new
, rn
);
3450 /* Update MPLS label */
3451 if (has_valid_label
) {
3452 extra
= bgp_path_info_extra_get(new);
3453 if (extra
->label
!= label
) {
3454 memcpy(&extra
->label
, label
, num_labels
* sizeof(mpls_label_t
));
3455 extra
->num_labels
= num_labels
;
3457 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3458 bgp_set_valid_label(&extra
->label
[0]);
3461 /* Update Overlay Index */
3462 if (afi
== AFI_L2VPN
) {
3463 overlay_index_update(new->attr
,
3464 evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3465 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3467 /* Nexthop reachability check. */
3468 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3469 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
3470 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
3471 && !CHECK_FLAG(peer
->flags
,
3472 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3473 && !bgp_flag_check(bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3478 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, new, NULL
, connected
)
3479 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3480 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
3482 if (BGP_DEBUG(nht
, NHT
)) {
3483 char buf1
[INET6_ADDRSTRLEN
];
3485 (const void *)&attr_new
->nexthop
,
3486 buf1
, INET6_ADDRSTRLEN
);
3487 zlog_debug("%s(%s): NH unresolved",
3488 __FUNCTION__
, buf1
);
3490 bgp_path_info_unset_flag(rn
, new, BGP_PATH_VALID
);
3493 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
3496 new->addpath_rx_id
= addpath_id
;
3498 /* Increment prefix */
3499 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
3501 /* Register new BGP information. */
3502 bgp_path_info_add(rn
, new);
3504 /* route_node_get lock */
3505 bgp_unlock_node(rn
);
3508 if (safi
== SAFI_MPLS_VPN
) {
3509 struct bgp_node
*prn
= NULL
;
3510 struct bgp_table
*table
= NULL
;
3512 prn
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
3513 if (bgp_node_has_bgp_path_info_data(prn
)) {
3514 table
= bgp_node_get_bgp_table_info(prn
);
3516 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3517 bgp
, prd
, table
, p
, new);
3519 bgp_unlock_node(prn
);
3523 /* If maximum prefix count is configured and current prefix
3525 if (bgp_maximum_prefix_overflow(peer
, afi
, safi
, 0))
3528 /* If this is an EVPN route, process for import. */
3529 if (safi
== SAFI_EVPN
)
3530 bgp_evpn_import_route(bgp
, afi
, safi
, p
, new);
3532 /* Process change. */
3533 bgp_process(bgp
, rn
, afi
, safi
);
3535 if (SAFI_UNICAST
== safi
3536 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3537 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3538 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
3540 if ((SAFI_MPLS_VPN
== safi
)
3541 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3543 vpn_leak_to_vrf_update(bgp
, new);
3546 if (SAFI_MPLS_VPN
== safi
) {
3547 mpls_label_t label_decoded
= decode_label(label
);
3549 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3550 sub_type
, &label_decoded
);
3552 if (SAFI_ENCAP
== safi
) {
3553 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3560 /* This BGP update is filtered. Log the reason then update BGP
3563 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3564 if (!peer
->rcvd_attr_printed
) {
3565 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3566 peer
->rcvd_attr_str
);
3567 peer
->rcvd_attr_printed
= 1;
3570 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3571 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3573 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
3574 peer
->host
, pfx_buf
, reason
);
3578 /* If this is an EVPN route, un-import it as it is now filtered.
3580 if (safi
== SAFI_EVPN
)
3581 bgp_evpn_unimport_route(bgp
, afi
, safi
, p
, pi
);
3583 if (SAFI_UNICAST
== safi
3584 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3585 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3587 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
3589 if ((SAFI_MPLS_VPN
== safi
)
3590 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3592 vpn_leak_to_vrf_withdraw(bgp
, pi
);
3595 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
3598 bgp_unlock_node(rn
);
3602 * Filtered update is treated as an implicit withdrawal (see
3604 * a few lines above)
3606 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3607 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3615 int bgp_withdraw(struct peer
*peer
, struct prefix
*p
, uint32_t addpath_id
,
3616 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
3617 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
3618 uint32_t num_labels
, struct bgp_route_evpn
*evpn
)
3621 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
3622 struct bgp_node
*rn
;
3623 struct bgp_path_info
*pi
;
3626 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3627 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3635 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
3637 /* If peer is soft reconfiguration enabled. Record input packet for
3638 * further calculation.
3640 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
3641 * routes that are filtered. This tanks out Quagga RS pretty badly due
3643 * the iteration over all RS clients.
3644 * Since we need to remove the entry from adj_in anyway, do that first
3646 * if there was no entry, we don't need to do anything more.
3648 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
3649 && peer
!= bgp
->peer_self
)
3650 if (!bgp_adj_in_unset(rn
, peer
, addpath_id
)) {
3651 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3652 bgp_debug_rdpfxpath2str(
3653 afi
, safi
, prd
, p
, label
, num_labels
,
3654 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3657 "%s withdrawing route %s not in adj-in",
3658 peer
->host
, pfx_buf
);
3660 bgp_unlock_node(rn
);
3664 /* Lookup withdrawn route. */
3665 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
3666 if (pi
->peer
== peer
&& pi
->type
== type
3667 && pi
->sub_type
== sub_type
3668 && pi
->addpath_rx_id
== addpath_id
)
3672 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3673 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3674 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3676 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer
->host
,
3680 /* Withdraw specified route from routing table. */
3681 if (pi
&& !CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3682 bgp_rib_withdraw(rn
, pi
, peer
, afi
, safi
, prd
);
3683 if (SAFI_UNICAST
== safi
3684 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3685 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3686 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
3688 if ((SAFI_MPLS_VPN
== safi
)
3689 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3691 vpn_leak_to_vrf_withdraw(bgp
, pi
);
3693 } else if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3694 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3695 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3697 zlog_debug("%s Can't find the route %s", peer
->host
, pfx_buf
);
3700 /* Unlock bgp_node_get() lock. */
3701 bgp_unlock_node(rn
);
3706 void bgp_default_originate(struct peer
*peer
, afi_t afi
, safi_t safi
,
3709 struct update_subgroup
*subgrp
;
3710 subgrp
= peer_subgroup(peer
, afi
, safi
);
3711 subgroup_default_originate(subgrp
, withdraw
);
3716 * bgp_stop_announce_route_timer
3718 void bgp_stop_announce_route_timer(struct peer_af
*paf
)
3720 if (!paf
->t_announce_route
)
3723 THREAD_TIMER_OFF(paf
->t_announce_route
);
3727 * bgp_announce_route_timer_expired
3729 * Callback that is invoked when the route announcement timer for a
3732 static int bgp_announce_route_timer_expired(struct thread
*t
)
3734 struct peer_af
*paf
;
3737 paf
= THREAD_ARG(t
);
3740 if (peer
->status
!= Established
)
3743 if (!peer
->afc_nego
[paf
->afi
][paf
->safi
])
3746 peer_af_announce_route(paf
, 1);
3751 * bgp_announce_route
3753 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
3755 void bgp_announce_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
3757 struct peer_af
*paf
;
3758 struct update_subgroup
*subgrp
;
3760 paf
= peer_af_find(peer
, afi
, safi
);
3763 subgrp
= PAF_SUBGRP(paf
);
3766 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
3767 * or a refresh has already been triggered.
3769 if (!subgrp
|| paf
->t_announce_route
)
3773 * Start a timer to stagger/delay the announce. This serves
3774 * two purposes - announcement can potentially be combined for
3775 * multiple peers and the announcement doesn't happen in the
3778 thread_add_timer_msec(bm
->master
, bgp_announce_route_timer_expired
, paf
,
3779 (subgrp
->peer_count
== 1)
3780 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
3781 : BGP_ANNOUNCE_ROUTE_DELAY_MS
,
3782 &paf
->t_announce_route
);
3786 * Announce routes from all AF tables to a peer.
3788 * This should ONLY be called when there is a need to refresh the
3789 * routes to the peer based on a policy change for this peer alone
3790 * or a route refresh request received from the peer.
3791 * The operation will result in splitting the peer from its existing
3792 * subgroups and putting it in new subgroups.
3794 void bgp_announce_route_all(struct peer
*peer
)
3799 FOREACH_AFI_SAFI (afi
, safi
)
3800 bgp_announce_route(peer
, afi
, safi
);
3803 static void bgp_soft_reconfig_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
3804 struct bgp_table
*table
,
3805 struct prefix_rd
*prd
)
3808 struct bgp_node
*rn
;
3809 struct bgp_adj_in
*ain
;
3812 table
= peer
->bgp
->rib
[afi
][safi
];
3814 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
3815 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
3816 if (ain
->peer
!= peer
)
3819 struct bgp_path_info
*pi
=
3820 bgp_node_get_bgp_path_info(rn
);
3821 uint32_t num_labels
= 0;
3822 mpls_label_t
*label_pnt
= NULL
;
3823 struct bgp_route_evpn evpn
;
3825 if (pi
&& pi
->extra
)
3826 num_labels
= pi
->extra
->num_labels
;
3828 label_pnt
= &pi
->extra
->label
[0];
3830 memcpy(&evpn
, &pi
->attr
->evpn_overlay
,
3833 memset(&evpn
, 0, sizeof(evpn
));
3835 ret
= bgp_update(peer
, &rn
->p
, ain
->addpath_rx_id
,
3836 ain
->attr
, afi
, safi
, ZEBRA_ROUTE_BGP
,
3837 BGP_ROUTE_NORMAL
, prd
, label_pnt
,
3838 num_labels
, 1, &evpn
);
3841 bgp_unlock_node(rn
);
3847 void bgp_soft_reconfig_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
3849 struct bgp_node
*rn
;
3850 struct bgp_table
*table
;
3852 if (peer
->status
!= Established
)
3855 if ((safi
!= SAFI_MPLS_VPN
) && (safi
!= SAFI_ENCAP
)
3856 && (safi
!= SAFI_EVPN
))
3857 bgp_soft_reconfig_table(peer
, afi
, safi
, NULL
, NULL
);
3859 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
3860 rn
= bgp_route_next(rn
)) {
3861 table
= bgp_node_get_bgp_table_info(rn
);
3862 if (table
!= NULL
) {
3863 struct prefix_rd prd
;
3865 prd
.family
= AF_UNSPEC
;
3867 memcpy(&prd
.val
, rn
->p
.u
.val
, 8);
3869 bgp_soft_reconfig_table(peer
, afi
, safi
, table
,
3876 struct bgp_clear_node_queue
{
3877 struct bgp_node
*rn
;
3880 static wq_item_status
bgp_clear_route_node(struct work_queue
*wq
, void *data
)
3882 struct bgp_clear_node_queue
*cnq
= data
;
3883 struct bgp_node
*rn
= cnq
->rn
;
3884 struct peer
*peer
= wq
->spec
.data
;
3885 struct bgp_path_info
*pi
;
3887 afi_t afi
= bgp_node_table(rn
)->afi
;
3888 safi_t safi
= bgp_node_table(rn
)->safi
;
3893 /* It is possible that we have multiple paths for a prefix from a peer
3894 * if that peer is using AddPath.
3896 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
3897 if (pi
->peer
!= peer
)
3900 /* graceful restart STALE flag set. */
3901 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_NSF_WAIT
)
3902 && peer
->nsf
[afi
][safi
]
3903 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
3904 && !CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
3905 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_STALE
);
3907 /* If this is an EVPN route, process for
3909 if (safi
== SAFI_EVPN
)
3910 bgp_evpn_unimport_route(bgp
, afi
, safi
, &rn
->p
,
3912 /* Handle withdraw for VRF route-leaking and L3VPN */
3913 if (SAFI_UNICAST
== safi
3914 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
||
3915 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3916 vpn_leak_from_vrf_withdraw(bgp_get_default(),
3919 if (SAFI_MPLS_VPN
== safi
&&
3920 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
3921 vpn_leak_to_vrf_withdraw(bgp
, pi
);
3924 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
3930 static void bgp_clear_node_queue_del(struct work_queue
*wq
, void *data
)
3932 struct bgp_clear_node_queue
*cnq
= data
;
3933 struct bgp_node
*rn
= cnq
->rn
;
3934 struct bgp_table
*table
= bgp_node_table(rn
);
3936 bgp_unlock_node(rn
);
3937 bgp_table_unlock(table
);
3938 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE
, cnq
);
3941 static void bgp_clear_node_complete(struct work_queue
*wq
)
3943 struct peer
*peer
= wq
->spec
.data
;
3945 /* Tickle FSM to start moving again */
3946 BGP_EVENT_ADD(peer
, Clearing_Completed
);
3948 peer_unlock(peer
); /* bgp_clear_route */
3951 static void bgp_clear_node_queue_init(struct peer
*peer
)
3953 char wname
[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
3955 snprintf(wname
, sizeof(wname
), "clear %s", peer
->host
);
3956 #undef CLEAR_QUEUE_NAME_LEN
3958 peer
->clear_node_queue
= work_queue_new(bm
->master
, wname
);
3959 peer
->clear_node_queue
->spec
.hold
= 10;
3960 peer
->clear_node_queue
->spec
.workfunc
= &bgp_clear_route_node
;
3961 peer
->clear_node_queue
->spec
.del_item_data
= &bgp_clear_node_queue_del
;
3962 peer
->clear_node_queue
->spec
.completion_func
= &bgp_clear_node_complete
;
3963 peer
->clear_node_queue
->spec
.max_retries
= 0;
3965 /* we only 'lock' this peer reference when the queue is actually active
3967 peer
->clear_node_queue
->spec
.data
= peer
;
3970 static void bgp_clear_route_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
3971 struct bgp_table
*table
)
3973 struct bgp_node
*rn
;
3974 int force
= bm
->process_main_queue
? 0 : 1;
3977 table
= peer
->bgp
->rib
[afi
][safi
];
3979 /* If still no table => afi/safi isn't configured at all or smth. */
3983 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
3984 struct bgp_path_info
*pi
, *next
;
3985 struct bgp_adj_in
*ain
;
3986 struct bgp_adj_in
*ain_next
;
3988 /* XXX:TODO: This is suboptimal, every non-empty route_node is
3989 * queued for every clearing peer, regardless of whether it is
3990 * relevant to the peer at hand.
3992 * Overview: There are 3 different indices which need to be
3993 * scrubbed, potentially, when a peer is removed:
3995 * 1 peer's routes visible via the RIB (ie accepted routes)
3996 * 2 peer's routes visible by the (optional) peer's adj-in index
3997 * 3 other routes visible by the peer's adj-out index
3999 * 3 there is no hurry in scrubbing, once the struct peer is
4000 * removed from bgp->peer, we could just GC such deleted peer's
4001 * adj-outs at our leisure.
4003 * 1 and 2 must be 'scrubbed' in some way, at least made
4004 * invisible via RIB index before peer session is allowed to be
4005 * brought back up. So one needs to know when such a 'search' is
4010 * - there'd be a single global queue or a single RIB walker
4011 * - rather than tracking which route_nodes still need to be
4012 * examined on a peer basis, we'd track which peers still
4015 * Given that our per-peer prefix-counts now should be reliable,
4016 * this may actually be achievable. It doesn't seem to be a huge
4017 * problem at this time,
4019 * It is possible that we have multiple paths for a prefix from
4021 * if that peer is using AddPath.
4025 ain_next
= ain
->next
;
4027 if (ain
->peer
== peer
) {
4028 bgp_adj_in_remove(rn
, ain
);
4029 bgp_unlock_node(rn
);
4035 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= next
) {
4037 if (pi
->peer
!= peer
)
4041 bgp_path_info_reap(rn
, pi
);
4043 struct bgp_clear_node_queue
*cnq
;
4045 /* both unlocked in bgp_clear_node_queue_del */
4046 bgp_table_lock(bgp_node_table(rn
));
4049 MTYPE_BGP_CLEAR_NODE_QUEUE
,
4050 sizeof(struct bgp_clear_node_queue
));
4052 work_queue_add(peer
->clear_node_queue
, cnq
);
4060 void bgp_clear_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4062 struct bgp_node
*rn
;
4063 struct bgp_table
*table
;
4065 if (peer
->clear_node_queue
== NULL
)
4066 bgp_clear_node_queue_init(peer
);
4068 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
4069 * Idle until it receives a Clearing_Completed event. This protects
4070 * against peers which flap faster than we can we clear, which could
4073 * a) race with routes from the new session being installed before
4074 * clear_route_node visits the node (to delete the route of that
4076 * b) resource exhaustion, clear_route_node likely leads to an entry
4077 * on the process_main queue. Fast-flapping could cause that queue
4081 /* lock peer in assumption that clear-node-queue will get nodes; if so,
4082 * the unlock will happen upon work-queue completion; other wise, the
4083 * unlock happens at the end of this function.
4085 if (!peer
->clear_node_queue
->thread
)
4088 if (safi
!= SAFI_MPLS_VPN
&& safi
!= SAFI_ENCAP
&& safi
!= SAFI_EVPN
)
4089 bgp_clear_route_table(peer
, afi
, safi
, NULL
);
4091 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4092 rn
= bgp_route_next(rn
)) {
4093 table
= bgp_node_get_bgp_table_info(rn
);
4097 bgp_clear_route_table(peer
, afi
, safi
, table
);
4100 /* unlock if no nodes got added to the clear-node-queue. */
4101 if (!peer
->clear_node_queue
->thread
)
4105 void bgp_clear_route_all(struct peer
*peer
)
4110 FOREACH_AFI_SAFI (afi
, safi
)
4111 bgp_clear_route(peer
, afi
, safi
);
4114 rfapiProcessPeerDown(peer
);
4118 void bgp_clear_adj_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
4120 struct bgp_table
*table
;
4121 struct bgp_node
*rn
;
4122 struct bgp_adj_in
*ain
;
4123 struct bgp_adj_in
*ain_next
;
4125 table
= peer
->bgp
->rib
[afi
][safi
];
4127 /* It is possible that we have multiple paths for a prefix from a peer
4128 * if that peer is using AddPath.
4130 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
4134 ain_next
= ain
->next
;
4136 if (ain
->peer
== peer
) {
4137 bgp_adj_in_remove(rn
, ain
);
4138 bgp_unlock_node(rn
);
4146 void bgp_clear_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4148 struct bgp_node
*rn
;
4149 struct bgp_path_info
*pi
;
4150 struct bgp_table
*table
;
4152 if (safi
== SAFI_MPLS_VPN
) {
4153 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4154 rn
= bgp_route_next(rn
)) {
4155 struct bgp_node
*rm
;
4157 /* look for neighbor in tables */
4158 table
= bgp_node_get_bgp_table_info(rn
);
4162 for (rm
= bgp_table_top(table
); rm
;
4163 rm
= bgp_route_next(rm
))
4164 for (pi
= bgp_node_get_bgp_path_info(rm
); pi
;
4166 if (pi
->peer
!= peer
)
4168 if (!CHECK_FLAG(pi
->flags
,
4172 bgp_rib_remove(rm
, pi
, peer
, afi
, safi
);
4177 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4178 rn
= bgp_route_next(rn
))
4179 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
;
4181 if (pi
->peer
!= peer
)
4183 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
4185 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
4191 int bgp_outbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
4193 if (peer
->sort
== BGP_PEER_EBGP
4194 && (ROUTE_MAP_OUT_NAME(filter
) || PREFIX_LIST_OUT_NAME(filter
)
4195 || FILTER_LIST_OUT_NAME(filter
)
4196 || DISTRIBUTE_OUT_NAME(filter
)))
4201 int bgp_inbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
4203 if (peer
->sort
== BGP_PEER_EBGP
4204 && (ROUTE_MAP_IN_NAME(filter
) || PREFIX_LIST_IN_NAME(filter
)
4205 || FILTER_LIST_IN_NAME(filter
)
4206 || DISTRIBUTE_IN_NAME(filter
)))
4211 static void bgp_cleanup_table(struct bgp
*bgp
, struct bgp_table
*table
,
4214 struct bgp_node
*rn
;
4215 struct bgp_path_info
*pi
;
4216 struct bgp_path_info
*next
;
4218 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
4219 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= next
) {
4221 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)
4222 && pi
->type
== ZEBRA_ROUTE_BGP
4223 && (pi
->sub_type
== BGP_ROUTE_NORMAL
4224 || pi
->sub_type
== BGP_ROUTE_AGGREGATE
4225 || pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
4227 if (bgp_fibupd_safi(safi
))
4228 bgp_zebra_withdraw(&rn
->p
, pi
, bgp
,
4230 bgp_path_info_reap(rn
, pi
);
4235 /* Delete all kernel routes. */
4236 void bgp_cleanup_routes(struct bgp
*bgp
)
4239 struct bgp_node
*rn
;
4240 struct bgp_table
*table
;
4242 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
4243 if (afi
== AFI_L2VPN
)
4245 bgp_cleanup_table(bgp
, bgp
->rib
[afi
][SAFI_UNICAST
],
4248 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
4250 if (afi
!= AFI_L2VPN
) {
4252 safi
= SAFI_MPLS_VPN
;
4253 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4254 rn
= bgp_route_next(rn
)) {
4255 table
= bgp_node_get_bgp_table_info(rn
);
4256 if (table
!= NULL
) {
4257 bgp_cleanup_table(bgp
, table
, safi
);
4258 bgp_table_finish(&table
);
4259 bgp_node_set_bgp_table_info(rn
, NULL
);
4260 bgp_unlock_node(rn
);
4264 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4265 rn
= bgp_route_next(rn
)) {
4266 table
= bgp_node_get_bgp_table_info(rn
);
4267 if (table
!= NULL
) {
4268 bgp_cleanup_table(bgp
, table
, safi
);
4269 bgp_table_finish(&table
);
4270 bgp_node_set_bgp_table_info(rn
, NULL
);
4271 bgp_unlock_node(rn
);
4276 for (rn
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); rn
;
4277 rn
= bgp_route_next(rn
)) {
4278 table
= bgp_node_get_bgp_table_info(rn
);
4279 if (table
!= NULL
) {
4280 bgp_cleanup_table(bgp
, table
, SAFI_EVPN
);
4281 bgp_table_finish(&table
);
4282 bgp_node_set_bgp_table_info(rn
, NULL
);
4283 bgp_unlock_node(rn
);
4288 void bgp_reset(void)
4291 bgp_zclient_reset();
4292 access_list_reset();
4293 prefix_list_reset();
4296 static int bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
4298 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
4299 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
4300 PEER_CAP_ADDPATH_AF_TX_RCV
));
4303 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
4305 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
4306 struct bgp_nlri
*packet
)
4315 int addpath_encoded
;
4316 uint32_t addpath_id
;
4319 lim
= pnt
+ packet
->length
;
4321 safi
= packet
->safi
;
4323 addpath_encoded
= bgp_addpath_encode_rx(peer
, afi
, safi
);
4325 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
4326 syntactic validity. If the field is syntactically incorrect,
4327 then the Error Subcode is set to Invalid Network Field. */
4328 for (; pnt
< lim
; pnt
+= psize
) {
4329 /* Clear prefix structure. */
4330 memset(&p
, 0, sizeof(struct prefix
));
4332 if (addpath_encoded
) {
4334 /* When packet overflow occurs return immediately. */
4335 if (pnt
+ BGP_ADDPATH_ID_LEN
> lim
)
4338 addpath_id
= ntohl(*((uint32_t *)pnt
));
4339 pnt
+= BGP_ADDPATH_ID_LEN
;
4342 /* Fetch prefix length. */
4343 p
.prefixlen
= *pnt
++;
4344 /* afi/safi validity already verified by caller,
4345 * bgp_update_receive */
4346 p
.family
= afi2family(afi
);
4348 /* Prefix length check. */
4349 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
4352 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
4353 peer
->host
, p
.prefixlen
, packet
->afi
);
4357 /* Packet size overflow check. */
4358 psize
= PSIZE(p
.prefixlen
);
4360 /* When packet overflow occur return immediately. */
4361 if (pnt
+ psize
> lim
) {
4364 "%s [Error] Update packet error (prefix length %d overflows packet)",
4365 peer
->host
, p
.prefixlen
);
4369 /* Defensive coding, double-check the psize fits in a struct
4371 if (psize
> (ssize_t
)sizeof(p
.u
)) {
4374 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
4375 peer
->host
, p
.prefixlen
, sizeof(p
.u
));
4379 /* Fetch prefix from NLRI packet. */
4380 memcpy(p
.u
.val
, pnt
, psize
);
4382 /* Check address. */
4383 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
4384 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
4385 /* From RFC4271 Section 6.3:
4387 * If a prefix in the NLRI field is semantically
4389 * (e.g., an unexpected multicast IP address),
4391 * be logged locally, and the prefix SHOULD be
4396 "%s: IPv4 unicast NLRI is multicast address %s, ignoring",
4397 peer
->host
, inet_ntoa(p
.u
.prefix4
));
4402 /* Check address. */
4403 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
4404 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4409 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
4411 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4416 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
4421 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
4423 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4430 /* Normal process. */
4432 ret
= bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
4433 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
4434 NULL
, NULL
, 0, 0, NULL
);
4436 ret
= bgp_withdraw(peer
, &p
, addpath_id
, attr
, afi
,
4437 safi
, ZEBRA_ROUTE_BGP
,
4438 BGP_ROUTE_NORMAL
, NULL
, NULL
, 0,
4441 /* Address family configuration mismatch or maximum-prefix count
4447 /* Packet length consistency check. */
4451 "%s [Error] Update packet error (prefix length mismatch with total length)",
4459 static struct bgp_static
*bgp_static_new(void)
4461 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
4464 static void bgp_static_free(struct bgp_static
*bgp_static
)
4466 if (bgp_static
->rmap
.name
)
4467 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
4468 route_map_counter_decrement(bgp_static
->rmap
.map
);
4470 if (bgp_static
->eth_s_id
)
4471 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
4472 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
4475 void bgp_static_update(struct bgp
*bgp
, struct prefix
*p
,
4476 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
4478 struct bgp_node
*rn
;
4479 struct bgp_path_info
*pi
;
4480 struct bgp_path_info
*new;
4481 struct bgp_path_info rmap_path
;
4483 struct attr
*attr_new
;
4486 int vnc_implicit_withdraw
= 0;
4493 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4495 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4497 attr
.nexthop
= bgp_static
->igpnexthop
;
4498 attr
.med
= bgp_static
->igpmetric
;
4499 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4501 if (bgp_static
->atomic
)
4502 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
4504 /* Store label index, if required. */
4505 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
4506 attr
.label_index
= bgp_static
->label_index
;
4507 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
4510 /* Apply route-map. */
4511 if (bgp_static
->rmap
.name
) {
4512 struct attr attr_tmp
= attr
;
4514 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
4515 rmap_path
.peer
= bgp
->peer_self
;
4516 rmap_path
.attr
= &attr_tmp
;
4518 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4520 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
,
4523 bgp
->peer_self
->rmap_type
= 0;
4525 if (ret
== RMAP_DENYMATCH
) {
4526 /* Free uninterned attribute. */
4527 bgp_attr_flush(&attr_tmp
);
4529 /* Unintern original. */
4530 aspath_unintern(&attr
.aspath
);
4531 bgp_static_withdraw(bgp
, p
, afi
, safi
);
4535 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4536 bgp_attr_add_gshut_community(&attr_tmp
);
4538 attr_new
= bgp_attr_intern(&attr_tmp
);
4541 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4542 bgp_attr_add_gshut_community(&attr
);
4544 attr_new
= bgp_attr_intern(&attr
);
4547 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4548 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4549 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4553 if (attrhash_cmp(pi
->attr
, attr_new
)
4554 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
4555 && !bgp_flag_check(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
4556 bgp_unlock_node(rn
);
4557 bgp_attr_unintern(&attr_new
);
4558 aspath_unintern(&attr
.aspath
);
4561 /* The attribute is changed. */
4562 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_ATTR_CHANGED
);
4564 /* Rewrite BGP route information. */
4565 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
4566 bgp_path_info_restore(rn
, pi
);
4568 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4570 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4571 && (safi
== SAFI_UNICAST
)) {
4572 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
4574 * Implicit withdraw case.
4575 * We have to do this before pi is
4578 ++vnc_implicit_withdraw
;
4579 vnc_import_bgp_del_route(bgp
, p
, pi
);
4580 vnc_import_bgp_exterior_del_route(
4585 bgp_attr_unintern(&pi
->attr
);
4586 pi
->attr
= attr_new
;
4587 pi
->uptime
= bgp_clock();
4589 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4590 && (safi
== SAFI_UNICAST
)) {
4591 if (vnc_implicit_withdraw
) {
4592 vnc_import_bgp_add_route(bgp
, p
, pi
);
4593 vnc_import_bgp_exterior_add_route(
4599 /* Nexthop reachability check. */
4600 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4601 && (safi
== SAFI_UNICAST
4602 || safi
== SAFI_LABELED_UNICAST
)) {
4604 struct bgp
*bgp_nexthop
= bgp
;
4606 if (pi
->extra
&& pi
->extra
->bgp_orig
)
4607 bgp_nexthop
= pi
->extra
->bgp_orig
;
4609 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
,
4611 bgp_path_info_set_flag(rn
, pi
,
4614 if (BGP_DEBUG(nht
, NHT
)) {
4615 char buf1
[INET6_ADDRSTRLEN
];
4616 inet_ntop(p
->family
,
4620 "%s(%s): Route not in table, not advertising",
4621 __FUNCTION__
, buf1
);
4623 bgp_path_info_unset_flag(
4624 rn
, pi
, BGP_PATH_VALID
);
4627 /* Delete the NHT structure if any, if we're
4629 * enabling/disabling import check. We
4630 * deregister the route
4631 * from NHT to avoid overloading NHT and the
4632 * process interaction
4634 bgp_unlink_nexthop(pi
);
4635 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_VALID
);
4637 /* Process change. */
4638 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
4639 bgp_process(bgp
, rn
, afi
, safi
);
4641 if (SAFI_UNICAST
== safi
4642 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4644 == BGP_INSTANCE_TYPE_DEFAULT
)) {
4645 vpn_leak_from_vrf_update(bgp_get_default(), bgp
,
4649 bgp_unlock_node(rn
);
4650 aspath_unintern(&attr
.aspath
);
4655 /* Make new BGP info. */
4656 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
4658 /* Nexthop reachability check. */
4659 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4660 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
4661 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, new, NULL
, 0))
4662 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
4664 if (BGP_DEBUG(nht
, NHT
)) {
4665 char buf1
[INET6_ADDRSTRLEN
];
4666 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
4669 "%s(%s): Route not in table, not advertising",
4670 __FUNCTION__
, buf1
);
4672 bgp_path_info_unset_flag(rn
, new, BGP_PATH_VALID
);
4675 /* Delete the NHT structure if any, if we're toggling between
4676 * enabling/disabling import check. We deregister the route
4677 * from NHT to avoid overloading NHT and the process interaction
4679 bgp_unlink_nexthop(new);
4681 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
4684 /* Aggregate address increment. */
4685 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4687 /* Register new BGP information. */
4688 bgp_path_info_add(rn
, new);
4690 /* route_node_get lock */
4691 bgp_unlock_node(rn
);
4693 /* Process change. */
4694 bgp_process(bgp
, rn
, afi
, safi
);
4696 if (SAFI_UNICAST
== safi
4697 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4698 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4699 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
4702 /* Unintern original. */
4703 aspath_unintern(&attr
.aspath
);
4706 void bgp_static_withdraw(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
4709 struct bgp_node
*rn
;
4710 struct bgp_path_info
*pi
;
4712 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4714 /* Check selected route and self inserted route. */
4715 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4716 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4717 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4720 /* Withdraw static BGP route from routing table. */
4722 if (SAFI_UNICAST
== safi
4723 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4724 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4725 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
4727 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4728 bgp_unlink_nexthop(pi
);
4729 bgp_path_info_delete(rn
, pi
);
4730 bgp_process(bgp
, rn
, afi
, safi
);
4733 /* Unlock bgp_node_lookup. */
4734 bgp_unlock_node(rn
);
4738 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
4740 static void bgp_static_withdraw_safi(struct bgp
*bgp
, struct prefix
*p
,
4741 afi_t afi
, safi_t safi
,
4742 struct prefix_rd
*prd
)
4744 struct bgp_node
*rn
;
4745 struct bgp_path_info
*pi
;
4747 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4749 /* Check selected route and self inserted route. */
4750 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4751 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4752 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4755 /* Withdraw static BGP route from routing table. */
4758 rfapiProcessWithdraw(
4759 pi
->peer
, NULL
, p
, prd
, pi
->attr
, afi
, safi
, pi
->type
,
4760 1); /* Kill, since it is an administrative change */
4762 if (SAFI_MPLS_VPN
== safi
4763 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4764 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4766 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4767 bgp_path_info_delete(rn
, pi
);
4768 bgp_process(bgp
, rn
, afi
, safi
);
4771 /* Unlock bgp_node_lookup. */
4772 bgp_unlock_node(rn
);
4775 static void bgp_static_update_safi(struct bgp
*bgp
, struct prefix
*p
,
4776 struct bgp_static
*bgp_static
, afi_t afi
,
4779 struct bgp_node
*rn
;
4780 struct bgp_path_info
*new;
4781 struct attr
*attr_new
;
4782 struct attr attr
= {0};
4783 struct bgp_path_info
*pi
;
4785 mpls_label_t label
= 0;
4787 uint32_t num_labels
= 0;
4792 if (bgp_static
->label
!= MPLS_INVALID_LABEL
)
4794 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
4797 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4799 attr
.nexthop
= bgp_static
->igpnexthop
;
4800 attr
.med
= bgp_static
->igpmetric
;
4801 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4803 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
4804 || (safi
== SAFI_ENCAP
)) {
4805 if (afi
== AFI_IP
) {
4806 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
4807 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
4810 if (afi
== AFI_L2VPN
) {
4811 if (bgp_static
->gatewayIp
.family
== AF_INET
)
4813 bgp_static
->gatewayIp
.u
.prefix4
.s_addr
;
4814 else if (bgp_static
->gatewayIp
.family
== AF_INET6
)
4815 memcpy(&(add
.ipv6
), &(bgp_static
->gatewayIp
.u
.prefix6
),
4816 sizeof(struct in6_addr
));
4817 overlay_index_update(&attr
, bgp_static
->eth_s_id
, &add
);
4818 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
4819 struct bgp_encap_type_vxlan bet
;
4820 memset(&bet
, 0, sizeof(struct bgp_encap_type_vxlan
));
4821 bet
.vnid
= p
->u
.prefix_evpn
.prefix_addr
.eth_tag
;
4822 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
4824 if (bgp_static
->router_mac
) {
4825 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
4828 /* Apply route-map. */
4829 if (bgp_static
->rmap
.name
) {
4830 struct attr attr_tmp
= attr
;
4831 struct bgp_path_info rmap_path
;
4834 rmap_path
.peer
= bgp
->peer_self
;
4835 rmap_path
.attr
= &attr_tmp
;
4837 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4839 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
,
4842 bgp
->peer_self
->rmap_type
= 0;
4844 if (ret
== RMAP_DENYMATCH
) {
4845 /* Free uninterned attribute. */
4846 bgp_attr_flush(&attr_tmp
);
4848 /* Unintern original. */
4849 aspath_unintern(&attr
.aspath
);
4850 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
4855 attr_new
= bgp_attr_intern(&attr_tmp
);
4857 attr_new
= bgp_attr_intern(&attr
);
4860 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4861 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4862 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4866 memset(&add
, 0, sizeof(union gw_addr
));
4867 if (attrhash_cmp(pi
->attr
, attr_new
)
4868 && overlay_index_equal(afi
, pi
, bgp_static
->eth_s_id
, &add
)
4869 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
4870 bgp_unlock_node(rn
);
4871 bgp_attr_unintern(&attr_new
);
4872 aspath_unintern(&attr
.aspath
);
4875 /* The attribute is changed. */
4876 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_ATTR_CHANGED
);
4878 /* Rewrite BGP route information. */
4879 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
4880 bgp_path_info_restore(rn
, pi
);
4882 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4883 bgp_attr_unintern(&pi
->attr
);
4884 pi
->attr
= attr_new
;
4885 pi
->uptime
= bgp_clock();
4888 label
= decode_label(&pi
->extra
->label
[0]);
4891 /* Process change. */
4892 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
4893 bgp_process(bgp
, rn
, afi
, safi
);
4895 if (SAFI_MPLS_VPN
== safi
4896 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4897 vpn_leak_to_vrf_update(bgp
, pi
);
4900 rfapiProcessUpdate(pi
->peer
, NULL
, p
, &bgp_static
->prd
,
4901 pi
->attr
, afi
, safi
, pi
->type
,
4902 pi
->sub_type
, &label
);
4904 bgp_unlock_node(rn
);
4905 aspath_unintern(&attr
.aspath
);
4911 /* Make new BGP info. */
4912 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
4914 SET_FLAG(new->flags
, BGP_PATH_VALID
);
4915 new->extra
= bgp_path_info_extra_new();
4917 new->extra
->label
[0] = bgp_static
->label
;
4918 new->extra
->num_labels
= num_labels
;
4921 label
= decode_label(&bgp_static
->label
);
4924 /* Aggregate address increment. */
4925 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4927 /* Register new BGP information. */
4928 bgp_path_info_add(rn
, new);
4929 /* route_node_get lock */
4930 bgp_unlock_node(rn
);
4932 /* Process change. */
4933 bgp_process(bgp
, rn
, afi
, safi
);
4935 if (SAFI_MPLS_VPN
== safi
4936 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4937 vpn_leak_to_vrf_update(bgp
, new);
4940 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
4941 safi
, new->type
, new->sub_type
, &label
);
4944 /* Unintern original. */
4945 aspath_unintern(&attr
.aspath
);
4948 /* Configure static BGP network. When user don't run zebra, static
4949 route should be installed as valid. */
4950 static int bgp_static_set(struct vty
*vty
, const char *negate
,
4951 const char *ip_str
, afi_t afi
, safi_t safi
,
4952 const char *rmap
, int backdoor
, uint32_t label_index
)
4954 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
4957 struct bgp_static
*bgp_static
;
4958 struct bgp_node
*rn
;
4959 uint8_t need_update
= 0;
4961 /* Convert IP prefix string to struct prefix. */
4962 ret
= str2prefix(ip_str
, &p
);
4964 vty_out(vty
, "%% Malformed prefix\n");
4965 return CMD_WARNING_CONFIG_FAILED
;
4967 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4968 vty_out(vty
, "%% Malformed prefix (link-local address)\n");
4969 return CMD_WARNING_CONFIG_FAILED
;
4976 /* Set BGP static route configuration. */
4977 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
4980 vty_out(vty
, "%% Can't find static route specified\n");
4981 return CMD_WARNING_CONFIG_FAILED
;
4984 bgp_static
= bgp_node_get_bgp_static_info(rn
);
4986 if ((label_index
!= BGP_INVALID_LABEL_INDEX
)
4987 && (label_index
!= bgp_static
->label_index
)) {
4989 "%% label-index doesn't match static route\n");
4990 return CMD_WARNING_CONFIG_FAILED
;
4993 if ((rmap
&& bgp_static
->rmap
.name
)
4994 && strcmp(rmap
, bgp_static
->rmap
.name
)) {
4996 "%% route-map name doesn't match static route\n");
4997 return CMD_WARNING_CONFIG_FAILED
;
5000 /* Update BGP RIB. */
5001 if (!bgp_static
->backdoor
)
5002 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
5004 /* Clear configuration. */
5005 bgp_static_free(bgp_static
);
5006 bgp_node_set_bgp_static_info(rn
, NULL
);
5007 bgp_unlock_node(rn
);
5008 bgp_unlock_node(rn
);
5011 /* Set BGP static route configuration. */
5012 rn
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
5014 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5016 /* Configuration change. */
5017 /* Label index cannot be changed. */
5018 if (bgp_static
->label_index
!= label_index
) {
5019 vty_out(vty
, "%% cannot change label-index\n");
5020 return CMD_WARNING_CONFIG_FAILED
;
5023 /* Check previous routes are installed into BGP. */
5024 if (bgp_static
->valid
5025 && bgp_static
->backdoor
!= backdoor
)
5028 bgp_static
->backdoor
= backdoor
;
5031 if (bgp_static
->rmap
.name
)
5032 XFREE(MTYPE_ROUTE_MAP_NAME
,
5033 bgp_static
->rmap
.name
);
5034 route_map_counter_decrement(
5035 bgp_static
->rmap
.map
);
5036 bgp_static
->rmap
.name
=
5037 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
5038 bgp_static
->rmap
.map
=
5039 route_map_lookup_by_name(rmap
);
5040 route_map_counter_increment(
5041 bgp_static
->rmap
.map
);
5043 if (bgp_static
->rmap
.name
)
5044 XFREE(MTYPE_ROUTE_MAP_NAME
,
5045 bgp_static
->rmap
.name
);
5046 route_map_counter_decrement(
5047 bgp_static
->rmap
.map
);
5048 bgp_static
->rmap
.name
= NULL
;
5049 bgp_static
->rmap
.map
= NULL
;
5050 bgp_static
->valid
= 0;
5052 bgp_unlock_node(rn
);
5054 /* New configuration. */
5055 bgp_static
= bgp_static_new();
5056 bgp_static
->backdoor
= backdoor
;
5057 bgp_static
->valid
= 0;
5058 bgp_static
->igpmetric
= 0;
5059 bgp_static
->igpnexthop
.s_addr
= 0;
5060 bgp_static
->label_index
= label_index
;
5063 if (bgp_static
->rmap
.name
)
5064 XFREE(MTYPE_ROUTE_MAP_NAME
,
5065 bgp_static
->rmap
.name
);
5066 route_map_counter_decrement(
5067 bgp_static
->rmap
.map
);
5068 bgp_static
->rmap
.name
=
5069 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
5070 bgp_static
->rmap
.map
=
5071 route_map_lookup_by_name(rmap
);
5072 route_map_counter_increment(
5073 bgp_static
->rmap
.map
);
5075 bgp_node_set_bgp_static_info(rn
, bgp_static
);
5078 bgp_static
->valid
= 1;
5080 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
5082 if (!bgp_static
->backdoor
)
5083 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
5089 void bgp_static_add(struct bgp
*bgp
)
5093 struct bgp_node
*rn
;
5094 struct bgp_node
*rm
;
5095 struct bgp_table
*table
;
5096 struct bgp_static
*bgp_static
;
5098 FOREACH_AFI_SAFI (afi
, safi
)
5099 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5100 rn
= bgp_route_next(rn
)) {
5101 if (!bgp_node_has_bgp_path_info_data(rn
))
5104 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5105 || (safi
== SAFI_EVPN
)) {
5106 table
= bgp_node_get_bgp_table_info(rn
);
5108 for (rm
= bgp_table_top(table
); rm
;
5109 rm
= bgp_route_next(rm
)) {
5111 bgp_node_get_bgp_static_info(
5113 bgp_static_update_safi(bgp
, &rm
->p
,
5120 bgp_node_get_bgp_static_info(rn
), afi
,
5126 /* Called from bgp_delete(). Delete all static routes from the BGP
5128 void bgp_static_delete(struct bgp
*bgp
)
5132 struct bgp_node
*rn
;
5133 struct bgp_node
*rm
;
5134 struct bgp_table
*table
;
5135 struct bgp_static
*bgp_static
;
5137 FOREACH_AFI_SAFI (afi
, safi
)
5138 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5139 rn
= bgp_route_next(rn
)) {
5140 if (!bgp_node_has_bgp_path_info_data(rn
))
5143 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5144 || (safi
== SAFI_EVPN
)) {
5145 table
= bgp_node_get_bgp_table_info(rn
);
5147 for (rm
= bgp_table_top(table
); rm
;
5148 rm
= bgp_route_next(rm
)) {
5150 bgp_node_get_bgp_static_info(
5155 bgp_static_withdraw_safi(
5156 bgp
, &rm
->p
, AFI_IP
, safi
,
5157 (struct prefix_rd
*)&rn
->p
);
5158 bgp_static_free(bgp_static
);
5159 bgp_node_set_bgp_static_info(rn
, NULL
);
5160 bgp_unlock_node(rn
);
5163 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5164 bgp_static_withdraw(bgp
, &rn
->p
, afi
, safi
);
5165 bgp_static_free(bgp_static
);
5166 bgp_node_set_bgp_static_info(rn
, NULL
);
5167 bgp_unlock_node(rn
);
5172 void bgp_static_redo_import_check(struct bgp
*bgp
)
5176 struct bgp_node
*rn
;
5177 struct bgp_node
*rm
;
5178 struct bgp_table
*table
;
5179 struct bgp_static
*bgp_static
;
5181 /* Use this flag to force reprocessing of the route */
5182 bgp_flag_set(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5183 FOREACH_AFI_SAFI (afi
, safi
) {
5184 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5185 rn
= bgp_route_next(rn
)) {
5186 if (!bgp_node_has_bgp_path_info_data(rn
))
5189 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5190 || (safi
== SAFI_EVPN
)) {
5191 table
= bgp_node_get_bgp_table_info(rn
);
5193 for (rm
= bgp_table_top(table
); rm
;
5194 rm
= bgp_route_next(rm
)) {
5196 bgp_node_get_bgp_static_info(
5198 bgp_static_update_safi(bgp
, &rm
->p
,
5203 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5204 bgp_static_update(bgp
, &rn
->p
, bgp_static
, afi
,
5209 bgp_flag_unset(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5212 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
5215 struct bgp_table
*table
;
5216 struct bgp_node
*rn
;
5217 struct bgp_path_info
*pi
;
5219 table
= bgp
->rib
[afi
][safi
];
5220 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
5221 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
5222 if (pi
->peer
== bgp
->peer_self
5223 && ((pi
->type
== ZEBRA_ROUTE_BGP
5224 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5225 || (pi
->type
!= ZEBRA_ROUTE_BGP
5227 == BGP_ROUTE_REDISTRIBUTE
))) {
5228 bgp_aggregate_decrement(bgp
, &rn
->p
, pi
, afi
,
5230 bgp_unlink_nexthop(pi
);
5231 bgp_path_info_delete(rn
, pi
);
5232 bgp_process(bgp
, rn
, afi
, safi
);
5239 * Purge all networks and redistributed routes from routing table.
5240 * Invoked upon the instance going down.
5242 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
5247 FOREACH_AFI_SAFI (afi
, safi
)
5248 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
5253 * Currently this is used to set static routes for VPN and ENCAP.
5254 * I think it can probably be factored with bgp_static_set.
5256 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5257 const char *ip_str
, const char *rd_str
,
5258 const char *label_str
, const char *rmap_str
,
5259 int evpn_type
, const char *esi
, const char *gwip
,
5260 const char *ethtag
, const char *routermac
)
5262 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5265 struct prefix_rd prd
;
5266 struct bgp_node
*prn
;
5267 struct bgp_node
*rn
;
5268 struct bgp_table
*table
;
5269 struct bgp_static
*bgp_static
;
5270 mpls_label_t label
= MPLS_INVALID_LABEL
;
5271 struct prefix gw_ip
;
5273 /* validate ip prefix */
5274 ret
= str2prefix(ip_str
, &p
);
5276 vty_out(vty
, "%% Malformed prefix\n");
5277 return CMD_WARNING_CONFIG_FAILED
;
5280 if ((afi
== AFI_L2VPN
)
5281 && (bgp_build_evpn_prefix(evpn_type
,
5282 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5283 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5284 return CMD_WARNING_CONFIG_FAILED
;
5287 ret
= str2prefix_rd(rd_str
, &prd
);
5289 vty_out(vty
, "%% Malformed rd\n");
5290 return CMD_WARNING_CONFIG_FAILED
;
5294 unsigned long label_val
;
5295 label_val
= strtoul(label_str
, NULL
, 10);
5296 encode_label(label_val
, &label
);
5299 if (safi
== SAFI_EVPN
) {
5300 if (esi
&& str2esi(esi
, NULL
) == 0) {
5301 vty_out(vty
, "%% Malformed ESI\n");
5302 return CMD_WARNING_CONFIG_FAILED
;
5304 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
5305 vty_out(vty
, "%% Malformed Router MAC\n");
5306 return CMD_WARNING_CONFIG_FAILED
;
5309 memset(&gw_ip
, 0, sizeof(struct prefix
));
5310 ret
= str2prefix(gwip
, &gw_ip
);
5312 vty_out(vty
, "%% Malformed GatewayIp\n");
5313 return CMD_WARNING_CONFIG_FAILED
;
5315 if ((gw_ip
.family
== AF_INET
5316 && is_evpn_prefix_ipaddr_v6(
5317 (struct prefix_evpn
*)&p
))
5318 || (gw_ip
.family
== AF_INET6
5319 && is_evpn_prefix_ipaddr_v4(
5320 (struct prefix_evpn
*)&p
))) {
5322 "%% GatewayIp family differs with IP prefix\n");
5323 return CMD_WARNING_CONFIG_FAILED
;
5327 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5328 if (!bgp_node_has_bgp_path_info_data(prn
))
5329 bgp_node_set_bgp_table_info(prn
,
5330 bgp_table_init(bgp
, afi
, safi
));
5331 table
= bgp_node_get_bgp_table_info(prn
);
5333 rn
= bgp_node_get(table
, &p
);
5335 if (bgp_node_has_bgp_path_info_data(rn
)) {
5336 vty_out(vty
, "%% Same network configuration exists\n");
5337 bgp_unlock_node(rn
);
5339 /* New configuration. */
5340 bgp_static
= bgp_static_new();
5341 bgp_static
->backdoor
= 0;
5342 bgp_static
->valid
= 0;
5343 bgp_static
->igpmetric
= 0;
5344 bgp_static
->igpnexthop
.s_addr
= 0;
5345 bgp_static
->label
= label
;
5346 bgp_static
->prd
= prd
;
5349 if (bgp_static
->rmap
.name
)
5350 XFREE(MTYPE_ROUTE_MAP_NAME
,
5351 bgp_static
->rmap
.name
);
5352 route_map_counter_decrement(bgp_static
->rmap
.map
);
5353 bgp_static
->rmap
.name
=
5354 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
5355 bgp_static
->rmap
.map
=
5356 route_map_lookup_by_name(rmap_str
);
5357 route_map_counter_increment(bgp_static
->rmap
.map
);
5360 if (safi
== SAFI_EVPN
) {
5362 bgp_static
->eth_s_id
=
5364 sizeof(struct eth_segment_id
));
5365 str2esi(esi
, bgp_static
->eth_s_id
);
5368 bgp_static
->router_mac
=
5369 XCALLOC(MTYPE_ATTR
, ETH_ALEN
+ 1);
5370 (void)prefix_str2mac(routermac
,
5371 bgp_static
->router_mac
);
5374 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
5376 bgp_node_set_bgp_static_info(rn
, bgp_static
);
5378 bgp_static
->valid
= 1;
5379 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
5385 /* Configure static BGP network. */
5386 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5387 const char *ip_str
, const char *rd_str
,
5388 const char *label_str
, int evpn_type
, const char *esi
,
5389 const char *gwip
, const char *ethtag
)
5391 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5394 struct prefix_rd prd
;
5395 struct bgp_node
*prn
;
5396 struct bgp_node
*rn
;
5397 struct bgp_table
*table
;
5398 struct bgp_static
*bgp_static
;
5399 mpls_label_t label
= MPLS_INVALID_LABEL
;
5401 /* Convert IP prefix string to struct prefix. */
5402 ret
= str2prefix(ip_str
, &p
);
5404 vty_out(vty
, "%% Malformed prefix\n");
5405 return CMD_WARNING_CONFIG_FAILED
;
5408 if ((afi
== AFI_L2VPN
)
5409 && (bgp_build_evpn_prefix(evpn_type
,
5410 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5411 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5412 return CMD_WARNING_CONFIG_FAILED
;
5414 ret
= str2prefix_rd(rd_str
, &prd
);
5416 vty_out(vty
, "%% Malformed rd\n");
5417 return CMD_WARNING_CONFIG_FAILED
;
5421 unsigned long label_val
;
5422 label_val
= strtoul(label_str
, NULL
, 10);
5423 encode_label(label_val
, &label
);
5426 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5427 if (!bgp_node_has_bgp_path_info_data(prn
))
5428 bgp_node_set_bgp_table_info(prn
,
5429 bgp_table_init(bgp
, afi
, safi
));
5431 bgp_unlock_node(prn
);
5432 table
= bgp_node_get_bgp_table_info(prn
);
5434 rn
= bgp_node_lookup(table
, &p
);
5437 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
5439 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5440 bgp_static_free(bgp_static
);
5441 bgp_node_set_bgp_static_info(rn
, NULL
);
5442 bgp_unlock_node(rn
);
5443 bgp_unlock_node(rn
);
5445 vty_out(vty
, "%% Can't find the route\n");
5450 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
5451 const char *rmap_name
)
5453 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5454 struct bgp_rmap
*rmap
;
5456 rmap
= &bgp
->table_map
[afi
][safi
];
5459 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5460 route_map_counter_decrement(rmap
->map
);
5461 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
5462 rmap
->map
= route_map_lookup_by_name(rmap_name
);
5463 route_map_counter_increment(rmap
->map
);
5466 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5467 route_map_counter_decrement(rmap
->map
);
5472 if (bgp_fibupd_safi(safi
))
5473 bgp_zebra_announce_table(bgp
, afi
, safi
);
5478 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
5479 const char *rmap_name
)
5481 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5482 struct bgp_rmap
*rmap
;
5484 rmap
= &bgp
->table_map
[afi
][safi
];
5486 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5487 route_map_counter_decrement(rmap
->map
);
5491 if (bgp_fibupd_safi(safi
))
5492 bgp_zebra_announce_table(bgp
, afi
, safi
);
5497 void bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
5500 if (bgp
->table_map
[afi
][safi
].name
) {
5501 vty_out(vty
, " table-map %s\n",
5502 bgp
->table_map
[afi
][safi
].name
);
5506 DEFUN (bgp_table_map
,
5509 "BGP table to RIB route download filter\n"
5510 "Name of the route map\n")
5513 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5514 argv
[idx_word
]->arg
);
5516 DEFUN (no_bgp_table_map
,
5517 no_bgp_table_map_cmd
,
5518 "no table-map WORD",
5520 "BGP table to RIB route download filter\n"
5521 "Name of the route map\n")
5524 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5525 argv
[idx_word
]->arg
);
5531 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
5532 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
5533 backdoor$backdoor}]",
5535 "Specify a network to announce via BGP\n"
5540 "Route-map to modify the attributes\n"
5541 "Name of the route map\n"
5542 "Label index to associate with the prefix\n"
5543 "Label index value\n"
5544 "Specify a BGP backdoor route\n")
5546 char addr_prefix_str
[BUFSIZ
];
5551 ret
= netmask_str2prefix_str(address_str
, netmask_str
,
5554 vty_out(vty
, "%% Inconsistent address and mask\n");
5555 return CMD_WARNING_CONFIG_FAILED
;
5559 return bgp_static_set(
5560 vty
, no
, address_str
? addr_prefix_str
: prefix_str
, AFI_IP
,
5561 bgp_node_safi(vty
), map_name
, backdoor
? 1 : 0,
5562 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5565 DEFPY(ipv6_bgp_network
,
5566 ipv6_bgp_network_cmd
,
5567 "[no] network X:X::X:X/M$prefix \
5568 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
5570 "Specify a network to announce via BGP\n"
5572 "Route-map to modify the attributes\n"
5573 "Name of the route map\n"
5574 "Label index to associate with the prefix\n"
5575 "Label index value\n")
5577 return bgp_static_set(
5578 vty
, no
, prefix_str
, AFI_IP6
, bgp_node_safi(vty
), map_name
, 0,
5579 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5582 /* Aggreagete address:
5584 advertise-map Set condition to advertise attribute
5585 as-set Generate AS set path information
5586 attribute-map Set attributes of aggregate
5587 route-map Set parameters of aggregate
5588 summary-only Filter more specific routes from updates
5589 suppress-map Conditionally filter more specific routes from updates
5592 struct bgp_aggregate
{
5593 /* Summary-only flag. */
5594 uint8_t summary_only
;
5596 /* AS set generation. */
5599 /* Route-map for aggregated route. */
5600 struct route_map
*map
;
5602 /* Suppress-count. */
5603 unsigned long count
;
5605 /* SAFI configuration. */
5609 static struct bgp_aggregate
*bgp_aggregate_new(void)
5611 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
5614 static void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
5616 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
5619 static int bgp_aggregate_info_same(struct bgp_path_info
*pi
, uint8_t origin
,
5620 struct aspath
*aspath
,
5621 struct community
*comm
,
5622 struct ecommunity
*ecomm
,
5623 struct lcommunity
*lcomm
)
5625 static struct aspath
*ae
= NULL
;
5628 ae
= aspath_empty();
5633 if (origin
!= pi
->attr
->origin
)
5636 if (!aspath_cmp(pi
->attr
->aspath
, (aspath
) ? aspath
: ae
))
5639 if (!community_cmp(pi
->attr
->community
, comm
))
5642 if (!ecommunity_cmp(pi
->attr
->ecommunity
, ecomm
))
5645 if (!lcommunity_cmp(pi
->attr
->lcommunity
, lcomm
))
5648 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
5654 static void bgp_aggregate_install(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
5655 struct prefix
*p
, uint8_t origin
,
5656 struct aspath
*aspath
,
5657 struct community
*community
,
5658 struct ecommunity
*ecommunity
,
5659 struct lcommunity
*lcommunity
,
5660 uint8_t atomic_aggregate
,
5661 struct bgp_aggregate
*aggregate
)
5663 struct bgp_node
*rn
;
5664 struct bgp_table
*table
;
5665 struct bgp_path_info
*pi
, *orig
, *new;
5667 table
= bgp
->rib
[afi
][safi
];
5669 rn
= bgp_node_get(table
, p
);
5671 for (orig
= pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
5672 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5673 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5676 if (aggregate
->count
> 0) {
5678 * If the aggregate information has not changed
5679 * no need to re-install it again.
5681 if (bgp_aggregate_info_same(orig
, origin
, aspath
, community
,
5682 ecommunity
, lcommunity
)) {
5683 bgp_unlock_node(rn
);
5686 aspath_free(aspath
);
5688 community_free(&community
);
5690 ecommunity_free(&ecommunity
);
5692 lcommunity_free(&lcommunity
);
5698 * Mark the old as unusable
5701 bgp_path_info_delete(rn
, pi
);
5703 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0,
5705 bgp_attr_aggregate_intern(bgp
, origin
, aspath
,
5706 community
, ecommunity
,
5711 SET_FLAG(new->flags
, BGP_PATH_VALID
);
5713 bgp_path_info_add(rn
, new);
5714 bgp_process(bgp
, rn
, afi
, safi
);
5716 for (pi
= orig
; pi
; pi
= pi
->next
)
5717 if (pi
->peer
== bgp
->peer_self
5718 && pi
->type
== ZEBRA_ROUTE_BGP
5719 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5722 /* Withdraw static BGP route from routing table. */
5724 bgp_path_info_delete(rn
, pi
);
5725 bgp_process(bgp
, rn
, afi
, safi
);
5729 bgp_unlock_node(rn
);
5732 /* Update an aggregate as routes are added/removed from the BGP table */
5733 static void bgp_aggregate_route(struct bgp
*bgp
, struct prefix
*p
,
5734 struct bgp_path_info
*pinew
, afi_t afi
,
5735 safi_t safi
, struct bgp_path_info
*del
,
5736 struct bgp_aggregate
*aggregate
)
5738 struct bgp_table
*table
;
5739 struct bgp_node
*top
;
5740 struct bgp_node
*rn
;
5742 struct aspath
*aspath
= NULL
;
5743 struct aspath
*asmerge
= NULL
;
5744 struct community
*community
= NULL
;
5745 struct community
*commerge
= NULL
;
5746 struct ecommunity
*ecommunity
= NULL
;
5747 struct ecommunity
*ecommerge
= NULL
;
5748 struct lcommunity
*lcommunity
= NULL
;
5749 struct lcommunity
*lcommerge
= NULL
;
5750 struct bgp_path_info
*pi
;
5751 unsigned long match
= 0;
5752 uint8_t atomic_aggregate
= 0;
5754 /* ORIGIN attribute: If at least one route among routes that are
5755 aggregated has ORIGIN with the value INCOMPLETE, then the
5756 aggregated route must have the ORIGIN attribute with the value
5757 INCOMPLETE. Otherwise, if at least one route among routes that
5758 are aggregated has ORIGIN with the value EGP, then the aggregated
5759 route must have the origin attribute with the value EGP. In all
5760 other case the value of the ORIGIN attribute of the aggregated
5761 route is INTERNAL. */
5762 origin
= BGP_ORIGIN_IGP
;
5764 table
= bgp
->rib
[afi
][safi
];
5766 top
= bgp_node_get(table
, p
);
5767 for (rn
= bgp_node_get(table
, p
); rn
;
5768 rn
= bgp_route_next_until(rn
, top
)) {
5769 if (rn
->p
.prefixlen
<= p
->prefixlen
)
5774 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
5775 if (BGP_PATH_HOLDDOWN(pi
))
5778 if (del
&& pi
== del
)
5782 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
5783 atomic_aggregate
= 1;
5785 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5789 * summary-only aggregate route suppress
5790 * aggregated route announcements.
5792 if (aggregate
->summary_only
) {
5793 (bgp_path_info_extra_get(pi
))->suppress
++;
5794 bgp_path_info_set_flag(rn
, pi
,
5795 BGP_PATH_ATTR_CHANGED
);
5802 * If at least one route among routes that are
5803 * aggregated has ORIGIN with the value INCOMPLETE,
5804 * then the aggregated route MUST have the ORIGIN
5805 * attribute with the value INCOMPLETE. Otherwise, if
5806 * at least one route among routes that are aggregated
5807 * has ORIGIN with the value EGP, then the aggregated
5808 * route MUST have the ORIGIN attribute with the value
5811 if (origin
< pi
->attr
->origin
)
5812 origin
= pi
->attr
->origin
;
5814 if (!aggregate
->as_set
)
5818 * as-set aggregate route generate origin, as path,
5819 * and community aggregation.
5822 asmerge
= aspath_aggregate(aspath
,
5824 aspath_free(aspath
);
5827 aspath
= aspath_dup(pi
->attr
->aspath
);
5829 if (pi
->attr
->community
) {
5831 commerge
= community_merge(
5832 community
, pi
->attr
->community
);
5834 community_uniq_sort(commerge
);
5835 community_free(&commerge
);
5837 community
= community_dup(
5838 pi
->attr
->community
);
5841 if (pi
->attr
->ecommunity
) {
5843 ecommerge
= ecommunity_merge(
5845 pi
->attr
->ecommunity
);
5847 ecommunity_uniq_sort(ecommerge
);
5848 ecommunity_free(&ecommerge
);
5850 ecommunity
= ecommunity_dup(
5851 pi
->attr
->ecommunity
);
5854 if (pi
->attr
->lcommunity
) {
5856 lcommerge
= lcommunity_merge(
5858 pi
->attr
->lcommunity
);
5860 lcommunity_uniq_sort(lcommerge
);
5861 lcommunity_free(&lcommerge
);
5863 lcommunity
= lcommunity_dup(
5864 pi
->attr
->lcommunity
);
5868 bgp_process(bgp
, rn
, afi
, safi
);
5870 bgp_unlock_node(top
);
5875 if (aggregate
->summary_only
)
5876 (bgp_path_info_extra_get(pinew
))->suppress
++;
5878 if (origin
< pinew
->attr
->origin
)
5879 origin
= pinew
->attr
->origin
;
5881 if (aggregate
->as_set
) {
5883 asmerge
= aspath_aggregate(aspath
,
5884 pinew
->attr
->aspath
);
5885 aspath_free(aspath
);
5888 aspath
= aspath_dup(pinew
->attr
->aspath
);
5890 if (pinew
->attr
->community
) {
5892 commerge
= community_merge(
5894 pinew
->attr
->community
);
5896 community_uniq_sort(commerge
);
5897 community_free(&commerge
);
5899 community
= community_dup(
5900 pinew
->attr
->community
);
5903 if (pinew
->attr
->ecommunity
) {
5905 ecommerge
= ecommunity_merge(
5907 pinew
->attr
->ecommunity
);
5909 ecommunity_uniq_sort(ecommerge
);
5910 ecommunity_free(&ecommerge
);
5912 ecommunity
= ecommunity_dup(
5913 pinew
->attr
->ecommunity
);
5916 if (pinew
->attr
->lcommunity
) {
5918 lcommerge
= lcommunity_merge(
5920 pinew
->attr
->lcommunity
);
5922 lcommunity_uniq_sort(lcommerge
);
5923 lcommunity_free(&lcommerge
);
5925 lcommunity
= lcommunity_dup(
5926 pinew
->attr
->lcommunity
);
5931 bgp_aggregate_install(bgp
, afi
, safi
, p
, origin
, aspath
, community
,
5932 ecommunity
, lcommunity
, atomic_aggregate
,
5935 if (aggregate
->count
== 0) {
5937 aspath_free(aspath
);
5939 community_free(&community
);
5941 ecommunity_free(&ecommunity
);
5943 lcommunity_free(&lcommunity
);
5947 static void bgp_aggregate_delete(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
5948 safi_t safi
, struct bgp_aggregate
*aggregate
)
5950 struct bgp_table
*table
;
5951 struct bgp_node
*top
;
5952 struct bgp_node
*rn
;
5953 struct bgp_path_info
*pi
;
5954 unsigned long match
;
5956 table
= bgp
->rib
[afi
][safi
];
5958 /* If routes exists below this node, generate aggregate routes. */
5959 top
= bgp_node_get(table
, p
);
5960 for (rn
= bgp_node_get(table
, p
); rn
;
5961 rn
= bgp_route_next_until(rn
, top
)) {
5962 if (rn
->p
.prefixlen
<= p
->prefixlen
)
5966 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
5967 if (BGP_PATH_HOLDDOWN(pi
))
5970 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5973 if (aggregate
->summary_only
&& pi
->extra
) {
5974 pi
->extra
->suppress
--;
5976 if (pi
->extra
->suppress
== 0) {
5977 bgp_path_info_set_flag(
5978 rn
, pi
, BGP_PATH_ATTR_CHANGED
);
5985 /* If this node was suppressed, process the change. */
5987 bgp_process(bgp
, rn
, afi
, safi
);
5989 bgp_unlock_node(top
);
5992 void bgp_aggregate_increment(struct bgp
*bgp
, struct prefix
*p
,
5993 struct bgp_path_info
*pi
, afi_t afi
, safi_t safi
)
5995 struct bgp_node
*child
;
5996 struct bgp_node
*rn
;
5997 struct bgp_aggregate
*aggregate
;
5998 struct bgp_table
*table
;
6000 table
= bgp
->aggregate
[afi
][safi
];
6002 /* No aggregates configured. */
6003 if (bgp_table_top_nolock(table
) == NULL
)
6006 if (p
->prefixlen
== 0)
6009 if (BGP_PATH_HOLDDOWN(pi
))
6012 child
= bgp_node_get(table
, p
);
6014 /* Aggregate address configuration check. */
6015 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
)) {
6016 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6017 if (aggregate
!= NULL
&& rn
->p
.prefixlen
< p
->prefixlen
) {
6018 bgp_aggregate_delete(bgp
, &rn
->p
, afi
, safi
, aggregate
);
6019 bgp_aggregate_route(bgp
, &rn
->p
, pi
, afi
, safi
, NULL
,
6023 bgp_unlock_node(child
);
6026 void bgp_aggregate_decrement(struct bgp
*bgp
, struct prefix
*p
,
6027 struct bgp_path_info
*del
, afi_t afi
, safi_t safi
)
6029 struct bgp_node
*child
;
6030 struct bgp_node
*rn
;
6031 struct bgp_aggregate
*aggregate
;
6032 struct bgp_table
*table
;
6034 table
= bgp
->aggregate
[afi
][safi
];
6036 /* No aggregates configured. */
6037 if (bgp_table_top_nolock(table
) == NULL
)
6040 if (p
->prefixlen
== 0)
6043 child
= bgp_node_get(table
, p
);
6045 /* Aggregate address configuration check. */
6046 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
)) {
6047 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6048 if (aggregate
!= NULL
&& rn
->p
.prefixlen
< p
->prefixlen
) {
6049 bgp_aggregate_delete(bgp
, &rn
->p
, afi
, safi
, aggregate
);
6050 bgp_aggregate_route(bgp
, &rn
->p
, NULL
, afi
, safi
, del
,
6054 bgp_unlock_node(child
);
6057 /* Aggregate route attribute. */
6058 #define AGGREGATE_SUMMARY_ONLY 1
6059 #define AGGREGATE_AS_SET 1
6061 static int bgp_aggregate_unset(struct vty
*vty
, const char *prefix_str
,
6062 afi_t afi
, safi_t safi
)
6064 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6067 struct bgp_node
*rn
;
6068 struct bgp_aggregate
*aggregate
;
6070 /* Convert string to prefix structure. */
6071 ret
= str2prefix(prefix_str
, &p
);
6073 vty_out(vty
, "Malformed prefix\n");
6074 return CMD_WARNING_CONFIG_FAILED
;
6078 /* Old configuration check. */
6079 rn
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], &p
);
6082 "%% There is no aggregate-address configuration.\n");
6083 return CMD_WARNING_CONFIG_FAILED
;
6086 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6087 bgp_aggregate_delete(bgp
, &p
, afi
, safi
, aggregate
);
6088 bgp_aggregate_install(bgp
, afi
, safi
, &p
, 0, NULL
, NULL
,
6089 NULL
, NULL
, 0, aggregate
);
6091 /* Unlock aggregate address configuration. */
6092 bgp_node_set_bgp_aggregate_info(rn
, NULL
);
6093 bgp_aggregate_free(aggregate
);
6094 bgp_unlock_node(rn
);
6095 bgp_unlock_node(rn
);
6100 static int bgp_aggregate_set(struct vty
*vty
, const char *prefix_str
, afi_t afi
,
6101 safi_t safi
, uint8_t summary_only
, uint8_t as_set
)
6103 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6106 struct bgp_node
*rn
;
6107 struct bgp_aggregate
*aggregate
;
6109 /* Convert string to prefix structure. */
6110 ret
= str2prefix(prefix_str
, &p
);
6112 vty_out(vty
, "Malformed prefix\n");
6113 return CMD_WARNING_CONFIG_FAILED
;
6117 if ((afi
== AFI_IP
&& p
.prefixlen
== IPV4_MAX_BITLEN
) ||
6118 (afi
== AFI_IP6
&& p
.prefixlen
== IPV6_MAX_BITLEN
)) {
6119 vty_out(vty
, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
6121 return CMD_WARNING_CONFIG_FAILED
;
6124 /* Old configuration check. */
6125 rn
= bgp_node_get(bgp
->aggregate
[afi
][safi
], &p
);
6127 if (bgp_node_has_bgp_path_info_data(rn
)) {
6128 vty_out(vty
, "There is already same aggregate network.\n");
6129 /* try to remove the old entry */
6130 ret
= bgp_aggregate_unset(vty
, prefix_str
, afi
, safi
);
6132 vty_out(vty
, "Error deleting aggregate.\n");
6133 bgp_unlock_node(rn
);
6134 return CMD_WARNING_CONFIG_FAILED
;
6138 /* Make aggregate address structure. */
6139 aggregate
= bgp_aggregate_new();
6140 aggregate
->summary_only
= summary_only
;
6141 aggregate
->as_set
= as_set
;
6142 aggregate
->safi
= safi
;
6143 bgp_node_set_bgp_aggregate_info(rn
, aggregate
);
6145 /* Aggregate address insert into BGP routing table. */
6146 bgp_aggregate_route(bgp
, &p
, NULL
, afi
, safi
, NULL
, aggregate
);
6151 DEFUN (aggregate_address
,
6152 aggregate_address_cmd
,
6153 "aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
6154 "Configure BGP aggregate entries\n"
6155 "Aggregate prefix\n"
6156 "Generate AS set path information\n"
6157 "Filter more specific routes from updates\n"
6158 "Filter more specific routes from updates\n"
6159 "Generate AS set path information\n")
6162 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
6163 char *prefix
= argv
[idx
]->arg
;
6165 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
6167 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6168 ? AGGREGATE_SUMMARY_ONLY
6171 return bgp_aggregate_set(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
),
6172 summary_only
, as_set
);
6175 DEFUN (aggregate_address_mask
,
6176 aggregate_address_mask_cmd
,
6177 "aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
6178 "Configure BGP aggregate entries\n"
6179 "Aggregate address\n"
6181 "Generate AS set path information\n"
6182 "Filter more specific routes from updates\n"
6183 "Filter more specific routes from updates\n"
6184 "Generate AS set path information\n")
6187 argv_find(argv
, argc
, "A.B.C.D", &idx
);
6188 char *prefix
= argv
[idx
]->arg
;
6189 char *mask
= argv
[idx
+ 1]->arg
;
6191 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
6193 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6194 ? AGGREGATE_SUMMARY_ONLY
6197 char prefix_str
[BUFSIZ
];
6198 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
6201 vty_out(vty
, "%% Inconsistent address and mask\n");
6202 return CMD_WARNING_CONFIG_FAILED
;
6205 return bgp_aggregate_set(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
),
6206 summary_only
, as_set
);
6209 DEFUN (no_aggregate_address
,
6210 no_aggregate_address_cmd
,
6211 "no aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
6213 "Configure BGP aggregate entries\n"
6214 "Aggregate prefix\n"
6215 "Generate AS set path information\n"
6216 "Filter more specific routes from updates\n"
6217 "Filter more specific routes from updates\n"
6218 "Generate AS set path information\n")
6221 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
6222 char *prefix
= argv
[idx
]->arg
;
6223 return bgp_aggregate_unset(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
));
6226 DEFUN (no_aggregate_address_mask
,
6227 no_aggregate_address_mask_cmd
,
6228 "no aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
6230 "Configure BGP aggregate entries\n"
6231 "Aggregate address\n"
6233 "Generate AS set path information\n"
6234 "Filter more specific routes from updates\n"
6235 "Filter more specific routes from updates\n"
6236 "Generate AS set path information\n")
6239 argv_find(argv
, argc
, "A.B.C.D", &idx
);
6240 char *prefix
= argv
[idx
]->arg
;
6241 char *mask
= argv
[idx
+ 1]->arg
;
6243 char prefix_str
[BUFSIZ
];
6244 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
6247 vty_out(vty
, "%% Inconsistent address and mask\n");
6248 return CMD_WARNING_CONFIG_FAILED
;
6251 return bgp_aggregate_unset(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
));
6254 DEFUN (ipv6_aggregate_address
,
6255 ipv6_aggregate_address_cmd
,
6256 "aggregate-address X:X::X:X/M [summary-only]",
6257 "Configure BGP aggregate entries\n"
6258 "Aggregate prefix\n"
6259 "Filter more specific routes from updates\n")
6262 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6263 char *prefix
= argv
[idx
]->arg
;
6264 int sum_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6265 ? AGGREGATE_SUMMARY_ONLY
6267 return bgp_aggregate_set(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
, sum_only
,
6271 DEFUN (no_ipv6_aggregate_address
,
6272 no_ipv6_aggregate_address_cmd
,
6273 "no aggregate-address X:X::X:X/M [summary-only]",
6275 "Configure BGP aggregate entries\n"
6276 "Aggregate prefix\n"
6277 "Filter more specific routes from updates\n")
6280 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6281 char *prefix
= argv
[idx
]->arg
;
6282 return bgp_aggregate_unset(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
);
6285 /* Redistribute route treatment. */
6286 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
6287 const union g_addr
*nexthop
, ifindex_t ifindex
,
6288 enum nexthop_types_t nhtype
, uint32_t metric
,
6289 uint8_t type
, unsigned short instance
,
6292 struct bgp_path_info
*new;
6293 struct bgp_path_info
*bpi
;
6294 struct bgp_path_info rmap_path
;
6295 struct bgp_node
*bn
;
6297 struct attr
*new_attr
;
6300 struct bgp_redist
*red
;
6302 /* Make default attribute. */
6303 bgp_attr_default_set(&attr
, BGP_ORIGIN_INCOMPLETE
);
6306 case NEXTHOP_TYPE_IFINDEX
:
6308 case NEXTHOP_TYPE_IPV4
:
6309 case NEXTHOP_TYPE_IPV4_IFINDEX
:
6310 attr
.nexthop
= nexthop
->ipv4
;
6312 case NEXTHOP_TYPE_IPV6
:
6313 case NEXTHOP_TYPE_IPV6_IFINDEX
:
6314 attr
.mp_nexthop_global
= nexthop
->ipv6
;
6315 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6317 case NEXTHOP_TYPE_BLACKHOLE
:
6318 switch (p
->family
) {
6320 attr
.nexthop
.s_addr
= INADDR_ANY
;
6323 memset(&attr
.mp_nexthop_global
, 0,
6324 sizeof(attr
.mp_nexthop_global
));
6325 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6330 attr
.nh_ifindex
= ifindex
;
6333 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6336 afi
= family2afi(p
->family
);
6338 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6340 struct attr attr_new
;
6342 /* Copy attribute for modification. */
6343 bgp_attr_dup(&attr_new
, &attr
);
6345 if (red
->redist_metric_flag
)
6346 attr_new
.med
= red
->redist_metric
;
6348 /* Apply route-map. */
6349 if (red
->rmap
.name
) {
6350 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
6351 rmap_path
.peer
= bgp
->peer_self
;
6352 rmap_path
.attr
= &attr_new
;
6354 SET_FLAG(bgp
->peer_self
->rmap_type
,
6355 PEER_RMAP_TYPE_REDISTRIBUTE
);
6357 ret
= route_map_apply(red
->rmap
.map
, p
, RMAP_BGP
,
6360 bgp
->peer_self
->rmap_type
= 0;
6362 if (ret
== RMAP_DENYMATCH
) {
6363 /* Free uninterned attribute. */
6364 bgp_attr_flush(&attr_new
);
6366 /* Unintern original. */
6367 aspath_unintern(&attr
.aspath
);
6368 bgp_redistribute_delete(bgp
, p
, type
, instance
);
6373 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
6374 bgp_attr_add_gshut_community(&attr_new
);
6376 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6377 SAFI_UNICAST
, p
, NULL
);
6379 new_attr
= bgp_attr_intern(&attr_new
);
6381 for (bpi
= bgp_node_get_bgp_path_info(bn
); bpi
;
6383 if (bpi
->peer
== bgp
->peer_self
6384 && bpi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
6388 /* Ensure the (source route) type is updated. */
6390 if (attrhash_cmp(bpi
->attr
, new_attr
)
6391 && !CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
)) {
6392 bgp_attr_unintern(&new_attr
);
6393 aspath_unintern(&attr
.aspath
);
6394 bgp_unlock_node(bn
);
6397 /* The attribute is changed. */
6398 bgp_path_info_set_flag(bn
, bpi
,
6399 BGP_PATH_ATTR_CHANGED
);
6401 /* Rewrite BGP route information. */
6402 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
6403 bgp_path_info_restore(bn
, bpi
);
6405 bgp_aggregate_decrement(
6406 bgp
, p
, bpi
, afi
, SAFI_UNICAST
);
6407 bgp_attr_unintern(&bpi
->attr
);
6408 bpi
->attr
= new_attr
;
6409 bpi
->uptime
= bgp_clock();
6411 /* Process change. */
6412 bgp_aggregate_increment(bgp
, p
, bpi
, afi
,
6414 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6415 bgp_unlock_node(bn
);
6416 aspath_unintern(&attr
.aspath
);
6418 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6420 == BGP_INSTANCE_TYPE_DEFAULT
)) {
6422 vpn_leak_from_vrf_update(
6423 bgp_get_default(), bgp
, bpi
);
6429 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
6430 bgp
->peer_self
, new_attr
, bn
);
6431 SET_FLAG(new->flags
, BGP_PATH_VALID
);
6433 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
6434 bgp_path_info_add(bn
, new);
6435 bgp_unlock_node(bn
);
6436 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6438 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6439 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6441 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
6445 /* Unintern original. */
6446 aspath_unintern(&attr
.aspath
);
6449 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, uint8_t type
,
6450 unsigned short instance
)
6453 struct bgp_node
*rn
;
6454 struct bgp_path_info
*pi
;
6455 struct bgp_redist
*red
;
6457 afi
= family2afi(p
->family
);
6459 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6461 rn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6462 SAFI_UNICAST
, p
, NULL
);
6464 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
6465 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
)
6469 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6470 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6472 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6475 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, SAFI_UNICAST
);
6476 bgp_path_info_delete(rn
, pi
);
6477 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6479 bgp_unlock_node(rn
);
6483 /* Withdraw specified route type's route. */
6484 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
6485 unsigned short instance
)
6487 struct bgp_node
*rn
;
6488 struct bgp_path_info
*pi
;
6489 struct bgp_table
*table
;
6491 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
6493 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
6494 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
6495 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
6496 && pi
->instance
== instance
)
6500 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6501 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6503 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6506 bgp_aggregate_decrement(bgp
, &rn
->p
, pi
, afi
,
6508 bgp_path_info_delete(rn
, pi
);
6509 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6514 /* Static function to display route. */
6515 static void route_vty_out_route(struct prefix
*p
, struct vty
*vty
,
6522 if (p
->family
== AF_INET
) {
6526 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
6529 json_object_string_add(json
, "prefix",
6530 inet_ntop(p
->family
,
6533 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
6534 prefix2str(p
, buf2
, PREFIX_STRLEN
);
6535 json_object_string_add(json
, "network", buf2
);
6537 } else if (p
->family
== AF_ETHERNET
) {
6538 prefix2str(p
, buf
, PREFIX_STRLEN
);
6539 len
= vty_out(vty
, "%s", buf
);
6540 } else if (p
->family
== AF_EVPN
) {
6544 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf
,
6547 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
6548 } else if (p
->family
== AF_FLOWSPEC
) {
6549 route_vty_out_flowspec(vty
, p
, NULL
,
6551 NLRI_STRING_FORMAT_JSON_SIMPLE
:
6552 NLRI_STRING_FORMAT_MIN
, json
);
6557 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
6560 json_object_string_add(json
, "prefix",
6561 inet_ntop(p
->family
,
6564 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
6565 prefix2str(p
, buf2
, PREFIX_STRLEN
);
6566 json_object_string_add(json
, "network", buf2
);
6573 vty_out(vty
, "\n%*s", 20, " ");
6575 vty_out(vty
, "%*s", len
, " ");
6579 enum bgp_display_type
{
6583 /* Print the short form route status for a bgp_path_info */
6584 static void route_vty_short_status_out(struct vty
*vty
,
6585 struct bgp_path_info
*path
,
6586 json_object
*json_path
)
6590 /* Route status display. */
6591 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
6592 json_object_boolean_true_add(json_path
, "removed");
6594 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
6595 json_object_boolean_true_add(json_path
, "stale");
6597 if (path
->extra
&& path
->extra
->suppress
)
6598 json_object_boolean_true_add(json_path
, "suppressed");
6600 if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
6601 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
6602 json_object_boolean_true_add(json_path
, "valid");
6605 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
6606 json_object_boolean_true_add(json_path
, "history");
6608 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
6609 json_object_boolean_true_add(json_path
, "damped");
6611 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
6612 json_object_boolean_true_add(json_path
, "bestpath");
6614 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
6615 json_object_boolean_true_add(json_path
, "multipath");
6617 /* Internal route. */
6618 if ((path
->peer
->as
)
6619 && (path
->peer
->as
== path
->peer
->local_as
))
6620 json_object_string_add(json_path
, "pathFrom",
6623 json_object_string_add(json_path
, "pathFrom",
6629 /* Route status display. */
6630 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
6632 else if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
6634 else if (path
->extra
&& path
->extra
->suppress
)
6636 else if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
6637 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
6643 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
6645 else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
6647 else if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
6649 else if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
6654 /* Internal route. */
6655 if (path
->peer
&& (path
->peer
->as
)
6656 && (path
->peer
->as
== path
->peer
->local_as
))
6662 /* called from terminal list command */
6663 void route_vty_out(struct vty
*vty
, struct prefix
*p
,
6664 struct bgp_path_info
*path
, int display
, safi_t safi
,
6665 json_object
*json_paths
)
6668 json_object
*json_path
= NULL
;
6669 json_object
*json_nexthops
= NULL
;
6670 json_object
*json_nexthop_global
= NULL
;
6671 json_object
*json_nexthop_ll
= NULL
;
6672 char vrf_id_str
[VRF_NAMSIZ
] = {0};
6674 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
6675 bool nexthop_othervrf
= false;
6676 vrf_id_t nexthop_vrfid
= VRF_DEFAULT
;
6677 const char *nexthop_vrfname
= VRF_DEFAULT_NAME
;
6680 json_path
= json_object_new_object();
6682 /* short status lead text */
6683 route_vty_short_status_out(vty
, path
, json_path
);
6686 /* print prefix and mask */
6688 route_vty_out_route(p
, vty
, json_path
);
6690 vty_out(vty
, "%*s", 17, " ");
6692 route_vty_out_route(p
, vty
, json_path
);
6695 /* Print attribute */
6699 json_object_array_add(json_paths
, json_path
);
6707 * If vrf id of nexthop is different from that of prefix,
6708 * set up printable string to append
6710 if (path
->extra
&& path
->extra
->bgp_orig
) {
6711 const char *self
= "";
6716 nexthop_othervrf
= true;
6717 nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
6719 if (path
->extra
->bgp_orig
->vrf_id
== VRF_UNKNOWN
)
6720 snprintf(vrf_id_str
, sizeof(vrf_id_str
),
6721 "@%s%s", VRFID_NONE_STR
, self
);
6723 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "@%u%s",
6724 path
->extra
->bgp_orig
->vrf_id
, self
);
6726 if (path
->extra
->bgp_orig
->inst_type
6727 != BGP_INSTANCE_TYPE_DEFAULT
)
6729 nexthop_vrfname
= path
->extra
->bgp_orig
->name
;
6731 const char *self
= "";
6736 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "%s", self
);
6740 * For ENCAP and EVPN routes, nexthop address family is not
6741 * neccessarily the same as the prefix address family.
6742 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
6743 * EVPN routes are also exchanged with a MP nexthop. Currently,
6745 * is only IPv4, the value will be present in either
6747 * attr->mp_nexthop_global_in
6749 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
6752 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
6756 sprintf(nexthop
, "%s",
6757 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
6761 sprintf(nexthop
, "%s",
6762 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
6766 sprintf(nexthop
, "?");
6771 json_nexthop_global
= json_object_new_object();
6773 json_object_string_add(json_nexthop_global
, "afi",
6774 (af
== AF_INET
) ? "ip" : "ipv6");
6775 json_object_string_add(json_nexthop_global
,
6776 (af
== AF_INET
) ? "ip" : "ipv6",
6778 json_object_boolean_true_add(json_nexthop_global
,
6781 vty_out(vty
, "%s%s", nexthop
, vrf_id_str
);
6782 } else if (safi
== SAFI_EVPN
) {
6784 json_nexthop_global
= json_object_new_object();
6786 json_object_string_add(json_nexthop_global
, "ip",
6787 inet_ntoa(attr
->nexthop
));
6788 json_object_string_add(json_nexthop_global
, "afi",
6790 json_object_boolean_true_add(json_nexthop_global
,
6793 vty_out(vty
, "%-16s%s", inet_ntoa(attr
->nexthop
),
6795 } else if (safi
== SAFI_FLOWSPEC
) {
6796 if (attr
->nexthop
.s_addr
!= 0) {
6798 json_nexthop_global
= json_object_new_object();
6799 json_object_string_add(
6800 json_nexthop_global
, "ip",
6801 inet_ntoa(attr
->nexthop
));
6802 json_object_string_add(json_nexthop_global
,
6804 json_object_boolean_true_add(
6805 json_nexthop_global
,
6808 vty_out(vty
, "%-16s", inet_ntoa(attr
->nexthop
));
6811 } else if (p
->family
== AF_INET
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6813 json_nexthop_global
= json_object_new_object();
6815 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_EVPN
))
6816 json_object_string_add(
6817 json_nexthop_global
, "ip",
6818 inet_ntoa(attr
->mp_nexthop_global_in
));
6820 json_object_string_add(
6821 json_nexthop_global
, "ip",
6822 inet_ntoa(attr
->nexthop
));
6824 json_object_string_add(json_nexthop_global
, "afi",
6826 json_object_boolean_true_add(json_nexthop_global
,
6831 snprintf(buf
, sizeof(buf
), "%s%s",
6832 inet_ntoa(attr
->nexthop
), vrf_id_str
);
6833 vty_out(vty
, "%-16s", buf
);
6838 else if (p
->family
== AF_INET6
|| BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6843 json_nexthop_global
= json_object_new_object();
6844 json_object_string_add(
6845 json_nexthop_global
, "ip",
6846 inet_ntop(AF_INET6
, &attr
->mp_nexthop_global
,
6848 json_object_string_add(json_nexthop_global
, "afi",
6850 json_object_string_add(json_nexthop_global
, "scope",
6853 /* We display both LL & GL if both have been
6855 if ((attr
->mp_nexthop_len
== 32)
6856 || (path
->peer
->conf_if
)) {
6857 json_nexthop_ll
= json_object_new_object();
6858 json_object_string_add(
6859 json_nexthop_ll
, "ip",
6861 &attr
->mp_nexthop_local
, buf
,
6863 json_object_string_add(json_nexthop_ll
, "afi",
6865 json_object_string_add(json_nexthop_ll
, "scope",
6868 if ((IPV6_ADDR_CMP(&attr
->mp_nexthop_global
,
6869 &attr
->mp_nexthop_local
)
6871 && !attr
->mp_nexthop_prefer_global
)
6872 json_object_boolean_true_add(
6873 json_nexthop_ll
, "used");
6875 json_object_boolean_true_add(
6876 json_nexthop_global
, "used");
6878 json_object_boolean_true_add(
6879 json_nexthop_global
, "used");
6881 /* Display LL if LL/Global both in table unless
6882 * prefer-global is set */
6883 if (((attr
->mp_nexthop_len
== 32)
6884 && !attr
->mp_nexthop_prefer_global
)
6885 || (path
->peer
->conf_if
)) {
6886 if (path
->peer
->conf_if
) {
6887 len
= vty_out(vty
, "%s",
6888 path
->peer
->conf_if
);
6889 len
= 16 - len
; /* len of IPv6
6895 vty_out(vty
, "\n%*s", 36, " ");
6897 vty_out(vty
, "%*s", len
, " ");
6903 &attr
->mp_nexthop_local
,
6909 vty_out(vty
, "\n%*s", 36, " ");
6911 vty_out(vty
, "%*s", len
, " ");
6917 &attr
->mp_nexthop_global
, buf
,
6923 vty_out(vty
, "\n%*s", 36, " ");
6925 vty_out(vty
, "%*s", len
, " ");
6931 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
6935 * Adding "metric" field to match with corresponding
6936 * CLI. "med" will be deprecated in future.
6938 json_object_int_add(json_path
, "med", attr
->med
);
6939 json_object_int_add(json_path
, "metric", attr
->med
);
6941 vty_out(vty
, "%10u", attr
->med
);
6942 else if (!json_paths
)
6946 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
6950 * Adding "locPrf" field to match with corresponding
6951 * CLI. "localPref" will be deprecated in future.
6953 json_object_int_add(json_path
, "localpref",
6955 json_object_int_add(json_path
, "locPrf",
6958 vty_out(vty
, "%7u", attr
->local_pref
);
6959 else if (!json_paths
)
6963 json_object_int_add(json_path
, "weight", attr
->weight
);
6965 vty_out(vty
, "%7u ", attr
->weight
);
6969 json_object_string_add(
6970 json_path
, "peerId",
6971 sockunion2str(&path
->peer
->su
, buf
, SU_ADDRSTRLEN
));
6979 * Adding "path" field to match with corresponding
6980 * CLI. "aspath" will be deprecated in future.
6982 json_object_string_add(json_path
, "aspath",
6984 json_object_string_add(json_path
, "path",
6987 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
6992 json_object_string_add(json_path
, "origin",
6993 bgp_origin_long_str
[attr
->origin
]);
6995 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
6999 json_object_boolean_true_add(json_path
,
7000 "announceNexthopSelf");
7001 if (nexthop_othervrf
) {
7002 json_object_string_add(json_path
, "nhVrfName",
7005 json_object_int_add(json_path
, "nhVrfId",
7006 ((nexthop_vrfid
== VRF_UNKNOWN
)
7008 : (int)nexthop_vrfid
));
7013 if (json_nexthop_global
|| json_nexthop_ll
) {
7014 json_nexthops
= json_object_new_array();
7016 if (json_nexthop_global
)
7017 json_object_array_add(json_nexthops
,
7018 json_nexthop_global
);
7020 if (json_nexthop_ll
)
7021 json_object_array_add(json_nexthops
,
7024 json_object_object_add(json_path
, "nexthops",
7028 json_object_array_add(json_paths
, json_path
);
7032 /* prints an additional line, indented, with VNC info, if
7034 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
7035 rfapi_vty_out_vncinfo(vty
, p
, path
, safi
);
7040 /* called from terminal list command */
7041 void route_vty_out_tmp(struct vty
*vty
, struct prefix
*p
, struct attr
*attr
,
7042 safi_t safi
, bool use_json
, json_object
*json_ar
)
7044 json_object
*json_status
= NULL
;
7045 json_object
*json_net
= NULL
;
7048 /* Route status display. */
7050 json_status
= json_object_new_object();
7051 json_net
= json_object_new_object();
7058 /* print prefix and mask */
7060 json_object_string_add(
7061 json_net
, "addrPrefix",
7062 inet_ntop(p
->family
, &p
->u
.prefix
, buff
, BUFSIZ
));
7063 json_object_int_add(json_net
, "prefixLen", p
->prefixlen
);
7064 prefix2str(p
, buf2
, PREFIX_STRLEN
);
7065 json_object_string_add(json_net
, "network", buf2
);
7067 route_vty_out_route(p
, vty
, NULL
);
7069 /* Print attribute */
7072 if (p
->family
== AF_INET
7073 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7074 || safi
== SAFI_EVPN
7075 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7076 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7077 || safi
== SAFI_EVPN
)
7078 json_object_string_add(
7079 json_net
, "nextHop",
7081 attr
->mp_nexthop_global_in
));
7083 json_object_string_add(
7084 json_net
, "nextHop",
7085 inet_ntoa(attr
->nexthop
));
7086 } else if (p
->family
== AF_INET6
7087 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7090 json_object_string_add(
7091 json_net
, "nextHopGlobal",
7093 &attr
->mp_nexthop_global
, buf
,
7098 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
7099 json_object_int_add(json_net
, "metric",
7102 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
7105 * Adding "locPrf" field to match with
7106 * corresponding CLI. "localPref" will be
7107 * deprecated in future.
7109 json_object_int_add(json_net
, "localPref",
7111 json_object_int_add(json_net
, "locPrf",
7115 json_object_int_add(json_net
, "weight", attr
->weight
);
7121 * Adding "path" field to match with
7122 * corresponding CLI. "localPref" will be
7123 * deprecated in future.
7125 json_object_string_add(json_net
, "asPath",
7127 json_object_string_add(json_net
, "path",
7132 json_object_string_add(json_net
, "bgpOriginCode",
7133 bgp_origin_str
[attr
->origin
]);
7135 if (p
->family
== AF_INET
7136 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7137 || safi
== SAFI_EVPN
7138 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7139 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7140 || safi
== SAFI_EVPN
)
7141 vty_out(vty
, "%-16s",
7143 attr
->mp_nexthop_global_in
));
7145 vty_out(vty
, "%-16s",
7146 inet_ntoa(attr
->nexthop
));
7147 } else if (p
->family
== AF_INET6
7148 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7155 &attr
->mp_nexthop_global
, buf
,
7159 vty_out(vty
, "\n%*s", 36, " ");
7161 vty_out(vty
, "%*s", len
, " ");
7164 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
7165 vty_out(vty
, "%10u", attr
->med
);
7169 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
7170 vty_out(vty
, "%7u", attr
->local_pref
);
7174 vty_out(vty
, "%7u ", attr
->weight
);
7178 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7181 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7185 json_object_boolean_true_add(json_status
, "*");
7186 json_object_boolean_true_add(json_status
, ">");
7187 json_object_object_add(json_net
, "appliedStatusSymbols",
7189 char buf_cut
[BUFSIZ
];
7190 json_object_object_add(
7192 inet_ntop(p
->family
, &p
->u
.prefix
, buf_cut
, BUFSIZ
),
7198 void route_vty_out_tag(struct vty
*vty
, struct prefix
*p
,
7199 struct bgp_path_info
*path
, int display
, safi_t safi
,
7202 json_object
*json_out
= NULL
;
7204 mpls_label_t label
= MPLS_INVALID_LABEL
;
7210 json_out
= json_object_new_object();
7212 /* short status lead text */
7213 route_vty_short_status_out(vty
, path
, json_out
);
7215 /* print prefix and mask */
7218 route_vty_out_route(p
, vty
, NULL
);
7220 vty_out(vty
, "%*s", 17, " ");
7223 /* Print attribute */
7226 if (((p
->family
== AF_INET
)
7227 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
7228 || (safi
== SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
7229 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7230 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7231 || safi
== SAFI_EVPN
) {
7233 json_object_string_add(
7234 json_out
, "mpNexthopGlobalIn",
7236 attr
->mp_nexthop_global_in
));
7238 vty_out(vty
, "%-16s",
7240 attr
->mp_nexthop_global_in
));
7243 json_object_string_add(
7244 json_out
, "nexthop",
7245 inet_ntoa(attr
->nexthop
));
7247 vty_out(vty
, "%-16s",
7248 inet_ntoa(attr
->nexthop
));
7250 } else if (((p
->family
== AF_INET6
)
7251 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
7252 || (safi
== SAFI_EVPN
7253 && BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
7254 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7258 if (attr
->mp_nexthop_len
7259 == BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
7261 json_object_string_add(
7262 json_out
, "mpNexthopGlobalIn",
7265 &attr
->mp_nexthop_global
,
7266 buf_a
, sizeof(buf_a
)));
7271 &attr
->mp_nexthop_global
,
7272 buf_a
, sizeof(buf_a
)));
7273 } else if (attr
->mp_nexthop_len
7274 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
7277 &attr
->mp_nexthop_global
,
7278 buf_a
, sizeof(buf_a
));
7280 &attr
->mp_nexthop_local
,
7281 buf_b
, sizeof(buf_b
));
7282 sprintf(buf_c
, "%s(%s)", buf_a
, buf_b
);
7283 json_object_string_add(
7285 "mpNexthopGlobalLocal", buf_c
);
7287 vty_out(vty
, "%s(%s)",
7290 &attr
->mp_nexthop_global
,
7291 buf_a
, sizeof(buf_a
)),
7294 &attr
->mp_nexthop_local
,
7295 buf_b
, sizeof(buf_b
)));
7300 label
= decode_label(&path
->extra
->label
[0]);
7302 if (bgp_is_valid_label(&label
)) {
7304 json_object_int_add(json_out
, "notag", label
);
7305 json_object_array_add(json
, json_out
);
7307 vty_out(vty
, "notag/%d", label
);
7313 void route_vty_out_overlay(struct vty
*vty
, struct prefix
*p
,
7314 struct bgp_path_info
*path
, int display
,
7315 json_object
*json_paths
)
7319 json_object
*json_path
= NULL
;
7322 json_path
= json_object_new_object();
7327 /* short status lead text */
7328 route_vty_short_status_out(vty
, path
, json_path
);
7330 /* print prefix and mask */
7332 route_vty_out_route(p
, vty
, NULL
);
7334 vty_out(vty
, "%*s", 17, " ");
7336 /* Print attribute */
7340 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
7344 vty_out(vty
, "%-16s",
7345 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
7349 vty_out(vty
, "%s(%s)",
7350 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
7352 inet_ntop(af
, &attr
->mp_nexthop_local
, buf1
,
7359 char *str
= esi2str(&(attr
->evpn_overlay
.eth_s_id
));
7361 vty_out(vty
, "%s", str
);
7362 XFREE(MTYPE_TMP
, str
);
7364 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn
*)p
)) {
7366 inet_ntoa(attr
->evpn_overlay
.gw_ip
.ipv4
));
7367 } else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn
*)p
)) {
7370 &(attr
->evpn_overlay
.gw_ip
.ipv6
), buf
,
7373 if (attr
->ecommunity
) {
7375 struct ecommunity_val
*routermac
= ecommunity_lookup(
7376 attr
->ecommunity
, ECOMMUNITY_ENCODE_EVPN
,
7377 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
7379 mac
= ecom_mac2str((char *)routermac
->val
);
7381 vty_out(vty
, "/%s", (char *)mac
);
7382 XFREE(MTYPE_TMP
, mac
);
7390 /* dampening route */
7391 static void damp_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7392 struct bgp_path_info
*path
, int display
,
7393 safi_t safi
, bool use_json
, json_object
*json
)
7397 char timebuf
[BGP_UPTIME_LEN
];
7399 /* short status lead text */
7400 route_vty_short_status_out(vty
, path
, json
);
7402 /* print prefix and mask */
7405 route_vty_out_route(p
, vty
, NULL
);
7407 vty_out(vty
, "%*s", 17, " ");
7410 len
= vty_out(vty
, "%s", path
->peer
->host
);
7414 vty_out(vty
, "\n%*s", 34, " ");
7417 json_object_int_add(json
, "peerHost", len
);
7419 vty_out(vty
, "%*s", len
, " ");
7423 bgp_damp_reuse_time_vty(vty
, path
, timebuf
, BGP_UPTIME_LEN
,
7427 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
7428 BGP_UPTIME_LEN
, use_json
,
7431 /* Print attribute */
7437 json_object_string_add(json
, "asPath",
7440 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7445 json_object_string_add(json
, "origin",
7446 bgp_origin_str
[attr
->origin
]);
7448 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7455 static void flap_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7456 struct bgp_path_info
*path
, int display
,
7457 safi_t safi
, bool use_json
, json_object
*json
)
7460 struct bgp_damp_info
*bdi
;
7461 char timebuf
[BGP_UPTIME_LEN
];
7467 bdi
= path
->extra
->damp_info
;
7469 /* short status lead text */
7470 route_vty_short_status_out(vty
, path
, json
);
7472 /* print prefix and mask */
7475 route_vty_out_route(p
, vty
, NULL
);
7477 vty_out(vty
, "%*s", 17, " ");
7480 len
= vty_out(vty
, "%s", path
->peer
->host
);
7484 vty_out(vty
, "\n%*s", 33, " ");
7487 json_object_int_add(json
, "peerHost", len
);
7489 vty_out(vty
, "%*s", len
, " ");
7492 len
= vty_out(vty
, "%d", bdi
->flap
);
7499 json_object_int_add(json
, "bdiFlap", len
);
7501 vty_out(vty
, "%*s", len
, " ");
7505 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
7508 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
7509 BGP_UPTIME_LEN
, 0, NULL
));
7511 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
7512 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
7514 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
7515 BGP_UPTIME_LEN
, use_json
, json
);
7518 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
7523 vty_out(vty
, "%*s ", 8, " ");
7526 /* Print attribute */
7532 json_object_string_add(json
, "asPath",
7535 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7540 json_object_string_add(json
, "origin",
7541 bgp_origin_str
[attr
->origin
]);
7543 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7549 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
7550 int *first
, const char *header
,
7551 json_object
*json_adv_to
)
7553 char buf1
[INET6_ADDRSTRLEN
];
7554 json_object
*json_peer
= NULL
;
7557 /* 'advertised-to' is a dictionary of peers we have advertised
7559 * prefix too. The key is the peer's IP or swpX, the value is
7561 * hostname if we know it and "" if not.
7563 json_peer
= json_object_new_object();
7566 json_object_string_add(json_peer
, "hostname",
7570 json_object_object_add(json_adv_to
, peer
->conf_if
,
7573 json_object_object_add(
7575 sockunion2str(&peer
->su
, buf1
, SU_ADDRSTRLEN
),
7579 vty_out(vty
, "%s", header
);
7584 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
7586 vty_out(vty
, " %s(%s)", peer
->hostname
,
7589 vty_out(vty
, " %s(%s)", peer
->hostname
,
7590 sockunion2str(&peer
->su
, buf1
,
7594 vty_out(vty
, " %s", peer
->conf_if
);
7597 sockunion2str(&peer
->su
, buf1
,
7603 static void route_vty_out_tx_ids(struct vty
*vty
,
7604 struct bgp_addpath_info_data
*d
)
7608 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
7609 vty_out(vty
, "TX-%s %u%s", bgp_addpath_names(i
)->human_name
,
7610 d
->addpath_tx_id
[i
],
7611 i
< BGP_ADDPATH_MAX
- 1 ? " " : "\n");
7615 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
, struct prefix
*p
,
7616 struct bgp_path_info
*path
, afi_t afi
, safi_t safi
,
7617 json_object
*json_paths
)
7619 char buf
[INET6_ADDRSTRLEN
];
7621 char buf2
[EVPN_ROUTE_STRLEN
];
7623 int sockunion_vty_out(struct vty
*, union sockunion
*);
7625 json_object
*json_bestpath
= NULL
;
7626 json_object
*json_cluster_list
= NULL
;
7627 json_object
*json_cluster_list_list
= NULL
;
7628 json_object
*json_ext_community
= NULL
;
7629 json_object
*json_last_update
= NULL
;
7630 json_object
*json_pmsi
= NULL
;
7631 json_object
*json_nexthop_global
= NULL
;
7632 json_object
*json_nexthop_ll
= NULL
;
7633 json_object
*json_nexthops
= NULL
;
7634 json_object
*json_path
= NULL
;
7635 json_object
*json_peer
= NULL
;
7636 json_object
*json_string
= NULL
;
7637 json_object
*json_adv_to
= NULL
;
7639 struct listnode
*node
, *nnode
;
7641 int addpath_capable
;
7643 unsigned int first_as
;
7645 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
7649 json_path
= json_object_new_object();
7650 json_peer
= json_object_new_object();
7651 json_nexthop_global
= json_object_new_object();
7654 if (!json_paths
&& safi
== SAFI_EVPN
) {
7657 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf2
, sizeof(buf2
));
7658 vty_out(vty
, " Route %s", buf2
);
7660 if (path
->extra
&& path
->extra
->num_labels
) {
7661 bgp_evpn_label2str(path
->extra
->label
,
7662 path
->extra
->num_labels
, tag_buf
,
7664 vty_out(vty
, " VNI %s", tag_buf
);
7667 if (path
->extra
&& path
->extra
->parent
) {
7668 struct bgp_path_info
*parent_ri
;
7669 struct bgp_node
*rn
, *prn
;
7671 parent_ri
= (struct bgp_path_info
*)path
->extra
->parent
;
7672 rn
= parent_ri
->net
;
7673 if (rn
&& rn
->prn
) {
7675 vty_out(vty
, " Imported from %s:%s\n",
7677 (struct prefix_rd
*)&prn
->p
,
7678 buf1
, sizeof(buf1
)),
7687 /* Line1 display AS-path, Aggregator */
7690 if (!attr
->aspath
->json
)
7691 aspath_str_update(attr
->aspath
, true);
7692 json_object_lock(attr
->aspath
->json
);
7693 json_object_object_add(json_path
, "aspath",
7694 attr
->aspath
->json
);
7696 if (attr
->aspath
->segments
)
7697 aspath_print_vty(vty
, " %s",
7700 vty_out(vty
, " Local");
7704 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
)) {
7706 json_object_boolean_true_add(json_path
,
7709 vty_out(vty
, ", (removed)");
7712 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
7714 json_object_boolean_true_add(json_path
,
7717 vty_out(vty
, ", (stale)");
7720 if (CHECK_FLAG(attr
->flag
,
7721 ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
7723 json_object_int_add(json_path
, "aggregatorAs",
7724 attr
->aggregator_as
);
7725 json_object_string_add(
7726 json_path
, "aggregatorId",
7727 inet_ntoa(attr
->aggregator_addr
));
7729 vty_out(vty
, ", (aggregated by %u %s)",
7730 attr
->aggregator_as
,
7731 inet_ntoa(attr
->aggregator_addr
));
7735 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
7736 PEER_FLAG_REFLECTOR_CLIENT
)) {
7738 json_object_boolean_true_add(
7739 json_path
, "rxedFromRrClient");
7741 vty_out(vty
, ", (Received from a RR-client)");
7744 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
7745 PEER_FLAG_RSERVER_CLIENT
)) {
7747 json_object_boolean_true_add(
7748 json_path
, "rxedFromRsClient");
7750 vty_out(vty
, ", (Received from a RS-client)");
7753 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
7755 json_object_boolean_true_add(
7756 json_path
, "dampeningHistoryEntry");
7758 vty_out(vty
, ", (history entry)");
7759 } else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)) {
7761 json_object_boolean_true_add(
7762 json_path
, "dampeningSuppressed");
7764 vty_out(vty
, ", (suppressed due to dampening)");
7770 /* Line2 display Next-hop, Neighbor, Router-id */
7771 /* Display the nexthop */
7772 if ((p
->family
== AF_INET
|| p
->family
== AF_ETHERNET
7773 || p
->family
== AF_EVPN
)
7774 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7775 || safi
== SAFI_EVPN
7776 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7777 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7778 || safi
== SAFI_EVPN
) {
7780 json_object_string_add(
7781 json_nexthop_global
, "ip",
7783 attr
->mp_nexthop_global_in
));
7787 attr
->mp_nexthop_global_in
));
7790 json_object_string_add(
7791 json_nexthop_global
, "ip",
7792 inet_ntoa(attr
->nexthop
));
7795 inet_ntoa(attr
->nexthop
));
7799 json_object_string_add(json_nexthop_global
,
7803 json_object_string_add(
7804 json_nexthop_global
, "ip",
7806 &attr
->mp_nexthop_global
, buf
,
7808 json_object_string_add(json_nexthop_global
,
7810 json_object_string_add(json_nexthop_global
,
7815 &attr
->mp_nexthop_global
, buf
,
7820 /* Display the IGP cost or 'inaccessible' */
7821 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
7823 json_object_boolean_false_add(
7824 json_nexthop_global
, "accessible");
7826 vty_out(vty
, " (inaccessible)");
7828 if (path
->extra
&& path
->extra
->igpmetric
) {
7830 json_object_int_add(
7831 json_nexthop_global
, "metric",
7832 path
->extra
->igpmetric
);
7834 vty_out(vty
, " (metric %u)",
7835 path
->extra
->igpmetric
);
7838 /* IGP cost is 0, display this only for json */
7841 json_object_int_add(json_nexthop_global
,
7846 json_object_boolean_true_add(
7847 json_nexthop_global
, "accessible");
7850 /* Display peer "from" output */
7851 /* This path was originated locally */
7852 if (path
->peer
== bgp
->peer_self
) {
7854 if (safi
== SAFI_EVPN
7855 || (p
->family
== AF_INET
7856 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7858 json_object_string_add(
7859 json_peer
, "peerId", "0.0.0.0");
7861 vty_out(vty
, " from 0.0.0.0 ");
7864 json_object_string_add(json_peer
,
7867 vty_out(vty
, " from :: ");
7871 json_object_string_add(
7872 json_peer
, "routerId",
7873 inet_ntoa(bgp
->router_id
));
7875 vty_out(vty
, "(%s)", inet_ntoa(bgp
->router_id
));
7878 /* We RXed this path from one of our peers */
7882 json_object_string_add(
7883 json_peer
, "peerId",
7884 sockunion2str(&path
->peer
->su
, buf
,
7886 json_object_string_add(
7887 json_peer
, "routerId",
7889 &path
->peer
->remote_id
, buf1
,
7892 if (path
->peer
->hostname
)
7893 json_object_string_add(
7894 json_peer
, "hostname",
7895 path
->peer
->hostname
);
7897 if (path
->peer
->domainname
)
7898 json_object_string_add(
7899 json_peer
, "domainname",
7900 path
->peer
->domainname
);
7902 if (path
->peer
->conf_if
)
7903 json_object_string_add(
7904 json_peer
, "interface",
7905 path
->peer
->conf_if
);
7907 if (path
->peer
->conf_if
) {
7908 if (path
->peer
->hostname
7911 BGP_FLAG_SHOW_HOSTNAME
))
7912 vty_out(vty
, " from %s(%s)",
7913 path
->peer
->hostname
,
7914 path
->peer
->conf_if
);
7916 vty_out(vty
, " from %s",
7917 path
->peer
->conf_if
);
7919 if (path
->peer
->hostname
7922 BGP_FLAG_SHOW_HOSTNAME
))
7923 vty_out(vty
, " from %s(%s)",
7924 path
->peer
->hostname
,
7927 vty_out(vty
, " from %s",
7935 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
7936 vty_out(vty
, " (%s)",
7937 inet_ntoa(attr
->originator_id
));
7939 vty_out(vty
, " (%s)",
7942 &path
->peer
->remote_id
,
7943 buf1
, sizeof(buf1
)));
7948 * Note when vrfid of nexthop is different from that of prefix
7950 if (path
->extra
&& path
->extra
->bgp_orig
) {
7951 vrf_id_t nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
7956 if (path
->extra
->bgp_orig
->inst_type
7957 == BGP_INSTANCE_TYPE_DEFAULT
)
7959 vn
= VRF_DEFAULT_NAME
;
7961 vn
= path
->extra
->bgp_orig
->name
;
7963 json_object_string_add(json_path
, "nhVrfName",
7966 if (nexthop_vrfid
== VRF_UNKNOWN
) {
7967 json_object_int_add(json_path
,
7970 json_object_int_add(json_path
,
7971 "nhVrfId", (int)nexthop_vrfid
);
7974 if (nexthop_vrfid
== VRF_UNKNOWN
)
7975 vty_out(vty
, " vrf ?");
7977 vty_out(vty
, " vrf %u", nexthop_vrfid
);
7983 json_object_boolean_true_add(json_path
,
7984 "announceNexthopSelf");
7986 vty_out(vty
, " announce-nh-self");
7993 /* display the link-local nexthop */
7994 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
7996 json_nexthop_ll
= json_object_new_object();
7997 json_object_string_add(
7998 json_nexthop_ll
, "ip",
8000 &attr
->mp_nexthop_local
, buf
,
8002 json_object_string_add(json_nexthop_ll
, "afi",
8004 json_object_string_add(json_nexthop_ll
, "scope",
8007 json_object_boolean_true_add(json_nexthop_ll
,
8010 if (!attr
->mp_nexthop_prefer_global
)
8011 json_object_boolean_true_add(
8012 json_nexthop_ll
, "used");
8014 json_object_boolean_true_add(
8015 json_nexthop_global
, "used");
8017 vty_out(vty
, " (%s) %s\n",
8019 &attr
->mp_nexthop_local
, buf
,
8021 attr
->mp_nexthop_prefer_global
8026 /* If we do not have a link-local nexthop then we must flag the
8030 json_object_boolean_true_add(
8031 json_nexthop_global
, "used");
8034 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
8035 * Int/Ext/Local, Atomic, best */
8037 json_object_string_add(
8038 json_path
, "origin",
8039 bgp_origin_long_str
[attr
->origin
]);
8041 vty_out(vty
, " Origin %s",
8042 bgp_origin_long_str
[attr
->origin
]);
8044 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
8048 * Adding "metric" field to match with
8049 * corresponding CLI. "med" will be
8050 * deprecated in future.
8052 json_object_int_add(json_path
, "med",
8054 json_object_int_add(json_path
, "metric",
8057 vty_out(vty
, ", metric %u", attr
->med
);
8060 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
8062 json_object_int_add(json_path
, "localpref",
8065 vty_out(vty
, ", localpref %u",
8069 if (attr
->weight
!= 0) {
8071 json_object_int_add(json_path
, "weight",
8074 vty_out(vty
, ", weight %u", attr
->weight
);
8077 if (attr
->tag
!= 0) {
8079 json_object_int_add(json_path
, "tag",
8082 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
,
8086 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
8088 json_object_boolean_false_add(json_path
,
8091 vty_out(vty
, ", invalid");
8092 } else if (!CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
8094 json_object_boolean_true_add(json_path
,
8097 vty_out(vty
, ", valid");
8100 if (path
->peer
!= bgp
->peer_self
) {
8101 if (path
->peer
->as
== path
->peer
->local_as
) {
8102 if (CHECK_FLAG(bgp
->config
,
8103 BGP_CONFIG_CONFEDERATION
)) {
8105 json_object_string_add(
8110 ", confed-internal");
8113 json_object_string_add(
8117 vty_out(vty
, ", internal");
8120 if (bgp_confederation_peers_check(
8121 bgp
, path
->peer
->as
)) {
8123 json_object_string_add(
8128 ", confed-external");
8131 json_object_string_add(
8135 vty_out(vty
, ", external");
8138 } else if (path
->sub_type
== BGP_ROUTE_AGGREGATE
) {
8140 json_object_boolean_true_add(json_path
,
8142 json_object_boolean_true_add(json_path
,
8145 vty_out(vty
, ", aggregated, local");
8147 } else if (path
->type
!= ZEBRA_ROUTE_BGP
) {
8149 json_object_boolean_true_add(json_path
,
8152 vty_out(vty
, ", sourced");
8155 json_object_boolean_true_add(json_path
,
8157 json_object_boolean_true_add(json_path
,
8160 vty_out(vty
, ", sourced, local");
8164 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
8166 json_object_boolean_true_add(json_path
,
8169 vty_out(vty
, ", atomic-aggregate");
8172 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
)
8173 || (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)
8174 && bgp_path_info_mpath_count(path
))) {
8176 json_object_boolean_true_add(json_path
,
8179 vty_out(vty
, ", multipath");
8182 // Mark the bestpath(s)
8183 if (CHECK_FLAG(path
->flags
, BGP_PATH_DMED_SELECTED
)) {
8184 first_as
= aspath_get_first_as(attr
->aspath
);
8189 json_object_new_object();
8190 json_object_int_add(json_bestpath
,
8191 "bestpathFromAs", first_as
);
8194 vty_out(vty
, ", bestpath-from-AS %u",
8198 ", bestpath-from-AS Local");
8202 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
8206 json_object_new_object();
8207 json_object_boolean_true_add(json_bestpath
,
8210 vty_out(vty
, ", best");
8214 json_object_object_add(json_path
, "bestpath",
8220 /* Line 4 display Community */
8221 if (attr
->community
) {
8223 if (!attr
->community
->json
)
8224 community_str(attr
->community
, true);
8225 json_object_lock(attr
->community
->json
);
8226 json_object_object_add(json_path
, "community",
8227 attr
->community
->json
);
8229 vty_out(vty
, " Community: %s\n",
8230 attr
->community
->str
);
8234 /* Line 5 display Extended-community */
8235 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
8237 json_ext_community
= json_object_new_object();
8238 json_object_string_add(json_ext_community
,
8240 attr
->ecommunity
->str
);
8241 json_object_object_add(json_path
,
8242 "extendedCommunity",
8243 json_ext_community
);
8245 vty_out(vty
, " Extended Community: %s\n",
8246 attr
->ecommunity
->str
);
8250 /* Line 6 display Large community */
8251 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
8253 if (!attr
->lcommunity
->json
)
8254 lcommunity_str(attr
->lcommunity
, true);
8255 json_object_lock(attr
->lcommunity
->json
);
8256 json_object_object_add(json_path
,
8258 attr
->lcommunity
->json
);
8260 vty_out(vty
, " Large Community: %s\n",
8261 attr
->lcommunity
->str
);
8265 /* Line 7 display Originator, Cluster-id */
8266 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
8267 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
8269 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
8271 json_object_string_add(
8272 json_path
, "originatorId",
8273 inet_ntoa(attr
->originator_id
));
8275 vty_out(vty
, " Originator: %s",
8276 inet_ntoa(attr
->originator_id
));
8279 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
8284 json_object_new_object();
8285 json_cluster_list_list
=
8286 json_object_new_array();
8289 i
< attr
->cluster
->length
/ 4;
8291 json_string
= json_object_new_string(
8295 json_object_array_add(
8296 json_cluster_list_list
,
8300 /* struct cluster_list does not have
8302 * aspath and community do. Add this
8305 json_object_string_add(json_cluster_list,
8306 "string", attr->cluster->str);
8308 json_object_object_add(
8309 json_cluster_list
, "list",
8310 json_cluster_list_list
);
8311 json_object_object_add(
8312 json_path
, "clusterList",
8315 vty_out(vty
, ", Cluster list: ");
8318 i
< attr
->cluster
->length
/ 4;
8332 if (path
->extra
&& path
->extra
->damp_info
)
8333 bgp_damp_info_vty(vty
, path
, json_path
);
8336 if (path
->extra
&& bgp_is_valid_label(&path
->extra
->label
[0])
8337 && safi
!= SAFI_EVPN
) {
8338 mpls_label_t label
= label_pton(&path
->extra
->label
[0]);
8341 json_object_int_add(json_path
, "remoteLabel",
8344 vty_out(vty
, " Remote label: %d\n", label
);
8348 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
8350 json_object_int_add(json_path
, "labelIndex",
8353 vty_out(vty
, " Label Index: %d\n",
8357 /* Line 8 display Addpath IDs */
8358 if (path
->addpath_rx_id
8359 || bgp_addpath_info_has_ids(&path
->tx_addpath
)) {
8361 json_object_int_add(json_path
, "addpathRxId",
8362 path
->addpath_rx_id
);
8364 /* Keep backwards compatibility with the old API
8365 * by putting TX All's ID in the old field
8367 json_object_int_add(
8368 json_path
, "addpathTxId",
8369 path
->tx_addpath
.addpath_tx_id
8372 /* ... but create a specific field for each
8375 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
8376 json_object_int_add(
8378 bgp_addpath_names(i
)
8384 vty_out(vty
, " AddPath ID: RX %u, ",
8385 path
->addpath_rx_id
);
8387 route_vty_out_tx_ids(vty
, &path
->tx_addpath
);
8391 /* If we used addpath to TX a non-bestpath we need to display
8392 * "Advertised to" on a path-by-path basis
8394 if (bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
8397 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
8399 bgp_addpath_encode_tx(peer
, afi
, safi
);
8400 has_adj
= bgp_adj_out_lookup(
8402 bgp_addpath_id_for_peer(
8404 &path
->tx_addpath
));
8406 if ((addpath_capable
&& has_adj
)
8407 || (!addpath_capable
&& has_adj
8408 && CHECK_FLAG(path
->flags
,
8409 BGP_PATH_SELECTED
))) {
8410 if (json_path
&& !json_adv_to
)
8412 json_object_new_object();
8414 route_vty_out_advertised_to(
8423 json_object_object_add(json_path
,
8434 /* Line 9 display Uptime */
8435 tbuf
= time(NULL
) - (bgp_clock() - path
->uptime
);
8437 json_last_update
= json_object_new_object();
8438 json_object_int_add(json_last_update
, "epoch", tbuf
);
8439 json_object_string_add(json_last_update
, "string",
8441 json_object_object_add(json_path
, "lastUpdate",
8444 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
8446 /* Line 10 display PMSI tunnel attribute, if present */
8447 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
8448 const char *str
= lookup_msg(bgp_pmsi_tnltype_str
,
8449 attr
->pmsi_tnl_type
,
8450 PMSI_TNLTYPE_STR_DEFAULT
);
8453 json_pmsi
= json_object_new_object();
8454 json_object_string_add(json_pmsi
,
8456 json_object_int_add(json_pmsi
,
8458 label2vni(&attr
->label
));
8459 json_object_object_add(json_path
, "pmsi",
8463 " PMSI Tunnel Type: %s, label: %d\n",
8464 str
, label2vni(&attr
->label
));
8469 /* We've constructed the json object for this path, add it to the json
8473 if (json_nexthop_global
|| json_nexthop_ll
) {
8474 json_nexthops
= json_object_new_array();
8476 if (json_nexthop_global
)
8477 json_object_array_add(json_nexthops
,
8478 json_nexthop_global
);
8480 if (json_nexthop_ll
)
8481 json_object_array_add(json_nexthops
,
8484 json_object_object_add(json_path
, "nexthops",
8488 json_object_object_add(json_path
, "peer", json_peer
);
8489 json_object_array_add(json_paths
, json_path
);
8494 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
8495 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
8496 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
8498 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
8499 const char *prefix_list_str
, afi_t afi
,
8500 safi_t safi
, enum bgp_show_type type
);
8501 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
8502 const char *filter
, afi_t afi
, safi_t safi
,
8503 enum bgp_show_type type
);
8504 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
8505 const char *rmap_str
, afi_t afi
, safi_t safi
,
8506 enum bgp_show_type type
);
8507 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
8508 const char *com
, int exact
, afi_t afi
,
8510 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
8511 const char *prefix
, afi_t afi
, safi_t safi
,
8512 enum bgp_show_type type
);
8513 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
8514 afi_t afi
, safi_t safi
, enum bgp_show_type type
);
8515 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
8516 const char *comstr
, int exact
, afi_t afi
,
8517 safi_t safi
, bool use_json
);
8520 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
8521 struct bgp_table
*table
, enum bgp_show_type type
,
8522 void *output_arg
, bool use_json
, char *rd
,
8523 int is_last
, unsigned long *output_cum
,
8524 unsigned long *total_cum
,
8525 unsigned long *json_header_depth
)
8527 struct bgp_path_info
*pi
;
8528 struct bgp_node
*rn
;
8531 unsigned long output_count
= 0;
8532 unsigned long total_count
= 0;
8535 json_object
*json_paths
= NULL
;
8538 if (output_cum
&& *output_cum
!= 0)
8541 if (use_json
&& !*json_header_depth
) {
8543 "{\n \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
8544 ",\n \"routerId\": \"%s\",\n \"defaultLocPrf\": %u,\n"
8545 " \"localAS\": %u,\n \"routes\": { ",
8546 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
8547 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
8550 table
->version
, inet_ntoa(bgp
->router_id
),
8551 bgp
->default_local_pref
, bgp
->as
);
8552 *json_header_depth
= 2;
8554 vty_out(vty
, " \"routeDistinguishers\" : {");
8555 ++*json_header_depth
;
8559 if (use_json
&& rd
) {
8560 vty_out(vty
, " \"%s\" : { ", rd
);
8563 /* Start processing of routes. */
8564 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
8565 pi
= bgp_node_get_bgp_path_info(rn
);
8571 json_paths
= json_object_new_array();
8575 for (; pi
; pi
= pi
->next
) {
8577 if (type
== bgp_show_type_flap_statistics
8578 || type
== bgp_show_type_flap_neighbor
8579 || type
== bgp_show_type_dampend_paths
8580 || type
== bgp_show_type_damp_neighbor
) {
8581 if (!(pi
->extra
&& pi
->extra
->damp_info
))
8584 if (type
== bgp_show_type_regexp
) {
8585 regex_t
*regex
= output_arg
;
8587 if (bgp_regexec(regex
, pi
->attr
->aspath
)
8591 if (type
== bgp_show_type_prefix_list
) {
8592 struct prefix_list
*plist
= output_arg
;
8594 if (prefix_list_apply(plist
, &rn
->p
)
8598 if (type
== bgp_show_type_filter_list
) {
8599 struct as_list
*as_list
= output_arg
;
8601 if (as_list_apply(as_list
, pi
->attr
->aspath
)
8602 != AS_FILTER_PERMIT
)
8605 if (type
== bgp_show_type_route_map
) {
8606 struct route_map
*rmap
= output_arg
;
8607 struct bgp_path_info path
;
8608 struct attr dummy_attr
;
8611 bgp_attr_dup(&dummy_attr
, pi
->attr
);
8613 path
.peer
= pi
->peer
;
8614 path
.attr
= &dummy_attr
;
8616 ret
= route_map_apply(rmap
, &rn
->p
, RMAP_BGP
,
8618 if (ret
== RMAP_DENYMATCH
)
8621 if (type
== bgp_show_type_neighbor
8622 || type
== bgp_show_type_flap_neighbor
8623 || type
== bgp_show_type_damp_neighbor
) {
8624 union sockunion
*su
= output_arg
;
8626 if (pi
->peer
== NULL
8627 || pi
->peer
->su_remote
== NULL
8628 || !sockunion_same(pi
->peer
->su_remote
, su
))
8631 if (type
== bgp_show_type_cidr_only
) {
8632 uint32_t destination
;
8634 destination
= ntohl(rn
->p
.u
.prefix4
.s_addr
);
8635 if (IN_CLASSC(destination
)
8636 && rn
->p
.prefixlen
== 24)
8638 if (IN_CLASSB(destination
)
8639 && rn
->p
.prefixlen
== 16)
8641 if (IN_CLASSA(destination
)
8642 && rn
->p
.prefixlen
== 8)
8645 if (type
== bgp_show_type_prefix_longer
) {
8647 if (!prefix_match(p
, &rn
->p
))
8650 if (type
== bgp_show_type_community_all
) {
8651 if (!pi
->attr
->community
)
8654 if (type
== bgp_show_type_community
) {
8655 struct community
*com
= output_arg
;
8657 if (!pi
->attr
->community
8658 || !community_match(pi
->attr
->community
,
8662 if (type
== bgp_show_type_community_exact
) {
8663 struct community
*com
= output_arg
;
8665 if (!pi
->attr
->community
8666 || !community_cmp(pi
->attr
->community
, com
))
8669 if (type
== bgp_show_type_community_list
) {
8670 struct community_list
*list
= output_arg
;
8672 if (!community_list_match(pi
->attr
->community
,
8676 if (type
== bgp_show_type_community_list_exact
) {
8677 struct community_list
*list
= output_arg
;
8679 if (!community_list_exact_match(
8680 pi
->attr
->community
, list
))
8683 if (type
== bgp_show_type_lcommunity
) {
8684 struct lcommunity
*lcom
= output_arg
;
8686 if (!pi
->attr
->lcommunity
8687 || !lcommunity_match(pi
->attr
->lcommunity
,
8691 if (type
== bgp_show_type_lcommunity_list
) {
8692 struct community_list
*list
= output_arg
;
8694 if (!lcommunity_list_match(pi
->attr
->lcommunity
,
8698 if (type
== bgp_show_type_lcommunity_all
) {
8699 if (!pi
->attr
->lcommunity
)
8702 if (type
== bgp_show_type_dampend_paths
8703 || type
== bgp_show_type_damp_neighbor
) {
8704 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
)
8705 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
8709 if (!use_json
&& header
) {
8710 vty_out(vty
, "BGP table version is %" PRIu64
8711 ", local router ID is %s, vrf id ",
8713 inet_ntoa(bgp
->router_id
));
8714 if (bgp
->vrf_id
== VRF_UNKNOWN
)
8715 vty_out(vty
, "%s", VRFID_NONE_STR
);
8717 vty_out(vty
, "%u", bgp
->vrf_id
);
8719 vty_out(vty
, "Default local pref %u, ",
8720 bgp
->default_local_pref
);
8721 vty_out(vty
, "local AS %u\n", bgp
->as
);
8722 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
8723 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
8724 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
8725 if (type
== bgp_show_type_dampend_paths
8726 || type
== bgp_show_type_damp_neighbor
)
8727 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
8728 else if (type
== bgp_show_type_flap_statistics
8729 || type
== bgp_show_type_flap_neighbor
)
8730 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
8732 vty_out(vty
, BGP_SHOW_HEADER
);
8735 if (rd
!= NULL
&& !display
&& !output_count
) {
8738 "Route Distinguisher: %s\n",
8741 if (type
== bgp_show_type_dampend_paths
8742 || type
== bgp_show_type_damp_neighbor
)
8743 damp_route_vty_out(vty
, &rn
->p
, pi
, display
,
8744 safi
, use_json
, json_paths
);
8745 else if (type
== bgp_show_type_flap_statistics
8746 || type
== bgp_show_type_flap_neighbor
)
8747 flap_route_vty_out(vty
, &rn
->p
, pi
, display
,
8748 safi
, use_json
, json_paths
);
8750 route_vty_out(vty
, &rn
->p
, pi
, display
, safi
,
8762 if (p
->family
== AF_FLOWSPEC
) {
8763 char retstr
[BGP_FLOWSPEC_STRING_DISPLAY_MAX
];
8765 bgp_fs_nlri_get_string((unsigned char *)
8766 p
->u
.prefix_flowspec
.ptr
,
8767 p
->u
.prefix_flowspec
8770 NLRI_STRING_FORMAT_MIN
,
8773 vty_out(vty
, "\"%s/%d\": ",
8775 p
->u
.prefix_flowspec
.prefixlen
);
8777 vty_out(vty
, ",\"%s/%d\": ",
8779 p
->u
.prefix_flowspec
.prefixlen
);
8781 prefix2str(p
, buf2
, sizeof(buf2
));
8783 vty_out(vty
, "\"%s\": ", buf2
);
8785 vty_out(vty
, ",\"%s\": ", buf2
);
8788 json_object_to_json_string(json_paths
));
8789 json_object_free(json_paths
);
8796 output_count
+= *output_cum
;
8797 *output_cum
= output_count
;
8800 total_count
+= *total_cum
;
8801 *total_cum
= total_count
;
8805 vty_out(vty
, " }%s ", (is_last
? "" : ","));
8809 for (i
= 0; i
< *json_header_depth
; ++i
)
8810 vty_out(vty
, " } ");
8814 /* No route is displayed */
8815 if (output_count
== 0) {
8816 if (type
== bgp_show_type_normal
)
8818 "No BGP prefixes displayed, %ld exist\n",
8822 "\nDisplayed %ld routes and %ld total paths\n",
8823 output_count
, total_count
);
8830 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
8831 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
8832 enum bgp_show_type type
, void *output_arg
, bool use_json
)
8834 struct bgp_node
*rn
, *next
;
8835 unsigned long output_cum
= 0;
8836 unsigned long total_cum
= 0;
8837 unsigned long json_header_depth
= 0;
8838 struct bgp_table
*itable
;
8841 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
8843 for (rn
= bgp_table_top(table
); rn
; rn
= next
) {
8844 next
= bgp_route_next(rn
);
8845 if (prd_match
&& memcmp(rn
->p
.u
.val
, prd_match
->val
, 8) != 0)
8848 itable
= bgp_node_get_bgp_table_info(rn
);
8849 if (itable
!= NULL
) {
8850 struct prefix_rd prd
;
8851 char rd
[RD_ADDRSTRLEN
];
8853 memcpy(&prd
, &(rn
->p
), sizeof(struct prefix_rd
));
8854 prefix_rd2str(&prd
, rd
, sizeof(rd
));
8855 bgp_show_table(vty
, bgp
, safi
, itable
, type
, output_arg
,
8856 use_json
, rd
, next
== NULL
, &output_cum
,
8857 &total_cum
, &json_header_depth
);
8863 if (output_cum
== 0)
8864 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
8868 "\nDisplayed %ld routes and %ld total paths\n",
8869 output_cum
, total_cum
);
8873 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
8874 enum bgp_show_type type
, void *output_arg
, bool use_json
)
8876 struct bgp_table
*table
;
8877 unsigned long json_header_depth
= 0;
8880 bgp
= bgp_get_default();
8885 vty_out(vty
, "No BGP process is configured\n");
8887 vty_out(vty
, "{}\n");
8891 table
= bgp
->rib
[afi
][safi
];
8892 /* use MPLS and ENCAP specific shows until they are merged */
8893 if (safi
== SAFI_MPLS_VPN
) {
8894 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
8895 output_arg
, use_json
);
8898 if (safi
== SAFI_FLOWSPEC
&& type
== bgp_show_type_detail
) {
8899 return bgp_show_table_flowspec(vty
, bgp
, afi
, table
, type
,
8900 output_arg
, use_json
,
8903 /* labeled-unicast routes live in the unicast table */
8904 else if (safi
== SAFI_LABELED_UNICAST
)
8905 safi
= SAFI_UNICAST
;
8907 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, use_json
,
8908 NULL
, 1, NULL
, NULL
, &json_header_depth
);
8911 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
8912 safi_t safi
, bool use_json
)
8914 struct listnode
*node
, *nnode
;
8917 bool route_output
= false;
8920 vty_out(vty
, "{\n");
8922 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
8923 route_output
= true;
8926 vty_out(vty
, ",\n");
8930 vty_out(vty
, "\"%s\":",
8931 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
8935 vty_out(vty
, "\nInstance %s:\n",
8936 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
8940 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
8945 vty_out(vty
, "}\n");
8946 else if (!route_output
)
8947 vty_out(vty
, "%% BGP instance not found\n");
8950 /* Header of detailed BGP route information */
8951 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
8952 struct bgp_node
*rn
, struct prefix_rd
*prd
,
8953 afi_t afi
, safi_t safi
, json_object
*json
)
8955 struct bgp_path_info
*pi
;
8958 struct listnode
*node
, *nnode
;
8959 char buf1
[RD_ADDRSTRLEN
];
8960 char buf2
[INET6_ADDRSTRLEN
];
8961 char buf3
[EVPN_ROUTE_STRLEN
];
8962 char prefix_str
[BUFSIZ
];
8967 int route_filter_translated_v4
= 0;
8968 int route_filter_v4
= 0;
8969 int route_filter_translated_v6
= 0;
8970 int route_filter_v6
= 0;
8973 int accept_own_nexthop
= 0;
8976 int no_advertise
= 0;
8980 int has_valid_label
= 0;
8981 mpls_label_t label
= 0;
8982 json_object
*json_adv_to
= NULL
;
8985 has_valid_label
= bgp_is_valid_label(&rn
->local_label
);
8987 if (has_valid_label
)
8988 label
= label_pton(&rn
->local_label
);
8991 if (has_valid_label
)
8992 json_object_int_add(json
, "localLabel", label
);
8994 json_object_string_add(
8996 prefix2str(p
, prefix_str
, sizeof(prefix_str
)));
8998 if (safi
== SAFI_EVPN
)
8999 vty_out(vty
, "BGP routing table entry for %s%s%s\n",
9000 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
))
9003 bgp_evpn_route2str((struct prefix_evpn
*)p
,
9004 buf3
, sizeof(buf3
)));
9006 vty_out(vty
, "BGP routing table entry for %s%s%s/%d\n",
9007 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
9008 ? prefix_rd2str(prd
, buf1
,
9011 safi
== SAFI_MPLS_VPN
? ":" : "",
9012 inet_ntop(p
->family
, &p
->u
.prefix
, buf2
,
9016 if (has_valid_label
)
9017 vty_out(vty
, "Local label: %d\n", label
);
9018 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
9019 vty_out(vty
, "not allocated\n");
9022 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
9024 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
9026 if (pi
->extra
&& pi
->extra
->suppress
)
9029 if (pi
->attr
->community
== NULL
)
9032 no_advertise
+= community_include(
9033 pi
->attr
->community
, COMMUNITY_NO_ADVERTISE
);
9034 no_export
+= community_include(pi
->attr
->community
,
9035 COMMUNITY_NO_EXPORT
);
9036 local_as
+= community_include(pi
->attr
->community
,
9037 COMMUNITY_LOCAL_AS
);
9038 accept_own
+= community_include(pi
->attr
->community
,
9039 COMMUNITY_ACCEPT_OWN
);
9040 route_filter_translated_v4
+= community_include(
9041 pi
->attr
->community
,
9042 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4
);
9043 route_filter_translated_v6
+= community_include(
9044 pi
->attr
->community
,
9045 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6
);
9046 route_filter_v4
+= community_include(
9047 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v4
);
9048 route_filter_v6
+= community_include(
9049 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v6
);
9050 llgr_stale
+= community_include(pi
->attr
->community
,
9051 COMMUNITY_LLGR_STALE
);
9052 no_llgr
+= community_include(pi
->attr
->community
,
9054 accept_own_nexthop
+=
9055 community_include(pi
->attr
->community
,
9056 COMMUNITY_ACCEPT_OWN_NEXTHOP
);
9057 blackhole
+= community_include(pi
->attr
->community
,
9058 COMMUNITY_BLACKHOLE
);
9059 no_peer
+= community_include(pi
->attr
->community
,
9065 vty_out(vty
, "Paths: (%d available", count
);
9067 vty_out(vty
, ", best #%d", best
);
9068 if (safi
== SAFI_UNICAST
)
9069 vty_out(vty
, ", table %s",
9071 == BGP_INSTANCE_TYPE_DEFAULT
)
9075 vty_out(vty
, ", no best path");
9079 ", accept own local route exported and imported in different VRF");
9080 else if (route_filter_translated_v4
)
9082 ", mark translated RTs for VPNv4 route filtering");
9083 else if (route_filter_v4
)
9085 ", attach RT as-is for VPNv4 route filtering");
9086 else if (route_filter_translated_v6
)
9088 ", mark translated RTs for VPNv6 route filtering");
9089 else if (route_filter_v6
)
9091 ", attach RT as-is for VPNv6 route filtering");
9092 else if (llgr_stale
)
9094 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
9097 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
9098 else if (accept_own_nexthop
)
9100 ", accept local nexthop");
9102 vty_out(vty
, ", inform peer to blackhole prefix");
9104 vty_out(vty
, ", not advertised to EBGP peer");
9105 else if (no_advertise
)
9106 vty_out(vty
, ", not advertised to any peer");
9108 vty_out(vty
, ", not advertised outside local AS");
9111 ", inform EBGP peer not to advertise to their EBGP peers");
9115 ", Advertisements suppressed by an aggregate.");
9116 vty_out(vty
, ")\n");
9119 /* If we are not using addpath then we can display Advertised to and
9121 * show what peers we advertised the bestpath to. If we are using
9123 * though then we must display Advertised to on a path-by-path basis. */
9124 if (!bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
9125 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
9126 if (bgp_adj_out_lookup(peer
, rn
, 0)) {
9127 if (json
&& !json_adv_to
)
9128 json_adv_to
= json_object_new_object();
9130 route_vty_out_advertised_to(
9132 " Advertised to non peer-group peers:\n ",
9139 json_object_object_add(json
, "advertisedTo",
9144 vty_out(vty
, " Not advertised to any peer");
9150 /* Display specified route of BGP table. */
9151 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
9152 struct bgp_table
*rib
, const char *ip_str
,
9153 afi_t afi
, safi_t safi
,
9154 struct prefix_rd
*prd
, int prefix_check
,
9155 enum bgp_path_type pathtype
, bool use_json
)
9160 struct prefix match
;
9161 struct bgp_node
*rn
;
9162 struct bgp_node
*rm
;
9163 struct bgp_path_info
*pi
;
9164 struct bgp_table
*table
;
9165 json_object
*json
= NULL
;
9166 json_object
*json_paths
= NULL
;
9168 /* Check IP address argument. */
9169 ret
= str2prefix(ip_str
, &match
);
9171 vty_out(vty
, "address is malformed\n");
9175 match
.family
= afi2family(afi
);
9178 json
= json_object_new_object();
9179 json_paths
= json_object_new_array();
9182 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
9183 for (rn
= bgp_table_top(rib
); rn
; rn
= bgp_route_next(rn
)) {
9184 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
9186 table
= bgp_node_get_bgp_table_info(rn
);
9192 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
9196 && rm
->p
.prefixlen
!= match
.prefixlen
) {
9197 bgp_unlock_node(rm
);
9201 for (pi
= bgp_node_get_bgp_path_info(rm
); pi
;
9204 route_vty_out_detail_header(
9206 (struct prefix_rd
*)&rn
->p
,
9207 AFI_IP
, safi
, json
);
9212 if (pathtype
== BGP_PATH_SHOW_ALL
9213 || (pathtype
== BGP_PATH_SHOW_BESTPATH
9214 && CHECK_FLAG(pi
->flags
,
9216 || (pathtype
== BGP_PATH_SHOW_MULTIPATH
9217 && (CHECK_FLAG(pi
->flags
,
9219 || CHECK_FLAG(pi
->flags
,
9220 BGP_PATH_SELECTED
))))
9221 route_vty_out_detail(vty
, bgp
, &rm
->p
,
9226 bgp_unlock_node(rm
);
9228 } else if (safi
== SAFI_FLOWSPEC
) {
9229 display
= bgp_flowspec_display_match_per_ip(afi
, rib
,
9230 &match
, prefix_check
,
9237 if ((rn
= bgp_node_match(rib
, &match
)) != NULL
) {
9239 || rn
->p
.prefixlen
== match
.prefixlen
) {
9240 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
;
9243 route_vty_out_detail_header(
9244 vty
, bgp
, rn
, NULL
, afi
,
9250 if (pathtype
== BGP_PATH_SHOW_ALL
9252 == BGP_PATH_SHOW_BESTPATH
9257 == BGP_PATH_SHOW_MULTIPATH
9263 BGP_PATH_SELECTED
))))
9264 route_vty_out_detail(
9265 vty
, bgp
, &rn
->p
, pi
,
9266 afi
, safi
, json_paths
);
9270 bgp_unlock_node(rn
);
9276 json_object_object_add(json
, "paths", json_paths
);
9278 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
9279 json
, JSON_C_TO_STRING_PRETTY
));
9280 json_object_free(json
);
9283 vty_out(vty
, "%% Network not in table\n");
9291 /* Display specified route of Main RIB */
9292 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
9293 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
9294 int prefix_check
, enum bgp_path_type pathtype
,
9298 bgp
= bgp_get_default();
9301 vty_out(vty
, "No BGP process is configured\n");
9303 vty_out(vty
, "{}\n");
9308 /* labeled-unicast routes live in the unicast table */
9309 if (safi
== SAFI_LABELED_UNICAST
)
9310 safi
= SAFI_UNICAST
;
9312 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
9313 afi
, safi
, prd
, prefix_check
, pathtype
,
9317 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
9318 struct cmd_token
**argv
, afi_t afi
, safi_t safi
,
9321 struct lcommunity
*lcom
;
9327 b
= buffer_new(1024);
9328 for (i
= 0; i
< argc
; i
++) {
9330 buffer_putc(b
, ' ');
9332 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
9334 buffer_putstr(b
, argv
[i
]->arg
);
9338 buffer_putc(b
, '\0');
9340 str
= buffer_getstr(b
);
9343 lcom
= lcommunity_str2com(str
);
9344 XFREE(MTYPE_TMP
, str
);
9346 vty_out(vty
, "%% Large-community malformed\n");
9350 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_lcommunity
, lcom
,
9354 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
9355 const char *lcom
, afi_t afi
, safi_t safi
,
9358 struct community_list
*list
;
9360 list
= community_list_lookup(bgp_clist
, lcom
, 0,
9361 LARGE_COMMUNITY_LIST_MASTER
);
9363 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
9368 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_lcommunity_list
,
9372 DEFUN (show_ip_bgp_large_community_list
,
9373 show_ip_bgp_large_community_list_cmd
,
9374 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community-list <(1-500)|WORD> [json]",
9378 BGP_INSTANCE_HELP_STR
9380 BGP_SAFI_WITH_LABEL_HELP_STR
9381 "Display routes matching the large-community-list\n"
9382 "large-community-list number\n"
9383 "large-community-list name\n"
9387 afi_t afi
= AFI_IP6
;
9388 safi_t safi
= SAFI_UNICAST
;
9391 if (argv_find(argv
, argc
, "ip", &idx
))
9393 if (argv_find(argv
, argc
, "view", &idx
)
9394 || argv_find(argv
, argc
, "vrf", &idx
))
9395 vrf
= argv
[++idx
]->arg
;
9396 if (argv_find(argv
, argc
, "ipv4", &idx
)
9397 || argv_find(argv
, argc
, "ipv6", &idx
)) {
9398 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
9399 if (argv_find(argv
, argc
, "unicast", &idx
)
9400 || argv_find(argv
, argc
, "multicast", &idx
))
9401 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
9404 bool uj
= use_json(argc
, argv
);
9406 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
9408 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
9412 argv_find(argv
, argc
, "large-community-list", &idx
);
9413 return bgp_show_lcommunity_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
, safi
,
9416 DEFUN (show_ip_bgp_large_community
,
9417 show_ip_bgp_large_community_cmd
,
9418 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [AA:BB:CC] [json]",
9422 BGP_INSTANCE_HELP_STR
9424 BGP_SAFI_WITH_LABEL_HELP_STR
9425 "Display routes matching the large-communities\n"
9426 "List of large-community numbers\n"
9430 afi_t afi
= AFI_IP6
;
9431 safi_t safi
= SAFI_UNICAST
;
9434 if (argv_find(argv
, argc
, "ip", &idx
))
9436 if (argv_find(argv
, argc
, "view", &idx
)
9437 || argv_find(argv
, argc
, "vrf", &idx
))
9438 vrf
= argv
[++idx
]->arg
;
9439 if (argv_find(argv
, argc
, "ipv4", &idx
)
9440 || argv_find(argv
, argc
, "ipv6", &idx
)) {
9441 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
9442 if (argv_find(argv
, argc
, "unicast", &idx
)
9443 || argv_find(argv
, argc
, "multicast", &idx
))
9444 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
9447 bool uj
= use_json(argc
, argv
);
9449 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
9451 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
9455 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
))
9456 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
, afi
, safi
, uj
);
9458 return bgp_show(vty
, bgp
, afi
, safi
,
9459 bgp_show_type_lcommunity_all
, NULL
, uj
);
9462 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
9466 /* BGP route print out function without JSON */
9469 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
9470 <dampening <parameters>\
9475 |community-list <(1-500)|WORD> [exact-match]\
9476 |A.B.C.D/M longer-prefixes\
9477 |X:X::X:X/M longer-prefixes\
9482 BGP_INSTANCE_HELP_STR
9484 BGP_SAFI_WITH_LABEL_HELP_STR
9485 "Display detailed information about dampening\n"
9486 "Display detail of configured dampening parameters\n"
9487 "Display routes matching the route-map\n"
9488 "A route-map to match on\n"
9489 "Display routes conforming to the prefix-list\n"
9490 "Prefix-list name\n"
9491 "Display routes conforming to the filter-list\n"
9492 "Regular expression access list name\n"
9493 "BGP RIB advertisement statistics\n"
9494 "Display routes matching the community-list\n"
9495 "community-list number\n"
9496 "community-list name\n"
9497 "Exact match of the communities\n"
9499 "Display route and more specific routes\n"
9501 "Display route and more specific routes\n")
9503 afi_t afi
= AFI_IP6
;
9504 safi_t safi
= SAFI_UNICAST
;
9505 int exact_match
= 0;
9506 struct bgp
*bgp
= NULL
;
9509 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9514 if (argv_find(argv
, argc
, "dampening", &idx
)) {
9515 if (argv_find(argv
, argc
, "parameters", &idx
))
9516 return bgp_show_dampening_parameters(vty
, afi
, safi
);
9519 if (argv_find(argv
, argc
, "prefix-list", &idx
))
9520 return bgp_show_prefix_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9521 safi
, bgp_show_type_prefix_list
);
9523 if (argv_find(argv
, argc
, "filter-list", &idx
))
9524 return bgp_show_filter_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9525 safi
, bgp_show_type_filter_list
);
9527 if (argv_find(argv
, argc
, "statistics", &idx
))
9528 return bgp_table_stats(vty
, bgp
, afi
, safi
);
9530 if (argv_find(argv
, argc
, "route-map", &idx
))
9531 return bgp_show_route_map(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9532 safi
, bgp_show_type_route_map
);
9534 if (argv_find(argv
, argc
, "community-list", &idx
)) {
9535 const char *clist_number_or_name
= argv
[++idx
]->arg
;
9536 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
9538 return bgp_show_community_list(vty
, bgp
, clist_number_or_name
,
9539 exact_match
, afi
, safi
);
9542 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
9543 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
9544 return bgp_show_prefix_longer(vty
, bgp
, argv
[idx
]->arg
, afi
,
9546 bgp_show_type_prefix_longer
);
9551 /* BGP route print out function with JSON */
9552 DEFUN (show_ip_bgp_json
,
9553 show_ip_bgp_json_cmd
,
9554 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
9556 |dampening <flap-statistics|dampened-paths>\
9557 |community [AA:NN|local-AS|no-advertise|no-export\
9558 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
9559 |accept-own|accept-own-nexthop|route-filter-v6\
9560 |route-filter-v4|route-filter-translated-v6\
9561 |route-filter-translated-v4] [exact-match]\
9566 BGP_INSTANCE_HELP_STR
9568 BGP_SAFI_WITH_LABEL_HELP_STR
9569 "Display only routes with non-natural netmasks\n"
9570 "Display detailed information about dampening\n"
9571 "Display flap statistics of routes\n"
9572 "Display paths suppressed due to dampening\n"
9573 "Display routes matching the communities\n"
9575 "Do not send outside local AS (well-known community)\n"
9576 "Do not advertise to any peer (well-known community)\n"
9577 "Do not export to next AS (well-known community)\n"
9578 "Graceful shutdown (well-known community)\n"
9579 "Do not export to any peer (well-known community)\n"
9580 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
9581 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
9582 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
9583 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
9584 "Should accept VPN route with local nexthop (well-known community)\n"
9585 "RT VPNv6 route filtering (well-known community)\n"
9586 "RT VPNv4 route filtering (well-known community)\n"
9587 "RT translated VPNv6 route filtering (well-known community)\n"
9588 "RT translated VPNv4 route filtering (well-known community)\n"
9589 "Exact match of the communities\n"
9592 afi_t afi
= AFI_IP6
;
9593 safi_t safi
= SAFI_UNICAST
;
9594 enum bgp_show_type sh_type
= bgp_show_type_normal
;
9595 struct bgp
*bgp
= NULL
;
9597 int exact_match
= 0;
9598 bool uj
= use_json(argc
, argv
);
9603 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9608 if (argv_find(argv
, argc
, "cidr-only", &idx
))
9609 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_cidr_only
,
9612 if (argv_find(argv
, argc
, "dampening", &idx
)) {
9613 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
9614 return bgp_show(vty
, bgp
, afi
, safi
,
9615 bgp_show_type_dampend_paths
, NULL
, uj
);
9616 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
9617 return bgp_show(vty
, bgp
, afi
, safi
,
9618 bgp_show_type_flap_statistics
, NULL
,
9622 if (argv_find(argv
, argc
, "community", &idx
)) {
9623 char *maybecomm
= NULL
;
9624 char *community
= NULL
;
9626 if (idx
+ 1 < argc
) {
9627 if (argv
[idx
+ 1]->type
== VARIABLE_TKN
)
9628 maybecomm
= argv
[idx
+ 1]->arg
;
9630 maybecomm
= argv
[idx
+ 1]->text
;
9633 if (maybecomm
&& !strmatch(maybecomm
, "json")
9634 && !strmatch(maybecomm
, "exact-match"))
9635 community
= maybecomm
;
9637 if (argv_find(argv
, argc
, "exact-match", &idx
))
9641 return bgp_show_community(vty
, bgp
, community
,
9642 exact_match
, afi
, safi
, uj
);
9644 return (bgp_show(vty
, bgp
, afi
, safi
,
9645 bgp_show_type_community_all
, NULL
,
9649 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
, NULL
, uj
);
9652 DEFUN (show_ip_bgp_route
,
9653 show_ip_bgp_route_cmd
,
9654 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]"
9655 "<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [json]",
9659 BGP_INSTANCE_HELP_STR
9661 BGP_SAFI_WITH_LABEL_HELP_STR
9662 "Network in the BGP routing table to display\n"
9664 "Network in the BGP routing table to display\n"
9666 "Display only the bestpath\n"
9667 "Display only multipaths\n"
9670 int prefix_check
= 0;
9672 afi_t afi
= AFI_IP6
;
9673 safi_t safi
= SAFI_UNICAST
;
9674 char *prefix
= NULL
;
9675 struct bgp
*bgp
= NULL
;
9676 enum bgp_path_type path_type
;
9677 bool uj
= use_json(argc
, argv
);
9681 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9688 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
9692 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
9693 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
9694 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
9696 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
9697 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
9700 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
9701 && afi
!= AFI_IP6
) {
9703 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
9706 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
9709 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
9713 prefix
= argv
[idx
]->arg
;
9715 /* [<bestpath|multipath>] */
9716 if (argv_find(argv
, argc
, "bestpath", &idx
))
9717 path_type
= BGP_PATH_SHOW_BESTPATH
;
9718 else if (argv_find(argv
, argc
, "multipath", &idx
))
9719 path_type
= BGP_PATH_SHOW_MULTIPATH
;
9721 path_type
= BGP_PATH_SHOW_ALL
;
9723 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
9727 DEFUN (show_ip_bgp_regexp
,
9728 show_ip_bgp_regexp_cmd
,
9729 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX...",
9733 BGP_INSTANCE_HELP_STR
9735 BGP_SAFI_WITH_LABEL_HELP_STR
9736 "Display routes matching the AS path regular expression\n"
9737 "A regular-expression to match the BGP AS paths\n")
9739 afi_t afi
= AFI_IP6
;
9740 safi_t safi
= SAFI_UNICAST
;
9741 struct bgp
*bgp
= NULL
;
9744 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9749 // get index of regex
9750 argv_find(argv
, argc
, "regexp", &idx
);
9753 char *regstr
= argv_concat(argv
, argc
, idx
);
9754 int rc
= bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
9755 bgp_show_type_regexp
);
9756 XFREE(MTYPE_TMP
, regstr
);
9760 DEFUN (show_ip_bgp_instance_all
,
9761 show_ip_bgp_instance_all_cmd
,
9762 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json]",
9766 BGP_INSTANCE_ALL_HELP_STR
9768 BGP_SAFI_WITH_LABEL_HELP_STR
9772 safi_t safi
= SAFI_UNICAST
;
9773 struct bgp
*bgp
= NULL
;
9775 bool uj
= use_json(argc
, argv
);
9780 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9785 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, uj
);
9789 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
9790 afi_t afi
, safi_t safi
, enum bgp_show_type type
)
9795 regex
= bgp_regcomp(regstr
);
9797 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
9801 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, 0);
9802 bgp_regex_free(regex
);
9806 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
9807 const char *prefix_list_str
, afi_t afi
,
9808 safi_t safi
, enum bgp_show_type type
)
9810 struct prefix_list
*plist
;
9812 plist
= prefix_list_lookup(afi
, prefix_list_str
);
9813 if (plist
== NULL
) {
9814 vty_out(vty
, "%% %s is not a valid prefix-list name\n",
9819 return bgp_show(vty
, bgp
, afi
, safi
, type
, plist
, 0);
9822 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
9823 const char *filter
, afi_t afi
, safi_t safi
,
9824 enum bgp_show_type type
)
9826 struct as_list
*as_list
;
9828 as_list
= as_list_lookup(filter
);
9829 if (as_list
== NULL
) {
9830 vty_out(vty
, "%% %s is not a valid AS-path access-list name\n",
9835 return bgp_show(vty
, bgp
, afi
, safi
, type
, as_list
, 0);
9838 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
9839 const char *rmap_str
, afi_t afi
, safi_t safi
,
9840 enum bgp_show_type type
)
9842 struct route_map
*rmap
;
9844 rmap
= route_map_lookup_by_name(rmap_str
);
9846 vty_out(vty
, "%% %s is not a valid route-map name\n", rmap_str
);
9850 return bgp_show(vty
, bgp
, afi
, safi
, type
, rmap
, 0);
9853 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
9854 const char *comstr
, int exact
, afi_t afi
,
9855 safi_t safi
, bool use_json
)
9857 struct community
*com
;
9860 com
= community_str2com(comstr
);
9862 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
9866 ret
= bgp_show(vty
, bgp
, afi
, safi
,
9867 (exact
? bgp_show_type_community_exact
9868 : bgp_show_type_community
),
9870 community_free(&com
);
9875 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
9876 const char *com
, int exact
, afi_t afi
,
9879 struct community_list
*list
;
9881 list
= community_list_lookup(bgp_clist
, com
, 0, COMMUNITY_LIST_MASTER
);
9883 vty_out(vty
, "%% %s is not a valid community-list name\n", com
);
9887 return bgp_show(vty
, bgp
, afi
, safi
,
9888 (exact
? bgp_show_type_community_list_exact
9889 : bgp_show_type_community_list
),
9893 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
9894 const char *prefix
, afi_t afi
, safi_t safi
,
9895 enum bgp_show_type type
)
9902 ret
= str2prefix(prefix
, p
);
9904 vty_out(vty
, "%% Malformed Prefix\n");
9908 ret
= bgp_show(vty
, bgp
, afi
, safi
, type
, p
, 0);
9913 static struct peer
*peer_lookup_in_view(struct vty
*vty
, struct bgp
*bgp
,
9914 const char *ip_str
, bool use_json
)
9920 /* Get peer sockunion. */
9921 ret
= str2sockunion(ip_str
, &su
);
9923 peer
= peer_lookup_by_conf_if(bgp
, ip_str
);
9925 peer
= peer_lookup_by_hostname(bgp
, ip_str
);
9929 json_object
*json_no
= NULL
;
9930 json_no
= json_object_new_object();
9931 json_object_string_add(
9933 "malformedAddressOrName",
9935 vty_out(vty
, "%s\n",
9936 json_object_to_json_string_ext(
9938 JSON_C_TO_STRING_PRETTY
));
9939 json_object_free(json_no
);
9942 "%% Malformed address or name: %s\n",
9950 /* Peer structure lookup. */
9951 peer
= peer_lookup(bgp
, &su
);
9954 json_object
*json_no
= NULL
;
9955 json_no
= json_object_new_object();
9956 json_object_string_add(json_no
, "warning",
9957 "No such neighbor in this view/vrf");
9958 vty_out(vty
, "%s\n",
9959 json_object_to_json_string_ext(
9960 json_no
, JSON_C_TO_STRING_PRETTY
));
9961 json_object_free(json_no
);
9963 vty_out(vty
, "No such neighbor in this view/vrf\n");
9971 BGP_STATS_MAXBITLEN
= 0,
9975 BGP_STATS_UNAGGREGATEABLE
,
9976 BGP_STATS_MAX_AGGREGATEABLE
,
9977 BGP_STATS_AGGREGATES
,
9979 BGP_STATS_ASPATH_COUNT
,
9980 BGP_STATS_ASPATH_MAXHOPS
,
9981 BGP_STATS_ASPATH_TOTHOPS
,
9982 BGP_STATS_ASPATH_MAXSIZE
,
9983 BGP_STATS_ASPATH_TOTSIZE
,
9984 BGP_STATS_ASN_HIGHEST
,
9988 static const char *table_stats_strs
[] = {
9989 [BGP_STATS_PREFIXES
] = "Total Prefixes",
9990 [BGP_STATS_TOTPLEN
] = "Average prefix length",
9991 [BGP_STATS_RIB
] = "Total Advertisements",
9992 [BGP_STATS_UNAGGREGATEABLE
] = "Unaggregateable prefixes",
9993 [BGP_STATS_MAX_AGGREGATEABLE
] =
9994 "Maximum aggregateable prefixes",
9995 [BGP_STATS_AGGREGATES
] = "BGP Aggregate advertisements",
9996 [BGP_STATS_SPACE
] = "Address space advertised",
9997 [BGP_STATS_ASPATH_COUNT
] = "Advertisements with paths",
9998 [BGP_STATS_ASPATH_MAXHOPS
] = "Longest AS-Path (hops)",
9999 [BGP_STATS_ASPATH_MAXSIZE
] = "Largest AS-Path (bytes)",
10000 [BGP_STATS_ASPATH_TOTHOPS
] = "Average AS-Path length (hops)",
10001 [BGP_STATS_ASPATH_TOTSIZE
] = "Average AS-Path size (bytes)",
10002 [BGP_STATS_ASN_HIGHEST
] = "Highest public ASN",
10003 [BGP_STATS_MAX
] = NULL
,
10006 struct bgp_table_stats
{
10007 struct bgp_table
*table
;
10008 unsigned long long counts
[BGP_STATS_MAX
];
10009 double total_space
;
10013 #define TALLY_SIGFIG 100000
10014 static unsigned long
10015 ravg_tally (unsigned long count
, unsigned long oldavg
, unsigned long newval
)
10017 unsigned long newtot
= (count
-1) * oldavg
+ (newval
* TALLY_SIGFIG
);
10018 unsigned long res
= (newtot
* TALLY_SIGFIG
) / count
;
10019 unsigned long ret
= newtot
/ count
;
10021 if ((res
% TALLY_SIGFIG
) > (TALLY_SIGFIG
/2))
10028 static int bgp_table_stats_walker(struct thread
*t
)
10030 struct bgp_node
*rn
;
10031 struct bgp_node
*top
;
10032 struct bgp_table_stats
*ts
= THREAD_ARG(t
);
10033 unsigned int space
= 0;
10035 if (!(top
= bgp_table_top(ts
->table
)))
10038 switch (top
->p
.family
) {
10040 space
= IPV4_MAX_BITLEN
;
10043 space
= IPV6_MAX_BITLEN
;
10047 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
10049 for (rn
= top
; rn
; rn
= bgp_route_next(rn
)) {
10050 struct bgp_path_info
*pi
;
10051 struct bgp_node
*prn
= bgp_node_parent_nolock(rn
);
10052 unsigned int pinum
= 0;
10057 if (!bgp_node_has_bgp_path_info_data(rn
))
10060 ts
->counts
[BGP_STATS_PREFIXES
]++;
10061 ts
->counts
[BGP_STATS_TOTPLEN
] += rn
->p
.prefixlen
;
10064 ts
->counts
[BGP_STATS_AVGPLEN
]
10065 = ravg_tally (ts
->counts
[BGP_STATS_PREFIXES
],
10066 ts
->counts
[BGP_STATS_AVGPLEN
],
10070 /* check if the prefix is included by any other announcements */
10071 while (prn
&& !bgp_node_has_bgp_path_info_data(prn
))
10072 prn
= bgp_node_parent_nolock(prn
);
10074 if (prn
== NULL
|| prn
== top
) {
10075 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
10076 /* announced address space */
10079 pow(2.0, space
- rn
->p
.prefixlen
);
10080 } else if (bgp_node_has_bgp_path_info_data(prn
))
10081 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
10083 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
10085 ts
->counts
[BGP_STATS_RIB
]++;
10088 && (CHECK_FLAG(pi
->attr
->flag
,
10090 BGP_ATTR_ATOMIC_AGGREGATE
))))
10091 ts
->counts
[BGP_STATS_AGGREGATES
]++;
10093 /* as-path stats */
10094 if (pi
->attr
&& pi
->attr
->aspath
) {
10095 unsigned int hops
=
10096 aspath_count_hops(pi
->attr
->aspath
);
10097 unsigned int size
=
10098 aspath_size(pi
->attr
->aspath
);
10099 as_t highest
= aspath_highest(pi
->attr
->aspath
);
10101 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
10103 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
10104 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] =
10107 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
10108 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] =
10111 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
10112 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
10114 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
]
10115 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
10116 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
],
10118 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
]
10119 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
10120 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
],
10123 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
10124 ts
->counts
[BGP_STATS_ASN_HIGHEST
] =
10132 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
10135 struct bgp_table_stats ts
;
10138 if (!bgp
->rib
[afi
][safi
]) {
10139 vty_out(vty
, "%% No RIB exist's for the AFI(%d)/SAFI(%d)\n",
10141 return CMD_WARNING
;
10144 vty_out(vty
, "BGP %s RIB statistics\n", afi_safi_print(afi
, safi
));
10146 /* labeled-unicast routes live in the unicast table */
10147 if (safi
== SAFI_LABELED_UNICAST
)
10148 safi
= SAFI_UNICAST
;
10150 memset(&ts
, 0, sizeof(ts
));
10151 ts
.table
= bgp
->rib
[afi
][safi
];
10152 thread_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
10154 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
10155 if (!table_stats_strs
[i
])
10160 case BGP_STATS_ASPATH_AVGHOPS
:
10161 case BGP_STATS_ASPATH_AVGSIZE
:
10162 case BGP_STATS_AVGPLEN
:
10163 vty_out (vty
, "%-30s: ", table_stats_strs
[i
]);
10164 vty_out (vty
, "%12.2f",
10165 (float)ts
.counts
[i
] / (float)TALLY_SIGFIG
);
10168 case BGP_STATS_ASPATH_TOTHOPS
:
10169 case BGP_STATS_ASPATH_TOTSIZE
:
10170 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10171 vty_out(vty
, "%12.2f",
10173 ? (float)ts
.counts
[i
]
10175 [BGP_STATS_ASPATH_COUNT
]
10178 case BGP_STATS_TOTPLEN
:
10179 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10180 vty_out(vty
, "%12.2f",
10182 ? (float)ts
.counts
[i
]
10184 [BGP_STATS_PREFIXES
]
10187 case BGP_STATS_SPACE
:
10188 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10189 vty_out(vty
, "%12g\n", ts
.total_space
);
10191 if (afi
== AFI_IP6
) {
10192 vty_out(vty
, "%30s: ", "/32 equivalent ");
10193 vty_out(vty
, "%12g\n",
10194 ts
.total_space
* pow(2.0, -128 + 32));
10195 vty_out(vty
, "%30s: ", "/48 equivalent ");
10196 vty_out(vty
, "%12g\n",
10197 ts
.total_space
* pow(2.0, -128 + 48));
10199 vty_out(vty
, "%30s: ", "% announced ");
10200 vty_out(vty
, "%12.2f\n",
10201 ts
.total_space
* 100. * pow(2.0, -32));
10202 vty_out(vty
, "%30s: ", "/8 equivalent ");
10203 vty_out(vty
, "%12.2f\n",
10204 ts
.total_space
* pow(2.0, -32 + 8));
10205 vty_out(vty
, "%30s: ", "/24 equivalent ");
10206 vty_out(vty
, "%12.2f\n",
10207 ts
.total_space
* pow(2.0, -32 + 24));
10211 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10212 vty_out(vty
, "%12llu", ts
.counts
[i
]);
10215 vty_out(vty
, "\n");
10217 return CMD_SUCCESS
;
10229 PCOUNT_PFCNT
, /* the figure we display to users */
10233 static const char *pcount_strs
[] = {
10234 [PCOUNT_ADJ_IN
] = "Adj-in",
10235 [PCOUNT_DAMPED
] = "Damped",
10236 [PCOUNT_REMOVED
] = "Removed",
10237 [PCOUNT_HISTORY
] = "History",
10238 [PCOUNT_STALE
] = "Stale",
10239 [PCOUNT_VALID
] = "Valid",
10240 [PCOUNT_ALL
] = "All RIB",
10241 [PCOUNT_COUNTED
] = "PfxCt counted",
10242 [PCOUNT_PFCNT
] = "Useable",
10243 [PCOUNT_MAX
] = NULL
,
10246 struct peer_pcounts
{
10247 unsigned int count
[PCOUNT_MAX
];
10248 const struct peer
*peer
;
10249 const struct bgp_table
*table
;
10252 static int bgp_peer_count_walker(struct thread
*t
)
10254 struct bgp_node
*rn
;
10255 struct peer_pcounts
*pc
= THREAD_ARG(t
);
10256 const struct peer
*peer
= pc
->peer
;
10258 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
)) {
10259 struct bgp_adj_in
*ain
;
10260 struct bgp_path_info
*pi
;
10262 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
10263 if (ain
->peer
== peer
)
10264 pc
->count
[PCOUNT_ADJ_IN
]++;
10266 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
10268 if (pi
->peer
!= peer
)
10271 pc
->count
[PCOUNT_ALL
]++;
10273 if (CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
))
10274 pc
->count
[PCOUNT_DAMPED
]++;
10275 if (CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
10276 pc
->count
[PCOUNT_HISTORY
]++;
10277 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
10278 pc
->count
[PCOUNT_REMOVED
]++;
10279 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
10280 pc
->count
[PCOUNT_STALE
]++;
10281 if (CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
10282 pc
->count
[PCOUNT_VALID
]++;
10283 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
10284 pc
->count
[PCOUNT_PFCNT
]++;
10286 if (CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
10287 pc
->count
[PCOUNT_COUNTED
]++;
10288 if (CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
10290 EC_LIB_DEVELOPMENT
,
10291 "Attempting to count but flags say it is unusable");
10293 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
10295 EC_LIB_DEVELOPMENT
,
10296 "Not counted but flags say we should");
10303 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
10304 safi_t safi
, bool use_json
)
10306 struct peer_pcounts pcounts
= {.peer
= peer
};
10308 json_object
*json
= NULL
;
10309 json_object
*json_loop
= NULL
;
10312 json
= json_object_new_object();
10313 json_loop
= json_object_new_object();
10316 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
10317 || !peer
->bgp
->rib
[afi
][safi
]) {
10319 json_object_string_add(
10321 "No such neighbor or address family");
10322 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10323 json_object_free(json
);
10325 vty_out(vty
, "%% No such neighbor or address family\n");
10327 return CMD_WARNING
;
10330 memset(&pcounts
, 0, sizeof(pcounts
));
10331 pcounts
.peer
= peer
;
10332 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
10334 /* in-place call via thread subsystem so as to record execution time
10335 * stats for the thread-walk (i.e. ensure this can't be blamed on
10336 * on just vty_read()).
10338 thread_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
10341 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
10342 json_object_string_add(json
, "multiProtocol",
10343 afi_safi_print(afi
, safi
));
10344 json_object_int_add(json
, "pfxCounter",
10345 peer
->pcount
[afi
][safi
]);
10347 for (i
= 0; i
< PCOUNT_MAX
; i
++)
10348 json_object_int_add(json_loop
, pcount_strs
[i
],
10351 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
10353 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
10354 json_object_string_add(json
, "pfxctDriftFor",
10356 json_object_string_add(
10357 json
, "recommended",
10358 "Please report this bug, with the above command output");
10360 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
10361 json
, JSON_C_TO_STRING_PRETTY
));
10362 json_object_free(json
);
10366 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
10367 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
10368 peer
->hostname
, peer
->host
,
10369 afi_safi_print(afi
, safi
));
10371 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
10372 afi_safi_print(afi
, safi
));
10375 vty_out(vty
, "PfxCt: %ld\n", peer
->pcount
[afi
][safi
]);
10376 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
10378 for (i
= 0; i
< PCOUNT_MAX
; i
++)
10379 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
10382 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
10383 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
10385 "Please report this bug, with the above command output\n");
10389 return CMD_SUCCESS
;
10392 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
10393 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
10394 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_CMD_STR
"]] "
10395 "neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
10399 BGP_INSTANCE_HELP_STR
10402 "Detailed information on TCP and BGP neighbor connections\n"
10403 "Neighbor to display information about\n"
10404 "Neighbor to display information about\n"
10405 "Neighbor on BGP configured interface\n"
10406 "Display detailed prefix count information\n"
10409 afi_t afi
= AFI_IP6
;
10410 safi_t safi
= SAFI_UNICAST
;
10413 struct bgp
*bgp
= NULL
;
10414 bool uj
= use_json(argc
, argv
);
10419 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10422 return CMD_WARNING
;
10424 argv_find(argv
, argc
, "neighbors", &idx
);
10425 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
10427 return CMD_WARNING
;
10429 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_UNICAST
, uj
);
10432 #ifdef KEEP_OLD_VPN_COMMANDS
10433 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
10434 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
10435 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
10440 "Display information about all VPNv4 NLRIs\n"
10441 "Detailed information on TCP and BGP neighbor connections\n"
10442 "Neighbor to display information about\n"
10443 "Neighbor to display information about\n"
10444 "Neighbor on BGP configured interface\n"
10445 "Display detailed prefix count information\n"
10450 bool uj
= use_json(argc
, argv
);
10452 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
10454 return CMD_WARNING
;
10456 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
10459 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
10460 show_ip_bgp_vpn_all_route_prefix_cmd
,
10461 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
10466 "Display information about all VPNv4 NLRIs\n"
10467 "Network in the BGP routing table to display\n"
10468 "Network in the BGP routing table to display\n"
10472 char *network
= NULL
;
10473 struct bgp
*bgp
= bgp_get_default();
10475 vty_out(vty
, "Can't find default instance\n");
10476 return CMD_WARNING
;
10479 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
10480 network
= argv
[idx
]->arg
;
10481 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
10482 network
= argv
[idx
]->arg
;
10484 vty_out(vty
, "Unable to figure out Network\n");
10485 return CMD_WARNING
;
10488 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
10489 BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
10491 #endif /* KEEP_OLD_VPN_COMMANDS */
10493 DEFUN (show_ip_bgp_l2vpn_evpn_all_route_prefix
,
10494 show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd
,
10495 "show [ip] bgp l2vpn evpn all <A.B.C.D|A.B.C.D/M> [json]",
10501 "Display information about all EVPN NLRIs\n"
10502 "Network in the BGP routing table to display\n"
10503 "Network in the BGP routing table to display\n"
10507 char *network
= NULL
;
10509 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
10510 network
= argv
[idx
]->arg
;
10511 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
10512 network
= argv
[idx
]->arg
;
10514 vty_out(vty
, "Unable to figure out Network\n");
10515 return CMD_WARNING
;
10517 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
, 0,
10518 BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
10521 static void show_adj_route(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
10522 safi_t safi
, enum bgp_show_adj_route_type type
,
10523 const char *rmap_name
, bool use_json
,
10526 struct bgp_table
*table
;
10527 struct bgp_adj_in
*ain
;
10528 struct bgp_adj_out
*adj
;
10529 unsigned long output_count
;
10530 unsigned long filtered_count
;
10531 struct bgp_node
*rn
;
10537 struct update_subgroup
*subgrp
;
10538 json_object
*json_scode
= NULL
;
10539 json_object
*json_ocode
= NULL
;
10540 json_object
*json_ar
= NULL
;
10541 struct peer_af
*paf
;
10542 bool route_filtered
;
10545 json_scode
= json_object_new_object();
10546 json_ocode
= json_object_new_object();
10547 json_ar
= json_object_new_object();
10549 json_object_string_add(json_scode
, "suppressed", "s");
10550 json_object_string_add(json_scode
, "damped", "d");
10551 json_object_string_add(json_scode
, "history", "h");
10552 json_object_string_add(json_scode
, "valid", "*");
10553 json_object_string_add(json_scode
, "best", ">");
10554 json_object_string_add(json_scode
, "multipath", "=");
10555 json_object_string_add(json_scode
, "internal", "i");
10556 json_object_string_add(json_scode
, "ribFailure", "r");
10557 json_object_string_add(json_scode
, "stale", "S");
10558 json_object_string_add(json_scode
, "removed", "R");
10560 json_object_string_add(json_ocode
, "igp", "i");
10561 json_object_string_add(json_ocode
, "egp", "e");
10562 json_object_string_add(json_ocode
, "incomplete", "?");
10569 json_object_string_add(json
, "alert", "no BGP");
10570 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10571 json_object_free(json
);
10573 vty_out(vty
, "%% No bgp\n");
10577 table
= bgp
->rib
[afi
][safi
];
10579 output_count
= filtered_count
= 0;
10580 subgrp
= peer_subgroup(peer
, afi
, safi
);
10582 if (type
== bgp_show_adj_route_advertised
&& subgrp
10583 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
10585 json_object_int_add(json
, "bgpTableVersion",
10587 json_object_string_add(json
, "bgpLocalRouterId",
10588 inet_ntoa(bgp
->router_id
));
10589 json_object_int_add(json
, "defaultLocPrf",
10590 bgp
->default_local_pref
);
10591 json_object_int_add(json
, "localAS", bgp
->as
);
10592 json_object_object_add(json
, "bgpStatusCodes",
10594 json_object_object_add(json
, "bgpOriginCodes",
10596 json_object_string_add(
10597 json
, "bgpOriginatingDefaultNetwork",
10598 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
10600 vty_out(vty
, "BGP table version is %" PRIu64
10601 ", local router ID is %s, vrf id ",
10602 table
->version
, inet_ntoa(bgp
->router_id
));
10603 if (bgp
->vrf_id
== VRF_UNKNOWN
)
10604 vty_out(vty
, "%s", VRFID_NONE_STR
);
10606 vty_out(vty
, "%u", bgp
->vrf_id
);
10607 vty_out(vty
, "\n");
10608 vty_out(vty
, "Default local pref %u, ",
10609 bgp
->default_local_pref
);
10610 vty_out(vty
, "local AS %u\n", bgp
->as
);
10611 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
10612 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
10613 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
10615 vty_out(vty
, "Originating default network %s\n\n",
10616 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
10621 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
10622 if (type
== bgp_show_adj_route_received
10623 || type
== bgp_show_adj_route_filtered
) {
10624 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
10625 if (ain
->peer
!= peer
|| !ain
->attr
)
10630 json_object_int_add(
10631 json
, "bgpTableVersion",
10633 json_object_string_add(
10635 "bgpLocalRouterId",
10638 json_object_int_add(json
,
10640 bgp
->default_local_pref
);
10641 json_object_int_add(json
,
10642 "localAS", bgp
->as
);
10643 json_object_object_add(
10644 json
, "bgpStatusCodes",
10646 json_object_object_add(
10647 json
, "bgpOriginCodes",
10651 "BGP table version is 0, local router ID is %s, vrf id ",
10654 if (bgp
->vrf_id
== VRF_UNKNOWN
)
10660 vty_out(vty
, "\n");
10662 "Default local pref %u, ",
10663 bgp
->default_local_pref
);
10664 vty_out(vty
, "local AS %u\n",
10667 BGP_SHOW_SCODE_HEADER
);
10669 BGP_SHOW_NCODE_HEADER
);
10671 BGP_SHOW_OCODE_HEADER
);
10677 vty_out(vty
, BGP_SHOW_HEADER
);
10681 bgp_attr_dup(&attr
, ain
->attr
);
10682 route_filtered
= false;
10684 /* Filter prefix using distribute list,
10685 * filter list or prefix list
10687 if ((bgp_input_filter(peer
, &rn
->p
, &attr
, afi
,
10688 safi
)) == FILTER_DENY
)
10689 route_filtered
= true;
10691 /* Filter prefix using route-map */
10692 ret
= bgp_input_modifier(peer
, &rn
->p
, &attr
,
10693 afi
, safi
, rmap_name
);
10695 if (type
== bgp_show_adj_route_filtered
&&
10696 !route_filtered
&& ret
!= RMAP_DENY
) {
10697 bgp_attr_undup(&attr
, ain
->attr
);
10701 if (type
== bgp_show_adj_route_received
&&
10702 (route_filtered
|| ret
== RMAP_DENY
))
10705 route_vty_out_tmp(vty
, &rn
->p
, &attr
, safi
,
10706 use_json
, json_ar
);
10707 bgp_attr_undup(&attr
, ain
->attr
);
10710 } else if (type
== bgp_show_adj_route_advertised
) {
10711 RB_FOREACH (adj
, bgp_adj_out_rb
, &rn
->adj_out
)
10712 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
10713 if (paf
->peer
!= peer
|| !adj
->attr
)
10718 json_object_int_add(
10722 json_object_string_add(
10724 "bgpLocalRouterId",
10727 json_object_int_add(
10728 json
, "defaultLocPrf",
10729 bgp
->default_local_pref
10731 json_object_int_add(
10734 json_object_object_add(
10738 json_object_object_add(
10744 "BGP table version is %" PRIu64
10745 ", local router ID is %s, vrf id ",
10758 vty_out(vty
, "\n");
10760 "Default local pref %u, ",
10761 bgp
->default_local_pref
10767 BGP_SHOW_SCODE_HEADER
);
10769 BGP_SHOW_NCODE_HEADER
);
10771 BGP_SHOW_OCODE_HEADER
);
10782 bgp_attr_dup(&attr
, adj
->attr
);
10783 ret
= bgp_output_modifier(
10784 peer
, &rn
->p
, &attr
, afi
, safi
,
10787 if (ret
!= RMAP_DENY
) {
10788 route_vty_out_tmp(vty
, &rn
->p
,
10797 bgp_attr_undup(&attr
, adj
->attr
);
10803 json_object_object_add(json
, "advertisedRoutes", json_ar
);
10804 json_object_int_add(json
, "totalPrefixCounter", output_count
);
10805 json_object_int_add(json
, "filteredPrefixCounter",
10808 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
10809 json
, JSON_C_TO_STRING_PRETTY
));
10810 json_object_free(json
);
10811 } else if (output_count
> 0) {
10812 if (filtered_count
> 0)
10814 "\nTotal number of prefixes %ld (%ld filtered)\n",
10815 output_count
, filtered_count
);
10817 vty_out(vty
, "\nTotal number of prefixes %ld\n",
10822 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
10823 safi_t safi
, enum bgp_show_adj_route_type type
,
10824 const char *rmap_name
, bool use_json
)
10826 json_object
*json
= NULL
;
10829 json
= json_object_new_object();
10831 /* labeled-unicast routes live in the unicast table */
10832 if (safi
== SAFI_LABELED_UNICAST
)
10833 safi
= SAFI_UNICAST
;
10835 if (!peer
|| !peer
->afc
[afi
][safi
]) {
10837 json_object_string_add(
10839 "No such neighbor or address family");
10840 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10841 json_object_free(json
);
10843 vty_out(vty
, "%% No such neighbor or address family\n");
10845 return CMD_WARNING
;
10848 if ((type
== bgp_show_adj_route_received
10849 || type
== bgp_show_adj_route_filtered
)
10850 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
10851 PEER_FLAG_SOFT_RECONFIG
)) {
10853 json_object_string_add(
10855 "Inbound soft reconfiguration not enabled");
10856 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10857 json_object_free(json
);
10860 "%% Inbound soft reconfiguration not enabled\n");
10862 return CMD_WARNING
;
10865 show_adj_route(vty
, peer
, afi
, safi
, type
, rmap_name
, use_json
, json
);
10867 return CMD_SUCCESS
;
10870 DEFUN (show_ip_bgp_instance_neighbor_advertised_route
,
10871 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
10872 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
10873 "neighbors <A.B.C.D|X:X::X:X|WORD> <advertised-routes|received-routes|filtered-routes> [route-map WORD] [json]",
10877 BGP_INSTANCE_HELP_STR
10879 BGP_SAFI_WITH_LABEL_HELP_STR
10880 "Detailed information on TCP and BGP neighbor connections\n"
10881 "Neighbor to display information about\n"
10882 "Neighbor to display information about\n"
10883 "Neighbor on BGP configured interface\n"
10884 "Display the routes advertised to a BGP neighbor\n"
10885 "Display the received routes from neighbor\n"
10886 "Display the filtered routes received from neighbor\n"
10887 "Route-map to modify the attributes\n"
10888 "Name of the route map\n"
10891 afi_t afi
= AFI_IP6
;
10892 safi_t safi
= SAFI_UNICAST
;
10893 char *rmap_name
= NULL
;
10894 char *peerstr
= NULL
;
10895 struct bgp
*bgp
= NULL
;
10897 enum bgp_show_adj_route_type type
= bgp_show_adj_route_advertised
;
10899 bool uj
= use_json(argc
, argv
);
10904 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10907 return CMD_WARNING
;
10909 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10910 argv_find(argv
, argc
, "neighbors", &idx
);
10911 peerstr
= argv
[++idx
]->arg
;
10913 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
10915 return CMD_WARNING
;
10917 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
10918 type
= bgp_show_adj_route_advertised
;
10919 else if (argv_find(argv
, argc
, "received-routes", &idx
))
10920 type
= bgp_show_adj_route_received
;
10921 else if (argv_find(argv
, argc
, "filtered-routes", &idx
))
10922 type
= bgp_show_adj_route_filtered
;
10924 if (argv_find(argv
, argc
, "route-map", &idx
))
10925 rmap_name
= argv
[++idx
]->arg
;
10927 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
, uj
);
10930 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
10931 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
10932 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
10938 "Address Family modifier\n"
10939 "Detailed information on TCP and BGP neighbor connections\n"
10940 "Neighbor to display information about\n"
10941 "Neighbor to display information about\n"
10942 "Neighbor on BGP configured interface\n"
10943 "Display information received from a BGP neighbor\n"
10944 "Display the prefixlist filter\n"
10947 afi_t afi
= AFI_IP6
;
10948 safi_t safi
= SAFI_UNICAST
;
10949 char *peerstr
= NULL
;
10952 union sockunion su
;
10958 /* show [ip] bgp */
10959 if (argv_find(argv
, argc
, "ip", &idx
))
10961 /* [<ipv4|ipv6> [unicast]] */
10962 if (argv_find(argv
, argc
, "ipv4", &idx
))
10964 if (argv_find(argv
, argc
, "ipv6", &idx
))
10966 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10967 argv_find(argv
, argc
, "neighbors", &idx
);
10968 peerstr
= argv
[++idx
]->arg
;
10970 bool uj
= use_json(argc
, argv
);
10972 ret
= str2sockunion(peerstr
, &su
);
10974 peer
= peer_lookup_by_conf_if(NULL
, peerstr
);
10977 vty_out(vty
, "{}\n");
10980 "%% Malformed address or name: %s\n",
10982 return CMD_WARNING
;
10985 peer
= peer_lookup(NULL
, &su
);
10988 vty_out(vty
, "{}\n");
10990 vty_out(vty
, "No peer\n");
10991 return CMD_WARNING
;
10995 sprintf(name
, "%s.%d.%d", peer
->host
, afi
, safi
);
10996 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
10999 vty_out(vty
, "Address Family: %s\n",
11000 afi_safi_print(afi
, safi
));
11001 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
11004 vty_out(vty
, "{}\n");
11006 vty_out(vty
, "No functional output\n");
11009 return CMD_SUCCESS
;
11012 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
11013 afi_t afi
, safi_t safi
,
11014 enum bgp_show_type type
, bool use_json
)
11016 /* labeled-unicast routes live in the unicast table */
11017 if (safi
== SAFI_LABELED_UNICAST
)
11018 safi
= SAFI_UNICAST
;
11020 if (!peer
|| !peer
->afc
[afi
][safi
]) {
11022 json_object
*json_no
= NULL
;
11023 json_no
= json_object_new_object();
11024 json_object_string_add(
11025 json_no
, "warning",
11026 "No such neighbor or address family");
11027 vty_out(vty
, "%s\n",
11028 json_object_to_json_string(json_no
));
11029 json_object_free(json_no
);
11031 vty_out(vty
, "%% No such neighbor or address family\n");
11032 return CMD_WARNING
;
11035 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, use_json
);
11038 DEFUN (show_ip_bgp_flowspec_routes_detailed
,
11039 show_ip_bgp_flowspec_routes_detailed_cmd
,
11040 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" flowspec] detail [json]",
11044 BGP_INSTANCE_HELP_STR
11047 "Detailed information on flowspec entries\n"
11050 afi_t afi
= AFI_IP
;
11051 safi_t safi
= SAFI_UNICAST
;
11052 struct bgp
*bgp
= NULL
;
11054 bool uj
= use_json(argc
, argv
);
11059 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11062 return CMD_WARNING
;
11064 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_detail
, NULL
, uj
);
11067 DEFUN (show_ip_bgp_neighbor_routes
,
11068 show_ip_bgp_neighbor_routes_cmd
,
11069 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
11070 "neighbors <A.B.C.D|X:X::X:X|WORD> <flap-statistics|dampened-routes|routes> [json]",
11074 BGP_INSTANCE_HELP_STR
11076 BGP_SAFI_WITH_LABEL_HELP_STR
11077 "Detailed information on TCP and BGP neighbor connections\n"
11078 "Neighbor to display information about\n"
11079 "Neighbor to display information about\n"
11080 "Neighbor on BGP configured interface\n"
11081 "Display flap statistics of the routes learned from neighbor\n"
11082 "Display the dampened routes received from neighbor\n"
11083 "Display routes learned from neighbor\n"
11086 char *peerstr
= NULL
;
11087 struct bgp
*bgp
= NULL
;
11088 afi_t afi
= AFI_IP6
;
11089 safi_t safi
= SAFI_UNICAST
;
11091 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
11093 bool uj
= use_json(argc
, argv
);
11098 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11101 return CMD_WARNING
;
11103 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11104 argv_find(argv
, argc
, "neighbors", &idx
);
11105 peerstr
= argv
[++idx
]->arg
;
11107 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
11109 return CMD_WARNING
;
11111 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
11112 sh_type
= bgp_show_type_flap_neighbor
;
11113 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
11114 sh_type
= bgp_show_type_damp_neighbor
;
11115 else if (argv_find(argv
, argc
, "routes", &idx
))
11116 sh_type
= bgp_show_type_neighbor
;
11118 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
11121 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
11123 struct bgp_distance
{
11124 /* Distance value for the IP source prefix. */
11127 /* Name of the access-list to be matched. */
11131 DEFUN (show_bgp_afi_vpn_rd_route
,
11132 show_bgp_afi_vpn_rd_route_cmd
,
11133 "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]",
11137 "Address Family modifier\n"
11138 "Display information for a route distinguisher\n"
11139 "Route Distinguisher\n"
11140 "Network in the BGP routing table to display\n"
11141 "Network in the BGP routing table to display\n"
11145 struct prefix_rd prd
;
11146 afi_t afi
= AFI_MAX
;
11149 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
11150 vty_out(vty
, "%% Malformed Address Family\n");
11151 return CMD_WARNING
;
11154 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
11156 vty_out(vty
, "%% Malformed Route Distinguisher\n");
11157 return CMD_WARNING
;
11160 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
11161 0, BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
11164 static struct bgp_distance
*bgp_distance_new(void)
11166 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
11169 static void bgp_distance_free(struct bgp_distance
*bdistance
)
11171 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
11174 static int bgp_distance_set(struct vty
*vty
, const char *distance_str
,
11175 const char *ip_str
, const char *access_list_str
)
11182 struct bgp_node
*rn
;
11183 struct bgp_distance
*bdistance
;
11185 afi
= bgp_node_afi(vty
);
11186 safi
= bgp_node_safi(vty
);
11188 ret
= str2prefix(ip_str
, &p
);
11190 vty_out(vty
, "Malformed prefix\n");
11191 return CMD_WARNING_CONFIG_FAILED
;
11194 distance
= atoi(distance_str
);
11196 /* Get BGP distance node. */
11197 rn
= bgp_node_get(bgp_distance_table
[afi
][safi
], (struct prefix
*)&p
);
11198 bdistance
= bgp_node_get_bgp_distance_info(rn
);
11200 bgp_unlock_node(rn
);
11202 bdistance
= bgp_distance_new();
11203 bgp_node_set_bgp_distance_info(rn
, bdistance
);
11206 /* Set distance value. */
11207 bdistance
->distance
= distance
;
11209 /* Reset access-list configuration. */
11210 if (bdistance
->access_list
) {
11211 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
11212 bdistance
->access_list
= NULL
;
11214 if (access_list_str
)
11215 bdistance
->access_list
=
11216 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
11218 return CMD_SUCCESS
;
11221 static int bgp_distance_unset(struct vty
*vty
, const char *distance_str
,
11222 const char *ip_str
, const char *access_list_str
)
11229 struct bgp_node
*rn
;
11230 struct bgp_distance
*bdistance
;
11232 afi
= bgp_node_afi(vty
);
11233 safi
= bgp_node_safi(vty
);
11235 ret
= str2prefix(ip_str
, &p
);
11237 vty_out(vty
, "Malformed prefix\n");
11238 return CMD_WARNING_CONFIG_FAILED
;
11241 rn
= bgp_node_lookup(bgp_distance_table
[afi
][safi
],
11242 (struct prefix
*)&p
);
11244 vty_out(vty
, "Can't find specified prefix\n");
11245 return CMD_WARNING_CONFIG_FAILED
;
11248 bdistance
= bgp_node_get_bgp_distance_info(rn
);
11249 distance
= atoi(distance_str
);
11251 if (bdistance
->distance
!= distance
) {
11252 vty_out(vty
, "Distance does not match configured\n");
11253 return CMD_WARNING_CONFIG_FAILED
;
11256 if (bdistance
->access_list
)
11257 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
11258 bgp_distance_free(bdistance
);
11260 bgp_node_set_bgp_path_info(rn
, NULL
);
11261 bgp_unlock_node(rn
);
11262 bgp_unlock_node(rn
);
11264 return CMD_SUCCESS
;
11267 /* Apply BGP information to distance method. */
11268 uint8_t bgp_distance_apply(struct prefix
*p
, struct bgp_path_info
*pinfo
,
11269 afi_t afi
, safi_t safi
, struct bgp
*bgp
)
11271 struct bgp_node
*rn
;
11274 struct bgp_distance
*bdistance
;
11275 struct access_list
*alist
;
11276 struct bgp_static
*bgp_static
;
11281 peer
= pinfo
->peer
;
11283 /* Check source address. */
11284 sockunion2hostprefix(&peer
->su
, &q
);
11285 rn
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
11287 bdistance
= bgp_node_get_bgp_distance_info(rn
);
11288 bgp_unlock_node(rn
);
11290 if (bdistance
->access_list
) {
11291 alist
= access_list_lookup(afi
, bdistance
->access_list
);
11293 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
11294 return bdistance
->distance
;
11296 return bdistance
->distance
;
11299 /* Backdoor check. */
11300 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
11302 bgp_static
= bgp_node_get_bgp_static_info(rn
);
11303 bgp_unlock_node(rn
);
11305 if (bgp_static
->backdoor
) {
11306 if (bgp
->distance_local
[afi
][safi
])
11307 return bgp
->distance_local
[afi
][safi
];
11309 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
11313 if (peer
->sort
== BGP_PEER_EBGP
) {
11314 if (bgp
->distance_ebgp
[afi
][safi
])
11315 return bgp
->distance_ebgp
[afi
][safi
];
11316 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
11318 if (bgp
->distance_ibgp
[afi
][safi
])
11319 return bgp
->distance_ibgp
[afi
][safi
];
11320 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
11324 DEFUN (bgp_distance
,
11326 "distance bgp (1-255) (1-255) (1-255)",
11327 "Define an administrative distance\n"
11329 "Distance for routes external to the AS\n"
11330 "Distance for routes internal to the AS\n"
11331 "Distance for local routes\n")
11333 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11334 int idx_number
= 2;
11335 int idx_number_2
= 3;
11336 int idx_number_3
= 4;
11340 afi
= bgp_node_afi(vty
);
11341 safi
= bgp_node_safi(vty
);
11343 bgp
->distance_ebgp
[afi
][safi
] = atoi(argv
[idx_number
]->arg
);
11344 bgp
->distance_ibgp
[afi
][safi
] = atoi(argv
[idx_number_2
]->arg
);
11345 bgp
->distance_local
[afi
][safi
] = atoi(argv
[idx_number_3
]->arg
);
11346 return CMD_SUCCESS
;
11349 DEFUN (no_bgp_distance
,
11350 no_bgp_distance_cmd
,
11351 "no distance bgp [(1-255) (1-255) (1-255)]",
11353 "Define an administrative distance\n"
11355 "Distance for routes external to the AS\n"
11356 "Distance for routes internal to the AS\n"
11357 "Distance for local routes\n")
11359 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11363 afi
= bgp_node_afi(vty
);
11364 safi
= bgp_node_safi(vty
);
11366 bgp
->distance_ebgp
[afi
][safi
] = 0;
11367 bgp
->distance_ibgp
[afi
][safi
] = 0;
11368 bgp
->distance_local
[afi
][safi
] = 0;
11369 return CMD_SUCCESS
;
11373 DEFUN (bgp_distance_source
,
11374 bgp_distance_source_cmd
,
11375 "distance (1-255) A.B.C.D/M",
11376 "Define an administrative distance\n"
11377 "Administrative distance\n"
11378 "IP source prefix\n")
11380 int idx_number
= 1;
11381 int idx_ipv4_prefixlen
= 2;
11382 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
11383 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
11384 return CMD_SUCCESS
;
11387 DEFUN (no_bgp_distance_source
,
11388 no_bgp_distance_source_cmd
,
11389 "no distance (1-255) A.B.C.D/M",
11391 "Define an administrative distance\n"
11392 "Administrative distance\n"
11393 "IP source prefix\n")
11395 int idx_number
= 2;
11396 int idx_ipv4_prefixlen
= 3;
11397 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
11398 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
11399 return CMD_SUCCESS
;
11402 DEFUN (bgp_distance_source_access_list
,
11403 bgp_distance_source_access_list_cmd
,
11404 "distance (1-255) A.B.C.D/M WORD",
11405 "Define an administrative distance\n"
11406 "Administrative distance\n"
11407 "IP source prefix\n"
11408 "Access list name\n")
11410 int idx_number
= 1;
11411 int idx_ipv4_prefixlen
= 2;
11413 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
11414 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
11415 return CMD_SUCCESS
;
11418 DEFUN (no_bgp_distance_source_access_list
,
11419 no_bgp_distance_source_access_list_cmd
,
11420 "no distance (1-255) A.B.C.D/M WORD",
11422 "Define an administrative distance\n"
11423 "Administrative distance\n"
11424 "IP source prefix\n"
11425 "Access list name\n")
11427 int idx_number
= 2;
11428 int idx_ipv4_prefixlen
= 3;
11430 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
11431 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
11432 return CMD_SUCCESS
;
11435 DEFUN (ipv6_bgp_distance_source
,
11436 ipv6_bgp_distance_source_cmd
,
11437 "distance (1-255) X:X::X:X/M",
11438 "Define an administrative distance\n"
11439 "Administrative distance\n"
11440 "IP source prefix\n")
11442 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, NULL
);
11443 return CMD_SUCCESS
;
11446 DEFUN (no_ipv6_bgp_distance_source
,
11447 no_ipv6_bgp_distance_source_cmd
,
11448 "no distance (1-255) X:X::X:X/M",
11450 "Define an administrative distance\n"
11451 "Administrative distance\n"
11452 "IP source prefix\n")
11454 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, NULL
);
11455 return CMD_SUCCESS
;
11458 DEFUN (ipv6_bgp_distance_source_access_list
,
11459 ipv6_bgp_distance_source_access_list_cmd
,
11460 "distance (1-255) X:X::X:X/M WORD",
11461 "Define an administrative distance\n"
11462 "Administrative distance\n"
11463 "IP source prefix\n"
11464 "Access list name\n")
11466 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, argv
[3]->arg
);
11467 return CMD_SUCCESS
;
11470 DEFUN (no_ipv6_bgp_distance_source_access_list
,
11471 no_ipv6_bgp_distance_source_access_list_cmd
,
11472 "no distance (1-255) X:X::X:X/M WORD",
11474 "Define an administrative distance\n"
11475 "Administrative distance\n"
11476 "IP source prefix\n"
11477 "Access list name\n")
11479 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, argv
[4]->arg
);
11480 return CMD_SUCCESS
;
11483 DEFUN (bgp_damp_set
,
11485 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
11486 "BGP Specific commands\n"
11487 "Enable route-flap dampening\n"
11488 "Half-life time for the penalty\n"
11489 "Value to start reusing a route\n"
11490 "Value to start suppressing a route\n"
11491 "Maximum duration to suppress a stable route\n")
11493 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11494 int idx_half_life
= 2;
11496 int idx_suppress
= 4;
11497 int idx_max_suppress
= 5;
11498 int half
= DEFAULT_HALF_LIFE
* 60;
11499 int reuse
= DEFAULT_REUSE
;
11500 int suppress
= DEFAULT_SUPPRESS
;
11501 int max
= 4 * half
;
11504 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
11505 reuse
= atoi(argv
[idx_reuse
]->arg
);
11506 suppress
= atoi(argv
[idx_suppress
]->arg
);
11507 max
= atoi(argv
[idx_max_suppress
]->arg
) * 60;
11508 } else if (argc
== 3) {
11509 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
11513 if (suppress
< reuse
) {
11515 "Suppress value cannot be less than reuse value \n");
11519 return bgp_damp_enable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
), half
,
11520 reuse
, suppress
, max
);
11523 DEFUN (bgp_damp_unset
,
11524 bgp_damp_unset_cmd
,
11525 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
11527 "BGP Specific commands\n"
11528 "Enable route-flap dampening\n"
11529 "Half-life time for the penalty\n"
11530 "Value to start reusing a route\n"
11531 "Value to start suppressing a route\n"
11532 "Maximum duration to suppress a stable route\n")
11534 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11535 return bgp_damp_disable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
));
11538 /* Display specified route of BGP table. */
11539 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
11540 const char *ip_str
, afi_t afi
, safi_t safi
,
11541 struct prefix_rd
*prd
, int prefix_check
)
11544 struct prefix match
;
11545 struct bgp_node
*rn
;
11546 struct bgp_node
*rm
;
11547 struct bgp_path_info
*pi
;
11548 struct bgp_path_info
*pi_temp
;
11550 struct bgp_table
*table
;
11552 /* BGP structure lookup. */
11554 bgp
= bgp_lookup_by_name(view_name
);
11556 vty_out(vty
, "%% Can't find BGP instance %s\n",
11558 return CMD_WARNING
;
11561 bgp
= bgp_get_default();
11563 vty_out(vty
, "%% No BGP process is configured\n");
11564 return CMD_WARNING
;
11568 /* Check IP address argument. */
11569 ret
= str2prefix(ip_str
, &match
);
11571 vty_out(vty
, "%% address is malformed\n");
11572 return CMD_WARNING
;
11575 match
.family
= afi2family(afi
);
11577 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
11578 || (safi
== SAFI_EVPN
)) {
11579 for (rn
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); rn
;
11580 rn
= bgp_route_next(rn
)) {
11581 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
11583 table
= bgp_node_get_bgp_table_info(rn
);
11586 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
11590 || rm
->p
.prefixlen
== match
.prefixlen
) {
11591 pi
= bgp_node_get_bgp_path_info(rm
);
11593 if (pi
->extra
&& pi
->extra
->damp_info
) {
11594 pi_temp
= pi
->next
;
11595 bgp_damp_info_free(
11596 pi
->extra
->damp_info
,
11604 bgp_unlock_node(rm
);
11607 if ((rn
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
))
11610 || rn
->p
.prefixlen
== match
.prefixlen
) {
11611 pi
= bgp_node_get_bgp_path_info(rn
);
11613 if (pi
->extra
&& pi
->extra
->damp_info
) {
11614 pi_temp
= pi
->next
;
11615 bgp_damp_info_free(
11616 pi
->extra
->damp_info
,
11624 bgp_unlock_node(rn
);
11628 return CMD_SUCCESS
;
11631 DEFUN (clear_ip_bgp_dampening
,
11632 clear_ip_bgp_dampening_cmd
,
11633 "clear ip bgp dampening",
11637 "Clear route flap dampening information\n")
11639 bgp_damp_info_clean();
11640 return CMD_SUCCESS
;
11643 DEFUN (clear_ip_bgp_dampening_prefix
,
11644 clear_ip_bgp_dampening_prefix_cmd
,
11645 "clear ip bgp dampening A.B.C.D/M",
11649 "Clear route flap dampening information\n"
11652 int idx_ipv4_prefixlen
= 4;
11653 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
11654 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
11657 DEFUN (clear_ip_bgp_dampening_address
,
11658 clear_ip_bgp_dampening_address_cmd
,
11659 "clear ip bgp dampening A.B.C.D",
11663 "Clear route flap dampening information\n"
11664 "Network to clear damping information\n")
11667 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
11668 SAFI_UNICAST
, NULL
, 0);
11671 DEFUN (clear_ip_bgp_dampening_address_mask
,
11672 clear_ip_bgp_dampening_address_mask_cmd
,
11673 "clear ip bgp dampening A.B.C.D A.B.C.D",
11677 "Clear route flap dampening information\n"
11678 "Network to clear damping information\n"
11682 int idx_ipv4_2
= 5;
11684 char prefix_str
[BUFSIZ
];
11686 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
11689 vty_out(vty
, "%% Inconsistent address and mask\n");
11690 return CMD_WARNING
;
11693 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
11697 static void show_bgp_peerhash_entry(struct hash_backet
*backet
, void *arg
)
11699 struct vty
*vty
= arg
;
11700 struct peer
*peer
= backet
->data
;
11701 char buf
[SU_ADDRSTRLEN
];
11703 vty_out(vty
, "\tPeer: %s %s\n", peer
->host
,
11704 sockunion2str(&peer
->su
, buf
, sizeof(buf
)));
11707 DEFUN (show_bgp_peerhash
,
11708 show_bgp_peerhash_cmd
,
11709 "show bgp peerhash",
11712 "Display information about the BGP peerhash\n")
11714 struct list
*instances
= bm
->bgp
;
11715 struct listnode
*node
;
11718 for (ALL_LIST_ELEMENTS_RO(instances
, node
, bgp
)) {
11719 vty_out(vty
, "BGP: %s\n", bgp
->name
);
11720 hash_iterate(bgp
->peerhash
, show_bgp_peerhash_entry
,
11724 return CMD_SUCCESS
;
11727 /* also used for encap safi */
11728 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
11729 afi_t afi
, safi_t safi
)
11731 struct bgp_node
*prn
;
11732 struct bgp_node
*rn
;
11733 struct bgp_table
*table
;
11735 struct prefix_rd
*prd
;
11736 struct bgp_static
*bgp_static
;
11737 mpls_label_t label
;
11738 char buf
[SU_ADDRSTRLEN
];
11739 char rdbuf
[RD_ADDRSTRLEN
];
11741 /* Network configuration. */
11742 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
11743 prn
= bgp_route_next(prn
)) {
11744 table
= bgp_node_get_bgp_table_info(prn
);
11748 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
11749 bgp_static
= bgp_node_get_bgp_static_info(rn
);
11750 if (bgp_static
== NULL
)
11754 prd
= (struct prefix_rd
*)&prn
->p
;
11756 /* "network" configuration display. */
11757 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
11758 label
= decode_label(&bgp_static
->label
);
11760 vty_out(vty
, " network %s/%d rd %s",
11761 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11763 p
->prefixlen
, rdbuf
);
11764 if (safi
== SAFI_MPLS_VPN
)
11765 vty_out(vty
, " label %u", label
);
11767 if (bgp_static
->rmap
.name
)
11768 vty_out(vty
, " route-map %s",
11769 bgp_static
->rmap
.name
);
11771 if (bgp_static
->backdoor
)
11772 vty_out(vty
, " backdoor");
11774 vty_out(vty
, "\n");
11779 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
11780 afi_t afi
, safi_t safi
)
11782 struct bgp_node
*prn
;
11783 struct bgp_node
*rn
;
11784 struct bgp_table
*table
;
11786 struct prefix_rd
*prd
;
11787 struct bgp_static
*bgp_static
;
11788 char buf
[PREFIX_STRLEN
* 2];
11789 char buf2
[SU_ADDRSTRLEN
];
11790 char rdbuf
[RD_ADDRSTRLEN
];
11792 /* Network configuration. */
11793 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
11794 prn
= bgp_route_next(prn
)) {
11795 table
= bgp_node_get_bgp_table_info(prn
);
11799 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
11800 bgp_static
= bgp_node_get_bgp_static_info(rn
);
11801 if (bgp_static
== NULL
)
11804 char *macrouter
= NULL
;
11807 if (bgp_static
->router_mac
)
11808 macrouter
= prefix_mac2str(
11809 bgp_static
->router_mac
, NULL
, 0);
11810 if (bgp_static
->eth_s_id
)
11811 esi
= esi2str(bgp_static
->eth_s_id
);
11813 prd
= (struct prefix_rd
*)&prn
->p
;
11815 /* "network" configuration display. */
11816 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
11817 if (p
->u
.prefix_evpn
.route_type
== 5) {
11818 char local_buf
[PREFIX_STRLEN
];
11819 uint8_t family
= is_evpn_prefix_ipaddr_v4((
11820 struct prefix_evpn
*)p
)
11824 &p
->u
.prefix_evpn
.prefix_addr
.ip
.ip
.addr
,
11825 local_buf
, PREFIX_STRLEN
);
11826 sprintf(buf
, "%s/%u", local_buf
,
11827 p
->u
.prefix_evpn
.prefix_addr
.ip_prefix_length
);
11829 prefix2str(p
, buf
, sizeof(buf
));
11832 if (bgp_static
->gatewayIp
.family
== AF_INET
11833 || bgp_static
->gatewayIp
.family
== AF_INET6
)
11834 inet_ntop(bgp_static
->gatewayIp
.family
,
11835 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
11838 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
11840 p
->u
.prefix_evpn
.prefix_addr
.eth_tag
,
11841 decode_label(&bgp_static
->label
), esi
, buf2
,
11845 XFREE(MTYPE_TMP
, macrouter
);
11847 XFREE(MTYPE_TMP
, esi
);
11852 /* Configuration of static route announcement and aggregate
11854 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11857 struct bgp_node
*rn
;
11859 struct bgp_static
*bgp_static
;
11860 struct bgp_aggregate
*bgp_aggregate
;
11861 char buf
[SU_ADDRSTRLEN
];
11863 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
11864 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
11868 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
11869 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
11873 /* Network configuration. */
11874 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
11875 rn
= bgp_route_next(rn
)) {
11876 bgp_static
= bgp_node_get_bgp_static_info(rn
);
11877 if (bgp_static
== NULL
)
11882 /* "network" configuration display. */
11883 if (bgp_option_check(BGP_OPT_CONFIG_CISCO
) && afi
== AFI_IP
) {
11884 uint32_t destination
;
11885 struct in_addr netmask
;
11887 destination
= ntohl(p
->u
.prefix4
.s_addr
);
11888 masklen2ip(p
->prefixlen
, &netmask
);
11889 vty_out(vty
, " network %s",
11890 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11893 if ((IN_CLASSC(destination
) && p
->prefixlen
== 24)
11894 || (IN_CLASSB(destination
) && p
->prefixlen
== 16)
11895 || (IN_CLASSA(destination
) && p
->prefixlen
== 8)
11896 || p
->u
.prefix4
.s_addr
== 0) {
11897 /* Natural mask is not display. */
11899 vty_out(vty
, " mask %s", inet_ntoa(netmask
));
11901 vty_out(vty
, " network %s/%d",
11902 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11907 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
11908 vty_out(vty
, " label-index %u",
11909 bgp_static
->label_index
);
11911 if (bgp_static
->rmap
.name
)
11912 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
11914 if (bgp_static
->backdoor
)
11915 vty_out(vty
, " backdoor");
11917 vty_out(vty
, "\n");
11920 /* Aggregate-address configuration. */
11921 for (rn
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); rn
;
11922 rn
= bgp_route_next(rn
)) {
11923 bgp_aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
11924 if (bgp_aggregate
== NULL
)
11929 if (bgp_option_check(BGP_OPT_CONFIG_CISCO
) && afi
== AFI_IP
) {
11930 struct in_addr netmask
;
11932 masklen2ip(p
->prefixlen
, &netmask
);
11933 vty_out(vty
, " aggregate-address %s %s",
11934 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11936 inet_ntoa(netmask
));
11938 vty_out(vty
, " aggregate-address %s/%d",
11939 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11944 if (bgp_aggregate
->as_set
)
11945 vty_out(vty
, " as-set");
11947 if (bgp_aggregate
->summary_only
)
11948 vty_out(vty
, " summary-only");
11950 vty_out(vty
, "\n");
11954 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11957 struct bgp_node
*rn
;
11958 struct bgp_distance
*bdistance
;
11960 /* Distance configuration. */
11961 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
11962 && bgp
->distance_local
[afi
][safi
]
11963 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
11964 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
11965 || bgp
->distance_local
[afi
][safi
]
11966 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
11967 vty_out(vty
, " distance bgp %d %d %d\n",
11968 bgp
->distance_ebgp
[afi
][safi
],
11969 bgp
->distance_ibgp
[afi
][safi
],
11970 bgp
->distance_local
[afi
][safi
]);
11973 for (rn
= bgp_table_top(bgp_distance_table
[afi
][safi
]); rn
;
11974 rn
= bgp_route_next(rn
)) {
11975 bdistance
= bgp_node_get_bgp_distance_info(rn
);
11976 if (bdistance
!= NULL
) {
11977 char buf
[PREFIX_STRLEN
];
11979 vty_out(vty
, " distance %d %s %s\n",
11980 bdistance
->distance
,
11981 prefix2str(&rn
->p
, buf
, sizeof(buf
)),
11982 bdistance
->access_list
? bdistance
->access_list
11988 /* Allocate routing table structure and install commands. */
11989 void bgp_route_init(void)
11994 /* Init BGP distance table. */
11995 FOREACH_AFI_SAFI (afi
, safi
)
11996 bgp_distance_table
[afi
][safi
] = bgp_table_init(NULL
, afi
, safi
);
11998 /* IPv4 BGP commands. */
11999 install_element(BGP_NODE
, &bgp_table_map_cmd
);
12000 install_element(BGP_NODE
, &bgp_network_cmd
);
12001 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
12003 install_element(BGP_NODE
, &aggregate_address_cmd
);
12004 install_element(BGP_NODE
, &aggregate_address_mask_cmd
);
12005 install_element(BGP_NODE
, &no_aggregate_address_cmd
);
12006 install_element(BGP_NODE
, &no_aggregate_address_mask_cmd
);
12008 /* IPv4 unicast configuration. */
12009 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
12010 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
12011 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
12013 install_element(BGP_IPV4_NODE
, &aggregate_address_cmd
);
12014 install_element(BGP_IPV4_NODE
, &aggregate_address_mask_cmd
);
12015 install_element(BGP_IPV4_NODE
, &no_aggregate_address_cmd
);
12016 install_element(BGP_IPV4_NODE
, &no_aggregate_address_mask_cmd
);
12018 /* IPv4 multicast configuration. */
12019 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
12020 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
12021 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
12022 install_element(BGP_IPV4M_NODE
, &aggregate_address_cmd
);
12023 install_element(BGP_IPV4M_NODE
, &aggregate_address_mask_cmd
);
12024 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_cmd
);
12025 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_mask_cmd
);
12027 /* IPv4 labeled-unicast configuration. */
12028 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
12029 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
12030 install_element(VIEW_NODE
, &show_ip_bgp_json_cmd
);
12031 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
12032 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
12034 install_element(VIEW_NODE
,
12035 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
12036 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
12037 install_element(VIEW_NODE
,
12038 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
12039 #ifdef KEEP_OLD_VPN_COMMANDS
12040 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
12041 #endif /* KEEP_OLD_VPN_COMMANDS */
12042 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
12043 install_element(VIEW_NODE
,
12044 &show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd
);
12046 /* BGP dampening clear commands */
12047 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
12048 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
12050 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
12051 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
12054 install_element(ENABLE_NODE
,
12055 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
12056 #ifdef KEEP_OLD_VPN_COMMANDS
12057 install_element(ENABLE_NODE
,
12058 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
12059 #endif /* KEEP_OLD_VPN_COMMANDS */
12061 /* New config IPv6 BGP commands. */
12062 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
12063 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
12064 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
12066 install_element(BGP_IPV6_NODE
, &ipv6_aggregate_address_cmd
);
12067 install_element(BGP_IPV6_NODE
, &no_ipv6_aggregate_address_cmd
);
12069 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
12071 install_element(BGP_NODE
, &bgp_distance_cmd
);
12072 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
12073 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
12074 install_element(BGP_NODE
, &no_bgp_distance_source_cmd
);
12075 install_element(BGP_NODE
, &bgp_distance_source_access_list_cmd
);
12076 install_element(BGP_NODE
, &no_bgp_distance_source_access_list_cmd
);
12077 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
12078 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
12079 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
12080 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_cmd
);
12081 install_element(BGP_IPV4_NODE
, &bgp_distance_source_access_list_cmd
);
12082 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_access_list_cmd
);
12083 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
12084 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
12085 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
12086 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_source_cmd
);
12087 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_access_list_cmd
);
12088 install_element(BGP_IPV4M_NODE
,
12089 &no_bgp_distance_source_access_list_cmd
);
12090 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
12091 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
12092 install_element(BGP_IPV6_NODE
, &ipv6_bgp_distance_source_cmd
);
12093 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_distance_source_cmd
);
12094 install_element(BGP_IPV6_NODE
,
12095 &ipv6_bgp_distance_source_access_list_cmd
);
12096 install_element(BGP_IPV6_NODE
,
12097 &no_ipv6_bgp_distance_source_access_list_cmd
);
12098 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
12099 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
12100 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_distance_source_cmd
);
12101 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_distance_source_cmd
);
12102 install_element(BGP_IPV6M_NODE
,
12103 &ipv6_bgp_distance_source_access_list_cmd
);
12104 install_element(BGP_IPV6M_NODE
,
12105 &no_ipv6_bgp_distance_source_access_list_cmd
);
12107 install_element(BGP_NODE
, &bgp_damp_set_cmd
);
12108 install_element(BGP_NODE
, &bgp_damp_unset_cmd
);
12109 install_element(BGP_IPV4_NODE
, &bgp_damp_set_cmd
);
12110 install_element(BGP_IPV4_NODE
, &bgp_damp_unset_cmd
);
12112 /* IPv4 Multicast Mode */
12113 install_element(BGP_IPV4M_NODE
, &bgp_damp_set_cmd
);
12114 install_element(BGP_IPV4M_NODE
, &bgp_damp_unset_cmd
);
12116 /* Large Communities */
12117 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
12118 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
12120 /* show bgp ipv4 flowspec detailed */
12121 install_element(VIEW_NODE
, &show_ip_bgp_flowspec_routes_detailed_cmd
);
12123 install_element(VIEW_NODE
, &show_bgp_peerhash_cmd
);
12126 void bgp_route_finish(void)
12131 FOREACH_AFI_SAFI (afi
, safi
) {
12132 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
12133 bgp_distance_table
[afi
][safi
] = NULL
;