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
= NULL
;
179 new->bgp_fs_iprule
= NULL
;
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 /* Free bgp route information. */
243 static void bgp_path_info_free(struct bgp_path_info
*path
)
246 bgp_attr_unintern(&path
->attr
);
248 bgp_unlink_nexthop(path
);
249 bgp_path_info_extra_free(&path
->extra
);
250 bgp_path_info_mpath_free(&path
->mpath
);
252 bgp_addpath_free_info_data(&path
->tx_addpath
,
253 &path
->net
->tx_addpath
);
255 peer_unlock(path
->peer
); /* bgp_path_info peer reference */
257 XFREE(MTYPE_BGP_ROUTE
, path
);
260 struct bgp_path_info
*bgp_path_info_lock(struct bgp_path_info
*path
)
266 struct bgp_path_info
*bgp_path_info_unlock(struct bgp_path_info
*path
)
268 assert(path
&& path
->lock
> 0);
271 if (path
->lock
== 0) {
273 zlog_debug ("%s: unlocked and freeing", __func__
);
274 zlog_backtrace (LOG_DEBUG
);
276 bgp_path_info_free(path
);
283 zlog_debug ("%s: unlocked to 1", __func__
);
284 zlog_backtrace (LOG_DEBUG
);
291 void bgp_path_info_add(struct bgp_node
*rn
, struct bgp_path_info
*pi
)
293 struct bgp_path_info
*top
;
295 top
= bgp_node_get_bgp_path_info(rn
);
301 bgp_node_set_bgp_path_info(rn
, pi
);
303 bgp_path_info_lock(pi
);
305 peer_lock(pi
->peer
); /* bgp_path_info peer reference */
308 /* Do the actual removal of info from RIB, for use by bgp_process
309 completion callback *only* */
310 void bgp_path_info_reap(struct bgp_node
*rn
, struct bgp_path_info
*pi
)
313 pi
->next
->prev
= pi
->prev
;
315 pi
->prev
->next
= pi
->next
;
317 bgp_node_set_bgp_path_info(rn
, pi
->next
);
319 bgp_path_info_mpath_dequeue(pi
);
320 bgp_path_info_unlock(pi
);
324 void bgp_path_info_delete(struct bgp_node
*rn
, struct bgp_path_info
*pi
)
326 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_REMOVED
);
327 /* set of previous already took care of pcount */
328 UNSET_FLAG(pi
->flags
, BGP_PATH_VALID
);
331 /* undo the effects of a previous call to bgp_path_info_delete; typically
332 called when a route is deleted and then quickly re-added before the
333 deletion has been processed */
334 void bgp_path_info_restore(struct bgp_node
*rn
, struct bgp_path_info
*pi
)
336 bgp_path_info_unset_flag(rn
, pi
, BGP_PATH_REMOVED
);
337 /* unset of previous already took care of pcount */
338 SET_FLAG(pi
->flags
, BGP_PATH_VALID
);
341 /* Adjust pcount as required */
342 static void bgp_pcount_adjust(struct bgp_node
*rn
, struct bgp_path_info
*pi
)
344 struct bgp_table
*table
;
346 assert(rn
&& bgp_node_table(rn
));
347 assert(pi
&& pi
->peer
&& pi
->peer
->bgp
);
349 table
= bgp_node_table(rn
);
351 if (pi
->peer
== pi
->peer
->bgp
->peer_self
)
354 if (!BGP_PATH_COUNTABLE(pi
)
355 && CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
357 UNSET_FLAG(pi
->flags
, BGP_PATH_COUNTED
);
359 /* slight hack, but more robust against errors. */
360 if (pi
->peer
->pcount
[table
->afi
][table
->safi
])
361 pi
->peer
->pcount
[table
->afi
][table
->safi
]--;
363 flog_err(EC_LIB_DEVELOPMENT
,
364 "Asked to decrement 0 prefix count for peer");
365 } else if (BGP_PATH_COUNTABLE(pi
)
366 && !CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
367 SET_FLAG(pi
->flags
, BGP_PATH_COUNTED
);
368 pi
->peer
->pcount
[table
->afi
][table
->safi
]++;
372 static int bgp_label_index_differs(struct bgp_path_info
*pi1
,
373 struct bgp_path_info
*pi2
)
375 return (!(pi1
->attr
->label_index
== pi2
->attr
->label_index
));
378 /* Set/unset bgp_path_info flags, adjusting any other state as needed.
379 * This is here primarily to keep prefix-count in check.
381 void bgp_path_info_set_flag(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
384 SET_FLAG(pi
->flags
, flag
);
386 /* early bath if we know it's not a flag that changes countability state
388 if (!CHECK_FLAG(flag
,
389 BGP_PATH_VALID
| BGP_PATH_HISTORY
| BGP_PATH_REMOVED
))
392 bgp_pcount_adjust(rn
, pi
);
395 void bgp_path_info_unset_flag(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
398 UNSET_FLAG(pi
->flags
, flag
);
400 /* early bath if we know it's not a flag that changes countability state
402 if (!CHECK_FLAG(flag
,
403 BGP_PATH_VALID
| BGP_PATH_HISTORY
| BGP_PATH_REMOVED
))
406 bgp_pcount_adjust(rn
, pi
);
409 /* Get MED value. If MED value is missing and "bgp bestpath
410 missing-as-worst" is specified, treat it as the worst value. */
411 static uint32_t bgp_med_value(struct attr
*attr
, struct bgp
*bgp
)
413 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
416 if (bgp_flag_check(bgp
, BGP_FLAG_MED_MISSING_AS_WORST
))
423 void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info
*pi
, char *buf
)
425 if (pi
->addpath_rx_id
)
426 sprintf(buf
, "path %s (addpath rxid %d)", pi
->peer
->host
,
429 sprintf(buf
, "path %s", pi
->peer
->host
);
432 /* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
434 static int bgp_path_info_cmp(struct bgp
*bgp
, struct bgp_path_info
*new,
435 struct bgp_path_info
*exist
, int *paths_eq
,
436 struct bgp_maxpaths_cfg
*mpath_cfg
, int debug
,
437 char *pfx_buf
, afi_t afi
, safi_t safi
)
439 struct attr
*newattr
, *existattr
;
440 bgp_peer_sort_t new_sort
;
441 bgp_peer_sort_t exist_sort
;
447 uint32_t exist_weight
;
448 uint32_t newm
, existm
;
449 struct in_addr new_id
;
450 struct in_addr exist_id
;
453 int internal_as_route
;
456 char new_buf
[PATH_ADDPATH_STR_BUFFER
];
457 char exist_buf
[PATH_ADDPATH_STR_BUFFER
];
459 uint32_t exist_mm_seq
;
467 zlog_debug("%s: new is NULL", pfx_buf
);
472 bgp_path_info_path_with_addpath_rx_str(new, new_buf
);
476 zlog_debug("%s: %s is the initial bestpath", pfx_buf
,
482 bgp_path_info_path_with_addpath_rx_str(exist
, exist_buf
);
483 zlog_debug("%s: Comparing %s flags 0x%x with %s flags 0x%x",
484 pfx_buf
, new_buf
, new->flags
, exist_buf
,
489 existattr
= exist
->attr
;
491 /* For EVPN routes, we cannot just go by local vs remote, we have to
492 * look at the MAC mobility sequence number, if present.
494 if (safi
== SAFI_EVPN
) {
495 /* This is an error condition described in RFC 7432 Section
497 * states that in this scenario "the PE MUST alert the operator"
499 * does not state what other action to take. In order to provide
501 * consistency in this scenario we are going to prefer the path
505 if (newattr
->sticky
!= existattr
->sticky
) {
507 prefix2str(&new->net
->p
, pfx_buf
,
509 * PREFIX2STR_BUFFER
);
510 bgp_path_info_path_with_addpath_rx_str(new,
512 bgp_path_info_path_with_addpath_rx_str(
516 if (newattr
->sticky
&& !existattr
->sticky
) {
519 "%s: %s wins over %s due to sticky MAC flag",
520 pfx_buf
, new_buf
, exist_buf
);
524 if (!newattr
->sticky
&& existattr
->sticky
) {
527 "%s: %s loses to %s due to sticky MAC flag",
528 pfx_buf
, new_buf
, exist_buf
);
533 new_mm_seq
= mac_mobility_seqnum(newattr
);
534 exist_mm_seq
= mac_mobility_seqnum(existattr
);
536 if (new_mm_seq
> exist_mm_seq
) {
539 "%s: %s wins over %s due to MM seq %u > %u",
540 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
545 if (new_mm_seq
< exist_mm_seq
) {
548 "%s: %s loses to %s due to MM seq %u < %u",
549 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
555 * if sequence numbers are the same path with the lowest IP
558 nh_cmp
= bgp_path_info_nexthop_cmp(new, exist
);
562 "%s: %s wins over %s due to same MM seq %u and lower IP %s",
563 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
564 inet_ntoa(new->attr
->nexthop
));
570 "%s: %s loses to %s due to same MM seq %u and higher IP %s",
571 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
572 inet_ntoa(new->attr
->nexthop
));
577 /* 1. Weight check. */
578 new_weight
= newattr
->weight
;
579 exist_weight
= existattr
->weight
;
581 if (new_weight
> exist_weight
) {
583 zlog_debug("%s: %s wins over %s due to weight %d > %d",
584 pfx_buf
, new_buf
, exist_buf
, new_weight
,
589 if (new_weight
< exist_weight
) {
591 zlog_debug("%s: %s loses to %s due to weight %d < %d",
592 pfx_buf
, new_buf
, exist_buf
, new_weight
,
597 /* 2. Local preference check. */
598 new_pref
= exist_pref
= bgp
->default_local_pref
;
600 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
601 new_pref
= newattr
->local_pref
;
602 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
603 exist_pref
= existattr
->local_pref
;
605 if (new_pref
> exist_pref
) {
608 "%s: %s wins over %s due to localpref %d > %d",
609 pfx_buf
, new_buf
, exist_buf
, new_pref
,
614 if (new_pref
< exist_pref
) {
617 "%s: %s loses to %s due to localpref %d < %d",
618 pfx_buf
, new_buf
, exist_buf
, new_pref
,
623 /* 3. Local route check. We prefer:
625 * - BGP_ROUTE_AGGREGATE
626 * - BGP_ROUTE_REDISTRIBUTE
628 if (!(new->sub_type
== BGP_ROUTE_NORMAL
||
629 new->sub_type
== BGP_ROUTE_IMPORTED
)) {
632 "%s: %s wins over %s due to preferred BGP_ROUTE type",
633 pfx_buf
, new_buf
, exist_buf
);
637 if (!(exist
->sub_type
== BGP_ROUTE_NORMAL
||
638 exist
->sub_type
== BGP_ROUTE_IMPORTED
)) {
641 "%s: %s loses to %s due to preferred BGP_ROUTE type",
642 pfx_buf
, new_buf
, exist_buf
);
646 /* 4. AS path length check. */
647 if (!bgp_flag_check(bgp
, BGP_FLAG_ASPATH_IGNORE
)) {
648 int exist_hops
= aspath_count_hops(existattr
->aspath
);
649 int exist_confeds
= aspath_count_confeds(existattr
->aspath
);
651 if (bgp_flag_check(bgp
, BGP_FLAG_ASPATH_CONFED
)) {
654 aspath_hops
= aspath_count_hops(newattr
->aspath
);
655 aspath_hops
+= aspath_count_confeds(newattr
->aspath
);
657 if (aspath_hops
< (exist_hops
+ exist_confeds
)) {
660 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
661 pfx_buf
, new_buf
, exist_buf
,
663 (exist_hops
+ exist_confeds
));
667 if (aspath_hops
> (exist_hops
+ exist_confeds
)) {
670 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
671 pfx_buf
, new_buf
, exist_buf
,
673 (exist_hops
+ exist_confeds
));
677 int newhops
= aspath_count_hops(newattr
->aspath
);
679 if (newhops
< exist_hops
) {
682 "%s: %s wins over %s due to aspath hopcount %d < %d",
683 pfx_buf
, new_buf
, exist_buf
,
684 newhops
, exist_hops
);
688 if (newhops
> exist_hops
) {
691 "%s: %s loses to %s due to aspath hopcount %d > %d",
692 pfx_buf
, new_buf
, exist_buf
,
693 newhops
, exist_hops
);
699 /* 5. Origin check. */
700 if (newattr
->origin
< existattr
->origin
) {
702 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
703 pfx_buf
, new_buf
, exist_buf
,
704 bgp_origin_long_str
[newattr
->origin
],
705 bgp_origin_long_str
[existattr
->origin
]);
709 if (newattr
->origin
> existattr
->origin
) {
711 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
712 pfx_buf
, new_buf
, exist_buf
,
713 bgp_origin_long_str
[newattr
->origin
],
714 bgp_origin_long_str
[existattr
->origin
]);
719 internal_as_route
= (aspath_count_hops(newattr
->aspath
) == 0
720 && aspath_count_hops(existattr
->aspath
) == 0);
721 confed_as_route
= (aspath_count_confeds(newattr
->aspath
) > 0
722 && aspath_count_confeds(existattr
->aspath
) > 0
723 && aspath_count_hops(newattr
->aspath
) == 0
724 && aspath_count_hops(existattr
->aspath
) == 0);
726 if (bgp_flag_check(bgp
, BGP_FLAG_ALWAYS_COMPARE_MED
)
727 || (bgp_flag_check(bgp
, BGP_FLAG_MED_CONFED
) && confed_as_route
)
728 || aspath_cmp_left(newattr
->aspath
, existattr
->aspath
)
729 || aspath_cmp_left_confed(newattr
->aspath
, existattr
->aspath
)
730 || internal_as_route
) {
731 new_med
= bgp_med_value(new->attr
, bgp
);
732 exist_med
= bgp_med_value(exist
->attr
, bgp
);
734 if (new_med
< exist_med
) {
737 "%s: %s wins over %s due to MED %d < %d",
738 pfx_buf
, new_buf
, exist_buf
, new_med
,
743 if (new_med
> exist_med
) {
746 "%s: %s loses to %s due to MED %d > %d",
747 pfx_buf
, new_buf
, exist_buf
, new_med
,
753 /* 7. Peer type check. */
754 new_sort
= new->peer
->sort
;
755 exist_sort
= exist
->peer
->sort
;
757 if (new_sort
== BGP_PEER_EBGP
758 && (exist_sort
== BGP_PEER_IBGP
|| exist_sort
== BGP_PEER_CONFED
)) {
761 "%s: %s wins over %s due to eBGP peer > iBGP peer",
762 pfx_buf
, new_buf
, exist_buf
);
766 if (exist_sort
== BGP_PEER_EBGP
767 && (new_sort
== BGP_PEER_IBGP
|| new_sort
== BGP_PEER_CONFED
)) {
770 "%s: %s loses to %s due to iBGP peer < eBGP peer",
771 pfx_buf
, new_buf
, exist_buf
);
775 /* 8. IGP metric check. */
779 newm
= new->extra
->igpmetric
;
781 existm
= exist
->extra
->igpmetric
;
786 "%s: %s wins over %s due to IGP metric %d < %d",
787 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
794 "%s: %s loses to %s due to IGP metric %d > %d",
795 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
799 /* 9. Same IGP metric. Compare the cluster list length as
800 representative of IGP hops metric. Rewrite the metric value
801 pair (newm, existm) with the cluster list length. Prefer the
802 path with smaller cluster list length. */
803 if (newm
== existm
) {
804 if (peer_sort(new->peer
) == BGP_PEER_IBGP
805 && peer_sort(exist
->peer
) == BGP_PEER_IBGP
806 && (mpath_cfg
== NULL
808 mpath_cfg
->ibgp_flags
,
809 BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN
))) {
810 newm
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
811 existm
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
816 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
817 pfx_buf
, new_buf
, exist_buf
,
825 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
826 pfx_buf
, new_buf
, exist_buf
,
833 /* 10. confed-external vs. confed-internal */
834 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
835 if (new_sort
== BGP_PEER_CONFED
836 && exist_sort
== BGP_PEER_IBGP
) {
839 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
840 pfx_buf
, new_buf
, exist_buf
);
844 if (exist_sort
== BGP_PEER_CONFED
845 && new_sort
== BGP_PEER_IBGP
) {
848 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
849 pfx_buf
, new_buf
, exist_buf
);
854 /* 11. Maximum path check. */
855 if (newm
== existm
) {
856 /* If one path has a label but the other does not, do not treat
857 * them as equals for multipath
859 if ((new->extra
&&bgp_is_valid_label(&new->extra
->label
[0]))
861 && bgp_is_valid_label(&exist
->extra
->label
[0]))) {
864 "%s: %s and %s cannot be multipath, one has a label while the other does not",
865 pfx_buf
, new_buf
, exist_buf
);
866 } else if (bgp_flag_check(bgp
,
867 BGP_FLAG_ASPATH_MULTIPATH_RELAX
)) {
870 * For the two paths, all comparison steps till IGP
872 * have succeeded - including AS_PATH hop count. Since
874 * bestpath as-path multipath-relax' knob is on, we
876 * an exact match of AS_PATH. Thus, mark the paths are
878 * That will trigger both these paths to get into the
886 "%s: %s and %s are equal via multipath-relax",
887 pfx_buf
, new_buf
, exist_buf
);
888 } else if (new->peer
->sort
== BGP_PEER_IBGP
) {
889 if (aspath_cmp(new->attr
->aspath
,
890 exist
->attr
->aspath
)) {
895 "%s: %s and %s are equal via matching aspaths",
896 pfx_buf
, new_buf
, exist_buf
);
898 } else if (new->peer
->as
== exist
->peer
->as
) {
903 "%s: %s and %s are equal via same remote-as",
904 pfx_buf
, new_buf
, exist_buf
);
908 * TODO: If unequal cost ibgp multipath is enabled we can
909 * mark the paths as equal here instead of returning
914 "%s: %s wins over %s after IGP metric comparison",
915 pfx_buf
, new_buf
, exist_buf
);
918 "%s: %s loses to %s after IGP metric comparison",
919 pfx_buf
, new_buf
, exist_buf
);
924 /* 12. If both paths are external, prefer the path that was received
925 first (the oldest one). This step minimizes route-flap, since a
926 newer path won't displace an older one, even if it was the
927 preferred route based on the additional decision criteria below. */
928 if (!bgp_flag_check(bgp
, BGP_FLAG_COMPARE_ROUTER_ID
)
929 && new_sort
== BGP_PEER_EBGP
&& exist_sort
== BGP_PEER_EBGP
) {
930 if (CHECK_FLAG(new->flags
, BGP_PATH_SELECTED
)) {
933 "%s: %s wins over %s due to oldest external",
934 pfx_buf
, new_buf
, exist_buf
);
938 if (CHECK_FLAG(exist
->flags
, BGP_PATH_SELECTED
)) {
941 "%s: %s loses to %s due to oldest external",
942 pfx_buf
, new_buf
, exist_buf
);
947 /* 13. Router-ID comparision. */
948 /* If one of the paths is "stale", the corresponding peer router-id will
949 * be 0 and would always win over the other path. If originator id is
950 * used for the comparision, it will decide which path is better.
952 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
953 new_id
.s_addr
= newattr
->originator_id
.s_addr
;
955 new_id
.s_addr
= new->peer
->remote_id
.s_addr
;
956 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
957 exist_id
.s_addr
= existattr
->originator_id
.s_addr
;
959 exist_id
.s_addr
= exist
->peer
->remote_id
.s_addr
;
961 if (ntohl(new_id
.s_addr
) < ntohl(exist_id
.s_addr
)) {
964 "%s: %s wins over %s due to Router-ID comparison",
965 pfx_buf
, new_buf
, exist_buf
);
969 if (ntohl(new_id
.s_addr
) > ntohl(exist_id
.s_addr
)) {
972 "%s: %s loses to %s due to Router-ID comparison",
973 pfx_buf
, new_buf
, exist_buf
);
977 /* 14. Cluster length comparision. */
978 new_cluster
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
979 exist_cluster
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
981 if (new_cluster
< exist_cluster
) {
984 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
985 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
990 if (new_cluster
> exist_cluster
) {
993 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
994 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
999 /* 15. Neighbor address comparision. */
1000 /* Do this only if neither path is "stale" as stale paths do not have
1001 * valid peer information (as the connection may or may not be up).
1003 if (CHECK_FLAG(exist
->flags
, BGP_PATH_STALE
)) {
1006 "%s: %s wins over %s due to latter path being STALE",
1007 pfx_buf
, new_buf
, exist_buf
);
1011 if (CHECK_FLAG(new->flags
, BGP_PATH_STALE
)) {
1014 "%s: %s loses to %s due to former path being STALE",
1015 pfx_buf
, new_buf
, exist_buf
);
1019 /* locally configured routes to advertise do not have su_remote */
1020 if (new->peer
->su_remote
== NULL
)
1022 if (exist
->peer
->su_remote
== NULL
)
1025 ret
= sockunion_cmp(new->peer
->su_remote
, exist
->peer
->su_remote
);
1030 "%s: %s loses to %s due to Neighor IP comparison",
1031 pfx_buf
, new_buf
, exist_buf
);
1038 "%s: %s wins over %s due to Neighor IP comparison",
1039 pfx_buf
, new_buf
, exist_buf
);
1044 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1045 pfx_buf
, new_buf
, exist_buf
);
1050 /* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1051 * is preferred, or 0 if they are the same (usually will only occur if
1052 * multipath is enabled
1053 * This version is compatible with */
1054 int bgp_path_info_cmp_compatible(struct bgp
*bgp
, struct bgp_path_info
*new,
1055 struct bgp_path_info
*exist
, char *pfx_buf
,
1056 afi_t afi
, safi_t safi
)
1060 ret
= bgp_path_info_cmp(bgp
, new, exist
, &paths_eq
, NULL
, 0, pfx_buf
,
1074 static enum filter_type
bgp_input_filter(struct peer
*peer
, struct prefix
*p
,
1075 struct attr
*attr
, afi_t afi
,
1078 struct bgp_filter
*filter
;
1080 filter
= &peer
->filter
[afi
][safi
];
1082 #define FILTER_EXIST_WARN(F, f, filter) \
1083 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
1084 zlog_debug("%s: Could not find configured input %s-list %s!", \
1085 peer->host, #f, F##_IN_NAME(filter));
1087 if (DISTRIBUTE_IN_NAME(filter
)) {
1088 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1090 if (access_list_apply(DISTRIBUTE_IN(filter
), p
) == FILTER_DENY
)
1094 if (PREFIX_LIST_IN_NAME(filter
)) {
1095 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1097 if (prefix_list_apply(PREFIX_LIST_IN(filter
), p
) == PREFIX_DENY
)
1101 if (FILTER_LIST_IN_NAME(filter
)) {
1102 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1104 if (as_list_apply(FILTER_LIST_IN(filter
), attr
->aspath
)
1109 return FILTER_PERMIT
;
1110 #undef FILTER_EXIST_WARN
1113 static enum filter_type
bgp_output_filter(struct peer
*peer
, struct prefix
*p
,
1114 struct attr
*attr
, afi_t afi
,
1117 struct bgp_filter
*filter
;
1119 filter
= &peer
->filter
[afi
][safi
];
1121 #define FILTER_EXIST_WARN(F, f, filter) \
1122 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
1123 zlog_debug("%s: Could not find configured output %s-list %s!", \
1124 peer->host, #f, F##_OUT_NAME(filter));
1126 if (DISTRIBUTE_OUT_NAME(filter
)) {
1127 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1129 if (access_list_apply(DISTRIBUTE_OUT(filter
), p
) == FILTER_DENY
)
1133 if (PREFIX_LIST_OUT_NAME(filter
)) {
1134 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1136 if (prefix_list_apply(PREFIX_LIST_OUT(filter
), p
)
1141 if (FILTER_LIST_OUT_NAME(filter
)) {
1142 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1144 if (as_list_apply(FILTER_LIST_OUT(filter
), attr
->aspath
)
1149 return FILTER_PERMIT
;
1150 #undef FILTER_EXIST_WARN
1153 /* If community attribute includes no_export then return 1. */
1154 static int bgp_community_filter(struct peer
*peer
, struct attr
*attr
)
1156 if (attr
->community
) {
1157 /* NO_ADVERTISE check. */
1158 if (community_include(attr
->community
, COMMUNITY_NO_ADVERTISE
))
1161 /* NO_EXPORT check. */
1162 if (peer
->sort
== BGP_PEER_EBGP
1163 && community_include(attr
->community
, COMMUNITY_NO_EXPORT
))
1166 /* NO_EXPORT_SUBCONFED check. */
1167 if (peer
->sort
== BGP_PEER_EBGP
1168 || peer
->sort
== BGP_PEER_CONFED
)
1169 if (community_include(attr
->community
,
1170 COMMUNITY_NO_EXPORT_SUBCONFED
))
1176 /* Route reflection loop check. */
1177 static int bgp_cluster_filter(struct peer
*peer
, struct attr
*attr
)
1179 struct in_addr cluster_id
;
1181 if (attr
->cluster
) {
1182 if (peer
->bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
1183 cluster_id
= peer
->bgp
->cluster_id
;
1185 cluster_id
= peer
->bgp
->router_id
;
1187 if (cluster_loop_check(attr
->cluster
, cluster_id
))
1193 static int bgp_input_modifier(struct peer
*peer
, struct prefix
*p
,
1194 struct attr
*attr
, afi_t afi
, safi_t safi
,
1195 const char *rmap_name
)
1197 struct bgp_filter
*filter
;
1198 struct bgp_path_info rmap_path
;
1199 route_map_result_t ret
;
1200 struct route_map
*rmap
= NULL
;
1202 filter
= &peer
->filter
[afi
][safi
];
1204 /* Apply default weight value. */
1205 if (peer
->weight
[afi
][safi
])
1206 attr
->weight
= peer
->weight
[afi
][safi
];
1209 rmap
= route_map_lookup_by_name(rmap_name
);
1214 if (ROUTE_MAP_IN_NAME(filter
)) {
1215 rmap
= ROUTE_MAP_IN(filter
);
1222 /* RFC 8212 to prevent route leaks.
1223 * This specification intends to improve this situation by requiring the
1224 * explicit configuration of both BGP Import and Export Policies for any
1225 * External BGP (EBGP) session such as customers, peers, or
1226 * confederation boundaries for all enabled address families. Through
1227 * codification of the aforementioned requirement, operators will
1228 * benefit from consistent behavior across different BGP
1231 if (peer
->bgp
->ebgp_requires_policy
1232 == DEFAULT_EBGP_POLICY_ENABLED
)
1233 if (!bgp_inbound_policy_exists(peer
, filter
))
1236 /* Route map apply. */
1238 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
1239 /* Duplicate current value to new strucutre for modification. */
1240 rmap_path
.peer
= peer
;
1241 rmap_path
.attr
= attr
;
1243 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_IN
);
1245 /* Apply BGP route map to the attribute. */
1246 ret
= route_map_apply(rmap
, p
, RMAP_BGP
, &rmap_path
);
1248 peer
->rmap_type
= 0;
1250 if (ret
== RMAP_DENYMATCH
)
1256 static int bgp_output_modifier(struct peer
*peer
, struct prefix
*p
,
1257 struct attr
*attr
, afi_t afi
, safi_t safi
,
1258 const char *rmap_name
)
1260 struct bgp_path_info rmap_path
;
1261 route_map_result_t ret
;
1262 struct route_map
*rmap
= NULL
;
1266 * So if we get to this point and have no rmap_name
1267 * we want to just show the output as it currently
1273 /* Apply default weight value. */
1274 if (peer
->weight
[afi
][safi
])
1275 attr
->weight
= peer
->weight
[afi
][safi
];
1277 rmap
= route_map_lookup_by_name(rmap_name
);
1280 * If we have a route map name and we do not find
1281 * the routemap that means we have an implicit
1287 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
1288 /* Route map apply. */
1289 /* Duplicate current value to new strucutre for modification. */
1290 rmap_path
.peer
= peer
;
1291 rmap_path
.attr
= attr
;
1293 rmap_type
= peer
->rmap_type
;
1294 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1296 /* Apply BGP route map to the attribute. */
1297 ret
= route_map_apply(rmap
, p
, RMAP_BGP
, &rmap_path
);
1299 peer
->rmap_type
= rmap_type
;
1301 if (ret
== RMAP_DENYMATCH
)
1303 * caller has multiple error paths with bgp_attr_flush()
1310 /* If this is an EBGP peer with remove-private-AS */
1311 static void bgp_peer_remove_private_as(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1312 struct peer
*peer
, struct attr
*attr
)
1314 if (peer
->sort
== BGP_PEER_EBGP
1315 && (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_REPLACE
)
1319 || peer_af_flag_check(peer
, afi
, safi
,
1320 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)
1321 || peer_af_flag_check(peer
, afi
, safi
,
1322 PEER_FLAG_REMOVE_PRIVATE_AS
))) {
1323 // Take action on the entire aspath
1324 if (peer_af_flag_check(peer
, afi
, safi
,
1325 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1326 || peer_af_flag_check(peer
, afi
, safi
,
1327 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)) {
1328 if (peer_af_flag_check(
1330 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
))
1331 attr
->aspath
= aspath_replace_private_asns(
1332 attr
->aspath
, bgp
->as
);
1334 // The entire aspath consists of private ASNs so create
1336 else if (aspath_private_as_check(attr
->aspath
))
1337 attr
->aspath
= aspath_empty_get();
1339 // There are some public and some private ASNs, remove
1342 attr
->aspath
= aspath_remove_private_asns(
1346 // 'all' was not specified so the entire aspath must be private
1348 // for us to do anything
1349 else if (aspath_private_as_check(attr
->aspath
)) {
1350 if (peer_af_flag_check(
1352 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
))
1353 attr
->aspath
= aspath_replace_private_asns(
1354 attr
->aspath
, bgp
->as
);
1356 attr
->aspath
= aspath_empty_get();
1361 /* If this is an EBGP peer with as-override */
1362 static void bgp_peer_as_override(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1363 struct peer
*peer
, struct attr
*attr
)
1365 if (peer
->sort
== BGP_PEER_EBGP
1366 && peer_af_flag_check(peer
, afi
, safi
, PEER_FLAG_AS_OVERRIDE
)) {
1367 if (aspath_single_asn_check(attr
->aspath
, peer
->as
))
1368 attr
->aspath
= aspath_replace_specific_asn(
1369 attr
->aspath
, peer
->as
, bgp
->as
);
1373 void bgp_attr_add_gshut_community(struct attr
*attr
)
1375 struct community
*old
;
1376 struct community
*new;
1377 struct community
*merge
;
1378 struct community
*gshut
;
1380 old
= attr
->community
;
1381 gshut
= community_str2com("graceful-shutdown");
1386 merge
= community_merge(community_dup(old
), gshut
);
1388 if (old
->refcnt
== 0)
1389 community_free(&old
);
1391 new = community_uniq_sort(merge
);
1392 community_free(&merge
);
1394 new = community_dup(gshut
);
1397 community_free(&gshut
);
1398 attr
->community
= new;
1399 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
1401 /* When we add the graceful-shutdown community we must also
1402 * lower the local-preference */
1403 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1404 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1408 static void subgroup_announce_reset_nhop(uint8_t family
, struct attr
*attr
)
1410 if (family
== AF_INET
) {
1411 attr
->nexthop
.s_addr
= 0;
1412 attr
->mp_nexthop_global_in
.s_addr
= 0;
1414 if (family
== AF_INET6
)
1415 memset(&attr
->mp_nexthop_global
, 0, IPV6_MAX_BYTELEN
);
1416 if (family
== AF_EVPN
)
1417 memset(&attr
->mp_nexthop_global_in
, 0, BGP_ATTR_NHLEN_IPV4
);
1420 int subgroup_announce_check(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
1421 struct update_subgroup
*subgrp
, struct prefix
*p
,
1424 struct bgp_filter
*filter
;
1427 struct peer
*onlypeer
;
1429 struct attr
*piattr
;
1430 char buf
[PREFIX_STRLEN
];
1436 int samepeer_safe
= 0; /* for synthetic mplsvpns routes */
1438 if (DISABLE_BGP_ANNOUNCE
)
1441 afi
= SUBGRP_AFI(subgrp
);
1442 safi
= SUBGRP_SAFI(subgrp
);
1443 peer
= SUBGRP_PEER(subgrp
);
1445 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_LONESOUL
))
1446 onlypeer
= SUBGRP_PFIRST(subgrp
)->peer
;
1449 filter
= &peer
->filter
[afi
][safi
];
1450 bgp
= SUBGRP_INST(subgrp
);
1451 piattr
= bgp_path_info_mpath_count(pi
) ? bgp_path_info_mpath_attr(pi
)
1455 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
)) && (safi
== SAFI_MPLS_VPN
)
1456 && ((pi
->type
== ZEBRA_ROUTE_BGP_DIRECT
)
1457 || (pi
->type
== ZEBRA_ROUTE_BGP_DIRECT_EXT
))) {
1460 * direct and direct_ext type routes originate internally even
1461 * though they can have peer pointers that reference other
1464 prefix2str(p
, buf
, PREFIX_STRLEN
);
1465 zlog_debug("%s: pfx %s bgp_direct->vpn route peer safe",
1471 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
))
1472 && ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_UNICAST
))
1473 && (pi
->type
== ZEBRA_ROUTE_BGP
)
1474 && (pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
1476 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1481 /* With addpath we may be asked to TX all kinds of paths so make sure
1483 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
)
1484 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)
1485 || CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
1489 /* If this is not the bestpath then check to see if there is an enabled
1491 * feature that requires us to advertise it */
1492 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
1493 if (!bgp_addpath_tx_path(peer
->addpath_type
[afi
][safi
], pi
)) {
1498 /* Aggregate-address suppress check. */
1499 if (pi
->extra
&& pi
->extra
->suppress
)
1500 if (!UNSUPPRESS_MAP_NAME(filter
)) {
1505 * If we are doing VRF 2 VRF leaking via the import
1506 * statement, we want to prevent the route going
1507 * off box as that the RT and RD created are localy
1508 * significant and globaly useless.
1510 if (safi
== SAFI_MPLS_VPN
&& pi
->extra
&& pi
->extra
->num_labels
1511 && pi
->extra
->label
[0] == BGP_PREVENT_VRF_2_VRF_LEAK
)
1514 /* If it's labeled safi, make sure the route has a valid label. */
1515 if (safi
== SAFI_LABELED_UNICAST
) {
1516 mpls_label_t label
= bgp_adv_label(rn
, pi
, peer
, afi
, safi
);
1517 if (!bgp_is_valid_label(&label
)) {
1518 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1519 zlog_debug("u%" PRIu64
":s%" PRIu64
1520 " %s/%d is filtered - no label (%p)",
1521 subgrp
->update_group
->id
, subgrp
->id
,
1522 inet_ntop(p
->family
, &p
->u
.prefix
,
1523 buf
, SU_ADDRSTRLEN
),
1524 p
->prefixlen
, &label
);
1529 /* Do not send back route to sender. */
1530 if (onlypeer
&& from
== onlypeer
) {
1534 /* Do not send the default route in the BGP table if the neighbor is
1535 * configured for default-originate */
1536 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1537 PEER_FLAG_DEFAULT_ORIGINATE
)) {
1538 if (p
->family
== AF_INET
&& p
->u
.prefix4
.s_addr
== INADDR_ANY
)
1540 else if (p
->family
== AF_INET6
&& p
->prefixlen
== 0)
1544 /* Transparency check. */
1545 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
)
1546 && CHECK_FLAG(from
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
))
1551 /* If community is not disabled check the no-export and local. */
1552 if (!transparent
&& bgp_community_filter(peer
, piattr
)) {
1553 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1555 "subgrpannouncecheck: community filter check fail");
1559 /* If the attribute has originator-id and it is same as remote
1561 if (onlypeer
&& piattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
1562 && (IPV4_ADDR_SAME(&onlypeer
->remote_id
, &piattr
->originator_id
))) {
1563 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1565 "%s [Update:SEND] %s originator-id is same as "
1568 prefix2str(p
, buf
, sizeof(buf
)));
1572 /* ORF prefix-list filter check */
1573 if (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_RM_ADV
)
1574 && (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_SM_RCV
)
1575 || CHECK_FLAG(peer
->af_cap
[afi
][safi
],
1576 PEER_CAP_ORF_PREFIX_SM_OLD_RCV
)))
1577 if (peer
->orf_plist
[afi
][safi
]) {
1578 if (prefix_list_apply(peer
->orf_plist
[afi
][safi
], p
)
1580 if (bgp_debug_update(NULL
, p
,
1581 subgrp
->update_group
, 0))
1583 "%s [Update:SEND] %s is filtered via ORF",
1591 /* Output filter check. */
1592 if (bgp_output_filter(peer
, p
, piattr
, afi
, safi
) == FILTER_DENY
) {
1593 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1594 zlog_debug("%s [Update:SEND] %s is filtered",
1595 peer
->host
, prefix2str(p
, buf
, sizeof(buf
)));
1599 #ifdef BGP_SEND_ASPATH_CHECK
1600 /* AS path loop check. */
1601 if (onlypeer
&& aspath_loop_check(piattr
->aspath
, onlypeer
->as
)) {
1602 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1604 "%s [Update:SEND] suppress announcement to peer AS %u "
1605 "that is part of AS path.",
1606 onlypeer
->host
, onlypeer
->as
);
1609 #endif /* BGP_SEND_ASPATH_CHECK */
1611 /* If we're a CONFED we need to loop check the CONFED ID too */
1612 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
1613 if (aspath_loop_check(piattr
->aspath
, bgp
->confed_id
)) {
1614 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1616 "%s [Update:SEND] suppress announcement to peer AS %u"
1618 peer
->host
, bgp
->confed_id
);
1623 /* Route-Reflect check. */
1624 if (from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1629 /* IBGP reflection check. */
1630 if (reflect
&& !samepeer_safe
) {
1631 /* A route from a Client peer. */
1632 if (CHECK_FLAG(from
->af_flags
[afi
][safi
],
1633 PEER_FLAG_REFLECTOR_CLIENT
)) {
1634 /* Reflect to all the Non-Client peers and also to the
1635 Client peers other than the originator. Originator
1637 is already done. So there is noting to do. */
1638 /* no bgp client-to-client reflection check. */
1639 if (bgp_flag_check(bgp
, BGP_FLAG_NO_CLIENT_TO_CLIENT
))
1640 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1641 PEER_FLAG_REFLECTOR_CLIENT
))
1644 /* A route from a Non-client peer. Reflect to all other
1646 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1647 PEER_FLAG_REFLECTOR_CLIENT
))
1652 /* For modify attribute, copy it to temporary structure. */
1653 bgp_attr_dup(attr
, piattr
);
1655 /* If local-preference is not set. */
1656 if ((peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
)
1657 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))) {
1658 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1659 attr
->local_pref
= bgp
->default_local_pref
;
1662 /* If originator-id is not set and the route is to be reflected,
1663 set the originator id */
1665 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)))) {
1666 IPV4_ADDR_COPY(&(attr
->originator_id
), &(from
->remote_id
));
1667 SET_FLAG(attr
->flag
, BGP_ATTR_ORIGINATOR_ID
);
1670 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
1672 if (peer
->sort
== BGP_PEER_EBGP
1673 && attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
1674 if (from
!= bgp
->peer_self
&& !transparent
1675 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1676 PEER_FLAG_MED_UNCHANGED
))
1678 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
));
1681 /* Since the nexthop attribute can vary per peer, it is not explicitly
1683 * in announce check, only certain flags and length (or number of
1685 * -- for IPv6/MP_REACH) are set here in order to guide the update
1687 * code in setting the nexthop(s) on a per peer basis in
1689 * Typically, the source nexthop in the attribute is preserved but in
1691 * scenarios where we know it will always be overwritten, we reset the
1692 * nexthop to "0" in an attempt to achieve better Update packing. An
1693 * example of this is when a prefix from each of 2 IBGP peers needs to
1695 * announced to an EBGP peer (and they have the same attributes barring
1699 SET_FLAG(attr
->rmap_change_flags
, BATTR_REFLECTED
);
1701 #define NEXTHOP_IS_V6 \
1702 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
1703 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
1704 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
1705 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
1707 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
1709 * the peer (group) is configured to receive link-local nexthop
1711 * and it is available in the prefix OR we're not reflecting the route,
1712 * link-local nexthop address is valid and
1713 * the peer (group) to whom we're going to announce is on a shared
1715 * and this is either a self-originated route or the peer is EBGP.
1716 * By checking if nexthop LL address is valid we are sure that
1717 * we do not announce LL address as `::`.
1719 if (NEXTHOP_IS_V6
) {
1720 attr
->mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
1721 if ((CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1722 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)
1723 && IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
))
1725 && IN6_IS_ADDR_LINKLOCAL(&peer
->nexthop
.v6_local
)
1726 && peer
->shared_network
1727 && (from
== bgp
->peer_self
1728 || peer
->sort
== BGP_PEER_EBGP
))) {
1729 attr
->mp_nexthop_len
=
1730 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
;
1733 /* Clear off link-local nexthop in source, whenever it is not
1735 * ensure more prefixes share the same attribute for
1738 if (!(CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1739 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)))
1740 memset(&attr
->mp_nexthop_local
, 0, IPV6_MAX_BYTELEN
);
1743 bgp_peer_remove_private_as(bgp
, afi
, safi
, peer
, attr
);
1744 bgp_peer_as_override(bgp
, afi
, safi
, peer
, attr
);
1746 /* Route map & unsuppress-map apply. */
1747 if (ROUTE_MAP_OUT_NAME(filter
) || (pi
->extra
&& pi
->extra
->suppress
)) {
1748 struct bgp_path_info rmap_path
;
1749 struct bgp_path_info_extra dummy_rmap_path_extra
;
1750 struct attr dummy_attr
;
1752 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
1753 rmap_path
.peer
= peer
;
1754 rmap_path
.attr
= attr
;
1757 memcpy(&dummy_rmap_path_extra
, pi
->extra
,
1758 sizeof(struct bgp_path_info_extra
));
1759 rmap_path
.extra
= &dummy_rmap_path_extra
;
1762 /* don't confuse inbound and outbound setting */
1763 RESET_FLAG(attr
->rmap_change_flags
);
1766 * The route reflector is not allowed to modify the attributes
1767 * of the reflected IBGP routes unless explicitly allowed.
1769 if ((from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1770 && !bgp_flag_check(bgp
,
1771 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY
)) {
1772 bgp_attr_dup(&dummy_attr
, attr
);
1773 rmap_path
.attr
= &dummy_attr
;
1776 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1778 if (pi
->extra
&& pi
->extra
->suppress
)
1779 ret
= route_map_apply(UNSUPPRESS_MAP(filter
), p
,
1780 RMAP_BGP
, &rmap_path
);
1782 ret
= route_map_apply(ROUTE_MAP_OUT(filter
), p
,
1783 RMAP_BGP
, &rmap_path
);
1785 peer
->rmap_type
= 0;
1787 if (ret
== RMAP_DENYMATCH
) {
1788 bgp_attr_flush(attr
);
1793 /* RFC 8212 to prevent route leaks.
1794 * This specification intends to improve this situation by requiring the
1795 * explicit configuration of both BGP Import and Export Policies for any
1796 * External BGP (EBGP) session such as customers, peers, or
1797 * confederation boundaries for all enabled address families. Through
1798 * codification of the aforementioned requirement, operators will
1799 * benefit from consistent behavior across different BGP
1802 if (peer
->bgp
->ebgp_requires_policy
1803 == DEFAULT_EBGP_POLICY_ENABLED
)
1804 if (!bgp_outbound_policy_exists(peer
, filter
))
1807 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
1808 if (peer
->sort
== BGP_PEER_IBGP
1809 || peer
->sort
== BGP_PEER_CONFED
) {
1810 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1811 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1813 bgp_attr_add_gshut_community(attr
);
1817 /* After route-map has been applied, we check to see if the nexthop to
1818 * be carried in the attribute (that is used for the announcement) can
1819 * be cleared off or not. We do this in all cases where we would be
1820 * setting the nexthop to "ourselves". For IPv6, we only need to
1822 * the global nexthop here; the link-local nexthop would have been
1824 * already, and if not, it is required by the update formation code.
1825 * Also see earlier comments in this function.
1828 * If route-map has performed some operation on the nexthop or the peer
1829 * configuration says to pass it unchanged, we cannot reset the nexthop
1830 * here, so only attempt to do it if these aren't true. Note that the
1831 * route-map handler itself might have cleared the nexthop, if for
1833 * it is configured as 'peer-address'.
1835 if (!bgp_rmap_nhop_changed(attr
->rmap_change_flags
,
1836 piattr
->rmap_change_flags
)
1838 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1839 PEER_FLAG_NEXTHOP_UNCHANGED
)) {
1840 /* We can reset the nexthop, if setting (or forcing) it to
1842 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1843 PEER_FLAG_NEXTHOP_SELF
)
1844 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1845 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
1847 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1848 PEER_FLAG_FORCE_NEXTHOP_SELF
))
1849 subgroup_announce_reset_nhop(
1850 (peer_cap_enhe(peer
, afi
, safi
)
1854 } else if (peer
->sort
== BGP_PEER_EBGP
) {
1855 /* Can also reset the nexthop if announcing to EBGP, but
1857 * no peer in the subgroup is on a shared subnet.
1858 * Note: 3rd party nexthop currently implemented for
1861 if (!bgp_subgrp_multiaccess_check_v4(piattr
->nexthop
,
1863 subgroup_announce_reset_nhop(
1864 (peer_cap_enhe(peer
, afi
, safi
)
1868 } else if (CHECK_FLAG(pi
->flags
, BGP_PATH_ANNC_NH_SELF
)) {
1870 * This flag is used for leaked vpn-vrf routes
1872 int family
= p
->family
;
1874 if (peer_cap_enhe(peer
, afi
, safi
))
1877 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1879 "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
1880 __func__
, family2str(family
));
1881 subgroup_announce_reset_nhop(family
, attr
);
1884 /* If IPv6/MP and nexthop does not have any override and happens
1886 * be a link-local address, reset it so that we don't pass along
1888 * source's link-local IPv6 address to recipients who may not be
1890 * the same interface.
1892 if (p
->family
== AF_INET6
|| peer_cap_enhe(peer
, afi
, safi
)) {
1893 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
))
1894 subgroup_announce_reset_nhop(AF_INET6
, attr
);
1901 void bgp_best_selection(struct bgp
*bgp
, struct bgp_node
*rn
,
1902 struct bgp_maxpaths_cfg
*mpath_cfg
,
1903 struct bgp_path_info_pair
*result
, afi_t afi
,
1906 struct bgp_path_info
*new_select
;
1907 struct bgp_path_info
*old_select
;
1908 struct bgp_path_info
*pi
;
1909 struct bgp_path_info
*pi1
;
1910 struct bgp_path_info
*pi2
;
1911 struct bgp_path_info
*nextpi
= NULL
;
1912 int paths_eq
, do_mpath
, debug
;
1913 struct list mp_list
;
1914 char pfx_buf
[PREFIX2STR_BUFFER
];
1915 char path_buf
[PATH_ADDPATH_STR_BUFFER
];
1917 bgp_mp_list_init(&mp_list
);
1919 (mpath_cfg
->maxpaths_ebgp
> 1 || mpath_cfg
->maxpaths_ibgp
> 1);
1921 debug
= bgp_debug_bestpath(&rn
->p
);
1924 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
1926 /* bgp deterministic-med */
1928 if (bgp_flag_check(bgp
, BGP_FLAG_DETERMINISTIC_MED
)) {
1930 /* Clear BGP_PATH_DMED_SELECTED for all paths */
1931 for (pi1
= bgp_node_get_bgp_path_info(rn
); pi1
;
1933 bgp_path_info_unset_flag(rn
, pi1
,
1934 BGP_PATH_DMED_SELECTED
);
1936 for (pi1
= bgp_node_get_bgp_path_info(rn
); pi1
;
1938 if (CHECK_FLAG(pi1
->flags
, BGP_PATH_DMED_CHECK
))
1940 if (BGP_PATH_HOLDDOWN(pi1
))
1942 if (pi1
->peer
!= bgp
->peer_self
)
1943 if (pi1
->peer
->status
!= Established
)
1948 for (pi2
= pi1
->next
; pi2
; pi2
= pi2
->next
) {
1949 if (CHECK_FLAG(pi2
->flags
,
1950 BGP_PATH_DMED_CHECK
))
1952 if (BGP_PATH_HOLDDOWN(pi2
))
1954 if (pi2
->peer
!= bgp
->peer_self
1957 PEER_STATUS_NSF_WAIT
))
1958 if (pi2
->peer
->status
1962 if (!aspath_cmp_left(pi1
->attr
->aspath
,
1964 && !aspath_cmp_left_confed(
1969 if (bgp_path_info_cmp(
1970 bgp
, pi2
, new_select
,
1971 &paths_eq
, mpath_cfg
, debug
,
1972 pfx_buf
, afi
, safi
)) {
1973 bgp_path_info_unset_flag(
1975 BGP_PATH_DMED_SELECTED
);
1979 bgp_path_info_set_flag(
1980 rn
, pi2
, BGP_PATH_DMED_CHECK
);
1983 bgp_path_info_set_flag(rn
, new_select
,
1984 BGP_PATH_DMED_CHECK
);
1985 bgp_path_info_set_flag(rn
, new_select
,
1986 BGP_PATH_DMED_SELECTED
);
1989 bgp_path_info_path_with_addpath_rx_str(
1990 new_select
, path_buf
);
1991 zlog_debug("%s: %s is the bestpath from AS %u",
1993 aspath_get_first_as(
1994 new_select
->attr
->aspath
));
1999 /* Check old selected route and new selected route. */
2002 for (pi
= bgp_node_get_bgp_path_info(rn
);
2003 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2004 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
2007 if (BGP_PATH_HOLDDOWN(pi
)) {
2008 /* reap REMOVED routes, if needs be
2009 * selected route must stay for a while longer though
2011 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
2012 && (pi
!= old_select
))
2013 bgp_path_info_reap(rn
, pi
);
2016 zlog_debug("%s: pi %p in holddown", __func__
,
2022 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2023 && !CHECK_FLAG(pi
->peer
->sflags
, PEER_STATUS_NSF_WAIT
))
2024 if (pi
->peer
->status
!= Established
) {
2028 "%s: pi %p non self peer %s not estab state",
2029 __func__
, pi
, pi
->peer
->host
);
2034 if (bgp_flag_check(bgp
, BGP_FLAG_DETERMINISTIC_MED
)
2035 && (!CHECK_FLAG(pi
->flags
, BGP_PATH_DMED_SELECTED
))) {
2036 bgp_path_info_unset_flag(rn
, pi
, BGP_PATH_DMED_CHECK
);
2038 zlog_debug("%s: pi %p dmed", __func__
, pi
);
2042 bgp_path_info_unset_flag(rn
, pi
, BGP_PATH_DMED_CHECK
);
2044 if (bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
, mpath_cfg
,
2045 debug
, pfx_buf
, afi
, safi
)) {
2050 /* Now that we know which path is the bestpath see if any of the other
2052 * qualify as multipaths
2056 bgp_path_info_path_with_addpath_rx_str(new_select
,
2059 sprintf(path_buf
, "NONE");
2061 "%s: After path selection, newbest is %s oldbest was %s",
2063 old_select
? old_select
->peer
->host
: "NONE");
2066 if (do_mpath
&& new_select
) {
2067 for (pi
= bgp_node_get_bgp_path_info(rn
);
2068 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2071 bgp_path_info_path_with_addpath_rx_str(
2074 if (pi
== new_select
) {
2077 "%s: %s is the bestpath, add to the multipath list",
2079 bgp_mp_list_add(&mp_list
, pi
);
2083 if (BGP_PATH_HOLDDOWN(pi
))
2086 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2087 && !CHECK_FLAG(pi
->peer
->sflags
,
2088 PEER_STATUS_NSF_WAIT
))
2089 if (pi
->peer
->status
!= Established
)
2092 if (!bgp_path_info_nexthop_cmp(pi
, new_select
)) {
2095 "%s: %s has the same nexthop as the bestpath, skip it",
2100 bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
,
2101 mpath_cfg
, debug
, pfx_buf
, afi
, safi
);
2106 "%s: %s is equivalent to the bestpath, add to the multipath list",
2108 bgp_mp_list_add(&mp_list
, pi
);
2113 bgp_path_info_mpath_update(rn
, new_select
, old_select
, &mp_list
,
2115 bgp_path_info_mpath_aggregate_update(new_select
, old_select
);
2116 bgp_mp_list_clear(&mp_list
);
2118 bgp_addpath_update_ids(bgp
, rn
, afi
, safi
);
2120 result
->old
= old_select
;
2121 result
->new = new_select
;
2127 * A new route/change in bestpath of an existing route. Evaluate the path
2128 * for advertisement to the subgroup.
2130 int subgroup_process_announce_selected(struct update_subgroup
*subgrp
,
2131 struct bgp_path_info
*selected
,
2132 struct bgp_node
*rn
,
2133 uint32_t addpath_tx_id
)
2136 struct peer
*onlypeer
;
2142 afi
= SUBGRP_AFI(subgrp
);
2143 safi
= SUBGRP_SAFI(subgrp
);
2144 onlypeer
= ((SUBGRP_PCOUNT(subgrp
) == 1) ? (SUBGRP_PFIRST(subgrp
))->peer
2147 if (BGP_DEBUG(update
, UPDATE_OUT
)) {
2148 char buf_prefix
[PREFIX_STRLEN
];
2149 prefix2str(p
, buf_prefix
, sizeof(buf_prefix
));
2150 zlog_debug("%s: p=%s, selected=%p", __func__
, buf_prefix
,
2154 /* First update is deferred until ORF or ROUTE-REFRESH is received */
2155 if (onlypeer
&& CHECK_FLAG(onlypeer
->af_sflags
[afi
][safi
],
2156 PEER_STATUS_ORF_WAIT_REFRESH
))
2159 memset(&attr
, 0, sizeof(struct attr
));
2160 /* It's initialized in bgp_announce_check() */
2162 /* Announcement to the subgroup. If the route is filtered withdraw it.
2165 if (subgroup_announce_check(rn
, selected
, subgrp
, p
, &attr
))
2166 bgp_adj_out_set_subgroup(rn
, subgrp
, &attr
, selected
);
2168 bgp_adj_out_unset_subgroup(rn
, subgrp
, 1,
2172 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2174 bgp_adj_out_unset_subgroup(rn
, subgrp
, 1, addpath_tx_id
);
2181 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2182 * This is called at the end of route processing.
2184 void bgp_zebra_clear_route_change_flags(struct bgp_node
*rn
)
2186 struct bgp_path_info
*pi
;
2188 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
2189 if (BGP_PATH_HOLDDOWN(pi
))
2191 UNSET_FLAG(pi
->flags
, BGP_PATH_IGP_CHANGED
);
2192 UNSET_FLAG(pi
->flags
, BGP_PATH_ATTR_CHANGED
);
2197 * Has the route changed from the RIB's perspective? This is invoked only
2198 * if the route selection returns the same best route as earlier - to
2199 * determine if we need to update zebra or not.
2201 int bgp_zebra_has_route_changed(struct bgp_node
*rn
,
2202 struct bgp_path_info
*selected
)
2204 struct bgp_path_info
*mpinfo
;
2206 /* If this is multipath, check all selected paths for any nexthop
2207 * change or attribute change. Some attribute changes (e.g., community)
2208 * aren't of relevance to the RIB, but we'll update zebra to ensure
2209 * we handle the case of BGP nexthop change. This is the behavior
2210 * when the best path has an attribute change anyway.
2212 if (CHECK_FLAG(selected
->flags
, BGP_PATH_IGP_CHANGED
)
2213 || CHECK_FLAG(selected
->flags
, BGP_PATH_MULTIPATH_CHG
))
2217 * If this is multipath, check all selected paths for any nexthop change
2219 for (mpinfo
= bgp_path_info_mpath_first(selected
); mpinfo
;
2220 mpinfo
= bgp_path_info_mpath_next(mpinfo
)) {
2221 if (CHECK_FLAG(mpinfo
->flags
, BGP_PATH_IGP_CHANGED
)
2222 || CHECK_FLAG(mpinfo
->flags
, BGP_PATH_ATTR_CHANGED
))
2226 /* Nothing has changed from the RIB's perspective. */
2230 struct bgp_process_queue
{
2232 STAILQ_HEAD(, bgp_node
) pqueue
;
2233 #define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2235 unsigned int queued
;
2239 * old_select = The old best path
2240 * new_select = the new best path
2242 * if (!old_select && new_select)
2243 * We are sending new information on.
2245 * if (old_select && new_select) {
2246 * if (new_select != old_select)
2247 * We have a new best path send a change
2249 * We've received a update with new attributes that needs
2253 * if (old_select && !new_select)
2254 * We have no eligible route that we can announce or the rn
2257 static void bgp_process_main_one(struct bgp
*bgp
, struct bgp_node
*rn
,
2258 afi_t afi
, safi_t safi
)
2260 struct bgp_path_info
*new_select
;
2261 struct bgp_path_info
*old_select
;
2262 struct bgp_path_info_pair old_and_new
;
2263 char pfx_buf
[PREFIX2STR_BUFFER
];
2266 /* Is it end of initial update? (after startup) */
2268 quagga_timestamp(3, bgp
->update_delay_zebra_resume_time
,
2269 sizeof(bgp
->update_delay_zebra_resume_time
));
2271 bgp
->main_zebra_update_hold
= 0;
2272 FOREACH_AFI_SAFI (afi
, safi
) {
2273 if (bgp_fibupd_safi(safi
))
2274 bgp_zebra_announce_table(bgp
, afi
, safi
);
2276 bgp
->main_peers_update_hold
= 0;
2278 bgp_start_routeadv(bgp
);
2282 struct prefix
*p
= &rn
->p
;
2284 debug
= bgp_debug_bestpath(&rn
->p
);
2286 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
2287 zlog_debug("%s: p=%s afi=%s, safi=%s start", __func__
, pfx_buf
,
2288 afi2str(afi
), safi2str(safi
));
2291 /* Best path selection. */
2292 bgp_best_selection(bgp
, rn
, &bgp
->maxpaths
[afi
][safi
], &old_and_new
,
2294 old_select
= old_and_new
.old
;
2295 new_select
= old_and_new
.new;
2297 /* Do we need to allocate or free labels?
2298 * Right now, since we only deal with per-prefix labels, it is not
2299 * necessary to do this upon changes to best path. Exceptions:
2300 * - label index has changed -> recalculate resulting label
2301 * - path_info sub_type changed -> switch to/from implicit-null
2302 * - no valid label (due to removed static label binding) -> get new one
2304 if (bgp
->allocate_mpls_labels
[afi
][safi
]) {
2307 || bgp_label_index_differs(new_select
, old_select
)
2308 || new_select
->sub_type
!= old_select
->sub_type
2309 || !bgp_is_valid_label(&rn
->local_label
)) {
2310 /* Enforced penultimate hop popping:
2311 * implicit-null for local routes, aggregate
2312 * and redistributed routes
2314 if (new_select
->sub_type
== BGP_ROUTE_STATIC
2315 || new_select
->sub_type
2316 == BGP_ROUTE_AGGREGATE
2317 || new_select
->sub_type
2318 == BGP_ROUTE_REDISTRIBUTE
) {
2321 BGP_NODE_REGISTERED_FOR_LABEL
))
2322 bgp_unregister_for_label(rn
);
2323 label_ntop(MPLS_LABEL_IMPLICIT_NULL
, 1,
2325 bgp_set_valid_label(&rn
->local_label
);
2327 bgp_register_for_label(rn
, new_select
);
2329 } else if (CHECK_FLAG(rn
->flags
,
2330 BGP_NODE_REGISTERED_FOR_LABEL
)) {
2331 bgp_unregister_for_label(rn
);
2333 } else if (CHECK_FLAG(rn
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
)) {
2334 bgp_unregister_for_label(rn
);
2338 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
2340 "%s: p=%s afi=%s, safi=%s, old_select=%p, new_select=%p",
2341 __func__
, pfx_buf
, afi2str(afi
), safi2str(safi
),
2342 old_select
, new_select
);
2345 /* If best route remains the same and this is not due to user-initiated
2346 * clear, see exactly what needs to be done.
2348 if (old_select
&& old_select
== new_select
2349 && !CHECK_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
)
2350 && !CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
2351 && !bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
2352 if (bgp_zebra_has_route_changed(rn
, old_select
)) {
2354 vnc_import_bgp_add_route(bgp
, p
, old_select
);
2355 vnc_import_bgp_exterior_add_route(bgp
, p
, old_select
);
2357 if (bgp_fibupd_safi(safi
)
2358 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2360 if (new_select
->type
== ZEBRA_ROUTE_BGP
2361 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2362 || new_select
->sub_type
2363 == BGP_ROUTE_IMPORTED
))
2365 bgp_zebra_announce(rn
, p
, old_select
,
2369 UNSET_FLAG(old_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
2370 bgp_zebra_clear_route_change_flags(rn
);
2372 /* If there is a change of interest to peers, reannounce the
2374 if (CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
2375 || CHECK_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
)) {
2376 group_announce_route(bgp
, afi
, safi
, rn
, new_select
);
2378 /* unicast routes must also be annouced to
2379 * labeled-unicast update-groups */
2380 if (safi
== SAFI_UNICAST
)
2381 group_announce_route(bgp
, afi
,
2382 SAFI_LABELED_UNICAST
, rn
,
2385 UNSET_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
);
2386 UNSET_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
);
2389 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2393 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2395 UNSET_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
);
2397 /* bestpath has changed; bump version */
2398 if (old_select
|| new_select
) {
2399 bgp_bump_version(rn
);
2401 if (!bgp
->t_rmap_def_originate_eval
) {
2405 update_group_refresh_default_originate_route_map
,
2406 bgp
, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER
,
2407 &bgp
->t_rmap_def_originate_eval
);
2412 bgp_path_info_unset_flag(rn
, old_select
, BGP_PATH_SELECTED
);
2415 zlog_debug("%s: setting SELECTED flag", __func__
);
2416 bgp_path_info_set_flag(rn
, new_select
, BGP_PATH_SELECTED
);
2417 bgp_path_info_unset_flag(rn
, new_select
, BGP_PATH_ATTR_CHANGED
);
2418 UNSET_FLAG(new_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
2422 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2423 if (old_select
!= new_select
) {
2425 vnc_import_bgp_exterior_del_route(bgp
, p
,
2427 vnc_import_bgp_del_route(bgp
, p
, old_select
);
2430 vnc_import_bgp_exterior_add_route(bgp
, p
,
2432 vnc_import_bgp_add_route(bgp
, p
, new_select
);
2438 group_announce_route(bgp
, afi
, safi
, rn
, new_select
);
2440 /* unicast routes must also be annouced to labeled-unicast update-groups
2442 if (safi
== SAFI_UNICAST
)
2443 group_announce_route(bgp
, afi
, SAFI_LABELED_UNICAST
, rn
,
2447 if (bgp_fibupd_safi(safi
) && (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VIEW
)
2448 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2449 if (new_select
&& new_select
->type
== ZEBRA_ROUTE_BGP
2450 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2451 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
2452 || new_select
->sub_type
== BGP_ROUTE_IMPORTED
)) {
2454 /* if this is an evpn imported type-5 prefix,
2455 * we need to withdraw the route first to clear
2456 * the nh neigh and the RMAC entry.
2459 is_route_parent_evpn(old_select
))
2460 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2462 bgp_zebra_announce(rn
, p
, new_select
, bgp
, afi
, safi
);
2464 /* Withdraw the route from the kernel. */
2465 if (old_select
&& old_select
->type
== ZEBRA_ROUTE_BGP
2466 && (old_select
->sub_type
== BGP_ROUTE_NORMAL
2467 || old_select
->sub_type
== BGP_ROUTE_AGGREGATE
2468 || old_select
->sub_type
== BGP_ROUTE_IMPORTED
))
2470 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2474 /* advertise/withdraw type-5 routes */
2475 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2476 if (advertise_type5_routes(bgp
, afi
) &&
2478 is_route_injectable_into_evpn(new_select
)) {
2480 /* apply the route-map */
2481 if (bgp
->adv_cmd_rmap
[afi
][safi
].map
) {
2484 ret
= route_map_apply(
2485 bgp
->adv_cmd_rmap
[afi
][safi
].map
,
2486 &rn
->p
, RMAP_BGP
, new_select
);
2487 if (ret
== RMAP_MATCH
)
2488 bgp_evpn_advertise_type5_route(
2489 bgp
, &rn
->p
, new_select
->attr
,
2492 bgp_evpn_withdraw_type5_route(
2493 bgp
, &rn
->p
, afi
, safi
);
2495 bgp_evpn_advertise_type5_route(bgp
,
2501 } else if (advertise_type5_routes(bgp
, afi
) &&
2503 is_route_injectable_into_evpn(old_select
))
2504 bgp_evpn_withdraw_type5_route(bgp
, &rn
->p
, afi
, safi
);
2507 /* Clear any route change flags. */
2508 bgp_zebra_clear_route_change_flags(rn
);
2510 /* Reap old select bgp_path_info, if it has been removed */
2511 if (old_select
&& CHECK_FLAG(old_select
->flags
, BGP_PATH_REMOVED
))
2512 bgp_path_info_reap(rn
, old_select
);
2514 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2518 static wq_item_status
bgp_process_wq(struct work_queue
*wq
, void *data
)
2520 struct bgp_process_queue
*pqnode
= data
;
2521 struct bgp
*bgp
= pqnode
->bgp
;
2522 struct bgp_table
*table
;
2523 struct bgp_node
*rn
;
2526 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)) {
2527 bgp_process_main_one(bgp
, NULL
, 0, 0);
2528 /* should always have dedicated wq call */
2529 assert(STAILQ_FIRST(&pqnode
->pqueue
) == NULL
);
2533 while (!STAILQ_EMPTY(&pqnode
->pqueue
)) {
2534 rn
= STAILQ_FIRST(&pqnode
->pqueue
);
2535 STAILQ_REMOVE_HEAD(&pqnode
->pqueue
, pq
);
2536 STAILQ_NEXT(rn
, pq
) = NULL
; /* complete unlink */
2537 table
= bgp_node_table(rn
);
2538 /* note, new RNs may be added as part of processing */
2539 bgp_process_main_one(bgp
, rn
, table
->afi
, table
->safi
);
2541 bgp_unlock_node(rn
);
2542 bgp_table_unlock(table
);
2548 static void bgp_processq_del(struct work_queue
*wq
, void *data
)
2550 struct bgp_process_queue
*pqnode
= data
;
2552 bgp_unlock(pqnode
->bgp
);
2554 XFREE(MTYPE_BGP_PROCESS_QUEUE
, pqnode
);
2557 void bgp_process_queue_init(void)
2559 if (!bm
->process_main_queue
)
2560 bm
->process_main_queue
=
2561 work_queue_new(bm
->master
, "process_main_queue");
2563 bm
->process_main_queue
->spec
.workfunc
= &bgp_process_wq
;
2564 bm
->process_main_queue
->spec
.del_item_data
= &bgp_processq_del
;
2565 bm
->process_main_queue
->spec
.max_retries
= 0;
2566 bm
->process_main_queue
->spec
.hold
= 50;
2567 /* Use a higher yield value of 50ms for main queue processing */
2568 bm
->process_main_queue
->spec
.yield
= 50 * 1000L;
2571 static struct bgp_process_queue
*bgp_processq_alloc(struct bgp
*bgp
)
2573 struct bgp_process_queue
*pqnode
;
2575 pqnode
= XCALLOC(MTYPE_BGP_PROCESS_QUEUE
,
2576 sizeof(struct bgp_process_queue
));
2578 /* unlocked in bgp_processq_del */
2579 pqnode
->bgp
= bgp_lock(bgp
);
2580 STAILQ_INIT(&pqnode
->pqueue
);
2585 void bgp_process(struct bgp
*bgp
, struct bgp_node
*rn
, afi_t afi
, safi_t safi
)
2587 #define ARBITRARY_PROCESS_QLEN 10000
2588 struct work_queue
*wq
= bm
->process_main_queue
;
2589 struct bgp_process_queue
*pqnode
;
2590 int pqnode_reuse
= 0;
2592 /* already scheduled for processing? */
2593 if (CHECK_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
2599 /* Add route nodes to an existing work queue item until reaching the
2600 limit only if is from the same BGP view and it's not an EOIU marker
2602 if (work_queue_item_count(wq
)) {
2603 struct work_queue_item
*item
= work_queue_last_item(wq
);
2604 pqnode
= item
->data
;
2606 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)
2607 || pqnode
->bgp
!= bgp
2608 || pqnode
->queued
>= ARBITRARY_PROCESS_QLEN
)
2609 pqnode
= bgp_processq_alloc(bgp
);
2613 pqnode
= bgp_processq_alloc(bgp
);
2614 /* all unlocked in bgp_process_wq */
2615 bgp_table_lock(bgp_node_table(rn
));
2617 SET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2620 /* can't be enqueued twice */
2621 assert(STAILQ_NEXT(rn
, pq
) == NULL
);
2622 STAILQ_INSERT_TAIL(&pqnode
->pqueue
, rn
, pq
);
2626 work_queue_add(wq
, pqnode
);
2631 void bgp_add_eoiu_mark(struct bgp
*bgp
)
2633 struct bgp_process_queue
*pqnode
;
2635 if (bm
->process_main_queue
== NULL
)
2638 pqnode
= bgp_processq_alloc(bgp
);
2640 SET_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
);
2641 work_queue_add(bm
->process_main_queue
, pqnode
);
2644 static int bgp_maximum_prefix_restart_timer(struct thread
*thread
)
2648 peer
= THREAD_ARG(thread
);
2649 peer
->t_pmax_restart
= NULL
;
2651 if (bgp_debug_neighbor_events(peer
))
2653 "%s Maximum-prefix restart timer expired, restore peering",
2656 if ((peer_clear(peer
, NULL
) < 0) && bgp_debug_neighbor_events(peer
))
2657 zlog_debug("%s: %s peer_clear failed",
2658 __PRETTY_FUNCTION__
, peer
->host
);
2663 int bgp_maximum_prefix_overflow(struct peer
*peer
, afi_t afi
, safi_t safi
,
2667 iana_safi_t pkt_safi
;
2669 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX
))
2672 if (peer
->pcount
[afi
][safi
] > peer
->pmax
[afi
][safi
]) {
2673 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2674 PEER_STATUS_PREFIX_LIMIT
)
2679 "%%MAXPFXEXCEED: No. of %s prefix received from %s %" PRIu32
2680 " exceed, limit %" PRIu32
,
2681 afi_safi_print(afi
, safi
), peer
->host
,
2682 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2683 SET_FLAG(peer
->af_sflags
[afi
][safi
], PEER_STATUS_PREFIX_LIMIT
);
2685 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2686 PEER_FLAG_MAX_PREFIX_WARNING
))
2689 /* Convert AFI, SAFI to values for packet. */
2690 pkt_afi
= afi_int2iana(afi
);
2691 pkt_safi
= safi_int2iana(safi
);
2695 ndata
[0] = (pkt_afi
>> 8);
2697 ndata
[2] = pkt_safi
;
2698 ndata
[3] = (peer
->pmax
[afi
][safi
] >> 24);
2699 ndata
[4] = (peer
->pmax
[afi
][safi
] >> 16);
2700 ndata
[5] = (peer
->pmax
[afi
][safi
] >> 8);
2701 ndata
[6] = (peer
->pmax
[afi
][safi
]);
2703 SET_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
);
2704 bgp_notify_send_with_data(peer
, BGP_NOTIFY_CEASE
,
2705 BGP_NOTIFY_CEASE_MAX_PREFIX
,
2709 /* Dynamic peers will just close their connection. */
2710 if (peer_dynamic_neighbor(peer
))
2713 /* restart timer start */
2714 if (peer
->pmax_restart
[afi
][safi
]) {
2715 peer
->v_pmax_restart
=
2716 peer
->pmax_restart
[afi
][safi
] * 60;
2718 if (bgp_debug_neighbor_events(peer
))
2720 "%s Maximum-prefix restart timer started for %d secs",
2721 peer
->host
, peer
->v_pmax_restart
);
2723 BGP_TIMER_ON(peer
->t_pmax_restart
,
2724 bgp_maximum_prefix_restart_timer
,
2725 peer
->v_pmax_restart
);
2730 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
2731 PEER_STATUS_PREFIX_LIMIT
);
2733 if (peer
->pcount
[afi
][safi
]
2734 > (peer
->pmax
[afi
][safi
] * peer
->pmax_threshold
[afi
][safi
] / 100)) {
2735 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2736 PEER_STATUS_PREFIX_THRESHOLD
)
2741 "%%MAXPFX: No. of %s prefix received from %s reaches %" PRIu32
2743 afi_safi_print(afi
, safi
), peer
->host
,
2744 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2745 SET_FLAG(peer
->af_sflags
[afi
][safi
],
2746 PEER_STATUS_PREFIX_THRESHOLD
);
2748 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
2749 PEER_STATUS_PREFIX_THRESHOLD
);
2753 /* Unconditionally remove the route from the RIB, without taking
2754 * damping into consideration (eg, because the session went down)
2756 void bgp_rib_remove(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
2757 struct peer
*peer
, afi_t afi
, safi_t safi
)
2759 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, pi
, afi
, safi
);
2761 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
2762 bgp_path_info_delete(rn
, pi
); /* keep historical info */
2764 bgp_process(peer
->bgp
, rn
, afi
, safi
);
2767 static void bgp_rib_withdraw(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
2768 struct peer
*peer
, afi_t afi
, safi_t safi
,
2769 struct prefix_rd
*prd
)
2771 /* apply dampening, if result is suppressed, we'll be retaining
2772 * the bgp_path_info in the RIB for historical reference.
2774 if (CHECK_FLAG(peer
->bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
2775 && peer
->sort
== BGP_PEER_EBGP
)
2776 if ((bgp_damp_withdraw(pi
, rn
, afi
, safi
, 0))
2777 == BGP_DAMP_SUPPRESSED
) {
2778 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, pi
, afi
,
2784 if (safi
== SAFI_MPLS_VPN
) {
2785 struct bgp_node
*prn
= NULL
;
2786 struct bgp_table
*table
= NULL
;
2788 prn
= bgp_node_get(peer
->bgp
->rib
[afi
][safi
],
2789 (struct prefix
*)prd
);
2790 if (bgp_node_has_bgp_path_info_data(prn
)) {
2791 table
= bgp_node_get_bgp_table_info(prn
);
2793 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
2794 peer
->bgp
, prd
, table
, &rn
->p
, pi
);
2796 bgp_unlock_node(prn
);
2798 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2799 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
2801 vnc_import_bgp_del_route(peer
->bgp
, &rn
->p
, pi
);
2802 vnc_import_bgp_exterior_del_route(peer
->bgp
, &rn
->p
,
2808 /* If this is an EVPN route, process for un-import. */
2809 if (safi
== SAFI_EVPN
)
2810 bgp_evpn_unimport_route(peer
->bgp
, afi
, safi
, &rn
->p
, pi
);
2812 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
2815 struct bgp_path_info
*info_make(int type
, int sub_type
, unsigned short instance
,
2816 struct peer
*peer
, struct attr
*attr
,
2817 struct bgp_node
*rn
)
2819 struct bgp_path_info
*new;
2821 /* Make new BGP info. */
2822 new = XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_path_info
));
2824 new->instance
= instance
;
2825 new->sub_type
= sub_type
;
2828 new->uptime
= bgp_clock();
2833 static void overlay_index_update(struct attr
*attr
,
2834 struct eth_segment_id
*eth_s_id
,
2835 union gw_addr
*gw_ip
)
2840 if (eth_s_id
== NULL
) {
2841 memset(&(attr
->evpn_overlay
.eth_s_id
), 0,
2842 sizeof(struct eth_segment_id
));
2844 memcpy(&(attr
->evpn_overlay
.eth_s_id
), eth_s_id
,
2845 sizeof(struct eth_segment_id
));
2847 if (gw_ip
== NULL
) {
2848 memset(&(attr
->evpn_overlay
.gw_ip
), 0, sizeof(union gw_addr
));
2850 memcpy(&(attr
->evpn_overlay
.gw_ip
), gw_ip
,
2851 sizeof(union gw_addr
));
2855 static bool overlay_index_equal(afi_t afi
, struct bgp_path_info
*path
,
2856 struct eth_segment_id
*eth_s_id
,
2857 union gw_addr
*gw_ip
)
2859 struct eth_segment_id
*path_eth_s_id
, *path_eth_s_id_remote
;
2860 union gw_addr
*path_gw_ip
, *path_gw_ip_remote
;
2862 struct eth_segment_id esi
;
2866 if (afi
!= AFI_L2VPN
)
2869 memset(&temp
, 0, sizeof(temp
));
2870 path_eth_s_id
= &temp
.esi
;
2871 path_gw_ip
= &temp
.ip
;
2873 if (eth_s_id
== NULL
&& gw_ip
== NULL
)
2876 path_eth_s_id
= &(path
->attr
->evpn_overlay
.eth_s_id
);
2877 path_gw_ip
= &(path
->attr
->evpn_overlay
.gw_ip
);
2880 if (gw_ip
== NULL
) {
2881 memset(&temp
, 0, sizeof(temp
));
2882 path_gw_ip_remote
= &temp
.ip
;
2884 path_gw_ip_remote
= gw_ip
;
2886 if (eth_s_id
== NULL
) {
2887 memset(&temp
, 0, sizeof(temp
));
2888 path_eth_s_id_remote
= &temp
.esi
;
2890 path_eth_s_id_remote
= eth_s_id
;
2892 if (!memcmp(path_gw_ip
, path_gw_ip_remote
, sizeof(union gw_addr
)))
2895 return !memcmp(path_eth_s_id
, path_eth_s_id_remote
,
2896 sizeof(struct eth_segment_id
));
2899 /* Check if received nexthop is valid or not. */
2900 static int bgp_update_martian_nexthop(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
2905 /* Only validated for unicast and multicast currently. */
2906 /* Also valid for EVPN where the nexthop is an IP address. */
2907 if (safi
!= SAFI_UNICAST
&& safi
!= SAFI_MULTICAST
&& safi
!= SAFI_EVPN
)
2910 /* If NEXT_HOP is present, validate it. */
2911 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
2912 if (attr
->nexthop
.s_addr
== 0
2913 || IPV4_CLASS_DE(ntohl(attr
->nexthop
.s_addr
))
2914 || bgp_nexthop_self(bgp
, attr
->nexthop
))
2918 /* If MP_NEXTHOP is present, validate it. */
2919 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
2920 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
2921 * it is not an IPv6 link-local address.
2923 if (attr
->mp_nexthop_len
) {
2924 switch (attr
->mp_nexthop_len
) {
2925 case BGP_ATTR_NHLEN_IPV4
:
2926 case BGP_ATTR_NHLEN_VPNV4
:
2927 ret
= (attr
->mp_nexthop_global_in
.s_addr
== 0
2928 || IPV4_CLASS_DE(ntohl(
2929 attr
->mp_nexthop_global_in
.s_addr
))
2930 || bgp_nexthop_self(bgp
,
2931 attr
->mp_nexthop_global_in
));
2934 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
2935 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
2936 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
2937 ret
= (IN6_IS_ADDR_UNSPECIFIED(&attr
->mp_nexthop_global
)
2938 || IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
2939 || IN6_IS_ADDR_MULTICAST(
2940 &attr
->mp_nexthop_global
));
2952 int bgp_update(struct peer
*peer
, struct prefix
*p
, uint32_t addpath_id
,
2953 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
2954 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
2955 uint32_t num_labels
, int soft_reconfig
,
2956 struct bgp_route_evpn
*evpn
)
2959 int aspath_loop_count
= 0;
2960 struct bgp_node
*rn
;
2962 struct attr new_attr
;
2963 struct attr
*attr_new
;
2964 struct bgp_path_info
*pi
;
2965 struct bgp_path_info
*new;
2966 struct bgp_path_info_extra
*extra
;
2968 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
2970 int do_loop_check
= 1;
2971 int has_valid_label
= 0;
2973 int vnc_implicit_withdraw
= 0;
2977 memset(&new_attr
, 0, sizeof(struct attr
));
2978 new_attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
2979 new_attr
.label
= MPLS_INVALID_LABEL
;
2982 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
2983 /* TODO: Check to see if we can get rid of "is_valid_label" */
2984 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
2985 has_valid_label
= (num_labels
> 0) ? 1 : 0;
2987 has_valid_label
= bgp_is_valid_label(label
);
2989 /* When peer's soft reconfiguration enabled. Record input packet in
2992 && CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
2993 && peer
!= bgp
->peer_self
)
2994 bgp_adj_in_set(rn
, peer
, attr
, addpath_id
);
2996 /* Check previously received route. */
2997 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
2998 if (pi
->peer
== peer
&& pi
->type
== type
2999 && pi
->sub_type
== sub_type
3000 && pi
->addpath_rx_id
== addpath_id
)
3003 /* AS path local-as loop check. */
3004 if (peer
->change_local_as
) {
3005 if (peer
->allowas_in
[afi
][safi
])
3006 aspath_loop_count
= peer
->allowas_in
[afi
][safi
];
3007 else if (!CHECK_FLAG(peer
->flags
,
3008 PEER_FLAG_LOCAL_AS_NO_PREPEND
))
3009 aspath_loop_count
= 1;
3011 if (aspath_loop_check(attr
->aspath
, peer
->change_local_as
)
3012 > aspath_loop_count
) {
3013 reason
= "as-path contains our own AS;";
3018 /* If the peer is configured for "allowas-in origin" and the last ASN in
3020 * as-path is our ASN then we do not need to call aspath_loop_check
3022 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN_ORIGIN
))
3023 if (aspath_get_last_as(attr
->aspath
) == bgp
->as
)
3026 /* AS path loop check. */
3027 if (do_loop_check
) {
3028 if (aspath_loop_check(attr
->aspath
, bgp
->as
)
3029 > peer
->allowas_in
[afi
][safi
]
3030 || (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)
3031 && aspath_loop_check(attr
->aspath
, bgp
->confed_id
)
3032 > peer
->allowas_in
[afi
][safi
])) {
3033 reason
= "as-path contains our own AS;";
3038 /* Route reflector originator ID check. */
3039 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
3040 && IPV4_ADDR_SAME(&bgp
->router_id
, &attr
->originator_id
)) {
3041 reason
= "originator is us;";
3045 /* Route reflector cluster ID check. */
3046 if (bgp_cluster_filter(peer
, attr
)) {
3047 reason
= "reflected from the same cluster;";
3051 /* Apply incoming filter. */
3052 if (bgp_input_filter(peer
, p
, attr
, afi
, safi
) == FILTER_DENY
) {
3057 bgp_attr_dup(&new_attr
, attr
);
3059 /* Apply incoming route-map.
3060 * NB: new_attr may now contain newly allocated values from route-map
3062 * commands, so we need bgp_attr_flush in the error paths, until we
3064 * the attr (which takes over the memory references) */
3065 if (bgp_input_modifier(peer
, p
, &new_attr
, afi
, safi
, NULL
)
3067 reason
= "route-map;";
3068 bgp_attr_flush(&new_attr
);
3072 if (peer
->sort
== BGP_PEER_EBGP
) {
3074 /* If we receive the graceful-shutdown community from an eBGP
3075 * peer we must lower local-preference */
3076 if (new_attr
.community
3077 && community_include(new_attr
.community
, COMMUNITY_GSHUT
)) {
3078 new_attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
3079 new_attr
.local_pref
= BGP_GSHUT_LOCAL_PREF
;
3081 /* If graceful-shutdown is configured then add the GSHUT
3082 * community to all paths received from eBGP peers */
3083 } else if (bgp_flag_check(peer
->bgp
,
3084 BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
3085 bgp_attr_add_gshut_community(&new_attr
);
3089 /* next hop check. */
3090 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
)
3091 && bgp_update_martian_nexthop(bgp
, afi
, safi
, &new_attr
)) {
3092 reason
= "martian or self next-hop;";
3093 bgp_attr_flush(&new_attr
);
3097 if (bgp_mac_entry_exists(p
) || bgp_mac_exist(&attr
->rmac
)) {
3098 reason
= "self mac;";
3102 attr_new
= bgp_attr_intern(&new_attr
);
3104 /* If the update is implicit withdraw. */
3106 pi
->uptime
= bgp_clock();
3107 same_attr
= attrhash_cmp(pi
->attr
, attr_new
);
3109 /* Same attribute comes in. */
3110 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
3111 && attrhash_cmp(pi
->attr
, attr_new
)
3112 && (!has_valid_label
3113 || memcmp(&(bgp_path_info_extra_get(pi
))->label
, label
,
3114 num_labels
* sizeof(mpls_label_t
))
3116 && (overlay_index_equal(
3117 afi
, pi
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3118 evpn
== NULL
? NULL
: &evpn
->gw_ip
))) {
3119 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
3120 BGP_CONFIG_DAMPENING
)
3121 && peer
->sort
== BGP_PEER_EBGP
3122 && CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3123 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3124 bgp_debug_rdpfxpath2str(
3125 afi
, safi
, prd
, p
, label
,
3126 num_labels
, addpath_id
? 1 : 0,
3127 addpath_id
, pfx_buf
,
3129 zlog_debug("%s rcvd %s", peer
->host
,
3133 if (bgp_damp_update(pi
, rn
, afi
, safi
)
3134 != BGP_DAMP_SUPPRESSED
) {
3135 bgp_aggregate_increment(bgp
, p
, pi
, afi
,
3137 bgp_process(bgp
, rn
, afi
, safi
);
3139 } else /* Duplicate - odd */
3141 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3142 if (!peer
->rcvd_attr_printed
) {
3144 "%s rcvd UPDATE w/ attr: %s",
3146 peer
->rcvd_attr_str
);
3147 peer
->rcvd_attr_printed
= 1;
3150 bgp_debug_rdpfxpath2str(
3151 afi
, safi
, prd
, p
, label
,
3152 num_labels
, addpath_id
? 1 : 0,
3153 addpath_id
, pfx_buf
,
3156 "%s rcvd %s...duplicate ignored",
3157 peer
->host
, pfx_buf
);
3160 /* graceful restart STALE flag unset. */
3161 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
3162 bgp_path_info_unset_flag(
3163 rn
, pi
, BGP_PATH_STALE
);
3164 bgp_process(bgp
, rn
, afi
, safi
);
3168 bgp_unlock_node(rn
);
3169 bgp_attr_unintern(&attr_new
);
3174 /* Withdraw/Announce before we fully processed the withdraw */
3175 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
3176 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3177 bgp_debug_rdpfxpath2str(
3178 afi
, safi
, prd
, p
, label
, num_labels
,
3179 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3182 "%s rcvd %s, flapped quicker than processing",
3183 peer
->host
, pfx_buf
);
3186 bgp_path_info_restore(rn
, pi
);
3189 /* Received Logging. */
3190 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3191 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
3192 num_labels
, addpath_id
? 1 : 0,
3193 addpath_id
, pfx_buf
,
3195 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3198 /* graceful restart STALE flag unset. */
3199 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
3200 bgp_path_info_unset_flag(rn
, pi
, BGP_PATH_STALE
);
3202 /* The attribute is changed. */
3203 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_ATTR_CHANGED
);
3205 /* implicit withdraw, decrement aggregate and pcount here.
3206 * only if update is accepted, they'll increment below.
3208 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
3210 /* Update bgp route dampening information. */
3211 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3212 && peer
->sort
== BGP_PEER_EBGP
) {
3213 /* This is implicit withdraw so we should update
3216 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
3217 bgp_damp_withdraw(pi
, rn
, afi
, safi
, 1);
3220 if (safi
== SAFI_MPLS_VPN
) {
3221 struct bgp_node
*prn
= NULL
;
3222 struct bgp_table
*table
= NULL
;
3224 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3225 (struct prefix
*)prd
);
3226 if (bgp_node_has_bgp_path_info_data(prn
)) {
3227 table
= bgp_node_get_bgp_table_info(prn
);
3229 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3230 bgp
, prd
, table
, p
, pi
);
3232 bgp_unlock_node(prn
);
3234 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3235 && (safi
== SAFI_UNICAST
)) {
3236 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
3238 * Implicit withdraw case.
3240 ++vnc_implicit_withdraw
;
3241 vnc_import_bgp_del_route(bgp
, p
, pi
);
3242 vnc_import_bgp_exterior_del_route(bgp
, p
, pi
);
3247 /* Special handling for EVPN update of an existing route. If the
3248 * extended community attribute has changed, we need to
3250 * the route using its existing extended community. It will be
3251 * subsequently processed for import with the new extended
3254 if (safi
== SAFI_EVPN
&& !same_attr
) {
3256 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))
3258 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
3261 cmp
= ecommunity_cmp(pi
->attr
->ecommunity
,
3262 attr_new
->ecommunity
);
3264 if (bgp_debug_update(peer
, p
, NULL
, 1))
3266 "Change in EXT-COMM, existing %s new %s",
3268 pi
->attr
->ecommunity
),
3270 attr_new
->ecommunity
));
3271 bgp_evpn_unimport_route(bgp
, afi
, safi
,
3277 /* Update to new attribute. */
3278 bgp_attr_unintern(&pi
->attr
);
3279 pi
->attr
= attr_new
;
3281 /* Update MPLS label */
3282 if (has_valid_label
) {
3283 extra
= bgp_path_info_extra_get(pi
);
3284 if (extra
->label
!= label
) {
3285 memcpy(&extra
->label
, label
,
3286 num_labels
* sizeof(mpls_label_t
));
3287 extra
->num_labels
= num_labels
;
3289 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3290 bgp_set_valid_label(&extra
->label
[0]);
3294 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3295 && (safi
== SAFI_UNICAST
)) {
3296 if (vnc_implicit_withdraw
) {
3298 * Add back the route with its new attributes
3300 * The route is still selected, until the route
3302 * queued by bgp_process actually runs. We have
3304 * update to the VNC side immediately to avoid
3306 * configuration changes (e.g., route-map
3308 * trigger re-importation of the entire RIB.
3310 vnc_import_bgp_add_route(bgp
, p
, pi
);
3311 vnc_import_bgp_exterior_add_route(bgp
, p
, pi
);
3315 /* Update Overlay Index */
3316 if (afi
== AFI_L2VPN
) {
3317 overlay_index_update(
3318 pi
->attr
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3319 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3322 /* Update bgp route dampening information. */
3323 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3324 && peer
->sort
== BGP_PEER_EBGP
) {
3325 /* Now we do normal update dampening. */
3326 ret
= bgp_damp_update(pi
, rn
, afi
, safi
);
3327 if (ret
== BGP_DAMP_SUPPRESSED
) {
3328 bgp_unlock_node(rn
);
3333 /* Nexthop reachability check - for unicast and
3334 * labeled-unicast.. */
3335 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3336 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
3337 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
3338 && !CHECK_FLAG(peer
->flags
,
3339 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3341 bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3346 struct bgp
*bgp_nexthop
= bgp
;
3348 if (pi
->extra
&& pi
->extra
->bgp_orig
)
3349 bgp_nexthop
= pi
->extra
->bgp_orig
;
3351 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
, afi
, pi
,
3353 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3354 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_VALID
);
3356 if (BGP_DEBUG(nht
, NHT
)) {
3357 char buf1
[INET6_ADDRSTRLEN
];
3359 (const void *)&attr_new
3361 buf1
, INET6_ADDRSTRLEN
);
3362 zlog_debug("%s(%s): NH unresolved",
3363 __FUNCTION__
, buf1
);
3365 bgp_path_info_unset_flag(rn
, pi
,
3369 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_VALID
);
3372 if (safi
== SAFI_MPLS_VPN
) {
3373 struct bgp_node
*prn
= NULL
;
3374 struct bgp_table
*table
= NULL
;
3376 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3377 (struct prefix
*)prd
);
3378 if (bgp_node_has_bgp_path_info_data(prn
)) {
3379 table
= bgp_node_get_bgp_table_info(prn
);
3381 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3382 bgp
, prd
, table
, p
, pi
);
3384 bgp_unlock_node(prn
);
3388 /* If this is an EVPN route and some attribute has changed,
3390 * route for import. If the extended community has changed, we
3392 * have done the un-import earlier and the import would result
3394 * route getting injected into appropriate L2 VNIs. If it is
3396 * some other attribute change, the import will result in
3398 * the attributes for the route in the VNI(s).
3400 if (safi
== SAFI_EVPN
&& !same_attr
)
3401 bgp_evpn_import_route(bgp
, afi
, safi
, p
, pi
);
3403 /* Process change. */
3404 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
3406 bgp_process(bgp
, rn
, afi
, safi
);
3407 bgp_unlock_node(rn
);
3409 if (SAFI_UNICAST
== safi
3410 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3411 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3413 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, pi
);
3415 if ((SAFI_MPLS_VPN
== safi
)
3416 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3418 vpn_leak_to_vrf_update(bgp
, pi
);
3422 if (SAFI_MPLS_VPN
== safi
) {
3423 mpls_label_t label_decoded
= decode_label(label
);
3425 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3426 type
, sub_type
, &label_decoded
);
3428 if (SAFI_ENCAP
== safi
) {
3429 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3430 type
, sub_type
, NULL
);
3435 } // End of implicit withdraw
3437 /* Received Logging. */
3438 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3439 if (!peer
->rcvd_attr_printed
) {
3440 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3441 peer
->rcvd_attr_str
);
3442 peer
->rcvd_attr_printed
= 1;
3445 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3446 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3448 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3451 /* Make new BGP info. */
3452 new = info_make(type
, sub_type
, 0, peer
, attr_new
, rn
);
3454 /* Update MPLS label */
3455 if (has_valid_label
) {
3456 extra
= bgp_path_info_extra_get(new);
3457 if (extra
->label
!= label
) {
3458 memcpy(&extra
->label
, label
,
3459 num_labels
* sizeof(mpls_label_t
));
3460 extra
->num_labels
= num_labels
;
3462 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3463 bgp_set_valid_label(&extra
->label
[0]);
3466 /* Update Overlay Index */
3467 if (afi
== AFI_L2VPN
) {
3468 overlay_index_update(new->attr
,
3469 evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3470 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3472 /* Nexthop reachability check. */
3473 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3474 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
3475 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
3476 && !CHECK_FLAG(peer
->flags
,
3477 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3478 && !bgp_flag_check(bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3483 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, new, NULL
, connected
)
3484 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3485 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
3487 if (BGP_DEBUG(nht
, NHT
)) {
3488 char buf1
[INET6_ADDRSTRLEN
];
3490 (const void *)&attr_new
->nexthop
,
3491 buf1
, INET6_ADDRSTRLEN
);
3492 zlog_debug("%s(%s): NH unresolved",
3493 __FUNCTION__
, buf1
);
3495 bgp_path_info_unset_flag(rn
, new, BGP_PATH_VALID
);
3498 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
3501 new->addpath_rx_id
= addpath_id
;
3503 /* Increment prefix */
3504 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
3506 /* Register new BGP information. */
3507 bgp_path_info_add(rn
, new);
3509 /* route_node_get lock */
3510 bgp_unlock_node(rn
);
3513 if (safi
== SAFI_MPLS_VPN
) {
3514 struct bgp_node
*prn
= NULL
;
3515 struct bgp_table
*table
= NULL
;
3517 prn
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
3518 if (bgp_node_has_bgp_path_info_data(prn
)) {
3519 table
= bgp_node_get_bgp_table_info(prn
);
3521 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3522 bgp
, prd
, table
, p
, new);
3524 bgp_unlock_node(prn
);
3528 /* If maximum prefix count is configured and current prefix
3530 if (bgp_maximum_prefix_overflow(peer
, afi
, safi
, 0))
3533 /* If this is an EVPN route, process for import. */
3534 if (safi
== SAFI_EVPN
)
3535 bgp_evpn_import_route(bgp
, afi
, safi
, p
, new);
3537 /* Process change. */
3538 bgp_process(bgp
, rn
, afi
, safi
);
3540 if (SAFI_UNICAST
== safi
3541 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3542 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3543 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
3545 if ((SAFI_MPLS_VPN
== safi
)
3546 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3548 vpn_leak_to_vrf_update(bgp
, new);
3551 if (SAFI_MPLS_VPN
== safi
) {
3552 mpls_label_t label_decoded
= decode_label(label
);
3554 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3555 sub_type
, &label_decoded
);
3557 if (SAFI_ENCAP
== safi
) {
3558 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3565 /* This BGP update is filtered. Log the reason then update BGP
3568 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3569 if (!peer
->rcvd_attr_printed
) {
3570 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3571 peer
->rcvd_attr_str
);
3572 peer
->rcvd_attr_printed
= 1;
3575 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3576 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3578 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
3579 peer
->host
, pfx_buf
, reason
);
3583 /* If this is an EVPN route, un-import it as it is now filtered.
3585 if (safi
== SAFI_EVPN
)
3586 bgp_evpn_unimport_route(bgp
, afi
, safi
, p
, pi
);
3588 if (SAFI_UNICAST
== safi
3589 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3590 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3592 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
3594 if ((SAFI_MPLS_VPN
== safi
)
3595 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3597 vpn_leak_to_vrf_withdraw(bgp
, pi
);
3600 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
3603 bgp_unlock_node(rn
);
3607 * Filtered update is treated as an implicit withdrawal (see
3609 * a few lines above)
3611 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3612 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3620 int bgp_withdraw(struct peer
*peer
, struct prefix
*p
, uint32_t addpath_id
,
3621 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
3622 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
3623 uint32_t num_labels
, struct bgp_route_evpn
*evpn
)
3626 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
3627 struct bgp_node
*rn
;
3628 struct bgp_path_info
*pi
;
3631 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3632 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3640 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
3642 /* If peer is soft reconfiguration enabled. Record input packet for
3643 * further calculation.
3645 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
3646 * routes that are filtered. This tanks out Quagga RS pretty badly due
3648 * the iteration over all RS clients.
3649 * Since we need to remove the entry from adj_in anyway, do that first
3651 * if there was no entry, we don't need to do anything more.
3653 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
3654 && peer
!= bgp
->peer_self
)
3655 if (!bgp_adj_in_unset(rn
, peer
, addpath_id
)) {
3656 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3657 bgp_debug_rdpfxpath2str(
3658 afi
, safi
, prd
, p
, label
, num_labels
,
3659 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3662 "%s withdrawing route %s not in adj-in",
3663 peer
->host
, pfx_buf
);
3665 bgp_unlock_node(rn
);
3669 /* Lookup withdrawn route. */
3670 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
3671 if (pi
->peer
== peer
&& pi
->type
== type
3672 && pi
->sub_type
== sub_type
3673 && pi
->addpath_rx_id
== addpath_id
)
3677 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3678 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3679 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3681 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer
->host
,
3685 /* Withdraw specified route from routing table. */
3686 if (pi
&& !CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3687 bgp_rib_withdraw(rn
, pi
, peer
, afi
, safi
, prd
);
3688 if (SAFI_UNICAST
== safi
3689 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3690 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3691 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
3693 if ((SAFI_MPLS_VPN
== safi
)
3694 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3696 vpn_leak_to_vrf_withdraw(bgp
, pi
);
3698 } else if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3699 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3700 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3702 zlog_debug("%s Can't find the route %s", peer
->host
, pfx_buf
);
3705 /* Unlock bgp_node_get() lock. */
3706 bgp_unlock_node(rn
);
3711 void bgp_default_originate(struct peer
*peer
, afi_t afi
, safi_t safi
,
3714 struct update_subgroup
*subgrp
;
3715 subgrp
= peer_subgroup(peer
, afi
, safi
);
3716 subgroup_default_originate(subgrp
, withdraw
);
3721 * bgp_stop_announce_route_timer
3723 void bgp_stop_announce_route_timer(struct peer_af
*paf
)
3725 if (!paf
->t_announce_route
)
3728 THREAD_TIMER_OFF(paf
->t_announce_route
);
3732 * bgp_announce_route_timer_expired
3734 * Callback that is invoked when the route announcement timer for a
3737 static int bgp_announce_route_timer_expired(struct thread
*t
)
3739 struct peer_af
*paf
;
3742 paf
= THREAD_ARG(t
);
3745 if (peer
->status
!= Established
)
3748 if (!peer
->afc_nego
[paf
->afi
][paf
->safi
])
3751 peer_af_announce_route(paf
, 1);
3756 * bgp_announce_route
3758 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
3760 void bgp_announce_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
3762 struct peer_af
*paf
;
3763 struct update_subgroup
*subgrp
;
3765 paf
= peer_af_find(peer
, afi
, safi
);
3768 subgrp
= PAF_SUBGRP(paf
);
3771 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
3772 * or a refresh has already been triggered.
3774 if (!subgrp
|| paf
->t_announce_route
)
3778 * Start a timer to stagger/delay the announce. This serves
3779 * two purposes - announcement can potentially be combined for
3780 * multiple peers and the announcement doesn't happen in the
3783 thread_add_timer_msec(bm
->master
, bgp_announce_route_timer_expired
, paf
,
3784 (subgrp
->peer_count
== 1)
3785 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
3786 : BGP_ANNOUNCE_ROUTE_DELAY_MS
,
3787 &paf
->t_announce_route
);
3791 * Announce routes from all AF tables to a peer.
3793 * This should ONLY be called when there is a need to refresh the
3794 * routes to the peer based on a policy change for this peer alone
3795 * or a route refresh request received from the peer.
3796 * The operation will result in splitting the peer from its existing
3797 * subgroups and putting it in new subgroups.
3799 void bgp_announce_route_all(struct peer
*peer
)
3804 FOREACH_AFI_SAFI (afi
, safi
)
3805 bgp_announce_route(peer
, afi
, safi
);
3808 static void bgp_soft_reconfig_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
3809 struct bgp_table
*table
,
3810 struct prefix_rd
*prd
)
3813 struct bgp_node
*rn
;
3814 struct bgp_adj_in
*ain
;
3817 table
= peer
->bgp
->rib
[afi
][safi
];
3819 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
3820 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
3821 if (ain
->peer
!= peer
)
3824 struct bgp_path_info
*pi
=
3825 bgp_node_get_bgp_path_info(rn
);
3826 uint32_t num_labels
= 0;
3827 mpls_label_t
*label_pnt
= NULL
;
3828 struct bgp_route_evpn evpn
;
3830 if (pi
&& pi
->extra
)
3831 num_labels
= pi
->extra
->num_labels
;
3833 label_pnt
= &pi
->extra
->label
[0];
3835 memcpy(&evpn
, &pi
->attr
->evpn_overlay
,
3838 memset(&evpn
, 0, sizeof(evpn
));
3840 ret
= bgp_update(peer
, &rn
->p
, ain
->addpath_rx_id
,
3841 ain
->attr
, afi
, safi
, ZEBRA_ROUTE_BGP
,
3842 BGP_ROUTE_NORMAL
, prd
, label_pnt
,
3843 num_labels
, 1, &evpn
);
3846 bgp_unlock_node(rn
);
3852 void bgp_soft_reconfig_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
3854 struct bgp_node
*rn
;
3855 struct bgp_table
*table
;
3857 if (peer
->status
!= Established
)
3860 if ((safi
!= SAFI_MPLS_VPN
) && (safi
!= SAFI_ENCAP
)
3861 && (safi
!= SAFI_EVPN
))
3862 bgp_soft_reconfig_table(peer
, afi
, safi
, NULL
, NULL
);
3864 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
3865 rn
= bgp_route_next(rn
)) {
3866 table
= bgp_node_get_bgp_table_info(rn
);
3867 if (table
!= NULL
) {
3868 struct prefix_rd prd
;
3870 prd
.family
= AF_UNSPEC
;
3872 memcpy(&prd
.val
, rn
->p
.u
.val
, 8);
3874 bgp_soft_reconfig_table(peer
, afi
, safi
, table
,
3881 struct bgp_clear_node_queue
{
3882 struct bgp_node
*rn
;
3885 static wq_item_status
bgp_clear_route_node(struct work_queue
*wq
, void *data
)
3887 struct bgp_clear_node_queue
*cnq
= data
;
3888 struct bgp_node
*rn
= cnq
->rn
;
3889 struct peer
*peer
= wq
->spec
.data
;
3890 struct bgp_path_info
*pi
;
3892 afi_t afi
= bgp_node_table(rn
)->afi
;
3893 safi_t safi
= bgp_node_table(rn
)->safi
;
3898 /* It is possible that we have multiple paths for a prefix from a peer
3899 * if that peer is using AddPath.
3901 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
3902 if (pi
->peer
!= peer
)
3905 /* graceful restart STALE flag set. */
3906 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_NSF_WAIT
)
3907 && peer
->nsf
[afi
][safi
]
3908 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
3909 && !CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
3910 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_STALE
);
3912 /* If this is an EVPN route, process for
3914 if (safi
== SAFI_EVPN
)
3915 bgp_evpn_unimport_route(bgp
, afi
, safi
, &rn
->p
,
3917 /* Handle withdraw for VRF route-leaking and L3VPN */
3918 if (SAFI_UNICAST
== safi
3919 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
||
3920 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3921 vpn_leak_from_vrf_withdraw(bgp_get_default(),
3924 if (SAFI_MPLS_VPN
== safi
&&
3925 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
3926 vpn_leak_to_vrf_withdraw(bgp
, pi
);
3929 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
3935 static void bgp_clear_node_queue_del(struct work_queue
*wq
, void *data
)
3937 struct bgp_clear_node_queue
*cnq
= data
;
3938 struct bgp_node
*rn
= cnq
->rn
;
3939 struct bgp_table
*table
= bgp_node_table(rn
);
3941 bgp_unlock_node(rn
);
3942 bgp_table_unlock(table
);
3943 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE
, cnq
);
3946 static void bgp_clear_node_complete(struct work_queue
*wq
)
3948 struct peer
*peer
= wq
->spec
.data
;
3950 /* Tickle FSM to start moving again */
3951 BGP_EVENT_ADD(peer
, Clearing_Completed
);
3953 peer_unlock(peer
); /* bgp_clear_route */
3956 static void bgp_clear_node_queue_init(struct peer
*peer
)
3958 char wname
[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
3960 snprintf(wname
, sizeof(wname
), "clear %s", peer
->host
);
3961 #undef CLEAR_QUEUE_NAME_LEN
3963 peer
->clear_node_queue
= work_queue_new(bm
->master
, wname
);
3964 peer
->clear_node_queue
->spec
.hold
= 10;
3965 peer
->clear_node_queue
->spec
.workfunc
= &bgp_clear_route_node
;
3966 peer
->clear_node_queue
->spec
.del_item_data
= &bgp_clear_node_queue_del
;
3967 peer
->clear_node_queue
->spec
.completion_func
= &bgp_clear_node_complete
;
3968 peer
->clear_node_queue
->spec
.max_retries
= 0;
3970 /* we only 'lock' this peer reference when the queue is actually active
3972 peer
->clear_node_queue
->spec
.data
= peer
;
3975 static void bgp_clear_route_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
3976 struct bgp_table
*table
)
3978 struct bgp_node
*rn
;
3979 int force
= bm
->process_main_queue
? 0 : 1;
3982 table
= peer
->bgp
->rib
[afi
][safi
];
3984 /* If still no table => afi/safi isn't configured at all or smth. */
3988 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
3989 struct bgp_path_info
*pi
, *next
;
3990 struct bgp_adj_in
*ain
;
3991 struct bgp_adj_in
*ain_next
;
3993 /* XXX:TODO: This is suboptimal, every non-empty route_node is
3994 * queued for every clearing peer, regardless of whether it is
3995 * relevant to the peer at hand.
3997 * Overview: There are 3 different indices which need to be
3998 * scrubbed, potentially, when a peer is removed:
4000 * 1 peer's routes visible via the RIB (ie accepted routes)
4001 * 2 peer's routes visible by the (optional) peer's adj-in index
4002 * 3 other routes visible by the peer's adj-out index
4004 * 3 there is no hurry in scrubbing, once the struct peer is
4005 * removed from bgp->peer, we could just GC such deleted peer's
4006 * adj-outs at our leisure.
4008 * 1 and 2 must be 'scrubbed' in some way, at least made
4009 * invisible via RIB index before peer session is allowed to be
4010 * brought back up. So one needs to know when such a 'search' is
4015 * - there'd be a single global queue or a single RIB walker
4016 * - rather than tracking which route_nodes still need to be
4017 * examined on a peer basis, we'd track which peers still
4020 * Given that our per-peer prefix-counts now should be reliable,
4021 * this may actually be achievable. It doesn't seem to be a huge
4022 * problem at this time,
4024 * It is possible that we have multiple paths for a prefix from
4026 * if that peer is using AddPath.
4030 ain_next
= ain
->next
;
4032 if (ain
->peer
== peer
) {
4033 bgp_adj_in_remove(rn
, ain
);
4034 bgp_unlock_node(rn
);
4040 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= next
) {
4042 if (pi
->peer
!= peer
)
4046 bgp_path_info_reap(rn
, pi
);
4048 struct bgp_clear_node_queue
*cnq
;
4050 /* both unlocked in bgp_clear_node_queue_del */
4051 bgp_table_lock(bgp_node_table(rn
));
4054 MTYPE_BGP_CLEAR_NODE_QUEUE
,
4055 sizeof(struct bgp_clear_node_queue
));
4057 work_queue_add(peer
->clear_node_queue
, cnq
);
4065 void bgp_clear_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4067 struct bgp_node
*rn
;
4068 struct bgp_table
*table
;
4070 if (peer
->clear_node_queue
== NULL
)
4071 bgp_clear_node_queue_init(peer
);
4073 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
4074 * Idle until it receives a Clearing_Completed event. This protects
4075 * against peers which flap faster than we can we clear, which could
4078 * a) race with routes from the new session being installed before
4079 * clear_route_node visits the node (to delete the route of that
4081 * b) resource exhaustion, clear_route_node likely leads to an entry
4082 * on the process_main queue. Fast-flapping could cause that queue
4086 /* lock peer in assumption that clear-node-queue will get nodes; if so,
4087 * the unlock will happen upon work-queue completion; other wise, the
4088 * unlock happens at the end of this function.
4090 if (!peer
->clear_node_queue
->thread
)
4093 if (safi
!= SAFI_MPLS_VPN
&& safi
!= SAFI_ENCAP
&& safi
!= SAFI_EVPN
)
4094 bgp_clear_route_table(peer
, afi
, safi
, NULL
);
4096 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4097 rn
= bgp_route_next(rn
)) {
4098 table
= bgp_node_get_bgp_table_info(rn
);
4102 bgp_clear_route_table(peer
, afi
, safi
, table
);
4105 /* unlock if no nodes got added to the clear-node-queue. */
4106 if (!peer
->clear_node_queue
->thread
)
4110 void bgp_clear_route_all(struct peer
*peer
)
4115 FOREACH_AFI_SAFI (afi
, safi
)
4116 bgp_clear_route(peer
, afi
, safi
);
4119 rfapiProcessPeerDown(peer
);
4123 void bgp_clear_adj_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
4125 struct bgp_table
*table
;
4126 struct bgp_node
*rn
;
4127 struct bgp_adj_in
*ain
;
4128 struct bgp_adj_in
*ain_next
;
4130 table
= peer
->bgp
->rib
[afi
][safi
];
4132 /* It is possible that we have multiple paths for a prefix from a peer
4133 * if that peer is using AddPath.
4135 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
4139 ain_next
= ain
->next
;
4141 if (ain
->peer
== peer
) {
4142 bgp_adj_in_remove(rn
, ain
);
4143 bgp_unlock_node(rn
);
4151 void bgp_clear_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4153 struct bgp_node
*rn
;
4154 struct bgp_path_info
*pi
;
4155 struct bgp_table
*table
;
4157 if (safi
== SAFI_MPLS_VPN
) {
4158 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4159 rn
= bgp_route_next(rn
)) {
4160 struct bgp_node
*rm
;
4162 /* look for neighbor in tables */
4163 table
= bgp_node_get_bgp_table_info(rn
);
4167 for (rm
= bgp_table_top(table
); rm
;
4168 rm
= bgp_route_next(rm
))
4169 for (pi
= bgp_node_get_bgp_path_info(rm
); pi
;
4171 if (pi
->peer
!= peer
)
4173 if (!CHECK_FLAG(pi
->flags
,
4177 bgp_rib_remove(rm
, pi
, peer
, afi
, safi
);
4182 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4183 rn
= bgp_route_next(rn
))
4184 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
;
4186 if (pi
->peer
!= peer
)
4188 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
4190 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
4196 int bgp_outbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
4198 if (peer
->sort
== BGP_PEER_EBGP
4199 && (ROUTE_MAP_OUT_NAME(filter
) || PREFIX_LIST_OUT_NAME(filter
)
4200 || FILTER_LIST_OUT_NAME(filter
)
4201 || DISTRIBUTE_OUT_NAME(filter
)))
4206 int bgp_inbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
4208 if (peer
->sort
== BGP_PEER_EBGP
4209 && (ROUTE_MAP_IN_NAME(filter
) || PREFIX_LIST_IN_NAME(filter
)
4210 || FILTER_LIST_IN_NAME(filter
)
4211 || DISTRIBUTE_IN_NAME(filter
)))
4216 static void bgp_cleanup_table(struct bgp
*bgp
, struct bgp_table
*table
,
4219 struct bgp_node
*rn
;
4220 struct bgp_path_info
*pi
;
4221 struct bgp_path_info
*next
;
4223 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
4224 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= next
) {
4227 /* Unimport EVPN routes from VRFs */
4228 if (safi
== SAFI_EVPN
)
4229 bgp_evpn_unimport_route(bgp
, AFI_L2VPN
,
4233 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)
4234 && pi
->type
== ZEBRA_ROUTE_BGP
4235 && (pi
->sub_type
== BGP_ROUTE_NORMAL
4236 || pi
->sub_type
== BGP_ROUTE_AGGREGATE
4237 || pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
4239 if (bgp_fibupd_safi(safi
))
4240 bgp_zebra_withdraw(&rn
->p
, pi
, bgp
,
4242 bgp_path_info_reap(rn
, pi
);
4247 /* Delete all kernel routes. */
4248 void bgp_cleanup_routes(struct bgp
*bgp
)
4251 struct bgp_node
*rn
;
4252 struct bgp_table
*table
;
4254 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
4255 if (afi
== AFI_L2VPN
)
4257 bgp_cleanup_table(bgp
, bgp
->rib
[afi
][SAFI_UNICAST
],
4260 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
4262 if (afi
!= AFI_L2VPN
) {
4264 safi
= SAFI_MPLS_VPN
;
4265 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4266 rn
= bgp_route_next(rn
)) {
4267 table
= bgp_node_get_bgp_table_info(rn
);
4268 if (table
!= NULL
) {
4269 bgp_cleanup_table(bgp
, table
, safi
);
4270 bgp_table_finish(&table
);
4271 bgp_node_set_bgp_table_info(rn
, NULL
);
4272 bgp_unlock_node(rn
);
4276 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4277 rn
= bgp_route_next(rn
)) {
4278 table
= bgp_node_get_bgp_table_info(rn
);
4279 if (table
!= NULL
) {
4280 bgp_cleanup_table(bgp
, table
, safi
);
4281 bgp_table_finish(&table
);
4282 bgp_node_set_bgp_table_info(rn
, NULL
);
4283 bgp_unlock_node(rn
);
4288 for (rn
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); rn
;
4289 rn
= bgp_route_next(rn
)) {
4290 table
= bgp_node_get_bgp_table_info(rn
);
4291 if (table
!= NULL
) {
4292 bgp_cleanup_table(bgp
, table
, SAFI_EVPN
);
4293 bgp_table_finish(&table
);
4294 bgp_node_set_bgp_table_info(rn
, NULL
);
4295 bgp_unlock_node(rn
);
4300 void bgp_reset(void)
4303 bgp_zclient_reset();
4304 access_list_reset();
4305 prefix_list_reset();
4308 static int bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
4310 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
4311 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
4312 PEER_CAP_ADDPATH_AF_TX_RCV
));
4315 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
4317 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
4318 struct bgp_nlri
*packet
)
4327 int addpath_encoded
;
4328 uint32_t addpath_id
;
4331 lim
= pnt
+ packet
->length
;
4333 safi
= packet
->safi
;
4335 addpath_encoded
= bgp_addpath_encode_rx(peer
, afi
, safi
);
4337 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
4338 syntactic validity. If the field is syntactically incorrect,
4339 then the Error Subcode is set to Invalid Network Field. */
4340 for (; pnt
< lim
; pnt
+= psize
) {
4341 /* Clear prefix structure. */
4342 memset(&p
, 0, sizeof(struct prefix
));
4344 if (addpath_encoded
) {
4346 /* When packet overflow occurs return immediately. */
4347 if (pnt
+ BGP_ADDPATH_ID_LEN
> lim
)
4348 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
4350 addpath_id
= ntohl(*((uint32_t *)pnt
));
4351 pnt
+= BGP_ADDPATH_ID_LEN
;
4354 /* Fetch prefix length. */
4355 p
.prefixlen
= *pnt
++;
4356 /* afi/safi validity already verified by caller,
4357 * bgp_update_receive */
4358 p
.family
= afi2family(afi
);
4360 /* Prefix length check. */
4361 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
4364 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
4365 peer
->host
, p
.prefixlen
, packet
->afi
);
4366 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH
;
4369 /* Packet size overflow check. */
4370 psize
= PSIZE(p
.prefixlen
);
4372 /* When packet overflow occur return immediately. */
4373 if (pnt
+ psize
> lim
) {
4376 "%s [Error] Update packet error (prefix length %d overflows packet)",
4377 peer
->host
, p
.prefixlen
);
4378 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
4381 /* Defensive coding, double-check the psize fits in a struct
4383 if (psize
> (ssize_t
)sizeof(p
.u
)) {
4386 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
4387 peer
->host
, p
.prefixlen
, sizeof(p
.u
));
4388 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
4391 /* Fetch prefix from NLRI packet. */
4392 memcpy(p
.u
.val
, pnt
, psize
);
4394 /* Check address. */
4395 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
4396 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
4397 /* From RFC4271 Section 6.3:
4399 * If a prefix in the NLRI field is semantically
4401 * (e.g., an unexpected multicast IP address),
4403 * be logged locally, and the prefix SHOULD be
4408 "%s: IPv4 unicast NLRI is multicast address %s, ignoring",
4409 peer
->host
, inet_ntoa(p
.u
.prefix4
));
4414 /* Check address. */
4415 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
4416 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4421 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
4423 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4428 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
4433 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
4435 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4442 /* Normal process. */
4444 ret
= bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
4445 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
4446 NULL
, NULL
, 0, 0, NULL
);
4448 ret
= bgp_withdraw(peer
, &p
, addpath_id
, attr
, afi
,
4449 safi
, ZEBRA_ROUTE_BGP
,
4450 BGP_ROUTE_NORMAL
, NULL
, NULL
, 0,
4453 /* Do not send BGP notification twice when maximum-prefix count
4455 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
))
4456 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW
;
4458 /* Address family configuration mismatch. */
4460 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY
;
4463 /* Packet length consistency check. */
4467 "%s [Error] Update packet error (prefix length mismatch with total length)",
4469 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
4472 return BGP_NLRI_PARSE_OK
;
4475 static struct bgp_static
*bgp_static_new(void)
4477 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
4480 static void bgp_static_free(struct bgp_static
*bgp_static
)
4482 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
4483 route_map_counter_decrement(bgp_static
->rmap
.map
);
4485 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
4486 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
4489 void bgp_static_update(struct bgp
*bgp
, struct prefix
*p
,
4490 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
4492 struct bgp_node
*rn
;
4493 struct bgp_path_info
*pi
;
4494 struct bgp_path_info
*new;
4495 struct bgp_path_info rmap_path
;
4497 struct attr
*attr_new
;
4500 int vnc_implicit_withdraw
= 0;
4507 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4509 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4511 attr
.nexthop
= bgp_static
->igpnexthop
;
4512 attr
.med
= bgp_static
->igpmetric
;
4513 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4515 if (bgp_static
->atomic
)
4516 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
4518 /* Store label index, if required. */
4519 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
4520 attr
.label_index
= bgp_static
->label_index
;
4521 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
4524 /* Apply route-map. */
4525 if (bgp_static
->rmap
.name
) {
4526 struct attr attr_tmp
= attr
;
4528 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
4529 rmap_path
.peer
= bgp
->peer_self
;
4530 rmap_path
.attr
= &attr_tmp
;
4532 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4534 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
,
4537 bgp
->peer_self
->rmap_type
= 0;
4539 if (ret
== RMAP_DENYMATCH
) {
4540 /* Free uninterned attribute. */
4541 bgp_attr_flush(&attr_tmp
);
4543 /* Unintern original. */
4544 aspath_unintern(&attr
.aspath
);
4545 bgp_static_withdraw(bgp
, p
, afi
, safi
);
4549 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4550 bgp_attr_add_gshut_community(&attr_tmp
);
4552 attr_new
= bgp_attr_intern(&attr_tmp
);
4555 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4556 bgp_attr_add_gshut_community(&attr
);
4558 attr_new
= bgp_attr_intern(&attr
);
4561 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4562 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4563 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4567 if (attrhash_cmp(pi
->attr
, attr_new
)
4568 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
4569 && !bgp_flag_check(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
4570 bgp_unlock_node(rn
);
4571 bgp_attr_unintern(&attr_new
);
4572 aspath_unintern(&attr
.aspath
);
4575 /* The attribute is changed. */
4576 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_ATTR_CHANGED
);
4578 /* Rewrite BGP route information. */
4579 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
4580 bgp_path_info_restore(rn
, pi
);
4582 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4584 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4585 && (safi
== SAFI_UNICAST
)) {
4586 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
4588 * Implicit withdraw case.
4589 * We have to do this before pi is
4592 ++vnc_implicit_withdraw
;
4593 vnc_import_bgp_del_route(bgp
, p
, pi
);
4594 vnc_import_bgp_exterior_del_route(
4599 bgp_attr_unintern(&pi
->attr
);
4600 pi
->attr
= attr_new
;
4601 pi
->uptime
= bgp_clock();
4603 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4604 && (safi
== SAFI_UNICAST
)) {
4605 if (vnc_implicit_withdraw
) {
4606 vnc_import_bgp_add_route(bgp
, p
, pi
);
4607 vnc_import_bgp_exterior_add_route(
4613 /* Nexthop reachability check. */
4614 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4615 && (safi
== SAFI_UNICAST
4616 || safi
== SAFI_LABELED_UNICAST
)) {
4618 struct bgp
*bgp_nexthop
= bgp
;
4620 if (pi
->extra
&& pi
->extra
->bgp_orig
)
4621 bgp_nexthop
= pi
->extra
->bgp_orig
;
4623 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
,
4625 bgp_path_info_set_flag(rn
, pi
,
4628 if (BGP_DEBUG(nht
, NHT
)) {
4629 char buf1
[INET6_ADDRSTRLEN
];
4630 inet_ntop(p
->family
,
4634 "%s(%s): Route not in table, not advertising",
4635 __FUNCTION__
, buf1
);
4637 bgp_path_info_unset_flag(
4638 rn
, pi
, BGP_PATH_VALID
);
4641 /* Delete the NHT structure if any, if we're
4643 * enabling/disabling import check. We
4644 * deregister the route
4645 * from NHT to avoid overloading NHT and the
4646 * process interaction
4648 bgp_unlink_nexthop(pi
);
4649 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_VALID
);
4651 /* Process change. */
4652 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
4653 bgp_process(bgp
, rn
, afi
, safi
);
4655 if (SAFI_UNICAST
== safi
4656 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4658 == BGP_INSTANCE_TYPE_DEFAULT
)) {
4659 vpn_leak_from_vrf_update(bgp_get_default(), bgp
,
4663 bgp_unlock_node(rn
);
4664 aspath_unintern(&attr
.aspath
);
4669 /* Make new BGP info. */
4670 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
4672 /* Nexthop reachability check. */
4673 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4674 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
4675 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, new, NULL
, 0))
4676 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
4678 if (BGP_DEBUG(nht
, NHT
)) {
4679 char buf1
[INET6_ADDRSTRLEN
];
4680 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
4683 "%s(%s): Route not in table, not advertising",
4684 __FUNCTION__
, buf1
);
4686 bgp_path_info_unset_flag(rn
, new, BGP_PATH_VALID
);
4689 /* Delete the NHT structure if any, if we're toggling between
4690 * enabling/disabling import check. We deregister the route
4691 * from NHT to avoid overloading NHT and the process interaction
4693 bgp_unlink_nexthop(new);
4695 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
4698 /* Aggregate address increment. */
4699 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4701 /* Register new BGP information. */
4702 bgp_path_info_add(rn
, new);
4704 /* route_node_get lock */
4705 bgp_unlock_node(rn
);
4707 /* Process change. */
4708 bgp_process(bgp
, rn
, afi
, safi
);
4710 if (SAFI_UNICAST
== safi
4711 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4712 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4713 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
4716 /* Unintern original. */
4717 aspath_unintern(&attr
.aspath
);
4720 void bgp_static_withdraw(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
4723 struct bgp_node
*rn
;
4724 struct bgp_path_info
*pi
;
4726 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4728 /* Check selected route and self inserted route. */
4729 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4730 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4731 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4734 /* Withdraw static BGP route from routing table. */
4736 if (SAFI_UNICAST
== safi
4737 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4738 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4739 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
4741 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4742 bgp_unlink_nexthop(pi
);
4743 bgp_path_info_delete(rn
, pi
);
4744 bgp_process(bgp
, rn
, afi
, safi
);
4747 /* Unlock bgp_node_lookup. */
4748 bgp_unlock_node(rn
);
4752 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
4754 static void bgp_static_withdraw_safi(struct bgp
*bgp
, struct prefix
*p
,
4755 afi_t afi
, safi_t safi
,
4756 struct prefix_rd
*prd
)
4758 struct bgp_node
*rn
;
4759 struct bgp_path_info
*pi
;
4761 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4763 /* Check selected route and self inserted route. */
4764 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4765 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4766 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4769 /* Withdraw static BGP route from routing table. */
4772 rfapiProcessWithdraw(
4773 pi
->peer
, NULL
, p
, prd
, pi
->attr
, afi
, safi
, pi
->type
,
4774 1); /* Kill, since it is an administrative change */
4776 if (SAFI_MPLS_VPN
== safi
4777 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4778 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4780 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4781 bgp_path_info_delete(rn
, pi
);
4782 bgp_process(bgp
, rn
, afi
, safi
);
4785 /* Unlock bgp_node_lookup. */
4786 bgp_unlock_node(rn
);
4789 static void bgp_static_update_safi(struct bgp
*bgp
, struct prefix
*p
,
4790 struct bgp_static
*bgp_static
, afi_t afi
,
4793 struct bgp_node
*rn
;
4794 struct bgp_path_info
*new;
4795 struct attr
*attr_new
;
4796 struct attr attr
= {0};
4797 struct bgp_path_info
*pi
;
4799 mpls_label_t label
= 0;
4801 uint32_t num_labels
= 0;
4806 if (bgp_static
->label
!= MPLS_INVALID_LABEL
)
4808 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
4811 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4813 attr
.nexthop
= bgp_static
->igpnexthop
;
4814 attr
.med
= bgp_static
->igpmetric
;
4815 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4817 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
4818 || (safi
== SAFI_ENCAP
)) {
4819 if (afi
== AFI_IP
) {
4820 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
4821 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
4824 if (afi
== AFI_L2VPN
) {
4825 if (bgp_static
->gatewayIp
.family
== AF_INET
)
4827 bgp_static
->gatewayIp
.u
.prefix4
.s_addr
;
4828 else if (bgp_static
->gatewayIp
.family
== AF_INET6
)
4829 memcpy(&(add
.ipv6
), &(bgp_static
->gatewayIp
.u
.prefix6
),
4830 sizeof(struct in6_addr
));
4831 overlay_index_update(&attr
, bgp_static
->eth_s_id
, &add
);
4832 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
4833 struct bgp_encap_type_vxlan bet
;
4834 memset(&bet
, 0, sizeof(struct bgp_encap_type_vxlan
));
4835 bet
.vnid
= p
->u
.prefix_evpn
.prefix_addr
.eth_tag
;
4836 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
4838 if (bgp_static
->router_mac
) {
4839 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
4842 /* Apply route-map. */
4843 if (bgp_static
->rmap
.name
) {
4844 struct attr attr_tmp
= attr
;
4845 struct bgp_path_info rmap_path
;
4848 rmap_path
.peer
= bgp
->peer_self
;
4849 rmap_path
.attr
= &attr_tmp
;
4851 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4853 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
,
4856 bgp
->peer_self
->rmap_type
= 0;
4858 if (ret
== RMAP_DENYMATCH
) {
4859 /* Free uninterned attribute. */
4860 bgp_attr_flush(&attr_tmp
);
4862 /* Unintern original. */
4863 aspath_unintern(&attr
.aspath
);
4864 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
4869 attr_new
= bgp_attr_intern(&attr_tmp
);
4871 attr_new
= bgp_attr_intern(&attr
);
4874 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4875 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4876 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4880 memset(&add
, 0, sizeof(union gw_addr
));
4881 if (attrhash_cmp(pi
->attr
, attr_new
)
4882 && overlay_index_equal(afi
, pi
, bgp_static
->eth_s_id
, &add
)
4883 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
4884 bgp_unlock_node(rn
);
4885 bgp_attr_unintern(&attr_new
);
4886 aspath_unintern(&attr
.aspath
);
4889 /* The attribute is changed. */
4890 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_ATTR_CHANGED
);
4892 /* Rewrite BGP route information. */
4893 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
4894 bgp_path_info_restore(rn
, pi
);
4896 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4897 bgp_attr_unintern(&pi
->attr
);
4898 pi
->attr
= attr_new
;
4899 pi
->uptime
= bgp_clock();
4902 label
= decode_label(&pi
->extra
->label
[0]);
4905 /* Process change. */
4906 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
4907 bgp_process(bgp
, rn
, afi
, safi
);
4909 if (SAFI_MPLS_VPN
== safi
4910 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4911 vpn_leak_to_vrf_update(bgp
, pi
);
4914 rfapiProcessUpdate(pi
->peer
, NULL
, p
, &bgp_static
->prd
,
4915 pi
->attr
, afi
, safi
, pi
->type
,
4916 pi
->sub_type
, &label
);
4918 bgp_unlock_node(rn
);
4919 aspath_unintern(&attr
.aspath
);
4925 /* Make new BGP info. */
4926 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
4928 SET_FLAG(new->flags
, BGP_PATH_VALID
);
4929 new->extra
= bgp_path_info_extra_new();
4931 new->extra
->label
[0] = bgp_static
->label
;
4932 new->extra
->num_labels
= num_labels
;
4935 label
= decode_label(&bgp_static
->label
);
4938 /* Aggregate address increment. */
4939 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4941 /* Register new BGP information. */
4942 bgp_path_info_add(rn
, new);
4943 /* route_node_get lock */
4944 bgp_unlock_node(rn
);
4946 /* Process change. */
4947 bgp_process(bgp
, rn
, afi
, safi
);
4949 if (SAFI_MPLS_VPN
== safi
4950 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4951 vpn_leak_to_vrf_update(bgp
, new);
4954 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
4955 safi
, new->type
, new->sub_type
, &label
);
4958 /* Unintern original. */
4959 aspath_unintern(&attr
.aspath
);
4962 /* Configure static BGP network. When user don't run zebra, static
4963 route should be installed as valid. */
4964 static int bgp_static_set(struct vty
*vty
, const char *negate
,
4965 const char *ip_str
, afi_t afi
, safi_t safi
,
4966 const char *rmap
, int backdoor
, uint32_t label_index
)
4968 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
4971 struct bgp_static
*bgp_static
;
4972 struct bgp_node
*rn
;
4973 uint8_t need_update
= 0;
4975 /* Convert IP prefix string to struct prefix. */
4976 ret
= str2prefix(ip_str
, &p
);
4978 vty_out(vty
, "%% Malformed prefix\n");
4979 return CMD_WARNING_CONFIG_FAILED
;
4981 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4982 vty_out(vty
, "%% Malformed prefix (link-local address)\n");
4983 return CMD_WARNING_CONFIG_FAILED
;
4990 /* Set BGP static route configuration. */
4991 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
4994 vty_out(vty
, "%% Can't find static route specified\n");
4995 return CMD_WARNING_CONFIG_FAILED
;
4998 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5000 if ((label_index
!= BGP_INVALID_LABEL_INDEX
)
5001 && (label_index
!= bgp_static
->label_index
)) {
5003 "%% label-index doesn't match static route\n");
5004 return CMD_WARNING_CONFIG_FAILED
;
5007 if ((rmap
&& bgp_static
->rmap
.name
)
5008 && strcmp(rmap
, bgp_static
->rmap
.name
)) {
5010 "%% route-map name doesn't match static route\n");
5011 return CMD_WARNING_CONFIG_FAILED
;
5014 /* Update BGP RIB. */
5015 if (!bgp_static
->backdoor
)
5016 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
5018 /* Clear configuration. */
5019 bgp_static_free(bgp_static
);
5020 bgp_node_set_bgp_static_info(rn
, NULL
);
5021 bgp_unlock_node(rn
);
5022 bgp_unlock_node(rn
);
5025 /* Set BGP static route configuration. */
5026 rn
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
5028 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5030 /* Configuration change. */
5031 /* Label index cannot be changed. */
5032 if (bgp_static
->label_index
!= label_index
) {
5033 vty_out(vty
, "%% cannot change label-index\n");
5034 return CMD_WARNING_CONFIG_FAILED
;
5037 /* Check previous routes are installed into BGP. */
5038 if (bgp_static
->valid
5039 && bgp_static
->backdoor
!= backdoor
)
5042 bgp_static
->backdoor
= backdoor
;
5045 XFREE(MTYPE_ROUTE_MAP_NAME
,
5046 bgp_static
->rmap
.name
);
5047 route_map_counter_decrement(
5048 bgp_static
->rmap
.map
);
5049 bgp_static
->rmap
.name
=
5050 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
5051 bgp_static
->rmap
.map
=
5052 route_map_lookup_by_name(rmap
);
5053 route_map_counter_increment(
5054 bgp_static
->rmap
.map
);
5056 XFREE(MTYPE_ROUTE_MAP_NAME
,
5057 bgp_static
->rmap
.name
);
5058 route_map_counter_decrement(
5059 bgp_static
->rmap
.map
);
5060 bgp_static
->rmap
.name
= NULL
;
5061 bgp_static
->rmap
.map
= NULL
;
5062 bgp_static
->valid
= 0;
5064 bgp_unlock_node(rn
);
5066 /* New configuration. */
5067 bgp_static
= bgp_static_new();
5068 bgp_static
->backdoor
= backdoor
;
5069 bgp_static
->valid
= 0;
5070 bgp_static
->igpmetric
= 0;
5071 bgp_static
->igpnexthop
.s_addr
= 0;
5072 bgp_static
->label_index
= label_index
;
5075 XFREE(MTYPE_ROUTE_MAP_NAME
,
5076 bgp_static
->rmap
.name
);
5077 route_map_counter_decrement(
5078 bgp_static
->rmap
.map
);
5079 bgp_static
->rmap
.name
=
5080 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
5081 bgp_static
->rmap
.map
=
5082 route_map_lookup_by_name(rmap
);
5083 route_map_counter_increment(
5084 bgp_static
->rmap
.map
);
5086 bgp_node_set_bgp_static_info(rn
, bgp_static
);
5089 bgp_static
->valid
= 1;
5091 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
5093 if (!bgp_static
->backdoor
)
5094 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
5100 void bgp_static_add(struct bgp
*bgp
)
5104 struct bgp_node
*rn
;
5105 struct bgp_node
*rm
;
5106 struct bgp_table
*table
;
5107 struct bgp_static
*bgp_static
;
5109 FOREACH_AFI_SAFI (afi
, safi
)
5110 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5111 rn
= bgp_route_next(rn
)) {
5112 if (!bgp_node_has_bgp_path_info_data(rn
))
5115 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5116 || (safi
== SAFI_EVPN
)) {
5117 table
= bgp_node_get_bgp_table_info(rn
);
5119 for (rm
= bgp_table_top(table
); rm
;
5120 rm
= bgp_route_next(rm
)) {
5122 bgp_node_get_bgp_static_info(
5124 bgp_static_update_safi(bgp
, &rm
->p
,
5131 bgp_node_get_bgp_static_info(rn
), afi
,
5137 /* Called from bgp_delete(). Delete all static routes from the BGP
5139 void bgp_static_delete(struct bgp
*bgp
)
5143 struct bgp_node
*rn
;
5144 struct bgp_node
*rm
;
5145 struct bgp_table
*table
;
5146 struct bgp_static
*bgp_static
;
5148 FOREACH_AFI_SAFI (afi
, safi
)
5149 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5150 rn
= bgp_route_next(rn
)) {
5151 if (!bgp_node_has_bgp_path_info_data(rn
))
5154 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5155 || (safi
== SAFI_EVPN
)) {
5156 table
= bgp_node_get_bgp_table_info(rn
);
5158 for (rm
= bgp_table_top(table
); rm
;
5159 rm
= bgp_route_next(rm
)) {
5161 bgp_node_get_bgp_static_info(
5166 bgp_static_withdraw_safi(
5167 bgp
, &rm
->p
, AFI_IP
, safi
,
5168 (struct prefix_rd
*)&rn
->p
);
5169 bgp_static_free(bgp_static
);
5170 bgp_node_set_bgp_static_info(rn
, NULL
);
5171 bgp_unlock_node(rn
);
5174 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5175 bgp_static_withdraw(bgp
, &rn
->p
, afi
, safi
);
5176 bgp_static_free(bgp_static
);
5177 bgp_node_set_bgp_static_info(rn
, NULL
);
5178 bgp_unlock_node(rn
);
5183 void bgp_static_redo_import_check(struct bgp
*bgp
)
5187 struct bgp_node
*rn
;
5188 struct bgp_node
*rm
;
5189 struct bgp_table
*table
;
5190 struct bgp_static
*bgp_static
;
5192 /* Use this flag to force reprocessing of the route */
5193 bgp_flag_set(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5194 FOREACH_AFI_SAFI (afi
, safi
) {
5195 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5196 rn
= bgp_route_next(rn
)) {
5197 if (!bgp_node_has_bgp_path_info_data(rn
))
5200 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5201 || (safi
== SAFI_EVPN
)) {
5202 table
= bgp_node_get_bgp_table_info(rn
);
5204 for (rm
= bgp_table_top(table
); rm
;
5205 rm
= bgp_route_next(rm
)) {
5207 bgp_node_get_bgp_static_info(
5209 bgp_static_update_safi(bgp
, &rm
->p
,
5214 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5215 bgp_static_update(bgp
, &rn
->p
, bgp_static
, afi
,
5220 bgp_flag_unset(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5223 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
5226 struct bgp_table
*table
;
5227 struct bgp_node
*rn
;
5228 struct bgp_path_info
*pi
;
5230 table
= bgp
->rib
[afi
][safi
];
5231 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
5232 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
5233 if (pi
->peer
== bgp
->peer_self
5234 && ((pi
->type
== ZEBRA_ROUTE_BGP
5235 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5236 || (pi
->type
!= ZEBRA_ROUTE_BGP
5238 == BGP_ROUTE_REDISTRIBUTE
))) {
5239 bgp_aggregate_decrement(bgp
, &rn
->p
, pi
, afi
,
5241 bgp_unlink_nexthop(pi
);
5242 bgp_path_info_delete(rn
, pi
);
5243 bgp_process(bgp
, rn
, afi
, safi
);
5250 * Purge all networks and redistributed routes from routing table.
5251 * Invoked upon the instance going down.
5253 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
5258 FOREACH_AFI_SAFI (afi
, safi
)
5259 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
5264 * Currently this is used to set static routes for VPN and ENCAP.
5265 * I think it can probably be factored with bgp_static_set.
5267 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5268 const char *ip_str
, const char *rd_str
,
5269 const char *label_str
, const char *rmap_str
,
5270 int evpn_type
, const char *esi
, const char *gwip
,
5271 const char *ethtag
, const char *routermac
)
5273 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5276 struct prefix_rd prd
;
5277 struct bgp_node
*prn
;
5278 struct bgp_node
*rn
;
5279 struct bgp_table
*table
;
5280 struct bgp_static
*bgp_static
;
5281 mpls_label_t label
= MPLS_INVALID_LABEL
;
5282 struct prefix gw_ip
;
5284 /* validate ip prefix */
5285 ret
= str2prefix(ip_str
, &p
);
5287 vty_out(vty
, "%% Malformed prefix\n");
5288 return CMD_WARNING_CONFIG_FAILED
;
5291 if ((afi
== AFI_L2VPN
)
5292 && (bgp_build_evpn_prefix(evpn_type
,
5293 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5294 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5295 return CMD_WARNING_CONFIG_FAILED
;
5298 ret
= str2prefix_rd(rd_str
, &prd
);
5300 vty_out(vty
, "%% Malformed rd\n");
5301 return CMD_WARNING_CONFIG_FAILED
;
5305 unsigned long label_val
;
5306 label_val
= strtoul(label_str
, NULL
, 10);
5307 encode_label(label_val
, &label
);
5310 if (safi
== SAFI_EVPN
) {
5311 if (esi
&& str2esi(esi
, NULL
) == 0) {
5312 vty_out(vty
, "%% Malformed ESI\n");
5313 return CMD_WARNING_CONFIG_FAILED
;
5315 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
5316 vty_out(vty
, "%% Malformed Router MAC\n");
5317 return CMD_WARNING_CONFIG_FAILED
;
5320 memset(&gw_ip
, 0, sizeof(struct prefix
));
5321 ret
= str2prefix(gwip
, &gw_ip
);
5323 vty_out(vty
, "%% Malformed GatewayIp\n");
5324 return CMD_WARNING_CONFIG_FAILED
;
5326 if ((gw_ip
.family
== AF_INET
5327 && is_evpn_prefix_ipaddr_v6(
5328 (struct prefix_evpn
*)&p
))
5329 || (gw_ip
.family
== AF_INET6
5330 && is_evpn_prefix_ipaddr_v4(
5331 (struct prefix_evpn
*)&p
))) {
5333 "%% GatewayIp family differs with IP prefix\n");
5334 return CMD_WARNING_CONFIG_FAILED
;
5338 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5339 if (!bgp_node_has_bgp_path_info_data(prn
))
5340 bgp_node_set_bgp_table_info(prn
,
5341 bgp_table_init(bgp
, afi
, safi
));
5342 table
= bgp_node_get_bgp_table_info(prn
);
5344 rn
= bgp_node_get(table
, &p
);
5346 if (bgp_node_has_bgp_path_info_data(rn
)) {
5347 vty_out(vty
, "%% Same network configuration exists\n");
5348 bgp_unlock_node(rn
);
5350 /* New configuration. */
5351 bgp_static
= bgp_static_new();
5352 bgp_static
->backdoor
= 0;
5353 bgp_static
->valid
= 0;
5354 bgp_static
->igpmetric
= 0;
5355 bgp_static
->igpnexthop
.s_addr
= 0;
5356 bgp_static
->label
= label
;
5357 bgp_static
->prd
= prd
;
5360 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
5361 route_map_counter_decrement(bgp_static
->rmap
.map
);
5362 bgp_static
->rmap
.name
=
5363 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
5364 bgp_static
->rmap
.map
=
5365 route_map_lookup_by_name(rmap_str
);
5366 route_map_counter_increment(bgp_static
->rmap
.map
);
5369 if (safi
== SAFI_EVPN
) {
5371 bgp_static
->eth_s_id
=
5373 sizeof(struct eth_segment_id
));
5374 str2esi(esi
, bgp_static
->eth_s_id
);
5377 bgp_static
->router_mac
=
5378 XCALLOC(MTYPE_ATTR
, ETH_ALEN
+ 1);
5379 (void)prefix_str2mac(routermac
,
5380 bgp_static
->router_mac
);
5383 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
5385 bgp_node_set_bgp_static_info(rn
, bgp_static
);
5387 bgp_static
->valid
= 1;
5388 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
5394 /* Configure static BGP network. */
5395 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5396 const char *ip_str
, const char *rd_str
,
5397 const char *label_str
, int evpn_type
, const char *esi
,
5398 const char *gwip
, const char *ethtag
)
5400 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5403 struct prefix_rd prd
;
5404 struct bgp_node
*prn
;
5405 struct bgp_node
*rn
;
5406 struct bgp_table
*table
;
5407 struct bgp_static
*bgp_static
;
5408 mpls_label_t label
= MPLS_INVALID_LABEL
;
5410 /* Convert IP prefix string to struct prefix. */
5411 ret
= str2prefix(ip_str
, &p
);
5413 vty_out(vty
, "%% Malformed prefix\n");
5414 return CMD_WARNING_CONFIG_FAILED
;
5417 if ((afi
== AFI_L2VPN
)
5418 && (bgp_build_evpn_prefix(evpn_type
,
5419 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5420 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5421 return CMD_WARNING_CONFIG_FAILED
;
5423 ret
= str2prefix_rd(rd_str
, &prd
);
5425 vty_out(vty
, "%% Malformed rd\n");
5426 return CMD_WARNING_CONFIG_FAILED
;
5430 unsigned long label_val
;
5431 label_val
= strtoul(label_str
, NULL
, 10);
5432 encode_label(label_val
, &label
);
5435 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5436 if (!bgp_node_has_bgp_path_info_data(prn
))
5437 bgp_node_set_bgp_table_info(prn
,
5438 bgp_table_init(bgp
, afi
, safi
));
5440 bgp_unlock_node(prn
);
5441 table
= bgp_node_get_bgp_table_info(prn
);
5443 rn
= bgp_node_lookup(table
, &p
);
5446 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
5448 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5449 bgp_static_free(bgp_static
);
5450 bgp_node_set_bgp_static_info(rn
, NULL
);
5451 bgp_unlock_node(rn
);
5452 bgp_unlock_node(rn
);
5454 vty_out(vty
, "%% Can't find the route\n");
5459 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
5460 const char *rmap_name
)
5462 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5463 struct bgp_rmap
*rmap
;
5465 rmap
= &bgp
->table_map
[afi
][safi
];
5467 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5468 route_map_counter_decrement(rmap
->map
);
5469 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
5470 rmap
->map
= route_map_lookup_by_name(rmap_name
);
5471 route_map_counter_increment(rmap
->map
);
5473 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5474 route_map_counter_decrement(rmap
->map
);
5479 if (bgp_fibupd_safi(safi
))
5480 bgp_zebra_announce_table(bgp
, afi
, safi
);
5485 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
5486 const char *rmap_name
)
5488 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5489 struct bgp_rmap
*rmap
;
5491 rmap
= &bgp
->table_map
[afi
][safi
];
5492 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5493 route_map_counter_decrement(rmap
->map
);
5497 if (bgp_fibupd_safi(safi
))
5498 bgp_zebra_announce_table(bgp
, afi
, safi
);
5503 void bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
5506 if (bgp
->table_map
[afi
][safi
].name
) {
5507 vty_out(vty
, " table-map %s\n",
5508 bgp
->table_map
[afi
][safi
].name
);
5512 DEFUN (bgp_table_map
,
5515 "BGP table to RIB route download filter\n"
5516 "Name of the route map\n")
5519 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5520 argv
[idx_word
]->arg
);
5522 DEFUN (no_bgp_table_map
,
5523 no_bgp_table_map_cmd
,
5524 "no table-map WORD",
5526 "BGP table to RIB route download filter\n"
5527 "Name of the route map\n")
5530 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5531 argv
[idx_word
]->arg
);
5537 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
5538 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
5539 backdoor$backdoor}]",
5541 "Specify a network to announce via BGP\n"
5546 "Route-map to modify the attributes\n"
5547 "Name of the route map\n"
5548 "Label index to associate with the prefix\n"
5549 "Label index value\n"
5550 "Specify a BGP backdoor route\n")
5552 char addr_prefix_str
[BUFSIZ
];
5557 ret
= netmask_str2prefix_str(address_str
, netmask_str
,
5560 vty_out(vty
, "%% Inconsistent address and mask\n");
5561 return CMD_WARNING_CONFIG_FAILED
;
5565 return bgp_static_set(
5566 vty
, no
, address_str
? addr_prefix_str
: prefix_str
, AFI_IP
,
5567 bgp_node_safi(vty
), map_name
, backdoor
? 1 : 0,
5568 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5571 DEFPY(ipv6_bgp_network
,
5572 ipv6_bgp_network_cmd
,
5573 "[no] network X:X::X:X/M$prefix \
5574 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
5576 "Specify a network to announce via BGP\n"
5578 "Route-map to modify the attributes\n"
5579 "Name of the route map\n"
5580 "Label index to associate with the prefix\n"
5581 "Label index value\n")
5583 return bgp_static_set(
5584 vty
, no
, prefix_str
, AFI_IP6
, bgp_node_safi(vty
), map_name
, 0,
5585 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5588 static struct bgp_aggregate
*bgp_aggregate_new(void)
5590 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
5593 static void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
5595 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
5598 static int bgp_aggregate_info_same(struct bgp_path_info
*pi
, uint8_t origin
,
5599 struct aspath
*aspath
,
5600 struct community
*comm
,
5601 struct ecommunity
*ecomm
,
5602 struct lcommunity
*lcomm
)
5604 static struct aspath
*ae
= NULL
;
5607 ae
= aspath_empty();
5612 if (origin
!= pi
->attr
->origin
)
5615 if (!aspath_cmp(pi
->attr
->aspath
, (aspath
) ? aspath
: ae
))
5618 if (!community_cmp(pi
->attr
->community
, comm
))
5621 if (!ecommunity_cmp(pi
->attr
->ecommunity
, ecomm
))
5624 if (!lcommunity_cmp(pi
->attr
->lcommunity
, lcomm
))
5627 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
5633 static void bgp_aggregate_install(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
5634 struct prefix
*p
, uint8_t origin
,
5635 struct aspath
*aspath
,
5636 struct community
*community
,
5637 struct ecommunity
*ecommunity
,
5638 struct lcommunity
*lcommunity
,
5639 uint8_t atomic_aggregate
,
5640 struct bgp_aggregate
*aggregate
)
5642 struct bgp_node
*rn
;
5643 struct bgp_table
*table
;
5644 struct bgp_path_info
*pi
, *orig
, *new;
5646 table
= bgp
->rib
[afi
][safi
];
5648 rn
= bgp_node_get(table
, p
);
5650 for (orig
= pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
5651 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5652 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5655 if (aggregate
->count
> 0) {
5657 * If the aggregate information has not changed
5658 * no need to re-install it again.
5660 if (bgp_aggregate_info_same(orig
, origin
, aspath
, community
,
5661 ecommunity
, lcommunity
)) {
5662 bgp_unlock_node(rn
);
5665 aspath_free(aspath
);
5667 community_free(&community
);
5669 ecommunity_free(&ecommunity
);
5671 lcommunity_free(&lcommunity
);
5677 * Mark the old as unusable
5680 bgp_path_info_delete(rn
, pi
);
5682 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0,
5684 bgp_attr_aggregate_intern(bgp
, origin
, aspath
,
5685 community
, ecommunity
,
5690 SET_FLAG(new->flags
, BGP_PATH_VALID
);
5692 bgp_path_info_add(rn
, new);
5693 bgp_process(bgp
, rn
, afi
, safi
);
5695 for (pi
= orig
; pi
; pi
= pi
->next
)
5696 if (pi
->peer
== bgp
->peer_self
5697 && pi
->type
== ZEBRA_ROUTE_BGP
5698 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5701 /* Withdraw static BGP route from routing table. */
5703 bgp_path_info_delete(rn
, pi
);
5704 bgp_process(bgp
, rn
, afi
, safi
);
5708 bgp_unlock_node(rn
);
5711 /* Update an aggregate as routes are added/removed from the BGP table */
5712 static void bgp_aggregate_route(struct bgp
*bgp
, struct prefix
*p
,
5713 afi_t afi
, safi_t safi
,
5714 struct bgp_aggregate
*aggregate
)
5716 struct bgp_table
*table
;
5717 struct bgp_node
*top
;
5718 struct bgp_node
*rn
;
5720 struct aspath
*aspath
= NULL
;
5721 struct community
*community
= NULL
;
5722 struct ecommunity
*ecommunity
= NULL
;
5723 struct lcommunity
*lcommunity
= NULL
;
5724 struct bgp_path_info
*pi
;
5725 unsigned long match
= 0;
5726 uint8_t atomic_aggregate
= 0;
5728 /* ORIGIN attribute: If at least one route among routes that are
5729 aggregated has ORIGIN with the value INCOMPLETE, then the
5730 aggregated route must have the ORIGIN attribute with the value
5731 INCOMPLETE. Otherwise, if at least one route among routes that
5732 are aggregated has ORIGIN with the value EGP, then the aggregated
5733 route must have the origin attribute with the value EGP. In all
5734 other case the value of the ORIGIN attribute of the aggregated
5735 route is INTERNAL. */
5736 origin
= BGP_ORIGIN_IGP
;
5738 table
= bgp
->rib
[afi
][safi
];
5740 top
= bgp_node_get(table
, p
);
5741 for (rn
= bgp_node_get(table
, p
); rn
;
5742 rn
= bgp_route_next_until(rn
, top
)) {
5743 if (rn
->p
.prefixlen
<= p
->prefixlen
)
5748 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
5749 if (BGP_PATH_HOLDDOWN(pi
))
5753 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
5754 atomic_aggregate
= 1;
5756 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5760 * summary-only aggregate route suppress
5761 * aggregated route announcements.
5763 if (aggregate
->summary_only
) {
5764 (bgp_path_info_extra_get(pi
))->suppress
++;
5765 bgp_path_info_set_flag(rn
, pi
,
5766 BGP_PATH_ATTR_CHANGED
);
5773 * If at least one route among routes that are
5774 * aggregated has ORIGIN with the value INCOMPLETE,
5775 * then the aggregated route MUST have the ORIGIN
5776 * attribute with the value INCOMPLETE. Otherwise, if
5777 * at least one route among routes that are aggregated
5778 * has ORIGIN with the value EGP, then the aggregated
5779 * route MUST have the ORIGIN attribute with the value
5782 switch (pi
->attr
->origin
) {
5783 case BGP_ORIGIN_INCOMPLETE
:
5784 aggregate
->incomplete_origin_count
++;
5786 case BGP_ORIGIN_EGP
:
5787 aggregate
->egp_origin_count
++;
5795 if (!aggregate
->as_set
)
5799 * as-set aggregate route generate origin, as path,
5800 * and community aggregation.
5802 /* Compute aggregate route's as-path.
5804 bgp_compute_aggregate_aspath(aggregate
,
5807 /* Compute aggregate route's community.
5809 if (pi
->attr
->community
)
5810 bgp_compute_aggregate_community(
5812 pi
->attr
->community
);
5814 /* Compute aggregate route's extended community.
5816 if (pi
->attr
->ecommunity
)
5817 bgp_compute_aggregate_ecommunity(
5819 pi
->attr
->ecommunity
);
5821 /* Compute aggregate route's large community.
5823 if (pi
->attr
->lcommunity
)
5824 bgp_compute_aggregate_lcommunity(
5826 pi
->attr
->lcommunity
);
5829 bgp_process(bgp
, rn
, afi
, safi
);
5831 bgp_unlock_node(top
);
5834 if (aggregate
->incomplete_origin_count
> 0)
5835 origin
= BGP_ORIGIN_INCOMPLETE
;
5836 else if (aggregate
->egp_origin_count
> 0)
5837 origin
= BGP_ORIGIN_EGP
;
5839 if (aggregate
->as_set
) {
5840 if (aggregate
->aspath
)
5841 /* Retrieve aggregate route's as-path.
5843 aspath
= aspath_dup(aggregate
->aspath
);
5845 if (aggregate
->community
)
5846 /* Retrieve aggregate route's community.
5848 community
= community_dup(aggregate
->community
);
5850 if (aggregate
->ecommunity
)
5851 /* Retrieve aggregate route's ecommunity.
5853 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
5855 if (aggregate
->lcommunity
)
5856 /* Retrieve aggregate route's lcommunity.
5858 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
5861 bgp_aggregate_install(bgp
, afi
, safi
, p
, origin
, aspath
, community
,
5862 ecommunity
, lcommunity
, atomic_aggregate
,
5866 static void bgp_aggregate_delete(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
5867 safi_t safi
, struct bgp_aggregate
*aggregate
)
5869 struct bgp_table
*table
;
5870 struct bgp_node
*top
;
5871 struct bgp_node
*rn
;
5872 struct bgp_path_info
*pi
;
5873 unsigned long match
;
5875 table
= bgp
->rib
[afi
][safi
];
5877 /* If routes exists below this node, generate aggregate routes. */
5878 top
= bgp_node_get(table
, p
);
5879 for (rn
= bgp_node_get(table
, p
); rn
;
5880 rn
= bgp_route_next_until(rn
, top
)) {
5881 if (rn
->p
.prefixlen
<= p
->prefixlen
)
5885 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
5886 if (BGP_PATH_HOLDDOWN(pi
))
5889 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5892 if (aggregate
->summary_only
&& pi
->extra
) {
5893 pi
->extra
->suppress
--;
5895 if (pi
->extra
->suppress
== 0) {
5896 bgp_path_info_set_flag(
5897 rn
, pi
, BGP_PATH_ATTR_CHANGED
);
5903 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
5904 aggregate
->incomplete_origin_count
--;
5905 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
5906 aggregate
->egp_origin_count
--;
5908 if (aggregate
->as_set
) {
5909 /* Remove as-path from aggregate.
5911 bgp_remove_aspath_from_aggregate(
5915 if (pi
->attr
->community
)
5916 /* Remove community from aggregate.
5918 bgp_remove_community_from_aggregate(
5920 pi
->attr
->community
);
5922 if (pi
->attr
->ecommunity
)
5923 /* Remove ecommunity from aggregate.
5925 bgp_remove_ecommunity_from_aggregate(
5927 pi
->attr
->ecommunity
);
5929 if (pi
->attr
->lcommunity
)
5930 /* Remove lcommunity from aggregate.
5932 bgp_remove_lcommunity_from_aggregate(
5934 pi
->attr
->lcommunity
);
5939 /* If this node was suppressed, process the change. */
5941 bgp_process(bgp
, rn
, afi
, safi
);
5943 bgp_unlock_node(top
);
5946 static void bgp_add_route_to_aggregate(struct bgp
*bgp
, struct prefix
*aggr_p
,
5947 struct bgp_path_info
*pinew
, afi_t afi
,
5949 struct bgp_aggregate
*aggregate
)
5952 struct aspath
*aspath
= NULL
;
5953 uint8_t atomic_aggregate
= 0;
5954 struct community
*community
= NULL
;
5955 struct ecommunity
*ecommunity
= NULL
;
5956 struct lcommunity
*lcommunity
= NULL
;
5958 /* ORIGIN attribute: If at least one route among routes that are
5959 * aggregated has ORIGIN with the value INCOMPLETE, then the
5960 * aggregated route must have the ORIGIN attribute with the value
5961 * INCOMPLETE. Otherwise, if at least one route among routes that
5962 * are aggregated has ORIGIN with the value EGP, then the aggregated
5963 * route must have the origin attribute with the value EGP. In all
5964 * other case the value of the ORIGIN attribute of the aggregated
5965 * route is INTERNAL.
5967 origin
= BGP_ORIGIN_IGP
;
5971 if (aggregate
->summary_only
)
5972 (bgp_path_info_extra_get(pinew
))->suppress
++;
5974 switch (pinew
->attr
->origin
) {
5975 case BGP_ORIGIN_INCOMPLETE
:
5976 aggregate
->incomplete_origin_count
++;
5978 case BGP_ORIGIN_EGP
:
5979 aggregate
->egp_origin_count
++;
5987 if (aggregate
->incomplete_origin_count
> 0)
5988 origin
= BGP_ORIGIN_INCOMPLETE
;
5989 else if (aggregate
->egp_origin_count
> 0)
5990 origin
= BGP_ORIGIN_EGP
;
5992 if (aggregate
->as_set
) {
5993 /* Compute aggregate route's as-path.
5995 bgp_compute_aggregate_aspath(aggregate
,
5996 pinew
->attr
->aspath
);
5998 /* Compute aggregate route's community.
6000 if (pinew
->attr
->community
)
6001 bgp_compute_aggregate_community(
6003 pinew
->attr
->community
);
6005 /* Compute aggregate route's extended community.
6007 if (pinew
->attr
->ecommunity
)
6008 bgp_compute_aggregate_ecommunity(
6010 pinew
->attr
->ecommunity
);
6012 /* Compute aggregate route's large community.
6014 if (pinew
->attr
->lcommunity
)
6015 bgp_compute_aggregate_lcommunity(
6017 pinew
->attr
->lcommunity
);
6019 /* Retrieve aggregate route's as-path.
6021 if (aggregate
->aspath
)
6022 aspath
= aspath_dup(aggregate
->aspath
);
6024 /* Retrieve aggregate route's community.
6026 if (aggregate
->community
)
6027 community
= community_dup(aggregate
->community
);
6029 /* Retrieve aggregate route's ecommunity.
6031 if (aggregate
->ecommunity
)
6032 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
6034 /* Retrieve aggregate route's lcommunity.
6036 if (aggregate
->lcommunity
)
6037 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
6040 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
6041 aspath
, community
, ecommunity
,
6042 lcommunity
, atomic_aggregate
, aggregate
);
6045 static void bgp_remove_route_from_aggregate(struct bgp
*bgp
, afi_t afi
,
6047 struct bgp_path_info
*pi
,
6048 struct bgp_aggregate
*aggregate
,
6049 struct prefix
*aggr_p
)
6052 struct aspath
*aspath
= NULL
;
6053 uint8_t atomic_aggregate
= 0;
6054 struct community
*community
= NULL
;
6055 struct ecommunity
*ecommunity
= NULL
;
6056 struct lcommunity
*lcommunity
= NULL
;
6057 unsigned long match
= 0;
6059 if (BGP_PATH_HOLDDOWN(pi
))
6062 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6065 if (aggregate
->summary_only
6067 && pi
->extra
->suppress
> 0) {
6068 pi
->extra
->suppress
--;
6070 if (pi
->extra
->suppress
== 0) {
6071 bgp_path_info_set_flag(pi
->net
, pi
,
6072 BGP_PATH_ATTR_CHANGED
);
6077 if (aggregate
->count
> 0)
6080 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
6081 aggregate
->incomplete_origin_count
--;
6082 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
6083 aggregate
->egp_origin_count
--;
6085 if (aggregate
->as_set
) {
6086 /* Remove as-path from aggregate.
6088 bgp_remove_aspath_from_aggregate(aggregate
,
6091 if (pi
->attr
->community
)
6092 /* Remove community from aggregate.
6094 bgp_remove_community_from_aggregate(
6096 pi
->attr
->community
);
6098 if (pi
->attr
->ecommunity
)
6099 /* Remove ecommunity from aggregate.
6101 bgp_remove_ecommunity_from_aggregate(
6103 pi
->attr
->ecommunity
);
6105 if (pi
->attr
->lcommunity
)
6106 /* Remove lcommunity from aggregate.
6108 bgp_remove_lcommunity_from_aggregate(
6110 pi
->attr
->lcommunity
);
6113 /* If this node was suppressed, process the change. */
6115 bgp_process(bgp
, pi
->net
, afi
, safi
);
6117 origin
= BGP_ORIGIN_IGP
;
6118 if (aggregate
->incomplete_origin_count
> 0)
6119 origin
= BGP_ORIGIN_INCOMPLETE
;
6120 else if (aggregate
->egp_origin_count
> 0)
6121 origin
= BGP_ORIGIN_EGP
;
6123 if (aggregate
->as_set
) {
6124 /* Retrieve aggregate route's as-path.
6126 if (aggregate
->aspath
)
6127 aspath
= aspath_dup(aggregate
->aspath
);
6129 /* Retrieve aggregate route's community.
6131 if (aggregate
->community
)
6132 community
= community_dup(aggregate
->community
);
6134 /* Retrieve aggregate route's ecommunity.
6136 if (aggregate
->ecommunity
)
6137 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
6139 /* Retrieve aggregate route's lcommunity.
6141 if (aggregate
->lcommunity
)
6142 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
6145 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
6146 aspath
, community
, ecommunity
,
6147 lcommunity
, atomic_aggregate
, aggregate
);
6150 void bgp_aggregate_increment(struct bgp
*bgp
, struct prefix
*p
,
6151 struct bgp_path_info
*pi
, afi_t afi
, safi_t safi
)
6153 struct bgp_node
*child
;
6154 struct bgp_node
*rn
;
6155 struct bgp_aggregate
*aggregate
;
6156 struct bgp_table
*table
;
6158 table
= bgp
->aggregate
[afi
][safi
];
6160 /* No aggregates configured. */
6161 if (bgp_table_top_nolock(table
) == NULL
)
6164 if (p
->prefixlen
== 0)
6167 if (BGP_PATH_HOLDDOWN(pi
))
6170 child
= bgp_node_get(table
, p
);
6172 /* Aggregate address configuration check. */
6173 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
)) {
6174 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6175 if (aggregate
!= NULL
&& rn
->p
.prefixlen
< p
->prefixlen
) {
6176 bgp_add_route_to_aggregate(bgp
, &rn
->p
, pi
, afi
,
6180 bgp_unlock_node(child
);
6183 void bgp_aggregate_decrement(struct bgp
*bgp
, struct prefix
*p
,
6184 struct bgp_path_info
*del
, afi_t afi
, safi_t safi
)
6186 struct bgp_node
*child
;
6187 struct bgp_node
*rn
;
6188 struct bgp_aggregate
*aggregate
;
6189 struct bgp_table
*table
;
6191 table
= bgp
->aggregate
[afi
][safi
];
6193 /* No aggregates configured. */
6194 if (bgp_table_top_nolock(table
) == NULL
)
6197 if (p
->prefixlen
== 0)
6200 child
= bgp_node_get(table
, p
);
6202 /* Aggregate address configuration check. */
6203 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
)) {
6204 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6205 if (aggregate
!= NULL
&& rn
->p
.prefixlen
< p
->prefixlen
) {
6206 bgp_remove_route_from_aggregate(bgp
, afi
, safi
,
6207 del
, aggregate
, &rn
->p
);
6210 bgp_unlock_node(child
);
6213 /* Aggregate route attribute. */
6214 #define AGGREGATE_SUMMARY_ONLY 1
6215 #define AGGREGATE_AS_SET 1
6217 static int bgp_aggregate_unset(struct vty
*vty
, const char *prefix_str
,
6218 afi_t afi
, safi_t safi
)
6220 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6223 struct bgp_node
*rn
;
6224 struct bgp_aggregate
*aggregate
;
6226 /* Convert string to prefix structure. */
6227 ret
= str2prefix(prefix_str
, &p
);
6229 vty_out(vty
, "Malformed prefix\n");
6230 return CMD_WARNING_CONFIG_FAILED
;
6234 /* Old configuration check. */
6235 rn
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], &p
);
6238 "%% There is no aggregate-address configuration.\n");
6239 return CMD_WARNING_CONFIG_FAILED
;
6242 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6243 bgp_aggregate_delete(bgp
, &p
, afi
, safi
, aggregate
);
6244 bgp_aggregate_install(bgp
, afi
, safi
, &p
, 0, NULL
, NULL
,
6245 NULL
, NULL
, 0, aggregate
);
6247 /* Unlock aggregate address configuration. */
6248 bgp_node_set_bgp_aggregate_info(rn
, NULL
);
6250 if (aggregate
->community
)
6251 community_free(&aggregate
->community
);
6253 if (aggregate
->community_hash
) {
6254 /* Delete all communities in the hash.
6256 hash_clean(aggregate
->community_hash
,
6257 bgp_aggr_community_remove
);
6258 /* Free up the community_hash.
6260 hash_free(aggregate
->community_hash
);
6263 if (aggregate
->ecommunity
)
6264 ecommunity_free(&aggregate
->ecommunity
);
6266 if (aggregate
->ecommunity_hash
) {
6267 /* Delete all ecommunities in the hash.
6269 hash_clean(aggregate
->ecommunity_hash
,
6270 bgp_aggr_ecommunity_remove
);
6271 /* Free up the ecommunity_hash.
6273 hash_free(aggregate
->ecommunity_hash
);
6276 if (aggregate
->lcommunity
)
6277 lcommunity_free(&aggregate
->lcommunity
);
6279 if (aggregate
->lcommunity_hash
) {
6280 /* Delete all lcommunities in the hash.
6282 hash_clean(aggregate
->lcommunity_hash
,
6283 bgp_aggr_lcommunity_remove
);
6284 /* Free up the lcommunity_hash.
6286 hash_free(aggregate
->lcommunity_hash
);
6289 if (aggregate
->aspath
)
6290 aspath_free(aggregate
->aspath
);
6292 if (aggregate
->aspath_hash
) {
6293 /* Delete all as-paths in the hash.
6295 hash_clean(aggregate
->aspath_hash
,
6296 bgp_aggr_aspath_remove
);
6297 /* Free up the aspath_hash.
6299 hash_free(aggregate
->aspath_hash
);
6302 bgp_aggregate_free(aggregate
);
6303 bgp_unlock_node(rn
);
6304 bgp_unlock_node(rn
);
6309 static int bgp_aggregate_set(struct vty
*vty
, const char *prefix_str
, afi_t afi
,
6310 safi_t safi
, uint8_t summary_only
, uint8_t as_set
)
6312 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6315 struct bgp_node
*rn
;
6316 struct bgp_aggregate
*aggregate
;
6318 /* Convert string to prefix structure. */
6319 ret
= str2prefix(prefix_str
, &p
);
6321 vty_out(vty
, "Malformed prefix\n");
6322 return CMD_WARNING_CONFIG_FAILED
;
6326 if ((afi
== AFI_IP
&& p
.prefixlen
== IPV4_MAX_BITLEN
) ||
6327 (afi
== AFI_IP6
&& p
.prefixlen
== IPV6_MAX_BITLEN
)) {
6328 vty_out(vty
, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
6330 return CMD_WARNING_CONFIG_FAILED
;
6333 /* Old configuration check. */
6334 rn
= bgp_node_get(bgp
->aggregate
[afi
][safi
], &p
);
6336 if (bgp_node_has_bgp_path_info_data(rn
)) {
6337 vty_out(vty
, "There is already same aggregate network.\n");
6338 /* try to remove the old entry */
6339 ret
= bgp_aggregate_unset(vty
, prefix_str
, afi
, safi
);
6341 vty_out(vty
, "Error deleting aggregate.\n");
6342 bgp_unlock_node(rn
);
6343 return CMD_WARNING_CONFIG_FAILED
;
6347 /* Make aggregate address structure. */
6348 aggregate
= bgp_aggregate_new();
6349 aggregate
->summary_only
= summary_only
;
6350 aggregate
->as_set
= as_set
;
6351 aggregate
->safi
= safi
;
6352 bgp_node_set_bgp_aggregate_info(rn
, aggregate
);
6354 /* Aggregate address insert into BGP routing table. */
6355 bgp_aggregate_route(bgp
, &p
, afi
, safi
, aggregate
);
6360 DEFUN (aggregate_address
,
6361 aggregate_address_cmd
,
6362 "aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
6363 "Configure BGP aggregate entries\n"
6364 "Aggregate prefix\n"
6365 "Generate AS set path information\n"
6366 "Filter more specific routes from updates\n"
6367 "Filter more specific routes from updates\n"
6368 "Generate AS set path information\n")
6371 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
6372 char *prefix
= argv
[idx
]->arg
;
6374 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
6376 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6377 ? AGGREGATE_SUMMARY_ONLY
6380 return bgp_aggregate_set(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
),
6381 summary_only
, as_set
);
6384 DEFUN (aggregate_address_mask
,
6385 aggregate_address_mask_cmd
,
6386 "aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
6387 "Configure BGP aggregate entries\n"
6388 "Aggregate address\n"
6390 "Generate AS set path information\n"
6391 "Filter more specific routes from updates\n"
6392 "Filter more specific routes from updates\n"
6393 "Generate AS set path information\n")
6396 argv_find(argv
, argc
, "A.B.C.D", &idx
);
6397 char *prefix
= argv
[idx
]->arg
;
6398 char *mask
= argv
[idx
+ 1]->arg
;
6400 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
6402 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6403 ? AGGREGATE_SUMMARY_ONLY
6406 char prefix_str
[BUFSIZ
];
6407 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
6410 vty_out(vty
, "%% Inconsistent address and mask\n");
6411 return CMD_WARNING_CONFIG_FAILED
;
6414 return bgp_aggregate_set(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
),
6415 summary_only
, as_set
);
6418 DEFUN (no_aggregate_address
,
6419 no_aggregate_address_cmd
,
6420 "no aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
6422 "Configure BGP aggregate entries\n"
6423 "Aggregate prefix\n"
6424 "Generate AS set path information\n"
6425 "Filter more specific routes from updates\n"
6426 "Filter more specific routes from updates\n"
6427 "Generate AS set path information\n")
6430 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
6431 char *prefix
= argv
[idx
]->arg
;
6432 return bgp_aggregate_unset(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
));
6435 DEFUN (no_aggregate_address_mask
,
6436 no_aggregate_address_mask_cmd
,
6437 "no aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
6439 "Configure BGP aggregate entries\n"
6440 "Aggregate address\n"
6442 "Generate AS set path information\n"
6443 "Filter more specific routes from updates\n"
6444 "Filter more specific routes from updates\n"
6445 "Generate AS set path information\n")
6448 argv_find(argv
, argc
, "A.B.C.D", &idx
);
6449 char *prefix
= argv
[idx
]->arg
;
6450 char *mask
= argv
[idx
+ 1]->arg
;
6452 char prefix_str
[BUFSIZ
];
6453 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
6456 vty_out(vty
, "%% Inconsistent address and mask\n");
6457 return CMD_WARNING_CONFIG_FAILED
;
6460 return bgp_aggregate_unset(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
));
6463 DEFUN (ipv6_aggregate_address
,
6464 ipv6_aggregate_address_cmd
,
6465 "aggregate-address X:X::X:X/M [summary-only]",
6466 "Configure BGP aggregate entries\n"
6467 "Aggregate prefix\n"
6468 "Filter more specific routes from updates\n")
6471 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6472 char *prefix
= argv
[idx
]->arg
;
6473 int sum_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6474 ? AGGREGATE_SUMMARY_ONLY
6476 return bgp_aggregate_set(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
, sum_only
,
6480 DEFUN (no_ipv6_aggregate_address
,
6481 no_ipv6_aggregate_address_cmd
,
6482 "no aggregate-address X:X::X:X/M [summary-only]",
6484 "Configure BGP aggregate entries\n"
6485 "Aggregate prefix\n"
6486 "Filter more specific routes from updates\n")
6489 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6490 char *prefix
= argv
[idx
]->arg
;
6491 return bgp_aggregate_unset(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
);
6494 /* Redistribute route treatment. */
6495 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
6496 const union g_addr
*nexthop
, ifindex_t ifindex
,
6497 enum nexthop_types_t nhtype
, uint32_t metric
,
6498 uint8_t type
, unsigned short instance
,
6501 struct bgp_path_info
*new;
6502 struct bgp_path_info
*bpi
;
6503 struct bgp_path_info rmap_path
;
6504 struct bgp_node
*bn
;
6506 struct attr
*new_attr
;
6509 struct bgp_redist
*red
;
6511 /* Make default attribute. */
6512 bgp_attr_default_set(&attr
, BGP_ORIGIN_INCOMPLETE
);
6515 case NEXTHOP_TYPE_IFINDEX
:
6517 case NEXTHOP_TYPE_IPV4
:
6518 case NEXTHOP_TYPE_IPV4_IFINDEX
:
6519 attr
.nexthop
= nexthop
->ipv4
;
6521 case NEXTHOP_TYPE_IPV6
:
6522 case NEXTHOP_TYPE_IPV6_IFINDEX
:
6523 attr
.mp_nexthop_global
= nexthop
->ipv6
;
6524 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6526 case NEXTHOP_TYPE_BLACKHOLE
:
6527 switch (p
->family
) {
6529 attr
.nexthop
.s_addr
= INADDR_ANY
;
6532 memset(&attr
.mp_nexthop_global
, 0,
6533 sizeof(attr
.mp_nexthop_global
));
6534 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6539 attr
.nh_ifindex
= ifindex
;
6542 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6545 afi
= family2afi(p
->family
);
6547 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6549 struct attr attr_new
;
6551 /* Copy attribute for modification. */
6552 bgp_attr_dup(&attr_new
, &attr
);
6554 if (red
->redist_metric_flag
)
6555 attr_new
.med
= red
->redist_metric
;
6557 /* Apply route-map. */
6558 if (red
->rmap
.name
) {
6559 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
6560 rmap_path
.peer
= bgp
->peer_self
;
6561 rmap_path
.attr
= &attr_new
;
6563 SET_FLAG(bgp
->peer_self
->rmap_type
,
6564 PEER_RMAP_TYPE_REDISTRIBUTE
);
6566 ret
= route_map_apply(red
->rmap
.map
, p
, RMAP_BGP
,
6569 bgp
->peer_self
->rmap_type
= 0;
6571 if (ret
== RMAP_DENYMATCH
) {
6572 /* Free uninterned attribute. */
6573 bgp_attr_flush(&attr_new
);
6575 /* Unintern original. */
6576 aspath_unintern(&attr
.aspath
);
6577 bgp_redistribute_delete(bgp
, p
, type
, instance
);
6582 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
6583 bgp_attr_add_gshut_community(&attr_new
);
6585 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6586 SAFI_UNICAST
, p
, NULL
);
6588 new_attr
= bgp_attr_intern(&attr_new
);
6590 for (bpi
= bgp_node_get_bgp_path_info(bn
); bpi
;
6592 if (bpi
->peer
== bgp
->peer_self
6593 && bpi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
6597 /* Ensure the (source route) type is updated. */
6599 if (attrhash_cmp(bpi
->attr
, new_attr
)
6600 && !CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
)) {
6601 bgp_attr_unintern(&new_attr
);
6602 aspath_unintern(&attr
.aspath
);
6603 bgp_unlock_node(bn
);
6606 /* The attribute is changed. */
6607 bgp_path_info_set_flag(bn
, bpi
,
6608 BGP_PATH_ATTR_CHANGED
);
6610 /* Rewrite BGP route information. */
6611 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
6612 bgp_path_info_restore(bn
, bpi
);
6614 bgp_aggregate_decrement(
6615 bgp
, p
, bpi
, afi
, SAFI_UNICAST
);
6616 bgp_attr_unintern(&bpi
->attr
);
6617 bpi
->attr
= new_attr
;
6618 bpi
->uptime
= bgp_clock();
6620 /* Process change. */
6621 bgp_aggregate_increment(bgp
, p
, bpi
, afi
,
6623 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6624 bgp_unlock_node(bn
);
6625 aspath_unintern(&attr
.aspath
);
6627 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6629 == BGP_INSTANCE_TYPE_DEFAULT
)) {
6631 vpn_leak_from_vrf_update(
6632 bgp_get_default(), bgp
, bpi
);
6638 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
6639 bgp
->peer_self
, new_attr
, bn
);
6640 SET_FLAG(new->flags
, BGP_PATH_VALID
);
6642 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
6643 bgp_path_info_add(bn
, new);
6644 bgp_unlock_node(bn
);
6645 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6647 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6648 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6650 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
6654 /* Unintern original. */
6655 aspath_unintern(&attr
.aspath
);
6658 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, uint8_t type
,
6659 unsigned short instance
)
6662 struct bgp_node
*rn
;
6663 struct bgp_path_info
*pi
;
6664 struct bgp_redist
*red
;
6666 afi
= family2afi(p
->family
);
6668 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6670 rn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6671 SAFI_UNICAST
, p
, NULL
);
6673 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
6674 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
)
6678 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6679 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6681 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6684 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, SAFI_UNICAST
);
6685 bgp_path_info_delete(rn
, pi
);
6686 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6688 bgp_unlock_node(rn
);
6692 /* Withdraw specified route type's route. */
6693 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
6694 unsigned short instance
)
6696 struct bgp_node
*rn
;
6697 struct bgp_path_info
*pi
;
6698 struct bgp_table
*table
;
6700 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
6702 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
6703 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
6704 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
6705 && pi
->instance
== instance
)
6709 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6710 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6712 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6715 bgp_aggregate_decrement(bgp
, &rn
->p
, pi
, afi
,
6717 bgp_path_info_delete(rn
, pi
);
6718 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6723 /* Static function to display route. */
6724 static void route_vty_out_route(struct prefix
*p
, struct vty
*vty
,
6731 if (p
->family
== AF_INET
) {
6735 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
6738 json_object_string_add(json
, "prefix",
6739 inet_ntop(p
->family
,
6742 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
6743 prefix2str(p
, buf2
, PREFIX_STRLEN
);
6744 json_object_string_add(json
, "network", buf2
);
6746 } else if (p
->family
== AF_ETHERNET
) {
6747 prefix2str(p
, buf
, PREFIX_STRLEN
);
6748 len
= vty_out(vty
, "%s", buf
);
6749 } else if (p
->family
== AF_EVPN
) {
6753 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf
,
6756 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
6757 } else if (p
->family
== AF_FLOWSPEC
) {
6758 route_vty_out_flowspec(vty
, p
, NULL
,
6760 NLRI_STRING_FORMAT_JSON_SIMPLE
:
6761 NLRI_STRING_FORMAT_MIN
, json
);
6766 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
6769 json_object_string_add(json
, "prefix",
6770 inet_ntop(p
->family
,
6773 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
6774 prefix2str(p
, buf2
, PREFIX_STRLEN
);
6775 json_object_string_add(json
, "network", buf2
);
6782 vty_out(vty
, "\n%*s", 20, " ");
6784 vty_out(vty
, "%*s", len
, " ");
6788 enum bgp_display_type
{
6792 /* Print the short form route status for a bgp_path_info */
6793 static void route_vty_short_status_out(struct vty
*vty
,
6794 struct bgp_path_info
*path
,
6795 json_object
*json_path
)
6799 /* Route status display. */
6800 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
6801 json_object_boolean_true_add(json_path
, "removed");
6803 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
6804 json_object_boolean_true_add(json_path
, "stale");
6806 if (path
->extra
&& path
->extra
->suppress
)
6807 json_object_boolean_true_add(json_path
, "suppressed");
6809 if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
6810 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
6811 json_object_boolean_true_add(json_path
, "valid");
6814 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
6815 json_object_boolean_true_add(json_path
, "history");
6817 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
6818 json_object_boolean_true_add(json_path
, "damped");
6820 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
6821 json_object_boolean_true_add(json_path
, "bestpath");
6823 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
6824 json_object_boolean_true_add(json_path
, "multipath");
6826 /* Internal route. */
6827 if ((path
->peer
->as
)
6828 && (path
->peer
->as
== path
->peer
->local_as
))
6829 json_object_string_add(json_path
, "pathFrom",
6832 json_object_string_add(json_path
, "pathFrom",
6838 /* Route status display. */
6839 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
6841 else if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
6843 else if (path
->extra
&& path
->extra
->suppress
)
6845 else if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
6846 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
6852 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
6854 else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
6856 else if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
6858 else if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
6863 /* Internal route. */
6864 if (path
->peer
&& (path
->peer
->as
)
6865 && (path
->peer
->as
== path
->peer
->local_as
))
6871 static char *bgp_nexthop_fqdn(struct peer
*peer
)
6873 if (peer
->hostname
&& bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
))
6874 return peer
->hostname
;
6878 /* called from terminal list command */
6879 void route_vty_out(struct vty
*vty
, struct prefix
*p
,
6880 struct bgp_path_info
*path
, int display
, safi_t safi
,
6881 json_object
*json_paths
)
6884 json_object
*json_path
= NULL
;
6885 json_object
*json_nexthops
= NULL
;
6886 json_object
*json_nexthop_global
= NULL
;
6887 json_object
*json_nexthop_ll
= NULL
;
6888 char vrf_id_str
[VRF_NAMSIZ
] = {0};
6890 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
6891 bool nexthop_othervrf
= false;
6892 vrf_id_t nexthop_vrfid
= VRF_DEFAULT
;
6893 const char *nexthop_vrfname
= VRF_DEFAULT_NAME
;
6894 char *nexthop_fqdn
= bgp_nexthop_fqdn(path
->peer
);
6897 json_path
= json_object_new_object();
6899 /* short status lead text */
6900 route_vty_short_status_out(vty
, path
, json_path
);
6903 /* print prefix and mask */
6905 route_vty_out_route(p
, vty
, json_path
);
6907 vty_out(vty
, "%*s", 17, " ");
6909 route_vty_out_route(p
, vty
, json_path
);
6912 /* Print attribute */
6916 json_object_array_add(json_paths
, json_path
);
6924 * If vrf id of nexthop is different from that of prefix,
6925 * set up printable string to append
6927 if (path
->extra
&& path
->extra
->bgp_orig
) {
6928 const char *self
= "";
6933 nexthop_othervrf
= true;
6934 nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
6936 if (path
->extra
->bgp_orig
->vrf_id
== VRF_UNKNOWN
)
6937 snprintf(vrf_id_str
, sizeof(vrf_id_str
),
6938 "@%s%s", VRFID_NONE_STR
, self
);
6940 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "@%u%s",
6941 path
->extra
->bgp_orig
->vrf_id
, self
);
6943 if (path
->extra
->bgp_orig
->inst_type
6944 != BGP_INSTANCE_TYPE_DEFAULT
)
6946 nexthop_vrfname
= path
->extra
->bgp_orig
->name
;
6948 const char *self
= "";
6953 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "%s", self
);
6957 * For ENCAP and EVPN routes, nexthop address family is not
6958 * neccessarily the same as the prefix address family.
6959 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
6960 * EVPN routes are also exchanged with a MP nexthop. Currently,
6962 * is only IPv4, the value will be present in either
6964 * attr->mp_nexthop_global_in
6966 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
6969 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
6973 sprintf(nexthop
, "%s",
6974 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
6978 sprintf(nexthop
, "%s",
6979 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
6983 sprintf(nexthop
, "?");
6988 json_nexthop_global
= json_object_new_object();
6990 json_object_string_add(
6991 json_nexthop_global
, "afi",
6992 nexthop_fqdn
? "fqdn"
6993 : (af
== AF_INET
) ? "ip" : "ipv6");
6994 json_object_string_add(
6995 json_nexthop_global
,
6996 nexthop_fqdn
? "fqdn"
6997 : (af
== AF_INET
) ? "ip" : "ipv6",
6998 nexthop_fqdn
? nexthop_fqdn
: nexthop
);
6999 json_object_boolean_true_add(json_nexthop_global
,
7002 vty_out(vty
, "%s%s",
7003 nexthop_fqdn
? nexthop_fqdn
: nexthop
,
7005 } else if (safi
== SAFI_EVPN
) {
7007 json_nexthop_global
= json_object_new_object();
7009 json_object_string_add(
7010 json_nexthop_global
,
7011 nexthop_fqdn
? "fqdn" : "ip",
7012 nexthop_fqdn
? nexthop_fqdn
7013 : inet_ntoa(attr
->nexthop
));
7014 json_object_string_add(json_nexthop_global
, "afi",
7016 json_object_boolean_true_add(json_nexthop_global
,
7019 vty_out(vty
, "%-16s%s",
7020 nexthop_fqdn
?: inet_ntoa(attr
->nexthop
),
7022 } else if (safi
== SAFI_FLOWSPEC
) {
7023 if (attr
->nexthop
.s_addr
!= 0) {
7025 json_nexthop_global
= json_object_new_object();
7026 json_object_string_add(
7027 json_nexthop_global
,
7028 nexthop_fqdn
? "fqdn" : "ip",
7031 : inet_ntoa(attr
->nexthop
));
7032 json_object_string_add(json_nexthop_global
,
7034 json_object_boolean_true_add(
7035 json_nexthop_global
,
7038 vty_out(vty
, "%-16s",
7041 : inet_ntoa(attr
->nexthop
));
7044 } else if (p
->family
== AF_INET
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7046 json_nexthop_global
= json_object_new_object();
7048 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_EVPN
))
7049 json_object_string_add(
7050 json_nexthop_global
,
7051 nexthop_fqdn
? "fqdn" : "ip",
7055 attr
->mp_nexthop_global_in
));
7057 json_object_string_add(
7058 json_nexthop_global
,
7059 nexthop_fqdn
? "fqdn" : "ip",
7062 : inet_ntoa(attr
->nexthop
));
7064 json_object_string_add(json_nexthop_global
, "afi",
7066 json_object_boolean_true_add(json_nexthop_global
,
7071 snprintf(buf
, sizeof(buf
), "%s%s",
7072 nexthop_fqdn
? nexthop_fqdn
7073 : inet_ntoa(attr
->nexthop
),
7075 vty_out(vty
, "%-16s", buf
);
7080 else if (p
->family
== AF_INET6
|| BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7085 json_nexthop_global
= json_object_new_object();
7086 json_object_string_add(
7087 json_nexthop_global
,
7088 nexthop_fqdn
? "fqdn" : "ip",
7091 : inet_ntop(AF_INET6
,
7092 &attr
->mp_nexthop_global
,
7094 json_object_string_add(json_nexthop_global
, "afi",
7096 json_object_string_add(json_nexthop_global
, "scope",
7099 /* We display both LL & GL if both have been
7101 if ((attr
->mp_nexthop_len
== 32)
7102 || (path
->peer
->conf_if
)) {
7103 json_nexthop_ll
= json_object_new_object();
7104 json_object_string_add(
7106 nexthop_fqdn
? "fqdn" : "ip",
7111 &attr
->mp_nexthop_local
,
7113 json_object_string_add(json_nexthop_ll
, "afi",
7115 json_object_string_add(json_nexthop_ll
, "scope",
7118 if ((IPV6_ADDR_CMP(&attr
->mp_nexthop_global
,
7119 &attr
->mp_nexthop_local
)
7121 && !attr
->mp_nexthop_prefer_global
)
7122 json_object_boolean_true_add(
7123 json_nexthop_ll
, "used");
7125 json_object_boolean_true_add(
7126 json_nexthop_global
, "used");
7128 json_object_boolean_true_add(
7129 json_nexthop_global
, "used");
7131 /* Display LL if LL/Global both in table unless
7132 * prefer-global is set */
7133 if (((attr
->mp_nexthop_len
== 32)
7134 && !attr
->mp_nexthop_prefer_global
)
7135 || (path
->peer
->conf_if
)) {
7136 if (path
->peer
->conf_if
) {
7137 len
= vty_out(vty
, "%s",
7138 path
->peer
->conf_if
);
7139 len
= 16 - len
; /* len of IPv6
7145 vty_out(vty
, "\n%*s", 36, " ");
7147 vty_out(vty
, "%*s", len
, " ");
7155 &attr
->mp_nexthop_local
,
7161 vty_out(vty
, "\n%*s", 36, " ");
7163 vty_out(vty
, "%*s", len
, " ");
7172 &attr
->mp_nexthop_global
,
7178 vty_out(vty
, "\n%*s", 36, " ");
7180 vty_out(vty
, "%*s", len
, " ");
7186 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
7190 * Adding "metric" field to match with corresponding
7191 * CLI. "med" will be deprecated in future.
7193 json_object_int_add(json_path
, "med", attr
->med
);
7194 json_object_int_add(json_path
, "metric", attr
->med
);
7196 vty_out(vty
, "%10u", attr
->med
);
7197 else if (!json_paths
)
7201 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
7205 * Adding "locPrf" field to match with corresponding
7206 * CLI. "localPref" will be deprecated in future.
7208 json_object_int_add(json_path
, "localpref",
7210 json_object_int_add(json_path
, "locPrf",
7213 vty_out(vty
, "%7u", attr
->local_pref
);
7214 else if (!json_paths
)
7218 json_object_int_add(json_path
, "weight", attr
->weight
);
7220 vty_out(vty
, "%7u ", attr
->weight
);
7224 json_object_string_add(
7225 json_path
, "peerId",
7226 sockunion2str(&path
->peer
->su
, buf
, SU_ADDRSTRLEN
));
7234 * Adding "path" field to match with corresponding
7235 * CLI. "aspath" will be deprecated in future.
7237 json_object_string_add(json_path
, "aspath",
7239 json_object_string_add(json_path
, "path",
7242 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7247 json_object_string_add(json_path
, "origin",
7248 bgp_origin_long_str
[attr
->origin
]);
7250 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7254 json_object_boolean_true_add(json_path
,
7255 "announceNexthopSelf");
7256 if (nexthop_othervrf
) {
7257 json_object_string_add(json_path
, "nhVrfName",
7260 json_object_int_add(json_path
, "nhVrfId",
7261 ((nexthop_vrfid
== VRF_UNKNOWN
)
7263 : (int)nexthop_vrfid
));
7268 if (json_nexthop_global
|| json_nexthop_ll
) {
7269 json_nexthops
= json_object_new_array();
7271 if (json_nexthop_global
)
7272 json_object_array_add(json_nexthops
,
7273 json_nexthop_global
);
7275 if (json_nexthop_ll
)
7276 json_object_array_add(json_nexthops
,
7279 json_object_object_add(json_path
, "nexthops",
7283 json_object_array_add(json_paths
, json_path
);
7287 /* prints an additional line, indented, with VNC info, if
7289 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
7290 rfapi_vty_out_vncinfo(vty
, p
, path
, safi
);
7295 /* called from terminal list command */
7296 void route_vty_out_tmp(struct vty
*vty
, struct prefix
*p
, struct attr
*attr
,
7297 safi_t safi
, bool use_json
, json_object
*json_ar
)
7299 json_object
*json_status
= NULL
;
7300 json_object
*json_net
= NULL
;
7303 /* Route status display. */
7305 json_status
= json_object_new_object();
7306 json_net
= json_object_new_object();
7313 /* print prefix and mask */
7315 json_object_string_add(
7316 json_net
, "addrPrefix",
7317 inet_ntop(p
->family
, &p
->u
.prefix
, buff
, BUFSIZ
));
7318 json_object_int_add(json_net
, "prefixLen", p
->prefixlen
);
7319 prefix2str(p
, buf2
, PREFIX_STRLEN
);
7320 json_object_string_add(json_net
, "network", buf2
);
7322 route_vty_out_route(p
, vty
, NULL
);
7324 /* Print attribute */
7327 if (p
->family
== AF_INET
7328 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7329 || safi
== SAFI_EVPN
7330 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7331 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7332 || safi
== SAFI_EVPN
)
7333 json_object_string_add(
7334 json_net
, "nextHop",
7336 attr
->mp_nexthop_global_in
));
7338 json_object_string_add(
7339 json_net
, "nextHop",
7340 inet_ntoa(attr
->nexthop
));
7341 } else if (p
->family
== AF_INET6
7342 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7345 json_object_string_add(
7346 json_net
, "nextHopGlobal",
7348 &attr
->mp_nexthop_global
, buf
,
7353 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
7354 json_object_int_add(json_net
, "metric",
7357 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
7360 * Adding "locPrf" field to match with
7361 * corresponding CLI. "localPref" will be
7362 * deprecated in future.
7364 json_object_int_add(json_net
, "localPref",
7366 json_object_int_add(json_net
, "locPrf",
7370 json_object_int_add(json_net
, "weight", attr
->weight
);
7376 * Adding "path" field to match with
7377 * corresponding CLI. "localPref" will be
7378 * deprecated in future.
7380 json_object_string_add(json_net
, "asPath",
7382 json_object_string_add(json_net
, "path",
7387 json_object_string_add(json_net
, "bgpOriginCode",
7388 bgp_origin_str
[attr
->origin
]);
7390 if (p
->family
== AF_INET
7391 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7392 || safi
== SAFI_EVPN
7393 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7394 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7395 || safi
== SAFI_EVPN
)
7396 vty_out(vty
, "%-16s",
7398 attr
->mp_nexthop_global_in
));
7400 vty_out(vty
, "%-16s",
7401 inet_ntoa(attr
->nexthop
));
7402 } else if (p
->family
== AF_INET6
7403 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7410 &attr
->mp_nexthop_global
, buf
,
7414 vty_out(vty
, "\n%*s", 36, " ");
7416 vty_out(vty
, "%*s", len
, " ");
7419 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
7420 vty_out(vty
, "%10u", attr
->med
);
7424 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
7425 vty_out(vty
, "%7u", attr
->local_pref
);
7429 vty_out(vty
, "%7u ", attr
->weight
);
7433 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7436 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7440 json_object_boolean_true_add(json_status
, "*");
7441 json_object_boolean_true_add(json_status
, ">");
7442 json_object_object_add(json_net
, "appliedStatusSymbols",
7444 char buf_cut
[BUFSIZ
];
7445 json_object_object_add(
7447 inet_ntop(p
->family
, &p
->u
.prefix
, buf_cut
, BUFSIZ
),
7453 void route_vty_out_tag(struct vty
*vty
, struct prefix
*p
,
7454 struct bgp_path_info
*path
, int display
, safi_t safi
,
7457 json_object
*json_out
= NULL
;
7459 mpls_label_t label
= MPLS_INVALID_LABEL
;
7465 json_out
= json_object_new_object();
7467 /* short status lead text */
7468 route_vty_short_status_out(vty
, path
, json_out
);
7470 /* print prefix and mask */
7473 route_vty_out_route(p
, vty
, NULL
);
7475 vty_out(vty
, "%*s", 17, " ");
7478 /* Print attribute */
7481 if (((p
->family
== AF_INET
)
7482 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
7483 || (safi
== SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
7484 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7485 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7486 || safi
== SAFI_EVPN
) {
7488 json_object_string_add(
7489 json_out
, "mpNexthopGlobalIn",
7491 attr
->mp_nexthop_global_in
));
7493 vty_out(vty
, "%-16s",
7495 attr
->mp_nexthop_global_in
));
7498 json_object_string_add(
7499 json_out
, "nexthop",
7500 inet_ntoa(attr
->nexthop
));
7502 vty_out(vty
, "%-16s",
7503 inet_ntoa(attr
->nexthop
));
7505 } else if (((p
->family
== AF_INET6
)
7506 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
7507 || (safi
== SAFI_EVPN
7508 && BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
7509 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7513 if (attr
->mp_nexthop_len
7514 == BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
7516 json_object_string_add(
7517 json_out
, "mpNexthopGlobalIn",
7520 &attr
->mp_nexthop_global
,
7521 buf_a
, sizeof(buf_a
)));
7526 &attr
->mp_nexthop_global
,
7527 buf_a
, sizeof(buf_a
)));
7528 } else if (attr
->mp_nexthop_len
7529 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
7532 &attr
->mp_nexthop_global
,
7533 buf_a
, sizeof(buf_a
));
7535 &attr
->mp_nexthop_local
,
7536 buf_b
, sizeof(buf_b
));
7537 sprintf(buf_c
, "%s(%s)", buf_a
, buf_b
);
7538 json_object_string_add(
7540 "mpNexthopGlobalLocal", buf_c
);
7542 vty_out(vty
, "%s(%s)",
7545 &attr
->mp_nexthop_global
,
7546 buf_a
, sizeof(buf_a
)),
7549 &attr
->mp_nexthop_local
,
7550 buf_b
, sizeof(buf_b
)));
7555 label
= decode_label(&path
->extra
->label
[0]);
7557 if (bgp_is_valid_label(&label
)) {
7559 json_object_int_add(json_out
, "notag", label
);
7560 json_object_array_add(json
, json_out
);
7562 vty_out(vty
, "notag/%d", label
);
7568 void route_vty_out_overlay(struct vty
*vty
, struct prefix
*p
,
7569 struct bgp_path_info
*path
, int display
,
7570 json_object
*json_paths
)
7574 json_object
*json_path
= NULL
;
7577 json_path
= json_object_new_object();
7582 /* short status lead text */
7583 route_vty_short_status_out(vty
, path
, json_path
);
7585 /* print prefix and mask */
7587 route_vty_out_route(p
, vty
, NULL
);
7589 vty_out(vty
, "%*s", 17, " ");
7591 /* Print attribute */
7595 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
7599 vty_out(vty
, "%-16s",
7600 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
7604 vty_out(vty
, "%s(%s)",
7605 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
7607 inet_ntop(af
, &attr
->mp_nexthop_local
, buf1
,
7614 char *str
= esi2str(&(attr
->evpn_overlay
.eth_s_id
));
7616 vty_out(vty
, "%s", str
);
7617 XFREE(MTYPE_TMP
, str
);
7619 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn
*)p
)) {
7621 inet_ntoa(attr
->evpn_overlay
.gw_ip
.ipv4
));
7622 } else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn
*)p
)) {
7625 &(attr
->evpn_overlay
.gw_ip
.ipv6
), buf
,
7628 if (attr
->ecommunity
) {
7630 struct ecommunity_val
*routermac
= ecommunity_lookup(
7631 attr
->ecommunity
, ECOMMUNITY_ENCODE_EVPN
,
7632 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
7634 mac
= ecom_mac2str((char *)routermac
->val
);
7636 vty_out(vty
, "/%s", (char *)mac
);
7637 XFREE(MTYPE_TMP
, mac
);
7645 /* dampening route */
7646 static void damp_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7647 struct bgp_path_info
*path
, int display
,
7648 safi_t safi
, bool use_json
, json_object
*json
)
7652 char timebuf
[BGP_UPTIME_LEN
];
7654 /* short status lead text */
7655 route_vty_short_status_out(vty
, path
, json
);
7657 /* print prefix and mask */
7660 route_vty_out_route(p
, vty
, NULL
);
7662 vty_out(vty
, "%*s", 17, " ");
7665 len
= vty_out(vty
, "%s", path
->peer
->host
);
7669 vty_out(vty
, "\n%*s", 34, " ");
7672 json_object_int_add(json
, "peerHost", len
);
7674 vty_out(vty
, "%*s", len
, " ");
7678 bgp_damp_reuse_time_vty(vty
, path
, timebuf
, BGP_UPTIME_LEN
,
7682 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
7683 BGP_UPTIME_LEN
, use_json
,
7686 /* Print attribute */
7692 json_object_string_add(json
, "asPath",
7695 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7700 json_object_string_add(json
, "origin",
7701 bgp_origin_str
[attr
->origin
]);
7703 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7710 static void flap_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7711 struct bgp_path_info
*path
, int display
,
7712 safi_t safi
, bool use_json
, json_object
*json
)
7715 struct bgp_damp_info
*bdi
;
7716 char timebuf
[BGP_UPTIME_LEN
];
7722 bdi
= path
->extra
->damp_info
;
7724 /* short status lead text */
7725 route_vty_short_status_out(vty
, path
, json
);
7727 /* print prefix and mask */
7730 route_vty_out_route(p
, vty
, NULL
);
7732 vty_out(vty
, "%*s", 17, " ");
7735 len
= vty_out(vty
, "%s", path
->peer
->host
);
7739 vty_out(vty
, "\n%*s", 33, " ");
7742 json_object_int_add(json
, "peerHost", len
);
7744 vty_out(vty
, "%*s", len
, " ");
7747 len
= vty_out(vty
, "%d", bdi
->flap
);
7754 json_object_int_add(json
, "bdiFlap", len
);
7756 vty_out(vty
, "%*s", len
, " ");
7760 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
7763 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
7764 BGP_UPTIME_LEN
, 0, NULL
));
7766 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
7767 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
7769 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
7770 BGP_UPTIME_LEN
, use_json
, json
);
7773 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
7778 vty_out(vty
, "%*s ", 8, " ");
7781 /* Print attribute */
7787 json_object_string_add(json
, "asPath",
7790 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7795 json_object_string_add(json
, "origin",
7796 bgp_origin_str
[attr
->origin
]);
7798 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7804 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
7805 int *first
, const char *header
,
7806 json_object
*json_adv_to
)
7808 char buf1
[INET6_ADDRSTRLEN
];
7809 json_object
*json_peer
= NULL
;
7812 /* 'advertised-to' is a dictionary of peers we have advertised
7814 * prefix too. The key is the peer's IP or swpX, the value is
7816 * hostname if we know it and "" if not.
7818 json_peer
= json_object_new_object();
7821 json_object_string_add(json_peer
, "hostname",
7825 json_object_object_add(json_adv_to
, peer
->conf_if
,
7828 json_object_object_add(
7830 sockunion2str(&peer
->su
, buf1
, SU_ADDRSTRLEN
),
7834 vty_out(vty
, "%s", header
);
7839 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
7841 vty_out(vty
, " %s(%s)", peer
->hostname
,
7844 vty_out(vty
, " %s(%s)", peer
->hostname
,
7845 sockunion2str(&peer
->su
, buf1
,
7849 vty_out(vty
, " %s", peer
->conf_if
);
7852 sockunion2str(&peer
->su
, buf1
,
7858 static void route_vty_out_tx_ids(struct vty
*vty
,
7859 struct bgp_addpath_info_data
*d
)
7863 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
7864 vty_out(vty
, "TX-%s %u%s", bgp_addpath_names(i
)->human_name
,
7865 d
->addpath_tx_id
[i
],
7866 i
< BGP_ADDPATH_MAX
- 1 ? " " : "\n");
7870 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
, struct prefix
*p
,
7871 struct bgp_path_info
*path
, afi_t afi
, safi_t safi
,
7872 json_object
*json_paths
)
7874 char buf
[INET6_ADDRSTRLEN
];
7876 char buf2
[EVPN_ROUTE_STRLEN
];
7878 int sockunion_vty_out(struct vty
*, union sockunion
*);
7880 json_object
*json_bestpath
= NULL
;
7881 json_object
*json_cluster_list
= NULL
;
7882 json_object
*json_cluster_list_list
= NULL
;
7883 json_object
*json_ext_community
= NULL
;
7884 json_object
*json_last_update
= NULL
;
7885 json_object
*json_pmsi
= NULL
;
7886 json_object
*json_nexthop_global
= NULL
;
7887 json_object
*json_nexthop_ll
= NULL
;
7888 json_object
*json_nexthops
= NULL
;
7889 json_object
*json_path
= NULL
;
7890 json_object
*json_peer
= NULL
;
7891 json_object
*json_string
= NULL
;
7892 json_object
*json_adv_to
= NULL
;
7894 struct listnode
*node
, *nnode
;
7896 int addpath_capable
;
7898 unsigned int first_as
;
7900 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
7902 char *nexthop_fqdn
= bgp_nexthop_fqdn(path
->peer
);
7905 json_path
= json_object_new_object();
7906 json_peer
= json_object_new_object();
7907 json_nexthop_global
= json_object_new_object();
7910 if (!json_paths
&& safi
== SAFI_EVPN
) {
7913 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf2
, sizeof(buf2
));
7914 vty_out(vty
, " Route %s", buf2
);
7916 if (path
->extra
&& path
->extra
->num_labels
) {
7917 bgp_evpn_label2str(path
->extra
->label
,
7918 path
->extra
->num_labels
, tag_buf
,
7920 vty_out(vty
, " VNI %s", tag_buf
);
7923 if (path
->extra
&& path
->extra
->parent
) {
7924 struct bgp_path_info
*parent_ri
;
7925 struct bgp_node
*rn
, *prn
;
7927 parent_ri
= (struct bgp_path_info
*)path
->extra
->parent
;
7928 rn
= parent_ri
->net
;
7929 if (rn
&& rn
->prn
) {
7931 vty_out(vty
, " Imported from %s:%s\n",
7933 (struct prefix_rd
*)&prn
->p
,
7934 buf1
, sizeof(buf1
)),
7943 /* Line1 display AS-path, Aggregator */
7946 if (!attr
->aspath
->json
)
7947 aspath_str_update(attr
->aspath
, true);
7948 json_object_lock(attr
->aspath
->json
);
7949 json_object_object_add(json_path
, "aspath",
7950 attr
->aspath
->json
);
7952 if (attr
->aspath
->segments
)
7953 aspath_print_vty(vty
, " %s",
7956 vty_out(vty
, " Local");
7960 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
)) {
7962 json_object_boolean_true_add(json_path
,
7965 vty_out(vty
, ", (removed)");
7968 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
7970 json_object_boolean_true_add(json_path
,
7973 vty_out(vty
, ", (stale)");
7976 if (CHECK_FLAG(attr
->flag
,
7977 ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
7979 json_object_int_add(json_path
, "aggregatorAs",
7980 attr
->aggregator_as
);
7981 json_object_string_add(
7982 json_path
, "aggregatorId",
7983 inet_ntoa(attr
->aggregator_addr
));
7985 vty_out(vty
, ", (aggregated by %u %s)",
7986 attr
->aggregator_as
,
7987 inet_ntoa(attr
->aggregator_addr
));
7991 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
7992 PEER_FLAG_REFLECTOR_CLIENT
)) {
7994 json_object_boolean_true_add(
7995 json_path
, "rxedFromRrClient");
7997 vty_out(vty
, ", (Received from a RR-client)");
8000 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
8001 PEER_FLAG_RSERVER_CLIENT
)) {
8003 json_object_boolean_true_add(
8004 json_path
, "rxedFromRsClient");
8006 vty_out(vty
, ", (Received from a RS-client)");
8009 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
8011 json_object_boolean_true_add(
8012 json_path
, "dampeningHistoryEntry");
8014 vty_out(vty
, ", (history entry)");
8015 } else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)) {
8017 json_object_boolean_true_add(
8018 json_path
, "dampeningSuppressed");
8020 vty_out(vty
, ", (suppressed due to dampening)");
8026 /* Line2 display Next-hop, Neighbor, Router-id */
8027 /* Display the nexthop */
8028 if ((p
->family
== AF_INET
|| p
->family
== AF_ETHERNET
8029 || p
->family
== AF_EVPN
)
8030 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
8031 || safi
== SAFI_EVPN
8032 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
8033 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
8034 || safi
== SAFI_EVPN
) {
8036 json_object_string_add(
8037 json_nexthop_global
,
8038 nexthop_fqdn
? "fqdn" : "ip",
8042 attr
->mp_nexthop_global_in
));
8048 attr
->mp_nexthop_global_in
));
8051 json_object_string_add(
8052 json_nexthop_global
,
8053 nexthop_fqdn
? "fqdn" : "ip",
8067 json_object_string_add(json_nexthop_global
,
8071 json_object_string_add(
8072 json_nexthop_global
,
8073 nexthop_fqdn
? "fqdn" : "ip",
8078 &attr
->mp_nexthop_global
,
8081 json_object_string_add(json_nexthop_global
,
8083 json_object_string_add(json_nexthop_global
,
8091 &attr
->mp_nexthop_global
,
8097 /* Display the IGP cost or 'inaccessible' */
8098 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
8100 json_object_boolean_false_add(
8101 json_nexthop_global
, "accessible");
8103 vty_out(vty
, " (inaccessible)");
8105 if (path
->extra
&& path
->extra
->igpmetric
) {
8107 json_object_int_add(
8108 json_nexthop_global
, "metric",
8109 path
->extra
->igpmetric
);
8111 vty_out(vty
, " (metric %u)",
8112 path
->extra
->igpmetric
);
8115 /* IGP cost is 0, display this only for json */
8118 json_object_int_add(json_nexthop_global
,
8123 json_object_boolean_true_add(
8124 json_nexthop_global
, "accessible");
8127 /* Display peer "from" output */
8128 /* This path was originated locally */
8129 if (path
->peer
== bgp
->peer_self
) {
8131 if (safi
== SAFI_EVPN
8132 || (p
->family
== AF_INET
8133 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
8135 json_object_string_add(
8136 json_peer
, "peerId", "0.0.0.0");
8138 vty_out(vty
, " from 0.0.0.0 ");
8141 json_object_string_add(json_peer
,
8144 vty_out(vty
, " from :: ");
8148 json_object_string_add(
8149 json_peer
, "routerId",
8150 inet_ntoa(bgp
->router_id
));
8152 vty_out(vty
, "(%s)", inet_ntoa(bgp
->router_id
));
8155 /* We RXed this path from one of our peers */
8159 json_object_string_add(
8160 json_peer
, "peerId",
8161 sockunion2str(&path
->peer
->su
, buf
,
8163 json_object_string_add(
8164 json_peer
, "routerId",
8166 &path
->peer
->remote_id
, buf1
,
8169 if (path
->peer
->hostname
)
8170 json_object_string_add(
8171 json_peer
, "hostname",
8172 path
->peer
->hostname
);
8174 if (path
->peer
->domainname
)
8175 json_object_string_add(
8176 json_peer
, "domainname",
8177 path
->peer
->domainname
);
8179 if (path
->peer
->conf_if
)
8180 json_object_string_add(
8181 json_peer
, "interface",
8182 path
->peer
->conf_if
);
8184 if (path
->peer
->conf_if
) {
8185 if (path
->peer
->hostname
8188 BGP_FLAG_SHOW_HOSTNAME
))
8189 vty_out(vty
, " from %s(%s)",
8190 path
->peer
->hostname
,
8191 path
->peer
->conf_if
);
8193 vty_out(vty
, " from %s",
8194 path
->peer
->conf_if
);
8196 if (path
->peer
->hostname
8199 BGP_FLAG_SHOW_HOSTNAME
))
8200 vty_out(vty
, " from %s(%s)",
8201 path
->peer
->hostname
,
8204 vty_out(vty
, " from %s",
8212 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
8213 vty_out(vty
, " (%s)",
8214 inet_ntoa(attr
->originator_id
));
8216 vty_out(vty
, " (%s)",
8219 &path
->peer
->remote_id
,
8220 buf1
, sizeof(buf1
)));
8225 * Note when vrfid of nexthop is different from that of prefix
8227 if (path
->extra
&& path
->extra
->bgp_orig
) {
8228 vrf_id_t nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
8233 if (path
->extra
->bgp_orig
->inst_type
8234 == BGP_INSTANCE_TYPE_DEFAULT
)
8236 vn
= VRF_DEFAULT_NAME
;
8238 vn
= path
->extra
->bgp_orig
->name
;
8240 json_object_string_add(json_path
, "nhVrfName",
8243 if (nexthop_vrfid
== VRF_UNKNOWN
) {
8244 json_object_int_add(json_path
,
8247 json_object_int_add(json_path
,
8248 "nhVrfId", (int)nexthop_vrfid
);
8251 if (nexthop_vrfid
== VRF_UNKNOWN
)
8252 vty_out(vty
, " vrf ?");
8254 vty_out(vty
, " vrf %u", nexthop_vrfid
);
8260 json_object_boolean_true_add(json_path
,
8261 "announceNexthopSelf");
8263 vty_out(vty
, " announce-nh-self");
8270 /* display the link-local nexthop */
8271 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
8273 json_nexthop_ll
= json_object_new_object();
8274 json_object_string_add(
8276 nexthop_fqdn
? "fqdn" : "ip",
8281 &attr
->mp_nexthop_local
,
8284 json_object_string_add(json_nexthop_ll
, "afi",
8286 json_object_string_add(json_nexthop_ll
, "scope",
8289 json_object_boolean_true_add(json_nexthop_ll
,
8292 if (!attr
->mp_nexthop_prefer_global
)
8293 json_object_boolean_true_add(
8294 json_nexthop_ll
, "used");
8296 json_object_boolean_true_add(
8297 json_nexthop_global
, "used");
8299 vty_out(vty
, " (%s) %s\n",
8301 &attr
->mp_nexthop_local
, buf
,
8303 attr
->mp_nexthop_prefer_global
8308 /* If we do not have a link-local nexthop then we must flag the
8312 json_object_boolean_true_add(
8313 json_nexthop_global
, "used");
8316 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
8317 * Int/Ext/Local, Atomic, best */
8319 json_object_string_add(
8320 json_path
, "origin",
8321 bgp_origin_long_str
[attr
->origin
]);
8323 vty_out(vty
, " Origin %s",
8324 bgp_origin_long_str
[attr
->origin
]);
8326 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
8330 * Adding "metric" field to match with
8331 * corresponding CLI. "med" will be
8332 * deprecated in future.
8334 json_object_int_add(json_path
, "med",
8336 json_object_int_add(json_path
, "metric",
8339 vty_out(vty
, ", metric %u", attr
->med
);
8342 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
8344 json_object_int_add(json_path
, "localpref",
8347 vty_out(vty
, ", localpref %u",
8351 if (attr
->weight
!= 0) {
8353 json_object_int_add(json_path
, "weight",
8356 vty_out(vty
, ", weight %u", attr
->weight
);
8359 if (attr
->tag
!= 0) {
8361 json_object_int_add(json_path
, "tag",
8364 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
,
8368 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
8370 json_object_boolean_false_add(json_path
,
8373 vty_out(vty
, ", invalid");
8374 } else if (!CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
8376 json_object_boolean_true_add(json_path
,
8379 vty_out(vty
, ", valid");
8382 if (path
->peer
!= bgp
->peer_self
) {
8383 if (path
->peer
->as
== path
->peer
->local_as
) {
8384 if (CHECK_FLAG(bgp
->config
,
8385 BGP_CONFIG_CONFEDERATION
)) {
8387 json_object_string_add(
8392 ", confed-internal");
8395 json_object_string_add(
8399 vty_out(vty
, ", internal");
8402 if (bgp_confederation_peers_check(
8403 bgp
, path
->peer
->as
)) {
8405 json_object_string_add(
8410 ", confed-external");
8413 json_object_string_add(
8417 vty_out(vty
, ", external");
8420 } else if (path
->sub_type
== BGP_ROUTE_AGGREGATE
) {
8422 json_object_boolean_true_add(json_path
,
8424 json_object_boolean_true_add(json_path
,
8427 vty_out(vty
, ", aggregated, local");
8429 } else if (path
->type
!= ZEBRA_ROUTE_BGP
) {
8431 json_object_boolean_true_add(json_path
,
8434 vty_out(vty
, ", sourced");
8437 json_object_boolean_true_add(json_path
,
8439 json_object_boolean_true_add(json_path
,
8442 vty_out(vty
, ", sourced, local");
8446 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
8448 json_object_boolean_true_add(json_path
,
8451 vty_out(vty
, ", atomic-aggregate");
8454 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
)
8455 || (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)
8456 && bgp_path_info_mpath_count(path
))) {
8458 json_object_boolean_true_add(json_path
,
8461 vty_out(vty
, ", multipath");
8464 // Mark the bestpath(s)
8465 if (CHECK_FLAG(path
->flags
, BGP_PATH_DMED_SELECTED
)) {
8466 first_as
= aspath_get_first_as(attr
->aspath
);
8471 json_object_new_object();
8472 json_object_int_add(json_bestpath
,
8473 "bestpathFromAs", first_as
);
8476 vty_out(vty
, ", bestpath-from-AS %u",
8480 ", bestpath-from-AS Local");
8484 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
8488 json_object_new_object();
8489 json_object_boolean_true_add(json_bestpath
,
8492 vty_out(vty
, ", best");
8496 json_object_object_add(json_path
, "bestpath",
8502 /* Line 4 display Community */
8503 if (attr
->community
) {
8505 if (!attr
->community
->json
)
8506 community_str(attr
->community
, true);
8507 json_object_lock(attr
->community
->json
);
8508 json_object_object_add(json_path
, "community",
8509 attr
->community
->json
);
8511 vty_out(vty
, " Community: %s\n",
8512 attr
->community
->str
);
8516 /* Line 5 display Extended-community */
8517 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
8519 json_ext_community
= json_object_new_object();
8520 json_object_string_add(json_ext_community
,
8522 attr
->ecommunity
->str
);
8523 json_object_object_add(json_path
,
8524 "extendedCommunity",
8525 json_ext_community
);
8527 vty_out(vty
, " Extended Community: %s\n",
8528 attr
->ecommunity
->str
);
8532 /* Line 6 display Large community */
8533 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
8535 if (!attr
->lcommunity
->json
)
8536 lcommunity_str(attr
->lcommunity
, true);
8537 json_object_lock(attr
->lcommunity
->json
);
8538 json_object_object_add(json_path
,
8540 attr
->lcommunity
->json
);
8542 vty_out(vty
, " Large Community: %s\n",
8543 attr
->lcommunity
->str
);
8547 /* Line 7 display Originator, Cluster-id */
8548 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
8549 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
8551 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
8553 json_object_string_add(
8554 json_path
, "originatorId",
8555 inet_ntoa(attr
->originator_id
));
8557 vty_out(vty
, " Originator: %s",
8558 inet_ntoa(attr
->originator_id
));
8561 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
8566 json_object_new_object();
8567 json_cluster_list_list
=
8568 json_object_new_array();
8571 i
< attr
->cluster
->length
/ 4;
8573 json_string
= json_object_new_string(
8577 json_object_array_add(
8578 json_cluster_list_list
,
8582 /* struct cluster_list does not have
8584 * aspath and community do. Add this
8587 json_object_string_add(json_cluster_list,
8588 "string", attr->cluster->str);
8590 json_object_object_add(
8591 json_cluster_list
, "list",
8592 json_cluster_list_list
);
8593 json_object_object_add(
8594 json_path
, "clusterList",
8597 vty_out(vty
, ", Cluster list: ");
8600 i
< attr
->cluster
->length
/ 4;
8614 if (path
->extra
&& path
->extra
->damp_info
)
8615 bgp_damp_info_vty(vty
, path
, json_path
);
8618 if (path
->extra
&& bgp_is_valid_label(&path
->extra
->label
[0])
8619 && safi
!= SAFI_EVPN
) {
8620 mpls_label_t label
= label_pton(&path
->extra
->label
[0]);
8623 json_object_int_add(json_path
, "remoteLabel",
8626 vty_out(vty
, " Remote label: %d\n", label
);
8630 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
8632 json_object_int_add(json_path
, "labelIndex",
8635 vty_out(vty
, " Label Index: %d\n",
8639 /* Line 8 display Addpath IDs */
8640 if (path
->addpath_rx_id
8641 || bgp_addpath_info_has_ids(&path
->tx_addpath
)) {
8643 json_object_int_add(json_path
, "addpathRxId",
8644 path
->addpath_rx_id
);
8646 /* Keep backwards compatibility with the old API
8647 * by putting TX All's ID in the old field
8649 json_object_int_add(
8650 json_path
, "addpathTxId",
8651 path
->tx_addpath
.addpath_tx_id
8654 /* ... but create a specific field for each
8657 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
8658 json_object_int_add(
8660 bgp_addpath_names(i
)
8666 vty_out(vty
, " AddPath ID: RX %u, ",
8667 path
->addpath_rx_id
);
8669 route_vty_out_tx_ids(vty
, &path
->tx_addpath
);
8673 /* If we used addpath to TX a non-bestpath we need to display
8674 * "Advertised to" on a path-by-path basis
8676 if (bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
8679 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
8681 bgp_addpath_encode_tx(peer
, afi
, safi
);
8682 has_adj
= bgp_adj_out_lookup(
8684 bgp_addpath_id_for_peer(
8686 &path
->tx_addpath
));
8688 if ((addpath_capable
&& has_adj
)
8689 || (!addpath_capable
&& has_adj
8690 && CHECK_FLAG(path
->flags
,
8691 BGP_PATH_SELECTED
))) {
8692 if (json_path
&& !json_adv_to
)
8694 json_object_new_object();
8696 route_vty_out_advertised_to(
8705 json_object_object_add(json_path
,
8716 /* Line 9 display Uptime */
8717 tbuf
= time(NULL
) - (bgp_clock() - path
->uptime
);
8719 json_last_update
= json_object_new_object();
8720 json_object_int_add(json_last_update
, "epoch", tbuf
);
8721 json_object_string_add(json_last_update
, "string",
8723 json_object_object_add(json_path
, "lastUpdate",
8726 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
8728 /* Line 10 display PMSI tunnel attribute, if present */
8729 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
8730 const char *str
= lookup_msg(bgp_pmsi_tnltype_str
,
8731 attr
->pmsi_tnl_type
,
8732 PMSI_TNLTYPE_STR_DEFAULT
);
8735 json_pmsi
= json_object_new_object();
8736 json_object_string_add(json_pmsi
,
8738 json_object_int_add(json_pmsi
,
8740 label2vni(&attr
->label
));
8741 json_object_object_add(json_path
, "pmsi",
8745 " PMSI Tunnel Type: %s, label: %d\n",
8746 str
, label2vni(&attr
->label
));
8751 /* We've constructed the json object for this path, add it to the json
8755 if (json_nexthop_global
|| json_nexthop_ll
) {
8756 json_nexthops
= json_object_new_array();
8758 if (json_nexthop_global
)
8759 json_object_array_add(json_nexthops
,
8760 json_nexthop_global
);
8762 if (json_nexthop_ll
)
8763 json_object_array_add(json_nexthops
,
8766 json_object_object_add(json_path
, "nexthops",
8770 json_object_object_add(json_path
, "peer", json_peer
);
8771 json_object_array_add(json_paths
, json_path
);
8776 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
8777 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
8778 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
8780 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
8781 const char *prefix_list_str
, afi_t afi
,
8782 safi_t safi
, enum bgp_show_type type
);
8783 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
8784 const char *filter
, afi_t afi
, safi_t safi
,
8785 enum bgp_show_type type
);
8786 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
8787 const char *rmap_str
, afi_t afi
, safi_t safi
,
8788 enum bgp_show_type type
);
8789 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
8790 const char *com
, int exact
, afi_t afi
,
8792 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
8793 const char *prefix
, afi_t afi
, safi_t safi
,
8794 enum bgp_show_type type
);
8795 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
8796 afi_t afi
, safi_t safi
, enum bgp_show_type type
);
8797 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
8798 const char *comstr
, int exact
, afi_t afi
,
8799 safi_t safi
, bool use_json
);
8802 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
8803 struct bgp_table
*table
, enum bgp_show_type type
,
8804 void *output_arg
, bool use_json
, char *rd
,
8805 int is_last
, unsigned long *output_cum
,
8806 unsigned long *total_cum
,
8807 unsigned long *json_header_depth
)
8809 struct bgp_path_info
*pi
;
8810 struct bgp_node
*rn
;
8813 unsigned long output_count
= 0;
8814 unsigned long total_count
= 0;
8817 json_object
*json_paths
= NULL
;
8820 if (output_cum
&& *output_cum
!= 0)
8823 if (use_json
&& !*json_header_depth
) {
8825 "{\n \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
8826 ",\n \"routerId\": \"%s\",\n \"defaultLocPrf\": %u,\n"
8827 " \"localAS\": %u,\n \"routes\": { ",
8828 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
8829 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
8832 table
->version
, inet_ntoa(bgp
->router_id
),
8833 bgp
->default_local_pref
, bgp
->as
);
8834 *json_header_depth
= 2;
8836 vty_out(vty
, " \"routeDistinguishers\" : {");
8837 ++*json_header_depth
;
8841 if (use_json
&& rd
) {
8842 vty_out(vty
, " \"%s\" : { ", rd
);
8845 /* Start processing of routes. */
8846 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
8847 pi
= bgp_node_get_bgp_path_info(rn
);
8853 json_paths
= json_object_new_array();
8857 for (; pi
; pi
= pi
->next
) {
8859 if (type
== bgp_show_type_flap_statistics
8860 || type
== bgp_show_type_flap_neighbor
8861 || type
== bgp_show_type_dampend_paths
8862 || type
== bgp_show_type_damp_neighbor
) {
8863 if (!(pi
->extra
&& pi
->extra
->damp_info
))
8866 if (type
== bgp_show_type_regexp
) {
8867 regex_t
*regex
= output_arg
;
8869 if (bgp_regexec(regex
, pi
->attr
->aspath
)
8873 if (type
== bgp_show_type_prefix_list
) {
8874 struct prefix_list
*plist
= output_arg
;
8876 if (prefix_list_apply(plist
, &rn
->p
)
8880 if (type
== bgp_show_type_filter_list
) {
8881 struct as_list
*as_list
= output_arg
;
8883 if (as_list_apply(as_list
, pi
->attr
->aspath
)
8884 != AS_FILTER_PERMIT
)
8887 if (type
== bgp_show_type_route_map
) {
8888 struct route_map
*rmap
= output_arg
;
8889 struct bgp_path_info path
;
8890 struct attr dummy_attr
;
8893 bgp_attr_dup(&dummy_attr
, pi
->attr
);
8895 path
.peer
= pi
->peer
;
8896 path
.attr
= &dummy_attr
;
8898 ret
= route_map_apply(rmap
, &rn
->p
, RMAP_BGP
,
8900 if (ret
== RMAP_DENYMATCH
)
8903 if (type
== bgp_show_type_neighbor
8904 || type
== bgp_show_type_flap_neighbor
8905 || type
== bgp_show_type_damp_neighbor
) {
8906 union sockunion
*su
= output_arg
;
8908 if (pi
->peer
== NULL
8909 || pi
->peer
->su_remote
== NULL
8910 || !sockunion_same(pi
->peer
->su_remote
, su
))
8913 if (type
== bgp_show_type_cidr_only
) {
8914 uint32_t destination
;
8916 destination
= ntohl(rn
->p
.u
.prefix4
.s_addr
);
8917 if (IN_CLASSC(destination
)
8918 && rn
->p
.prefixlen
== 24)
8920 if (IN_CLASSB(destination
)
8921 && rn
->p
.prefixlen
== 16)
8923 if (IN_CLASSA(destination
)
8924 && rn
->p
.prefixlen
== 8)
8927 if (type
== bgp_show_type_prefix_longer
) {
8929 if (!prefix_match(p
, &rn
->p
))
8932 if (type
== bgp_show_type_community_all
) {
8933 if (!pi
->attr
->community
)
8936 if (type
== bgp_show_type_community
) {
8937 struct community
*com
= output_arg
;
8939 if (!pi
->attr
->community
8940 || !community_match(pi
->attr
->community
,
8944 if (type
== bgp_show_type_community_exact
) {
8945 struct community
*com
= output_arg
;
8947 if (!pi
->attr
->community
8948 || !community_cmp(pi
->attr
->community
, com
))
8951 if (type
== bgp_show_type_community_list
) {
8952 struct community_list
*list
= output_arg
;
8954 if (!community_list_match(pi
->attr
->community
,
8958 if (type
== bgp_show_type_community_list_exact
) {
8959 struct community_list
*list
= output_arg
;
8961 if (!community_list_exact_match(
8962 pi
->attr
->community
, list
))
8965 if (type
== bgp_show_type_lcommunity
) {
8966 struct lcommunity
*lcom
= output_arg
;
8968 if (!pi
->attr
->lcommunity
8969 || !lcommunity_match(pi
->attr
->lcommunity
,
8973 if (type
== bgp_show_type_lcommunity_list
) {
8974 struct community_list
*list
= output_arg
;
8976 if (!lcommunity_list_match(pi
->attr
->lcommunity
,
8980 if (type
== bgp_show_type_lcommunity_all
) {
8981 if (!pi
->attr
->lcommunity
)
8984 if (type
== bgp_show_type_dampend_paths
8985 || type
== bgp_show_type_damp_neighbor
) {
8986 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
)
8987 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
8991 if (!use_json
&& header
) {
8992 vty_out(vty
, "BGP table version is %" PRIu64
8993 ", local router ID is %s, vrf id ",
8995 inet_ntoa(bgp
->router_id
));
8996 if (bgp
->vrf_id
== VRF_UNKNOWN
)
8997 vty_out(vty
, "%s", VRFID_NONE_STR
);
8999 vty_out(vty
, "%u", bgp
->vrf_id
);
9001 vty_out(vty
, "Default local pref %u, ",
9002 bgp
->default_local_pref
);
9003 vty_out(vty
, "local AS %u\n", bgp
->as
);
9004 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
9005 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
9006 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
9007 if (type
== bgp_show_type_dampend_paths
9008 || type
== bgp_show_type_damp_neighbor
)
9009 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
9010 else if (type
== bgp_show_type_flap_statistics
9011 || type
== bgp_show_type_flap_neighbor
)
9012 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
9014 vty_out(vty
, BGP_SHOW_HEADER
);
9017 if (rd
!= NULL
&& !display
&& !output_count
) {
9020 "Route Distinguisher: %s\n",
9023 if (type
== bgp_show_type_dampend_paths
9024 || type
== bgp_show_type_damp_neighbor
)
9025 damp_route_vty_out(vty
, &rn
->p
, pi
, display
,
9026 safi
, use_json
, json_paths
);
9027 else if (type
== bgp_show_type_flap_statistics
9028 || type
== bgp_show_type_flap_neighbor
)
9029 flap_route_vty_out(vty
, &rn
->p
, pi
, display
,
9030 safi
, use_json
, json_paths
);
9032 route_vty_out(vty
, &rn
->p
, pi
, display
, safi
,
9044 if (p
->family
== AF_FLOWSPEC
) {
9045 char retstr
[BGP_FLOWSPEC_STRING_DISPLAY_MAX
];
9047 bgp_fs_nlri_get_string((unsigned char *)
9048 p
->u
.prefix_flowspec
.ptr
,
9049 p
->u
.prefix_flowspec
9052 NLRI_STRING_FORMAT_MIN
,
9055 vty_out(vty
, "\"%s/%d\": ",
9057 p
->u
.prefix_flowspec
.prefixlen
);
9059 vty_out(vty
, ",\"%s/%d\": ",
9061 p
->u
.prefix_flowspec
.prefixlen
);
9063 prefix2str(p
, buf2
, sizeof(buf2
));
9065 vty_out(vty
, "\"%s\": ", buf2
);
9067 vty_out(vty
, ",\"%s\": ", buf2
);
9070 json_object_to_json_string(json_paths
));
9071 json_object_free(json_paths
);
9078 output_count
+= *output_cum
;
9079 *output_cum
= output_count
;
9082 total_count
+= *total_cum
;
9083 *total_cum
= total_count
;
9087 vty_out(vty
, " }%s ", (is_last
? "" : ","));
9091 for (i
= 0; i
< *json_header_depth
; ++i
)
9092 vty_out(vty
, " } ");
9097 /* No route is displayed */
9098 if (output_count
== 0) {
9099 if (type
== bgp_show_type_normal
)
9101 "No BGP prefixes displayed, %ld exist\n",
9105 "\nDisplayed %ld routes and %ld total paths\n",
9106 output_count
, total_count
);
9113 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
9114 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
9115 enum bgp_show_type type
, void *output_arg
, bool use_json
)
9117 struct bgp_node
*rn
, *next
;
9118 unsigned long output_cum
= 0;
9119 unsigned long total_cum
= 0;
9120 unsigned long json_header_depth
= 0;
9121 struct bgp_table
*itable
;
9124 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
9126 for (rn
= bgp_table_top(table
); rn
; rn
= next
) {
9127 next
= bgp_route_next(rn
);
9128 if (prd_match
&& memcmp(rn
->p
.u
.val
, prd_match
->val
, 8) != 0)
9131 itable
= bgp_node_get_bgp_table_info(rn
);
9132 if (itable
!= NULL
) {
9133 struct prefix_rd prd
;
9134 char rd
[RD_ADDRSTRLEN
];
9136 memcpy(&prd
, &(rn
->p
), sizeof(struct prefix_rd
));
9137 prefix_rd2str(&prd
, rd
, sizeof(rd
));
9138 bgp_show_table(vty
, bgp
, safi
, itable
, type
, output_arg
,
9139 use_json
, rd
, next
== NULL
, &output_cum
,
9140 &total_cum
, &json_header_depth
);
9146 if (output_cum
== 0)
9147 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
9151 "\nDisplayed %ld routes and %ld total paths\n",
9152 output_cum
, total_cum
);
9156 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
9157 enum bgp_show_type type
, void *output_arg
, bool use_json
)
9159 struct bgp_table
*table
;
9160 unsigned long json_header_depth
= 0;
9163 bgp
= bgp_get_default();
9168 vty_out(vty
, "No BGP process is configured\n");
9170 vty_out(vty
, "{}\n");
9174 table
= bgp
->rib
[afi
][safi
];
9175 /* use MPLS and ENCAP specific shows until they are merged */
9176 if (safi
== SAFI_MPLS_VPN
) {
9177 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
9178 output_arg
, use_json
);
9181 if (safi
== SAFI_FLOWSPEC
&& type
== bgp_show_type_detail
) {
9182 return bgp_show_table_flowspec(vty
, bgp
, afi
, table
, type
,
9183 output_arg
, use_json
,
9186 /* labeled-unicast routes live in the unicast table */
9187 else if (safi
== SAFI_LABELED_UNICAST
)
9188 safi
= SAFI_UNICAST
;
9190 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, use_json
,
9191 NULL
, 1, NULL
, NULL
, &json_header_depth
);
9194 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
9195 safi_t safi
, bool use_json
)
9197 struct listnode
*node
, *nnode
;
9200 bool route_output
= false;
9203 vty_out(vty
, "{\n");
9205 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
9206 route_output
= true;
9209 vty_out(vty
, ",\n");
9213 vty_out(vty
, "\"%s\":",
9214 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
9218 vty_out(vty
, "\nInstance %s:\n",
9219 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
9223 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
9228 vty_out(vty
, "}\n");
9229 else if (!route_output
)
9230 vty_out(vty
, "%% BGP instance not found\n");
9233 /* Header of detailed BGP route information */
9234 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
9235 struct bgp_node
*rn
, struct prefix_rd
*prd
,
9236 afi_t afi
, safi_t safi
, json_object
*json
)
9238 struct bgp_path_info
*pi
;
9241 struct listnode
*node
, *nnode
;
9242 char buf1
[RD_ADDRSTRLEN
];
9243 char buf2
[INET6_ADDRSTRLEN
];
9244 char buf3
[EVPN_ROUTE_STRLEN
];
9245 char prefix_str
[BUFSIZ
];
9250 int route_filter_translated_v4
= 0;
9251 int route_filter_v4
= 0;
9252 int route_filter_translated_v6
= 0;
9253 int route_filter_v6
= 0;
9256 int accept_own_nexthop
= 0;
9259 int no_advertise
= 0;
9263 int has_valid_label
= 0;
9264 mpls_label_t label
= 0;
9265 json_object
*json_adv_to
= NULL
;
9268 has_valid_label
= bgp_is_valid_label(&rn
->local_label
);
9270 if (has_valid_label
)
9271 label
= label_pton(&rn
->local_label
);
9274 if (has_valid_label
)
9275 json_object_int_add(json
, "localLabel", label
);
9277 json_object_string_add(
9279 prefix2str(p
, prefix_str
, sizeof(prefix_str
)));
9281 if (safi
== SAFI_EVPN
)
9282 vty_out(vty
, "BGP routing table entry for %s%s%s\n",
9283 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
))
9286 bgp_evpn_route2str((struct prefix_evpn
*)p
,
9287 buf3
, sizeof(buf3
)));
9289 vty_out(vty
, "BGP routing table entry for %s%s%s/%d\n",
9290 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
9291 ? prefix_rd2str(prd
, buf1
,
9294 safi
== SAFI_MPLS_VPN
? ":" : "",
9295 inet_ntop(p
->family
, &p
->u
.prefix
, buf2
,
9299 if (has_valid_label
)
9300 vty_out(vty
, "Local label: %d\n", label
);
9301 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
9302 vty_out(vty
, "not allocated\n");
9305 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
9307 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
9309 if (pi
->extra
&& pi
->extra
->suppress
)
9312 if (pi
->attr
->community
== NULL
)
9315 no_advertise
+= community_include(
9316 pi
->attr
->community
, COMMUNITY_NO_ADVERTISE
);
9317 no_export
+= community_include(pi
->attr
->community
,
9318 COMMUNITY_NO_EXPORT
);
9319 local_as
+= community_include(pi
->attr
->community
,
9320 COMMUNITY_LOCAL_AS
);
9321 accept_own
+= community_include(pi
->attr
->community
,
9322 COMMUNITY_ACCEPT_OWN
);
9323 route_filter_translated_v4
+= community_include(
9324 pi
->attr
->community
,
9325 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4
);
9326 route_filter_translated_v6
+= community_include(
9327 pi
->attr
->community
,
9328 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6
);
9329 route_filter_v4
+= community_include(
9330 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v4
);
9331 route_filter_v6
+= community_include(
9332 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v6
);
9333 llgr_stale
+= community_include(pi
->attr
->community
,
9334 COMMUNITY_LLGR_STALE
);
9335 no_llgr
+= community_include(pi
->attr
->community
,
9337 accept_own_nexthop
+=
9338 community_include(pi
->attr
->community
,
9339 COMMUNITY_ACCEPT_OWN_NEXTHOP
);
9340 blackhole
+= community_include(pi
->attr
->community
,
9341 COMMUNITY_BLACKHOLE
);
9342 no_peer
+= community_include(pi
->attr
->community
,
9348 vty_out(vty
, "Paths: (%d available", count
);
9350 vty_out(vty
, ", best #%d", best
);
9351 if (safi
== SAFI_UNICAST
)
9352 vty_out(vty
, ", table %s",
9354 == BGP_INSTANCE_TYPE_DEFAULT
)
9358 vty_out(vty
, ", no best path");
9362 ", accept own local route exported and imported in different VRF");
9363 else if (route_filter_translated_v4
)
9365 ", mark translated RTs for VPNv4 route filtering");
9366 else if (route_filter_v4
)
9368 ", attach RT as-is for VPNv4 route filtering");
9369 else if (route_filter_translated_v6
)
9371 ", mark translated RTs for VPNv6 route filtering");
9372 else if (route_filter_v6
)
9374 ", attach RT as-is for VPNv6 route filtering");
9375 else if (llgr_stale
)
9377 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
9380 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
9381 else if (accept_own_nexthop
)
9383 ", accept local nexthop");
9385 vty_out(vty
, ", inform peer to blackhole prefix");
9387 vty_out(vty
, ", not advertised to EBGP peer");
9388 else if (no_advertise
)
9389 vty_out(vty
, ", not advertised to any peer");
9391 vty_out(vty
, ", not advertised outside local AS");
9394 ", inform EBGP peer not to advertise to their EBGP peers");
9398 ", Advertisements suppressed by an aggregate.");
9399 vty_out(vty
, ")\n");
9402 /* If we are not using addpath then we can display Advertised to and
9404 * show what peers we advertised the bestpath to. If we are using
9406 * though then we must display Advertised to on a path-by-path basis. */
9407 if (!bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
9408 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
9409 if (bgp_adj_out_lookup(peer
, rn
, 0)) {
9410 if (json
&& !json_adv_to
)
9411 json_adv_to
= json_object_new_object();
9413 route_vty_out_advertised_to(
9415 " Advertised to non peer-group peers:\n ",
9422 json_object_object_add(json
, "advertisedTo",
9427 vty_out(vty
, " Not advertised to any peer");
9433 /* Display specified route of BGP table. */
9434 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
9435 struct bgp_table
*rib
, const char *ip_str
,
9436 afi_t afi
, safi_t safi
,
9437 struct prefix_rd
*prd
, int prefix_check
,
9438 enum bgp_path_type pathtype
, bool use_json
)
9443 struct prefix match
;
9444 struct bgp_node
*rn
;
9445 struct bgp_node
*rm
;
9446 struct bgp_path_info
*pi
;
9447 struct bgp_table
*table
;
9448 json_object
*json
= NULL
;
9449 json_object
*json_paths
= NULL
;
9451 /* Check IP address argument. */
9452 ret
= str2prefix(ip_str
, &match
);
9454 vty_out(vty
, "address is malformed\n");
9458 match
.family
= afi2family(afi
);
9461 json
= json_object_new_object();
9462 json_paths
= json_object_new_array();
9465 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
9466 for (rn
= bgp_table_top(rib
); rn
; rn
= bgp_route_next(rn
)) {
9467 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
9469 table
= bgp_node_get_bgp_table_info(rn
);
9475 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
9479 && rm
->p
.prefixlen
!= match
.prefixlen
) {
9480 bgp_unlock_node(rm
);
9484 for (pi
= bgp_node_get_bgp_path_info(rm
); pi
;
9487 route_vty_out_detail_header(
9489 (struct prefix_rd
*)&rn
->p
,
9490 AFI_IP
, safi
, json
);
9495 if (pathtype
== BGP_PATH_SHOW_ALL
9496 || (pathtype
== BGP_PATH_SHOW_BESTPATH
9497 && CHECK_FLAG(pi
->flags
,
9499 || (pathtype
== BGP_PATH_SHOW_MULTIPATH
9500 && (CHECK_FLAG(pi
->flags
,
9502 || CHECK_FLAG(pi
->flags
,
9503 BGP_PATH_SELECTED
))))
9504 route_vty_out_detail(vty
, bgp
, &rm
->p
,
9509 bgp_unlock_node(rm
);
9511 } else if (safi
== SAFI_FLOWSPEC
) {
9512 display
= bgp_flowspec_display_match_per_ip(afi
, rib
,
9513 &match
, prefix_check
,
9520 if ((rn
= bgp_node_match(rib
, &match
)) != NULL
) {
9522 || rn
->p
.prefixlen
== match
.prefixlen
) {
9523 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
;
9526 route_vty_out_detail_header(
9527 vty
, bgp
, rn
, NULL
, afi
,
9533 if (pathtype
== BGP_PATH_SHOW_ALL
9535 == BGP_PATH_SHOW_BESTPATH
9540 == BGP_PATH_SHOW_MULTIPATH
9546 BGP_PATH_SELECTED
))))
9547 route_vty_out_detail(
9548 vty
, bgp
, &rn
->p
, pi
,
9549 afi
, safi
, json_paths
);
9553 bgp_unlock_node(rn
);
9559 json_object_object_add(json
, "paths", json_paths
);
9561 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
9562 json
, JSON_C_TO_STRING_PRETTY
));
9563 json_object_free(json
);
9566 vty_out(vty
, "%% Network not in table\n");
9574 /* Display specified route of Main RIB */
9575 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
9576 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
9577 int prefix_check
, enum bgp_path_type pathtype
,
9581 bgp
= bgp_get_default();
9584 vty_out(vty
, "No BGP process is configured\n");
9586 vty_out(vty
, "{}\n");
9591 /* labeled-unicast routes live in the unicast table */
9592 if (safi
== SAFI_LABELED_UNICAST
)
9593 safi
= SAFI_UNICAST
;
9595 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
9596 afi
, safi
, prd
, prefix_check
, pathtype
,
9600 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
9601 struct cmd_token
**argv
, afi_t afi
, safi_t safi
,
9604 struct lcommunity
*lcom
;
9610 b
= buffer_new(1024);
9611 for (i
= 0; i
< argc
; i
++) {
9613 buffer_putc(b
, ' ');
9615 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
9617 buffer_putstr(b
, argv
[i
]->arg
);
9621 buffer_putc(b
, '\0');
9623 str
= buffer_getstr(b
);
9626 lcom
= lcommunity_str2com(str
);
9627 XFREE(MTYPE_TMP
, str
);
9629 vty_out(vty
, "%% Large-community malformed\n");
9633 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_lcommunity
, lcom
,
9637 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
9638 const char *lcom
, afi_t afi
, safi_t safi
,
9641 struct community_list
*list
;
9643 list
= community_list_lookup(bgp_clist
, lcom
, 0,
9644 LARGE_COMMUNITY_LIST_MASTER
);
9646 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
9651 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_lcommunity_list
,
9655 DEFUN (show_ip_bgp_large_community_list
,
9656 show_ip_bgp_large_community_list_cmd
,
9657 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community-list <(1-500)|WORD> [json]",
9661 BGP_INSTANCE_HELP_STR
9663 BGP_SAFI_WITH_LABEL_HELP_STR
9664 "Display routes matching the large-community-list\n"
9665 "large-community-list number\n"
9666 "large-community-list name\n"
9670 afi_t afi
= AFI_IP6
;
9671 safi_t safi
= SAFI_UNICAST
;
9674 if (argv_find(argv
, argc
, "ip", &idx
))
9676 if (argv_find(argv
, argc
, "view", &idx
)
9677 || argv_find(argv
, argc
, "vrf", &idx
))
9678 vrf
= argv
[++idx
]->arg
;
9679 if (argv_find(argv
, argc
, "ipv4", &idx
)
9680 || argv_find(argv
, argc
, "ipv6", &idx
)) {
9681 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
9682 if (argv_find(argv
, argc
, "unicast", &idx
)
9683 || argv_find(argv
, argc
, "multicast", &idx
))
9684 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
9687 bool uj
= use_json(argc
, argv
);
9689 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
9691 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
9695 argv_find(argv
, argc
, "large-community-list", &idx
);
9696 return bgp_show_lcommunity_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
, safi
,
9699 DEFUN (show_ip_bgp_large_community
,
9700 show_ip_bgp_large_community_cmd
,
9701 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [AA:BB:CC] [json]",
9705 BGP_INSTANCE_HELP_STR
9707 BGP_SAFI_WITH_LABEL_HELP_STR
9708 "Display routes matching the large-communities\n"
9709 "List of large-community numbers\n"
9713 afi_t afi
= AFI_IP6
;
9714 safi_t safi
= SAFI_UNICAST
;
9717 if (argv_find(argv
, argc
, "ip", &idx
))
9719 if (argv_find(argv
, argc
, "view", &idx
)
9720 || argv_find(argv
, argc
, "vrf", &idx
))
9721 vrf
= argv
[++idx
]->arg
;
9722 if (argv_find(argv
, argc
, "ipv4", &idx
)
9723 || argv_find(argv
, argc
, "ipv6", &idx
)) {
9724 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
9725 if (argv_find(argv
, argc
, "unicast", &idx
)
9726 || argv_find(argv
, argc
, "multicast", &idx
))
9727 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
9730 bool uj
= use_json(argc
, argv
);
9732 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
9734 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
9738 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
))
9739 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
, afi
, safi
, uj
);
9741 return bgp_show(vty
, bgp
, afi
, safi
,
9742 bgp_show_type_lcommunity_all
, NULL
, uj
);
9745 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
9749 /* BGP route print out function without JSON */
9752 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
9753 <dampening <parameters>\
9758 |community-list <(1-500)|WORD> [exact-match]\
9759 |A.B.C.D/M longer-prefixes\
9760 |X:X::X:X/M longer-prefixes\
9765 BGP_INSTANCE_HELP_STR
9767 BGP_SAFI_WITH_LABEL_HELP_STR
9768 "Display detailed information about dampening\n"
9769 "Display detail of configured dampening parameters\n"
9770 "Display routes matching the route-map\n"
9771 "A route-map to match on\n"
9772 "Display routes conforming to the prefix-list\n"
9773 "Prefix-list name\n"
9774 "Display routes conforming to the filter-list\n"
9775 "Regular expression access list name\n"
9776 "BGP RIB advertisement statistics\n"
9777 "Display routes matching the community-list\n"
9778 "community-list number\n"
9779 "community-list name\n"
9780 "Exact match of the communities\n"
9782 "Display route and more specific routes\n"
9784 "Display route and more specific routes\n")
9786 afi_t afi
= AFI_IP6
;
9787 safi_t safi
= SAFI_UNICAST
;
9788 int exact_match
= 0;
9789 struct bgp
*bgp
= NULL
;
9792 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9797 if (argv_find(argv
, argc
, "dampening", &idx
)) {
9798 if (argv_find(argv
, argc
, "parameters", &idx
))
9799 return bgp_show_dampening_parameters(vty
, afi
, safi
);
9802 if (argv_find(argv
, argc
, "prefix-list", &idx
))
9803 return bgp_show_prefix_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9804 safi
, bgp_show_type_prefix_list
);
9806 if (argv_find(argv
, argc
, "filter-list", &idx
))
9807 return bgp_show_filter_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9808 safi
, bgp_show_type_filter_list
);
9810 if (argv_find(argv
, argc
, "statistics", &idx
))
9811 return bgp_table_stats(vty
, bgp
, afi
, safi
);
9813 if (argv_find(argv
, argc
, "route-map", &idx
))
9814 return bgp_show_route_map(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9815 safi
, bgp_show_type_route_map
);
9817 if (argv_find(argv
, argc
, "community-list", &idx
)) {
9818 const char *clist_number_or_name
= argv
[++idx
]->arg
;
9819 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
9821 return bgp_show_community_list(vty
, bgp
, clist_number_or_name
,
9822 exact_match
, afi
, safi
);
9825 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
9826 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
9827 return bgp_show_prefix_longer(vty
, bgp
, argv
[idx
]->arg
, afi
,
9829 bgp_show_type_prefix_longer
);
9834 /* BGP route print out function with JSON */
9835 DEFUN (show_ip_bgp_json
,
9836 show_ip_bgp_json_cmd
,
9837 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
9839 |dampening <flap-statistics|dampened-paths>\
9840 |community [AA:NN|local-AS|no-advertise|no-export\
9841 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
9842 |accept-own|accept-own-nexthop|route-filter-v6\
9843 |route-filter-v4|route-filter-translated-v6\
9844 |route-filter-translated-v4] [exact-match]\
9849 BGP_INSTANCE_HELP_STR
9851 BGP_SAFI_WITH_LABEL_HELP_STR
9852 "Display only routes with non-natural netmasks\n"
9853 "Display detailed information about dampening\n"
9854 "Display flap statistics of routes\n"
9855 "Display paths suppressed due to dampening\n"
9856 "Display routes matching the communities\n"
9858 "Do not send outside local AS (well-known community)\n"
9859 "Do not advertise to any peer (well-known community)\n"
9860 "Do not export to next AS (well-known community)\n"
9861 "Graceful shutdown (well-known community)\n"
9862 "Do not export to any peer (well-known community)\n"
9863 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
9864 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
9865 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
9866 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
9867 "Should accept VPN route with local nexthop (well-known community)\n"
9868 "RT VPNv6 route filtering (well-known community)\n"
9869 "RT VPNv4 route filtering (well-known community)\n"
9870 "RT translated VPNv6 route filtering (well-known community)\n"
9871 "RT translated VPNv4 route filtering (well-known community)\n"
9872 "Exact match of the communities\n"
9875 afi_t afi
= AFI_IP6
;
9876 safi_t safi
= SAFI_UNICAST
;
9877 enum bgp_show_type sh_type
= bgp_show_type_normal
;
9878 struct bgp
*bgp
= NULL
;
9880 int exact_match
= 0;
9881 bool uj
= use_json(argc
, argv
);
9886 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9891 if (argv_find(argv
, argc
, "cidr-only", &idx
))
9892 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_cidr_only
,
9895 if (argv_find(argv
, argc
, "dampening", &idx
)) {
9896 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
9897 return bgp_show(vty
, bgp
, afi
, safi
,
9898 bgp_show_type_dampend_paths
, NULL
, uj
);
9899 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
9900 return bgp_show(vty
, bgp
, afi
, safi
,
9901 bgp_show_type_flap_statistics
, NULL
,
9905 if (argv_find(argv
, argc
, "community", &idx
)) {
9906 char *maybecomm
= NULL
;
9907 char *community
= NULL
;
9909 if (idx
+ 1 < argc
) {
9910 if (argv
[idx
+ 1]->type
== VARIABLE_TKN
)
9911 maybecomm
= argv
[idx
+ 1]->arg
;
9913 maybecomm
= argv
[idx
+ 1]->text
;
9916 if (maybecomm
&& !strmatch(maybecomm
, "json")
9917 && !strmatch(maybecomm
, "exact-match"))
9918 community
= maybecomm
;
9920 if (argv_find(argv
, argc
, "exact-match", &idx
))
9924 return bgp_show_community(vty
, bgp
, community
,
9925 exact_match
, afi
, safi
, uj
);
9927 return (bgp_show(vty
, bgp
, afi
, safi
,
9928 bgp_show_type_community_all
, NULL
,
9932 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
, NULL
, uj
);
9935 DEFUN (show_ip_bgp_route
,
9936 show_ip_bgp_route_cmd
,
9937 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]"
9938 "<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [json]",
9942 BGP_INSTANCE_HELP_STR
9944 BGP_SAFI_WITH_LABEL_HELP_STR
9945 "Network in the BGP routing table to display\n"
9947 "Network in the BGP routing table to display\n"
9949 "Display only the bestpath\n"
9950 "Display only multipaths\n"
9953 int prefix_check
= 0;
9955 afi_t afi
= AFI_IP6
;
9956 safi_t safi
= SAFI_UNICAST
;
9957 char *prefix
= NULL
;
9958 struct bgp
*bgp
= NULL
;
9959 enum bgp_path_type path_type
;
9960 bool uj
= use_json(argc
, argv
);
9964 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9971 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
9975 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
9976 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
9977 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
9979 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
9980 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
9983 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
9984 && afi
!= AFI_IP6
) {
9986 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
9989 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
9992 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
9996 prefix
= argv
[idx
]->arg
;
9998 /* [<bestpath|multipath>] */
9999 if (argv_find(argv
, argc
, "bestpath", &idx
))
10000 path_type
= BGP_PATH_SHOW_BESTPATH
;
10001 else if (argv_find(argv
, argc
, "multipath", &idx
))
10002 path_type
= BGP_PATH_SHOW_MULTIPATH
;
10004 path_type
= BGP_PATH_SHOW_ALL
;
10006 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
10010 DEFUN (show_ip_bgp_regexp
,
10011 show_ip_bgp_regexp_cmd
,
10012 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX...",
10016 BGP_INSTANCE_HELP_STR
10018 BGP_SAFI_WITH_LABEL_HELP_STR
10019 "Display routes matching the AS path regular expression\n"
10020 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n")
10022 afi_t afi
= AFI_IP6
;
10023 safi_t safi
= SAFI_UNICAST
;
10024 struct bgp
*bgp
= NULL
;
10027 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10030 return CMD_WARNING
;
10032 // get index of regex
10033 argv_find(argv
, argc
, "regexp", &idx
);
10036 char *regstr
= argv_concat(argv
, argc
, idx
);
10037 int rc
= bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
10038 bgp_show_type_regexp
);
10039 XFREE(MTYPE_TMP
, regstr
);
10043 DEFUN (show_ip_bgp_instance_all
,
10044 show_ip_bgp_instance_all_cmd
,
10045 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json]",
10049 BGP_INSTANCE_ALL_HELP_STR
10051 BGP_SAFI_WITH_LABEL_HELP_STR
10054 afi_t afi
= AFI_IP
;
10055 safi_t safi
= SAFI_UNICAST
;
10056 struct bgp
*bgp
= NULL
;
10058 bool uj
= use_json(argc
, argv
);
10063 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10066 return CMD_WARNING
;
10068 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, uj
);
10069 return CMD_SUCCESS
;
10072 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
10073 afi_t afi
, safi_t safi
, enum bgp_show_type type
)
10078 if (!config_bgp_aspath_validate(regstr
)) {
10079 vty_out(vty
, "Invalid character in as-path access-list %s\n",
10081 return CMD_WARNING_CONFIG_FAILED
;
10084 regex
= bgp_regcomp(regstr
);
10086 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
10087 return CMD_WARNING
;
10090 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, 0);
10091 bgp_regex_free(regex
);
10095 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
10096 const char *prefix_list_str
, afi_t afi
,
10097 safi_t safi
, enum bgp_show_type type
)
10099 struct prefix_list
*plist
;
10101 plist
= prefix_list_lookup(afi
, prefix_list_str
);
10102 if (plist
== NULL
) {
10103 vty_out(vty
, "%% %s is not a valid prefix-list name\n",
10105 return CMD_WARNING
;
10108 return bgp_show(vty
, bgp
, afi
, safi
, type
, plist
, 0);
10111 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
10112 const char *filter
, afi_t afi
, safi_t safi
,
10113 enum bgp_show_type type
)
10115 struct as_list
*as_list
;
10117 as_list
= as_list_lookup(filter
);
10118 if (as_list
== NULL
) {
10119 vty_out(vty
, "%% %s is not a valid AS-path access-list name\n",
10121 return CMD_WARNING
;
10124 return bgp_show(vty
, bgp
, afi
, safi
, type
, as_list
, 0);
10127 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
10128 const char *rmap_str
, afi_t afi
, safi_t safi
,
10129 enum bgp_show_type type
)
10131 struct route_map
*rmap
;
10133 rmap
= route_map_lookup_by_name(rmap_str
);
10135 vty_out(vty
, "%% %s is not a valid route-map name\n", rmap_str
);
10136 return CMD_WARNING
;
10139 return bgp_show(vty
, bgp
, afi
, safi
, type
, rmap
, 0);
10142 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
10143 const char *comstr
, int exact
, afi_t afi
,
10144 safi_t safi
, bool use_json
)
10146 struct community
*com
;
10149 com
= community_str2com(comstr
);
10151 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
10152 return CMD_WARNING
;
10155 ret
= bgp_show(vty
, bgp
, afi
, safi
,
10156 (exact
? bgp_show_type_community_exact
10157 : bgp_show_type_community
),
10159 community_free(&com
);
10164 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
10165 const char *com
, int exact
, afi_t afi
,
10168 struct community_list
*list
;
10170 list
= community_list_lookup(bgp_clist
, com
, 0, COMMUNITY_LIST_MASTER
);
10171 if (list
== NULL
) {
10172 vty_out(vty
, "%% %s is not a valid community-list name\n", com
);
10173 return CMD_WARNING
;
10176 return bgp_show(vty
, bgp
, afi
, safi
,
10177 (exact
? bgp_show_type_community_list_exact
10178 : bgp_show_type_community_list
),
10182 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
10183 const char *prefix
, afi_t afi
, safi_t safi
,
10184 enum bgp_show_type type
)
10191 ret
= str2prefix(prefix
, p
);
10193 vty_out(vty
, "%% Malformed Prefix\n");
10194 return CMD_WARNING
;
10197 ret
= bgp_show(vty
, bgp
, afi
, safi
, type
, p
, 0);
10202 static struct peer
*peer_lookup_in_view(struct vty
*vty
, struct bgp
*bgp
,
10203 const char *ip_str
, bool use_json
)
10207 union sockunion su
;
10209 /* Get peer sockunion. */
10210 ret
= str2sockunion(ip_str
, &su
);
10212 peer
= peer_lookup_by_conf_if(bgp
, ip_str
);
10214 peer
= peer_lookup_by_hostname(bgp
, ip_str
);
10218 json_object
*json_no
= NULL
;
10219 json_no
= json_object_new_object();
10220 json_object_string_add(
10222 "malformedAddressOrName",
10224 vty_out(vty
, "%s\n",
10225 json_object_to_json_string_ext(
10227 JSON_C_TO_STRING_PRETTY
));
10228 json_object_free(json_no
);
10231 "%% Malformed address or name: %s\n",
10239 /* Peer structure lookup. */
10240 peer
= peer_lookup(bgp
, &su
);
10243 json_object
*json_no
= NULL
;
10244 json_no
= json_object_new_object();
10245 json_object_string_add(json_no
, "warning",
10246 "No such neighbor in this view/vrf");
10247 vty_out(vty
, "%s\n",
10248 json_object_to_json_string_ext(
10249 json_no
, JSON_C_TO_STRING_PRETTY
));
10250 json_object_free(json_no
);
10252 vty_out(vty
, "No such neighbor in this view/vrf\n");
10260 BGP_STATS_MAXBITLEN
= 0,
10262 BGP_STATS_PREFIXES
,
10264 BGP_STATS_UNAGGREGATEABLE
,
10265 BGP_STATS_MAX_AGGREGATEABLE
,
10266 BGP_STATS_AGGREGATES
,
10268 BGP_STATS_ASPATH_COUNT
,
10269 BGP_STATS_ASPATH_MAXHOPS
,
10270 BGP_STATS_ASPATH_TOTHOPS
,
10271 BGP_STATS_ASPATH_MAXSIZE
,
10272 BGP_STATS_ASPATH_TOTSIZE
,
10273 BGP_STATS_ASN_HIGHEST
,
10277 static const char *table_stats_strs
[] = {
10278 [BGP_STATS_PREFIXES
] = "Total Prefixes",
10279 [BGP_STATS_TOTPLEN
] = "Average prefix length",
10280 [BGP_STATS_RIB
] = "Total Advertisements",
10281 [BGP_STATS_UNAGGREGATEABLE
] = "Unaggregateable prefixes",
10282 [BGP_STATS_MAX_AGGREGATEABLE
] =
10283 "Maximum aggregateable prefixes",
10284 [BGP_STATS_AGGREGATES
] = "BGP Aggregate advertisements",
10285 [BGP_STATS_SPACE
] = "Address space advertised",
10286 [BGP_STATS_ASPATH_COUNT
] = "Advertisements with paths",
10287 [BGP_STATS_ASPATH_MAXHOPS
] = "Longest AS-Path (hops)",
10288 [BGP_STATS_ASPATH_MAXSIZE
] = "Largest AS-Path (bytes)",
10289 [BGP_STATS_ASPATH_TOTHOPS
] = "Average AS-Path length (hops)",
10290 [BGP_STATS_ASPATH_TOTSIZE
] = "Average AS-Path size (bytes)",
10291 [BGP_STATS_ASN_HIGHEST
] = "Highest public ASN",
10292 [BGP_STATS_MAX
] = NULL
,
10295 struct bgp_table_stats
{
10296 struct bgp_table
*table
;
10297 unsigned long long counts
[BGP_STATS_MAX
];
10298 double total_space
;
10302 #define TALLY_SIGFIG 100000
10303 static unsigned long
10304 ravg_tally (unsigned long count
, unsigned long oldavg
, unsigned long newval
)
10306 unsigned long newtot
= (count
-1) * oldavg
+ (newval
* TALLY_SIGFIG
);
10307 unsigned long res
= (newtot
* TALLY_SIGFIG
) / count
;
10308 unsigned long ret
= newtot
/ count
;
10310 if ((res
% TALLY_SIGFIG
) > (TALLY_SIGFIG
/2))
10317 static void bgp_table_stats_rn(struct bgp_node
*rn
, struct bgp_node
*top
,
10318 struct bgp_table_stats
*ts
, unsigned int space
)
10320 struct bgp_node
*prn
= bgp_node_parent_nolock(rn
);
10321 struct bgp_path_info
*pi
;
10326 if (!bgp_node_has_bgp_path_info_data(rn
))
10329 ts
->counts
[BGP_STATS_PREFIXES
]++;
10330 ts
->counts
[BGP_STATS_TOTPLEN
] += rn
->p
.prefixlen
;
10333 ts
->counts
[BGP_STATS_AVGPLEN
]
10334 = ravg_tally (ts
->counts
[BGP_STATS_PREFIXES
],
10335 ts
->counts
[BGP_STATS_AVGPLEN
],
10339 /* check if the prefix is included by any other announcements */
10340 while (prn
&& !bgp_node_has_bgp_path_info_data(prn
))
10341 prn
= bgp_node_parent_nolock(prn
);
10343 if (prn
== NULL
|| prn
== top
) {
10344 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
10345 /* announced address space */
10347 ts
->total_space
+= pow(2.0, space
- rn
->p
.prefixlen
);
10348 } else if (bgp_node_has_bgp_path_info_data(prn
))
10349 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
10352 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
10353 ts
->counts
[BGP_STATS_RIB
]++;
10356 && (CHECK_FLAG(pi
->attr
->flag
,
10357 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))))
10358 ts
->counts
[BGP_STATS_AGGREGATES
]++;
10360 /* as-path stats */
10361 if (pi
->attr
&& pi
->attr
->aspath
) {
10362 unsigned int hops
= aspath_count_hops(pi
->attr
->aspath
);
10363 unsigned int size
= aspath_size(pi
->attr
->aspath
);
10364 as_t highest
= aspath_highest(pi
->attr
->aspath
);
10366 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
10368 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
10369 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] = hops
;
10371 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
10372 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] = size
;
10374 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
10375 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
10377 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
]
10378 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
10379 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
],
10381 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
]
10382 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
10383 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
],
10386 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
10387 ts
->counts
[BGP_STATS_ASN_HIGHEST
] = highest
;
10392 static int bgp_table_stats_walker(struct thread
*t
)
10394 struct bgp_node
*rn
, *nrn
;
10395 struct bgp_node
*top
;
10396 struct bgp_table_stats
*ts
= THREAD_ARG(t
);
10397 unsigned int space
= 0;
10399 if (!(top
= bgp_table_top(ts
->table
)))
10402 switch (ts
->table
->afi
) {
10404 space
= IPV4_MAX_BITLEN
;
10407 space
= IPV6_MAX_BITLEN
;
10413 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
10415 for (rn
= top
; rn
; rn
= bgp_route_next(rn
)) {
10416 if (ts
->table
->safi
== SAFI_MPLS_VPN
) {
10417 struct bgp_table
*table
;
10419 table
= bgp_node_get_bgp_table_info(rn
);
10423 top
= bgp_table_top(table
);
10424 for (nrn
= bgp_table_top(table
); nrn
;
10425 nrn
= bgp_route_next(nrn
))
10426 bgp_table_stats_rn(nrn
, top
, ts
, space
);
10428 bgp_table_stats_rn(rn
, top
, ts
, space
);
10435 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
10438 struct bgp_table_stats ts
;
10441 if (!bgp
->rib
[afi
][safi
]) {
10442 vty_out(vty
, "%% No RIB exist's for the AFI(%d)/SAFI(%d)\n",
10444 return CMD_WARNING
;
10447 vty_out(vty
, "BGP %s RIB statistics\n", afi_safi_print(afi
, safi
));
10449 /* labeled-unicast routes live in the unicast table */
10450 if (safi
== SAFI_LABELED_UNICAST
)
10451 safi
= SAFI_UNICAST
;
10453 memset(&ts
, 0, sizeof(ts
));
10454 ts
.table
= bgp
->rib
[afi
][safi
];
10455 thread_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
10457 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
10458 if (!table_stats_strs
[i
])
10463 case BGP_STATS_ASPATH_AVGHOPS
:
10464 case BGP_STATS_ASPATH_AVGSIZE
:
10465 case BGP_STATS_AVGPLEN
:
10466 vty_out (vty
, "%-30s: ", table_stats_strs
[i
]);
10467 vty_out (vty
, "%12.2f",
10468 (float)ts
.counts
[i
] / (float)TALLY_SIGFIG
);
10471 case BGP_STATS_ASPATH_TOTHOPS
:
10472 case BGP_STATS_ASPATH_TOTSIZE
:
10473 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10474 vty_out(vty
, "%12.2f",
10476 ? (float)ts
.counts
[i
]
10478 [BGP_STATS_ASPATH_COUNT
]
10481 case BGP_STATS_TOTPLEN
:
10482 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10483 vty_out(vty
, "%12.2f",
10485 ? (float)ts
.counts
[i
]
10487 [BGP_STATS_PREFIXES
]
10490 case BGP_STATS_SPACE
:
10491 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10492 vty_out(vty
, "%12g\n", ts
.total_space
);
10494 if (afi
== AFI_IP6
) {
10495 vty_out(vty
, "%30s: ", "/32 equivalent ");
10496 vty_out(vty
, "%12g\n",
10497 ts
.total_space
* pow(2.0, -128 + 32));
10498 vty_out(vty
, "%30s: ", "/48 equivalent ");
10499 vty_out(vty
, "%12g\n",
10500 ts
.total_space
* pow(2.0, -128 + 48));
10502 vty_out(vty
, "%30s: ", "% announced ");
10503 vty_out(vty
, "%12.2f\n",
10504 ts
.total_space
* 100. * pow(2.0, -32));
10505 vty_out(vty
, "%30s: ", "/8 equivalent ");
10506 vty_out(vty
, "%12.2f\n",
10507 ts
.total_space
* pow(2.0, -32 + 8));
10508 vty_out(vty
, "%30s: ", "/24 equivalent ");
10509 vty_out(vty
, "%12.2f\n",
10510 ts
.total_space
* pow(2.0, -32 + 24));
10514 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10515 vty_out(vty
, "%12llu", ts
.counts
[i
]);
10518 vty_out(vty
, "\n");
10520 return CMD_SUCCESS
;
10532 PCOUNT_PFCNT
, /* the figure we display to users */
10536 static const char *pcount_strs
[] = {
10537 [PCOUNT_ADJ_IN
] = "Adj-in",
10538 [PCOUNT_DAMPED
] = "Damped",
10539 [PCOUNT_REMOVED
] = "Removed",
10540 [PCOUNT_HISTORY
] = "History",
10541 [PCOUNT_STALE
] = "Stale",
10542 [PCOUNT_VALID
] = "Valid",
10543 [PCOUNT_ALL
] = "All RIB",
10544 [PCOUNT_COUNTED
] = "PfxCt counted",
10545 [PCOUNT_PFCNT
] = "Useable",
10546 [PCOUNT_MAX
] = NULL
,
10549 struct peer_pcounts
{
10550 unsigned int count
[PCOUNT_MAX
];
10551 const struct peer
*peer
;
10552 const struct bgp_table
*table
;
10555 static int bgp_peer_count_walker(struct thread
*t
)
10557 struct bgp_node
*rn
;
10558 struct peer_pcounts
*pc
= THREAD_ARG(t
);
10559 const struct peer
*peer
= pc
->peer
;
10561 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
)) {
10562 struct bgp_adj_in
*ain
;
10563 struct bgp_path_info
*pi
;
10565 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
10566 if (ain
->peer
== peer
)
10567 pc
->count
[PCOUNT_ADJ_IN
]++;
10569 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
10571 if (pi
->peer
!= peer
)
10574 pc
->count
[PCOUNT_ALL
]++;
10576 if (CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
))
10577 pc
->count
[PCOUNT_DAMPED
]++;
10578 if (CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
10579 pc
->count
[PCOUNT_HISTORY
]++;
10580 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
10581 pc
->count
[PCOUNT_REMOVED
]++;
10582 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
10583 pc
->count
[PCOUNT_STALE
]++;
10584 if (CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
10585 pc
->count
[PCOUNT_VALID
]++;
10586 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
10587 pc
->count
[PCOUNT_PFCNT
]++;
10589 if (CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
10590 pc
->count
[PCOUNT_COUNTED
]++;
10591 if (CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
10593 EC_LIB_DEVELOPMENT
,
10594 "Attempting to count but flags say it is unusable");
10596 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
10598 EC_LIB_DEVELOPMENT
,
10599 "Not counted but flags say we should");
10606 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
10607 safi_t safi
, bool use_json
)
10609 struct peer_pcounts pcounts
= {.peer
= peer
};
10611 json_object
*json
= NULL
;
10612 json_object
*json_loop
= NULL
;
10615 json
= json_object_new_object();
10616 json_loop
= json_object_new_object();
10619 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
10620 || !peer
->bgp
->rib
[afi
][safi
]) {
10622 json_object_string_add(
10624 "No such neighbor or address family");
10625 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10626 json_object_free(json
);
10628 vty_out(vty
, "%% No such neighbor or address family\n");
10630 return CMD_WARNING
;
10633 memset(&pcounts
, 0, sizeof(pcounts
));
10634 pcounts
.peer
= peer
;
10635 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
10637 /* in-place call via thread subsystem so as to record execution time
10638 * stats for the thread-walk (i.e. ensure this can't be blamed on
10639 * on just vty_read()).
10641 thread_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
10644 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
10645 json_object_string_add(json
, "multiProtocol",
10646 afi_safi_print(afi
, safi
));
10647 json_object_int_add(json
, "pfxCounter",
10648 peer
->pcount
[afi
][safi
]);
10650 for (i
= 0; i
< PCOUNT_MAX
; i
++)
10651 json_object_int_add(json_loop
, pcount_strs
[i
],
10654 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
10656 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
10657 json_object_string_add(json
, "pfxctDriftFor",
10659 json_object_string_add(
10660 json
, "recommended",
10661 "Please report this bug, with the above command output");
10663 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
10664 json
, JSON_C_TO_STRING_PRETTY
));
10665 json_object_free(json
);
10669 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
10670 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
10671 peer
->hostname
, peer
->host
,
10672 afi_safi_print(afi
, safi
));
10674 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
10675 afi_safi_print(afi
, safi
));
10678 vty_out(vty
, "PfxCt: %" PRIu32
"\n", peer
->pcount
[afi
][safi
]);
10679 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
10681 for (i
= 0; i
< PCOUNT_MAX
; i
++)
10682 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
10685 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
10686 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
10688 "Please report this bug, with the above command output\n");
10692 return CMD_SUCCESS
;
10695 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
10696 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
10697 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_CMD_STR
"]] "
10698 "neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
10702 BGP_INSTANCE_HELP_STR
10705 "Detailed information on TCP and BGP neighbor connections\n"
10706 "Neighbor to display information about\n"
10707 "Neighbor to display information about\n"
10708 "Neighbor on BGP configured interface\n"
10709 "Display detailed prefix count information\n"
10712 afi_t afi
= AFI_IP6
;
10713 safi_t safi
= SAFI_UNICAST
;
10716 struct bgp
*bgp
= NULL
;
10717 bool uj
= use_json(argc
, argv
);
10722 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10725 return CMD_WARNING
;
10727 argv_find(argv
, argc
, "neighbors", &idx
);
10728 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
10730 return CMD_WARNING
;
10732 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_UNICAST
, uj
);
10735 #ifdef KEEP_OLD_VPN_COMMANDS
10736 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
10737 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
10738 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
10743 "Display information about all VPNv4 NLRIs\n"
10744 "Detailed information on TCP and BGP neighbor connections\n"
10745 "Neighbor to display information about\n"
10746 "Neighbor to display information about\n"
10747 "Neighbor on BGP configured interface\n"
10748 "Display detailed prefix count information\n"
10753 bool uj
= use_json(argc
, argv
);
10755 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
10757 return CMD_WARNING
;
10759 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
10762 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
10763 show_ip_bgp_vpn_all_route_prefix_cmd
,
10764 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
10769 "Display information about all VPNv4 NLRIs\n"
10770 "Network in the BGP routing table to display\n"
10771 "Network in the BGP routing table to display\n"
10775 char *network
= NULL
;
10776 struct bgp
*bgp
= bgp_get_default();
10778 vty_out(vty
, "Can't find default instance\n");
10779 return CMD_WARNING
;
10782 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
10783 network
= argv
[idx
]->arg
;
10784 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
10785 network
= argv
[idx
]->arg
;
10787 vty_out(vty
, "Unable to figure out Network\n");
10788 return CMD_WARNING
;
10791 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
10792 BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
10794 #endif /* KEEP_OLD_VPN_COMMANDS */
10796 DEFUN (show_ip_bgp_l2vpn_evpn_all_route_prefix
,
10797 show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd
,
10798 "show [ip] bgp l2vpn evpn all <A.B.C.D|A.B.C.D/M> [json]",
10804 "Display information about all EVPN NLRIs\n"
10805 "Network in the BGP routing table to display\n"
10806 "Network in the BGP routing table to display\n"
10810 char *network
= NULL
;
10812 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
10813 network
= argv
[idx
]->arg
;
10814 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
10815 network
= argv
[idx
]->arg
;
10817 vty_out(vty
, "Unable to figure out Network\n");
10818 return CMD_WARNING
;
10820 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
, 0,
10821 BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
10824 static void show_adj_route(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
10825 safi_t safi
, enum bgp_show_adj_route_type type
,
10826 const char *rmap_name
, bool use_json
,
10829 struct bgp_table
*table
;
10830 struct bgp_adj_in
*ain
;
10831 struct bgp_adj_out
*adj
;
10832 unsigned long output_count
;
10833 unsigned long filtered_count
;
10834 struct bgp_node
*rn
;
10840 struct update_subgroup
*subgrp
;
10841 json_object
*json_scode
= NULL
;
10842 json_object
*json_ocode
= NULL
;
10843 json_object
*json_ar
= NULL
;
10844 struct peer_af
*paf
;
10845 bool route_filtered
;
10848 json_scode
= json_object_new_object();
10849 json_ocode
= json_object_new_object();
10850 json_ar
= json_object_new_object();
10852 json_object_string_add(json_scode
, "suppressed", "s");
10853 json_object_string_add(json_scode
, "damped", "d");
10854 json_object_string_add(json_scode
, "history", "h");
10855 json_object_string_add(json_scode
, "valid", "*");
10856 json_object_string_add(json_scode
, "best", ">");
10857 json_object_string_add(json_scode
, "multipath", "=");
10858 json_object_string_add(json_scode
, "internal", "i");
10859 json_object_string_add(json_scode
, "ribFailure", "r");
10860 json_object_string_add(json_scode
, "stale", "S");
10861 json_object_string_add(json_scode
, "removed", "R");
10863 json_object_string_add(json_ocode
, "igp", "i");
10864 json_object_string_add(json_ocode
, "egp", "e");
10865 json_object_string_add(json_ocode
, "incomplete", "?");
10872 json_object_string_add(json
, "alert", "no BGP");
10873 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10874 json_object_free(json
);
10876 vty_out(vty
, "%% No bgp\n");
10880 /* labeled-unicast routes live in the unicast table */
10881 if (safi
== SAFI_LABELED_UNICAST
)
10882 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
10884 table
= bgp
->rib
[afi
][safi
];
10886 output_count
= filtered_count
= 0;
10887 subgrp
= peer_subgroup(peer
, afi
, safi
);
10889 if (type
== bgp_show_adj_route_advertised
&& subgrp
10890 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
10892 json_object_int_add(json
, "bgpTableVersion",
10894 json_object_string_add(json
, "bgpLocalRouterId",
10895 inet_ntoa(bgp
->router_id
));
10896 json_object_int_add(json
, "defaultLocPrf",
10897 bgp
->default_local_pref
);
10898 json_object_int_add(json
, "localAS", bgp
->as
);
10899 json_object_object_add(json
, "bgpStatusCodes",
10901 json_object_object_add(json
, "bgpOriginCodes",
10903 json_object_string_add(
10904 json
, "bgpOriginatingDefaultNetwork",
10905 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
10907 vty_out(vty
, "BGP table version is %" PRIu64
10908 ", local router ID is %s, vrf id ",
10909 table
->version
, inet_ntoa(bgp
->router_id
));
10910 if (bgp
->vrf_id
== VRF_UNKNOWN
)
10911 vty_out(vty
, "%s", VRFID_NONE_STR
);
10913 vty_out(vty
, "%u", bgp
->vrf_id
);
10914 vty_out(vty
, "\n");
10915 vty_out(vty
, "Default local pref %u, ",
10916 bgp
->default_local_pref
);
10917 vty_out(vty
, "local AS %u\n", bgp
->as
);
10918 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
10919 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
10920 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
10922 vty_out(vty
, "Originating default network %s\n\n",
10923 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
10928 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
10929 if (type
== bgp_show_adj_route_received
10930 || type
== bgp_show_adj_route_filtered
) {
10931 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
10932 if (ain
->peer
!= peer
|| !ain
->attr
)
10937 json_object_int_add(
10938 json
, "bgpTableVersion",
10940 json_object_string_add(
10942 "bgpLocalRouterId",
10945 json_object_int_add(json
,
10947 bgp
->default_local_pref
);
10948 json_object_int_add(json
,
10949 "localAS", bgp
->as
);
10950 json_object_object_add(
10951 json
, "bgpStatusCodes",
10953 json_object_object_add(
10954 json
, "bgpOriginCodes",
10958 "BGP table version is 0, local router ID is %s, vrf id ",
10961 if (bgp
->vrf_id
== VRF_UNKNOWN
)
10967 vty_out(vty
, "\n");
10969 "Default local pref %u, ",
10970 bgp
->default_local_pref
);
10971 vty_out(vty
, "local AS %u\n",
10974 BGP_SHOW_SCODE_HEADER
);
10976 BGP_SHOW_NCODE_HEADER
);
10978 BGP_SHOW_OCODE_HEADER
);
10984 vty_out(vty
, BGP_SHOW_HEADER
);
10988 bgp_attr_dup(&attr
, ain
->attr
);
10989 route_filtered
= false;
10991 /* Filter prefix using distribute list,
10992 * filter list or prefix list
10994 if ((bgp_input_filter(peer
, &rn
->p
, &attr
, afi
,
10995 safi
)) == FILTER_DENY
)
10996 route_filtered
= true;
10998 /* Filter prefix using route-map */
10999 ret
= bgp_input_modifier(peer
, &rn
->p
, &attr
,
11000 afi
, safi
, rmap_name
);
11002 if (type
== bgp_show_adj_route_filtered
&&
11003 !route_filtered
&& ret
!= RMAP_DENY
) {
11004 bgp_attr_undup(&attr
, ain
->attr
);
11008 if (type
== bgp_show_adj_route_received
&&
11009 (route_filtered
|| ret
== RMAP_DENY
))
11012 route_vty_out_tmp(vty
, &rn
->p
, &attr
, safi
,
11013 use_json
, json_ar
);
11014 bgp_attr_undup(&attr
, ain
->attr
);
11017 } else if (type
== bgp_show_adj_route_advertised
) {
11018 RB_FOREACH (adj
, bgp_adj_out_rb
, &rn
->adj_out
)
11019 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
11020 if (paf
->peer
!= peer
|| !adj
->attr
)
11025 json_object_int_add(
11029 json_object_string_add(
11031 "bgpLocalRouterId",
11034 json_object_int_add(
11035 json
, "defaultLocPrf",
11036 bgp
->default_local_pref
11038 json_object_int_add(
11041 json_object_object_add(
11045 json_object_object_add(
11051 "BGP table version is %" PRIu64
11052 ", local router ID is %s, vrf id ",
11065 vty_out(vty
, "\n");
11067 "Default local pref %u, ",
11068 bgp
->default_local_pref
11074 BGP_SHOW_SCODE_HEADER
);
11076 BGP_SHOW_NCODE_HEADER
);
11078 BGP_SHOW_OCODE_HEADER
);
11089 bgp_attr_dup(&attr
, adj
->attr
);
11090 ret
= bgp_output_modifier(
11091 peer
, &rn
->p
, &attr
, afi
, safi
,
11094 if (ret
!= RMAP_DENY
) {
11095 route_vty_out_tmp(vty
, &rn
->p
,
11104 bgp_attr_undup(&attr
, adj
->attr
);
11110 json_object_object_add(json
, "advertisedRoutes", json_ar
);
11111 json_object_int_add(json
, "totalPrefixCounter", output_count
);
11112 json_object_int_add(json
, "filteredPrefixCounter",
11115 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
11116 json
, JSON_C_TO_STRING_PRETTY
));
11117 json_object_free(json
);
11118 } else if (output_count
> 0) {
11119 if (filtered_count
> 0)
11121 "\nTotal number of prefixes %ld (%ld filtered)\n",
11122 output_count
, filtered_count
);
11124 vty_out(vty
, "\nTotal number of prefixes %ld\n",
11129 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
11130 safi_t safi
, enum bgp_show_adj_route_type type
,
11131 const char *rmap_name
, bool use_json
)
11133 json_object
*json
= NULL
;
11136 json
= json_object_new_object();
11138 if (!peer
|| !peer
->afc
[afi
][safi
]) {
11140 json_object_string_add(
11142 "No such neighbor or address family");
11143 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
11144 json_object_free(json
);
11146 vty_out(vty
, "%% No such neighbor or address family\n");
11148 return CMD_WARNING
;
11151 if ((type
== bgp_show_adj_route_received
11152 || type
== bgp_show_adj_route_filtered
)
11153 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
11154 PEER_FLAG_SOFT_RECONFIG
)) {
11156 json_object_string_add(
11158 "Inbound soft reconfiguration not enabled");
11159 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
11160 json_object_free(json
);
11163 "%% Inbound soft reconfiguration not enabled\n");
11165 return CMD_WARNING
;
11168 show_adj_route(vty
, peer
, afi
, safi
, type
, rmap_name
, use_json
, json
);
11170 return CMD_SUCCESS
;
11173 DEFUN (show_ip_bgp_instance_neighbor_advertised_route
,
11174 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
11175 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
11176 "neighbors <A.B.C.D|X:X::X:X|WORD> <advertised-routes|received-routes|filtered-routes> [route-map WORD] [json]",
11180 BGP_INSTANCE_HELP_STR
11182 BGP_SAFI_WITH_LABEL_HELP_STR
11183 "Detailed information on TCP and BGP neighbor connections\n"
11184 "Neighbor to display information about\n"
11185 "Neighbor to display information about\n"
11186 "Neighbor on BGP configured interface\n"
11187 "Display the routes advertised to a BGP neighbor\n"
11188 "Display the received routes from neighbor\n"
11189 "Display the filtered routes received from neighbor\n"
11190 "Route-map to modify the attributes\n"
11191 "Name of the route map\n"
11194 afi_t afi
= AFI_IP6
;
11195 safi_t safi
= SAFI_UNICAST
;
11196 char *rmap_name
= NULL
;
11197 char *peerstr
= NULL
;
11198 struct bgp
*bgp
= NULL
;
11200 enum bgp_show_adj_route_type type
= bgp_show_adj_route_advertised
;
11202 bool uj
= use_json(argc
, argv
);
11207 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11210 return CMD_WARNING
;
11212 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11213 argv_find(argv
, argc
, "neighbors", &idx
);
11214 peerstr
= argv
[++idx
]->arg
;
11216 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
11218 return CMD_WARNING
;
11220 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
11221 type
= bgp_show_adj_route_advertised
;
11222 else if (argv_find(argv
, argc
, "received-routes", &idx
))
11223 type
= bgp_show_adj_route_received
;
11224 else if (argv_find(argv
, argc
, "filtered-routes", &idx
))
11225 type
= bgp_show_adj_route_filtered
;
11227 if (argv_find(argv
, argc
, "route-map", &idx
))
11228 rmap_name
= argv
[++idx
]->arg
;
11230 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
, uj
);
11233 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
11234 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
11235 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
11241 "Address Family modifier\n"
11242 "Detailed information on TCP and BGP neighbor connections\n"
11243 "Neighbor to display information about\n"
11244 "Neighbor to display information about\n"
11245 "Neighbor on BGP configured interface\n"
11246 "Display information received from a BGP neighbor\n"
11247 "Display the prefixlist filter\n"
11250 afi_t afi
= AFI_IP6
;
11251 safi_t safi
= SAFI_UNICAST
;
11252 char *peerstr
= NULL
;
11255 union sockunion su
;
11261 /* show [ip] bgp */
11262 if (argv_find(argv
, argc
, "ip", &idx
))
11264 /* [<ipv4|ipv6> [unicast]] */
11265 if (argv_find(argv
, argc
, "ipv4", &idx
))
11267 if (argv_find(argv
, argc
, "ipv6", &idx
))
11269 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11270 argv_find(argv
, argc
, "neighbors", &idx
);
11271 peerstr
= argv
[++idx
]->arg
;
11273 bool uj
= use_json(argc
, argv
);
11275 ret
= str2sockunion(peerstr
, &su
);
11277 peer
= peer_lookup_by_conf_if(NULL
, peerstr
);
11280 vty_out(vty
, "{}\n");
11283 "%% Malformed address or name: %s\n",
11285 return CMD_WARNING
;
11288 peer
= peer_lookup(NULL
, &su
);
11291 vty_out(vty
, "{}\n");
11293 vty_out(vty
, "No peer\n");
11294 return CMD_WARNING
;
11298 sprintf(name
, "%s.%d.%d", peer
->host
, afi
, safi
);
11299 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
11302 vty_out(vty
, "Address Family: %s\n",
11303 afi_safi_print(afi
, safi
));
11304 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
11307 vty_out(vty
, "{}\n");
11309 vty_out(vty
, "No functional output\n");
11312 return CMD_SUCCESS
;
11315 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
11316 afi_t afi
, safi_t safi
,
11317 enum bgp_show_type type
, bool use_json
)
11319 /* labeled-unicast routes live in the unicast table */
11320 if (safi
== SAFI_LABELED_UNICAST
)
11321 safi
= SAFI_UNICAST
;
11323 if (!peer
|| !peer
->afc
[afi
][safi
]) {
11325 json_object
*json_no
= NULL
;
11326 json_no
= json_object_new_object();
11327 json_object_string_add(
11328 json_no
, "warning",
11329 "No such neighbor or address family");
11330 vty_out(vty
, "%s\n",
11331 json_object_to_json_string(json_no
));
11332 json_object_free(json_no
);
11334 vty_out(vty
, "%% No such neighbor or address family\n");
11335 return CMD_WARNING
;
11338 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, use_json
);
11341 DEFUN (show_ip_bgp_flowspec_routes_detailed
,
11342 show_ip_bgp_flowspec_routes_detailed_cmd
,
11343 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" flowspec] detail [json]",
11347 BGP_INSTANCE_HELP_STR
11350 "Detailed information on flowspec entries\n"
11353 afi_t afi
= AFI_IP
;
11354 safi_t safi
= SAFI_UNICAST
;
11355 struct bgp
*bgp
= NULL
;
11357 bool uj
= use_json(argc
, argv
);
11362 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11365 return CMD_WARNING
;
11367 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_detail
, NULL
, uj
);
11370 DEFUN (show_ip_bgp_neighbor_routes
,
11371 show_ip_bgp_neighbor_routes_cmd
,
11372 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
11373 "neighbors <A.B.C.D|X:X::X:X|WORD> <flap-statistics|dampened-routes|routes> [json]",
11377 BGP_INSTANCE_HELP_STR
11379 BGP_SAFI_WITH_LABEL_HELP_STR
11380 "Detailed information on TCP and BGP neighbor connections\n"
11381 "Neighbor to display information about\n"
11382 "Neighbor to display information about\n"
11383 "Neighbor on BGP configured interface\n"
11384 "Display flap statistics of the routes learned from neighbor\n"
11385 "Display the dampened routes received from neighbor\n"
11386 "Display routes learned from neighbor\n"
11389 char *peerstr
= NULL
;
11390 struct bgp
*bgp
= NULL
;
11391 afi_t afi
= AFI_IP6
;
11392 safi_t safi
= SAFI_UNICAST
;
11394 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
11396 bool uj
= use_json(argc
, argv
);
11401 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11404 return CMD_WARNING
;
11406 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11407 argv_find(argv
, argc
, "neighbors", &idx
);
11408 peerstr
= argv
[++idx
]->arg
;
11410 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
11412 return CMD_WARNING
;
11414 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
11415 sh_type
= bgp_show_type_flap_neighbor
;
11416 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
11417 sh_type
= bgp_show_type_damp_neighbor
;
11418 else if (argv_find(argv
, argc
, "routes", &idx
))
11419 sh_type
= bgp_show_type_neighbor
;
11421 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
11424 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
11426 struct bgp_distance
{
11427 /* Distance value for the IP source prefix. */
11430 /* Name of the access-list to be matched. */
11434 DEFUN (show_bgp_afi_vpn_rd_route
,
11435 show_bgp_afi_vpn_rd_route_cmd
,
11436 "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]",
11440 "Address Family modifier\n"
11441 "Display information for a route distinguisher\n"
11442 "Route Distinguisher\n"
11443 "Network in the BGP routing table to display\n"
11444 "Network in the BGP routing table to display\n"
11448 struct prefix_rd prd
;
11449 afi_t afi
= AFI_MAX
;
11452 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
11453 vty_out(vty
, "%% Malformed Address Family\n");
11454 return CMD_WARNING
;
11457 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
11459 vty_out(vty
, "%% Malformed Route Distinguisher\n");
11460 return CMD_WARNING
;
11463 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
11464 0, BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
11467 static struct bgp_distance
*bgp_distance_new(void)
11469 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
11472 static void bgp_distance_free(struct bgp_distance
*bdistance
)
11474 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
11477 static int bgp_distance_set(struct vty
*vty
, const char *distance_str
,
11478 const char *ip_str
, const char *access_list_str
)
11485 struct bgp_node
*rn
;
11486 struct bgp_distance
*bdistance
;
11488 afi
= bgp_node_afi(vty
);
11489 safi
= bgp_node_safi(vty
);
11491 ret
= str2prefix(ip_str
, &p
);
11493 vty_out(vty
, "Malformed prefix\n");
11494 return CMD_WARNING_CONFIG_FAILED
;
11497 distance
= atoi(distance_str
);
11499 /* Get BGP distance node. */
11500 rn
= bgp_node_get(bgp_distance_table
[afi
][safi
], (struct prefix
*)&p
);
11501 bdistance
= bgp_node_get_bgp_distance_info(rn
);
11503 bgp_unlock_node(rn
);
11505 bdistance
= bgp_distance_new();
11506 bgp_node_set_bgp_distance_info(rn
, bdistance
);
11509 /* Set distance value. */
11510 bdistance
->distance
= distance
;
11512 /* Reset access-list configuration. */
11513 if (bdistance
->access_list
) {
11514 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
11515 bdistance
->access_list
= NULL
;
11517 if (access_list_str
)
11518 bdistance
->access_list
=
11519 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
11521 return CMD_SUCCESS
;
11524 static int bgp_distance_unset(struct vty
*vty
, const char *distance_str
,
11525 const char *ip_str
, const char *access_list_str
)
11532 struct bgp_node
*rn
;
11533 struct bgp_distance
*bdistance
;
11535 afi
= bgp_node_afi(vty
);
11536 safi
= bgp_node_safi(vty
);
11538 ret
= str2prefix(ip_str
, &p
);
11540 vty_out(vty
, "Malformed prefix\n");
11541 return CMD_WARNING_CONFIG_FAILED
;
11544 rn
= bgp_node_lookup(bgp_distance_table
[afi
][safi
],
11545 (struct prefix
*)&p
);
11547 vty_out(vty
, "Can't find specified prefix\n");
11548 return CMD_WARNING_CONFIG_FAILED
;
11551 bdistance
= bgp_node_get_bgp_distance_info(rn
);
11552 distance
= atoi(distance_str
);
11554 if (bdistance
->distance
!= distance
) {
11555 vty_out(vty
, "Distance does not match configured\n");
11556 return CMD_WARNING_CONFIG_FAILED
;
11559 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
11560 bgp_distance_free(bdistance
);
11562 bgp_node_set_bgp_path_info(rn
, NULL
);
11563 bgp_unlock_node(rn
);
11564 bgp_unlock_node(rn
);
11566 return CMD_SUCCESS
;
11569 /* Apply BGP information to distance method. */
11570 uint8_t bgp_distance_apply(struct prefix
*p
, struct bgp_path_info
*pinfo
,
11571 afi_t afi
, safi_t safi
, struct bgp
*bgp
)
11573 struct bgp_node
*rn
;
11576 struct bgp_distance
*bdistance
;
11577 struct access_list
*alist
;
11578 struct bgp_static
*bgp_static
;
11583 peer
= pinfo
->peer
;
11585 /* Check source address. */
11586 sockunion2hostprefix(&peer
->su
, &q
);
11587 rn
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
11589 bdistance
= bgp_node_get_bgp_distance_info(rn
);
11590 bgp_unlock_node(rn
);
11592 if (bdistance
->access_list
) {
11593 alist
= access_list_lookup(afi
, bdistance
->access_list
);
11595 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
11596 return bdistance
->distance
;
11598 return bdistance
->distance
;
11601 /* Backdoor check. */
11602 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
11604 bgp_static
= bgp_node_get_bgp_static_info(rn
);
11605 bgp_unlock_node(rn
);
11607 if (bgp_static
->backdoor
) {
11608 if (bgp
->distance_local
[afi
][safi
])
11609 return bgp
->distance_local
[afi
][safi
];
11611 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
11615 if (peer
->sort
== BGP_PEER_EBGP
) {
11616 if (bgp
->distance_ebgp
[afi
][safi
])
11617 return bgp
->distance_ebgp
[afi
][safi
];
11618 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
11620 if (bgp
->distance_ibgp
[afi
][safi
])
11621 return bgp
->distance_ibgp
[afi
][safi
];
11622 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
11626 DEFUN (bgp_distance
,
11628 "distance bgp (1-255) (1-255) (1-255)",
11629 "Define an administrative distance\n"
11631 "Distance for routes external to the AS\n"
11632 "Distance for routes internal to the AS\n"
11633 "Distance for local routes\n")
11635 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11636 int idx_number
= 2;
11637 int idx_number_2
= 3;
11638 int idx_number_3
= 4;
11642 afi
= bgp_node_afi(vty
);
11643 safi
= bgp_node_safi(vty
);
11645 bgp
->distance_ebgp
[afi
][safi
] = atoi(argv
[idx_number
]->arg
);
11646 bgp
->distance_ibgp
[afi
][safi
] = atoi(argv
[idx_number_2
]->arg
);
11647 bgp
->distance_local
[afi
][safi
] = atoi(argv
[idx_number_3
]->arg
);
11648 return CMD_SUCCESS
;
11651 DEFUN (no_bgp_distance
,
11652 no_bgp_distance_cmd
,
11653 "no distance bgp [(1-255) (1-255) (1-255)]",
11655 "Define an administrative distance\n"
11657 "Distance for routes external to the AS\n"
11658 "Distance for routes internal to the AS\n"
11659 "Distance for local routes\n")
11661 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11665 afi
= bgp_node_afi(vty
);
11666 safi
= bgp_node_safi(vty
);
11668 bgp
->distance_ebgp
[afi
][safi
] = 0;
11669 bgp
->distance_ibgp
[afi
][safi
] = 0;
11670 bgp
->distance_local
[afi
][safi
] = 0;
11671 return CMD_SUCCESS
;
11675 DEFUN (bgp_distance_source
,
11676 bgp_distance_source_cmd
,
11677 "distance (1-255) A.B.C.D/M",
11678 "Define an administrative distance\n"
11679 "Administrative distance\n"
11680 "IP source prefix\n")
11682 int idx_number
= 1;
11683 int idx_ipv4_prefixlen
= 2;
11684 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
11685 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
11686 return CMD_SUCCESS
;
11689 DEFUN (no_bgp_distance_source
,
11690 no_bgp_distance_source_cmd
,
11691 "no distance (1-255) A.B.C.D/M",
11693 "Define an administrative distance\n"
11694 "Administrative distance\n"
11695 "IP source prefix\n")
11697 int idx_number
= 2;
11698 int idx_ipv4_prefixlen
= 3;
11699 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
11700 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
11701 return CMD_SUCCESS
;
11704 DEFUN (bgp_distance_source_access_list
,
11705 bgp_distance_source_access_list_cmd
,
11706 "distance (1-255) A.B.C.D/M WORD",
11707 "Define an administrative distance\n"
11708 "Administrative distance\n"
11709 "IP source prefix\n"
11710 "Access list name\n")
11712 int idx_number
= 1;
11713 int idx_ipv4_prefixlen
= 2;
11715 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
11716 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
11717 return CMD_SUCCESS
;
11720 DEFUN (no_bgp_distance_source_access_list
,
11721 no_bgp_distance_source_access_list_cmd
,
11722 "no distance (1-255) A.B.C.D/M WORD",
11724 "Define an administrative distance\n"
11725 "Administrative distance\n"
11726 "IP source prefix\n"
11727 "Access list name\n")
11729 int idx_number
= 2;
11730 int idx_ipv4_prefixlen
= 3;
11732 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
11733 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
11734 return CMD_SUCCESS
;
11737 DEFUN (ipv6_bgp_distance_source
,
11738 ipv6_bgp_distance_source_cmd
,
11739 "distance (1-255) X:X::X:X/M",
11740 "Define an administrative distance\n"
11741 "Administrative distance\n"
11742 "IP source prefix\n")
11744 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, NULL
);
11745 return CMD_SUCCESS
;
11748 DEFUN (no_ipv6_bgp_distance_source
,
11749 no_ipv6_bgp_distance_source_cmd
,
11750 "no distance (1-255) X:X::X:X/M",
11752 "Define an administrative distance\n"
11753 "Administrative distance\n"
11754 "IP source prefix\n")
11756 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, NULL
);
11757 return CMD_SUCCESS
;
11760 DEFUN (ipv6_bgp_distance_source_access_list
,
11761 ipv6_bgp_distance_source_access_list_cmd
,
11762 "distance (1-255) X:X::X:X/M WORD",
11763 "Define an administrative distance\n"
11764 "Administrative distance\n"
11765 "IP source prefix\n"
11766 "Access list name\n")
11768 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, argv
[3]->arg
);
11769 return CMD_SUCCESS
;
11772 DEFUN (no_ipv6_bgp_distance_source_access_list
,
11773 no_ipv6_bgp_distance_source_access_list_cmd
,
11774 "no distance (1-255) X:X::X:X/M WORD",
11776 "Define an administrative distance\n"
11777 "Administrative distance\n"
11778 "IP source prefix\n"
11779 "Access list name\n")
11781 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, argv
[4]->arg
);
11782 return CMD_SUCCESS
;
11785 DEFUN (bgp_damp_set
,
11787 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
11788 "BGP Specific commands\n"
11789 "Enable route-flap dampening\n"
11790 "Half-life time for the penalty\n"
11791 "Value to start reusing a route\n"
11792 "Value to start suppressing a route\n"
11793 "Maximum duration to suppress a stable route\n")
11795 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11796 int idx_half_life
= 2;
11798 int idx_suppress
= 4;
11799 int idx_max_suppress
= 5;
11800 int half
= DEFAULT_HALF_LIFE
* 60;
11801 int reuse
= DEFAULT_REUSE
;
11802 int suppress
= DEFAULT_SUPPRESS
;
11803 int max
= 4 * half
;
11806 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
11807 reuse
= atoi(argv
[idx_reuse
]->arg
);
11808 suppress
= atoi(argv
[idx_suppress
]->arg
);
11809 max
= atoi(argv
[idx_max_suppress
]->arg
) * 60;
11810 } else if (argc
== 3) {
11811 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
11815 if (suppress
< reuse
) {
11817 "Suppress value cannot be less than reuse value \n");
11821 return bgp_damp_enable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
), half
,
11822 reuse
, suppress
, max
);
11825 DEFUN (bgp_damp_unset
,
11826 bgp_damp_unset_cmd
,
11827 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
11829 "BGP Specific commands\n"
11830 "Enable route-flap dampening\n"
11831 "Half-life time for the penalty\n"
11832 "Value to start reusing a route\n"
11833 "Value to start suppressing a route\n"
11834 "Maximum duration to suppress a stable route\n")
11836 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11837 return bgp_damp_disable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
));
11840 /* Display specified route of BGP table. */
11841 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
11842 const char *ip_str
, afi_t afi
, safi_t safi
,
11843 struct prefix_rd
*prd
, int prefix_check
)
11846 struct prefix match
;
11847 struct bgp_node
*rn
;
11848 struct bgp_node
*rm
;
11849 struct bgp_path_info
*pi
;
11850 struct bgp_path_info
*pi_temp
;
11852 struct bgp_table
*table
;
11854 /* BGP structure lookup. */
11856 bgp
= bgp_lookup_by_name(view_name
);
11858 vty_out(vty
, "%% Can't find BGP instance %s\n",
11860 return CMD_WARNING
;
11863 bgp
= bgp_get_default();
11865 vty_out(vty
, "%% No BGP process is configured\n");
11866 return CMD_WARNING
;
11870 /* Check IP address argument. */
11871 ret
= str2prefix(ip_str
, &match
);
11873 vty_out(vty
, "%% address is malformed\n");
11874 return CMD_WARNING
;
11877 match
.family
= afi2family(afi
);
11879 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
11880 || (safi
== SAFI_EVPN
)) {
11881 for (rn
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); rn
;
11882 rn
= bgp_route_next(rn
)) {
11883 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
11885 table
= bgp_node_get_bgp_table_info(rn
);
11888 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
11892 || rm
->p
.prefixlen
== match
.prefixlen
) {
11893 pi
= bgp_node_get_bgp_path_info(rm
);
11895 if (pi
->extra
&& pi
->extra
->damp_info
) {
11896 pi_temp
= pi
->next
;
11897 bgp_damp_info_free(
11898 pi
->extra
->damp_info
,
11906 bgp_unlock_node(rm
);
11909 if ((rn
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
))
11912 || rn
->p
.prefixlen
== match
.prefixlen
) {
11913 pi
= bgp_node_get_bgp_path_info(rn
);
11915 if (pi
->extra
&& pi
->extra
->damp_info
) {
11916 pi_temp
= pi
->next
;
11917 bgp_damp_info_free(
11918 pi
->extra
->damp_info
,
11926 bgp_unlock_node(rn
);
11930 return CMD_SUCCESS
;
11933 DEFUN (clear_ip_bgp_dampening
,
11934 clear_ip_bgp_dampening_cmd
,
11935 "clear ip bgp dampening",
11939 "Clear route flap dampening information\n")
11941 bgp_damp_info_clean();
11942 return CMD_SUCCESS
;
11945 DEFUN (clear_ip_bgp_dampening_prefix
,
11946 clear_ip_bgp_dampening_prefix_cmd
,
11947 "clear ip bgp dampening A.B.C.D/M",
11951 "Clear route flap dampening information\n"
11954 int idx_ipv4_prefixlen
= 4;
11955 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
11956 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
11959 DEFUN (clear_ip_bgp_dampening_address
,
11960 clear_ip_bgp_dampening_address_cmd
,
11961 "clear ip bgp dampening A.B.C.D",
11965 "Clear route flap dampening information\n"
11966 "Network to clear damping information\n")
11969 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
11970 SAFI_UNICAST
, NULL
, 0);
11973 DEFUN (clear_ip_bgp_dampening_address_mask
,
11974 clear_ip_bgp_dampening_address_mask_cmd
,
11975 "clear ip bgp dampening A.B.C.D A.B.C.D",
11979 "Clear route flap dampening information\n"
11980 "Network to clear damping information\n"
11984 int idx_ipv4_2
= 5;
11986 char prefix_str
[BUFSIZ
];
11988 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
11991 vty_out(vty
, "%% Inconsistent address and mask\n");
11992 return CMD_WARNING
;
11995 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
11999 static void show_bgp_peerhash_entry(struct hash_bucket
*bucket
, void *arg
)
12001 struct vty
*vty
= arg
;
12002 struct peer
*peer
= bucket
->data
;
12003 char buf
[SU_ADDRSTRLEN
];
12005 vty_out(vty
, "\tPeer: %s %s\n", peer
->host
,
12006 sockunion2str(&peer
->su
, buf
, sizeof(buf
)));
12009 DEFUN (show_bgp_peerhash
,
12010 show_bgp_peerhash_cmd
,
12011 "show bgp peerhash",
12014 "Display information about the BGP peerhash\n")
12016 struct list
*instances
= bm
->bgp
;
12017 struct listnode
*node
;
12020 for (ALL_LIST_ELEMENTS_RO(instances
, node
, bgp
)) {
12021 vty_out(vty
, "BGP: %s\n", bgp
->name
);
12022 hash_iterate(bgp
->peerhash
, show_bgp_peerhash_entry
,
12026 return CMD_SUCCESS
;
12029 /* also used for encap safi */
12030 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
12031 afi_t afi
, safi_t safi
)
12033 struct bgp_node
*prn
;
12034 struct bgp_node
*rn
;
12035 struct bgp_table
*table
;
12037 struct prefix_rd
*prd
;
12038 struct bgp_static
*bgp_static
;
12039 mpls_label_t label
;
12040 char buf
[SU_ADDRSTRLEN
];
12041 char rdbuf
[RD_ADDRSTRLEN
];
12043 /* Network configuration. */
12044 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
12045 prn
= bgp_route_next(prn
)) {
12046 table
= bgp_node_get_bgp_table_info(prn
);
12050 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
12051 bgp_static
= bgp_node_get_bgp_static_info(rn
);
12052 if (bgp_static
== NULL
)
12056 prd
= (struct prefix_rd
*)&prn
->p
;
12058 /* "network" configuration display. */
12059 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
12060 label
= decode_label(&bgp_static
->label
);
12062 vty_out(vty
, " network %s/%d rd %s",
12063 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
12065 p
->prefixlen
, rdbuf
);
12066 if (safi
== SAFI_MPLS_VPN
)
12067 vty_out(vty
, " label %u", label
);
12069 if (bgp_static
->rmap
.name
)
12070 vty_out(vty
, " route-map %s",
12071 bgp_static
->rmap
.name
);
12073 if (bgp_static
->backdoor
)
12074 vty_out(vty
, " backdoor");
12076 vty_out(vty
, "\n");
12081 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
12082 afi_t afi
, safi_t safi
)
12084 struct bgp_node
*prn
;
12085 struct bgp_node
*rn
;
12086 struct bgp_table
*table
;
12088 struct prefix_rd
*prd
;
12089 struct bgp_static
*bgp_static
;
12090 char buf
[PREFIX_STRLEN
* 2];
12091 char buf2
[SU_ADDRSTRLEN
];
12092 char rdbuf
[RD_ADDRSTRLEN
];
12094 /* Network configuration. */
12095 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
12096 prn
= bgp_route_next(prn
)) {
12097 table
= bgp_node_get_bgp_table_info(prn
);
12101 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
12102 bgp_static
= bgp_node_get_bgp_static_info(rn
);
12103 if (bgp_static
== NULL
)
12106 char *macrouter
= NULL
;
12109 if (bgp_static
->router_mac
)
12110 macrouter
= prefix_mac2str(
12111 bgp_static
->router_mac
, NULL
, 0);
12112 if (bgp_static
->eth_s_id
)
12113 esi
= esi2str(bgp_static
->eth_s_id
);
12115 prd
= (struct prefix_rd
*)&prn
->p
;
12117 /* "network" configuration display. */
12118 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
12119 if (p
->u
.prefix_evpn
.route_type
== 5) {
12120 char local_buf
[PREFIX_STRLEN
];
12121 uint8_t family
= is_evpn_prefix_ipaddr_v4((
12122 struct prefix_evpn
*)p
)
12126 &p
->u
.prefix_evpn
.prefix_addr
.ip
.ip
.addr
,
12127 local_buf
, PREFIX_STRLEN
);
12128 sprintf(buf
, "%s/%u", local_buf
,
12129 p
->u
.prefix_evpn
.prefix_addr
.ip_prefix_length
);
12131 prefix2str(p
, buf
, sizeof(buf
));
12134 if (bgp_static
->gatewayIp
.family
== AF_INET
12135 || bgp_static
->gatewayIp
.family
== AF_INET6
)
12136 inet_ntop(bgp_static
->gatewayIp
.family
,
12137 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
12140 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
12142 p
->u
.prefix_evpn
.prefix_addr
.eth_tag
,
12143 decode_label(&bgp_static
->label
), esi
, buf2
,
12146 XFREE(MTYPE_TMP
, macrouter
);
12147 XFREE(MTYPE_TMP
, esi
);
12152 /* Configuration of static route announcement and aggregate
12154 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12157 struct bgp_node
*rn
;
12159 struct bgp_static
*bgp_static
;
12160 struct bgp_aggregate
*bgp_aggregate
;
12161 char buf
[SU_ADDRSTRLEN
];
12163 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
12164 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
12168 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
12169 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
12173 /* Network configuration. */
12174 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
12175 rn
= bgp_route_next(rn
)) {
12176 bgp_static
= bgp_node_get_bgp_static_info(rn
);
12177 if (bgp_static
== NULL
)
12182 /* "network" configuration display. */
12183 if (bgp_option_check(BGP_OPT_CONFIG_CISCO
) && afi
== AFI_IP
) {
12184 uint32_t destination
;
12185 struct in_addr netmask
;
12187 destination
= ntohl(p
->u
.prefix4
.s_addr
);
12188 masklen2ip(p
->prefixlen
, &netmask
);
12189 vty_out(vty
, " network %s",
12190 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
12193 if ((IN_CLASSC(destination
) && p
->prefixlen
== 24)
12194 || (IN_CLASSB(destination
) && p
->prefixlen
== 16)
12195 || (IN_CLASSA(destination
) && p
->prefixlen
== 8)
12196 || p
->u
.prefix4
.s_addr
== 0) {
12197 /* Natural mask is not display. */
12199 vty_out(vty
, " mask %s", inet_ntoa(netmask
));
12201 vty_out(vty
, " network %s/%d",
12202 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
12207 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
12208 vty_out(vty
, " label-index %u",
12209 bgp_static
->label_index
);
12211 if (bgp_static
->rmap
.name
)
12212 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
12214 if (bgp_static
->backdoor
)
12215 vty_out(vty
, " backdoor");
12217 vty_out(vty
, "\n");
12220 /* Aggregate-address configuration. */
12221 for (rn
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); rn
;
12222 rn
= bgp_route_next(rn
)) {
12223 bgp_aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
12224 if (bgp_aggregate
== NULL
)
12229 if (bgp_option_check(BGP_OPT_CONFIG_CISCO
) && afi
== AFI_IP
) {
12230 struct in_addr netmask
;
12232 masklen2ip(p
->prefixlen
, &netmask
);
12233 vty_out(vty
, " aggregate-address %s %s",
12234 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
12236 inet_ntoa(netmask
));
12238 vty_out(vty
, " aggregate-address %s/%d",
12239 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
12244 if (bgp_aggregate
->as_set
)
12245 vty_out(vty
, " as-set");
12247 if (bgp_aggregate
->summary_only
)
12248 vty_out(vty
, " summary-only");
12250 vty_out(vty
, "\n");
12254 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12257 struct bgp_node
*rn
;
12258 struct bgp_distance
*bdistance
;
12260 /* Distance configuration. */
12261 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
12262 && bgp
->distance_local
[afi
][safi
]
12263 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
12264 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
12265 || bgp
->distance_local
[afi
][safi
]
12266 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
12267 vty_out(vty
, " distance bgp %d %d %d\n",
12268 bgp
->distance_ebgp
[afi
][safi
],
12269 bgp
->distance_ibgp
[afi
][safi
],
12270 bgp
->distance_local
[afi
][safi
]);
12273 for (rn
= bgp_table_top(bgp_distance_table
[afi
][safi
]); rn
;
12274 rn
= bgp_route_next(rn
)) {
12275 bdistance
= bgp_node_get_bgp_distance_info(rn
);
12276 if (bdistance
!= NULL
) {
12277 char buf
[PREFIX_STRLEN
];
12279 vty_out(vty
, " distance %d %s %s\n",
12280 bdistance
->distance
,
12281 prefix2str(&rn
->p
, buf
, sizeof(buf
)),
12282 bdistance
->access_list
? bdistance
->access_list
12288 /* Allocate routing table structure and install commands. */
12289 void bgp_route_init(void)
12294 /* Init BGP distance table. */
12295 FOREACH_AFI_SAFI (afi
, safi
)
12296 bgp_distance_table
[afi
][safi
] = bgp_table_init(NULL
, afi
, safi
);
12298 /* IPv4 BGP commands. */
12299 install_element(BGP_NODE
, &bgp_table_map_cmd
);
12300 install_element(BGP_NODE
, &bgp_network_cmd
);
12301 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
12303 install_element(BGP_NODE
, &aggregate_address_cmd
);
12304 install_element(BGP_NODE
, &aggregate_address_mask_cmd
);
12305 install_element(BGP_NODE
, &no_aggregate_address_cmd
);
12306 install_element(BGP_NODE
, &no_aggregate_address_mask_cmd
);
12308 /* IPv4 unicast configuration. */
12309 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
12310 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
12311 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
12313 install_element(BGP_IPV4_NODE
, &aggregate_address_cmd
);
12314 install_element(BGP_IPV4_NODE
, &aggregate_address_mask_cmd
);
12315 install_element(BGP_IPV4_NODE
, &no_aggregate_address_cmd
);
12316 install_element(BGP_IPV4_NODE
, &no_aggregate_address_mask_cmd
);
12318 /* IPv4 multicast configuration. */
12319 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
12320 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
12321 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
12322 install_element(BGP_IPV4M_NODE
, &aggregate_address_cmd
);
12323 install_element(BGP_IPV4M_NODE
, &aggregate_address_mask_cmd
);
12324 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_cmd
);
12325 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_mask_cmd
);
12327 /* IPv4 labeled-unicast configuration. */
12328 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
12329 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
12330 install_element(VIEW_NODE
, &show_ip_bgp_json_cmd
);
12331 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
12332 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
12334 install_element(VIEW_NODE
,
12335 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
12336 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
12337 install_element(VIEW_NODE
,
12338 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
12339 #ifdef KEEP_OLD_VPN_COMMANDS
12340 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
12341 #endif /* KEEP_OLD_VPN_COMMANDS */
12342 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
12343 install_element(VIEW_NODE
,
12344 &show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd
);
12346 /* BGP dampening clear commands */
12347 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
12348 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
12350 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
12351 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
12354 install_element(ENABLE_NODE
,
12355 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
12356 #ifdef KEEP_OLD_VPN_COMMANDS
12357 install_element(ENABLE_NODE
,
12358 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
12359 #endif /* KEEP_OLD_VPN_COMMANDS */
12361 /* New config IPv6 BGP commands. */
12362 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
12363 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
12364 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
12366 install_element(BGP_IPV6_NODE
, &ipv6_aggregate_address_cmd
);
12367 install_element(BGP_IPV6_NODE
, &no_ipv6_aggregate_address_cmd
);
12369 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
12371 install_element(BGP_NODE
, &bgp_distance_cmd
);
12372 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
12373 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
12374 install_element(BGP_NODE
, &no_bgp_distance_source_cmd
);
12375 install_element(BGP_NODE
, &bgp_distance_source_access_list_cmd
);
12376 install_element(BGP_NODE
, &no_bgp_distance_source_access_list_cmd
);
12377 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
12378 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
12379 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
12380 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_cmd
);
12381 install_element(BGP_IPV4_NODE
, &bgp_distance_source_access_list_cmd
);
12382 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_access_list_cmd
);
12383 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
12384 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
12385 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
12386 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_source_cmd
);
12387 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_access_list_cmd
);
12388 install_element(BGP_IPV4M_NODE
,
12389 &no_bgp_distance_source_access_list_cmd
);
12390 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
12391 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
12392 install_element(BGP_IPV6_NODE
, &ipv6_bgp_distance_source_cmd
);
12393 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_distance_source_cmd
);
12394 install_element(BGP_IPV6_NODE
,
12395 &ipv6_bgp_distance_source_access_list_cmd
);
12396 install_element(BGP_IPV6_NODE
,
12397 &no_ipv6_bgp_distance_source_access_list_cmd
);
12398 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
12399 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
12400 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_distance_source_cmd
);
12401 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_distance_source_cmd
);
12402 install_element(BGP_IPV6M_NODE
,
12403 &ipv6_bgp_distance_source_access_list_cmd
);
12404 install_element(BGP_IPV6M_NODE
,
12405 &no_ipv6_bgp_distance_source_access_list_cmd
);
12407 install_element(BGP_NODE
, &bgp_damp_set_cmd
);
12408 install_element(BGP_NODE
, &bgp_damp_unset_cmd
);
12409 install_element(BGP_IPV4_NODE
, &bgp_damp_set_cmd
);
12410 install_element(BGP_IPV4_NODE
, &bgp_damp_unset_cmd
);
12412 /* IPv4 Multicast Mode */
12413 install_element(BGP_IPV4M_NODE
, &bgp_damp_set_cmd
);
12414 install_element(BGP_IPV4M_NODE
, &bgp_damp_unset_cmd
);
12416 /* Large Communities */
12417 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
12418 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
12420 /* show bgp ipv4 flowspec detailed */
12421 install_element(VIEW_NODE
, &show_ip_bgp_flowspec_routes_detailed_cmd
);
12423 install_element(VIEW_NODE
, &show_bgp_peerhash_cmd
);
12426 void bgp_route_finish(void)
12431 FOREACH_AFI_SAFI (afi
, safi
) {
12432 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
12433 bgp_distance_table
[afi
][safi
] = NULL
;