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 /* Route map apply. */
1229 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
1230 /* Duplicate current value to new strucutre for modification. */
1231 rmap_path
.peer
= peer
;
1232 rmap_path
.attr
= attr
;
1234 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_IN
);
1236 /* Apply BGP route map to the attribute. */
1237 ret
= route_map_apply(rmap
, p
, RMAP_BGP
, &rmap_path
);
1239 peer
->rmap_type
= 0;
1241 if (ret
== RMAP_DENYMATCH
)
1247 static int bgp_output_modifier(struct peer
*peer
, struct prefix
*p
,
1248 struct attr
*attr
, afi_t afi
, safi_t safi
,
1249 const char *rmap_name
)
1251 struct bgp_path_info rmap_path
;
1252 route_map_result_t ret
;
1253 struct route_map
*rmap
= NULL
;
1257 * So if we get to this point and have no rmap_name
1258 * we want to just show the output as it currently
1264 /* Apply default weight value. */
1265 if (peer
->weight
[afi
][safi
])
1266 attr
->weight
= peer
->weight
[afi
][safi
];
1268 rmap
= route_map_lookup_by_name(rmap_name
);
1271 * If we have a route map name and we do not find
1272 * the routemap that means we have an implicit
1278 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
1279 /* Route map apply. */
1280 /* Duplicate current value to new strucutre for modification. */
1281 rmap_path
.peer
= peer
;
1282 rmap_path
.attr
= attr
;
1284 rmap_type
= peer
->rmap_type
;
1285 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1287 /* Apply BGP route map to the attribute. */
1288 ret
= route_map_apply(rmap
, p
, RMAP_BGP
, &rmap_path
);
1290 peer
->rmap_type
= rmap_type
;
1292 if (ret
== RMAP_DENYMATCH
)
1294 * caller has multiple error paths with bgp_attr_flush()
1301 /* If this is an EBGP peer with remove-private-AS */
1302 static void bgp_peer_remove_private_as(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1303 struct peer
*peer
, struct attr
*attr
)
1305 if (peer
->sort
== BGP_PEER_EBGP
1306 && (peer_af_flag_check(peer
, afi
, safi
,
1307 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1308 || peer_af_flag_check(peer
, afi
, safi
,
1309 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
)
1310 || peer_af_flag_check(peer
, afi
, safi
,
1311 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)
1312 || peer_af_flag_check(peer
, afi
, safi
,
1313 PEER_FLAG_REMOVE_PRIVATE_AS
))) {
1314 // Take action on the entire aspath
1315 if (peer_af_flag_check(peer
, afi
, safi
,
1316 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1317 || peer_af_flag_check(peer
, afi
, safi
,
1318 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)) {
1319 if (peer_af_flag_check(
1321 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
))
1322 attr
->aspath
= aspath_replace_private_asns(
1323 attr
->aspath
, bgp
->as
);
1325 // The entire aspath consists of private ASNs so create
1327 else if (aspath_private_as_check(attr
->aspath
))
1328 attr
->aspath
= aspath_empty_get();
1330 // There are some public and some private ASNs, remove
1333 attr
->aspath
= aspath_remove_private_asns(
1337 // 'all' was not specified so the entire aspath must be private
1339 // for us to do anything
1340 else if (aspath_private_as_check(attr
->aspath
)) {
1341 if (peer_af_flag_check(
1343 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
))
1344 attr
->aspath
= aspath_replace_private_asns(
1345 attr
->aspath
, bgp
->as
);
1347 attr
->aspath
= aspath_empty_get();
1352 /* If this is an EBGP peer with as-override */
1353 static void bgp_peer_as_override(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1354 struct peer
*peer
, struct attr
*attr
)
1356 if (peer
->sort
== BGP_PEER_EBGP
1357 && peer_af_flag_check(peer
, afi
, safi
, PEER_FLAG_AS_OVERRIDE
)) {
1358 if (aspath_single_asn_check(attr
->aspath
, peer
->as
))
1359 attr
->aspath
= aspath_replace_specific_asn(
1360 attr
->aspath
, peer
->as
, bgp
->as
);
1364 void bgp_attr_add_gshut_community(struct attr
*attr
)
1366 struct community
*old
;
1367 struct community
*new;
1368 struct community
*merge
;
1369 struct community
*gshut
;
1371 old
= attr
->community
;
1372 gshut
= community_str2com("graceful-shutdown");
1377 merge
= community_merge(community_dup(old
), gshut
);
1379 if (old
->refcnt
== 0)
1380 community_free(&old
);
1382 new = community_uniq_sort(merge
);
1383 community_free(&merge
);
1385 new = community_dup(gshut
);
1388 community_free(&gshut
);
1389 attr
->community
= new;
1390 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
1392 /* When we add the graceful-shutdown community we must also
1393 * lower the local-preference */
1394 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1395 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1399 static void subgroup_announce_reset_nhop(uint8_t family
, struct attr
*attr
)
1401 if (family
== AF_INET
) {
1402 attr
->nexthop
.s_addr
= 0;
1403 attr
->mp_nexthop_global_in
.s_addr
= 0;
1405 if (family
== AF_INET6
)
1406 memset(&attr
->mp_nexthop_global
, 0, IPV6_MAX_BYTELEN
);
1407 if (family
== AF_EVPN
)
1408 memset(&attr
->mp_nexthop_global_in
, 0, BGP_ATTR_NHLEN_IPV4
);
1411 int subgroup_announce_check(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
1412 struct update_subgroup
*subgrp
, struct prefix
*p
,
1415 struct bgp_filter
*filter
;
1418 struct peer
*onlypeer
;
1420 struct attr
*piattr
;
1421 char buf
[PREFIX_STRLEN
];
1427 int samepeer_safe
= 0; /* for synthetic mplsvpns routes */
1429 if (DISABLE_BGP_ANNOUNCE
)
1432 afi
= SUBGRP_AFI(subgrp
);
1433 safi
= SUBGRP_SAFI(subgrp
);
1434 peer
= SUBGRP_PEER(subgrp
);
1436 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_LONESOUL
))
1437 onlypeer
= SUBGRP_PFIRST(subgrp
)->peer
;
1440 filter
= &peer
->filter
[afi
][safi
];
1441 bgp
= SUBGRP_INST(subgrp
);
1442 piattr
= bgp_path_info_mpath_count(pi
) ? bgp_path_info_mpath_attr(pi
)
1446 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
)) && (safi
== SAFI_MPLS_VPN
)
1447 && ((pi
->type
== ZEBRA_ROUTE_BGP_DIRECT
)
1448 || (pi
->type
== ZEBRA_ROUTE_BGP_DIRECT_EXT
))) {
1451 * direct and direct_ext type routes originate internally even
1452 * though they can have peer pointers that reference other
1455 prefix2str(p
, buf
, PREFIX_STRLEN
);
1456 zlog_debug("%s: pfx %s bgp_direct->vpn route peer safe",
1462 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
))
1463 && ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_UNICAST
))
1464 && (pi
->type
== ZEBRA_ROUTE_BGP
)
1465 && (pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
1467 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1472 /* With addpath we may be asked to TX all kinds of paths so make sure
1474 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
)
1475 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)
1476 || CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
1480 /* If this is not the bestpath then check to see if there is an enabled
1482 * feature that requires us to advertise it */
1483 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
1484 if (!bgp_addpath_tx_path(peer
->addpath_type
[afi
][safi
], pi
)) {
1489 /* Aggregate-address suppress check. */
1490 if (pi
->extra
&& pi
->extra
->suppress
)
1491 if (!UNSUPPRESS_MAP_NAME(filter
)) {
1496 * If we are doing VRF 2 VRF leaking via the import
1497 * statement, we want to prevent the route going
1498 * off box as that the RT and RD created are localy
1499 * significant and globaly useless.
1501 if (safi
== SAFI_MPLS_VPN
&& pi
->extra
&& pi
->extra
->num_labels
1502 && pi
->extra
->label
[0] == BGP_PREVENT_VRF_2_VRF_LEAK
)
1505 /* If it's labeled safi, make sure the route has a valid label. */
1506 if (safi
== SAFI_LABELED_UNICAST
) {
1507 mpls_label_t label
= bgp_adv_label(rn
, pi
, peer
, afi
, safi
);
1508 if (!bgp_is_valid_label(&label
)) {
1509 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1510 zlog_debug("u%" PRIu64
":s%" PRIu64
1511 " %s/%d is filtered - no label (%p)",
1512 subgrp
->update_group
->id
, subgrp
->id
,
1513 inet_ntop(p
->family
, &p
->u
.prefix
,
1514 buf
, SU_ADDRSTRLEN
),
1515 p
->prefixlen
, &label
);
1520 /* Do not send back route to sender. */
1521 if (onlypeer
&& from
== onlypeer
) {
1525 /* Do not send the default route in the BGP table if the neighbor is
1526 * configured for default-originate */
1527 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1528 PEER_FLAG_DEFAULT_ORIGINATE
)) {
1529 if (p
->family
== AF_INET
&& p
->u
.prefix4
.s_addr
== INADDR_ANY
)
1531 else if (p
->family
== AF_INET6
&& p
->prefixlen
== 0)
1535 /* Transparency check. */
1536 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
)
1537 && CHECK_FLAG(from
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
))
1542 /* If community is not disabled check the no-export and local. */
1543 if (!transparent
&& bgp_community_filter(peer
, piattr
)) {
1544 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1546 "subgrpannouncecheck: community filter check fail");
1550 /* If the attribute has originator-id and it is same as remote
1552 if (onlypeer
&& piattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
1553 && (IPV4_ADDR_SAME(&onlypeer
->remote_id
, &piattr
->originator_id
))) {
1554 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1556 "%s [Update:SEND] %s originator-id is same as "
1559 prefix2str(p
, buf
, sizeof(buf
)));
1563 /* ORF prefix-list filter check */
1564 if (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_RM_ADV
)
1565 && (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_SM_RCV
)
1566 || CHECK_FLAG(peer
->af_cap
[afi
][safi
],
1567 PEER_CAP_ORF_PREFIX_SM_OLD_RCV
)))
1568 if (peer
->orf_plist
[afi
][safi
]) {
1569 if (prefix_list_apply(peer
->orf_plist
[afi
][safi
], p
)
1571 if (bgp_debug_update(NULL
, p
,
1572 subgrp
->update_group
, 0))
1574 "%s [Update:SEND] %s is filtered via ORF",
1582 /* Output filter check. */
1583 if (bgp_output_filter(peer
, p
, piattr
, afi
, safi
) == FILTER_DENY
) {
1584 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1585 zlog_debug("%s [Update:SEND] %s is filtered",
1586 peer
->host
, prefix2str(p
, buf
, sizeof(buf
)));
1590 #ifdef BGP_SEND_ASPATH_CHECK
1591 /* AS path loop check. */
1592 if (onlypeer
&& aspath_loop_check(piattr
->aspath
, onlypeer
->as
)) {
1593 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1595 "%s [Update:SEND] suppress announcement to peer AS %u "
1596 "that is part of AS path.",
1597 onlypeer
->host
, onlypeer
->as
);
1600 #endif /* BGP_SEND_ASPATH_CHECK */
1602 /* If we're a CONFED we need to loop check the CONFED ID too */
1603 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
1604 if (aspath_loop_check(piattr
->aspath
, bgp
->confed_id
)) {
1605 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1607 "%s [Update:SEND] suppress announcement to peer AS %u"
1609 peer
->host
, bgp
->confed_id
);
1614 /* Route-Reflect check. */
1615 if (from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1620 /* IBGP reflection check. */
1621 if (reflect
&& !samepeer_safe
) {
1622 /* A route from a Client peer. */
1623 if (CHECK_FLAG(from
->af_flags
[afi
][safi
],
1624 PEER_FLAG_REFLECTOR_CLIENT
)) {
1625 /* Reflect to all the Non-Client peers and also to the
1626 Client peers other than the originator. Originator
1628 is already done. So there is noting to do. */
1629 /* no bgp client-to-client reflection check. */
1630 if (bgp_flag_check(bgp
, BGP_FLAG_NO_CLIENT_TO_CLIENT
))
1631 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1632 PEER_FLAG_REFLECTOR_CLIENT
))
1635 /* A route from a Non-client peer. Reflect to all other
1637 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1638 PEER_FLAG_REFLECTOR_CLIENT
))
1643 /* For modify attribute, copy it to temporary structure. */
1644 bgp_attr_dup(attr
, piattr
);
1646 /* If local-preference is not set. */
1647 if ((peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
)
1648 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))) {
1649 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1650 attr
->local_pref
= bgp
->default_local_pref
;
1653 /* If originator-id is not set and the route is to be reflected,
1654 set the originator id */
1656 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)))) {
1657 IPV4_ADDR_COPY(&(attr
->originator_id
), &(from
->remote_id
));
1658 SET_FLAG(attr
->flag
, BGP_ATTR_ORIGINATOR_ID
);
1661 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
1663 if (peer
->sort
== BGP_PEER_EBGP
1664 && attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
1665 if (from
!= bgp
->peer_self
&& !transparent
1666 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1667 PEER_FLAG_MED_UNCHANGED
))
1669 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
));
1672 /* Since the nexthop attribute can vary per peer, it is not explicitly
1674 * in announce check, only certain flags and length (or number of
1676 * -- for IPv6/MP_REACH) are set here in order to guide the update
1678 * code in setting the nexthop(s) on a per peer basis in
1680 * Typically, the source nexthop in the attribute is preserved but in
1682 * scenarios where we know it will always be overwritten, we reset the
1683 * nexthop to "0" in an attempt to achieve better Update packing. An
1684 * example of this is when a prefix from each of 2 IBGP peers needs to
1686 * announced to an EBGP peer (and they have the same attributes barring
1690 SET_FLAG(attr
->rmap_change_flags
, BATTR_REFLECTED
);
1692 #define NEXTHOP_IS_V6 \
1693 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
1694 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
1695 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
1696 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
1698 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
1700 * the peer (group) is configured to receive link-local nexthop
1702 * and it is available in the prefix OR we're not reflecting the route
1704 * the peer (group) to whom we're going to announce is on a shared
1706 * and this is either a self-originated route or the peer is EBGP.
1708 if (NEXTHOP_IS_V6
) {
1709 attr
->mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
1710 if ((CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1711 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)
1712 && IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
))
1713 || (!reflect
&& peer
->shared_network
1714 && (from
== bgp
->peer_self
1715 || peer
->sort
== BGP_PEER_EBGP
))) {
1716 attr
->mp_nexthop_len
=
1717 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
;
1720 /* Clear off link-local nexthop in source, whenever it is not
1722 * ensure more prefixes share the same attribute for
1725 if (!(CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1726 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)))
1727 memset(&attr
->mp_nexthop_local
, 0, IPV6_MAX_BYTELEN
);
1730 bgp_peer_remove_private_as(bgp
, afi
, safi
, peer
, attr
);
1731 bgp_peer_as_override(bgp
, afi
, safi
, peer
, attr
);
1733 /* Route map & unsuppress-map apply. */
1734 if (ROUTE_MAP_OUT_NAME(filter
) || (pi
->extra
&& pi
->extra
->suppress
)) {
1735 struct bgp_path_info rmap_path
;
1736 struct bgp_path_info_extra dummy_rmap_path_extra
;
1737 struct attr dummy_attr
;
1739 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
1740 rmap_path
.peer
= peer
;
1741 rmap_path
.attr
= attr
;
1744 memcpy(&dummy_rmap_path_extra
, pi
->extra
,
1745 sizeof(struct bgp_path_info_extra
));
1746 rmap_path
.extra
= &dummy_rmap_path_extra
;
1749 /* don't confuse inbound and outbound setting */
1750 RESET_FLAG(attr
->rmap_change_flags
);
1753 * The route reflector is not allowed to modify the attributes
1754 * of the reflected IBGP routes unless explicitly allowed.
1756 if ((from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1757 && !bgp_flag_check(bgp
,
1758 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY
)) {
1759 bgp_attr_dup(&dummy_attr
, attr
);
1760 rmap_path
.attr
= &dummy_attr
;
1763 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1765 if (pi
->extra
&& pi
->extra
->suppress
)
1766 ret
= route_map_apply(UNSUPPRESS_MAP(filter
), p
,
1767 RMAP_BGP
, &rmap_path
);
1769 ret
= route_map_apply(ROUTE_MAP_OUT(filter
), p
,
1770 RMAP_BGP
, &rmap_path
);
1772 peer
->rmap_type
= 0;
1774 if (ret
== RMAP_DENYMATCH
) {
1775 bgp_attr_flush(attr
);
1780 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
1781 if (peer
->sort
== BGP_PEER_IBGP
1782 || peer
->sort
== BGP_PEER_CONFED
) {
1783 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1784 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1786 bgp_attr_add_gshut_community(attr
);
1790 /* After route-map has been applied, we check to see if the nexthop to
1791 * be carried in the attribute (that is used for the announcement) can
1792 * be cleared off or not. We do this in all cases where we would be
1793 * setting the nexthop to "ourselves". For IPv6, we only need to
1795 * the global nexthop here; the link-local nexthop would have been
1797 * already, and if not, it is required by the update formation code.
1798 * Also see earlier comments in this function.
1801 * If route-map has performed some operation on the nexthop or the peer
1802 * configuration says to pass it unchanged, we cannot reset the nexthop
1803 * here, so only attempt to do it if these aren't true. Note that the
1804 * route-map handler itself might have cleared the nexthop, if for
1806 * it is configured as 'peer-address'.
1808 if (!bgp_rmap_nhop_changed(attr
->rmap_change_flags
,
1809 piattr
->rmap_change_flags
)
1811 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1812 PEER_FLAG_NEXTHOP_UNCHANGED
)) {
1813 /* We can reset the nexthop, if setting (or forcing) it to
1815 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1816 PEER_FLAG_NEXTHOP_SELF
)
1817 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1818 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
1820 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1821 PEER_FLAG_FORCE_NEXTHOP_SELF
))
1822 subgroup_announce_reset_nhop(
1823 (peer_cap_enhe(peer
, afi
, safi
)
1827 } else if (peer
->sort
== BGP_PEER_EBGP
) {
1828 /* Can also reset the nexthop if announcing to EBGP, but
1830 * no peer in the subgroup is on a shared subnet.
1831 * Note: 3rd party nexthop currently implemented for
1834 if (!bgp_subgrp_multiaccess_check_v4(piattr
->nexthop
,
1836 subgroup_announce_reset_nhop(
1837 (peer_cap_enhe(peer
, afi
, safi
)
1841 } else if (CHECK_FLAG(pi
->flags
, BGP_PATH_ANNC_NH_SELF
)) {
1843 * This flag is used for leaked vpn-vrf routes
1845 int family
= p
->family
;
1847 if (peer_cap_enhe(peer
, afi
, safi
))
1850 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1852 "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
1853 __func__
, family2str(family
));
1854 subgroup_announce_reset_nhop(family
, attr
);
1857 /* If IPv6/MP and nexthop does not have any override and happens
1859 * be a link-local address, reset it so that we don't pass along
1861 * source's link-local IPv6 address to recipients who may not be
1863 * the same interface.
1865 if (p
->family
== AF_INET6
|| peer_cap_enhe(peer
, afi
, safi
)) {
1866 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
))
1867 subgroup_announce_reset_nhop(AF_INET6
, attr
);
1874 void bgp_best_selection(struct bgp
*bgp
, struct bgp_node
*rn
,
1875 struct bgp_maxpaths_cfg
*mpath_cfg
,
1876 struct bgp_path_info_pair
*result
, afi_t afi
,
1879 struct bgp_path_info
*new_select
;
1880 struct bgp_path_info
*old_select
;
1881 struct bgp_path_info
*pi
;
1882 struct bgp_path_info
*pi1
;
1883 struct bgp_path_info
*pi2
;
1884 struct bgp_path_info
*nextpi
= NULL
;
1885 int paths_eq
, do_mpath
, debug
;
1886 struct list mp_list
;
1887 char pfx_buf
[PREFIX2STR_BUFFER
];
1888 char path_buf
[PATH_ADDPATH_STR_BUFFER
];
1890 bgp_mp_list_init(&mp_list
);
1892 (mpath_cfg
->maxpaths_ebgp
> 1 || mpath_cfg
->maxpaths_ibgp
> 1);
1894 debug
= bgp_debug_bestpath(&rn
->p
);
1897 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
1899 /* bgp deterministic-med */
1901 if (bgp_flag_check(bgp
, BGP_FLAG_DETERMINISTIC_MED
)) {
1903 /* Clear BGP_PATH_DMED_SELECTED for all paths */
1904 for (pi1
= bgp_node_get_bgp_path_info(rn
); pi1
;
1906 bgp_path_info_unset_flag(rn
, pi1
,
1907 BGP_PATH_DMED_SELECTED
);
1909 for (pi1
= bgp_node_get_bgp_path_info(rn
); pi1
;
1911 if (CHECK_FLAG(pi1
->flags
, BGP_PATH_DMED_CHECK
))
1913 if (BGP_PATH_HOLDDOWN(pi1
))
1915 if (pi1
->peer
&& pi1
->peer
!= bgp
->peer_self
)
1916 if (pi1
->peer
->status
!= Established
)
1921 for (pi2
= pi1
->next
; pi2
; pi2
= pi2
->next
) {
1922 if (CHECK_FLAG(pi2
->flags
,
1923 BGP_PATH_DMED_CHECK
))
1925 if (BGP_PATH_HOLDDOWN(pi2
))
1928 && pi2
->peer
!= bgp
->peer_self
1931 PEER_STATUS_NSF_WAIT
))
1932 if (pi2
->peer
->status
1936 if (!aspath_cmp_left(pi1
->attr
->aspath
,
1938 && !aspath_cmp_left_confed(
1943 if (bgp_path_info_cmp(
1944 bgp
, pi2
, new_select
,
1945 &paths_eq
, mpath_cfg
, debug
,
1946 pfx_buf
, afi
, safi
)) {
1947 bgp_path_info_unset_flag(
1949 BGP_PATH_DMED_SELECTED
);
1953 bgp_path_info_set_flag(
1954 rn
, pi2
, BGP_PATH_DMED_CHECK
);
1957 bgp_path_info_set_flag(rn
, new_select
,
1958 BGP_PATH_DMED_CHECK
);
1959 bgp_path_info_set_flag(rn
, new_select
,
1960 BGP_PATH_DMED_SELECTED
);
1963 bgp_path_info_path_with_addpath_rx_str(
1964 new_select
, path_buf
);
1965 zlog_debug("%s: %s is the bestpath from AS %u",
1967 aspath_get_first_as(
1968 new_select
->attr
->aspath
));
1973 /* Check old selected route and new selected route. */
1976 for (pi
= bgp_node_get_bgp_path_info(rn
);
1977 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
1978 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
1981 if (BGP_PATH_HOLDDOWN(pi
)) {
1982 /* reap REMOVED routes, if needs be
1983 * selected route must stay for a while longer though
1985 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
1986 && (pi
!= old_select
))
1987 bgp_path_info_reap(rn
, pi
);
1990 zlog_debug("%s: pi %p in holddown", __func__
,
1996 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
1997 && !CHECK_FLAG(pi
->peer
->sflags
, PEER_STATUS_NSF_WAIT
))
1998 if (pi
->peer
->status
!= Established
) {
2002 "%s: pi %p non self peer %s not estab state",
2003 __func__
, pi
, pi
->peer
->host
);
2008 if (bgp_flag_check(bgp
, BGP_FLAG_DETERMINISTIC_MED
)
2009 && (!CHECK_FLAG(pi
->flags
, BGP_PATH_DMED_SELECTED
))) {
2010 bgp_path_info_unset_flag(rn
, pi
, BGP_PATH_DMED_CHECK
);
2012 zlog_debug("%s: pi %p dmed", __func__
, pi
);
2016 bgp_path_info_unset_flag(rn
, pi
, BGP_PATH_DMED_CHECK
);
2018 if (bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
, mpath_cfg
,
2019 debug
, pfx_buf
, afi
, safi
)) {
2024 /* Now that we know which path is the bestpath see if any of the other
2026 * qualify as multipaths
2030 bgp_path_info_path_with_addpath_rx_str(new_select
,
2033 sprintf(path_buf
, "NONE");
2035 "%s: After path selection, newbest is %s oldbest was %s",
2037 old_select
? old_select
->peer
->host
: "NONE");
2040 if (do_mpath
&& new_select
) {
2041 for (pi
= bgp_node_get_bgp_path_info(rn
);
2042 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2045 bgp_path_info_path_with_addpath_rx_str(
2048 if (pi
== new_select
) {
2051 "%s: %s is the bestpath, add to the multipath list",
2053 bgp_mp_list_add(&mp_list
, pi
);
2057 if (BGP_PATH_HOLDDOWN(pi
))
2060 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2061 && !CHECK_FLAG(pi
->peer
->sflags
,
2062 PEER_STATUS_NSF_WAIT
))
2063 if (pi
->peer
->status
!= Established
)
2066 if (!bgp_path_info_nexthop_cmp(pi
, new_select
)) {
2069 "%s: %s has the same nexthop as the bestpath, skip it",
2074 bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
,
2075 mpath_cfg
, debug
, pfx_buf
, afi
, safi
);
2080 "%s: %s is equivalent to the bestpath, add to the multipath list",
2082 bgp_mp_list_add(&mp_list
, pi
);
2087 bgp_path_info_mpath_update(rn
, new_select
, old_select
, &mp_list
,
2089 bgp_path_info_mpath_aggregate_update(new_select
, old_select
);
2090 bgp_mp_list_clear(&mp_list
);
2092 bgp_addpath_update_ids(bgp
, rn
, afi
, safi
);
2094 result
->old
= old_select
;
2095 result
->new = new_select
;
2101 * A new route/change in bestpath of an existing route. Evaluate the path
2102 * for advertisement to the subgroup.
2104 int subgroup_process_announce_selected(struct update_subgroup
*subgrp
,
2105 struct bgp_path_info
*selected
,
2106 struct bgp_node
*rn
,
2107 uint32_t addpath_tx_id
)
2110 struct peer
*onlypeer
;
2116 afi
= SUBGRP_AFI(subgrp
);
2117 safi
= SUBGRP_SAFI(subgrp
);
2118 onlypeer
= ((SUBGRP_PCOUNT(subgrp
) == 1) ? (SUBGRP_PFIRST(subgrp
))->peer
2121 if (BGP_DEBUG(update
, UPDATE_OUT
)) {
2122 char buf_prefix
[PREFIX_STRLEN
];
2123 prefix2str(p
, buf_prefix
, sizeof(buf_prefix
));
2124 zlog_debug("%s: p=%s, selected=%p", __func__
, buf_prefix
,
2128 /* First update is deferred until ORF or ROUTE-REFRESH is received */
2129 if (onlypeer
&& CHECK_FLAG(onlypeer
->af_sflags
[afi
][safi
],
2130 PEER_STATUS_ORF_WAIT_REFRESH
))
2133 memset(&attr
, 0, sizeof(struct attr
));
2134 /* It's initialized in bgp_announce_check() */
2136 /* Announcement to the subgroup. If the route is filtered withdraw it.
2139 if (subgroup_announce_check(rn
, selected
, subgrp
, p
, &attr
))
2140 bgp_adj_out_set_subgroup(rn
, subgrp
, &attr
, selected
);
2142 bgp_adj_out_unset_subgroup(rn
, subgrp
, 1,
2146 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2148 bgp_adj_out_unset_subgroup(rn
, subgrp
, 1, addpath_tx_id
);
2155 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2156 * This is called at the end of route processing.
2158 void bgp_zebra_clear_route_change_flags(struct bgp_node
*rn
)
2160 struct bgp_path_info
*pi
;
2162 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
2163 if (BGP_PATH_HOLDDOWN(pi
))
2165 UNSET_FLAG(pi
->flags
, BGP_PATH_IGP_CHANGED
);
2166 UNSET_FLAG(pi
->flags
, BGP_PATH_ATTR_CHANGED
);
2171 * Has the route changed from the RIB's perspective? This is invoked only
2172 * if the route selection returns the same best route as earlier - to
2173 * determine if we need to update zebra or not.
2175 int bgp_zebra_has_route_changed(struct bgp_node
*rn
,
2176 struct bgp_path_info
*selected
)
2178 struct bgp_path_info
*mpinfo
;
2180 /* If this is multipath, check all selected paths for any nexthop
2181 * change or attribute change. Some attribute changes (e.g., community)
2182 * aren't of relevance to the RIB, but we'll update zebra to ensure
2183 * we handle the case of BGP nexthop change. This is the behavior
2184 * when the best path has an attribute change anyway.
2186 if (CHECK_FLAG(selected
->flags
, BGP_PATH_IGP_CHANGED
)
2187 || CHECK_FLAG(selected
->flags
, BGP_PATH_MULTIPATH_CHG
))
2191 * If this is multipath, check all selected paths for any nexthop change
2193 for (mpinfo
= bgp_path_info_mpath_first(selected
); mpinfo
;
2194 mpinfo
= bgp_path_info_mpath_next(mpinfo
)) {
2195 if (CHECK_FLAG(mpinfo
->flags
, BGP_PATH_IGP_CHANGED
)
2196 || CHECK_FLAG(mpinfo
->flags
, BGP_PATH_ATTR_CHANGED
))
2200 /* Nothing has changed from the RIB's perspective. */
2204 struct bgp_process_queue
{
2206 STAILQ_HEAD(, bgp_node
) pqueue
;
2207 #define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2209 unsigned int queued
;
2213 * old_select = The old best path
2214 * new_select = the new best path
2216 * if (!old_select && new_select)
2217 * We are sending new information on.
2219 * if (old_select && new_select) {
2220 * if (new_select != old_select)
2221 * We have a new best path send a change
2223 * We've received a update with new attributes that needs
2227 * if (old_select && !new_select)
2228 * We have no eligible route that we can announce or the rn
2231 static void bgp_process_main_one(struct bgp
*bgp
, struct bgp_node
*rn
,
2232 afi_t afi
, safi_t safi
)
2234 struct bgp_path_info
*new_select
;
2235 struct bgp_path_info
*old_select
;
2236 struct bgp_path_info_pair old_and_new
;
2237 char pfx_buf
[PREFIX2STR_BUFFER
];
2240 /* Is it end of initial update? (after startup) */
2242 quagga_timestamp(3, bgp
->update_delay_zebra_resume_time
,
2243 sizeof(bgp
->update_delay_zebra_resume_time
));
2245 bgp
->main_zebra_update_hold
= 0;
2246 FOREACH_AFI_SAFI (afi
, safi
) {
2247 if (bgp_fibupd_safi(safi
))
2248 bgp_zebra_announce_table(bgp
, afi
, safi
);
2250 bgp
->main_peers_update_hold
= 0;
2252 bgp_start_routeadv(bgp
);
2256 struct prefix
*p
= &rn
->p
;
2258 debug
= bgp_debug_bestpath(&rn
->p
);
2260 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
2261 zlog_debug("%s: p=%s afi=%s, safi=%s start", __func__
, pfx_buf
,
2262 afi2str(afi
), safi2str(safi
));
2265 /* Best path selection. */
2266 bgp_best_selection(bgp
, rn
, &bgp
->maxpaths
[afi
][safi
], &old_and_new
,
2268 old_select
= old_and_new
.old
;
2269 new_select
= old_and_new
.new;
2271 /* Do we need to allocate or free labels?
2272 * Right now, since we only deal with per-prefix labels, it is not
2273 * necessary to do this upon changes to best path. Exceptions:
2274 * - label index has changed -> recalculate resulting label
2275 * - path_info sub_type changed -> switch to/from implicit-null
2276 * - no valid label (due to removed static label binding) -> get new one
2278 if (bgp
->allocate_mpls_labels
[afi
][safi
]) {
2281 || bgp_label_index_differs(new_select
, old_select
)
2282 || new_select
->sub_type
!= old_select
->sub_type
2283 || !bgp_is_valid_label(&rn
->local_label
)) {
2284 /* Enforced penultimate hop popping:
2285 * implicit-null for local routes, aggregate
2286 * and redistributed routes
2288 if (new_select
->sub_type
== BGP_ROUTE_STATIC
2289 || new_select
->sub_type
2290 == BGP_ROUTE_AGGREGATE
2291 || new_select
->sub_type
2292 == BGP_ROUTE_REDISTRIBUTE
) {
2295 BGP_NODE_REGISTERED_FOR_LABEL
))
2296 bgp_unregister_for_label(rn
);
2297 label_ntop(MPLS_LABEL_IMPLICIT_NULL
, 1,
2299 bgp_set_valid_label(&rn
->local_label
);
2301 bgp_register_for_label(rn
, new_select
);
2303 } else if (CHECK_FLAG(rn
->flags
,
2304 BGP_NODE_REGISTERED_FOR_LABEL
)) {
2305 bgp_unregister_for_label(rn
);
2307 } else if (CHECK_FLAG(rn
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
)) {
2308 bgp_unregister_for_label(rn
);
2312 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
2314 "%s: p=%s afi=%s, safi=%s, old_select=%p, new_select=%p",
2315 __func__
, pfx_buf
, afi2str(afi
), safi2str(safi
),
2316 old_select
, new_select
);
2319 /* If best route remains the same and this is not due to user-initiated
2320 * clear, see exactly what needs to be done.
2322 if (old_select
&& old_select
== new_select
2323 && !CHECK_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
)
2324 && !CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
2325 && !bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
2326 if (bgp_zebra_has_route_changed(rn
, old_select
)) {
2328 vnc_import_bgp_add_route(bgp
, p
, old_select
);
2329 vnc_import_bgp_exterior_add_route(bgp
, p
, old_select
);
2331 if (bgp_fibupd_safi(safi
)
2332 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2334 if (new_select
->type
== ZEBRA_ROUTE_BGP
2335 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2336 || new_select
->sub_type
2337 == BGP_ROUTE_IMPORTED
))
2339 bgp_zebra_announce(rn
, p
, old_select
,
2343 UNSET_FLAG(old_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
2344 bgp_zebra_clear_route_change_flags(rn
);
2346 /* If there is a change of interest to peers, reannounce the
2348 if (CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
2349 || CHECK_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
)) {
2350 group_announce_route(bgp
, afi
, safi
, rn
, new_select
);
2352 /* unicast routes must also be annouced to
2353 * labeled-unicast update-groups */
2354 if (safi
== SAFI_UNICAST
)
2355 group_announce_route(bgp
, afi
,
2356 SAFI_LABELED_UNICAST
, rn
,
2359 UNSET_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
);
2360 UNSET_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
);
2363 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2367 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2369 UNSET_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
);
2371 /* bestpath has changed; bump version */
2372 if (old_select
|| new_select
) {
2373 bgp_bump_version(rn
);
2375 if (!bgp
->t_rmap_def_originate_eval
) {
2379 update_group_refresh_default_originate_route_map
,
2380 bgp
, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER
,
2381 &bgp
->t_rmap_def_originate_eval
);
2386 bgp_path_info_unset_flag(rn
, old_select
, BGP_PATH_SELECTED
);
2389 zlog_debug("%s: setting SELECTED flag", __func__
);
2390 bgp_path_info_set_flag(rn
, new_select
, BGP_PATH_SELECTED
);
2391 bgp_path_info_unset_flag(rn
, new_select
, BGP_PATH_ATTR_CHANGED
);
2392 UNSET_FLAG(new_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
2396 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2397 if (old_select
!= new_select
) {
2399 vnc_import_bgp_exterior_del_route(bgp
, p
,
2401 vnc_import_bgp_del_route(bgp
, p
, old_select
);
2404 vnc_import_bgp_exterior_add_route(bgp
, p
,
2406 vnc_import_bgp_add_route(bgp
, p
, new_select
);
2412 group_announce_route(bgp
, afi
, safi
, rn
, new_select
);
2414 /* unicast routes must also be annouced to labeled-unicast update-groups
2416 if (safi
== SAFI_UNICAST
)
2417 group_announce_route(bgp
, afi
, SAFI_LABELED_UNICAST
, rn
,
2421 if (bgp_fibupd_safi(safi
) && (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VIEW
)
2422 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2423 if (new_select
&& new_select
->type
== ZEBRA_ROUTE_BGP
2424 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2425 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
2426 || new_select
->sub_type
== BGP_ROUTE_IMPORTED
)) {
2428 /* if this is an evpn imported type-5 prefix,
2429 * we need to withdraw the route first to clear
2430 * the nh neigh and the RMAC entry.
2433 is_route_parent_evpn(old_select
))
2434 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2436 bgp_zebra_announce(rn
, p
, new_select
, bgp
, afi
, safi
);
2438 /* Withdraw the route from the kernel. */
2439 if (old_select
&& old_select
->type
== ZEBRA_ROUTE_BGP
2440 && (old_select
->sub_type
== BGP_ROUTE_NORMAL
2441 || old_select
->sub_type
== BGP_ROUTE_AGGREGATE
2442 || old_select
->sub_type
== BGP_ROUTE_IMPORTED
))
2444 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2448 /* advertise/withdraw type-5 routes */
2449 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2450 if (advertise_type5_routes(bgp
, afi
) && new_select
&&
2451 (!new_select
->extra
|| !new_select
->extra
->parent
)) {
2453 /* apply the route-map */
2454 if (bgp
->adv_cmd_rmap
[afi
][safi
].map
) {
2457 ret
= route_map_apply(
2458 bgp
->adv_cmd_rmap
[afi
][safi
].map
,
2459 &rn
->p
, RMAP_BGP
, new_select
);
2460 if (ret
== RMAP_MATCH
)
2461 bgp_evpn_advertise_type5_route(
2462 bgp
, &rn
->p
, new_select
->attr
,
2465 bgp_evpn_advertise_type5_route(bgp
,
2471 } else if (advertise_type5_routes(bgp
, afi
) && old_select
&&
2472 (!old_select
->extra
|| !old_select
->extra
->parent
))
2473 bgp_evpn_withdraw_type5_route(bgp
, &rn
->p
, afi
, safi
);
2476 /* Clear any route change flags. */
2477 bgp_zebra_clear_route_change_flags(rn
);
2479 /* Reap old select bgp_path_info, if it has been removed */
2480 if (old_select
&& CHECK_FLAG(old_select
->flags
, BGP_PATH_REMOVED
))
2481 bgp_path_info_reap(rn
, old_select
);
2483 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2487 static wq_item_status
bgp_process_wq(struct work_queue
*wq
, void *data
)
2489 struct bgp_process_queue
*pqnode
= data
;
2490 struct bgp
*bgp
= pqnode
->bgp
;
2491 struct bgp_table
*table
;
2492 struct bgp_node
*rn
;
2495 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)) {
2496 bgp_process_main_one(bgp
, NULL
, 0, 0);
2497 /* should always have dedicated wq call */
2498 assert(STAILQ_FIRST(&pqnode
->pqueue
) == NULL
);
2502 while (!STAILQ_EMPTY(&pqnode
->pqueue
)) {
2503 rn
= STAILQ_FIRST(&pqnode
->pqueue
);
2504 STAILQ_REMOVE_HEAD(&pqnode
->pqueue
, pq
);
2505 STAILQ_NEXT(rn
, pq
) = NULL
; /* complete unlink */
2506 table
= bgp_node_table(rn
);
2507 /* note, new RNs may be added as part of processing */
2508 bgp_process_main_one(bgp
, rn
, table
->afi
, table
->safi
);
2510 bgp_unlock_node(rn
);
2511 bgp_table_unlock(table
);
2517 static void bgp_processq_del(struct work_queue
*wq
, void *data
)
2519 struct bgp_process_queue
*pqnode
= data
;
2521 bgp_unlock(pqnode
->bgp
);
2523 XFREE(MTYPE_BGP_PROCESS_QUEUE
, pqnode
);
2526 void bgp_process_queue_init(void)
2528 if (!bm
->process_main_queue
)
2529 bm
->process_main_queue
=
2530 work_queue_new(bm
->master
, "process_main_queue");
2532 bm
->process_main_queue
->spec
.workfunc
= &bgp_process_wq
;
2533 bm
->process_main_queue
->spec
.del_item_data
= &bgp_processq_del
;
2534 bm
->process_main_queue
->spec
.max_retries
= 0;
2535 bm
->process_main_queue
->spec
.hold
= 50;
2536 /* Use a higher yield value of 50ms for main queue processing */
2537 bm
->process_main_queue
->spec
.yield
= 50 * 1000L;
2540 static struct bgp_process_queue
*bgp_processq_alloc(struct bgp
*bgp
)
2542 struct bgp_process_queue
*pqnode
;
2544 pqnode
= XCALLOC(MTYPE_BGP_PROCESS_QUEUE
,
2545 sizeof(struct bgp_process_queue
));
2547 /* unlocked in bgp_processq_del */
2548 pqnode
->bgp
= bgp_lock(bgp
);
2549 STAILQ_INIT(&pqnode
->pqueue
);
2554 void bgp_process(struct bgp
*bgp
, struct bgp_node
*rn
, afi_t afi
, safi_t safi
)
2556 #define ARBITRARY_PROCESS_QLEN 10000
2557 struct work_queue
*wq
= bm
->process_main_queue
;
2558 struct bgp_process_queue
*pqnode
;
2559 int pqnode_reuse
= 0;
2561 /* already scheduled for processing? */
2562 if (CHECK_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
2568 /* Add route nodes to an existing work queue item until reaching the
2569 limit only if is from the same BGP view and it's not an EOIU marker
2571 if (work_queue_item_count(wq
)) {
2572 struct work_queue_item
*item
= work_queue_last_item(wq
);
2573 pqnode
= item
->data
;
2575 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)
2576 || pqnode
->bgp
!= bgp
2577 || pqnode
->queued
>= ARBITRARY_PROCESS_QLEN
)
2578 pqnode
= bgp_processq_alloc(bgp
);
2582 pqnode
= bgp_processq_alloc(bgp
);
2583 /* all unlocked in bgp_process_wq */
2584 bgp_table_lock(bgp_node_table(rn
));
2586 SET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2589 /* can't be enqueued twice */
2590 assert(STAILQ_NEXT(rn
, pq
) == NULL
);
2591 STAILQ_INSERT_TAIL(&pqnode
->pqueue
, rn
, pq
);
2595 work_queue_add(wq
, pqnode
);
2600 void bgp_add_eoiu_mark(struct bgp
*bgp
)
2602 struct bgp_process_queue
*pqnode
;
2604 if (bm
->process_main_queue
== NULL
)
2607 pqnode
= bgp_processq_alloc(bgp
);
2609 SET_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
);
2610 work_queue_add(bm
->process_main_queue
, pqnode
);
2613 static int bgp_maximum_prefix_restart_timer(struct thread
*thread
)
2617 peer
= THREAD_ARG(thread
);
2618 peer
->t_pmax_restart
= NULL
;
2620 if (bgp_debug_neighbor_events(peer
))
2622 "%s Maximum-prefix restart timer expired, restore peering",
2625 if ((peer_clear(peer
, NULL
) < 0) && bgp_debug_neighbor_events(peer
))
2626 zlog_debug("%s: %s peer_clear failed",
2627 __PRETTY_FUNCTION__
, peer
->host
);
2632 int bgp_maximum_prefix_overflow(struct peer
*peer
, afi_t afi
, safi_t safi
,
2636 iana_safi_t pkt_safi
;
2638 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX
))
2641 if (peer
->pcount
[afi
][safi
] > peer
->pmax
[afi
][safi
]) {
2642 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2643 PEER_STATUS_PREFIX_LIMIT
)
2648 "%%MAXPFXEXCEED: No. of %s prefix received from %s %ld exceed, "
2650 afi_safi_print(afi
, safi
), peer
->host
,
2651 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2652 SET_FLAG(peer
->af_sflags
[afi
][safi
], PEER_STATUS_PREFIX_LIMIT
);
2654 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2655 PEER_FLAG_MAX_PREFIX_WARNING
))
2658 /* Convert AFI, SAFI to values for packet. */
2659 pkt_afi
= afi_int2iana(afi
);
2660 pkt_safi
= safi_int2iana(safi
);
2664 ndata
[0] = (pkt_afi
>> 8);
2666 ndata
[2] = pkt_safi
;
2667 ndata
[3] = (peer
->pmax
[afi
][safi
] >> 24);
2668 ndata
[4] = (peer
->pmax
[afi
][safi
] >> 16);
2669 ndata
[5] = (peer
->pmax
[afi
][safi
] >> 8);
2670 ndata
[6] = (peer
->pmax
[afi
][safi
]);
2672 SET_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
);
2673 bgp_notify_send_with_data(peer
, BGP_NOTIFY_CEASE
,
2674 BGP_NOTIFY_CEASE_MAX_PREFIX
,
2678 /* Dynamic peers will just close their connection. */
2679 if (peer_dynamic_neighbor(peer
))
2682 /* restart timer start */
2683 if (peer
->pmax_restart
[afi
][safi
]) {
2684 peer
->v_pmax_restart
=
2685 peer
->pmax_restart
[afi
][safi
] * 60;
2687 if (bgp_debug_neighbor_events(peer
))
2689 "%s Maximum-prefix restart timer started for %d secs",
2690 peer
->host
, peer
->v_pmax_restart
);
2692 BGP_TIMER_ON(peer
->t_pmax_restart
,
2693 bgp_maximum_prefix_restart_timer
,
2694 peer
->v_pmax_restart
);
2699 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
2700 PEER_STATUS_PREFIX_LIMIT
);
2702 if (peer
->pcount
[afi
][safi
]
2703 > (peer
->pmax
[afi
][safi
] * peer
->pmax_threshold
[afi
][safi
] / 100)) {
2704 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2705 PEER_STATUS_PREFIX_THRESHOLD
)
2710 "%%MAXPFX: No. of %s prefix received from %s reaches %ld, max %ld",
2711 afi_safi_print(afi
, safi
), peer
->host
,
2712 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2713 SET_FLAG(peer
->af_sflags
[afi
][safi
],
2714 PEER_STATUS_PREFIX_THRESHOLD
);
2716 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
2717 PEER_STATUS_PREFIX_THRESHOLD
);
2721 /* Unconditionally remove the route from the RIB, without taking
2722 * damping into consideration (eg, because the session went down)
2724 void bgp_rib_remove(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
2725 struct peer
*peer
, afi_t afi
, safi_t safi
)
2727 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, pi
, afi
, safi
);
2729 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
2730 bgp_path_info_delete(rn
, pi
); /* keep historical info */
2732 bgp_process(peer
->bgp
, rn
, afi
, safi
);
2735 static void bgp_rib_withdraw(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
2736 struct peer
*peer
, afi_t afi
, safi_t safi
,
2737 struct prefix_rd
*prd
)
2739 /* apply dampening, if result is suppressed, we'll be retaining
2740 * the bgp_path_info in the RIB for historical reference.
2742 if (CHECK_FLAG(peer
->bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
2743 && peer
->sort
== BGP_PEER_EBGP
)
2744 if ((bgp_damp_withdraw(pi
, rn
, afi
, safi
, 0))
2745 == BGP_DAMP_SUPPRESSED
) {
2746 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, pi
, afi
,
2752 if (safi
== SAFI_MPLS_VPN
) {
2753 struct bgp_node
*prn
= NULL
;
2754 struct bgp_table
*table
= NULL
;
2756 prn
= bgp_node_get(peer
->bgp
->rib
[afi
][safi
],
2757 (struct prefix
*)prd
);
2758 if (bgp_node_has_bgp_path_info_data(prn
)) {
2759 table
= bgp_node_get_bgp_table_info(prn
);
2761 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
2762 peer
->bgp
, prd
, table
, &rn
->p
, pi
);
2764 bgp_unlock_node(prn
);
2766 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2767 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
2769 vnc_import_bgp_del_route(peer
->bgp
, &rn
->p
, pi
);
2770 vnc_import_bgp_exterior_del_route(peer
->bgp
, &rn
->p
,
2776 /* If this is an EVPN route, process for un-import. */
2777 if (safi
== SAFI_EVPN
)
2778 bgp_evpn_unimport_route(peer
->bgp
, afi
, safi
, &rn
->p
, pi
);
2780 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
2783 struct bgp_path_info
*info_make(int type
, int sub_type
, unsigned short instance
,
2784 struct peer
*peer
, struct attr
*attr
,
2785 struct bgp_node
*rn
)
2787 struct bgp_path_info
*new;
2789 /* Make new BGP info. */
2790 new = XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_path_info
));
2792 new->instance
= instance
;
2793 new->sub_type
= sub_type
;
2796 new->uptime
= bgp_clock();
2801 static void overlay_index_update(struct attr
*attr
,
2802 struct eth_segment_id
*eth_s_id
,
2803 union gw_addr
*gw_ip
)
2808 if (eth_s_id
== NULL
) {
2809 memset(&(attr
->evpn_overlay
.eth_s_id
), 0,
2810 sizeof(struct eth_segment_id
));
2812 memcpy(&(attr
->evpn_overlay
.eth_s_id
), eth_s_id
,
2813 sizeof(struct eth_segment_id
));
2815 if (gw_ip
== NULL
) {
2816 memset(&(attr
->evpn_overlay
.gw_ip
), 0, sizeof(union gw_addr
));
2818 memcpy(&(attr
->evpn_overlay
.gw_ip
), gw_ip
,
2819 sizeof(union gw_addr
));
2823 static bool overlay_index_equal(afi_t afi
, struct bgp_path_info
*path
,
2824 struct eth_segment_id
*eth_s_id
,
2825 union gw_addr
*gw_ip
)
2827 struct eth_segment_id
*path_eth_s_id
, *path_eth_s_id_remote
;
2828 union gw_addr
*path_gw_ip
, *path_gw_ip_remote
;
2830 struct eth_segment_id esi
;
2834 if (afi
!= AFI_L2VPN
)
2837 memset(&temp
, 0, sizeof(temp
));
2838 path_eth_s_id
= &temp
.esi
;
2839 path_gw_ip
= &temp
.ip
;
2841 if (eth_s_id
== NULL
&& gw_ip
== NULL
)
2844 path_eth_s_id
= &(path
->attr
->evpn_overlay
.eth_s_id
);
2845 path_gw_ip
= &(path
->attr
->evpn_overlay
.gw_ip
);
2848 if (gw_ip
== NULL
) {
2849 memset(&temp
, 0, sizeof(temp
));
2850 path_gw_ip_remote
= &temp
.ip
;
2852 path_gw_ip_remote
= gw_ip
;
2854 if (eth_s_id
== NULL
) {
2855 memset(&temp
, 0, sizeof(temp
));
2856 path_eth_s_id_remote
= &temp
.esi
;
2858 path_eth_s_id_remote
= eth_s_id
;
2860 if (!memcmp(path_gw_ip
, path_gw_ip_remote
, sizeof(union gw_addr
)))
2863 return !memcmp(path_eth_s_id
, path_eth_s_id_remote
,
2864 sizeof(struct eth_segment_id
));
2867 /* Check if received nexthop is valid or not. */
2868 static int bgp_update_martian_nexthop(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
2873 /* Only validated for unicast and multicast currently. */
2874 /* Also valid for EVPN where the nexthop is an IP address. */
2875 if (safi
!= SAFI_UNICAST
&& safi
!= SAFI_MULTICAST
&& safi
!= SAFI_EVPN
)
2878 /* If NEXT_HOP is present, validate it. */
2879 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
2880 if (attr
->nexthop
.s_addr
== 0
2881 || IPV4_CLASS_DE(ntohl(attr
->nexthop
.s_addr
))
2882 || bgp_nexthop_self(bgp
, attr
->nexthop
))
2886 /* If MP_NEXTHOP is present, validate it. */
2887 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
2888 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
2889 * it is not an IPv6 link-local address.
2891 if (attr
->mp_nexthop_len
) {
2892 switch (attr
->mp_nexthop_len
) {
2893 case BGP_ATTR_NHLEN_IPV4
:
2894 case BGP_ATTR_NHLEN_VPNV4
:
2895 ret
= (attr
->mp_nexthop_global_in
.s_addr
== 0
2896 || IPV4_CLASS_DE(ntohl(
2897 attr
->mp_nexthop_global_in
.s_addr
))
2898 || bgp_nexthop_self(bgp
,
2899 attr
->mp_nexthop_global_in
));
2902 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
2903 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
2904 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
2905 ret
= (IN6_IS_ADDR_UNSPECIFIED(&attr
->mp_nexthop_global
)
2906 || IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
2907 || IN6_IS_ADDR_MULTICAST(
2908 &attr
->mp_nexthop_global
));
2920 int bgp_update(struct peer
*peer
, struct prefix
*p
, uint32_t addpath_id
,
2921 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
2922 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
2923 uint32_t num_labels
, int soft_reconfig
,
2924 struct bgp_route_evpn
*evpn
)
2927 int aspath_loop_count
= 0;
2928 struct bgp_node
*rn
;
2930 struct attr new_attr
;
2931 struct attr
*attr_new
;
2932 struct bgp_path_info
*pi
;
2933 struct bgp_path_info
*new;
2934 struct bgp_path_info_extra
*extra
;
2936 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
2938 int do_loop_check
= 1;
2939 int has_valid_label
= 0;
2941 int vnc_implicit_withdraw
= 0;
2945 memset(&new_attr
, 0, sizeof(struct attr
));
2946 new_attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
2947 new_attr
.label
= MPLS_INVALID_LABEL
;
2950 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
2951 /* TODO: Check to see if we can get rid of "is_valid_label" */
2952 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
2953 has_valid_label
= (num_labels
> 0) ? 1 : 0;
2955 has_valid_label
= bgp_is_valid_label(label
);
2957 /* When peer's soft reconfiguration enabled. Record input packet in
2960 && CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
2961 && peer
!= bgp
->peer_self
)
2962 bgp_adj_in_set(rn
, peer
, attr
, addpath_id
);
2964 /* Check previously received route. */
2965 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
2966 if (pi
->peer
== peer
&& pi
->type
== type
2967 && pi
->sub_type
== sub_type
2968 && pi
->addpath_rx_id
== addpath_id
)
2971 /* AS path local-as loop check. */
2972 if (peer
->change_local_as
) {
2973 if (peer
->allowas_in
[afi
][safi
])
2974 aspath_loop_count
= peer
->allowas_in
[afi
][safi
];
2975 else if (!CHECK_FLAG(peer
->flags
,
2976 PEER_FLAG_LOCAL_AS_NO_PREPEND
))
2977 aspath_loop_count
= 1;
2979 if (aspath_loop_check(attr
->aspath
, peer
->change_local_as
)
2980 > aspath_loop_count
) {
2981 reason
= "as-path contains our own AS;";
2986 /* If the peer is configured for "allowas-in origin" and the last ASN in
2988 * as-path is our ASN then we do not need to call aspath_loop_check
2990 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN_ORIGIN
))
2991 if (aspath_get_last_as(attr
->aspath
) == bgp
->as
)
2994 /* AS path loop check. */
2995 if (do_loop_check
) {
2996 if (aspath_loop_check(attr
->aspath
, bgp
->as
)
2997 > peer
->allowas_in
[afi
][safi
]
2998 || (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)
2999 && aspath_loop_check(attr
->aspath
, bgp
->confed_id
)
3000 > peer
->allowas_in
[afi
][safi
])) {
3001 reason
= "as-path contains our own AS;";
3006 /* Route reflector originator ID check. */
3007 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
3008 && IPV4_ADDR_SAME(&bgp
->router_id
, &attr
->originator_id
)) {
3009 reason
= "originator is us;";
3013 /* Route reflector cluster ID check. */
3014 if (bgp_cluster_filter(peer
, attr
)) {
3015 reason
= "reflected from the same cluster;";
3019 /* Apply incoming filter. */
3020 if (bgp_input_filter(peer
, p
, attr
, afi
, safi
) == FILTER_DENY
) {
3025 bgp_attr_dup(&new_attr
, attr
);
3027 /* Apply incoming route-map.
3028 * NB: new_attr may now contain newly allocated values from route-map
3030 * commands, so we need bgp_attr_flush in the error paths, until we
3032 * the attr (which takes over the memory references) */
3033 if (bgp_input_modifier(peer
, p
, &new_attr
, afi
, safi
, NULL
)
3035 reason
= "route-map;";
3036 bgp_attr_flush(&new_attr
);
3040 if (peer
->sort
== BGP_PEER_EBGP
) {
3042 /* If we receive the graceful-shutdown community from an eBGP
3043 * peer we must lower local-preference */
3044 if (new_attr
.community
3045 && community_include(new_attr
.community
, COMMUNITY_GSHUT
)) {
3046 new_attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
3047 new_attr
.local_pref
= BGP_GSHUT_LOCAL_PREF
;
3049 /* If graceful-shutdown is configured then add the GSHUT
3050 * community to all paths received from eBGP peers */
3051 } else if (bgp_flag_check(peer
->bgp
,
3052 BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
3053 bgp_attr_add_gshut_community(&new_attr
);
3057 /* next hop check. */
3058 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
)
3059 && bgp_update_martian_nexthop(bgp
, afi
, safi
, &new_attr
)) {
3060 reason
= "martian or self next-hop;";
3061 bgp_attr_flush(&new_attr
);
3065 if (bgp_mac_entry_exists(p
)) {
3066 reason
= "self mac;";
3070 attr_new
= bgp_attr_intern(&new_attr
);
3072 /* If the update is implicit withdraw. */
3074 pi
->uptime
= bgp_clock();
3075 same_attr
= attrhash_cmp(pi
->attr
, attr_new
);
3077 /* Same attribute comes in. */
3078 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
3079 && attrhash_cmp(pi
->attr
, attr_new
)
3080 && (!has_valid_label
3081 || memcmp(&(bgp_path_info_extra_get(pi
))->label
, label
,
3082 num_labels
* sizeof(mpls_label_t
))
3084 && (overlay_index_equal(
3085 afi
, pi
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3086 evpn
== NULL
? NULL
: &evpn
->gw_ip
))) {
3087 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
3088 BGP_CONFIG_DAMPENING
)
3089 && peer
->sort
== BGP_PEER_EBGP
3090 && CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3091 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3092 bgp_debug_rdpfxpath2str(
3093 afi
, safi
, prd
, p
, label
,
3094 num_labels
, addpath_id
? 1 : 0,
3095 addpath_id
, pfx_buf
,
3097 zlog_debug("%s rcvd %s", peer
->host
,
3101 if (bgp_damp_update(pi
, rn
, afi
, safi
)
3102 != BGP_DAMP_SUPPRESSED
) {
3103 bgp_aggregate_increment(bgp
, p
, pi
, afi
,
3105 bgp_process(bgp
, rn
, afi
, safi
);
3107 } else /* Duplicate - odd */
3109 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3110 if (!peer
->rcvd_attr_printed
) {
3112 "%s rcvd UPDATE w/ attr: %s",
3114 peer
->rcvd_attr_str
);
3115 peer
->rcvd_attr_printed
= 1;
3118 bgp_debug_rdpfxpath2str(
3119 afi
, safi
, prd
, p
, label
,
3120 num_labels
, addpath_id
? 1 : 0,
3121 addpath_id
, pfx_buf
,
3124 "%s rcvd %s...duplicate ignored",
3125 peer
->host
, pfx_buf
);
3128 /* graceful restart STALE flag unset. */
3129 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
3130 bgp_path_info_unset_flag(
3131 rn
, pi
, BGP_PATH_STALE
);
3132 bgp_process(bgp
, rn
, afi
, safi
);
3136 bgp_unlock_node(rn
);
3137 bgp_attr_unintern(&attr_new
);
3142 /* Withdraw/Announce before we fully processed the withdraw */
3143 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
3144 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3145 bgp_debug_rdpfxpath2str(
3146 afi
, safi
, prd
, p
, label
, num_labels
,
3147 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3150 "%s rcvd %s, flapped quicker than processing",
3151 peer
->host
, pfx_buf
);
3154 bgp_path_info_restore(rn
, pi
);
3157 /* Received Logging. */
3158 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3159 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
3160 num_labels
, addpath_id
? 1 : 0,
3161 addpath_id
, pfx_buf
,
3163 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3166 /* graceful restart STALE flag unset. */
3167 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
3168 bgp_path_info_unset_flag(rn
, pi
, BGP_PATH_STALE
);
3170 /* The attribute is changed. */
3171 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_ATTR_CHANGED
);
3173 /* implicit withdraw, decrement aggregate and pcount here.
3174 * only if update is accepted, they'll increment below.
3176 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
3178 /* Update bgp route dampening information. */
3179 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3180 && peer
->sort
== BGP_PEER_EBGP
) {
3181 /* This is implicit withdraw so we should update
3184 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
3185 bgp_damp_withdraw(pi
, rn
, afi
, safi
, 1);
3188 if (safi
== SAFI_MPLS_VPN
) {
3189 struct bgp_node
*prn
= NULL
;
3190 struct bgp_table
*table
= NULL
;
3192 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3193 (struct prefix
*)prd
);
3194 if (bgp_node_has_bgp_path_info_data(prn
)) {
3195 table
= bgp_node_get_bgp_table_info(prn
);
3197 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3198 bgp
, prd
, table
, p
, pi
);
3200 bgp_unlock_node(prn
);
3202 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3203 && (safi
== SAFI_UNICAST
)) {
3204 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
3206 * Implicit withdraw case.
3208 ++vnc_implicit_withdraw
;
3209 vnc_import_bgp_del_route(bgp
, p
, pi
);
3210 vnc_import_bgp_exterior_del_route(bgp
, p
, pi
);
3215 /* Special handling for EVPN update of an existing route. If the
3216 * extended community attribute has changed, we need to
3218 * the route using its existing extended community. It will be
3219 * subsequently processed for import with the new extended
3222 if (safi
== SAFI_EVPN
&& !same_attr
) {
3224 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))
3226 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
3229 cmp
= ecommunity_cmp(pi
->attr
->ecommunity
,
3230 attr_new
->ecommunity
);
3232 if (bgp_debug_update(peer
, p
, NULL
, 1))
3234 "Change in EXT-COMM, existing %s new %s",
3236 pi
->attr
->ecommunity
),
3238 attr_new
->ecommunity
));
3239 bgp_evpn_unimport_route(bgp
, afi
, safi
,
3245 /* Update to new attribute. */
3246 bgp_attr_unintern(&pi
->attr
);
3247 pi
->attr
= attr_new
;
3249 /* Update MPLS label */
3250 if (has_valid_label
) {
3251 extra
= bgp_path_info_extra_get(pi
);
3252 memcpy(&extra
->label
, label
,
3253 num_labels
* sizeof(mpls_label_t
));
3254 extra
->num_labels
= num_labels
;
3255 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3256 bgp_set_valid_label(&extra
->label
[0]);
3260 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3261 && (safi
== SAFI_UNICAST
)) {
3262 if (vnc_implicit_withdraw
) {
3264 * Add back the route with its new attributes
3266 * The route is still selected, until the route
3268 * queued by bgp_process actually runs. We have
3270 * update to the VNC side immediately to avoid
3272 * configuration changes (e.g., route-map
3274 * trigger re-importation of the entire RIB.
3276 vnc_import_bgp_add_route(bgp
, p
, pi
);
3277 vnc_import_bgp_exterior_add_route(bgp
, p
, pi
);
3281 /* Update Overlay Index */
3282 if (afi
== AFI_L2VPN
) {
3283 overlay_index_update(
3284 pi
->attr
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3285 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3288 /* Update bgp route dampening information. */
3289 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3290 && peer
->sort
== BGP_PEER_EBGP
) {
3291 /* Now we do normal update dampening. */
3292 ret
= bgp_damp_update(pi
, rn
, afi
, safi
);
3293 if (ret
== BGP_DAMP_SUPPRESSED
) {
3294 bgp_unlock_node(rn
);
3299 /* Nexthop reachability check - for unicast and
3300 * labeled-unicast.. */
3301 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3302 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
3303 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
3304 && !CHECK_FLAG(peer
->flags
,
3305 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3307 bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3312 struct bgp
*bgp_nexthop
= bgp
;
3314 if (pi
->extra
&& pi
->extra
->bgp_orig
)
3315 bgp_nexthop
= pi
->extra
->bgp_orig
;
3317 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
, afi
, pi
,
3319 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3320 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_VALID
);
3322 if (BGP_DEBUG(nht
, NHT
)) {
3323 char buf1
[INET6_ADDRSTRLEN
];
3325 (const void *)&attr_new
3327 buf1
, INET6_ADDRSTRLEN
);
3328 zlog_debug("%s(%s): NH unresolved",
3329 __FUNCTION__
, buf1
);
3331 bgp_path_info_unset_flag(rn
, pi
,
3335 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_VALID
);
3338 if (safi
== SAFI_MPLS_VPN
) {
3339 struct bgp_node
*prn
= NULL
;
3340 struct bgp_table
*table
= NULL
;
3342 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3343 (struct prefix
*)prd
);
3344 if (bgp_node_has_bgp_path_info_data(prn
)) {
3345 table
= bgp_node_get_bgp_table_info(prn
);
3347 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3348 bgp
, prd
, table
, p
, pi
);
3350 bgp_unlock_node(prn
);
3354 /* If this is an EVPN route and some attribute has changed,
3356 * route for import. If the extended community has changed, we
3358 * have done the un-import earlier and the import would result
3360 * route getting injected into appropriate L2 VNIs. If it is
3362 * some other attribute change, the import will result in
3364 * the attributes for the route in the VNI(s).
3366 if (safi
== SAFI_EVPN
&& !same_attr
)
3367 bgp_evpn_import_route(bgp
, afi
, safi
, p
, pi
);
3369 /* Process change. */
3370 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
3372 bgp_process(bgp
, rn
, afi
, safi
);
3373 bgp_unlock_node(rn
);
3375 if (SAFI_UNICAST
== safi
3376 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3377 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3379 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, pi
);
3381 if ((SAFI_MPLS_VPN
== safi
)
3382 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3384 vpn_leak_to_vrf_update(bgp
, pi
);
3388 if (SAFI_MPLS_VPN
== safi
) {
3389 mpls_label_t label_decoded
= decode_label(label
);
3391 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3392 type
, sub_type
, &label_decoded
);
3394 if (SAFI_ENCAP
== safi
) {
3395 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3396 type
, sub_type
, NULL
);
3401 } // End of implicit withdraw
3403 /* Received Logging. */
3404 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3405 if (!peer
->rcvd_attr_printed
) {
3406 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3407 peer
->rcvd_attr_str
);
3408 peer
->rcvd_attr_printed
= 1;
3411 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3412 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3414 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3417 /* Make new BGP info. */
3418 new = info_make(type
, sub_type
, 0, peer
, attr_new
, rn
);
3420 /* Update MPLS label */
3421 if (has_valid_label
) {
3422 extra
= bgp_path_info_extra_get(new);
3423 memcpy(&extra
->label
, label
, num_labels
* sizeof(mpls_label_t
));
3424 extra
->num_labels
= num_labels
;
3425 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3426 bgp_set_valid_label(&extra
->label
[0]);
3429 /* Update Overlay Index */
3430 if (afi
== AFI_L2VPN
) {
3431 overlay_index_update(new->attr
,
3432 evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3433 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3435 /* Nexthop reachability check. */
3436 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3437 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
3438 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
3439 && !CHECK_FLAG(peer
->flags
,
3440 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3441 && !bgp_flag_check(bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3446 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, new, NULL
, connected
)
3447 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3448 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
3450 if (BGP_DEBUG(nht
, NHT
)) {
3451 char buf1
[INET6_ADDRSTRLEN
];
3453 (const void *)&attr_new
->nexthop
,
3454 buf1
, INET6_ADDRSTRLEN
);
3455 zlog_debug("%s(%s): NH unresolved",
3456 __FUNCTION__
, buf1
);
3458 bgp_path_info_unset_flag(rn
, new, BGP_PATH_VALID
);
3461 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
3464 new->addpath_rx_id
= addpath_id
;
3466 /* Increment prefix */
3467 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
3469 /* Register new BGP information. */
3470 bgp_path_info_add(rn
, new);
3472 /* route_node_get lock */
3473 bgp_unlock_node(rn
);
3476 if (safi
== SAFI_MPLS_VPN
) {
3477 struct bgp_node
*prn
= NULL
;
3478 struct bgp_table
*table
= NULL
;
3480 prn
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
3481 if (bgp_node_has_bgp_path_info_data(prn
)) {
3482 table
= bgp_node_get_bgp_table_info(prn
);
3484 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3485 bgp
, prd
, table
, p
, new);
3487 bgp_unlock_node(prn
);
3491 /* If maximum prefix count is configured and current prefix
3493 if (bgp_maximum_prefix_overflow(peer
, afi
, safi
, 0))
3496 /* If this is an EVPN route, process for import. */
3497 if (safi
== SAFI_EVPN
)
3498 bgp_evpn_import_route(bgp
, afi
, safi
, p
, new);
3500 /* Process change. */
3501 bgp_process(bgp
, rn
, afi
, safi
);
3503 if (SAFI_UNICAST
== safi
3504 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3505 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3506 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
3508 if ((SAFI_MPLS_VPN
== safi
)
3509 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3511 vpn_leak_to_vrf_update(bgp
, new);
3514 if (SAFI_MPLS_VPN
== safi
) {
3515 mpls_label_t label_decoded
= decode_label(label
);
3517 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3518 sub_type
, &label_decoded
);
3520 if (SAFI_ENCAP
== safi
) {
3521 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3528 /* This BGP update is filtered. Log the reason then update BGP
3531 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3532 if (!peer
->rcvd_attr_printed
) {
3533 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3534 peer
->rcvd_attr_str
);
3535 peer
->rcvd_attr_printed
= 1;
3538 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3539 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3541 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
3542 peer
->host
, pfx_buf
, reason
);
3546 /* If this is an EVPN route, un-import it as it is now filtered.
3548 if (safi
== SAFI_EVPN
)
3549 bgp_evpn_unimport_route(bgp
, afi
, safi
, p
, pi
);
3551 if (SAFI_UNICAST
== safi
3552 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3553 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3555 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
3557 if ((SAFI_MPLS_VPN
== safi
)
3558 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3560 vpn_leak_to_vrf_withdraw(bgp
, pi
);
3563 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
3566 bgp_unlock_node(rn
);
3570 * Filtered update is treated as an implicit withdrawal (see
3572 * a few lines above)
3574 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3575 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3583 int bgp_withdraw(struct peer
*peer
, struct prefix
*p
, uint32_t addpath_id
,
3584 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
3585 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
3586 uint32_t num_labels
, struct bgp_route_evpn
*evpn
)
3589 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
3590 struct bgp_node
*rn
;
3591 struct bgp_path_info
*pi
;
3594 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3595 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3603 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
3605 /* If peer is soft reconfiguration enabled. Record input packet for
3606 * further calculation.
3608 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
3609 * routes that are filtered. This tanks out Quagga RS pretty badly due
3611 * the iteration over all RS clients.
3612 * Since we need to remove the entry from adj_in anyway, do that first
3614 * if there was no entry, we don't need to do anything more.
3616 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
3617 && peer
!= bgp
->peer_self
)
3618 if (!bgp_adj_in_unset(rn
, peer
, addpath_id
)) {
3619 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3620 bgp_debug_rdpfxpath2str(
3621 afi
, safi
, prd
, p
, label
, num_labels
,
3622 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3625 "%s withdrawing route %s not in adj-in",
3626 peer
->host
, pfx_buf
);
3628 bgp_unlock_node(rn
);
3632 /* Lookup withdrawn route. */
3633 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
3634 if (pi
->peer
== peer
&& pi
->type
== type
3635 && pi
->sub_type
== sub_type
3636 && pi
->addpath_rx_id
== addpath_id
)
3640 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3641 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3642 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3644 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer
->host
,
3648 /* Withdraw specified route from routing table. */
3649 if (pi
&& !CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3650 bgp_rib_withdraw(rn
, pi
, peer
, afi
, safi
, prd
);
3651 if (SAFI_UNICAST
== safi
3652 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3653 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3654 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
3656 if ((SAFI_MPLS_VPN
== safi
)
3657 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3659 vpn_leak_to_vrf_withdraw(bgp
, pi
);
3661 } else if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3662 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3663 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3665 zlog_debug("%s Can't find the route %s", peer
->host
, pfx_buf
);
3668 /* Unlock bgp_node_get() lock. */
3669 bgp_unlock_node(rn
);
3674 void bgp_default_originate(struct peer
*peer
, afi_t afi
, safi_t safi
,
3677 struct update_subgroup
*subgrp
;
3678 subgrp
= peer_subgroup(peer
, afi
, safi
);
3679 subgroup_default_originate(subgrp
, withdraw
);
3684 * bgp_stop_announce_route_timer
3686 void bgp_stop_announce_route_timer(struct peer_af
*paf
)
3688 if (!paf
->t_announce_route
)
3691 THREAD_TIMER_OFF(paf
->t_announce_route
);
3695 * bgp_announce_route_timer_expired
3697 * Callback that is invoked when the route announcement timer for a
3700 static int bgp_announce_route_timer_expired(struct thread
*t
)
3702 struct peer_af
*paf
;
3705 paf
= THREAD_ARG(t
);
3708 if (peer
->status
!= Established
)
3711 if (!peer
->afc_nego
[paf
->afi
][paf
->safi
])
3714 peer_af_announce_route(paf
, 1);
3719 * bgp_announce_route
3721 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
3723 void bgp_announce_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
3725 struct peer_af
*paf
;
3726 struct update_subgroup
*subgrp
;
3728 paf
= peer_af_find(peer
, afi
, safi
);
3731 subgrp
= PAF_SUBGRP(paf
);
3734 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
3735 * or a refresh has already been triggered.
3737 if (!subgrp
|| paf
->t_announce_route
)
3741 * Start a timer to stagger/delay the announce. This serves
3742 * two purposes - announcement can potentially be combined for
3743 * multiple peers and the announcement doesn't happen in the
3746 thread_add_timer_msec(bm
->master
, bgp_announce_route_timer_expired
, paf
,
3747 (subgrp
->peer_count
== 1)
3748 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
3749 : BGP_ANNOUNCE_ROUTE_DELAY_MS
,
3750 &paf
->t_announce_route
);
3754 * Announce routes from all AF tables to a peer.
3756 * This should ONLY be called when there is a need to refresh the
3757 * routes to the peer based on a policy change for this peer alone
3758 * or a route refresh request received from the peer.
3759 * The operation will result in splitting the peer from its existing
3760 * subgroups and putting it in new subgroups.
3762 void bgp_announce_route_all(struct peer
*peer
)
3767 FOREACH_AFI_SAFI (afi
, safi
)
3768 bgp_announce_route(peer
, afi
, safi
);
3771 static void bgp_soft_reconfig_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
3772 struct bgp_table
*table
,
3773 struct prefix_rd
*prd
)
3776 struct bgp_node
*rn
;
3777 struct bgp_adj_in
*ain
;
3780 table
= peer
->bgp
->rib
[afi
][safi
];
3782 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
3783 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
3784 if (ain
->peer
!= peer
)
3787 struct bgp_path_info
*pi
=
3788 bgp_node_get_bgp_path_info(rn
);
3789 uint32_t num_labels
= 0;
3790 mpls_label_t
*label_pnt
= NULL
;
3791 struct bgp_route_evpn evpn
;
3793 if (pi
&& pi
->extra
)
3794 num_labels
= pi
->extra
->num_labels
;
3796 label_pnt
= &pi
->extra
->label
[0];
3798 memcpy(&evpn
, &pi
->attr
->evpn_overlay
,
3801 memset(&evpn
, 0, sizeof(evpn
));
3803 ret
= bgp_update(peer
, &rn
->p
, ain
->addpath_rx_id
,
3804 ain
->attr
, afi
, safi
, ZEBRA_ROUTE_BGP
,
3805 BGP_ROUTE_NORMAL
, prd
, label_pnt
,
3806 num_labels
, 1, &evpn
);
3809 bgp_unlock_node(rn
);
3815 void bgp_soft_reconfig_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
3817 struct bgp_node
*rn
;
3818 struct bgp_table
*table
;
3820 if (peer
->status
!= Established
)
3823 if ((safi
!= SAFI_MPLS_VPN
) && (safi
!= SAFI_ENCAP
)
3824 && (safi
!= SAFI_EVPN
))
3825 bgp_soft_reconfig_table(peer
, afi
, safi
, NULL
, NULL
);
3827 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
3828 rn
= bgp_route_next(rn
)) {
3829 table
= bgp_node_get_bgp_table_info(rn
);
3830 if (table
!= NULL
) {
3831 struct prefix_rd prd
;
3833 prd
.family
= AF_UNSPEC
;
3835 memcpy(&prd
.val
, rn
->p
.u
.val
, 8);
3837 bgp_soft_reconfig_table(peer
, afi
, safi
, table
,
3844 struct bgp_clear_node_queue
{
3845 struct bgp_node
*rn
;
3848 static wq_item_status
bgp_clear_route_node(struct work_queue
*wq
, void *data
)
3850 struct bgp_clear_node_queue
*cnq
= data
;
3851 struct bgp_node
*rn
= cnq
->rn
;
3852 struct peer
*peer
= wq
->spec
.data
;
3853 struct bgp_path_info
*pi
;
3855 afi_t afi
= bgp_node_table(rn
)->afi
;
3856 safi_t safi
= bgp_node_table(rn
)->safi
;
3861 /* It is possible that we have multiple paths for a prefix from a peer
3862 * if that peer is using AddPath.
3864 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
3865 if (pi
->peer
!= peer
)
3868 /* graceful restart STALE flag set. */
3869 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_NSF_WAIT
)
3870 && peer
->nsf
[afi
][safi
]
3871 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
3872 && !CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
3873 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_STALE
);
3875 /* If this is an EVPN route, process for
3877 if (safi
== SAFI_EVPN
)
3878 bgp_evpn_unimport_route(bgp
, afi
, safi
, &rn
->p
,
3880 /* Handle withdraw for VRF route-leaking and L3VPN */
3881 if (SAFI_UNICAST
== safi
3882 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
||
3883 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3884 vpn_leak_from_vrf_withdraw(bgp_get_default(),
3887 if (SAFI_MPLS_VPN
== safi
&&
3888 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
3889 vpn_leak_to_vrf_withdraw(bgp
, pi
);
3892 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
3898 static void bgp_clear_node_queue_del(struct work_queue
*wq
, void *data
)
3900 struct bgp_clear_node_queue
*cnq
= data
;
3901 struct bgp_node
*rn
= cnq
->rn
;
3902 struct bgp_table
*table
= bgp_node_table(rn
);
3904 bgp_unlock_node(rn
);
3905 bgp_table_unlock(table
);
3906 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE
, cnq
);
3909 static void bgp_clear_node_complete(struct work_queue
*wq
)
3911 struct peer
*peer
= wq
->spec
.data
;
3913 /* Tickle FSM to start moving again */
3914 BGP_EVENT_ADD(peer
, Clearing_Completed
);
3916 peer_unlock(peer
); /* bgp_clear_route */
3919 static void bgp_clear_node_queue_init(struct peer
*peer
)
3921 char wname
[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
3923 snprintf(wname
, sizeof(wname
), "clear %s", peer
->host
);
3924 #undef CLEAR_QUEUE_NAME_LEN
3926 peer
->clear_node_queue
= work_queue_new(bm
->master
, wname
);
3927 peer
->clear_node_queue
->spec
.hold
= 10;
3928 peer
->clear_node_queue
->spec
.workfunc
= &bgp_clear_route_node
;
3929 peer
->clear_node_queue
->spec
.del_item_data
= &bgp_clear_node_queue_del
;
3930 peer
->clear_node_queue
->spec
.completion_func
= &bgp_clear_node_complete
;
3931 peer
->clear_node_queue
->spec
.max_retries
= 0;
3933 /* we only 'lock' this peer reference when the queue is actually active
3935 peer
->clear_node_queue
->spec
.data
= peer
;
3938 static void bgp_clear_route_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
3939 struct bgp_table
*table
)
3941 struct bgp_node
*rn
;
3942 int force
= bm
->process_main_queue
? 0 : 1;
3945 table
= peer
->bgp
->rib
[afi
][safi
];
3947 /* If still no table => afi/safi isn't configured at all or smth. */
3951 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
3952 struct bgp_path_info
*pi
, *next
;
3953 struct bgp_adj_in
*ain
;
3954 struct bgp_adj_in
*ain_next
;
3956 /* XXX:TODO: This is suboptimal, every non-empty route_node is
3957 * queued for every clearing peer, regardless of whether it is
3958 * relevant to the peer at hand.
3960 * Overview: There are 3 different indices which need to be
3961 * scrubbed, potentially, when a peer is removed:
3963 * 1 peer's routes visible via the RIB (ie accepted routes)
3964 * 2 peer's routes visible by the (optional) peer's adj-in index
3965 * 3 other routes visible by the peer's adj-out index
3967 * 3 there is no hurry in scrubbing, once the struct peer is
3968 * removed from bgp->peer, we could just GC such deleted peer's
3969 * adj-outs at our leisure.
3971 * 1 and 2 must be 'scrubbed' in some way, at least made
3972 * invisible via RIB index before peer session is allowed to be
3973 * brought back up. So one needs to know when such a 'search' is
3978 * - there'd be a single global queue or a single RIB walker
3979 * - rather than tracking which route_nodes still need to be
3980 * examined on a peer basis, we'd track which peers still
3983 * Given that our per-peer prefix-counts now should be reliable,
3984 * this may actually be achievable. It doesn't seem to be a huge
3985 * problem at this time,
3987 * It is possible that we have multiple paths for a prefix from
3989 * if that peer is using AddPath.
3993 ain_next
= ain
->next
;
3995 if (ain
->peer
== peer
) {
3996 bgp_adj_in_remove(rn
, ain
);
3997 bgp_unlock_node(rn
);
4003 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= next
) {
4005 if (pi
->peer
!= peer
)
4009 bgp_path_info_reap(rn
, pi
);
4011 struct bgp_clear_node_queue
*cnq
;
4013 /* both unlocked in bgp_clear_node_queue_del */
4014 bgp_table_lock(bgp_node_table(rn
));
4017 MTYPE_BGP_CLEAR_NODE_QUEUE
,
4018 sizeof(struct bgp_clear_node_queue
));
4020 work_queue_add(peer
->clear_node_queue
, cnq
);
4028 void bgp_clear_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4030 struct bgp_node
*rn
;
4031 struct bgp_table
*table
;
4033 if (peer
->clear_node_queue
== NULL
)
4034 bgp_clear_node_queue_init(peer
);
4036 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
4037 * Idle until it receives a Clearing_Completed event. This protects
4038 * against peers which flap faster than we can we clear, which could
4041 * a) race with routes from the new session being installed before
4042 * clear_route_node visits the node (to delete the route of that
4044 * b) resource exhaustion, clear_route_node likely leads to an entry
4045 * on the process_main queue. Fast-flapping could cause that queue
4049 /* lock peer in assumption that clear-node-queue will get nodes; if so,
4050 * the unlock will happen upon work-queue completion; other wise, the
4051 * unlock happens at the end of this function.
4053 if (!peer
->clear_node_queue
->thread
)
4056 if (safi
!= SAFI_MPLS_VPN
&& safi
!= SAFI_ENCAP
&& safi
!= SAFI_EVPN
)
4057 bgp_clear_route_table(peer
, afi
, safi
, NULL
);
4059 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4060 rn
= bgp_route_next(rn
)) {
4061 table
= bgp_node_get_bgp_table_info(rn
);
4065 bgp_clear_route_table(peer
, afi
, safi
, table
);
4068 /* unlock if no nodes got added to the clear-node-queue. */
4069 if (!peer
->clear_node_queue
->thread
)
4073 void bgp_clear_route_all(struct peer
*peer
)
4078 FOREACH_AFI_SAFI (afi
, safi
)
4079 bgp_clear_route(peer
, afi
, safi
);
4082 rfapiProcessPeerDown(peer
);
4086 void bgp_clear_adj_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
4088 struct bgp_table
*table
;
4089 struct bgp_node
*rn
;
4090 struct bgp_adj_in
*ain
;
4091 struct bgp_adj_in
*ain_next
;
4093 table
= peer
->bgp
->rib
[afi
][safi
];
4095 /* It is possible that we have multiple paths for a prefix from a peer
4096 * if that peer is using AddPath.
4098 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
4102 ain_next
= ain
->next
;
4104 if (ain
->peer
== peer
) {
4105 bgp_adj_in_remove(rn
, ain
);
4106 bgp_unlock_node(rn
);
4114 void bgp_clear_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4116 struct bgp_node
*rn
;
4117 struct bgp_path_info
*pi
;
4118 struct bgp_table
*table
;
4120 if (safi
== SAFI_MPLS_VPN
) {
4121 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4122 rn
= bgp_route_next(rn
)) {
4123 struct bgp_node
*rm
;
4125 /* look for neighbor in tables */
4126 table
= bgp_node_get_bgp_table_info(rn
);
4130 for (rm
= bgp_table_top(table
); rm
;
4131 rm
= bgp_route_next(rm
))
4132 for (pi
= bgp_node_get_bgp_path_info(rm
); pi
;
4134 if (pi
->peer
!= peer
)
4136 if (!CHECK_FLAG(pi
->flags
,
4140 bgp_rib_remove(rm
, pi
, peer
, afi
, safi
);
4145 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4146 rn
= bgp_route_next(rn
))
4147 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
;
4149 if (pi
->peer
!= peer
)
4151 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
4153 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
4159 static void bgp_cleanup_table(struct bgp
*bgp
, struct bgp_table
*table
,
4162 struct bgp_node
*rn
;
4163 struct bgp_path_info
*pi
;
4164 struct bgp_path_info
*next
;
4166 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
4167 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= next
) {
4169 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)
4170 && pi
->type
== ZEBRA_ROUTE_BGP
4171 && (pi
->sub_type
== BGP_ROUTE_NORMAL
4172 || pi
->sub_type
== BGP_ROUTE_AGGREGATE
4173 || pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
4175 if (bgp_fibupd_safi(safi
))
4176 bgp_zebra_withdraw(&rn
->p
, pi
, bgp
,
4178 bgp_path_info_reap(rn
, pi
);
4183 /* Delete all kernel routes. */
4184 void bgp_cleanup_routes(struct bgp
*bgp
)
4187 struct bgp_node
*rn
;
4188 struct bgp_table
*table
;
4190 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
4191 if (afi
== AFI_L2VPN
)
4193 bgp_cleanup_table(bgp
, bgp
->rib
[afi
][SAFI_UNICAST
],
4196 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
4198 if (afi
!= AFI_L2VPN
) {
4200 safi
= SAFI_MPLS_VPN
;
4201 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4202 rn
= bgp_route_next(rn
)) {
4203 table
= bgp_node_get_bgp_table_info(rn
);
4204 if (table
!= NULL
) {
4205 bgp_cleanup_table(bgp
, table
, safi
);
4206 bgp_table_finish(&table
);
4207 bgp_node_set_bgp_table_info(rn
, NULL
);
4208 bgp_unlock_node(rn
);
4212 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4213 rn
= bgp_route_next(rn
)) {
4214 table
= bgp_node_get_bgp_table_info(rn
);
4215 if (table
!= NULL
) {
4216 bgp_cleanup_table(bgp
, table
, safi
);
4217 bgp_table_finish(&table
);
4218 bgp_node_set_bgp_table_info(rn
, NULL
);
4219 bgp_unlock_node(rn
);
4224 for (rn
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); rn
;
4225 rn
= bgp_route_next(rn
)) {
4226 table
= bgp_node_get_bgp_table_info(rn
);
4227 if (table
!= NULL
) {
4228 bgp_cleanup_table(bgp
, table
, SAFI_EVPN
);
4229 bgp_table_finish(&table
);
4230 bgp_node_set_bgp_table_info(rn
, NULL
);
4231 bgp_unlock_node(rn
);
4236 void bgp_reset(void)
4239 bgp_zclient_reset();
4240 access_list_reset();
4241 prefix_list_reset();
4244 static int bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
4246 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
4247 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
4248 PEER_CAP_ADDPATH_AF_TX_RCV
));
4251 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
4253 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
4254 struct bgp_nlri
*packet
)
4263 int addpath_encoded
;
4264 uint32_t addpath_id
;
4267 lim
= pnt
+ packet
->length
;
4269 safi
= packet
->safi
;
4271 addpath_encoded
= bgp_addpath_encode_rx(peer
, afi
, safi
);
4273 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
4274 syntactic validity. If the field is syntactically incorrect,
4275 then the Error Subcode is set to Invalid Network Field. */
4276 for (; pnt
< lim
; pnt
+= psize
) {
4277 /* Clear prefix structure. */
4278 memset(&p
, 0, sizeof(struct prefix
));
4280 if (addpath_encoded
) {
4282 /* When packet overflow occurs return immediately. */
4283 if (pnt
+ BGP_ADDPATH_ID_LEN
> lim
)
4286 addpath_id
= ntohl(*((uint32_t *)pnt
));
4287 pnt
+= BGP_ADDPATH_ID_LEN
;
4290 /* Fetch prefix length. */
4291 p
.prefixlen
= *pnt
++;
4292 /* afi/safi validity already verified by caller,
4293 * bgp_update_receive */
4294 p
.family
= afi2family(afi
);
4296 /* Prefix length check. */
4297 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
4300 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
4301 peer
->host
, p
.prefixlen
, packet
->afi
);
4305 /* Packet size overflow check. */
4306 psize
= PSIZE(p
.prefixlen
);
4308 /* When packet overflow occur return immediately. */
4309 if (pnt
+ psize
> lim
) {
4312 "%s [Error] Update packet error (prefix length %d overflows packet)",
4313 peer
->host
, p
.prefixlen
);
4317 /* Defensive coding, double-check the psize fits in a struct
4319 if (psize
> (ssize_t
)sizeof(p
.u
)) {
4322 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
4323 peer
->host
, p
.prefixlen
, sizeof(p
.u
));
4327 /* Fetch prefix from NLRI packet. */
4328 memcpy(p
.u
.val
, pnt
, psize
);
4330 /* Check address. */
4331 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
4332 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
4333 /* From RFC4271 Section 6.3:
4335 * If a prefix in the NLRI field is semantically
4337 * (e.g., an unexpected multicast IP address),
4339 * be logged locally, and the prefix SHOULD be
4344 "%s: IPv4 unicast NLRI is multicast address %s, ignoring",
4345 peer
->host
, inet_ntoa(p
.u
.prefix4
));
4350 /* Check address. */
4351 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
4352 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4357 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
4359 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4364 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
4369 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
4371 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4378 /* Normal process. */
4380 ret
= bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
4381 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
4382 NULL
, NULL
, 0, 0, NULL
);
4384 ret
= bgp_withdraw(peer
, &p
, addpath_id
, attr
, afi
,
4385 safi
, ZEBRA_ROUTE_BGP
,
4386 BGP_ROUTE_NORMAL
, NULL
, NULL
, 0,
4389 /* Address family configuration mismatch or maximum-prefix count
4395 /* Packet length consistency check. */
4399 "%s [Error] Update packet error (prefix length mismatch with total length)",
4407 static struct bgp_static
*bgp_static_new(void)
4409 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
4412 static void bgp_static_free(struct bgp_static
*bgp_static
)
4414 if (bgp_static
->rmap
.name
)
4415 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
4416 if (bgp_static
->eth_s_id
)
4417 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
4418 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
4421 void bgp_static_update(struct bgp
*bgp
, struct prefix
*p
,
4422 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
4424 struct bgp_node
*rn
;
4425 struct bgp_path_info
*pi
;
4426 struct bgp_path_info
*new;
4427 struct bgp_path_info rmap_path
;
4429 struct attr
*attr_new
;
4432 int vnc_implicit_withdraw
= 0;
4439 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4441 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4443 attr
.nexthop
= bgp_static
->igpnexthop
;
4444 attr
.med
= bgp_static
->igpmetric
;
4445 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4447 if (bgp_static
->atomic
)
4448 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
4450 /* Store label index, if required. */
4451 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
4452 attr
.label_index
= bgp_static
->label_index
;
4453 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
4456 /* Apply route-map. */
4457 if (bgp_static
->rmap
.name
) {
4458 struct attr attr_tmp
= attr
;
4460 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
4461 rmap_path
.peer
= bgp
->peer_self
;
4462 rmap_path
.attr
= &attr_tmp
;
4464 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4466 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
,
4469 bgp
->peer_self
->rmap_type
= 0;
4471 if (ret
== RMAP_DENYMATCH
) {
4472 /* Free uninterned attribute. */
4473 bgp_attr_flush(&attr_tmp
);
4475 /* Unintern original. */
4476 aspath_unintern(&attr
.aspath
);
4477 bgp_static_withdraw(bgp
, p
, afi
, safi
);
4481 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4482 bgp_attr_add_gshut_community(&attr_tmp
);
4484 attr_new
= bgp_attr_intern(&attr_tmp
);
4487 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4488 bgp_attr_add_gshut_community(&attr
);
4490 attr_new
= bgp_attr_intern(&attr
);
4493 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4494 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4495 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4499 if (attrhash_cmp(pi
->attr
, attr_new
)
4500 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
4501 && !bgp_flag_check(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
4502 bgp_unlock_node(rn
);
4503 bgp_attr_unintern(&attr_new
);
4504 aspath_unintern(&attr
.aspath
);
4507 /* The attribute is changed. */
4508 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_ATTR_CHANGED
);
4510 /* Rewrite BGP route information. */
4511 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
4512 bgp_path_info_restore(rn
, pi
);
4514 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4516 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4517 && (safi
== SAFI_UNICAST
)) {
4518 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
4520 * Implicit withdraw case.
4521 * We have to do this before pi is
4524 ++vnc_implicit_withdraw
;
4525 vnc_import_bgp_del_route(bgp
, p
, pi
);
4526 vnc_import_bgp_exterior_del_route(
4531 bgp_attr_unintern(&pi
->attr
);
4532 pi
->attr
= attr_new
;
4533 pi
->uptime
= bgp_clock();
4535 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4536 && (safi
== SAFI_UNICAST
)) {
4537 if (vnc_implicit_withdraw
) {
4538 vnc_import_bgp_add_route(bgp
, p
, pi
);
4539 vnc_import_bgp_exterior_add_route(
4545 /* Nexthop reachability check. */
4546 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4547 && (safi
== SAFI_UNICAST
4548 || safi
== SAFI_LABELED_UNICAST
)) {
4550 struct bgp
*bgp_nexthop
= bgp
;
4552 if (pi
->extra
&& pi
->extra
->bgp_orig
)
4553 bgp_nexthop
= pi
->extra
->bgp_orig
;
4555 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
,
4557 bgp_path_info_set_flag(rn
, pi
,
4560 if (BGP_DEBUG(nht
, NHT
)) {
4561 char buf1
[INET6_ADDRSTRLEN
];
4562 inet_ntop(p
->family
,
4566 "%s(%s): Route not in table, not advertising",
4567 __FUNCTION__
, buf1
);
4569 bgp_path_info_unset_flag(
4570 rn
, pi
, BGP_PATH_VALID
);
4573 /* Delete the NHT structure if any, if we're
4575 * enabling/disabling import check. We
4576 * deregister the route
4577 * from NHT to avoid overloading NHT and the
4578 * process interaction
4580 bgp_unlink_nexthop(pi
);
4581 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_VALID
);
4583 /* Process change. */
4584 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
4585 bgp_process(bgp
, rn
, afi
, safi
);
4587 if (SAFI_UNICAST
== safi
4588 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4590 == BGP_INSTANCE_TYPE_DEFAULT
)) {
4591 vpn_leak_from_vrf_update(bgp_get_default(), bgp
,
4595 bgp_unlock_node(rn
);
4596 aspath_unintern(&attr
.aspath
);
4601 /* Make new BGP info. */
4602 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
4604 /* Nexthop reachability check. */
4605 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4606 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
4607 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, new, NULL
, 0))
4608 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
4610 if (BGP_DEBUG(nht
, NHT
)) {
4611 char buf1
[INET6_ADDRSTRLEN
];
4612 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
4615 "%s(%s): Route not in table, not advertising",
4616 __FUNCTION__
, buf1
);
4618 bgp_path_info_unset_flag(rn
, new, BGP_PATH_VALID
);
4621 /* Delete the NHT structure if any, if we're toggling between
4622 * enabling/disabling import check. We deregister the route
4623 * from NHT to avoid overloading NHT and the process interaction
4625 bgp_unlink_nexthop(new);
4627 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
4630 /* Aggregate address increment. */
4631 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4633 /* Register new BGP information. */
4634 bgp_path_info_add(rn
, new);
4636 /* route_node_get lock */
4637 bgp_unlock_node(rn
);
4639 /* Process change. */
4640 bgp_process(bgp
, rn
, afi
, safi
);
4642 if (SAFI_UNICAST
== safi
4643 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4644 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4645 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
4648 /* Unintern original. */
4649 aspath_unintern(&attr
.aspath
);
4652 void bgp_static_withdraw(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
4655 struct bgp_node
*rn
;
4656 struct bgp_path_info
*pi
;
4658 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4660 /* Check selected route and self inserted route. */
4661 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4662 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4663 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4666 /* Withdraw static BGP route from routing table. */
4668 if (SAFI_UNICAST
== safi
4669 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4670 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4671 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
4673 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4674 bgp_unlink_nexthop(pi
);
4675 bgp_path_info_delete(rn
, pi
);
4676 bgp_process(bgp
, rn
, afi
, safi
);
4679 /* Unlock bgp_node_lookup. */
4680 bgp_unlock_node(rn
);
4684 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
4686 static void bgp_static_withdraw_safi(struct bgp
*bgp
, struct prefix
*p
,
4687 afi_t afi
, safi_t safi
,
4688 struct prefix_rd
*prd
)
4690 struct bgp_node
*rn
;
4691 struct bgp_path_info
*pi
;
4693 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4695 /* Check selected route and self inserted route. */
4696 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4697 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4698 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4701 /* Withdraw static BGP route from routing table. */
4704 rfapiProcessWithdraw(
4705 pi
->peer
, NULL
, p
, prd
, pi
->attr
, afi
, safi
, pi
->type
,
4706 1); /* Kill, since it is an administrative change */
4708 if (SAFI_MPLS_VPN
== safi
4709 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4710 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4712 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4713 bgp_path_info_delete(rn
, pi
);
4714 bgp_process(bgp
, rn
, afi
, safi
);
4717 /* Unlock bgp_node_lookup. */
4718 bgp_unlock_node(rn
);
4721 static void bgp_static_update_safi(struct bgp
*bgp
, struct prefix
*p
,
4722 struct bgp_static
*bgp_static
, afi_t afi
,
4725 struct bgp_node
*rn
;
4726 struct bgp_path_info
*new;
4727 struct attr
*attr_new
;
4728 struct attr attr
= {0};
4729 struct bgp_path_info
*pi
;
4731 mpls_label_t label
= 0;
4733 uint32_t num_labels
= 0;
4738 if (bgp_static
->label
!= MPLS_INVALID_LABEL
)
4740 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
4743 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4745 attr
.nexthop
= bgp_static
->igpnexthop
;
4746 attr
.med
= bgp_static
->igpmetric
;
4747 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4749 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
4750 || (safi
== SAFI_ENCAP
)) {
4751 if (afi
== AFI_IP
) {
4752 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
4753 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
4756 if (afi
== AFI_L2VPN
) {
4757 if (bgp_static
->gatewayIp
.family
== AF_INET
)
4759 bgp_static
->gatewayIp
.u
.prefix4
.s_addr
;
4760 else if (bgp_static
->gatewayIp
.family
== AF_INET6
)
4761 memcpy(&(add
.ipv6
), &(bgp_static
->gatewayIp
.u
.prefix6
),
4762 sizeof(struct in6_addr
));
4763 overlay_index_update(&attr
, bgp_static
->eth_s_id
, &add
);
4764 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
4765 struct bgp_encap_type_vxlan bet
;
4766 memset(&bet
, 0, sizeof(struct bgp_encap_type_vxlan
));
4767 bet
.vnid
= p
->u
.prefix_evpn
.prefix_addr
.eth_tag
;
4768 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
4770 if (bgp_static
->router_mac
) {
4771 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
4774 /* Apply route-map. */
4775 if (bgp_static
->rmap
.name
) {
4776 struct attr attr_tmp
= attr
;
4777 struct bgp_path_info rmap_path
;
4780 rmap_path
.peer
= bgp
->peer_self
;
4781 rmap_path
.attr
= &attr_tmp
;
4783 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4785 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
,
4788 bgp
->peer_self
->rmap_type
= 0;
4790 if (ret
== RMAP_DENYMATCH
) {
4791 /* Free uninterned attribute. */
4792 bgp_attr_flush(&attr_tmp
);
4794 /* Unintern original. */
4795 aspath_unintern(&attr
.aspath
);
4796 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
4801 attr_new
= bgp_attr_intern(&attr_tmp
);
4803 attr_new
= bgp_attr_intern(&attr
);
4806 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4807 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4808 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4812 memset(&add
, 0, sizeof(union gw_addr
));
4813 if (attrhash_cmp(pi
->attr
, attr_new
)
4814 && overlay_index_equal(afi
, pi
, bgp_static
->eth_s_id
, &add
)
4815 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
4816 bgp_unlock_node(rn
);
4817 bgp_attr_unintern(&attr_new
);
4818 aspath_unintern(&attr
.aspath
);
4821 /* The attribute is changed. */
4822 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_ATTR_CHANGED
);
4824 /* Rewrite BGP route information. */
4825 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
4826 bgp_path_info_restore(rn
, pi
);
4828 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4829 bgp_attr_unintern(&pi
->attr
);
4830 pi
->attr
= attr_new
;
4831 pi
->uptime
= bgp_clock();
4834 label
= decode_label(&pi
->extra
->label
[0]);
4837 /* Process change. */
4838 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
4839 bgp_process(bgp
, rn
, afi
, safi
);
4841 if (SAFI_MPLS_VPN
== safi
4842 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4843 vpn_leak_to_vrf_update(bgp
, pi
);
4846 rfapiProcessUpdate(pi
->peer
, NULL
, p
, &bgp_static
->prd
,
4847 pi
->attr
, afi
, safi
, pi
->type
,
4848 pi
->sub_type
, &label
);
4850 bgp_unlock_node(rn
);
4851 aspath_unintern(&attr
.aspath
);
4857 /* Make new BGP info. */
4858 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
4860 SET_FLAG(new->flags
, BGP_PATH_VALID
);
4861 new->extra
= bgp_path_info_extra_new();
4863 new->extra
->label
[0] = bgp_static
->label
;
4864 new->extra
->num_labels
= num_labels
;
4867 label
= decode_label(&bgp_static
->label
);
4870 /* Aggregate address increment. */
4871 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4873 /* Register new BGP information. */
4874 bgp_path_info_add(rn
, new);
4875 /* route_node_get lock */
4876 bgp_unlock_node(rn
);
4878 /* Process change. */
4879 bgp_process(bgp
, rn
, afi
, safi
);
4881 if (SAFI_MPLS_VPN
== safi
4882 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4883 vpn_leak_to_vrf_update(bgp
, new);
4886 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
4887 safi
, new->type
, new->sub_type
, &label
);
4890 /* Unintern original. */
4891 aspath_unintern(&attr
.aspath
);
4894 /* Configure static BGP network. When user don't run zebra, static
4895 route should be installed as valid. */
4896 static int bgp_static_set(struct vty
*vty
, const char *negate
,
4897 const char *ip_str
, afi_t afi
, safi_t safi
,
4898 const char *rmap
, int backdoor
, uint32_t label_index
)
4900 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
4903 struct bgp_static
*bgp_static
;
4904 struct bgp_node
*rn
;
4905 uint8_t need_update
= 0;
4907 /* Convert IP prefix string to struct prefix. */
4908 ret
= str2prefix(ip_str
, &p
);
4910 vty_out(vty
, "%% Malformed prefix\n");
4911 return CMD_WARNING_CONFIG_FAILED
;
4913 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4914 vty_out(vty
, "%% Malformed prefix (link-local address)\n");
4915 return CMD_WARNING_CONFIG_FAILED
;
4922 /* Set BGP static route configuration. */
4923 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
4926 vty_out(vty
, "%% Can't find static route specified\n");
4927 return CMD_WARNING_CONFIG_FAILED
;
4930 bgp_static
= bgp_node_get_bgp_static_info(rn
);
4932 if ((label_index
!= BGP_INVALID_LABEL_INDEX
)
4933 && (label_index
!= bgp_static
->label_index
)) {
4935 "%% label-index doesn't match static route\n");
4936 return CMD_WARNING_CONFIG_FAILED
;
4939 if ((rmap
&& bgp_static
->rmap
.name
)
4940 && strcmp(rmap
, bgp_static
->rmap
.name
)) {
4942 "%% route-map name doesn't match static route\n");
4943 return CMD_WARNING_CONFIG_FAILED
;
4946 /* Update BGP RIB. */
4947 if (!bgp_static
->backdoor
)
4948 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
4950 /* Clear configuration. */
4951 bgp_static_free(bgp_static
);
4952 bgp_node_set_bgp_static_info(rn
, NULL
);
4953 bgp_unlock_node(rn
);
4954 bgp_unlock_node(rn
);
4957 /* Set BGP static route configuration. */
4958 rn
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
4960 bgp_static
= bgp_node_get_bgp_static_info(rn
);
4962 /* Configuration change. */
4963 /* Label index cannot be changed. */
4964 if (bgp_static
->label_index
!= label_index
) {
4965 vty_out(vty
, "%% cannot change label-index\n");
4966 return CMD_WARNING_CONFIG_FAILED
;
4969 /* Check previous routes are installed into BGP. */
4970 if (bgp_static
->valid
4971 && bgp_static
->backdoor
!= backdoor
)
4974 bgp_static
->backdoor
= backdoor
;
4977 if (bgp_static
->rmap
.name
)
4978 XFREE(MTYPE_ROUTE_MAP_NAME
,
4979 bgp_static
->rmap
.name
);
4980 bgp_static
->rmap
.name
=
4981 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
4982 bgp_static
->rmap
.map
=
4983 route_map_lookup_by_name(rmap
);
4985 if (bgp_static
->rmap
.name
)
4986 XFREE(MTYPE_ROUTE_MAP_NAME
,
4987 bgp_static
->rmap
.name
);
4988 bgp_static
->rmap
.name
= NULL
;
4989 bgp_static
->rmap
.map
= NULL
;
4990 bgp_static
->valid
= 0;
4992 bgp_unlock_node(rn
);
4994 /* New configuration. */
4995 bgp_static
= bgp_static_new();
4996 bgp_static
->backdoor
= backdoor
;
4997 bgp_static
->valid
= 0;
4998 bgp_static
->igpmetric
= 0;
4999 bgp_static
->igpnexthop
.s_addr
= 0;
5000 bgp_static
->label_index
= label_index
;
5003 if (bgp_static
->rmap
.name
)
5004 XFREE(MTYPE_ROUTE_MAP_NAME
,
5005 bgp_static
->rmap
.name
);
5006 bgp_static
->rmap
.name
=
5007 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
5008 bgp_static
->rmap
.map
=
5009 route_map_lookup_by_name(rmap
);
5011 bgp_node_set_bgp_static_info(rn
, bgp_static
);
5014 bgp_static
->valid
= 1;
5016 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
5018 if (!bgp_static
->backdoor
)
5019 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
5025 void bgp_static_add(struct bgp
*bgp
)
5029 struct bgp_node
*rn
;
5030 struct bgp_node
*rm
;
5031 struct bgp_table
*table
;
5032 struct bgp_static
*bgp_static
;
5034 FOREACH_AFI_SAFI (afi
, safi
)
5035 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5036 rn
= bgp_route_next(rn
)) {
5037 if (!bgp_node_has_bgp_path_info_data(rn
))
5040 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5041 || (safi
== SAFI_EVPN
)) {
5042 table
= bgp_node_get_bgp_table_info(rn
);
5044 for (rm
= bgp_table_top(table
); rm
;
5045 rm
= bgp_route_next(rm
)) {
5047 bgp_node_get_bgp_static_info(
5049 bgp_static_update_safi(bgp
, &rm
->p
,
5056 bgp_node_get_bgp_static_info(rn
), afi
,
5062 /* Called from bgp_delete(). Delete all static routes from the BGP
5064 void bgp_static_delete(struct bgp
*bgp
)
5068 struct bgp_node
*rn
;
5069 struct bgp_node
*rm
;
5070 struct bgp_table
*table
;
5071 struct bgp_static
*bgp_static
;
5073 FOREACH_AFI_SAFI (afi
, safi
)
5074 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5075 rn
= bgp_route_next(rn
)) {
5076 if (!bgp_node_has_bgp_path_info_data(rn
))
5079 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5080 || (safi
== SAFI_EVPN
)) {
5081 table
= bgp_node_get_bgp_table_info(rn
);
5083 for (rm
= bgp_table_top(table
); rm
;
5084 rm
= bgp_route_next(rm
)) {
5086 bgp_node_get_bgp_static_info(
5091 bgp_static_withdraw_safi(
5092 bgp
, &rm
->p
, AFI_IP
, safi
,
5093 (struct prefix_rd
*)&rn
->p
);
5094 bgp_static_free(bgp_static
);
5095 bgp_node_set_bgp_static_info(rn
, NULL
);
5096 bgp_unlock_node(rn
);
5099 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5100 bgp_static_withdraw(bgp
, &rn
->p
, afi
, safi
);
5101 bgp_static_free(bgp_static
);
5102 bgp_node_set_bgp_static_info(rn
, NULL
);
5103 bgp_unlock_node(rn
);
5108 void bgp_static_redo_import_check(struct bgp
*bgp
)
5112 struct bgp_node
*rn
;
5113 struct bgp_node
*rm
;
5114 struct bgp_table
*table
;
5115 struct bgp_static
*bgp_static
;
5117 /* Use this flag to force reprocessing of the route */
5118 bgp_flag_set(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5119 FOREACH_AFI_SAFI (afi
, safi
) {
5120 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5121 rn
= bgp_route_next(rn
)) {
5122 if (!bgp_node_has_bgp_path_info_data(rn
))
5125 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5126 || (safi
== SAFI_EVPN
)) {
5127 table
= bgp_node_get_bgp_table_info(rn
);
5129 for (rm
= bgp_table_top(table
); rm
;
5130 rm
= bgp_route_next(rm
)) {
5132 bgp_node_get_bgp_static_info(
5134 bgp_static_update_safi(bgp
, &rm
->p
,
5139 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5140 bgp_static_update(bgp
, &rn
->p
, bgp_static
, afi
,
5145 bgp_flag_unset(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5148 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
5151 struct bgp_table
*table
;
5152 struct bgp_node
*rn
;
5153 struct bgp_path_info
*pi
;
5155 table
= bgp
->rib
[afi
][safi
];
5156 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
5157 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
5158 if (pi
->peer
== bgp
->peer_self
5159 && ((pi
->type
== ZEBRA_ROUTE_BGP
5160 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5161 || (pi
->type
!= ZEBRA_ROUTE_BGP
5163 == BGP_ROUTE_REDISTRIBUTE
))) {
5164 bgp_aggregate_decrement(bgp
, &rn
->p
, pi
, afi
,
5166 bgp_unlink_nexthop(pi
);
5167 bgp_path_info_delete(rn
, pi
);
5168 bgp_process(bgp
, rn
, afi
, safi
);
5175 * Purge all networks and redistributed routes from routing table.
5176 * Invoked upon the instance going down.
5178 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
5183 FOREACH_AFI_SAFI (afi
, safi
)
5184 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
5189 * Currently this is used to set static routes for VPN and ENCAP.
5190 * I think it can probably be factored with bgp_static_set.
5192 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5193 const char *ip_str
, const char *rd_str
,
5194 const char *label_str
, const char *rmap_str
,
5195 int evpn_type
, const char *esi
, const char *gwip
,
5196 const char *ethtag
, const char *routermac
)
5198 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5201 struct prefix_rd prd
;
5202 struct bgp_node
*prn
;
5203 struct bgp_node
*rn
;
5204 struct bgp_table
*table
;
5205 struct bgp_static
*bgp_static
;
5206 mpls_label_t label
= MPLS_INVALID_LABEL
;
5207 struct prefix gw_ip
;
5209 /* validate ip prefix */
5210 ret
= str2prefix(ip_str
, &p
);
5212 vty_out(vty
, "%% Malformed prefix\n");
5213 return CMD_WARNING_CONFIG_FAILED
;
5216 if ((afi
== AFI_L2VPN
)
5217 && (bgp_build_evpn_prefix(evpn_type
,
5218 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5219 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5220 return CMD_WARNING_CONFIG_FAILED
;
5223 ret
= str2prefix_rd(rd_str
, &prd
);
5225 vty_out(vty
, "%% Malformed rd\n");
5226 return CMD_WARNING_CONFIG_FAILED
;
5230 unsigned long label_val
;
5231 label_val
= strtoul(label_str
, NULL
, 10);
5232 encode_label(label_val
, &label
);
5235 if (safi
== SAFI_EVPN
) {
5236 if (esi
&& str2esi(esi
, NULL
) == 0) {
5237 vty_out(vty
, "%% Malformed ESI\n");
5238 return CMD_WARNING_CONFIG_FAILED
;
5240 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
5241 vty_out(vty
, "%% Malformed Router MAC\n");
5242 return CMD_WARNING_CONFIG_FAILED
;
5245 memset(&gw_ip
, 0, sizeof(struct prefix
));
5246 ret
= str2prefix(gwip
, &gw_ip
);
5248 vty_out(vty
, "%% Malformed GatewayIp\n");
5249 return CMD_WARNING_CONFIG_FAILED
;
5251 if ((gw_ip
.family
== AF_INET
5252 && is_evpn_prefix_ipaddr_v6(
5253 (struct prefix_evpn
*)&p
))
5254 || (gw_ip
.family
== AF_INET6
5255 && is_evpn_prefix_ipaddr_v4(
5256 (struct prefix_evpn
*)&p
))) {
5258 "%% GatewayIp family differs with IP prefix\n");
5259 return CMD_WARNING_CONFIG_FAILED
;
5263 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5264 if (!bgp_node_has_bgp_path_info_data(prn
))
5265 bgp_node_set_bgp_table_info(prn
,
5266 bgp_table_init(bgp
, afi
, safi
));
5267 table
= bgp_node_get_bgp_table_info(prn
);
5269 rn
= bgp_node_get(table
, &p
);
5271 if (bgp_node_has_bgp_path_info_data(rn
)) {
5272 vty_out(vty
, "%% Same network configuration exists\n");
5273 bgp_unlock_node(rn
);
5275 /* New configuration. */
5276 bgp_static
= bgp_static_new();
5277 bgp_static
->backdoor
= 0;
5278 bgp_static
->valid
= 0;
5279 bgp_static
->igpmetric
= 0;
5280 bgp_static
->igpnexthop
.s_addr
= 0;
5281 bgp_static
->label
= label
;
5282 bgp_static
->prd
= prd
;
5285 if (bgp_static
->rmap
.name
)
5286 XFREE(MTYPE_ROUTE_MAP_NAME
,
5287 bgp_static
->rmap
.name
);
5288 bgp_static
->rmap
.name
=
5289 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
5290 bgp_static
->rmap
.map
=
5291 route_map_lookup_by_name(rmap_str
);
5294 if (safi
== SAFI_EVPN
) {
5296 bgp_static
->eth_s_id
=
5298 sizeof(struct eth_segment_id
));
5299 str2esi(esi
, bgp_static
->eth_s_id
);
5302 bgp_static
->router_mac
=
5303 XCALLOC(MTYPE_ATTR
, ETH_ALEN
+ 1);
5304 (void)prefix_str2mac(routermac
,
5305 bgp_static
->router_mac
);
5308 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
5310 bgp_node_set_bgp_static_info(rn
, bgp_static
);
5312 bgp_static
->valid
= 1;
5313 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
5319 /* Configure static BGP network. */
5320 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5321 const char *ip_str
, const char *rd_str
,
5322 const char *label_str
, int evpn_type
, const char *esi
,
5323 const char *gwip
, const char *ethtag
)
5325 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5328 struct prefix_rd prd
;
5329 struct bgp_node
*prn
;
5330 struct bgp_node
*rn
;
5331 struct bgp_table
*table
;
5332 struct bgp_static
*bgp_static
;
5333 mpls_label_t label
= MPLS_INVALID_LABEL
;
5335 /* Convert IP prefix string to struct prefix. */
5336 ret
= str2prefix(ip_str
, &p
);
5338 vty_out(vty
, "%% Malformed prefix\n");
5339 return CMD_WARNING_CONFIG_FAILED
;
5342 if ((afi
== AFI_L2VPN
)
5343 && (bgp_build_evpn_prefix(evpn_type
,
5344 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5345 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5346 return CMD_WARNING_CONFIG_FAILED
;
5348 ret
= str2prefix_rd(rd_str
, &prd
);
5350 vty_out(vty
, "%% Malformed rd\n");
5351 return CMD_WARNING_CONFIG_FAILED
;
5355 unsigned long label_val
;
5356 label_val
= strtoul(label_str
, NULL
, 10);
5357 encode_label(label_val
, &label
);
5360 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5361 if (!bgp_node_has_bgp_path_info_data(prn
))
5362 bgp_node_set_bgp_table_info(prn
,
5363 bgp_table_init(bgp
, afi
, safi
));
5365 bgp_unlock_node(prn
);
5366 table
= bgp_node_get_bgp_table_info(prn
);
5368 rn
= bgp_node_lookup(table
, &p
);
5371 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
5373 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5374 bgp_static_free(bgp_static
);
5375 bgp_node_set_bgp_static_info(rn
, NULL
);
5376 bgp_unlock_node(rn
);
5377 bgp_unlock_node(rn
);
5379 vty_out(vty
, "%% Can't find the route\n");
5384 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
5385 const char *rmap_name
)
5387 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5388 struct bgp_rmap
*rmap
;
5390 rmap
= &bgp
->table_map
[afi
][safi
];
5393 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5394 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
5395 rmap
->map
= route_map_lookup_by_name(rmap_name
);
5398 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5403 if (bgp_fibupd_safi(safi
))
5404 bgp_zebra_announce_table(bgp
, afi
, safi
);
5409 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
5410 const char *rmap_name
)
5412 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5413 struct bgp_rmap
*rmap
;
5415 rmap
= &bgp
->table_map
[afi
][safi
];
5417 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5421 if (bgp_fibupd_safi(safi
))
5422 bgp_zebra_announce_table(bgp
, afi
, safi
);
5427 void bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
5430 if (bgp
->table_map
[afi
][safi
].name
) {
5431 vty_out(vty
, " table-map %s\n",
5432 bgp
->table_map
[afi
][safi
].name
);
5436 DEFUN (bgp_table_map
,
5439 "BGP table to RIB route download filter\n"
5440 "Name of the route map\n")
5443 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5444 argv
[idx_word
]->arg
);
5446 DEFUN (no_bgp_table_map
,
5447 no_bgp_table_map_cmd
,
5448 "no table-map WORD",
5450 "BGP table to RIB route download filter\n"
5451 "Name of the route map\n")
5454 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5455 argv
[idx_word
]->arg
);
5461 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
5462 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
5463 backdoor$backdoor}]",
5465 "Specify a network to announce via BGP\n"
5470 "Route-map to modify the attributes\n"
5471 "Name of the route map\n"
5472 "Label index to associate with the prefix\n"
5473 "Label index value\n"
5474 "Specify a BGP backdoor route\n")
5476 char addr_prefix_str
[BUFSIZ
];
5481 ret
= netmask_str2prefix_str(address_str
, netmask_str
,
5484 vty_out(vty
, "%% Inconsistent address and mask\n");
5485 return CMD_WARNING_CONFIG_FAILED
;
5489 return bgp_static_set(
5490 vty
, no
, address_str
? addr_prefix_str
: prefix_str
, AFI_IP
,
5491 bgp_node_safi(vty
), map_name
, backdoor
? 1 : 0,
5492 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5495 DEFPY(ipv6_bgp_network
,
5496 ipv6_bgp_network_cmd
,
5497 "[no] network X:X::X:X/M$prefix \
5498 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
5500 "Specify a network to announce via BGP\n"
5502 "Route-map to modify the attributes\n"
5503 "Name of the route map\n"
5504 "Label index to associate with the prefix\n"
5505 "Label index value\n")
5507 return bgp_static_set(
5508 vty
, no
, prefix_str
, AFI_IP6
, bgp_node_safi(vty
), map_name
, 0,
5509 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5512 /* Aggreagete address:
5514 advertise-map Set condition to advertise attribute
5515 as-set Generate AS set path information
5516 attribute-map Set attributes of aggregate
5517 route-map Set parameters of aggregate
5518 summary-only Filter more specific routes from updates
5519 suppress-map Conditionally filter more specific routes from updates
5522 struct bgp_aggregate
{
5523 /* Summary-only flag. */
5524 uint8_t summary_only
;
5526 /* AS set generation. */
5529 /* Route-map for aggregated route. */
5530 struct route_map
*map
;
5532 /* Suppress-count. */
5533 unsigned long count
;
5535 /* SAFI configuration. */
5539 static struct bgp_aggregate
*bgp_aggregate_new(void)
5541 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
5544 static void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
5546 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
5549 static int bgp_aggregate_info_same(struct bgp_path_info
*pi
, uint8_t origin
,
5550 struct aspath
*aspath
,
5551 struct community
*comm
,
5552 struct ecommunity
*ecomm
,
5553 struct lcommunity
*lcomm
)
5555 static struct aspath
*ae
= NULL
;
5558 ae
= aspath_empty();
5563 if (origin
!= pi
->attr
->origin
)
5566 if (!aspath_cmp(pi
->attr
->aspath
, (aspath
) ? aspath
: ae
))
5569 if (!community_cmp(pi
->attr
->community
, comm
))
5572 if (!ecommunity_cmp(pi
->attr
->ecommunity
, ecomm
))
5575 if (!lcommunity_cmp(pi
->attr
->lcommunity
, lcomm
))
5578 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
5584 static void bgp_aggregate_install(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
5585 struct prefix
*p
, uint8_t origin
,
5586 struct aspath
*aspath
,
5587 struct community
*community
,
5588 struct ecommunity
*ecommunity
,
5589 struct lcommunity
*lcommunity
,
5590 uint8_t atomic_aggregate
,
5591 struct bgp_aggregate
*aggregate
)
5593 struct bgp_node
*rn
;
5594 struct bgp_table
*table
;
5595 struct bgp_path_info
*pi
, *orig
, *new;
5597 table
= bgp
->rib
[afi
][safi
];
5599 rn
= bgp_node_get(table
, p
);
5601 for (orig
= pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
5602 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5603 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5606 if (aggregate
->count
> 0) {
5608 * If the aggregate information has not changed
5609 * no need to re-install it again.
5611 if (bgp_aggregate_info_same(orig
, origin
, aspath
, community
,
5612 ecommunity
, lcommunity
)) {
5613 bgp_unlock_node(rn
);
5616 aspath_free(aspath
);
5618 community_free(&community
);
5620 ecommunity_free(&ecommunity
);
5622 lcommunity_free(&lcommunity
);
5628 * Mark the old as unusable
5631 bgp_path_info_delete(rn
, pi
);
5633 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0,
5635 bgp_attr_aggregate_intern(bgp
, origin
, aspath
,
5636 community
, ecommunity
,
5641 SET_FLAG(new->flags
, BGP_PATH_VALID
);
5643 bgp_path_info_add(rn
, new);
5644 bgp_process(bgp
, rn
, afi
, safi
);
5646 for (pi
= orig
; pi
; pi
= pi
->next
)
5647 if (pi
->peer
== bgp
->peer_self
5648 && pi
->type
== ZEBRA_ROUTE_BGP
5649 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5652 /* Withdraw static BGP route from routing table. */
5654 bgp_path_info_delete(rn
, pi
);
5655 bgp_process(bgp
, rn
, afi
, safi
);
5659 bgp_unlock_node(rn
);
5662 /* Update an aggregate as routes are added/removed from the BGP table */
5663 static void bgp_aggregate_route(struct bgp
*bgp
, struct prefix
*p
,
5664 struct bgp_path_info
*pinew
, afi_t afi
,
5665 safi_t safi
, struct bgp_path_info
*del
,
5666 struct bgp_aggregate
*aggregate
)
5668 struct bgp_table
*table
;
5669 struct bgp_node
*top
;
5670 struct bgp_node
*rn
;
5672 struct aspath
*aspath
= NULL
;
5673 struct aspath
*asmerge
= NULL
;
5674 struct community
*community
= NULL
;
5675 struct community
*commerge
= NULL
;
5676 struct ecommunity
*ecommunity
= NULL
;
5677 struct ecommunity
*ecommerge
= NULL
;
5678 struct lcommunity
*lcommunity
= NULL
;
5679 struct lcommunity
*lcommerge
= NULL
;
5680 struct bgp_path_info
*pi
;
5681 unsigned long match
= 0;
5682 uint8_t atomic_aggregate
= 0;
5684 /* ORIGIN attribute: If at least one route among routes that are
5685 aggregated has ORIGIN with the value INCOMPLETE, then the
5686 aggregated route must have the ORIGIN attribute with the value
5687 INCOMPLETE. Otherwise, if at least one route among routes that
5688 are aggregated has ORIGIN with the value EGP, then the aggregated
5689 route must have the origin attribute with the value EGP. In all
5690 other case the value of the ORIGIN attribute of the aggregated
5691 route is INTERNAL. */
5692 origin
= BGP_ORIGIN_IGP
;
5694 table
= bgp
->rib
[afi
][safi
];
5696 top
= bgp_node_get(table
, p
);
5697 for (rn
= bgp_node_get(table
, p
); rn
;
5698 rn
= bgp_route_next_until(rn
, top
)) {
5699 if (rn
->p
.prefixlen
<= p
->prefixlen
)
5704 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
5705 if (BGP_PATH_HOLDDOWN(pi
))
5708 if (del
&& pi
== del
)
5712 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
5713 atomic_aggregate
= 1;
5715 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5719 * summary-only aggregate route suppress
5720 * aggregated route announcements.
5722 if (aggregate
->summary_only
) {
5723 (bgp_path_info_extra_get(pi
))->suppress
++;
5724 bgp_path_info_set_flag(rn
, pi
,
5725 BGP_PATH_ATTR_CHANGED
);
5732 * If at least one route among routes that are
5733 * aggregated has ORIGIN with the value INCOMPLETE,
5734 * then the aggregated route MUST have the ORIGIN
5735 * attribute with the value INCOMPLETE. Otherwise, if
5736 * at least one route among routes that are aggregated
5737 * has ORIGIN with the value EGP, then the aggregated
5738 * route MUST have the ORIGIN attribute with the value
5741 if (origin
< pi
->attr
->origin
)
5742 origin
= pi
->attr
->origin
;
5744 if (!aggregate
->as_set
)
5748 * as-set aggregate route generate origin, as path,
5749 * and community aggregation.
5752 asmerge
= aspath_aggregate(aspath
,
5754 aspath_free(aspath
);
5757 aspath
= aspath_dup(pi
->attr
->aspath
);
5759 if (pi
->attr
->community
) {
5761 commerge
= community_merge(
5762 community
, pi
->attr
->community
);
5764 community_uniq_sort(commerge
);
5765 community_free(&commerge
);
5767 community
= community_dup(
5768 pi
->attr
->community
);
5771 if (pi
->attr
->ecommunity
) {
5773 ecommerge
= ecommunity_merge(
5775 pi
->attr
->ecommunity
);
5777 ecommunity_uniq_sort(ecommerge
);
5778 ecommunity_free(&ecommerge
);
5780 ecommunity
= ecommunity_dup(
5781 pi
->attr
->ecommunity
);
5784 if (pi
->attr
->lcommunity
) {
5786 lcommerge
= lcommunity_merge(
5788 pi
->attr
->lcommunity
);
5790 lcommunity_uniq_sort(lcommerge
);
5791 lcommunity_free(&lcommerge
);
5793 lcommunity
= lcommunity_dup(
5794 pi
->attr
->lcommunity
);
5798 bgp_process(bgp
, rn
, afi
, safi
);
5800 bgp_unlock_node(top
);
5805 if (aggregate
->summary_only
)
5806 (bgp_path_info_extra_get(pinew
))->suppress
++;
5808 if (origin
< pinew
->attr
->origin
)
5809 origin
= pinew
->attr
->origin
;
5811 if (aggregate
->as_set
) {
5813 asmerge
= aspath_aggregate(aspath
,
5814 pinew
->attr
->aspath
);
5815 aspath_free(aspath
);
5818 aspath
= aspath_dup(pinew
->attr
->aspath
);
5820 if (pinew
->attr
->community
) {
5822 commerge
= community_merge(
5824 pinew
->attr
->community
);
5826 community_uniq_sort(commerge
);
5827 community_free(&commerge
);
5829 community
= community_dup(
5830 pinew
->attr
->community
);
5833 if (pinew
->attr
->ecommunity
) {
5835 ecommerge
= ecommunity_merge(
5837 pinew
->attr
->ecommunity
);
5839 ecommunity_uniq_sort(ecommerge
);
5840 ecommunity_free(&ecommerge
);
5842 ecommunity
= ecommunity_dup(
5843 pinew
->attr
->ecommunity
);
5846 if (pinew
->attr
->lcommunity
) {
5848 lcommerge
= lcommunity_merge(
5850 pinew
->attr
->lcommunity
);
5852 lcommunity_uniq_sort(lcommerge
);
5853 lcommunity_free(&lcommerge
);
5855 lcommunity
= lcommunity_dup(
5856 pinew
->attr
->lcommunity
);
5861 bgp_aggregate_install(bgp
, afi
, safi
, p
, origin
, aspath
, community
,
5862 ecommunity
, lcommunity
, atomic_aggregate
,
5865 if (aggregate
->count
== 0) {
5867 aspath_free(aspath
);
5869 community_free(&community
);
5871 ecommunity_free(&ecommunity
);
5873 lcommunity_free(&lcommunity
);
5877 static void bgp_aggregate_delete(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
5878 safi_t safi
, struct bgp_aggregate
*aggregate
)
5880 struct bgp_table
*table
;
5881 struct bgp_node
*top
;
5882 struct bgp_node
*rn
;
5883 struct bgp_path_info
*pi
;
5884 unsigned long match
;
5886 table
= bgp
->rib
[afi
][safi
];
5888 /* If routes exists below this node, generate aggregate routes. */
5889 top
= bgp_node_get(table
, p
);
5890 for (rn
= bgp_node_get(table
, p
); rn
;
5891 rn
= bgp_route_next_until(rn
, top
)) {
5892 if (rn
->p
.prefixlen
<= p
->prefixlen
)
5896 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
5897 if (BGP_PATH_HOLDDOWN(pi
))
5900 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5903 if (aggregate
->summary_only
&& pi
->extra
) {
5904 pi
->extra
->suppress
--;
5906 if (pi
->extra
->suppress
== 0) {
5907 bgp_path_info_set_flag(
5908 rn
, pi
, BGP_PATH_ATTR_CHANGED
);
5915 /* If this node was suppressed, process the change. */
5917 bgp_process(bgp
, rn
, afi
, safi
);
5919 bgp_unlock_node(top
);
5922 void bgp_aggregate_increment(struct bgp
*bgp
, struct prefix
*p
,
5923 struct bgp_path_info
*pi
, afi_t afi
, safi_t safi
)
5925 struct bgp_node
*child
;
5926 struct bgp_node
*rn
;
5927 struct bgp_aggregate
*aggregate
;
5928 struct bgp_table
*table
;
5930 table
= bgp
->aggregate
[afi
][safi
];
5932 /* No aggregates configured. */
5933 if (bgp_table_top_nolock(table
) == NULL
)
5936 if (p
->prefixlen
== 0)
5939 if (BGP_PATH_HOLDDOWN(pi
))
5942 child
= bgp_node_get(table
, p
);
5944 /* Aggregate address configuration check. */
5945 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
)) {
5946 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
5947 if (aggregate
!= NULL
&& rn
->p
.prefixlen
< p
->prefixlen
) {
5948 bgp_aggregate_delete(bgp
, &rn
->p
, afi
, safi
, aggregate
);
5949 bgp_aggregate_route(bgp
, &rn
->p
, pi
, afi
, safi
, NULL
,
5953 bgp_unlock_node(child
);
5956 void bgp_aggregate_decrement(struct bgp
*bgp
, struct prefix
*p
,
5957 struct bgp_path_info
*del
, afi_t afi
, safi_t safi
)
5959 struct bgp_node
*child
;
5960 struct bgp_node
*rn
;
5961 struct bgp_aggregate
*aggregate
;
5962 struct bgp_table
*table
;
5964 table
= bgp
->aggregate
[afi
][safi
];
5966 /* No aggregates configured. */
5967 if (bgp_table_top_nolock(table
) == NULL
)
5970 if (p
->prefixlen
== 0)
5973 child
= bgp_node_get(table
, p
);
5975 /* Aggregate address configuration check. */
5976 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
)) {
5977 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
5978 if (aggregate
!= NULL
&& rn
->p
.prefixlen
< p
->prefixlen
) {
5979 bgp_aggregate_delete(bgp
, &rn
->p
, afi
, safi
, aggregate
);
5980 bgp_aggregate_route(bgp
, &rn
->p
, NULL
, afi
, safi
, del
,
5984 bgp_unlock_node(child
);
5987 /* Aggregate route attribute. */
5988 #define AGGREGATE_SUMMARY_ONLY 1
5989 #define AGGREGATE_AS_SET 1
5991 static int bgp_aggregate_unset(struct vty
*vty
, const char *prefix_str
,
5992 afi_t afi
, safi_t safi
)
5994 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5997 struct bgp_node
*rn
;
5998 struct bgp_aggregate
*aggregate
;
6000 /* Convert string to prefix structure. */
6001 ret
= str2prefix(prefix_str
, &p
);
6003 vty_out(vty
, "Malformed prefix\n");
6004 return CMD_WARNING_CONFIG_FAILED
;
6008 /* Old configuration check. */
6009 rn
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], &p
);
6012 "%% There is no aggregate-address configuration.\n");
6013 return CMD_WARNING_CONFIG_FAILED
;
6016 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6017 bgp_aggregate_delete(bgp
, &p
, afi
, safi
, aggregate
);
6018 bgp_aggregate_install(bgp
, afi
, safi
, &p
, 0, NULL
, NULL
,
6019 NULL
, NULL
, 0, aggregate
);
6021 /* Unlock aggregate address configuration. */
6022 bgp_node_set_bgp_aggregate_info(rn
, NULL
);
6023 bgp_aggregate_free(aggregate
);
6024 bgp_unlock_node(rn
);
6025 bgp_unlock_node(rn
);
6030 static int bgp_aggregate_set(struct vty
*vty
, const char *prefix_str
, afi_t afi
,
6031 safi_t safi
, uint8_t summary_only
, uint8_t as_set
)
6033 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6036 struct bgp_node
*rn
;
6037 struct bgp_aggregate
*aggregate
;
6039 /* Convert string to prefix structure. */
6040 ret
= str2prefix(prefix_str
, &p
);
6042 vty_out(vty
, "Malformed prefix\n");
6043 return CMD_WARNING_CONFIG_FAILED
;
6047 if ((afi
== AFI_IP
&& p
.prefixlen
== IPV4_MAX_BITLEN
) ||
6048 (afi
== AFI_IP6
&& p
.prefixlen
== IPV6_MAX_BITLEN
)) {
6049 vty_out(vty
, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
6051 return CMD_WARNING_CONFIG_FAILED
;
6054 /* Old configuration check. */
6055 rn
= bgp_node_get(bgp
->aggregate
[afi
][safi
], &p
);
6057 if (bgp_node_has_bgp_path_info_data(rn
)) {
6058 vty_out(vty
, "There is already same aggregate network.\n");
6059 /* try to remove the old entry */
6060 ret
= bgp_aggregate_unset(vty
, prefix_str
, afi
, safi
);
6062 vty_out(vty
, "Error deleting aggregate.\n");
6063 bgp_unlock_node(rn
);
6064 return CMD_WARNING_CONFIG_FAILED
;
6068 /* Make aggregate address structure. */
6069 aggregate
= bgp_aggregate_new();
6070 aggregate
->summary_only
= summary_only
;
6071 aggregate
->as_set
= as_set
;
6072 aggregate
->safi
= safi
;
6073 bgp_node_set_bgp_aggregate_info(rn
, aggregate
);
6075 /* Aggregate address insert into BGP routing table. */
6076 bgp_aggregate_route(bgp
, &p
, NULL
, afi
, safi
, NULL
, aggregate
);
6081 DEFUN (aggregate_address
,
6082 aggregate_address_cmd
,
6083 "aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
6084 "Configure BGP aggregate entries\n"
6085 "Aggregate prefix\n"
6086 "Generate AS set path information\n"
6087 "Filter more specific routes from updates\n"
6088 "Filter more specific routes from updates\n"
6089 "Generate AS set path information\n")
6092 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
6093 char *prefix
= argv
[idx
]->arg
;
6095 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
6097 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6098 ? AGGREGATE_SUMMARY_ONLY
6101 return bgp_aggregate_set(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
),
6102 summary_only
, as_set
);
6105 DEFUN (aggregate_address_mask
,
6106 aggregate_address_mask_cmd
,
6107 "aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
6108 "Configure BGP aggregate entries\n"
6109 "Aggregate address\n"
6111 "Generate AS set path information\n"
6112 "Filter more specific routes from updates\n"
6113 "Filter more specific routes from updates\n"
6114 "Generate AS set path information\n")
6117 argv_find(argv
, argc
, "A.B.C.D", &idx
);
6118 char *prefix
= argv
[idx
]->arg
;
6119 char *mask
= argv
[idx
+ 1]->arg
;
6121 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
6123 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6124 ? AGGREGATE_SUMMARY_ONLY
6127 char prefix_str
[BUFSIZ
];
6128 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
6131 vty_out(vty
, "%% Inconsistent address and mask\n");
6132 return CMD_WARNING_CONFIG_FAILED
;
6135 return bgp_aggregate_set(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
),
6136 summary_only
, as_set
);
6139 DEFUN (no_aggregate_address
,
6140 no_aggregate_address_cmd
,
6141 "no aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
6143 "Configure BGP aggregate entries\n"
6144 "Aggregate prefix\n"
6145 "Generate AS set path information\n"
6146 "Filter more specific routes from updates\n"
6147 "Filter more specific routes from updates\n"
6148 "Generate AS set path information\n")
6151 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
6152 char *prefix
= argv
[idx
]->arg
;
6153 return bgp_aggregate_unset(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
));
6156 DEFUN (no_aggregate_address_mask
,
6157 no_aggregate_address_mask_cmd
,
6158 "no aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
6160 "Configure BGP aggregate entries\n"
6161 "Aggregate address\n"
6163 "Generate AS set path information\n"
6164 "Filter more specific routes from updates\n"
6165 "Filter more specific routes from updates\n"
6166 "Generate AS set path information\n")
6169 argv_find(argv
, argc
, "A.B.C.D", &idx
);
6170 char *prefix
= argv
[idx
]->arg
;
6171 char *mask
= argv
[idx
+ 1]->arg
;
6173 char prefix_str
[BUFSIZ
];
6174 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
6177 vty_out(vty
, "%% Inconsistent address and mask\n");
6178 return CMD_WARNING_CONFIG_FAILED
;
6181 return bgp_aggregate_unset(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
));
6184 DEFUN (ipv6_aggregate_address
,
6185 ipv6_aggregate_address_cmd
,
6186 "aggregate-address X:X::X:X/M [summary-only]",
6187 "Configure BGP aggregate entries\n"
6188 "Aggregate prefix\n"
6189 "Filter more specific routes from updates\n")
6192 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6193 char *prefix
= argv
[idx
]->arg
;
6194 int sum_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6195 ? AGGREGATE_SUMMARY_ONLY
6197 return bgp_aggregate_set(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
, sum_only
,
6201 DEFUN (no_ipv6_aggregate_address
,
6202 no_ipv6_aggregate_address_cmd
,
6203 "no aggregate-address X:X::X:X/M [summary-only]",
6205 "Configure BGP aggregate entries\n"
6206 "Aggregate prefix\n"
6207 "Filter more specific routes from updates\n")
6210 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6211 char *prefix
= argv
[idx
]->arg
;
6212 return bgp_aggregate_unset(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
);
6215 /* Redistribute route treatment. */
6216 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
6217 const union g_addr
*nexthop
, ifindex_t ifindex
,
6218 enum nexthop_types_t nhtype
, uint32_t metric
,
6219 uint8_t type
, unsigned short instance
,
6222 struct bgp_path_info
*new;
6223 struct bgp_path_info
*bpi
;
6224 struct bgp_path_info rmap_path
;
6225 struct bgp_node
*bn
;
6227 struct attr
*new_attr
;
6230 struct bgp_redist
*red
;
6232 /* Make default attribute. */
6233 bgp_attr_default_set(&attr
, BGP_ORIGIN_INCOMPLETE
);
6236 case NEXTHOP_TYPE_IFINDEX
:
6238 case NEXTHOP_TYPE_IPV4
:
6239 case NEXTHOP_TYPE_IPV4_IFINDEX
:
6240 attr
.nexthop
= nexthop
->ipv4
;
6242 case NEXTHOP_TYPE_IPV6
:
6243 case NEXTHOP_TYPE_IPV6_IFINDEX
:
6244 attr
.mp_nexthop_global
= nexthop
->ipv6
;
6245 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6247 case NEXTHOP_TYPE_BLACKHOLE
:
6248 switch (p
->family
) {
6250 attr
.nexthop
.s_addr
= INADDR_ANY
;
6253 memset(&attr
.mp_nexthop_global
, 0,
6254 sizeof(attr
.mp_nexthop_global
));
6255 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6260 attr
.nh_ifindex
= ifindex
;
6263 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6266 afi
= family2afi(p
->family
);
6268 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6270 struct attr attr_new
;
6272 /* Copy attribute for modification. */
6273 bgp_attr_dup(&attr_new
, &attr
);
6275 if (red
->redist_metric_flag
)
6276 attr_new
.med
= red
->redist_metric
;
6278 /* Apply route-map. */
6279 if (red
->rmap
.name
) {
6280 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
6281 rmap_path
.peer
= bgp
->peer_self
;
6282 rmap_path
.attr
= &attr_new
;
6284 SET_FLAG(bgp
->peer_self
->rmap_type
,
6285 PEER_RMAP_TYPE_REDISTRIBUTE
);
6287 ret
= route_map_apply(red
->rmap
.map
, p
, RMAP_BGP
,
6290 bgp
->peer_self
->rmap_type
= 0;
6292 if (ret
== RMAP_DENYMATCH
) {
6293 /* Free uninterned attribute. */
6294 bgp_attr_flush(&attr_new
);
6296 /* Unintern original. */
6297 aspath_unintern(&attr
.aspath
);
6298 bgp_redistribute_delete(bgp
, p
, type
, instance
);
6303 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
6304 bgp_attr_add_gshut_community(&attr_new
);
6306 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6307 SAFI_UNICAST
, p
, NULL
);
6309 new_attr
= bgp_attr_intern(&attr_new
);
6311 for (bpi
= bgp_node_get_bgp_path_info(bn
); bpi
;
6313 if (bpi
->peer
== bgp
->peer_self
6314 && bpi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
6318 /* Ensure the (source route) type is updated. */
6320 if (attrhash_cmp(bpi
->attr
, new_attr
)
6321 && !CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
)) {
6322 bgp_attr_unintern(&new_attr
);
6323 aspath_unintern(&attr
.aspath
);
6324 bgp_unlock_node(bn
);
6327 /* The attribute is changed. */
6328 bgp_path_info_set_flag(bn
, bpi
,
6329 BGP_PATH_ATTR_CHANGED
);
6331 /* Rewrite BGP route information. */
6332 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
6333 bgp_path_info_restore(bn
, bpi
);
6335 bgp_aggregate_decrement(
6336 bgp
, p
, bpi
, afi
, SAFI_UNICAST
);
6337 bgp_attr_unintern(&bpi
->attr
);
6338 bpi
->attr
= new_attr
;
6339 bpi
->uptime
= bgp_clock();
6341 /* Process change. */
6342 bgp_aggregate_increment(bgp
, p
, bpi
, afi
,
6344 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6345 bgp_unlock_node(bn
);
6346 aspath_unintern(&attr
.aspath
);
6348 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6350 == BGP_INSTANCE_TYPE_DEFAULT
)) {
6352 vpn_leak_from_vrf_update(
6353 bgp_get_default(), bgp
, bpi
);
6359 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
6360 bgp
->peer_self
, new_attr
, bn
);
6361 SET_FLAG(new->flags
, BGP_PATH_VALID
);
6363 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
6364 bgp_path_info_add(bn
, new);
6365 bgp_unlock_node(bn
);
6366 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6368 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6369 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6371 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
6375 /* Unintern original. */
6376 aspath_unintern(&attr
.aspath
);
6379 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, uint8_t type
,
6380 unsigned short instance
)
6383 struct bgp_node
*rn
;
6384 struct bgp_path_info
*pi
;
6385 struct bgp_redist
*red
;
6387 afi
= family2afi(p
->family
);
6389 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6391 rn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6392 SAFI_UNICAST
, p
, NULL
);
6394 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
6395 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
)
6399 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6400 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6402 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6405 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, SAFI_UNICAST
);
6406 bgp_path_info_delete(rn
, pi
);
6407 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6409 bgp_unlock_node(rn
);
6413 /* Withdraw specified route type's route. */
6414 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
6415 unsigned short instance
)
6417 struct bgp_node
*rn
;
6418 struct bgp_path_info
*pi
;
6419 struct bgp_table
*table
;
6421 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
6423 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
6424 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
6425 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
6426 && pi
->instance
== instance
)
6430 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6431 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6433 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6436 bgp_aggregate_decrement(bgp
, &rn
->p
, pi
, afi
,
6438 bgp_path_info_delete(rn
, pi
);
6439 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6444 /* Static function to display route. */
6445 static void route_vty_out_route(struct prefix
*p
, struct vty
*vty
,
6452 if (p
->family
== AF_INET
) {
6456 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
6459 json_object_string_add(json
, "prefix",
6460 inet_ntop(p
->family
,
6463 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
6464 prefix2str(p
, buf2
, PREFIX_STRLEN
);
6465 json_object_string_add(json
, "network", buf2
);
6467 } else if (p
->family
== AF_ETHERNET
) {
6468 prefix2str(p
, buf
, PREFIX_STRLEN
);
6469 len
= vty_out(vty
, "%s", buf
);
6470 } else if (p
->family
== AF_EVPN
) {
6474 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf
,
6477 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
6478 } else if (p
->family
== AF_FLOWSPEC
) {
6479 route_vty_out_flowspec(vty
, p
, NULL
,
6481 NLRI_STRING_FORMAT_JSON_SIMPLE
:
6482 NLRI_STRING_FORMAT_MIN
, json
);
6487 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
6490 json_object_string_add(json
, "prefix",
6491 inet_ntop(p
->family
,
6494 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
6495 prefix2str(p
, buf2
, PREFIX_STRLEN
);
6496 json_object_string_add(json
, "network", buf2
);
6503 vty_out(vty
, "\n%*s", 20, " ");
6505 vty_out(vty
, "%*s", len
, " ");
6509 enum bgp_display_type
{
6513 /* Print the short form route status for a bgp_path_info */
6514 static void route_vty_short_status_out(struct vty
*vty
,
6515 struct bgp_path_info
*path
,
6516 json_object
*json_path
)
6520 /* Route status display. */
6521 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
6522 json_object_boolean_true_add(json_path
, "removed");
6524 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
6525 json_object_boolean_true_add(json_path
, "stale");
6527 if (path
->extra
&& path
->extra
->suppress
)
6528 json_object_boolean_true_add(json_path
, "suppressed");
6530 if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
6531 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
6532 json_object_boolean_true_add(json_path
, "valid");
6535 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
6536 json_object_boolean_true_add(json_path
, "history");
6538 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
6539 json_object_boolean_true_add(json_path
, "damped");
6541 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
6542 json_object_boolean_true_add(json_path
, "bestpath");
6544 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
6545 json_object_boolean_true_add(json_path
, "multipath");
6547 /* Internal route. */
6548 if ((path
->peer
->as
)
6549 && (path
->peer
->as
== path
->peer
->local_as
))
6550 json_object_string_add(json_path
, "pathFrom",
6553 json_object_string_add(json_path
, "pathFrom",
6559 /* Route status display. */
6560 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
6562 else if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
6564 else if (path
->extra
&& path
->extra
->suppress
)
6566 else if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
6567 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
6573 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
6575 else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
6577 else if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
6579 else if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
6584 /* Internal route. */
6585 if (path
->peer
&& (path
->peer
->as
)
6586 && (path
->peer
->as
== path
->peer
->local_as
))
6592 /* called from terminal list command */
6593 void route_vty_out(struct vty
*vty
, struct prefix
*p
,
6594 struct bgp_path_info
*path
, int display
, safi_t safi
,
6595 json_object
*json_paths
)
6598 json_object
*json_path
= NULL
;
6599 json_object
*json_nexthops
= NULL
;
6600 json_object
*json_nexthop_global
= NULL
;
6601 json_object
*json_nexthop_ll
= NULL
;
6602 char vrf_id_str
[VRF_NAMSIZ
] = {0};
6604 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
6605 bool nexthop_othervrf
= false;
6606 vrf_id_t nexthop_vrfid
= VRF_DEFAULT
;
6607 const char *nexthop_vrfname
= VRF_DEFAULT_NAME
;
6610 json_path
= json_object_new_object();
6612 /* short status lead text */
6613 route_vty_short_status_out(vty
, path
, json_path
);
6616 /* print prefix and mask */
6618 route_vty_out_route(p
, vty
, json_path
);
6620 vty_out(vty
, "%*s", 17, " ");
6622 route_vty_out_route(p
, vty
, json_path
);
6625 /* Print attribute */
6629 json_object_array_add(json_paths
, json_path
);
6637 * If vrf id of nexthop is different from that of prefix,
6638 * set up printable string to append
6640 if (path
->extra
&& path
->extra
->bgp_orig
) {
6641 const char *self
= "";
6646 nexthop_othervrf
= true;
6647 nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
6649 if (path
->extra
->bgp_orig
->vrf_id
== VRF_UNKNOWN
)
6650 snprintf(vrf_id_str
, sizeof(vrf_id_str
),
6651 "@%s%s", VRFID_NONE_STR
, self
);
6653 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "@%u%s",
6654 path
->extra
->bgp_orig
->vrf_id
, self
);
6656 if (path
->extra
->bgp_orig
->inst_type
6657 != BGP_INSTANCE_TYPE_DEFAULT
)
6659 nexthop_vrfname
= path
->extra
->bgp_orig
->name
;
6661 const char *self
= "";
6666 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "%s", self
);
6670 * For ENCAP and EVPN routes, nexthop address family is not
6671 * neccessarily the same as the prefix address family.
6672 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
6673 * EVPN routes are also exchanged with a MP nexthop. Currently,
6675 * is only IPv4, the value will be present in either
6677 * attr->mp_nexthop_global_in
6679 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
6682 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
6686 sprintf(nexthop
, "%s",
6687 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
6691 sprintf(nexthop
, "%s",
6692 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
6696 sprintf(nexthop
, "?");
6701 json_nexthop_global
= json_object_new_object();
6703 json_object_string_add(json_nexthop_global
, "afi",
6704 (af
== AF_INET
) ? "ip" : "ipv6");
6705 json_object_string_add(json_nexthop_global
,
6706 (af
== AF_INET
) ? "ip" : "ipv6",
6708 json_object_boolean_true_add(json_nexthop_global
,
6711 vty_out(vty
, "%s%s", nexthop
, vrf_id_str
);
6712 } else if (safi
== SAFI_EVPN
) {
6714 json_nexthop_global
= json_object_new_object();
6716 json_object_string_add(json_nexthop_global
, "ip",
6717 inet_ntoa(attr
->nexthop
));
6718 json_object_string_add(json_nexthop_global
, "afi",
6720 json_object_boolean_true_add(json_nexthop_global
,
6723 vty_out(vty
, "%-16s%s", inet_ntoa(attr
->nexthop
),
6725 } else if (safi
== SAFI_FLOWSPEC
) {
6726 if (attr
->nexthop
.s_addr
!= 0) {
6728 json_nexthop_global
= json_object_new_object();
6729 json_object_string_add(
6730 json_nexthop_global
, "ip",
6731 inet_ntoa(attr
->nexthop
));
6732 json_object_string_add(json_nexthop_global
,
6734 json_object_boolean_true_add(
6735 json_nexthop_global
,
6738 vty_out(vty
, "%-16s", inet_ntoa(attr
->nexthop
));
6741 } else if (p
->family
== AF_INET
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6743 json_nexthop_global
= json_object_new_object();
6745 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_EVPN
))
6746 json_object_string_add(
6747 json_nexthop_global
, "ip",
6748 inet_ntoa(attr
->mp_nexthop_global_in
));
6750 json_object_string_add(
6751 json_nexthop_global
, "ip",
6752 inet_ntoa(attr
->nexthop
));
6754 json_object_string_add(json_nexthop_global
, "afi",
6756 json_object_boolean_true_add(json_nexthop_global
,
6761 snprintf(buf
, sizeof(buf
), "%s%s",
6762 inet_ntoa(attr
->nexthop
), vrf_id_str
);
6763 vty_out(vty
, "%-16s", buf
);
6768 else if (p
->family
== AF_INET6
|| BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6773 json_nexthop_global
= json_object_new_object();
6774 json_object_string_add(
6775 json_nexthop_global
, "ip",
6776 inet_ntop(AF_INET6
, &attr
->mp_nexthop_global
,
6778 json_object_string_add(json_nexthop_global
, "afi",
6780 json_object_string_add(json_nexthop_global
, "scope",
6783 /* We display both LL & GL if both have been
6785 if ((attr
->mp_nexthop_len
== 32)
6786 || (path
->peer
->conf_if
)) {
6787 json_nexthop_ll
= json_object_new_object();
6788 json_object_string_add(
6789 json_nexthop_ll
, "ip",
6791 &attr
->mp_nexthop_local
, buf
,
6793 json_object_string_add(json_nexthop_ll
, "afi",
6795 json_object_string_add(json_nexthop_ll
, "scope",
6798 if ((IPV6_ADDR_CMP(&attr
->mp_nexthop_global
,
6799 &attr
->mp_nexthop_local
)
6801 && !attr
->mp_nexthop_prefer_global
)
6802 json_object_boolean_true_add(
6803 json_nexthop_ll
, "used");
6805 json_object_boolean_true_add(
6806 json_nexthop_global
, "used");
6808 json_object_boolean_true_add(
6809 json_nexthop_global
, "used");
6811 /* Display LL if LL/Global both in table unless
6812 * prefer-global is set */
6813 if (((attr
->mp_nexthop_len
== 32)
6814 && !attr
->mp_nexthop_prefer_global
)
6815 || (path
->peer
->conf_if
)) {
6816 if (path
->peer
->conf_if
) {
6817 len
= vty_out(vty
, "%s",
6818 path
->peer
->conf_if
);
6819 len
= 16 - len
; /* len of IPv6
6825 vty_out(vty
, "\n%*s", 36, " ");
6827 vty_out(vty
, "%*s", len
, " ");
6833 &attr
->mp_nexthop_local
,
6839 vty_out(vty
, "\n%*s", 36, " ");
6841 vty_out(vty
, "%*s", len
, " ");
6847 &attr
->mp_nexthop_global
, buf
,
6853 vty_out(vty
, "\n%*s", 36, " ");
6855 vty_out(vty
, "%*s", len
, " ");
6861 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
6865 * Adding "metric" field to match with corresponding
6866 * CLI. "med" will be deprecated in future.
6868 json_object_int_add(json_path
, "med", attr
->med
);
6869 json_object_int_add(json_path
, "metric", attr
->med
);
6871 vty_out(vty
, "%10u", attr
->med
);
6872 else if (!json_paths
)
6876 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
6880 * Adding "locPrf" field to match with corresponding
6881 * CLI. "localPref" will be deprecated in future.
6883 json_object_int_add(json_path
, "localpref",
6885 json_object_int_add(json_path
, "locPrf",
6888 vty_out(vty
, "%7u", attr
->local_pref
);
6889 else if (!json_paths
)
6893 json_object_int_add(json_path
, "weight", attr
->weight
);
6895 vty_out(vty
, "%7u ", attr
->weight
);
6899 json_object_string_add(
6900 json_path
, "peerId",
6901 sockunion2str(&path
->peer
->su
, buf
, SU_ADDRSTRLEN
));
6909 * Adding "path" field to match with corresponding
6910 * CLI. "aspath" will be deprecated in future.
6912 json_object_string_add(json_path
, "aspath",
6914 json_object_string_add(json_path
, "path",
6917 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
6922 json_object_string_add(json_path
, "origin",
6923 bgp_origin_long_str
[attr
->origin
]);
6925 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
6929 json_object_boolean_true_add(json_path
,
6930 "announceNexthopSelf");
6931 if (nexthop_othervrf
) {
6932 json_object_string_add(json_path
, "nhVrfName",
6935 json_object_int_add(json_path
, "nhVrfId",
6936 ((nexthop_vrfid
== VRF_UNKNOWN
)
6938 : (int)nexthop_vrfid
));
6943 if (json_nexthop_global
|| json_nexthop_ll
) {
6944 json_nexthops
= json_object_new_array();
6946 if (json_nexthop_global
)
6947 json_object_array_add(json_nexthops
,
6948 json_nexthop_global
);
6950 if (json_nexthop_ll
)
6951 json_object_array_add(json_nexthops
,
6954 json_object_object_add(json_path
, "nexthops",
6958 json_object_array_add(json_paths
, json_path
);
6962 /* prints an additional line, indented, with VNC info, if
6964 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
6965 rfapi_vty_out_vncinfo(vty
, p
, path
, safi
);
6970 /* called from terminal list command */
6971 void route_vty_out_tmp(struct vty
*vty
, struct prefix
*p
, struct attr
*attr
,
6972 safi_t safi
, bool use_json
, json_object
*json_ar
)
6974 json_object
*json_status
= NULL
;
6975 json_object
*json_net
= NULL
;
6978 /* Route status display. */
6980 json_status
= json_object_new_object();
6981 json_net
= json_object_new_object();
6988 /* print prefix and mask */
6990 json_object_string_add(
6991 json_net
, "addrPrefix",
6992 inet_ntop(p
->family
, &p
->u
.prefix
, buff
, BUFSIZ
));
6993 json_object_int_add(json_net
, "prefixLen", p
->prefixlen
);
6994 prefix2str(p
, buf2
, PREFIX_STRLEN
);
6995 json_object_string_add(json_net
, "network", buf2
);
6997 route_vty_out_route(p
, vty
, NULL
);
6999 /* Print attribute */
7002 if (p
->family
== AF_INET
7003 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7004 || safi
== SAFI_EVPN
7005 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7006 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7007 || safi
== SAFI_EVPN
)
7008 json_object_string_add(
7009 json_net
, "nextHop",
7011 attr
->mp_nexthop_global_in
));
7013 json_object_string_add(
7014 json_net
, "nextHop",
7015 inet_ntoa(attr
->nexthop
));
7016 } else if (p
->family
== AF_INET6
7017 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7020 json_object_string_add(
7021 json_net
, "nextHopGlobal",
7023 &attr
->mp_nexthop_global
, buf
,
7028 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
7029 json_object_int_add(json_net
, "metric",
7032 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
7035 * Adding "locPrf" field to match with
7036 * corresponding CLI. "localPref" will be
7037 * deprecated in future.
7039 json_object_int_add(json_net
, "localPref",
7041 json_object_int_add(json_net
, "locPrf",
7045 json_object_int_add(json_net
, "weight", attr
->weight
);
7051 * Adding "path" field to match with
7052 * corresponding CLI. "localPref" will be
7053 * deprecated in future.
7055 json_object_string_add(json_net
, "asPath",
7057 json_object_string_add(json_net
, "path",
7062 json_object_string_add(json_net
, "bgpOriginCode",
7063 bgp_origin_str
[attr
->origin
]);
7065 if (p
->family
== AF_INET
7066 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7067 || safi
== SAFI_EVPN
7068 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7069 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7070 || safi
== SAFI_EVPN
)
7071 vty_out(vty
, "%-16s",
7073 attr
->mp_nexthop_global_in
));
7075 vty_out(vty
, "%-16s",
7076 inet_ntoa(attr
->nexthop
));
7077 } else if (p
->family
== AF_INET6
7078 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7085 &attr
->mp_nexthop_global
, buf
,
7089 vty_out(vty
, "\n%*s", 36, " ");
7091 vty_out(vty
, "%*s", len
, " ");
7094 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
7095 vty_out(vty
, "%10u", attr
->med
);
7099 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
7100 vty_out(vty
, "%7u", attr
->local_pref
);
7104 vty_out(vty
, "%7u ", attr
->weight
);
7108 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7111 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7115 json_object_boolean_true_add(json_status
, "*");
7116 json_object_boolean_true_add(json_status
, ">");
7117 json_object_object_add(json_net
, "appliedStatusSymbols",
7119 char buf_cut
[BUFSIZ
];
7120 json_object_object_add(
7122 inet_ntop(p
->family
, &p
->u
.prefix
, buf_cut
, BUFSIZ
),
7128 void route_vty_out_tag(struct vty
*vty
, struct prefix
*p
,
7129 struct bgp_path_info
*path
, int display
, safi_t safi
,
7132 json_object
*json_out
= NULL
;
7134 mpls_label_t label
= MPLS_INVALID_LABEL
;
7140 json_out
= json_object_new_object();
7142 /* short status lead text */
7143 route_vty_short_status_out(vty
, path
, json_out
);
7145 /* print prefix and mask */
7148 route_vty_out_route(p
, vty
, NULL
);
7150 vty_out(vty
, "%*s", 17, " ");
7153 /* Print attribute */
7156 if (((p
->family
== AF_INET
)
7157 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
7158 || (safi
== SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
7159 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7160 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7161 || safi
== SAFI_EVPN
) {
7163 json_object_string_add(
7164 json_out
, "mpNexthopGlobalIn",
7166 attr
->mp_nexthop_global_in
));
7168 vty_out(vty
, "%-16s",
7170 attr
->mp_nexthop_global_in
));
7173 json_object_string_add(
7174 json_out
, "nexthop",
7175 inet_ntoa(attr
->nexthop
));
7177 vty_out(vty
, "%-16s",
7178 inet_ntoa(attr
->nexthop
));
7180 } else if (((p
->family
== AF_INET6
)
7181 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
7182 || (safi
== SAFI_EVPN
7183 && BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
7184 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7188 if (attr
->mp_nexthop_len
7189 == BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
7191 json_object_string_add(
7192 json_out
, "mpNexthopGlobalIn",
7195 &attr
->mp_nexthop_global
,
7196 buf_a
, sizeof(buf_a
)));
7201 &attr
->mp_nexthop_global
,
7202 buf_a
, sizeof(buf_a
)));
7203 } else if (attr
->mp_nexthop_len
7204 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
7207 &attr
->mp_nexthop_global
,
7208 buf_a
, sizeof(buf_a
));
7210 &attr
->mp_nexthop_local
,
7211 buf_b
, sizeof(buf_b
));
7212 sprintf(buf_c
, "%s(%s)", buf_a
, buf_b
);
7213 json_object_string_add(
7215 "mpNexthopGlobalLocal", buf_c
);
7217 vty_out(vty
, "%s(%s)",
7220 &attr
->mp_nexthop_global
,
7221 buf_a
, sizeof(buf_a
)),
7224 &attr
->mp_nexthop_local
,
7225 buf_b
, sizeof(buf_b
)));
7230 label
= decode_label(&path
->extra
->label
[0]);
7232 if (bgp_is_valid_label(&label
)) {
7234 json_object_int_add(json_out
, "notag", label
);
7235 json_object_array_add(json
, json_out
);
7237 vty_out(vty
, "notag/%d", label
);
7243 void route_vty_out_overlay(struct vty
*vty
, struct prefix
*p
,
7244 struct bgp_path_info
*path
, int display
,
7245 json_object
*json_paths
)
7249 json_object
*json_path
= NULL
;
7252 json_path
= json_object_new_object();
7257 /* short status lead text */
7258 route_vty_short_status_out(vty
, path
, json_path
);
7260 /* print prefix and mask */
7262 route_vty_out_route(p
, vty
, NULL
);
7264 vty_out(vty
, "%*s", 17, " ");
7266 /* Print attribute */
7270 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
7274 vty_out(vty
, "%-16s",
7275 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
7279 vty_out(vty
, "%s(%s)",
7280 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
7282 inet_ntop(af
, &attr
->mp_nexthop_local
, buf1
,
7289 char *str
= esi2str(&(attr
->evpn_overlay
.eth_s_id
));
7291 vty_out(vty
, "%s", str
);
7292 XFREE(MTYPE_TMP
, str
);
7294 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn
*)p
)) {
7296 inet_ntoa(attr
->evpn_overlay
.gw_ip
.ipv4
));
7297 } else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn
*)p
)) {
7300 &(attr
->evpn_overlay
.gw_ip
.ipv6
), buf
,
7303 if (attr
->ecommunity
) {
7305 struct ecommunity_val
*routermac
= ecommunity_lookup(
7306 attr
->ecommunity
, ECOMMUNITY_ENCODE_EVPN
,
7307 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
7309 mac
= ecom_mac2str((char *)routermac
->val
);
7311 vty_out(vty
, "/%s", (char *)mac
);
7312 XFREE(MTYPE_TMP
, mac
);
7320 /* dampening route */
7321 static void damp_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7322 struct bgp_path_info
*path
, int display
,
7323 safi_t safi
, bool use_json
, json_object
*json
)
7327 char timebuf
[BGP_UPTIME_LEN
];
7329 /* short status lead text */
7330 route_vty_short_status_out(vty
, path
, json
);
7332 /* print prefix and mask */
7335 route_vty_out_route(p
, vty
, NULL
);
7337 vty_out(vty
, "%*s", 17, " ");
7340 len
= vty_out(vty
, "%s", path
->peer
->host
);
7344 vty_out(vty
, "\n%*s", 34, " ");
7347 json_object_int_add(json
, "peerHost", len
);
7349 vty_out(vty
, "%*s", len
, " ");
7353 bgp_damp_reuse_time_vty(vty
, path
, timebuf
, BGP_UPTIME_LEN
,
7357 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
7358 BGP_UPTIME_LEN
, use_json
,
7361 /* Print attribute */
7367 json_object_string_add(json
, "asPath",
7370 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7375 json_object_string_add(json
, "origin",
7376 bgp_origin_str
[attr
->origin
]);
7378 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7385 static void flap_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7386 struct bgp_path_info
*path
, int display
,
7387 safi_t safi
, bool use_json
, json_object
*json
)
7390 struct bgp_damp_info
*bdi
;
7391 char timebuf
[BGP_UPTIME_LEN
];
7397 bdi
= path
->extra
->damp_info
;
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", 33, " ");
7417 json_object_int_add(json
, "peerHost", len
);
7419 vty_out(vty
, "%*s", len
, " ");
7422 len
= vty_out(vty
, "%d", bdi
->flap
);
7429 json_object_int_add(json
, "bdiFlap", len
);
7431 vty_out(vty
, "%*s", len
, " ");
7435 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
7438 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
7439 BGP_UPTIME_LEN
, 0, NULL
));
7441 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
7442 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
7444 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
7445 BGP_UPTIME_LEN
, use_json
, json
);
7448 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
7453 vty_out(vty
, "%*s ", 8, " ");
7456 /* Print attribute */
7462 json_object_string_add(json
, "asPath",
7465 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7470 json_object_string_add(json
, "origin",
7471 bgp_origin_str
[attr
->origin
]);
7473 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7479 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
7480 int *first
, const char *header
,
7481 json_object
*json_adv_to
)
7483 char buf1
[INET6_ADDRSTRLEN
];
7484 json_object
*json_peer
= NULL
;
7487 /* 'advertised-to' is a dictionary of peers we have advertised
7489 * prefix too. The key is the peer's IP or swpX, the value is
7491 * hostname if we know it and "" if not.
7493 json_peer
= json_object_new_object();
7496 json_object_string_add(json_peer
, "hostname",
7500 json_object_object_add(json_adv_to
, peer
->conf_if
,
7503 json_object_object_add(
7505 sockunion2str(&peer
->su
, buf1
, SU_ADDRSTRLEN
),
7509 vty_out(vty
, "%s", header
);
7514 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
7516 vty_out(vty
, " %s(%s)", peer
->hostname
,
7519 vty_out(vty
, " %s(%s)", peer
->hostname
,
7520 sockunion2str(&peer
->su
, buf1
,
7524 vty_out(vty
, " %s", peer
->conf_if
);
7527 sockunion2str(&peer
->su
, buf1
,
7533 static void route_vty_out_tx_ids(struct vty
*vty
,
7534 struct bgp_addpath_info_data
*d
)
7538 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
7539 vty_out(vty
, "TX-%s %u%s", bgp_addpath_names(i
)->human_name
,
7540 d
->addpath_tx_id
[i
],
7541 i
< BGP_ADDPATH_MAX
- 1 ? " " : "\n");
7545 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
, struct prefix
*p
,
7546 struct bgp_path_info
*path
, afi_t afi
, safi_t safi
,
7547 json_object
*json_paths
)
7549 char buf
[INET6_ADDRSTRLEN
];
7551 char buf2
[EVPN_ROUTE_STRLEN
];
7553 int sockunion_vty_out(struct vty
*, union sockunion
*);
7555 json_object
*json_bestpath
= NULL
;
7556 json_object
*json_cluster_list
= NULL
;
7557 json_object
*json_cluster_list_list
= NULL
;
7558 json_object
*json_ext_community
= NULL
;
7559 json_object
*json_last_update
= NULL
;
7560 json_object
*json_pmsi
= NULL
;
7561 json_object
*json_nexthop_global
= NULL
;
7562 json_object
*json_nexthop_ll
= NULL
;
7563 json_object
*json_nexthops
= NULL
;
7564 json_object
*json_path
= NULL
;
7565 json_object
*json_peer
= NULL
;
7566 json_object
*json_string
= NULL
;
7567 json_object
*json_adv_to
= NULL
;
7569 struct listnode
*node
, *nnode
;
7571 int addpath_capable
;
7573 unsigned int first_as
;
7575 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
7579 json_path
= json_object_new_object();
7580 json_peer
= json_object_new_object();
7581 json_nexthop_global
= json_object_new_object();
7584 if (!json_paths
&& safi
== SAFI_EVPN
) {
7587 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf2
, sizeof(buf2
));
7588 vty_out(vty
, " Route %s", buf2
);
7590 if (path
->extra
&& path
->extra
->num_labels
) {
7591 bgp_evpn_label2str(path
->extra
->label
,
7592 path
->extra
->num_labels
, tag_buf
,
7594 vty_out(vty
, " VNI %s", tag_buf
);
7597 if (path
->extra
&& path
->extra
->parent
) {
7598 struct bgp_path_info
*parent_ri
;
7599 struct bgp_node
*rn
, *prn
;
7601 parent_ri
= (struct bgp_path_info
*)path
->extra
->parent
;
7602 rn
= parent_ri
->net
;
7603 if (rn
&& rn
->prn
) {
7605 vty_out(vty
, " Imported from %s:%s\n",
7607 (struct prefix_rd
*)&prn
->p
,
7608 buf1
, sizeof(buf1
)),
7617 /* Line1 display AS-path, Aggregator */
7620 if (!attr
->aspath
->json
)
7621 aspath_str_update(attr
->aspath
, true);
7622 json_object_lock(attr
->aspath
->json
);
7623 json_object_object_add(json_path
, "aspath",
7624 attr
->aspath
->json
);
7626 if (attr
->aspath
->segments
)
7627 aspath_print_vty(vty
, " %s",
7630 vty_out(vty
, " Local");
7634 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
)) {
7636 json_object_boolean_true_add(json_path
,
7639 vty_out(vty
, ", (removed)");
7642 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
7644 json_object_boolean_true_add(json_path
,
7647 vty_out(vty
, ", (stale)");
7650 if (CHECK_FLAG(attr
->flag
,
7651 ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
7653 json_object_int_add(json_path
, "aggregatorAs",
7654 attr
->aggregator_as
);
7655 json_object_string_add(
7656 json_path
, "aggregatorId",
7657 inet_ntoa(attr
->aggregator_addr
));
7659 vty_out(vty
, ", (aggregated by %u %s)",
7660 attr
->aggregator_as
,
7661 inet_ntoa(attr
->aggregator_addr
));
7665 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
7666 PEER_FLAG_REFLECTOR_CLIENT
)) {
7668 json_object_boolean_true_add(
7669 json_path
, "rxedFromRrClient");
7671 vty_out(vty
, ", (Received from a RR-client)");
7674 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
7675 PEER_FLAG_RSERVER_CLIENT
)) {
7677 json_object_boolean_true_add(
7678 json_path
, "rxedFromRsClient");
7680 vty_out(vty
, ", (Received from a RS-client)");
7683 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
7685 json_object_boolean_true_add(
7686 json_path
, "dampeningHistoryEntry");
7688 vty_out(vty
, ", (history entry)");
7689 } else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)) {
7691 json_object_boolean_true_add(
7692 json_path
, "dampeningSuppressed");
7694 vty_out(vty
, ", (suppressed due to dampening)");
7700 /* Line2 display Next-hop, Neighbor, Router-id */
7701 /* Display the nexthop */
7702 if ((p
->family
== AF_INET
|| p
->family
== AF_ETHERNET
7703 || p
->family
== AF_EVPN
)
7704 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7705 || safi
== SAFI_EVPN
7706 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7707 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7708 || safi
== SAFI_EVPN
) {
7710 json_object_string_add(
7711 json_nexthop_global
, "ip",
7713 attr
->mp_nexthop_global_in
));
7717 attr
->mp_nexthop_global_in
));
7720 json_object_string_add(
7721 json_nexthop_global
, "ip",
7722 inet_ntoa(attr
->nexthop
));
7725 inet_ntoa(attr
->nexthop
));
7729 json_object_string_add(json_nexthop_global
,
7733 json_object_string_add(
7734 json_nexthop_global
, "ip",
7736 &attr
->mp_nexthop_global
, buf
,
7738 json_object_string_add(json_nexthop_global
,
7740 json_object_string_add(json_nexthop_global
,
7745 &attr
->mp_nexthop_global
, buf
,
7750 /* Display the IGP cost or 'inaccessible' */
7751 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
7753 json_object_boolean_false_add(
7754 json_nexthop_global
, "accessible");
7756 vty_out(vty
, " (inaccessible)");
7758 if (path
->extra
&& path
->extra
->igpmetric
) {
7760 json_object_int_add(
7761 json_nexthop_global
, "metric",
7762 path
->extra
->igpmetric
);
7764 vty_out(vty
, " (metric %u)",
7765 path
->extra
->igpmetric
);
7768 /* IGP cost is 0, display this only for json */
7771 json_object_int_add(json_nexthop_global
,
7776 json_object_boolean_true_add(
7777 json_nexthop_global
, "accessible");
7780 /* Display peer "from" output */
7781 /* This path was originated locally */
7782 if (path
->peer
== bgp
->peer_self
) {
7784 if (safi
== SAFI_EVPN
7785 || (p
->family
== AF_INET
7786 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7788 json_object_string_add(
7789 json_peer
, "peerId", "0.0.0.0");
7791 vty_out(vty
, " from 0.0.0.0 ");
7794 json_object_string_add(json_peer
,
7797 vty_out(vty
, " from :: ");
7801 json_object_string_add(
7802 json_peer
, "routerId",
7803 inet_ntoa(bgp
->router_id
));
7805 vty_out(vty
, "(%s)", inet_ntoa(bgp
->router_id
));
7808 /* We RXed this path from one of our peers */
7812 json_object_string_add(
7813 json_peer
, "peerId",
7814 sockunion2str(&path
->peer
->su
, buf
,
7816 json_object_string_add(
7817 json_peer
, "routerId",
7819 &path
->peer
->remote_id
, buf1
,
7822 if (path
->peer
->hostname
)
7823 json_object_string_add(
7824 json_peer
, "hostname",
7825 path
->peer
->hostname
);
7827 if (path
->peer
->domainname
)
7828 json_object_string_add(
7829 json_peer
, "domainname",
7830 path
->peer
->domainname
);
7832 if (path
->peer
->conf_if
)
7833 json_object_string_add(
7834 json_peer
, "interface",
7835 path
->peer
->conf_if
);
7837 if (path
->peer
->conf_if
) {
7838 if (path
->peer
->hostname
7841 BGP_FLAG_SHOW_HOSTNAME
))
7842 vty_out(vty
, " from %s(%s)",
7843 path
->peer
->hostname
,
7844 path
->peer
->conf_if
);
7846 vty_out(vty
, " from %s",
7847 path
->peer
->conf_if
);
7849 if (path
->peer
->hostname
7852 BGP_FLAG_SHOW_HOSTNAME
))
7853 vty_out(vty
, " from %s(%s)",
7854 path
->peer
->hostname
,
7857 vty_out(vty
, " from %s",
7865 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
7866 vty_out(vty
, " (%s)",
7867 inet_ntoa(attr
->originator_id
));
7869 vty_out(vty
, " (%s)",
7872 &path
->peer
->remote_id
,
7873 buf1
, sizeof(buf1
)));
7878 * Note when vrfid of nexthop is different from that of prefix
7880 if (path
->extra
&& path
->extra
->bgp_orig
) {
7881 vrf_id_t nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
7886 if (path
->extra
->bgp_orig
->inst_type
7887 == BGP_INSTANCE_TYPE_DEFAULT
)
7889 vn
= VRF_DEFAULT_NAME
;
7891 vn
= path
->extra
->bgp_orig
->name
;
7893 json_object_string_add(json_path
, "nhVrfName",
7896 if (nexthop_vrfid
== VRF_UNKNOWN
) {
7897 json_object_int_add(json_path
,
7900 json_object_int_add(json_path
,
7901 "nhVrfId", (int)nexthop_vrfid
);
7904 if (nexthop_vrfid
== VRF_UNKNOWN
)
7905 vty_out(vty
, " vrf ?");
7907 vty_out(vty
, " vrf %u", nexthop_vrfid
);
7913 json_object_boolean_true_add(json_path
,
7914 "announceNexthopSelf");
7916 vty_out(vty
, " announce-nh-self");
7923 /* display the link-local nexthop */
7924 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
7926 json_nexthop_ll
= json_object_new_object();
7927 json_object_string_add(
7928 json_nexthop_ll
, "ip",
7930 &attr
->mp_nexthop_local
, buf
,
7932 json_object_string_add(json_nexthop_ll
, "afi",
7934 json_object_string_add(json_nexthop_ll
, "scope",
7937 json_object_boolean_true_add(json_nexthop_ll
,
7940 if (!attr
->mp_nexthop_prefer_global
)
7941 json_object_boolean_true_add(
7942 json_nexthop_ll
, "used");
7944 json_object_boolean_true_add(
7945 json_nexthop_global
, "used");
7947 vty_out(vty
, " (%s) %s\n",
7949 &attr
->mp_nexthop_local
, buf
,
7951 attr
->mp_nexthop_prefer_global
7956 /* If we do not have a link-local nexthop then we must flag the
7960 json_object_boolean_true_add(
7961 json_nexthop_global
, "used");
7964 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
7965 * Int/Ext/Local, Atomic, best */
7967 json_object_string_add(
7968 json_path
, "origin",
7969 bgp_origin_long_str
[attr
->origin
]);
7971 vty_out(vty
, " Origin %s",
7972 bgp_origin_long_str
[attr
->origin
]);
7974 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
7978 * Adding "metric" field to match with
7979 * corresponding CLI. "med" will be
7980 * deprecated in future.
7982 json_object_int_add(json_path
, "med",
7984 json_object_int_add(json_path
, "metric",
7987 vty_out(vty
, ", metric %u", attr
->med
);
7990 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
7992 json_object_int_add(json_path
, "localpref",
7995 vty_out(vty
, ", localpref %u",
7999 if (attr
->weight
!= 0) {
8001 json_object_int_add(json_path
, "weight",
8004 vty_out(vty
, ", weight %u", attr
->weight
);
8007 if (attr
->tag
!= 0) {
8009 json_object_int_add(json_path
, "tag",
8012 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
,
8016 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
8018 json_object_boolean_false_add(json_path
,
8021 vty_out(vty
, ", invalid");
8022 } else if (!CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
8024 json_object_boolean_true_add(json_path
,
8027 vty_out(vty
, ", valid");
8030 if (path
->peer
!= bgp
->peer_self
) {
8031 if (path
->peer
->as
== path
->peer
->local_as
) {
8032 if (CHECK_FLAG(bgp
->config
,
8033 BGP_CONFIG_CONFEDERATION
)) {
8035 json_object_string_add(
8040 ", confed-internal");
8043 json_object_string_add(
8047 vty_out(vty
, ", internal");
8050 if (bgp_confederation_peers_check(
8051 bgp
, path
->peer
->as
)) {
8053 json_object_string_add(
8058 ", confed-external");
8061 json_object_string_add(
8065 vty_out(vty
, ", external");
8068 } else if (path
->sub_type
== BGP_ROUTE_AGGREGATE
) {
8070 json_object_boolean_true_add(json_path
,
8072 json_object_boolean_true_add(json_path
,
8075 vty_out(vty
, ", aggregated, local");
8077 } else if (path
->type
!= ZEBRA_ROUTE_BGP
) {
8079 json_object_boolean_true_add(json_path
,
8082 vty_out(vty
, ", sourced");
8085 json_object_boolean_true_add(json_path
,
8087 json_object_boolean_true_add(json_path
,
8090 vty_out(vty
, ", sourced, local");
8094 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
8096 json_object_boolean_true_add(json_path
,
8099 vty_out(vty
, ", atomic-aggregate");
8102 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
)
8103 || (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)
8104 && bgp_path_info_mpath_count(path
))) {
8106 json_object_boolean_true_add(json_path
,
8109 vty_out(vty
, ", multipath");
8112 // Mark the bestpath(s)
8113 if (CHECK_FLAG(path
->flags
, BGP_PATH_DMED_SELECTED
)) {
8114 first_as
= aspath_get_first_as(attr
->aspath
);
8119 json_object_new_object();
8120 json_object_int_add(json_bestpath
,
8121 "bestpathFromAs", first_as
);
8124 vty_out(vty
, ", bestpath-from-AS %u",
8128 ", bestpath-from-AS Local");
8132 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
8136 json_object_new_object();
8137 json_object_boolean_true_add(json_bestpath
,
8140 vty_out(vty
, ", best");
8144 json_object_object_add(json_path
, "bestpath",
8150 /* Line 4 display Community */
8151 if (attr
->community
) {
8153 if (!attr
->community
->json
)
8154 community_str(attr
->community
, true);
8155 json_object_lock(attr
->community
->json
);
8156 json_object_object_add(json_path
, "community",
8157 attr
->community
->json
);
8159 vty_out(vty
, " Community: %s\n",
8160 attr
->community
->str
);
8164 /* Line 5 display Extended-community */
8165 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
8167 json_ext_community
= json_object_new_object();
8168 json_object_string_add(json_ext_community
,
8170 attr
->ecommunity
->str
);
8171 json_object_object_add(json_path
,
8172 "extendedCommunity",
8173 json_ext_community
);
8175 vty_out(vty
, " Extended Community: %s\n",
8176 attr
->ecommunity
->str
);
8180 /* Line 6 display Large community */
8181 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
8183 if (!attr
->lcommunity
->json
)
8184 lcommunity_str(attr
->lcommunity
, true);
8185 json_object_lock(attr
->lcommunity
->json
);
8186 json_object_object_add(json_path
,
8188 attr
->lcommunity
->json
);
8190 vty_out(vty
, " Large Community: %s\n",
8191 attr
->lcommunity
->str
);
8195 /* Line 7 display Originator, Cluster-id */
8196 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
8197 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
8199 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
8201 json_object_string_add(
8202 json_path
, "originatorId",
8203 inet_ntoa(attr
->originator_id
));
8205 vty_out(vty
, " Originator: %s",
8206 inet_ntoa(attr
->originator_id
));
8209 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
8214 json_object_new_object();
8215 json_cluster_list_list
=
8216 json_object_new_array();
8219 i
< attr
->cluster
->length
/ 4;
8221 json_string
= json_object_new_string(
8225 json_object_array_add(
8226 json_cluster_list_list
,
8230 /* struct cluster_list does not have
8232 * aspath and community do. Add this
8235 json_object_string_add(json_cluster_list,
8236 "string", attr->cluster->str);
8238 json_object_object_add(
8239 json_cluster_list
, "list",
8240 json_cluster_list_list
);
8241 json_object_object_add(
8242 json_path
, "clusterList",
8245 vty_out(vty
, ", Cluster list: ");
8248 i
< attr
->cluster
->length
/ 4;
8262 if (path
->extra
&& path
->extra
->damp_info
)
8263 bgp_damp_info_vty(vty
, path
, json_path
);
8266 if (path
->extra
&& bgp_is_valid_label(&path
->extra
->label
[0])
8267 && safi
!= SAFI_EVPN
) {
8268 mpls_label_t label
= label_pton(&path
->extra
->label
[0]);
8271 json_object_int_add(json_path
, "remoteLabel",
8274 vty_out(vty
, " Remote label: %d\n", label
);
8278 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
8280 json_object_int_add(json_path
, "labelIndex",
8283 vty_out(vty
, " Label Index: %d\n",
8287 /* Line 8 display Addpath IDs */
8288 if (path
->addpath_rx_id
8289 || bgp_addpath_info_has_ids(&path
->tx_addpath
)) {
8291 json_object_int_add(json_path
, "addpathRxId",
8292 path
->addpath_rx_id
);
8294 /* Keep backwards compatibility with the old API
8295 * by putting TX All's ID in the old field
8297 json_object_int_add(
8298 json_path
, "addpathTxId",
8299 path
->tx_addpath
.addpath_tx_id
8302 /* ... but create a specific field for each
8305 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
8306 json_object_int_add(
8308 bgp_addpath_names(i
)
8314 vty_out(vty
, " AddPath ID: RX %u, ",
8315 path
->addpath_rx_id
);
8317 route_vty_out_tx_ids(vty
, &path
->tx_addpath
);
8321 /* If we used addpath to TX a non-bestpath we need to display
8322 * "Advertised to" on a path-by-path basis
8324 if (bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
8327 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
8329 bgp_addpath_encode_tx(peer
, afi
, safi
);
8330 has_adj
= bgp_adj_out_lookup(
8332 bgp_addpath_id_for_peer(
8334 &path
->tx_addpath
));
8336 if ((addpath_capable
&& has_adj
)
8337 || (!addpath_capable
&& has_adj
8338 && CHECK_FLAG(path
->flags
,
8339 BGP_PATH_SELECTED
))) {
8340 if (json_path
&& !json_adv_to
)
8342 json_object_new_object();
8344 route_vty_out_advertised_to(
8353 json_object_object_add(json_path
,
8364 /* Line 9 display Uptime */
8365 tbuf
= time(NULL
) - (bgp_clock() - path
->uptime
);
8367 json_last_update
= json_object_new_object();
8368 json_object_int_add(json_last_update
, "epoch", tbuf
);
8369 json_object_string_add(json_last_update
, "string",
8371 json_object_object_add(json_path
, "lastUpdate",
8374 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
8376 /* Line 10 display PMSI tunnel attribute, if present */
8377 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
8378 const char *str
= lookup_msg(bgp_pmsi_tnltype_str
,
8379 attr
->pmsi_tnl_type
,
8380 PMSI_TNLTYPE_STR_DEFAULT
);
8383 json_pmsi
= json_object_new_object();
8384 json_object_string_add(json_pmsi
,
8386 json_object_object_add(json_path
, "pmsi",
8389 vty_out(vty
, " PMSI Tunnel Type: %s\n",
8395 /* We've constructed the json object for this path, add it to the json
8399 if (json_nexthop_global
|| json_nexthop_ll
) {
8400 json_nexthops
= json_object_new_array();
8402 if (json_nexthop_global
)
8403 json_object_array_add(json_nexthops
,
8404 json_nexthop_global
);
8406 if (json_nexthop_ll
)
8407 json_object_array_add(json_nexthops
,
8410 json_object_object_add(json_path
, "nexthops",
8414 json_object_object_add(json_path
, "peer", json_peer
);
8415 json_object_array_add(json_paths
, json_path
);
8420 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
8421 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
8422 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
8424 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
8425 const char *prefix_list_str
, afi_t afi
,
8426 safi_t safi
, enum bgp_show_type type
);
8427 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
8428 const char *filter
, afi_t afi
, safi_t safi
,
8429 enum bgp_show_type type
);
8430 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
8431 const char *rmap_str
, afi_t afi
, safi_t safi
,
8432 enum bgp_show_type type
);
8433 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
8434 const char *com
, int exact
, afi_t afi
,
8436 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
8437 const char *prefix
, afi_t afi
, safi_t safi
,
8438 enum bgp_show_type type
);
8439 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
8440 afi_t afi
, safi_t safi
, enum bgp_show_type type
);
8441 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
8442 const char *comstr
, int exact
, afi_t afi
,
8443 safi_t safi
, bool use_json
);
8446 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
8447 struct bgp_table
*table
, enum bgp_show_type type
,
8448 void *output_arg
, bool use_json
, char *rd
,
8449 int is_last
, unsigned long *output_cum
,
8450 unsigned long *total_cum
,
8451 unsigned long *json_header_depth
)
8453 struct bgp_path_info
*pi
;
8454 struct bgp_node
*rn
;
8457 unsigned long output_count
= 0;
8458 unsigned long total_count
= 0;
8461 json_object
*json_paths
= NULL
;
8464 if (output_cum
&& *output_cum
!= 0)
8467 if (use_json
&& !*json_header_depth
) {
8469 "{\n \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
8470 ",\n \"routerId\": \"%s\",\n \"defaultLocPrf\": %u,\n"
8471 " \"localAS\": %u,\n \"routes\": { ",
8472 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
8473 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
8476 table
->version
, inet_ntoa(bgp
->router_id
),
8477 bgp
->default_local_pref
, bgp
->as
);
8478 *json_header_depth
= 2;
8480 vty_out(vty
, " \"routeDistinguishers\" : {");
8481 ++*json_header_depth
;
8485 if (use_json
&& rd
) {
8486 vty_out(vty
, " \"%s\" : { ", rd
);
8489 /* Start processing of routes. */
8490 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
8491 pi
= bgp_node_get_bgp_path_info(rn
);
8497 json_paths
= json_object_new_array();
8501 for (; pi
; pi
= pi
->next
) {
8503 if (type
== bgp_show_type_flap_statistics
8504 || type
== bgp_show_type_flap_neighbor
8505 || type
== bgp_show_type_dampend_paths
8506 || type
== bgp_show_type_damp_neighbor
) {
8507 if (!(pi
->extra
&& pi
->extra
->damp_info
))
8510 if (type
== bgp_show_type_regexp
) {
8511 regex_t
*regex
= output_arg
;
8513 if (bgp_regexec(regex
, pi
->attr
->aspath
)
8517 if (type
== bgp_show_type_prefix_list
) {
8518 struct prefix_list
*plist
= output_arg
;
8520 if (prefix_list_apply(plist
, &rn
->p
)
8524 if (type
== bgp_show_type_filter_list
) {
8525 struct as_list
*as_list
= output_arg
;
8527 if (as_list_apply(as_list
, pi
->attr
->aspath
)
8528 != AS_FILTER_PERMIT
)
8531 if (type
== bgp_show_type_route_map
) {
8532 struct route_map
*rmap
= output_arg
;
8533 struct bgp_path_info path
;
8534 struct attr dummy_attr
;
8537 bgp_attr_dup(&dummy_attr
, pi
->attr
);
8539 path
.peer
= pi
->peer
;
8540 path
.attr
= &dummy_attr
;
8542 ret
= route_map_apply(rmap
, &rn
->p
, RMAP_BGP
,
8544 if (ret
== RMAP_DENYMATCH
)
8547 if (type
== bgp_show_type_neighbor
8548 || type
== bgp_show_type_flap_neighbor
8549 || type
== bgp_show_type_damp_neighbor
) {
8550 union sockunion
*su
= output_arg
;
8552 if (pi
->peer
== NULL
8553 || pi
->peer
->su_remote
== NULL
8554 || !sockunion_same(pi
->peer
->su_remote
, su
))
8557 if (type
== bgp_show_type_cidr_only
) {
8558 uint32_t destination
;
8560 destination
= ntohl(rn
->p
.u
.prefix4
.s_addr
);
8561 if (IN_CLASSC(destination
)
8562 && rn
->p
.prefixlen
== 24)
8564 if (IN_CLASSB(destination
)
8565 && rn
->p
.prefixlen
== 16)
8567 if (IN_CLASSA(destination
)
8568 && rn
->p
.prefixlen
== 8)
8571 if (type
== bgp_show_type_prefix_longer
) {
8573 if (!prefix_match(p
, &rn
->p
))
8576 if (type
== bgp_show_type_community_all
) {
8577 if (!pi
->attr
->community
)
8580 if (type
== bgp_show_type_community
) {
8581 struct community
*com
= output_arg
;
8583 if (!pi
->attr
->community
8584 || !community_match(pi
->attr
->community
,
8588 if (type
== bgp_show_type_community_exact
) {
8589 struct community
*com
= output_arg
;
8591 if (!pi
->attr
->community
8592 || !community_cmp(pi
->attr
->community
, com
))
8595 if (type
== bgp_show_type_community_list
) {
8596 struct community_list
*list
= output_arg
;
8598 if (!community_list_match(pi
->attr
->community
,
8602 if (type
== bgp_show_type_community_list_exact
) {
8603 struct community_list
*list
= output_arg
;
8605 if (!community_list_exact_match(
8606 pi
->attr
->community
, list
))
8609 if (type
== bgp_show_type_lcommunity
) {
8610 struct lcommunity
*lcom
= output_arg
;
8612 if (!pi
->attr
->lcommunity
8613 || !lcommunity_match(pi
->attr
->lcommunity
,
8617 if (type
== bgp_show_type_lcommunity_list
) {
8618 struct community_list
*list
= output_arg
;
8620 if (!lcommunity_list_match(pi
->attr
->lcommunity
,
8624 if (type
== bgp_show_type_lcommunity_all
) {
8625 if (!pi
->attr
->lcommunity
)
8628 if (type
== bgp_show_type_dampend_paths
8629 || type
== bgp_show_type_damp_neighbor
) {
8630 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
)
8631 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
8635 if (!use_json
&& header
) {
8636 vty_out(vty
, "BGP table version is %" PRIu64
8637 ", local router ID is %s, vrf id ",
8639 inet_ntoa(bgp
->router_id
));
8640 if (bgp
->vrf_id
== VRF_UNKNOWN
)
8641 vty_out(vty
, "%s", VRFID_NONE_STR
);
8643 vty_out(vty
, "%u", bgp
->vrf_id
);
8645 vty_out(vty
, "Default local pref %u, ",
8646 bgp
->default_local_pref
);
8647 vty_out(vty
, "local AS %u\n", bgp
->as
);
8648 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
8649 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
8650 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
8651 if (type
== bgp_show_type_dampend_paths
8652 || type
== bgp_show_type_damp_neighbor
)
8653 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
8654 else if (type
== bgp_show_type_flap_statistics
8655 || type
== bgp_show_type_flap_neighbor
)
8656 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
8658 vty_out(vty
, BGP_SHOW_HEADER
);
8661 if (rd
!= NULL
&& !display
&& !output_count
) {
8664 "Route Distinguisher: %s\n",
8667 if (type
== bgp_show_type_dampend_paths
8668 || type
== bgp_show_type_damp_neighbor
)
8669 damp_route_vty_out(vty
, &rn
->p
, pi
, display
,
8670 safi
, use_json
, json_paths
);
8671 else if (type
== bgp_show_type_flap_statistics
8672 || type
== bgp_show_type_flap_neighbor
)
8673 flap_route_vty_out(vty
, &rn
->p
, pi
, display
,
8674 safi
, use_json
, json_paths
);
8676 route_vty_out(vty
, &rn
->p
, pi
, display
, safi
,
8688 if (p
->family
== AF_FLOWSPEC
) {
8689 char retstr
[BGP_FLOWSPEC_STRING_DISPLAY_MAX
];
8691 bgp_fs_nlri_get_string((unsigned char *)
8692 p
->u
.prefix_flowspec
.ptr
,
8693 p
->u
.prefix_flowspec
8696 NLRI_STRING_FORMAT_MIN
,
8699 vty_out(vty
, "\"%s/%d\": ",
8701 p
->u
.prefix_flowspec
.prefixlen
);
8703 vty_out(vty
, ",\"%s/%d\": ",
8705 p
->u
.prefix_flowspec
.prefixlen
);
8707 prefix2str(p
, buf2
, sizeof(buf2
));
8709 vty_out(vty
, "\"%s\": ", buf2
);
8711 vty_out(vty
, ",\"%s\": ", buf2
);
8714 json_object_to_json_string(json_paths
));
8715 json_object_free(json_paths
);
8722 output_count
+= *output_cum
;
8723 *output_cum
= output_count
;
8726 total_count
+= *total_cum
;
8727 *total_cum
= total_count
;
8731 vty_out(vty
, " }%s ", (is_last
? "" : ","));
8735 for (i
= 0; i
< *json_header_depth
; ++i
)
8736 vty_out(vty
, " } ");
8740 /* No route is displayed */
8741 if (output_count
== 0) {
8742 if (type
== bgp_show_type_normal
)
8744 "No BGP prefixes displayed, %ld exist\n",
8748 "\nDisplayed %ld routes and %ld total paths\n",
8749 output_count
, total_count
);
8756 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
8757 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
8758 enum bgp_show_type type
, void *output_arg
, bool use_json
)
8760 struct bgp_node
*rn
, *next
;
8761 unsigned long output_cum
= 0;
8762 unsigned long total_cum
= 0;
8763 unsigned long json_header_depth
= 0;
8764 struct bgp_table
*itable
;
8767 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
8769 for (rn
= bgp_table_top(table
); rn
; rn
= next
) {
8770 next
= bgp_route_next(rn
);
8771 if (prd_match
&& memcmp(rn
->p
.u
.val
, prd_match
->val
, 8) != 0)
8774 itable
= bgp_node_get_bgp_table_info(rn
);
8775 if (itable
!= NULL
) {
8776 struct prefix_rd prd
;
8777 char rd
[RD_ADDRSTRLEN
];
8779 memcpy(&prd
, &(rn
->p
), sizeof(struct prefix_rd
));
8780 prefix_rd2str(&prd
, rd
, sizeof(rd
));
8781 bgp_show_table(vty
, bgp
, safi
, itable
, type
, output_arg
,
8782 use_json
, rd
, next
== NULL
, &output_cum
,
8783 &total_cum
, &json_header_depth
);
8789 if (output_cum
== 0)
8790 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
8794 "\nDisplayed %ld routes and %ld total paths\n",
8795 output_cum
, total_cum
);
8799 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
8800 enum bgp_show_type type
, void *output_arg
, bool use_json
)
8802 struct bgp_table
*table
;
8803 unsigned long json_header_depth
= 0;
8806 bgp
= bgp_get_default();
8811 vty_out(vty
, "No BGP process is configured\n");
8813 vty_out(vty
, "{}\n");
8817 table
= bgp
->rib
[afi
][safi
];
8818 /* use MPLS and ENCAP specific shows until they are merged */
8819 if (safi
== SAFI_MPLS_VPN
) {
8820 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
8821 output_arg
, use_json
);
8824 if (safi
== SAFI_FLOWSPEC
&& type
== bgp_show_type_detail
) {
8825 return bgp_show_table_flowspec(vty
, bgp
, afi
, table
, type
,
8826 output_arg
, use_json
,
8829 /* labeled-unicast routes live in the unicast table */
8830 else if (safi
== SAFI_LABELED_UNICAST
)
8831 safi
= SAFI_UNICAST
;
8833 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, use_json
,
8834 NULL
, 1, NULL
, NULL
, &json_header_depth
);
8837 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
8838 safi_t safi
, bool use_json
)
8840 struct listnode
*node
, *nnode
;
8843 bool route_output
= false;
8846 vty_out(vty
, "{\n");
8848 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
8849 route_output
= true;
8852 vty_out(vty
, ",\n");
8856 vty_out(vty
, "\"%s\":",
8857 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
8861 vty_out(vty
, "\nInstance %s:\n",
8862 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
8866 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
8871 vty_out(vty
, "}\n");
8872 else if (!route_output
)
8873 vty_out(vty
, "%% BGP instance not found\n");
8876 /* Header of detailed BGP route information */
8877 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
8878 struct bgp_node
*rn
, struct prefix_rd
*prd
,
8879 afi_t afi
, safi_t safi
, json_object
*json
)
8881 struct bgp_path_info
*pi
;
8884 struct listnode
*node
, *nnode
;
8885 char buf1
[RD_ADDRSTRLEN
];
8886 char buf2
[INET6_ADDRSTRLEN
];
8887 char buf3
[EVPN_ROUTE_STRLEN
];
8888 char prefix_str
[BUFSIZ
];
8893 int route_filter_translated_v4
= 0;
8894 int route_filter_v4
= 0;
8895 int route_filter_translated_v6
= 0;
8896 int route_filter_v6
= 0;
8899 int accept_own_nexthop
= 0;
8902 int no_advertise
= 0;
8906 int has_valid_label
= 0;
8907 mpls_label_t label
= 0;
8908 json_object
*json_adv_to
= NULL
;
8911 has_valid_label
= bgp_is_valid_label(&rn
->local_label
);
8913 if (has_valid_label
)
8914 label
= label_pton(&rn
->local_label
);
8917 if (has_valid_label
)
8918 json_object_int_add(json
, "localLabel", label
);
8920 json_object_string_add(
8922 prefix2str(p
, prefix_str
, sizeof(prefix_str
)));
8924 if (safi
== SAFI_EVPN
)
8925 vty_out(vty
, "BGP routing table entry for %s%s%s\n",
8926 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
))
8929 bgp_evpn_route2str((struct prefix_evpn
*)p
,
8930 buf3
, sizeof(buf3
)));
8932 vty_out(vty
, "BGP routing table entry for %s%s%s/%d\n",
8933 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
8934 ? prefix_rd2str(prd
, buf1
,
8937 safi
== SAFI_MPLS_VPN
? ":" : "",
8938 inet_ntop(p
->family
, &p
->u
.prefix
, buf2
,
8942 if (has_valid_label
)
8943 vty_out(vty
, "Local label: %d\n", label
);
8944 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
8945 vty_out(vty
, "not allocated\n");
8948 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
8950 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
8952 if (pi
->extra
&& pi
->extra
->suppress
)
8955 if (pi
->attr
->community
== NULL
)
8958 no_advertise
+= community_include(
8959 pi
->attr
->community
, COMMUNITY_NO_ADVERTISE
);
8960 no_export
+= community_include(pi
->attr
->community
,
8961 COMMUNITY_NO_EXPORT
);
8962 local_as
+= community_include(pi
->attr
->community
,
8963 COMMUNITY_LOCAL_AS
);
8964 accept_own
+= community_include(pi
->attr
->community
,
8965 COMMUNITY_ACCEPT_OWN
);
8966 route_filter_translated_v4
+= community_include(
8967 pi
->attr
->community
,
8968 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4
);
8969 route_filter_translated_v6
+= community_include(
8970 pi
->attr
->community
,
8971 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6
);
8972 route_filter_v4
+= community_include(
8973 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v4
);
8974 route_filter_v6
+= community_include(
8975 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v6
);
8976 llgr_stale
+= community_include(pi
->attr
->community
,
8977 COMMUNITY_LLGR_STALE
);
8978 no_llgr
+= community_include(pi
->attr
->community
,
8980 accept_own_nexthop
+=
8981 community_include(pi
->attr
->community
,
8982 COMMUNITY_ACCEPT_OWN_NEXTHOP
);
8983 blackhole
+= community_include(pi
->attr
->community
,
8984 COMMUNITY_BLACKHOLE
);
8985 no_peer
+= community_include(pi
->attr
->community
,
8991 vty_out(vty
, "Paths: (%d available", count
);
8993 vty_out(vty
, ", best #%d", best
);
8994 if (safi
== SAFI_UNICAST
)
8995 vty_out(vty
, ", table %s",
8997 == BGP_INSTANCE_TYPE_DEFAULT
)
9001 vty_out(vty
, ", no best path");
9005 ", accept own local route exported and imported in different VRF");
9006 else if (route_filter_translated_v4
)
9008 ", mark translated RTs for VPNv4 route filtering");
9009 else if (route_filter_v4
)
9011 ", attach RT as-is for VPNv4 route filtering");
9012 else if (route_filter_translated_v6
)
9014 ", mark translated RTs for VPNv6 route filtering");
9015 else if (route_filter_v6
)
9017 ", attach RT as-is for VPNv6 route filtering");
9018 else if (llgr_stale
)
9020 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
9023 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
9024 else if (accept_own_nexthop
)
9026 ", accept local nexthop");
9028 vty_out(vty
, ", inform peer to blackhole prefix");
9030 vty_out(vty
, ", not advertised to EBGP peer");
9031 else if (no_advertise
)
9032 vty_out(vty
, ", not advertised to any peer");
9034 vty_out(vty
, ", not advertised outside local AS");
9037 ", inform EBGP peer not to advertise to their EBGP peers");
9041 ", Advertisements suppressed by an aggregate.");
9042 vty_out(vty
, ")\n");
9045 /* If we are not using addpath then we can display Advertised to and
9047 * show what peers we advertised the bestpath to. If we are using
9049 * though then we must display Advertised to on a path-by-path basis. */
9050 if (!bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
9051 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
9052 if (bgp_adj_out_lookup(peer
, rn
, 0)) {
9053 if (json
&& !json_adv_to
)
9054 json_adv_to
= json_object_new_object();
9056 route_vty_out_advertised_to(
9058 " Advertised to non peer-group peers:\n ",
9065 json_object_object_add(json
, "advertisedTo",
9070 vty_out(vty
, " Not advertised to any peer");
9076 /* Display specified route of BGP table. */
9077 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
9078 struct bgp_table
*rib
, const char *ip_str
,
9079 afi_t afi
, safi_t safi
,
9080 struct prefix_rd
*prd
, int prefix_check
,
9081 enum bgp_path_type pathtype
, bool use_json
)
9086 struct prefix match
;
9087 struct bgp_node
*rn
;
9088 struct bgp_node
*rm
;
9089 struct bgp_path_info
*pi
;
9090 struct bgp_table
*table
;
9091 json_object
*json
= NULL
;
9092 json_object
*json_paths
= NULL
;
9094 /* Check IP address argument. */
9095 ret
= str2prefix(ip_str
, &match
);
9097 vty_out(vty
, "address is malformed\n");
9101 match
.family
= afi2family(afi
);
9104 json
= json_object_new_object();
9105 json_paths
= json_object_new_array();
9108 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
9109 for (rn
= bgp_table_top(rib
); rn
; rn
= bgp_route_next(rn
)) {
9110 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
9112 table
= bgp_node_get_bgp_table_info(rn
);
9118 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
9122 && rm
->p
.prefixlen
!= match
.prefixlen
) {
9123 bgp_unlock_node(rm
);
9127 for (pi
= bgp_node_get_bgp_path_info(rm
); pi
;
9130 route_vty_out_detail_header(
9132 (struct prefix_rd
*)&rn
->p
,
9133 AFI_IP
, safi
, json
);
9138 if (pathtype
== BGP_PATH_SHOW_ALL
9139 || (pathtype
== BGP_PATH_SHOW_BESTPATH
9140 && CHECK_FLAG(pi
->flags
,
9142 || (pathtype
== BGP_PATH_SHOW_MULTIPATH
9143 && (CHECK_FLAG(pi
->flags
,
9145 || CHECK_FLAG(pi
->flags
,
9146 BGP_PATH_SELECTED
))))
9147 route_vty_out_detail(vty
, bgp
, &rm
->p
,
9152 bgp_unlock_node(rm
);
9154 } else if (safi
== SAFI_FLOWSPEC
) {
9155 display
= bgp_flowspec_display_match_per_ip(afi
, rib
,
9156 &match
, prefix_check
,
9163 if ((rn
= bgp_node_match(rib
, &match
)) != NULL
) {
9165 || rn
->p
.prefixlen
== match
.prefixlen
) {
9166 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
;
9169 route_vty_out_detail_header(
9170 vty
, bgp
, rn
, NULL
, afi
,
9176 if (pathtype
== BGP_PATH_SHOW_ALL
9178 == BGP_PATH_SHOW_BESTPATH
9183 == BGP_PATH_SHOW_MULTIPATH
9189 BGP_PATH_SELECTED
))))
9190 route_vty_out_detail(
9191 vty
, bgp
, &rn
->p
, pi
,
9192 afi
, safi
, json_paths
);
9196 bgp_unlock_node(rn
);
9202 json_object_object_add(json
, "paths", json_paths
);
9204 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
9205 json
, JSON_C_TO_STRING_PRETTY
));
9206 json_object_free(json
);
9209 vty_out(vty
, "%% Network not in table\n");
9217 /* Display specified route of Main RIB */
9218 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
9219 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
9220 int prefix_check
, enum bgp_path_type pathtype
,
9224 bgp
= bgp_get_default();
9227 vty_out(vty
, "No BGP process is configured\n");
9229 vty_out(vty
, "{}\n");
9234 /* labeled-unicast routes live in the unicast table */
9235 if (safi
== SAFI_LABELED_UNICAST
)
9236 safi
= SAFI_UNICAST
;
9238 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
9239 afi
, safi
, prd
, prefix_check
, pathtype
,
9243 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
9244 struct cmd_token
**argv
, afi_t afi
, safi_t safi
,
9247 struct lcommunity
*lcom
;
9253 b
= buffer_new(1024);
9254 for (i
= 0; i
< argc
; i
++) {
9256 buffer_putc(b
, ' ');
9258 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
9260 buffer_putstr(b
, argv
[i
]->arg
);
9264 buffer_putc(b
, '\0');
9266 str
= buffer_getstr(b
);
9269 lcom
= lcommunity_str2com(str
);
9270 XFREE(MTYPE_TMP
, str
);
9272 vty_out(vty
, "%% Large-community malformed\n");
9276 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_lcommunity
, lcom
,
9280 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
9281 const char *lcom
, afi_t afi
, safi_t safi
,
9284 struct community_list
*list
;
9286 list
= community_list_lookup(bgp_clist
, lcom
, 0,
9287 LARGE_COMMUNITY_LIST_MASTER
);
9289 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
9294 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_lcommunity_list
,
9298 DEFUN (show_ip_bgp_large_community_list
,
9299 show_ip_bgp_large_community_list_cmd
,
9300 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community-list <(1-500)|WORD> [json]",
9304 BGP_INSTANCE_HELP_STR
9306 BGP_SAFI_WITH_LABEL_HELP_STR
9307 "Display routes matching the large-community-list\n"
9308 "large-community-list number\n"
9309 "large-community-list name\n"
9313 afi_t afi
= AFI_IP6
;
9314 safi_t safi
= SAFI_UNICAST
;
9317 if (argv_find(argv
, argc
, "ip", &idx
))
9319 if (argv_find(argv
, argc
, "view", &idx
)
9320 || argv_find(argv
, argc
, "vrf", &idx
))
9321 vrf
= argv
[++idx
]->arg
;
9322 if (argv_find(argv
, argc
, "ipv4", &idx
)
9323 || argv_find(argv
, argc
, "ipv6", &idx
)) {
9324 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
9325 if (argv_find(argv
, argc
, "unicast", &idx
)
9326 || argv_find(argv
, argc
, "multicast", &idx
))
9327 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
9330 bool uj
= use_json(argc
, argv
);
9332 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
9334 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
9338 argv_find(argv
, argc
, "large-community-list", &idx
);
9339 return bgp_show_lcommunity_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
, safi
,
9342 DEFUN (show_ip_bgp_large_community
,
9343 show_ip_bgp_large_community_cmd
,
9344 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [AA:BB:CC] [json]",
9348 BGP_INSTANCE_HELP_STR
9350 BGP_SAFI_WITH_LABEL_HELP_STR
9351 "Display routes matching the large-communities\n"
9352 "List of large-community numbers\n"
9356 afi_t afi
= AFI_IP6
;
9357 safi_t safi
= SAFI_UNICAST
;
9360 if (argv_find(argv
, argc
, "ip", &idx
))
9362 if (argv_find(argv
, argc
, "view", &idx
)
9363 || argv_find(argv
, argc
, "vrf", &idx
))
9364 vrf
= argv
[++idx
]->arg
;
9365 if (argv_find(argv
, argc
, "ipv4", &idx
)
9366 || argv_find(argv
, argc
, "ipv6", &idx
)) {
9367 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
9368 if (argv_find(argv
, argc
, "unicast", &idx
)
9369 || argv_find(argv
, argc
, "multicast", &idx
))
9370 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
9373 bool uj
= use_json(argc
, argv
);
9375 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
9377 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
9381 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
))
9382 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
, afi
, safi
, uj
);
9384 return bgp_show(vty
, bgp
, afi
, safi
,
9385 bgp_show_type_lcommunity_all
, NULL
, uj
);
9388 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
9392 /* BGP route print out function without JSON */
9395 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
9396 <dampening <parameters>\
9401 |community-list <(1-500)|WORD> [exact-match]\
9402 |A.B.C.D/M longer-prefixes\
9403 |X:X::X:X/M longer-prefixes\
9408 BGP_INSTANCE_HELP_STR
9410 BGP_SAFI_WITH_LABEL_HELP_STR
9411 "Display detailed information about dampening\n"
9412 "Display detail of configured dampening parameters\n"
9413 "Display routes matching the route-map\n"
9414 "A route-map to match on\n"
9415 "Display routes conforming to the prefix-list\n"
9416 "Prefix-list name\n"
9417 "Display routes conforming to the filter-list\n"
9418 "Regular expression access list name\n"
9419 "BGP RIB advertisement statistics\n"
9420 "Display routes matching the community-list\n"
9421 "community-list number\n"
9422 "community-list name\n"
9423 "Exact match of the communities\n"
9425 "Display route and more specific routes\n"
9427 "Display route and more specific routes\n")
9429 afi_t afi
= AFI_IP6
;
9430 safi_t safi
= SAFI_UNICAST
;
9431 int exact_match
= 0;
9432 struct bgp
*bgp
= NULL
;
9435 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9440 if (argv_find(argv
, argc
, "dampening", &idx
)) {
9441 if (argv_find(argv
, argc
, "parameters", &idx
))
9442 return bgp_show_dampening_parameters(vty
, afi
, safi
);
9445 if (argv_find(argv
, argc
, "prefix-list", &idx
))
9446 return bgp_show_prefix_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9447 safi
, bgp_show_type_prefix_list
);
9449 if (argv_find(argv
, argc
, "filter-list", &idx
))
9450 return bgp_show_filter_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9451 safi
, bgp_show_type_filter_list
);
9453 if (argv_find(argv
, argc
, "statistics", &idx
))
9454 return bgp_table_stats(vty
, bgp
, afi
, safi
);
9456 if (argv_find(argv
, argc
, "route-map", &idx
))
9457 return bgp_show_route_map(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9458 safi
, bgp_show_type_route_map
);
9460 if (argv_find(argv
, argc
, "community-list", &idx
)) {
9461 const char *clist_number_or_name
= argv
[++idx
]->arg
;
9462 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
9464 return bgp_show_community_list(vty
, bgp
, clist_number_or_name
,
9465 exact_match
, afi
, safi
);
9468 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
9469 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
9470 return bgp_show_prefix_longer(vty
, bgp
, argv
[idx
]->arg
, afi
,
9472 bgp_show_type_prefix_longer
);
9477 /* BGP route print out function with JSON */
9478 DEFUN (show_ip_bgp_json
,
9479 show_ip_bgp_json_cmd
,
9480 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
9482 |dampening <flap-statistics|dampened-paths>\
9483 |community [AA:NN|local-AS|no-advertise|no-export\
9484 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
9485 |accept-own|accept-own-nexthop|route-filter-v6\
9486 |route-filter-v4|route-filter-translated-v6\
9487 |route-filter-translated-v4] [exact-match]\
9492 BGP_INSTANCE_HELP_STR
9494 BGP_SAFI_WITH_LABEL_HELP_STR
9495 "Display only routes with non-natural netmasks\n"
9496 "Display detailed information about dampening\n"
9497 "Display flap statistics of routes\n"
9498 "Display paths suppressed due to dampening\n"
9499 "Display routes matching the communities\n"
9501 "Do not send outside local AS (well-known community)\n"
9502 "Do not advertise to any peer (well-known community)\n"
9503 "Do not export to next AS (well-known community)\n"
9504 "Graceful shutdown (well-known community)\n"
9505 "Do not export to any peer (well-known community)\n"
9506 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
9507 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
9508 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
9509 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
9510 "Should accept VPN route with local nexthop (well-known community)\n"
9511 "RT VPNv6 route filtering (well-known community)\n"
9512 "RT VPNv4 route filtering (well-known community)\n"
9513 "RT translated VPNv6 route filtering (well-known community)\n"
9514 "RT translated VPNv4 route filtering (well-known community)\n"
9515 "Exact match of the communities\n"
9518 afi_t afi
= AFI_IP6
;
9519 safi_t safi
= SAFI_UNICAST
;
9520 enum bgp_show_type sh_type
= bgp_show_type_normal
;
9521 struct bgp
*bgp
= NULL
;
9523 int exact_match
= 0;
9524 bool uj
= use_json(argc
, argv
);
9529 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9534 if (argv_find(argv
, argc
, "cidr-only", &idx
))
9535 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_cidr_only
,
9538 if (argv_find(argv
, argc
, "dampening", &idx
)) {
9539 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
9540 return bgp_show(vty
, bgp
, afi
, safi
,
9541 bgp_show_type_dampend_paths
, NULL
, uj
);
9542 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
9543 return bgp_show(vty
, bgp
, afi
, safi
,
9544 bgp_show_type_flap_statistics
, NULL
,
9548 if (argv_find(argv
, argc
, "community", &idx
)) {
9549 char *maybecomm
= NULL
;
9550 char *community
= NULL
;
9552 if (idx
+ 1 < argc
) {
9553 if (argv
[idx
+ 1]->type
== VARIABLE_TKN
)
9554 maybecomm
= argv
[idx
+ 1]->arg
;
9556 maybecomm
= argv
[idx
+ 1]->text
;
9559 if (maybecomm
&& !strmatch(maybecomm
, "json")
9560 && !strmatch(maybecomm
, "exact-match"))
9561 community
= maybecomm
;
9563 if (argv_find(argv
, argc
, "exact-match", &idx
))
9567 return bgp_show_community(vty
, bgp
, community
,
9568 exact_match
, afi
, safi
, uj
);
9570 return (bgp_show(vty
, bgp
, afi
, safi
,
9571 bgp_show_type_community_all
, NULL
,
9575 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
, NULL
, uj
);
9578 DEFUN (show_ip_bgp_route
,
9579 show_ip_bgp_route_cmd
,
9580 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]"
9581 "<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [json]",
9585 BGP_INSTANCE_HELP_STR
9587 BGP_SAFI_WITH_LABEL_HELP_STR
9588 "Network in the BGP routing table to display\n"
9590 "Network in the BGP routing table to display\n"
9592 "Display only the bestpath\n"
9593 "Display only multipaths\n"
9596 int prefix_check
= 0;
9598 afi_t afi
= AFI_IP6
;
9599 safi_t safi
= SAFI_UNICAST
;
9600 char *prefix
= NULL
;
9601 struct bgp
*bgp
= NULL
;
9602 enum bgp_path_type path_type
;
9603 bool uj
= use_json(argc
, argv
);
9607 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9614 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
9618 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
9619 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
9620 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
9622 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
9623 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
9626 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
9627 && afi
!= AFI_IP6
) {
9629 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
9632 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
9635 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
9639 prefix
= argv
[idx
]->arg
;
9641 /* [<bestpath|multipath>] */
9642 if (argv_find(argv
, argc
, "bestpath", &idx
))
9643 path_type
= BGP_PATH_SHOW_BESTPATH
;
9644 else if (argv_find(argv
, argc
, "multipath", &idx
))
9645 path_type
= BGP_PATH_SHOW_MULTIPATH
;
9647 path_type
= BGP_PATH_SHOW_ALL
;
9649 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
9653 DEFUN (show_ip_bgp_regexp
,
9654 show_ip_bgp_regexp_cmd
,
9655 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX...",
9659 BGP_INSTANCE_HELP_STR
9661 BGP_SAFI_WITH_LABEL_HELP_STR
9662 "Display routes matching the AS path regular expression\n"
9663 "A regular-expression to match the BGP AS paths\n")
9665 afi_t afi
= AFI_IP6
;
9666 safi_t safi
= SAFI_UNICAST
;
9667 struct bgp
*bgp
= NULL
;
9670 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9675 // get index of regex
9676 argv_find(argv
, argc
, "regexp", &idx
);
9679 char *regstr
= argv_concat(argv
, argc
, idx
);
9680 int rc
= bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
9681 bgp_show_type_regexp
);
9682 XFREE(MTYPE_TMP
, regstr
);
9686 DEFUN (show_ip_bgp_instance_all
,
9687 show_ip_bgp_instance_all_cmd
,
9688 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json]",
9692 BGP_INSTANCE_ALL_HELP_STR
9694 BGP_SAFI_WITH_LABEL_HELP_STR
9698 safi_t safi
= SAFI_UNICAST
;
9699 struct bgp
*bgp
= NULL
;
9701 bool uj
= use_json(argc
, argv
);
9706 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9711 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, uj
);
9715 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
9716 afi_t afi
, safi_t safi
, enum bgp_show_type type
)
9721 regex
= bgp_regcomp(regstr
);
9723 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
9727 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, 0);
9728 bgp_regex_free(regex
);
9732 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
9733 const char *prefix_list_str
, afi_t afi
,
9734 safi_t safi
, enum bgp_show_type type
)
9736 struct prefix_list
*plist
;
9738 plist
= prefix_list_lookup(afi
, prefix_list_str
);
9739 if (plist
== NULL
) {
9740 vty_out(vty
, "%% %s is not a valid prefix-list name\n",
9745 return bgp_show(vty
, bgp
, afi
, safi
, type
, plist
, 0);
9748 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
9749 const char *filter
, afi_t afi
, safi_t safi
,
9750 enum bgp_show_type type
)
9752 struct as_list
*as_list
;
9754 as_list
= as_list_lookup(filter
);
9755 if (as_list
== NULL
) {
9756 vty_out(vty
, "%% %s is not a valid AS-path access-list name\n",
9761 return bgp_show(vty
, bgp
, afi
, safi
, type
, as_list
, 0);
9764 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
9765 const char *rmap_str
, afi_t afi
, safi_t safi
,
9766 enum bgp_show_type type
)
9768 struct route_map
*rmap
;
9770 rmap
= route_map_lookup_by_name(rmap_str
);
9772 vty_out(vty
, "%% %s is not a valid route-map name\n", rmap_str
);
9776 return bgp_show(vty
, bgp
, afi
, safi
, type
, rmap
, 0);
9779 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
9780 const char *comstr
, int exact
, afi_t afi
,
9781 safi_t safi
, bool use_json
)
9783 struct community
*com
;
9786 com
= community_str2com(comstr
);
9788 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
9792 ret
= bgp_show(vty
, bgp
, afi
, safi
,
9793 (exact
? bgp_show_type_community_exact
9794 : bgp_show_type_community
),
9796 community_free(&com
);
9801 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
9802 const char *com
, int exact
, afi_t afi
,
9805 struct community_list
*list
;
9807 list
= community_list_lookup(bgp_clist
, com
, 0, COMMUNITY_LIST_MASTER
);
9809 vty_out(vty
, "%% %s is not a valid community-list name\n", com
);
9813 return bgp_show(vty
, bgp
, afi
, safi
,
9814 (exact
? bgp_show_type_community_list_exact
9815 : bgp_show_type_community_list
),
9819 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
9820 const char *prefix
, afi_t afi
, safi_t safi
,
9821 enum bgp_show_type type
)
9828 ret
= str2prefix(prefix
, p
);
9830 vty_out(vty
, "%% Malformed Prefix\n");
9834 ret
= bgp_show(vty
, bgp
, afi
, safi
, type
, p
, 0);
9839 static struct peer
*peer_lookup_in_view(struct vty
*vty
, struct bgp
*bgp
,
9840 const char *ip_str
, bool use_json
)
9846 /* Get peer sockunion. */
9847 ret
= str2sockunion(ip_str
, &su
);
9849 peer
= peer_lookup_by_conf_if(bgp
, ip_str
);
9851 peer
= peer_lookup_by_hostname(bgp
, ip_str
);
9855 json_object
*json_no
= NULL
;
9856 json_no
= json_object_new_object();
9857 json_object_string_add(
9859 "malformedAddressOrName",
9861 vty_out(vty
, "%s\n",
9862 json_object_to_json_string_ext(
9864 JSON_C_TO_STRING_PRETTY
));
9865 json_object_free(json_no
);
9868 "%% Malformed address or name: %s\n",
9876 /* Peer structure lookup. */
9877 peer
= peer_lookup(bgp
, &su
);
9880 json_object
*json_no
= NULL
;
9881 json_no
= json_object_new_object();
9882 json_object_string_add(json_no
, "warning",
9883 "No such neighbor in this view/vrf");
9884 vty_out(vty
, "%s\n",
9885 json_object_to_json_string_ext(
9886 json_no
, JSON_C_TO_STRING_PRETTY
));
9887 json_object_free(json_no
);
9889 vty_out(vty
, "No such neighbor in this view/vrf\n");
9897 BGP_STATS_MAXBITLEN
= 0,
9901 BGP_STATS_UNAGGREGATEABLE
,
9902 BGP_STATS_MAX_AGGREGATEABLE
,
9903 BGP_STATS_AGGREGATES
,
9905 BGP_STATS_ASPATH_COUNT
,
9906 BGP_STATS_ASPATH_MAXHOPS
,
9907 BGP_STATS_ASPATH_TOTHOPS
,
9908 BGP_STATS_ASPATH_MAXSIZE
,
9909 BGP_STATS_ASPATH_TOTSIZE
,
9910 BGP_STATS_ASN_HIGHEST
,
9914 static const char *table_stats_strs
[] = {
9915 [BGP_STATS_PREFIXES
] = "Total Prefixes",
9916 [BGP_STATS_TOTPLEN
] = "Average prefix length",
9917 [BGP_STATS_RIB
] = "Total Advertisements",
9918 [BGP_STATS_UNAGGREGATEABLE
] = "Unaggregateable prefixes",
9919 [BGP_STATS_MAX_AGGREGATEABLE
] =
9920 "Maximum aggregateable prefixes",
9921 [BGP_STATS_AGGREGATES
] = "BGP Aggregate advertisements",
9922 [BGP_STATS_SPACE
] = "Address space advertised",
9923 [BGP_STATS_ASPATH_COUNT
] = "Advertisements with paths",
9924 [BGP_STATS_ASPATH_MAXHOPS
] = "Longest AS-Path (hops)",
9925 [BGP_STATS_ASPATH_MAXSIZE
] = "Largest AS-Path (bytes)",
9926 [BGP_STATS_ASPATH_TOTHOPS
] = "Average AS-Path length (hops)",
9927 [BGP_STATS_ASPATH_TOTSIZE
] = "Average AS-Path size (bytes)",
9928 [BGP_STATS_ASN_HIGHEST
] = "Highest public ASN",
9929 [BGP_STATS_MAX
] = NULL
,
9932 struct bgp_table_stats
{
9933 struct bgp_table
*table
;
9934 unsigned long long counts
[BGP_STATS_MAX
];
9939 #define TALLY_SIGFIG 100000
9940 static unsigned long
9941 ravg_tally (unsigned long count
, unsigned long oldavg
, unsigned long newval
)
9943 unsigned long newtot
= (count
-1) * oldavg
+ (newval
* TALLY_SIGFIG
);
9944 unsigned long res
= (newtot
* TALLY_SIGFIG
) / count
;
9945 unsigned long ret
= newtot
/ count
;
9947 if ((res
% TALLY_SIGFIG
) > (TALLY_SIGFIG
/2))
9954 static int bgp_table_stats_walker(struct thread
*t
)
9956 struct bgp_node
*rn
;
9957 struct bgp_node
*top
;
9958 struct bgp_table_stats
*ts
= THREAD_ARG(t
);
9959 unsigned int space
= 0;
9961 if (!(top
= bgp_table_top(ts
->table
)))
9964 switch (top
->p
.family
) {
9966 space
= IPV4_MAX_BITLEN
;
9969 space
= IPV6_MAX_BITLEN
;
9973 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
9975 for (rn
= top
; rn
; rn
= bgp_route_next(rn
)) {
9976 struct bgp_path_info
*pi
;
9977 struct bgp_node
*prn
= bgp_node_parent_nolock(rn
);
9978 unsigned int pinum
= 0;
9983 if (!bgp_node_has_bgp_path_info_data(rn
))
9986 ts
->counts
[BGP_STATS_PREFIXES
]++;
9987 ts
->counts
[BGP_STATS_TOTPLEN
] += rn
->p
.prefixlen
;
9990 ts
->counts
[BGP_STATS_AVGPLEN
]
9991 = ravg_tally (ts
->counts
[BGP_STATS_PREFIXES
],
9992 ts
->counts
[BGP_STATS_AVGPLEN
],
9996 /* check if the prefix is included by any other announcements */
9997 while (prn
&& !bgp_node_has_bgp_path_info_data(prn
))
9998 prn
= bgp_node_parent_nolock(prn
);
10000 if (prn
== NULL
|| prn
== top
) {
10001 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
10002 /* announced address space */
10005 pow(2.0, space
- rn
->p
.prefixlen
);
10006 } else if (bgp_node_has_bgp_path_info_data(prn
))
10007 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
10009 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
10011 ts
->counts
[BGP_STATS_RIB
]++;
10014 && (CHECK_FLAG(pi
->attr
->flag
,
10016 BGP_ATTR_ATOMIC_AGGREGATE
))))
10017 ts
->counts
[BGP_STATS_AGGREGATES
]++;
10019 /* as-path stats */
10020 if (pi
->attr
&& pi
->attr
->aspath
) {
10021 unsigned int hops
=
10022 aspath_count_hops(pi
->attr
->aspath
);
10023 unsigned int size
=
10024 aspath_size(pi
->attr
->aspath
);
10025 as_t highest
= aspath_highest(pi
->attr
->aspath
);
10027 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
10029 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
10030 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] =
10033 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
10034 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] =
10037 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
10038 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
10040 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
]
10041 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
10042 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
],
10044 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
]
10045 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
10046 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
],
10049 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
10050 ts
->counts
[BGP_STATS_ASN_HIGHEST
] =
10058 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
10061 struct bgp_table_stats ts
;
10064 if (!bgp
->rib
[afi
][safi
]) {
10065 vty_out(vty
, "%% No RIB exist's for the AFI(%d)/SAFI(%d)\n",
10067 return CMD_WARNING
;
10070 vty_out(vty
, "BGP %s RIB statistics\n", afi_safi_print(afi
, safi
));
10072 /* labeled-unicast routes live in the unicast table */
10073 if (safi
== SAFI_LABELED_UNICAST
)
10074 safi
= SAFI_UNICAST
;
10076 memset(&ts
, 0, sizeof(ts
));
10077 ts
.table
= bgp
->rib
[afi
][safi
];
10078 thread_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
10080 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
10081 if (!table_stats_strs
[i
])
10086 case BGP_STATS_ASPATH_AVGHOPS
:
10087 case BGP_STATS_ASPATH_AVGSIZE
:
10088 case BGP_STATS_AVGPLEN
:
10089 vty_out (vty
, "%-30s: ", table_stats_strs
[i
]);
10090 vty_out (vty
, "%12.2f",
10091 (float)ts
.counts
[i
] / (float)TALLY_SIGFIG
);
10094 case BGP_STATS_ASPATH_TOTHOPS
:
10095 case BGP_STATS_ASPATH_TOTSIZE
:
10096 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10097 vty_out(vty
, "%12.2f",
10099 ? (float)ts
.counts
[i
]
10101 [BGP_STATS_ASPATH_COUNT
]
10104 case BGP_STATS_TOTPLEN
:
10105 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10106 vty_out(vty
, "%12.2f",
10108 ? (float)ts
.counts
[i
]
10110 [BGP_STATS_PREFIXES
]
10113 case BGP_STATS_SPACE
:
10114 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10115 vty_out(vty
, "%12g\n", ts
.total_space
);
10117 if (afi
== AFI_IP6
) {
10118 vty_out(vty
, "%30s: ", "/32 equivalent ");
10119 vty_out(vty
, "%12g\n",
10120 ts
.total_space
* pow(2.0, -128 + 32));
10121 vty_out(vty
, "%30s: ", "/48 equivalent ");
10122 vty_out(vty
, "%12g\n",
10123 ts
.total_space
* pow(2.0, -128 + 48));
10125 vty_out(vty
, "%30s: ", "% announced ");
10126 vty_out(vty
, "%12.2f\n",
10127 ts
.total_space
* 100. * pow(2.0, -32));
10128 vty_out(vty
, "%30s: ", "/8 equivalent ");
10129 vty_out(vty
, "%12.2f\n",
10130 ts
.total_space
* pow(2.0, -32 + 8));
10131 vty_out(vty
, "%30s: ", "/24 equivalent ");
10132 vty_out(vty
, "%12.2f\n",
10133 ts
.total_space
* pow(2.0, -32 + 24));
10137 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10138 vty_out(vty
, "%12llu", ts
.counts
[i
]);
10141 vty_out(vty
, "\n");
10143 return CMD_SUCCESS
;
10155 PCOUNT_PFCNT
, /* the figure we display to users */
10159 static const char *pcount_strs
[] = {
10160 [PCOUNT_ADJ_IN
] = "Adj-in",
10161 [PCOUNT_DAMPED
] = "Damped",
10162 [PCOUNT_REMOVED
] = "Removed",
10163 [PCOUNT_HISTORY
] = "History",
10164 [PCOUNT_STALE
] = "Stale",
10165 [PCOUNT_VALID
] = "Valid",
10166 [PCOUNT_ALL
] = "All RIB",
10167 [PCOUNT_COUNTED
] = "PfxCt counted",
10168 [PCOUNT_PFCNT
] = "Useable",
10169 [PCOUNT_MAX
] = NULL
,
10172 struct peer_pcounts
{
10173 unsigned int count
[PCOUNT_MAX
];
10174 const struct peer
*peer
;
10175 const struct bgp_table
*table
;
10178 static int bgp_peer_count_walker(struct thread
*t
)
10180 struct bgp_node
*rn
;
10181 struct peer_pcounts
*pc
= THREAD_ARG(t
);
10182 const struct peer
*peer
= pc
->peer
;
10184 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
)) {
10185 struct bgp_adj_in
*ain
;
10186 struct bgp_path_info
*pi
;
10188 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
10189 if (ain
->peer
== peer
)
10190 pc
->count
[PCOUNT_ADJ_IN
]++;
10192 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
10194 if (pi
->peer
!= peer
)
10197 pc
->count
[PCOUNT_ALL
]++;
10199 if (CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
))
10200 pc
->count
[PCOUNT_DAMPED
]++;
10201 if (CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
10202 pc
->count
[PCOUNT_HISTORY
]++;
10203 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
10204 pc
->count
[PCOUNT_REMOVED
]++;
10205 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
10206 pc
->count
[PCOUNT_STALE
]++;
10207 if (CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
10208 pc
->count
[PCOUNT_VALID
]++;
10209 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
10210 pc
->count
[PCOUNT_PFCNT
]++;
10212 if (CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
10213 pc
->count
[PCOUNT_COUNTED
]++;
10214 if (CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
10216 EC_LIB_DEVELOPMENT
,
10217 "Attempting to count but flags say it is unusable");
10219 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
10221 EC_LIB_DEVELOPMENT
,
10222 "Not counted but flags say we should");
10229 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
10230 safi_t safi
, bool use_json
)
10232 struct peer_pcounts pcounts
= {.peer
= peer
};
10234 json_object
*json
= NULL
;
10235 json_object
*json_loop
= NULL
;
10238 json
= json_object_new_object();
10239 json_loop
= json_object_new_object();
10242 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
10243 || !peer
->bgp
->rib
[afi
][safi
]) {
10245 json_object_string_add(
10247 "No such neighbor or address family");
10248 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10249 json_object_free(json
);
10251 vty_out(vty
, "%% No such neighbor or address family\n");
10253 return CMD_WARNING
;
10256 memset(&pcounts
, 0, sizeof(pcounts
));
10257 pcounts
.peer
= peer
;
10258 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
10260 /* in-place call via thread subsystem so as to record execution time
10261 * stats for the thread-walk (i.e. ensure this can't be blamed on
10262 * on just vty_read()).
10264 thread_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
10267 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
10268 json_object_string_add(json
, "multiProtocol",
10269 afi_safi_print(afi
, safi
));
10270 json_object_int_add(json
, "pfxCounter",
10271 peer
->pcount
[afi
][safi
]);
10273 for (i
= 0; i
< PCOUNT_MAX
; i
++)
10274 json_object_int_add(json_loop
, pcount_strs
[i
],
10277 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
10279 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
10280 json_object_string_add(json
, "pfxctDriftFor",
10282 json_object_string_add(
10283 json
, "recommended",
10284 "Please report this bug, with the above command output");
10286 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
10287 json
, JSON_C_TO_STRING_PRETTY
));
10288 json_object_free(json
);
10292 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
10293 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
10294 peer
->hostname
, peer
->host
,
10295 afi_safi_print(afi
, safi
));
10297 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
10298 afi_safi_print(afi
, safi
));
10301 vty_out(vty
, "PfxCt: %ld\n", peer
->pcount
[afi
][safi
]);
10302 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
10304 for (i
= 0; i
< PCOUNT_MAX
; i
++)
10305 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
10308 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
10309 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
10311 "Please report this bug, with the above command output\n");
10315 return CMD_SUCCESS
;
10318 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
10319 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
10320 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_CMD_STR
"]] "
10321 "neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
10325 BGP_INSTANCE_HELP_STR
10328 "Detailed information on TCP and BGP neighbor connections\n"
10329 "Neighbor to display information about\n"
10330 "Neighbor to display information about\n"
10331 "Neighbor on BGP configured interface\n"
10332 "Display detailed prefix count information\n"
10335 afi_t afi
= AFI_IP6
;
10336 safi_t safi
= SAFI_UNICAST
;
10339 struct bgp
*bgp
= NULL
;
10340 bool uj
= use_json(argc
, argv
);
10345 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10348 return CMD_WARNING
;
10350 argv_find(argv
, argc
, "neighbors", &idx
);
10351 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
10353 return CMD_WARNING
;
10355 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_UNICAST
, uj
);
10358 #ifdef KEEP_OLD_VPN_COMMANDS
10359 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
10360 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
10361 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
10366 "Display information about all VPNv4 NLRIs\n"
10367 "Detailed information on TCP and BGP neighbor connections\n"
10368 "Neighbor to display information about\n"
10369 "Neighbor to display information about\n"
10370 "Neighbor on BGP configured interface\n"
10371 "Display detailed prefix count information\n"
10376 bool uj
= use_json(argc
, argv
);
10378 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
10380 return CMD_WARNING
;
10382 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
10385 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
10386 show_ip_bgp_vpn_all_route_prefix_cmd
,
10387 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
10392 "Display information about all VPNv4 NLRIs\n"
10393 "Network in the BGP routing table to display\n"
10394 "Network in the BGP routing table to display\n"
10398 char *network
= NULL
;
10399 struct bgp
*bgp
= bgp_get_default();
10401 vty_out(vty
, "Can't find default instance\n");
10402 return CMD_WARNING
;
10405 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
10406 network
= argv
[idx
]->arg
;
10407 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
10408 network
= argv
[idx
]->arg
;
10410 vty_out(vty
, "Unable to figure out Network\n");
10411 return CMD_WARNING
;
10414 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
10415 BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
10417 #endif /* KEEP_OLD_VPN_COMMANDS */
10419 DEFUN (show_ip_bgp_l2vpn_evpn_all_route_prefix
,
10420 show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd
,
10421 "show [ip] bgp l2vpn evpn all <A.B.C.D|A.B.C.D/M> [json]",
10427 "Display information about all EVPN NLRIs\n"
10428 "Network in the BGP routing table to display\n"
10429 "Network in the BGP routing table to display\n"
10433 char *network
= NULL
;
10435 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
10436 network
= argv
[idx
]->arg
;
10437 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
10438 network
= argv
[idx
]->arg
;
10440 vty_out(vty
, "Unable to figure out Network\n");
10441 return CMD_WARNING
;
10443 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
, 0,
10444 BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
10447 static void show_adj_route(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
10448 safi_t safi
, enum bgp_show_adj_route_type type
,
10449 const char *rmap_name
, bool use_json
,
10452 struct bgp_table
*table
;
10453 struct bgp_adj_in
*ain
;
10454 struct bgp_adj_out
*adj
;
10455 unsigned long output_count
;
10456 unsigned long filtered_count
;
10457 struct bgp_node
*rn
;
10463 struct update_subgroup
*subgrp
;
10464 json_object
*json_scode
= NULL
;
10465 json_object
*json_ocode
= NULL
;
10466 json_object
*json_ar
= NULL
;
10467 struct peer_af
*paf
;
10468 bool route_filtered
;
10471 json_scode
= json_object_new_object();
10472 json_ocode
= json_object_new_object();
10473 json_ar
= json_object_new_object();
10475 json_object_string_add(json_scode
, "suppressed", "s");
10476 json_object_string_add(json_scode
, "damped", "d");
10477 json_object_string_add(json_scode
, "history", "h");
10478 json_object_string_add(json_scode
, "valid", "*");
10479 json_object_string_add(json_scode
, "best", ">");
10480 json_object_string_add(json_scode
, "multipath", "=");
10481 json_object_string_add(json_scode
, "internal", "i");
10482 json_object_string_add(json_scode
, "ribFailure", "r");
10483 json_object_string_add(json_scode
, "stale", "S");
10484 json_object_string_add(json_scode
, "removed", "R");
10486 json_object_string_add(json_ocode
, "igp", "i");
10487 json_object_string_add(json_ocode
, "egp", "e");
10488 json_object_string_add(json_ocode
, "incomplete", "?");
10495 json_object_string_add(json
, "alert", "no BGP");
10496 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10497 json_object_free(json
);
10499 vty_out(vty
, "%% No bgp\n");
10503 table
= bgp
->rib
[afi
][safi
];
10505 output_count
= filtered_count
= 0;
10506 subgrp
= peer_subgroup(peer
, afi
, safi
);
10508 if (type
== bgp_show_adj_route_advertised
&& subgrp
10509 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
10511 json_object_int_add(json
, "bgpTableVersion",
10513 json_object_string_add(json
, "bgpLocalRouterId",
10514 inet_ntoa(bgp
->router_id
));
10515 json_object_int_add(json
, "defaultLocPrf",
10516 bgp
->default_local_pref
);
10517 json_object_int_add(json
, "localAS", bgp
->as
);
10518 json_object_object_add(json
, "bgpStatusCodes",
10520 json_object_object_add(json
, "bgpOriginCodes",
10522 json_object_string_add(
10523 json
, "bgpOriginatingDefaultNetwork",
10524 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
10526 vty_out(vty
, "BGP table version is %" PRIu64
10527 ", local router ID is %s, vrf id ",
10528 table
->version
, inet_ntoa(bgp
->router_id
));
10529 if (bgp
->vrf_id
== VRF_UNKNOWN
)
10530 vty_out(vty
, "%s", VRFID_NONE_STR
);
10532 vty_out(vty
, "%u", bgp
->vrf_id
);
10533 vty_out(vty
, "\n");
10534 vty_out(vty
, "Default local pref %u, ",
10535 bgp
->default_local_pref
);
10536 vty_out(vty
, "local AS %u\n", bgp
->as
);
10537 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
10538 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
10539 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
10541 vty_out(vty
, "Originating default network %s\n\n",
10542 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
10547 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
10548 if (type
== bgp_show_adj_route_received
10549 || type
== bgp_show_adj_route_filtered
) {
10550 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
10551 if (ain
->peer
!= peer
|| !ain
->attr
)
10556 json_object_int_add(
10557 json
, "bgpTableVersion",
10559 json_object_string_add(
10561 "bgpLocalRouterId",
10564 json_object_int_add(json
,
10566 bgp
->default_local_pref
);
10567 json_object_int_add(json
,
10568 "localAS", bgp
->as
);
10569 json_object_object_add(
10570 json
, "bgpStatusCodes",
10572 json_object_object_add(
10573 json
, "bgpOriginCodes",
10577 "BGP table version is 0, local router ID is %s, vrf id ",
10580 if (bgp
->vrf_id
== VRF_UNKNOWN
)
10586 vty_out(vty
, "\n");
10588 "Default local pref %u, ",
10589 bgp
->default_local_pref
);
10590 vty_out(vty
, "local AS %u\n",
10593 BGP_SHOW_SCODE_HEADER
);
10595 BGP_SHOW_NCODE_HEADER
);
10597 BGP_SHOW_OCODE_HEADER
);
10603 vty_out(vty
, BGP_SHOW_HEADER
);
10607 bgp_attr_dup(&attr
, ain
->attr
);
10608 route_filtered
= false;
10610 /* Filter prefix using distribute list,
10611 * filter list or prefix list
10613 if ((bgp_input_filter(peer
, &rn
->p
, &attr
, afi
,
10614 safi
)) == FILTER_DENY
)
10615 route_filtered
= true;
10617 /* Filter prefix using route-map */
10618 ret
= bgp_input_modifier(peer
, &rn
->p
, &attr
,
10619 afi
, safi
, rmap_name
);
10621 if (type
== bgp_show_adj_route_filtered
&&
10622 !route_filtered
&& ret
!= RMAP_DENY
) {
10623 bgp_attr_undup(&attr
, ain
->attr
);
10627 if (type
== bgp_show_adj_route_received
&&
10628 (route_filtered
|| ret
== RMAP_DENY
))
10631 route_vty_out_tmp(vty
, &rn
->p
, &attr
, safi
,
10632 use_json
, json_ar
);
10633 bgp_attr_undup(&attr
, ain
->attr
);
10636 } else if (type
== bgp_show_adj_route_advertised
) {
10637 RB_FOREACH (adj
, bgp_adj_out_rb
, &rn
->adj_out
)
10638 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
10639 if (paf
->peer
!= peer
|| !adj
->attr
)
10644 json_object_int_add(
10648 json_object_string_add(
10650 "bgpLocalRouterId",
10653 json_object_int_add(
10654 json
, "defaultLocPrf",
10655 bgp
->default_local_pref
10657 json_object_int_add(
10660 json_object_object_add(
10664 json_object_object_add(
10670 "BGP table version is %" PRIu64
10671 ", local router ID is %s, vrf id ",
10684 vty_out(vty
, "\n");
10686 "Default local pref %u, ",
10687 bgp
->default_local_pref
10693 BGP_SHOW_SCODE_HEADER
);
10695 BGP_SHOW_NCODE_HEADER
);
10697 BGP_SHOW_OCODE_HEADER
);
10708 bgp_attr_dup(&attr
, adj
->attr
);
10709 ret
= bgp_output_modifier(
10710 peer
, &rn
->p
, &attr
, afi
, safi
,
10713 if (ret
!= RMAP_DENY
) {
10714 route_vty_out_tmp(vty
, &rn
->p
,
10723 bgp_attr_undup(&attr
, adj
->attr
);
10729 json_object_object_add(json
, "advertisedRoutes", json_ar
);
10730 json_object_int_add(json
, "totalPrefixCounter", output_count
);
10731 json_object_int_add(json
, "filteredPrefixCounter",
10734 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
10735 json
, JSON_C_TO_STRING_PRETTY
));
10736 json_object_free(json
);
10737 } else if (output_count
> 0) {
10738 if (filtered_count
> 0)
10740 "\nTotal number of prefixes %ld (%ld filtered)\n",
10741 output_count
, filtered_count
);
10743 vty_out(vty
, "\nTotal number of prefixes %ld\n",
10748 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
10749 safi_t safi
, enum bgp_show_adj_route_type type
,
10750 const char *rmap_name
, bool use_json
)
10752 json_object
*json
= NULL
;
10755 json
= json_object_new_object();
10757 /* labeled-unicast routes live in the unicast table */
10758 if (safi
== SAFI_LABELED_UNICAST
)
10759 safi
= SAFI_UNICAST
;
10761 if (!peer
|| !peer
->afc
[afi
][safi
]) {
10763 json_object_string_add(
10765 "No such neighbor or address family");
10766 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10767 json_object_free(json
);
10769 vty_out(vty
, "%% No such neighbor or address family\n");
10771 return CMD_WARNING
;
10774 if ((type
== bgp_show_adj_route_received
10775 || type
== bgp_show_adj_route_filtered
)
10776 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
10777 PEER_FLAG_SOFT_RECONFIG
)) {
10779 json_object_string_add(
10781 "Inbound soft reconfiguration not enabled");
10782 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10783 json_object_free(json
);
10786 "%% Inbound soft reconfiguration not enabled\n");
10788 return CMD_WARNING
;
10791 show_adj_route(vty
, peer
, afi
, safi
, type
, rmap_name
, use_json
, json
);
10793 return CMD_SUCCESS
;
10796 DEFUN (show_ip_bgp_instance_neighbor_advertised_route
,
10797 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
10798 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
10799 "neighbors <A.B.C.D|X:X::X:X|WORD> <advertised-routes|received-routes|filtered-routes> [route-map WORD] [json]",
10803 BGP_INSTANCE_HELP_STR
10805 BGP_SAFI_WITH_LABEL_HELP_STR
10806 "Detailed information on TCP and BGP neighbor connections\n"
10807 "Neighbor to display information about\n"
10808 "Neighbor to display information about\n"
10809 "Neighbor on BGP configured interface\n"
10810 "Display the routes advertised to a BGP neighbor\n"
10811 "Display the received routes from neighbor\n"
10812 "Display the filtered routes received from neighbor\n"
10813 "Route-map to modify the attributes\n"
10814 "Name of the route map\n"
10817 afi_t afi
= AFI_IP6
;
10818 safi_t safi
= SAFI_UNICAST
;
10819 char *rmap_name
= NULL
;
10820 char *peerstr
= NULL
;
10821 struct bgp
*bgp
= NULL
;
10823 enum bgp_show_adj_route_type type
= bgp_show_adj_route_advertised
;
10825 bool uj
= use_json(argc
, argv
);
10830 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10833 return CMD_WARNING
;
10835 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10836 argv_find(argv
, argc
, "neighbors", &idx
);
10837 peerstr
= argv
[++idx
]->arg
;
10839 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
10841 return CMD_WARNING
;
10843 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
10844 type
= bgp_show_adj_route_advertised
;
10845 else if (argv_find(argv
, argc
, "received-routes", &idx
))
10846 type
= bgp_show_adj_route_received
;
10847 else if (argv_find(argv
, argc
, "filtered-routes", &idx
))
10848 type
= bgp_show_adj_route_filtered
;
10850 if (argv_find(argv
, argc
, "route-map", &idx
))
10851 rmap_name
= argv
[++idx
]->arg
;
10853 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
, uj
);
10856 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
10857 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
10858 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
10864 "Address Family modifier\n"
10865 "Detailed information on TCP and BGP neighbor connections\n"
10866 "Neighbor to display information about\n"
10867 "Neighbor to display information about\n"
10868 "Neighbor on BGP configured interface\n"
10869 "Display information received from a BGP neighbor\n"
10870 "Display the prefixlist filter\n"
10873 afi_t afi
= AFI_IP6
;
10874 safi_t safi
= SAFI_UNICAST
;
10875 char *peerstr
= NULL
;
10878 union sockunion su
;
10884 /* show [ip] bgp */
10885 if (argv_find(argv
, argc
, "ip", &idx
))
10887 /* [<ipv4|ipv6> [unicast]] */
10888 if (argv_find(argv
, argc
, "ipv4", &idx
))
10890 if (argv_find(argv
, argc
, "ipv6", &idx
))
10892 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10893 argv_find(argv
, argc
, "neighbors", &idx
);
10894 peerstr
= argv
[++idx
]->arg
;
10896 bool uj
= use_json(argc
, argv
);
10898 ret
= str2sockunion(peerstr
, &su
);
10900 peer
= peer_lookup_by_conf_if(NULL
, peerstr
);
10903 vty_out(vty
, "{}\n");
10906 "%% Malformed address or name: %s\n",
10908 return CMD_WARNING
;
10911 peer
= peer_lookup(NULL
, &su
);
10914 vty_out(vty
, "{}\n");
10916 vty_out(vty
, "No peer\n");
10917 return CMD_WARNING
;
10921 sprintf(name
, "%s.%d.%d", peer
->host
, afi
, safi
);
10922 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
10925 vty_out(vty
, "Address Family: %s\n",
10926 afi_safi_print(afi
, safi
));
10927 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
10930 vty_out(vty
, "{}\n");
10932 vty_out(vty
, "No functional output\n");
10935 return CMD_SUCCESS
;
10938 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
10939 afi_t afi
, safi_t safi
,
10940 enum bgp_show_type type
, bool use_json
)
10942 /* labeled-unicast routes live in the unicast table */
10943 if (safi
== SAFI_LABELED_UNICAST
)
10944 safi
= SAFI_UNICAST
;
10946 if (!peer
|| !peer
->afc
[afi
][safi
]) {
10948 json_object
*json_no
= NULL
;
10949 json_no
= json_object_new_object();
10950 json_object_string_add(
10951 json_no
, "warning",
10952 "No such neighbor or address family");
10953 vty_out(vty
, "%s\n",
10954 json_object_to_json_string(json_no
));
10955 json_object_free(json_no
);
10957 vty_out(vty
, "%% No such neighbor or address family\n");
10958 return CMD_WARNING
;
10961 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, use_json
);
10964 DEFUN (show_ip_bgp_flowspec_routes_detailed
,
10965 show_ip_bgp_flowspec_routes_detailed_cmd
,
10966 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" flowspec] detail [json]",
10970 BGP_INSTANCE_HELP_STR
10973 "Detailed information on flowspec entries\n"
10976 afi_t afi
= AFI_IP
;
10977 safi_t safi
= SAFI_UNICAST
;
10978 struct bgp
*bgp
= NULL
;
10980 bool uj
= use_json(argc
, argv
);
10985 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10988 return CMD_WARNING
;
10990 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_detail
, NULL
, uj
);
10993 DEFUN (show_ip_bgp_neighbor_routes
,
10994 show_ip_bgp_neighbor_routes_cmd
,
10995 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
10996 "neighbors <A.B.C.D|X:X::X:X|WORD> <flap-statistics|dampened-routes|routes> [json]",
11000 BGP_INSTANCE_HELP_STR
11002 BGP_SAFI_WITH_LABEL_HELP_STR
11003 "Detailed information on TCP and BGP neighbor connections\n"
11004 "Neighbor to display information about\n"
11005 "Neighbor to display information about\n"
11006 "Neighbor on BGP configured interface\n"
11007 "Display flap statistics of the routes learned from neighbor\n"
11008 "Display the dampened routes received from neighbor\n"
11009 "Display routes learned from neighbor\n"
11012 char *peerstr
= NULL
;
11013 struct bgp
*bgp
= NULL
;
11014 afi_t afi
= AFI_IP6
;
11015 safi_t safi
= SAFI_UNICAST
;
11017 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
11019 bool uj
= use_json(argc
, argv
);
11024 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11027 return CMD_WARNING
;
11029 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11030 argv_find(argv
, argc
, "neighbors", &idx
);
11031 peerstr
= argv
[++idx
]->arg
;
11033 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
11035 return CMD_WARNING
;
11037 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
11038 sh_type
= bgp_show_type_flap_neighbor
;
11039 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
11040 sh_type
= bgp_show_type_damp_neighbor
;
11041 else if (argv_find(argv
, argc
, "routes", &idx
))
11042 sh_type
= bgp_show_type_neighbor
;
11044 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
11047 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
11049 struct bgp_distance
{
11050 /* Distance value for the IP source prefix. */
11053 /* Name of the access-list to be matched. */
11057 DEFUN (show_bgp_afi_vpn_rd_route
,
11058 show_bgp_afi_vpn_rd_route_cmd
,
11059 "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]",
11063 "Address Family modifier\n"
11064 "Display information for a route distinguisher\n"
11065 "Route Distinguisher\n"
11066 "Network in the BGP routing table to display\n"
11067 "Network in the BGP routing table to display\n"
11071 struct prefix_rd prd
;
11072 afi_t afi
= AFI_MAX
;
11075 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
11076 vty_out(vty
, "%% Malformed Address Family\n");
11077 return CMD_WARNING
;
11080 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
11082 vty_out(vty
, "%% Malformed Route Distinguisher\n");
11083 return CMD_WARNING
;
11086 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
11087 0, BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
11090 static struct bgp_distance
*bgp_distance_new(void)
11092 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
11095 static void bgp_distance_free(struct bgp_distance
*bdistance
)
11097 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
11100 static int bgp_distance_set(struct vty
*vty
, const char *distance_str
,
11101 const char *ip_str
, const char *access_list_str
)
11108 struct bgp_node
*rn
;
11109 struct bgp_distance
*bdistance
;
11111 afi
= bgp_node_afi(vty
);
11112 safi
= bgp_node_safi(vty
);
11114 ret
= str2prefix(ip_str
, &p
);
11116 vty_out(vty
, "Malformed prefix\n");
11117 return CMD_WARNING_CONFIG_FAILED
;
11120 distance
= atoi(distance_str
);
11122 /* Get BGP distance node. */
11123 rn
= bgp_node_get(bgp_distance_table
[afi
][safi
], (struct prefix
*)&p
);
11124 bdistance
= bgp_node_get_bgp_distance_info(rn
);
11126 bgp_unlock_node(rn
);
11128 bdistance
= bgp_distance_new();
11129 bgp_node_set_bgp_distance_info(rn
, bdistance
);
11132 /* Set distance value. */
11133 bdistance
->distance
= distance
;
11135 /* Reset access-list configuration. */
11136 if (bdistance
->access_list
) {
11137 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
11138 bdistance
->access_list
= NULL
;
11140 if (access_list_str
)
11141 bdistance
->access_list
=
11142 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
11144 return CMD_SUCCESS
;
11147 static int bgp_distance_unset(struct vty
*vty
, const char *distance_str
,
11148 const char *ip_str
, const char *access_list_str
)
11155 struct bgp_node
*rn
;
11156 struct bgp_distance
*bdistance
;
11158 afi
= bgp_node_afi(vty
);
11159 safi
= bgp_node_safi(vty
);
11161 ret
= str2prefix(ip_str
, &p
);
11163 vty_out(vty
, "Malformed prefix\n");
11164 return CMD_WARNING_CONFIG_FAILED
;
11167 rn
= bgp_node_lookup(bgp_distance_table
[afi
][safi
],
11168 (struct prefix
*)&p
);
11170 vty_out(vty
, "Can't find specified prefix\n");
11171 return CMD_WARNING_CONFIG_FAILED
;
11174 bdistance
= bgp_node_get_bgp_distance_info(rn
);
11175 distance
= atoi(distance_str
);
11177 if (bdistance
->distance
!= distance
) {
11178 vty_out(vty
, "Distance does not match configured\n");
11179 return CMD_WARNING_CONFIG_FAILED
;
11182 if (bdistance
->access_list
)
11183 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
11184 bgp_distance_free(bdistance
);
11186 bgp_node_set_bgp_path_info(rn
, NULL
);
11187 bgp_unlock_node(rn
);
11188 bgp_unlock_node(rn
);
11190 return CMD_SUCCESS
;
11193 /* Apply BGP information to distance method. */
11194 uint8_t bgp_distance_apply(struct prefix
*p
, struct bgp_path_info
*pinfo
,
11195 afi_t afi
, safi_t safi
, struct bgp
*bgp
)
11197 struct bgp_node
*rn
;
11200 struct bgp_distance
*bdistance
;
11201 struct access_list
*alist
;
11202 struct bgp_static
*bgp_static
;
11207 peer
= pinfo
->peer
;
11209 /* Check source address. */
11210 sockunion2hostprefix(&peer
->su
, &q
);
11211 rn
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
11213 bdistance
= bgp_node_get_bgp_distance_info(rn
);
11214 bgp_unlock_node(rn
);
11216 if (bdistance
->access_list
) {
11217 alist
= access_list_lookup(afi
, bdistance
->access_list
);
11219 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
11220 return bdistance
->distance
;
11222 return bdistance
->distance
;
11225 /* Backdoor check. */
11226 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
11228 bgp_static
= bgp_node_get_bgp_static_info(rn
);
11229 bgp_unlock_node(rn
);
11231 if (bgp_static
->backdoor
) {
11232 if (bgp
->distance_local
[afi
][safi
])
11233 return bgp
->distance_local
[afi
][safi
];
11235 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
11239 if (peer
->sort
== BGP_PEER_EBGP
) {
11240 if (bgp
->distance_ebgp
[afi
][safi
])
11241 return bgp
->distance_ebgp
[afi
][safi
];
11242 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
11244 if (bgp
->distance_ibgp
[afi
][safi
])
11245 return bgp
->distance_ibgp
[afi
][safi
];
11246 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
11250 DEFUN (bgp_distance
,
11252 "distance bgp (1-255) (1-255) (1-255)",
11253 "Define an administrative distance\n"
11255 "Distance for routes external to the AS\n"
11256 "Distance for routes internal to the AS\n"
11257 "Distance for local routes\n")
11259 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11260 int idx_number
= 2;
11261 int idx_number_2
= 3;
11262 int idx_number_3
= 4;
11266 afi
= bgp_node_afi(vty
);
11267 safi
= bgp_node_safi(vty
);
11269 bgp
->distance_ebgp
[afi
][safi
] = atoi(argv
[idx_number
]->arg
);
11270 bgp
->distance_ibgp
[afi
][safi
] = atoi(argv
[idx_number_2
]->arg
);
11271 bgp
->distance_local
[afi
][safi
] = atoi(argv
[idx_number_3
]->arg
);
11272 return CMD_SUCCESS
;
11275 DEFUN (no_bgp_distance
,
11276 no_bgp_distance_cmd
,
11277 "no distance bgp [(1-255) (1-255) (1-255)]",
11279 "Define an administrative distance\n"
11281 "Distance for routes external to the AS\n"
11282 "Distance for routes internal to the AS\n"
11283 "Distance for local routes\n")
11285 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11289 afi
= bgp_node_afi(vty
);
11290 safi
= bgp_node_safi(vty
);
11292 bgp
->distance_ebgp
[afi
][safi
] = 0;
11293 bgp
->distance_ibgp
[afi
][safi
] = 0;
11294 bgp
->distance_local
[afi
][safi
] = 0;
11295 return CMD_SUCCESS
;
11299 DEFUN (bgp_distance_source
,
11300 bgp_distance_source_cmd
,
11301 "distance (1-255) A.B.C.D/M",
11302 "Define an administrative distance\n"
11303 "Administrative distance\n"
11304 "IP source prefix\n")
11306 int idx_number
= 1;
11307 int idx_ipv4_prefixlen
= 2;
11308 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
11309 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
11310 return CMD_SUCCESS
;
11313 DEFUN (no_bgp_distance_source
,
11314 no_bgp_distance_source_cmd
,
11315 "no distance (1-255) A.B.C.D/M",
11317 "Define an administrative distance\n"
11318 "Administrative distance\n"
11319 "IP source prefix\n")
11321 int idx_number
= 2;
11322 int idx_ipv4_prefixlen
= 3;
11323 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
11324 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
11325 return CMD_SUCCESS
;
11328 DEFUN (bgp_distance_source_access_list
,
11329 bgp_distance_source_access_list_cmd
,
11330 "distance (1-255) A.B.C.D/M WORD",
11331 "Define an administrative distance\n"
11332 "Administrative distance\n"
11333 "IP source prefix\n"
11334 "Access list name\n")
11336 int idx_number
= 1;
11337 int idx_ipv4_prefixlen
= 2;
11339 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
11340 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
11341 return CMD_SUCCESS
;
11344 DEFUN (no_bgp_distance_source_access_list
,
11345 no_bgp_distance_source_access_list_cmd
,
11346 "no distance (1-255) A.B.C.D/M WORD",
11348 "Define an administrative distance\n"
11349 "Administrative distance\n"
11350 "IP source prefix\n"
11351 "Access list name\n")
11353 int idx_number
= 2;
11354 int idx_ipv4_prefixlen
= 3;
11356 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
11357 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
11358 return CMD_SUCCESS
;
11361 DEFUN (ipv6_bgp_distance_source
,
11362 ipv6_bgp_distance_source_cmd
,
11363 "distance (1-255) X:X::X:X/M",
11364 "Define an administrative distance\n"
11365 "Administrative distance\n"
11366 "IP source prefix\n")
11368 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, NULL
);
11369 return CMD_SUCCESS
;
11372 DEFUN (no_ipv6_bgp_distance_source
,
11373 no_ipv6_bgp_distance_source_cmd
,
11374 "no distance (1-255) X:X::X:X/M",
11376 "Define an administrative distance\n"
11377 "Administrative distance\n"
11378 "IP source prefix\n")
11380 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, NULL
);
11381 return CMD_SUCCESS
;
11384 DEFUN (ipv6_bgp_distance_source_access_list
,
11385 ipv6_bgp_distance_source_access_list_cmd
,
11386 "distance (1-255) X:X::X:X/M WORD",
11387 "Define an administrative distance\n"
11388 "Administrative distance\n"
11389 "IP source prefix\n"
11390 "Access list name\n")
11392 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, argv
[3]->arg
);
11393 return CMD_SUCCESS
;
11396 DEFUN (no_ipv6_bgp_distance_source_access_list
,
11397 no_ipv6_bgp_distance_source_access_list_cmd
,
11398 "no distance (1-255) X:X::X:X/M WORD",
11400 "Define an administrative distance\n"
11401 "Administrative distance\n"
11402 "IP source prefix\n"
11403 "Access list name\n")
11405 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, argv
[4]->arg
);
11406 return CMD_SUCCESS
;
11409 DEFUN (bgp_damp_set
,
11411 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
11412 "BGP Specific commands\n"
11413 "Enable route-flap dampening\n"
11414 "Half-life time for the penalty\n"
11415 "Value to start reusing a route\n"
11416 "Value to start suppressing a route\n"
11417 "Maximum duration to suppress a stable route\n")
11419 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11420 int idx_half_life
= 2;
11422 int idx_suppress
= 4;
11423 int idx_max_suppress
= 5;
11424 int half
= DEFAULT_HALF_LIFE
* 60;
11425 int reuse
= DEFAULT_REUSE
;
11426 int suppress
= DEFAULT_SUPPRESS
;
11427 int max
= 4 * half
;
11430 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
11431 reuse
= atoi(argv
[idx_reuse
]->arg
);
11432 suppress
= atoi(argv
[idx_suppress
]->arg
);
11433 max
= atoi(argv
[idx_max_suppress
]->arg
) * 60;
11434 } else if (argc
== 3) {
11435 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
11439 if (suppress
< reuse
) {
11441 "Suppress value cannot be less than reuse value \n");
11445 return bgp_damp_enable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
), half
,
11446 reuse
, suppress
, max
);
11449 DEFUN (bgp_damp_unset
,
11450 bgp_damp_unset_cmd
,
11451 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
11453 "BGP Specific commands\n"
11454 "Enable route-flap dampening\n"
11455 "Half-life time for the penalty\n"
11456 "Value to start reusing a route\n"
11457 "Value to start suppressing a route\n"
11458 "Maximum duration to suppress a stable route\n")
11460 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11461 return bgp_damp_disable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
));
11464 /* Display specified route of BGP table. */
11465 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
11466 const char *ip_str
, afi_t afi
, safi_t safi
,
11467 struct prefix_rd
*prd
, int prefix_check
)
11470 struct prefix match
;
11471 struct bgp_node
*rn
;
11472 struct bgp_node
*rm
;
11473 struct bgp_path_info
*pi
;
11474 struct bgp_path_info
*pi_temp
;
11476 struct bgp_table
*table
;
11478 /* BGP structure lookup. */
11480 bgp
= bgp_lookup_by_name(view_name
);
11482 vty_out(vty
, "%% Can't find BGP instance %s\n",
11484 return CMD_WARNING
;
11487 bgp
= bgp_get_default();
11489 vty_out(vty
, "%% No BGP process is configured\n");
11490 return CMD_WARNING
;
11494 /* Check IP address argument. */
11495 ret
= str2prefix(ip_str
, &match
);
11497 vty_out(vty
, "%% address is malformed\n");
11498 return CMD_WARNING
;
11501 match
.family
= afi2family(afi
);
11503 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
11504 || (safi
== SAFI_EVPN
)) {
11505 for (rn
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); rn
;
11506 rn
= bgp_route_next(rn
)) {
11507 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
11509 table
= bgp_node_get_bgp_table_info(rn
);
11512 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
11516 || rm
->p
.prefixlen
== match
.prefixlen
) {
11517 pi
= bgp_node_get_bgp_path_info(rm
);
11519 if (pi
->extra
&& pi
->extra
->damp_info
) {
11520 pi_temp
= pi
->next
;
11521 bgp_damp_info_free(
11522 pi
->extra
->damp_info
,
11530 bgp_unlock_node(rm
);
11533 if ((rn
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
))
11536 || rn
->p
.prefixlen
== match
.prefixlen
) {
11537 pi
= bgp_node_get_bgp_path_info(rn
);
11539 if (pi
->extra
&& pi
->extra
->damp_info
) {
11540 pi_temp
= pi
->next
;
11541 bgp_damp_info_free(
11542 pi
->extra
->damp_info
,
11550 bgp_unlock_node(rn
);
11554 return CMD_SUCCESS
;
11557 DEFUN (clear_ip_bgp_dampening
,
11558 clear_ip_bgp_dampening_cmd
,
11559 "clear ip bgp dampening",
11563 "Clear route flap dampening information\n")
11565 bgp_damp_info_clean();
11566 return CMD_SUCCESS
;
11569 DEFUN (clear_ip_bgp_dampening_prefix
,
11570 clear_ip_bgp_dampening_prefix_cmd
,
11571 "clear ip bgp dampening A.B.C.D/M",
11575 "Clear route flap dampening information\n"
11578 int idx_ipv4_prefixlen
= 4;
11579 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
11580 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
11583 DEFUN (clear_ip_bgp_dampening_address
,
11584 clear_ip_bgp_dampening_address_cmd
,
11585 "clear ip bgp dampening A.B.C.D",
11589 "Clear route flap dampening information\n"
11590 "Network to clear damping information\n")
11593 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
11594 SAFI_UNICAST
, NULL
, 0);
11597 DEFUN (clear_ip_bgp_dampening_address_mask
,
11598 clear_ip_bgp_dampening_address_mask_cmd
,
11599 "clear ip bgp dampening A.B.C.D A.B.C.D",
11603 "Clear route flap dampening information\n"
11604 "Network to clear damping information\n"
11608 int idx_ipv4_2
= 5;
11610 char prefix_str
[BUFSIZ
];
11612 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
11615 vty_out(vty
, "%% Inconsistent address and mask\n");
11616 return CMD_WARNING
;
11619 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
11623 static void show_bgp_peerhash_entry(struct hash_backet
*backet
, void *arg
)
11625 struct vty
*vty
= arg
;
11626 struct peer
*peer
= backet
->data
;
11627 char buf
[SU_ADDRSTRLEN
];
11629 vty_out(vty
, "\tPeer: %s %s\n", peer
->host
,
11630 sockunion2str(&peer
->su
, buf
, sizeof(buf
)));
11633 DEFUN (show_bgp_peerhash
,
11634 show_bgp_peerhash_cmd
,
11635 "show bgp peerhash",
11638 "Display information about the BGP peerhash\n")
11640 struct list
*instances
= bm
->bgp
;
11641 struct listnode
*node
;
11644 for (ALL_LIST_ELEMENTS_RO(instances
, node
, bgp
)) {
11645 vty_out(vty
, "BGP: %s\n", bgp
->name
);
11646 hash_iterate(bgp
->peerhash
, show_bgp_peerhash_entry
,
11650 return CMD_SUCCESS
;
11653 /* also used for encap safi */
11654 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
11655 afi_t afi
, safi_t safi
)
11657 struct bgp_node
*prn
;
11658 struct bgp_node
*rn
;
11659 struct bgp_table
*table
;
11661 struct prefix_rd
*prd
;
11662 struct bgp_static
*bgp_static
;
11663 mpls_label_t label
;
11664 char buf
[SU_ADDRSTRLEN
];
11665 char rdbuf
[RD_ADDRSTRLEN
];
11667 /* Network configuration. */
11668 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
11669 prn
= bgp_route_next(prn
)) {
11670 table
= bgp_node_get_bgp_table_info(prn
);
11674 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
11675 bgp_static
= bgp_node_get_bgp_static_info(rn
);
11676 if (bgp_static
== NULL
)
11680 prd
= (struct prefix_rd
*)&prn
->p
;
11682 /* "network" configuration display. */
11683 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
11684 label
= decode_label(&bgp_static
->label
);
11686 vty_out(vty
, " network %s/%d rd %s",
11687 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11689 p
->prefixlen
, rdbuf
);
11690 if (safi
== SAFI_MPLS_VPN
)
11691 vty_out(vty
, " label %u", label
);
11693 if (bgp_static
->rmap
.name
)
11694 vty_out(vty
, " route-map %s",
11695 bgp_static
->rmap
.name
);
11697 if (bgp_static
->backdoor
)
11698 vty_out(vty
, " backdoor");
11700 vty_out(vty
, "\n");
11705 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
11706 afi_t afi
, safi_t safi
)
11708 struct bgp_node
*prn
;
11709 struct bgp_node
*rn
;
11710 struct bgp_table
*table
;
11712 struct prefix_rd
*prd
;
11713 struct bgp_static
*bgp_static
;
11714 char buf
[PREFIX_STRLEN
* 2];
11715 char buf2
[SU_ADDRSTRLEN
];
11716 char rdbuf
[RD_ADDRSTRLEN
];
11718 /* Network configuration. */
11719 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
11720 prn
= bgp_route_next(prn
)) {
11721 table
= bgp_node_get_bgp_table_info(prn
);
11725 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
11726 bgp_static
= bgp_node_get_bgp_static_info(rn
);
11727 if (bgp_static
== NULL
)
11730 char *macrouter
= NULL
;
11733 if (bgp_static
->router_mac
)
11734 macrouter
= prefix_mac2str(
11735 bgp_static
->router_mac
, NULL
, 0);
11736 if (bgp_static
->eth_s_id
)
11737 esi
= esi2str(bgp_static
->eth_s_id
);
11739 prd
= (struct prefix_rd
*)&prn
->p
;
11741 /* "network" configuration display. */
11742 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
11743 if (p
->u
.prefix_evpn
.route_type
== 5) {
11744 char local_buf
[PREFIX_STRLEN
];
11745 uint8_t family
= is_evpn_prefix_ipaddr_v4((
11746 struct prefix_evpn
*)p
)
11750 &p
->u
.prefix_evpn
.prefix_addr
.ip
.ip
.addr
,
11751 local_buf
, PREFIX_STRLEN
);
11752 sprintf(buf
, "%s/%u", local_buf
,
11753 p
->u
.prefix_evpn
.prefix_addr
.ip_prefix_length
);
11755 prefix2str(p
, buf
, sizeof(buf
));
11758 if (bgp_static
->gatewayIp
.family
== AF_INET
11759 || bgp_static
->gatewayIp
.family
== AF_INET6
)
11760 inet_ntop(bgp_static
->gatewayIp
.family
,
11761 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
11764 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
11766 p
->u
.prefix_evpn
.prefix_addr
.eth_tag
,
11767 decode_label(&bgp_static
->label
), esi
, buf2
,
11771 XFREE(MTYPE_TMP
, macrouter
);
11773 XFREE(MTYPE_TMP
, esi
);
11778 /* Configuration of static route announcement and aggregate
11780 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11783 struct bgp_node
*rn
;
11785 struct bgp_static
*bgp_static
;
11786 struct bgp_aggregate
*bgp_aggregate
;
11787 char buf
[SU_ADDRSTRLEN
];
11789 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
11790 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
11794 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
11795 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
11799 /* Network configuration. */
11800 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
11801 rn
= bgp_route_next(rn
)) {
11802 bgp_static
= bgp_node_get_bgp_static_info(rn
);
11803 if (bgp_static
== NULL
)
11808 /* "network" configuration display. */
11809 if (bgp_option_check(BGP_OPT_CONFIG_CISCO
) && afi
== AFI_IP
) {
11810 uint32_t destination
;
11811 struct in_addr netmask
;
11813 destination
= ntohl(p
->u
.prefix4
.s_addr
);
11814 masklen2ip(p
->prefixlen
, &netmask
);
11815 vty_out(vty
, " network %s",
11816 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11819 if ((IN_CLASSC(destination
) && p
->prefixlen
== 24)
11820 || (IN_CLASSB(destination
) && p
->prefixlen
== 16)
11821 || (IN_CLASSA(destination
) && p
->prefixlen
== 8)
11822 || p
->u
.prefix4
.s_addr
== 0) {
11823 /* Natural mask is not display. */
11825 vty_out(vty
, " mask %s", inet_ntoa(netmask
));
11827 vty_out(vty
, " network %s/%d",
11828 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11833 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
11834 vty_out(vty
, " label-index %u",
11835 bgp_static
->label_index
);
11837 if (bgp_static
->rmap
.name
)
11838 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
11840 if (bgp_static
->backdoor
)
11841 vty_out(vty
, " backdoor");
11843 vty_out(vty
, "\n");
11846 /* Aggregate-address configuration. */
11847 for (rn
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); rn
;
11848 rn
= bgp_route_next(rn
)) {
11849 bgp_aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
11850 if (bgp_aggregate
== NULL
)
11855 if (bgp_option_check(BGP_OPT_CONFIG_CISCO
) && afi
== AFI_IP
) {
11856 struct in_addr netmask
;
11858 masklen2ip(p
->prefixlen
, &netmask
);
11859 vty_out(vty
, " aggregate-address %s %s",
11860 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11862 inet_ntoa(netmask
));
11864 vty_out(vty
, " aggregate-address %s/%d",
11865 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11870 if (bgp_aggregate
->as_set
)
11871 vty_out(vty
, " as-set");
11873 if (bgp_aggregate
->summary_only
)
11874 vty_out(vty
, " summary-only");
11876 vty_out(vty
, "\n");
11880 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11883 struct bgp_node
*rn
;
11884 struct bgp_distance
*bdistance
;
11886 /* Distance configuration. */
11887 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
11888 && bgp
->distance_local
[afi
][safi
]
11889 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
11890 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
11891 || bgp
->distance_local
[afi
][safi
]
11892 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
11893 vty_out(vty
, " distance bgp %d %d %d\n",
11894 bgp
->distance_ebgp
[afi
][safi
],
11895 bgp
->distance_ibgp
[afi
][safi
],
11896 bgp
->distance_local
[afi
][safi
]);
11899 for (rn
= bgp_table_top(bgp_distance_table
[afi
][safi
]); rn
;
11900 rn
= bgp_route_next(rn
)) {
11901 bdistance
= bgp_node_get_bgp_distance_info(rn
);
11902 if (bdistance
!= NULL
) {
11903 char buf
[PREFIX_STRLEN
];
11905 vty_out(vty
, " distance %d %s %s\n",
11906 bdistance
->distance
,
11907 prefix2str(&rn
->p
, buf
, sizeof(buf
)),
11908 bdistance
->access_list
? bdistance
->access_list
11914 /* Allocate routing table structure and install commands. */
11915 void bgp_route_init(void)
11920 /* Init BGP distance table. */
11921 FOREACH_AFI_SAFI (afi
, safi
)
11922 bgp_distance_table
[afi
][safi
] = bgp_table_init(NULL
, afi
, safi
);
11924 /* IPv4 BGP commands. */
11925 install_element(BGP_NODE
, &bgp_table_map_cmd
);
11926 install_element(BGP_NODE
, &bgp_network_cmd
);
11927 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
11929 install_element(BGP_NODE
, &aggregate_address_cmd
);
11930 install_element(BGP_NODE
, &aggregate_address_mask_cmd
);
11931 install_element(BGP_NODE
, &no_aggregate_address_cmd
);
11932 install_element(BGP_NODE
, &no_aggregate_address_mask_cmd
);
11934 /* IPv4 unicast configuration. */
11935 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
11936 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
11937 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
11939 install_element(BGP_IPV4_NODE
, &aggregate_address_cmd
);
11940 install_element(BGP_IPV4_NODE
, &aggregate_address_mask_cmd
);
11941 install_element(BGP_IPV4_NODE
, &no_aggregate_address_cmd
);
11942 install_element(BGP_IPV4_NODE
, &no_aggregate_address_mask_cmd
);
11944 /* IPv4 multicast configuration. */
11945 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
11946 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
11947 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
11948 install_element(BGP_IPV4M_NODE
, &aggregate_address_cmd
);
11949 install_element(BGP_IPV4M_NODE
, &aggregate_address_mask_cmd
);
11950 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_cmd
);
11951 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_mask_cmd
);
11953 /* IPv4 labeled-unicast configuration. */
11954 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
11955 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
11956 install_element(VIEW_NODE
, &show_ip_bgp_json_cmd
);
11957 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
11958 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
11960 install_element(VIEW_NODE
,
11961 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
11962 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
11963 install_element(VIEW_NODE
,
11964 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
11965 #ifdef KEEP_OLD_VPN_COMMANDS
11966 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
11967 #endif /* KEEP_OLD_VPN_COMMANDS */
11968 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
11969 install_element(VIEW_NODE
,
11970 &show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd
);
11972 /* BGP dampening clear commands */
11973 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
11974 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
11976 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
11977 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
11980 install_element(ENABLE_NODE
,
11981 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
11982 #ifdef KEEP_OLD_VPN_COMMANDS
11983 install_element(ENABLE_NODE
,
11984 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
11985 #endif /* KEEP_OLD_VPN_COMMANDS */
11987 /* New config IPv6 BGP commands. */
11988 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
11989 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
11990 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
11992 install_element(BGP_IPV6_NODE
, &ipv6_aggregate_address_cmd
);
11993 install_element(BGP_IPV6_NODE
, &no_ipv6_aggregate_address_cmd
);
11995 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
11997 install_element(BGP_NODE
, &bgp_distance_cmd
);
11998 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
11999 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
12000 install_element(BGP_NODE
, &no_bgp_distance_source_cmd
);
12001 install_element(BGP_NODE
, &bgp_distance_source_access_list_cmd
);
12002 install_element(BGP_NODE
, &no_bgp_distance_source_access_list_cmd
);
12003 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
12004 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
12005 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
12006 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_cmd
);
12007 install_element(BGP_IPV4_NODE
, &bgp_distance_source_access_list_cmd
);
12008 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_access_list_cmd
);
12009 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
12010 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
12011 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
12012 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_source_cmd
);
12013 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_access_list_cmd
);
12014 install_element(BGP_IPV4M_NODE
,
12015 &no_bgp_distance_source_access_list_cmd
);
12016 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
12017 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
12018 install_element(BGP_IPV6_NODE
, &ipv6_bgp_distance_source_cmd
);
12019 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_distance_source_cmd
);
12020 install_element(BGP_IPV6_NODE
,
12021 &ipv6_bgp_distance_source_access_list_cmd
);
12022 install_element(BGP_IPV6_NODE
,
12023 &no_ipv6_bgp_distance_source_access_list_cmd
);
12024 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
12025 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
12026 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_distance_source_cmd
);
12027 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_distance_source_cmd
);
12028 install_element(BGP_IPV6M_NODE
,
12029 &ipv6_bgp_distance_source_access_list_cmd
);
12030 install_element(BGP_IPV6M_NODE
,
12031 &no_ipv6_bgp_distance_source_access_list_cmd
);
12033 install_element(BGP_NODE
, &bgp_damp_set_cmd
);
12034 install_element(BGP_NODE
, &bgp_damp_unset_cmd
);
12035 install_element(BGP_IPV4_NODE
, &bgp_damp_set_cmd
);
12036 install_element(BGP_IPV4_NODE
, &bgp_damp_unset_cmd
);
12038 /* IPv4 Multicast Mode */
12039 install_element(BGP_IPV4M_NODE
, &bgp_damp_set_cmd
);
12040 install_element(BGP_IPV4M_NODE
, &bgp_damp_unset_cmd
);
12042 /* Large Communities */
12043 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
12044 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
12046 /* show bgp ipv4 flowspec detailed */
12047 install_element(VIEW_NODE
, &show_ip_bgp_flowspec_routes_detailed_cmd
);
12049 install_element(VIEW_NODE
, &show_bgp_peerhash_cmd
);
12052 void bgp_route_finish(void)
12057 FOREACH_AFI_SAFI (afi
, safi
) {
12058 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
12059 bgp_distance_table
[afi
][safi
] = NULL
;