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
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.
1717 if (NEXTHOP_IS_V6
) {
1718 attr
->mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
1719 if ((CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1720 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)
1721 && IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
))
1722 || (!reflect
&& peer
->shared_network
1723 && (from
== bgp
->peer_self
1724 || peer
->sort
== BGP_PEER_EBGP
))) {
1725 attr
->mp_nexthop_len
=
1726 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
;
1729 /* Clear off link-local nexthop in source, whenever it is not
1731 * ensure more prefixes share the same attribute for
1734 if (!(CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1735 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)))
1736 memset(&attr
->mp_nexthop_local
, 0, IPV6_MAX_BYTELEN
);
1739 bgp_peer_remove_private_as(bgp
, afi
, safi
, peer
, attr
);
1740 bgp_peer_as_override(bgp
, afi
, safi
, peer
, attr
);
1742 /* Route map & unsuppress-map apply. */
1743 if (ROUTE_MAP_OUT_NAME(filter
) || (pi
->extra
&& pi
->extra
->suppress
)) {
1744 struct bgp_path_info rmap_path
;
1745 struct bgp_path_info_extra dummy_rmap_path_extra
;
1746 struct attr dummy_attr
;
1748 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
1749 rmap_path
.peer
= peer
;
1750 rmap_path
.attr
= attr
;
1753 memcpy(&dummy_rmap_path_extra
, pi
->extra
,
1754 sizeof(struct bgp_path_info_extra
));
1755 rmap_path
.extra
= &dummy_rmap_path_extra
;
1758 /* don't confuse inbound and outbound setting */
1759 RESET_FLAG(attr
->rmap_change_flags
);
1762 * The route reflector is not allowed to modify the attributes
1763 * of the reflected IBGP routes unless explicitly allowed.
1765 if ((from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1766 && !bgp_flag_check(bgp
,
1767 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY
)) {
1768 bgp_attr_dup(&dummy_attr
, attr
);
1769 rmap_path
.attr
= &dummy_attr
;
1772 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1774 if (pi
->extra
&& pi
->extra
->suppress
)
1775 ret
= route_map_apply(UNSUPPRESS_MAP(filter
), p
,
1776 RMAP_BGP
, &rmap_path
);
1778 ret
= route_map_apply(ROUTE_MAP_OUT(filter
), p
,
1779 RMAP_BGP
, &rmap_path
);
1781 peer
->rmap_type
= 0;
1783 if (ret
== RMAP_DENYMATCH
) {
1784 bgp_attr_flush(attr
);
1789 /* RFC 8212 to prevent route leaks.
1790 * This specification intends to improve this situation by requiring the
1791 * explicit configuration of both BGP Import and Export Policies for any
1792 * External BGP (EBGP) session such as customers, peers, or
1793 * confederation boundaries for all enabled address families. Through
1794 * codification of the aforementioned requirement, operators will
1795 * benefit from consistent behavior across different BGP
1798 if (peer
->bgp
->ebgp_requires_policy
1799 == DEFAULT_EBGP_POLICY_ENABLED
)
1800 if (!bgp_outbound_policy_exists(peer
, filter
))
1803 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
1804 if (peer
->sort
== BGP_PEER_IBGP
1805 || peer
->sort
== BGP_PEER_CONFED
) {
1806 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1807 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1809 bgp_attr_add_gshut_community(attr
);
1813 /* After route-map has been applied, we check to see if the nexthop to
1814 * be carried in the attribute (that is used for the announcement) can
1815 * be cleared off or not. We do this in all cases where we would be
1816 * setting the nexthop to "ourselves". For IPv6, we only need to
1818 * the global nexthop here; the link-local nexthop would have been
1820 * already, and if not, it is required by the update formation code.
1821 * Also see earlier comments in this function.
1824 * If route-map has performed some operation on the nexthop or the peer
1825 * configuration says to pass it unchanged, we cannot reset the nexthop
1826 * here, so only attempt to do it if these aren't true. Note that the
1827 * route-map handler itself might have cleared the nexthop, if for
1829 * it is configured as 'peer-address'.
1831 if (!bgp_rmap_nhop_changed(attr
->rmap_change_flags
,
1832 piattr
->rmap_change_flags
)
1834 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1835 PEER_FLAG_NEXTHOP_UNCHANGED
)) {
1836 /* We can reset the nexthop, if setting (or forcing) it to
1838 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1839 PEER_FLAG_NEXTHOP_SELF
)
1840 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1841 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
1843 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1844 PEER_FLAG_FORCE_NEXTHOP_SELF
))
1845 subgroup_announce_reset_nhop(
1846 (peer_cap_enhe(peer
, afi
, safi
)
1850 } else if (peer
->sort
== BGP_PEER_EBGP
) {
1851 /* Can also reset the nexthop if announcing to EBGP, but
1853 * no peer in the subgroup is on a shared subnet.
1854 * Note: 3rd party nexthop currently implemented for
1857 if (!bgp_subgrp_multiaccess_check_v4(piattr
->nexthop
,
1859 subgroup_announce_reset_nhop(
1860 (peer_cap_enhe(peer
, afi
, safi
)
1864 } else if (CHECK_FLAG(pi
->flags
, BGP_PATH_ANNC_NH_SELF
)) {
1866 * This flag is used for leaked vpn-vrf routes
1868 int family
= p
->family
;
1870 if (peer_cap_enhe(peer
, afi
, safi
))
1873 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1875 "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
1876 __func__
, family2str(family
));
1877 subgroup_announce_reset_nhop(family
, attr
);
1880 /* If IPv6/MP and nexthop does not have any override and happens
1882 * be a link-local address, reset it so that we don't pass along
1884 * source's link-local IPv6 address to recipients who may not be
1886 * the same interface.
1888 if (p
->family
== AF_INET6
|| peer_cap_enhe(peer
, afi
, safi
)) {
1889 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
))
1890 subgroup_announce_reset_nhop(AF_INET6
, attr
);
1897 void bgp_best_selection(struct bgp
*bgp
, struct bgp_node
*rn
,
1898 struct bgp_maxpaths_cfg
*mpath_cfg
,
1899 struct bgp_path_info_pair
*result
, afi_t afi
,
1902 struct bgp_path_info
*new_select
;
1903 struct bgp_path_info
*old_select
;
1904 struct bgp_path_info
*pi
;
1905 struct bgp_path_info
*pi1
;
1906 struct bgp_path_info
*pi2
;
1907 struct bgp_path_info
*nextpi
= NULL
;
1908 int paths_eq
, do_mpath
, debug
;
1909 struct list mp_list
;
1910 char pfx_buf
[PREFIX2STR_BUFFER
];
1911 char path_buf
[PATH_ADDPATH_STR_BUFFER
];
1913 bgp_mp_list_init(&mp_list
);
1915 (mpath_cfg
->maxpaths_ebgp
> 1 || mpath_cfg
->maxpaths_ibgp
> 1);
1917 debug
= bgp_debug_bestpath(&rn
->p
);
1920 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
1922 /* bgp deterministic-med */
1924 if (bgp_flag_check(bgp
, BGP_FLAG_DETERMINISTIC_MED
)) {
1926 /* Clear BGP_PATH_DMED_SELECTED for all paths */
1927 for (pi1
= bgp_node_get_bgp_path_info(rn
); pi1
;
1929 bgp_path_info_unset_flag(rn
, pi1
,
1930 BGP_PATH_DMED_SELECTED
);
1932 for (pi1
= bgp_node_get_bgp_path_info(rn
); pi1
;
1934 if (CHECK_FLAG(pi1
->flags
, BGP_PATH_DMED_CHECK
))
1936 if (BGP_PATH_HOLDDOWN(pi1
))
1938 if (pi1
->peer
!= bgp
->peer_self
)
1939 if (pi1
->peer
->status
!= Established
)
1944 for (pi2
= pi1
->next
; pi2
; pi2
= pi2
->next
) {
1945 if (CHECK_FLAG(pi2
->flags
,
1946 BGP_PATH_DMED_CHECK
))
1948 if (BGP_PATH_HOLDDOWN(pi2
))
1950 if (pi2
->peer
!= bgp
->peer_self
1953 PEER_STATUS_NSF_WAIT
))
1954 if (pi2
->peer
->status
1958 if (!aspath_cmp_left(pi1
->attr
->aspath
,
1960 && !aspath_cmp_left_confed(
1965 if (bgp_path_info_cmp(
1966 bgp
, pi2
, new_select
,
1967 &paths_eq
, mpath_cfg
, debug
,
1968 pfx_buf
, afi
, safi
)) {
1969 bgp_path_info_unset_flag(
1971 BGP_PATH_DMED_SELECTED
);
1975 bgp_path_info_set_flag(
1976 rn
, pi2
, BGP_PATH_DMED_CHECK
);
1979 bgp_path_info_set_flag(rn
, new_select
,
1980 BGP_PATH_DMED_CHECK
);
1981 bgp_path_info_set_flag(rn
, new_select
,
1982 BGP_PATH_DMED_SELECTED
);
1985 bgp_path_info_path_with_addpath_rx_str(
1986 new_select
, path_buf
);
1987 zlog_debug("%s: %s is the bestpath from AS %u",
1989 aspath_get_first_as(
1990 new_select
->attr
->aspath
));
1995 /* Check old selected route and new selected route. */
1998 for (pi
= bgp_node_get_bgp_path_info(rn
);
1999 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2000 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
2003 if (BGP_PATH_HOLDDOWN(pi
)) {
2004 /* reap REMOVED routes, if needs be
2005 * selected route must stay for a while longer though
2007 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
2008 && (pi
!= old_select
))
2009 bgp_path_info_reap(rn
, pi
);
2012 zlog_debug("%s: pi %p in holddown", __func__
,
2018 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2019 && !CHECK_FLAG(pi
->peer
->sflags
, PEER_STATUS_NSF_WAIT
))
2020 if (pi
->peer
->status
!= Established
) {
2024 "%s: pi %p non self peer %s not estab state",
2025 __func__
, pi
, pi
->peer
->host
);
2030 if (bgp_flag_check(bgp
, BGP_FLAG_DETERMINISTIC_MED
)
2031 && (!CHECK_FLAG(pi
->flags
, BGP_PATH_DMED_SELECTED
))) {
2032 bgp_path_info_unset_flag(rn
, pi
, BGP_PATH_DMED_CHECK
);
2034 zlog_debug("%s: pi %p dmed", __func__
, pi
);
2038 bgp_path_info_unset_flag(rn
, pi
, BGP_PATH_DMED_CHECK
);
2040 if (bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
, mpath_cfg
,
2041 debug
, pfx_buf
, afi
, safi
)) {
2046 /* Now that we know which path is the bestpath see if any of the other
2048 * qualify as multipaths
2052 bgp_path_info_path_with_addpath_rx_str(new_select
,
2055 sprintf(path_buf
, "NONE");
2057 "%s: After path selection, newbest is %s oldbest was %s",
2059 old_select
? old_select
->peer
->host
: "NONE");
2062 if (do_mpath
&& new_select
) {
2063 for (pi
= bgp_node_get_bgp_path_info(rn
);
2064 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2067 bgp_path_info_path_with_addpath_rx_str(
2070 if (pi
== new_select
) {
2073 "%s: %s is the bestpath, add to the multipath list",
2075 bgp_mp_list_add(&mp_list
, pi
);
2079 if (BGP_PATH_HOLDDOWN(pi
))
2082 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2083 && !CHECK_FLAG(pi
->peer
->sflags
,
2084 PEER_STATUS_NSF_WAIT
))
2085 if (pi
->peer
->status
!= Established
)
2088 if (!bgp_path_info_nexthop_cmp(pi
, new_select
)) {
2091 "%s: %s has the same nexthop as the bestpath, skip it",
2096 bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
,
2097 mpath_cfg
, debug
, pfx_buf
, afi
, safi
);
2102 "%s: %s is equivalent to the bestpath, add to the multipath list",
2104 bgp_mp_list_add(&mp_list
, pi
);
2109 bgp_path_info_mpath_update(rn
, new_select
, old_select
, &mp_list
,
2111 bgp_path_info_mpath_aggregate_update(new_select
, old_select
);
2112 bgp_mp_list_clear(&mp_list
);
2114 bgp_addpath_update_ids(bgp
, rn
, afi
, safi
);
2116 result
->old
= old_select
;
2117 result
->new = new_select
;
2123 * A new route/change in bestpath of an existing route. Evaluate the path
2124 * for advertisement to the subgroup.
2126 int subgroup_process_announce_selected(struct update_subgroup
*subgrp
,
2127 struct bgp_path_info
*selected
,
2128 struct bgp_node
*rn
,
2129 uint32_t addpath_tx_id
)
2132 struct peer
*onlypeer
;
2138 afi
= SUBGRP_AFI(subgrp
);
2139 safi
= SUBGRP_SAFI(subgrp
);
2140 onlypeer
= ((SUBGRP_PCOUNT(subgrp
) == 1) ? (SUBGRP_PFIRST(subgrp
))->peer
2143 if (BGP_DEBUG(update
, UPDATE_OUT
)) {
2144 char buf_prefix
[PREFIX_STRLEN
];
2145 prefix2str(p
, buf_prefix
, sizeof(buf_prefix
));
2146 zlog_debug("%s: p=%s, selected=%p", __func__
, buf_prefix
,
2150 /* First update is deferred until ORF or ROUTE-REFRESH is received */
2151 if (onlypeer
&& CHECK_FLAG(onlypeer
->af_sflags
[afi
][safi
],
2152 PEER_STATUS_ORF_WAIT_REFRESH
))
2155 memset(&attr
, 0, sizeof(struct attr
));
2156 /* It's initialized in bgp_announce_check() */
2158 /* Announcement to the subgroup. If the route is filtered withdraw it.
2161 if (subgroup_announce_check(rn
, selected
, subgrp
, p
, &attr
))
2162 bgp_adj_out_set_subgroup(rn
, subgrp
, &attr
, selected
);
2164 bgp_adj_out_unset_subgroup(rn
, subgrp
, 1,
2168 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2170 bgp_adj_out_unset_subgroup(rn
, subgrp
, 1, addpath_tx_id
);
2177 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2178 * This is called at the end of route processing.
2180 void bgp_zebra_clear_route_change_flags(struct bgp_node
*rn
)
2182 struct bgp_path_info
*pi
;
2184 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
2185 if (BGP_PATH_HOLDDOWN(pi
))
2187 UNSET_FLAG(pi
->flags
, BGP_PATH_IGP_CHANGED
);
2188 UNSET_FLAG(pi
->flags
, BGP_PATH_ATTR_CHANGED
);
2193 * Has the route changed from the RIB's perspective? This is invoked only
2194 * if the route selection returns the same best route as earlier - to
2195 * determine if we need to update zebra or not.
2197 int bgp_zebra_has_route_changed(struct bgp_node
*rn
,
2198 struct bgp_path_info
*selected
)
2200 struct bgp_path_info
*mpinfo
;
2202 /* If this is multipath, check all selected paths for any nexthop
2203 * change or attribute change. Some attribute changes (e.g., community)
2204 * aren't of relevance to the RIB, but we'll update zebra to ensure
2205 * we handle the case of BGP nexthop change. This is the behavior
2206 * when the best path has an attribute change anyway.
2208 if (CHECK_FLAG(selected
->flags
, BGP_PATH_IGP_CHANGED
)
2209 || CHECK_FLAG(selected
->flags
, BGP_PATH_MULTIPATH_CHG
))
2213 * If this is multipath, check all selected paths for any nexthop change
2215 for (mpinfo
= bgp_path_info_mpath_first(selected
); mpinfo
;
2216 mpinfo
= bgp_path_info_mpath_next(mpinfo
)) {
2217 if (CHECK_FLAG(mpinfo
->flags
, BGP_PATH_IGP_CHANGED
)
2218 || CHECK_FLAG(mpinfo
->flags
, BGP_PATH_ATTR_CHANGED
))
2222 /* Nothing has changed from the RIB's perspective. */
2226 struct bgp_process_queue
{
2228 STAILQ_HEAD(, bgp_node
) pqueue
;
2229 #define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2231 unsigned int queued
;
2235 * old_select = The old best path
2236 * new_select = the new best path
2238 * if (!old_select && new_select)
2239 * We are sending new information on.
2241 * if (old_select && new_select) {
2242 * if (new_select != old_select)
2243 * We have a new best path send a change
2245 * We've received a update with new attributes that needs
2249 * if (old_select && !new_select)
2250 * We have no eligible route that we can announce or the rn
2253 static void bgp_process_main_one(struct bgp
*bgp
, struct bgp_node
*rn
,
2254 afi_t afi
, safi_t safi
)
2256 struct bgp_path_info
*new_select
;
2257 struct bgp_path_info
*old_select
;
2258 struct bgp_path_info_pair old_and_new
;
2259 char pfx_buf
[PREFIX2STR_BUFFER
];
2262 /* Is it end of initial update? (after startup) */
2264 quagga_timestamp(3, bgp
->update_delay_zebra_resume_time
,
2265 sizeof(bgp
->update_delay_zebra_resume_time
));
2267 bgp
->main_zebra_update_hold
= 0;
2268 FOREACH_AFI_SAFI (afi
, safi
) {
2269 if (bgp_fibupd_safi(safi
))
2270 bgp_zebra_announce_table(bgp
, afi
, safi
);
2272 bgp
->main_peers_update_hold
= 0;
2274 bgp_start_routeadv(bgp
);
2278 struct prefix
*p
= &rn
->p
;
2280 debug
= bgp_debug_bestpath(&rn
->p
);
2282 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
2283 zlog_debug("%s: p=%s afi=%s, safi=%s start", __func__
, pfx_buf
,
2284 afi2str(afi
), safi2str(safi
));
2287 /* Best path selection. */
2288 bgp_best_selection(bgp
, rn
, &bgp
->maxpaths
[afi
][safi
], &old_and_new
,
2290 old_select
= old_and_new
.old
;
2291 new_select
= old_and_new
.new;
2293 /* Do we need to allocate or free labels?
2294 * Right now, since we only deal with per-prefix labels, it is not
2295 * necessary to do this upon changes to best path. Exceptions:
2296 * - label index has changed -> recalculate resulting label
2297 * - path_info sub_type changed -> switch to/from implicit-null
2298 * - no valid label (due to removed static label binding) -> get new one
2300 if (bgp
->allocate_mpls_labels
[afi
][safi
]) {
2303 || bgp_label_index_differs(new_select
, old_select
)
2304 || new_select
->sub_type
!= old_select
->sub_type
2305 || !bgp_is_valid_label(&rn
->local_label
)) {
2306 /* Enforced penultimate hop popping:
2307 * implicit-null for local routes, aggregate
2308 * and redistributed routes
2310 if (new_select
->sub_type
== BGP_ROUTE_STATIC
2311 || new_select
->sub_type
2312 == BGP_ROUTE_AGGREGATE
2313 || new_select
->sub_type
2314 == BGP_ROUTE_REDISTRIBUTE
) {
2317 BGP_NODE_REGISTERED_FOR_LABEL
))
2318 bgp_unregister_for_label(rn
);
2319 label_ntop(MPLS_LABEL_IMPLICIT_NULL
, 1,
2321 bgp_set_valid_label(&rn
->local_label
);
2323 bgp_register_for_label(rn
, new_select
);
2325 } else if (CHECK_FLAG(rn
->flags
,
2326 BGP_NODE_REGISTERED_FOR_LABEL
)) {
2327 bgp_unregister_for_label(rn
);
2329 } else if (CHECK_FLAG(rn
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
)) {
2330 bgp_unregister_for_label(rn
);
2334 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
2336 "%s: p=%s afi=%s, safi=%s, old_select=%p, new_select=%p",
2337 __func__
, pfx_buf
, afi2str(afi
), safi2str(safi
),
2338 old_select
, new_select
);
2341 /* If best route remains the same and this is not due to user-initiated
2342 * clear, see exactly what needs to be done.
2344 if (old_select
&& old_select
== new_select
2345 && !CHECK_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
)
2346 && !CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
2347 && !bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
2348 if (bgp_zebra_has_route_changed(rn
, old_select
)) {
2350 vnc_import_bgp_add_route(bgp
, p
, old_select
);
2351 vnc_import_bgp_exterior_add_route(bgp
, p
, old_select
);
2353 if (bgp_fibupd_safi(safi
)
2354 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2356 if (new_select
->type
== ZEBRA_ROUTE_BGP
2357 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2358 || new_select
->sub_type
2359 == BGP_ROUTE_IMPORTED
))
2361 bgp_zebra_announce(rn
, p
, old_select
,
2365 UNSET_FLAG(old_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
2366 bgp_zebra_clear_route_change_flags(rn
);
2368 /* If there is a change of interest to peers, reannounce the
2370 if (CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
2371 || CHECK_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
)) {
2372 group_announce_route(bgp
, afi
, safi
, rn
, new_select
);
2374 /* unicast routes must also be annouced to
2375 * labeled-unicast update-groups */
2376 if (safi
== SAFI_UNICAST
)
2377 group_announce_route(bgp
, afi
,
2378 SAFI_LABELED_UNICAST
, rn
,
2381 UNSET_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
);
2382 UNSET_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
);
2385 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2389 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2391 UNSET_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
);
2393 /* bestpath has changed; bump version */
2394 if (old_select
|| new_select
) {
2395 bgp_bump_version(rn
);
2397 if (!bgp
->t_rmap_def_originate_eval
) {
2401 update_group_refresh_default_originate_route_map
,
2402 bgp
, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER
,
2403 &bgp
->t_rmap_def_originate_eval
);
2408 bgp_path_info_unset_flag(rn
, old_select
, BGP_PATH_SELECTED
);
2411 zlog_debug("%s: setting SELECTED flag", __func__
);
2412 bgp_path_info_set_flag(rn
, new_select
, BGP_PATH_SELECTED
);
2413 bgp_path_info_unset_flag(rn
, new_select
, BGP_PATH_ATTR_CHANGED
);
2414 UNSET_FLAG(new_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
2418 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2419 if (old_select
!= new_select
) {
2421 vnc_import_bgp_exterior_del_route(bgp
, p
,
2423 vnc_import_bgp_del_route(bgp
, p
, old_select
);
2426 vnc_import_bgp_exterior_add_route(bgp
, p
,
2428 vnc_import_bgp_add_route(bgp
, p
, new_select
);
2434 group_announce_route(bgp
, afi
, safi
, rn
, new_select
);
2436 /* unicast routes must also be annouced to labeled-unicast update-groups
2438 if (safi
== SAFI_UNICAST
)
2439 group_announce_route(bgp
, afi
, SAFI_LABELED_UNICAST
, rn
,
2443 if (bgp_fibupd_safi(safi
) && (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VIEW
)
2444 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2445 if (new_select
&& new_select
->type
== ZEBRA_ROUTE_BGP
2446 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2447 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
2448 || new_select
->sub_type
== BGP_ROUTE_IMPORTED
)) {
2450 /* if this is an evpn imported type-5 prefix,
2451 * we need to withdraw the route first to clear
2452 * the nh neigh and the RMAC entry.
2455 is_route_parent_evpn(old_select
))
2456 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2458 bgp_zebra_announce(rn
, p
, new_select
, bgp
, afi
, safi
);
2460 /* Withdraw the route from the kernel. */
2461 if (old_select
&& old_select
->type
== ZEBRA_ROUTE_BGP
2462 && (old_select
->sub_type
== BGP_ROUTE_NORMAL
2463 || old_select
->sub_type
== BGP_ROUTE_AGGREGATE
2464 || old_select
->sub_type
== BGP_ROUTE_IMPORTED
))
2466 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2470 /* advertise/withdraw type-5 routes */
2471 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2472 if (advertise_type5_routes(bgp
, afi
) &&
2474 is_route_injectable_into_evpn(new_select
)) {
2476 /* apply the route-map */
2477 if (bgp
->adv_cmd_rmap
[afi
][safi
].map
) {
2480 ret
= route_map_apply(
2481 bgp
->adv_cmd_rmap
[afi
][safi
].map
,
2482 &rn
->p
, RMAP_BGP
, new_select
);
2483 if (ret
== RMAP_MATCH
)
2484 bgp_evpn_advertise_type5_route(
2485 bgp
, &rn
->p
, new_select
->attr
,
2488 bgp_evpn_withdraw_type5_route(
2489 bgp
, &rn
->p
, afi
, safi
);
2491 bgp_evpn_advertise_type5_route(bgp
,
2497 } else if (advertise_type5_routes(bgp
, afi
) &&
2499 is_route_injectable_into_evpn(old_select
))
2500 bgp_evpn_withdraw_type5_route(bgp
, &rn
->p
, afi
, safi
);
2503 /* Clear any route change flags. */
2504 bgp_zebra_clear_route_change_flags(rn
);
2506 /* Reap old select bgp_path_info, if it has been removed */
2507 if (old_select
&& CHECK_FLAG(old_select
->flags
, BGP_PATH_REMOVED
))
2508 bgp_path_info_reap(rn
, old_select
);
2510 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2514 static wq_item_status
bgp_process_wq(struct work_queue
*wq
, void *data
)
2516 struct bgp_process_queue
*pqnode
= data
;
2517 struct bgp
*bgp
= pqnode
->bgp
;
2518 struct bgp_table
*table
;
2519 struct bgp_node
*rn
;
2522 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)) {
2523 bgp_process_main_one(bgp
, NULL
, 0, 0);
2524 /* should always have dedicated wq call */
2525 assert(STAILQ_FIRST(&pqnode
->pqueue
) == NULL
);
2529 while (!STAILQ_EMPTY(&pqnode
->pqueue
)) {
2530 rn
= STAILQ_FIRST(&pqnode
->pqueue
);
2531 STAILQ_REMOVE_HEAD(&pqnode
->pqueue
, pq
);
2532 STAILQ_NEXT(rn
, pq
) = NULL
; /* complete unlink */
2533 table
= bgp_node_table(rn
);
2534 /* note, new RNs may be added as part of processing */
2535 bgp_process_main_one(bgp
, rn
, table
->afi
, table
->safi
);
2537 bgp_unlock_node(rn
);
2538 bgp_table_unlock(table
);
2544 static void bgp_processq_del(struct work_queue
*wq
, void *data
)
2546 struct bgp_process_queue
*pqnode
= data
;
2548 bgp_unlock(pqnode
->bgp
);
2550 XFREE(MTYPE_BGP_PROCESS_QUEUE
, pqnode
);
2553 void bgp_process_queue_init(void)
2555 if (!bm
->process_main_queue
)
2556 bm
->process_main_queue
=
2557 work_queue_new(bm
->master
, "process_main_queue");
2559 bm
->process_main_queue
->spec
.workfunc
= &bgp_process_wq
;
2560 bm
->process_main_queue
->spec
.del_item_data
= &bgp_processq_del
;
2561 bm
->process_main_queue
->spec
.max_retries
= 0;
2562 bm
->process_main_queue
->spec
.hold
= 50;
2563 /* Use a higher yield value of 50ms for main queue processing */
2564 bm
->process_main_queue
->spec
.yield
= 50 * 1000L;
2567 static struct bgp_process_queue
*bgp_processq_alloc(struct bgp
*bgp
)
2569 struct bgp_process_queue
*pqnode
;
2571 pqnode
= XCALLOC(MTYPE_BGP_PROCESS_QUEUE
,
2572 sizeof(struct bgp_process_queue
));
2574 /* unlocked in bgp_processq_del */
2575 pqnode
->bgp
= bgp_lock(bgp
);
2576 STAILQ_INIT(&pqnode
->pqueue
);
2581 void bgp_process(struct bgp
*bgp
, struct bgp_node
*rn
, afi_t afi
, safi_t safi
)
2583 #define ARBITRARY_PROCESS_QLEN 10000
2584 struct work_queue
*wq
= bm
->process_main_queue
;
2585 struct bgp_process_queue
*pqnode
;
2586 int pqnode_reuse
= 0;
2588 /* already scheduled for processing? */
2589 if (CHECK_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
2595 /* Add route nodes to an existing work queue item until reaching the
2596 limit only if is from the same BGP view and it's not an EOIU marker
2598 if (work_queue_item_count(wq
)) {
2599 struct work_queue_item
*item
= work_queue_last_item(wq
);
2600 pqnode
= item
->data
;
2602 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)
2603 || pqnode
->bgp
!= bgp
2604 || pqnode
->queued
>= ARBITRARY_PROCESS_QLEN
)
2605 pqnode
= bgp_processq_alloc(bgp
);
2609 pqnode
= bgp_processq_alloc(bgp
);
2610 /* all unlocked in bgp_process_wq */
2611 bgp_table_lock(bgp_node_table(rn
));
2613 SET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2616 /* can't be enqueued twice */
2617 assert(STAILQ_NEXT(rn
, pq
) == NULL
);
2618 STAILQ_INSERT_TAIL(&pqnode
->pqueue
, rn
, pq
);
2622 work_queue_add(wq
, pqnode
);
2627 void bgp_add_eoiu_mark(struct bgp
*bgp
)
2629 struct bgp_process_queue
*pqnode
;
2631 if (bm
->process_main_queue
== NULL
)
2634 pqnode
= bgp_processq_alloc(bgp
);
2636 SET_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
);
2637 work_queue_add(bm
->process_main_queue
, pqnode
);
2640 static int bgp_maximum_prefix_restart_timer(struct thread
*thread
)
2644 peer
= THREAD_ARG(thread
);
2645 peer
->t_pmax_restart
= NULL
;
2647 if (bgp_debug_neighbor_events(peer
))
2649 "%s Maximum-prefix restart timer expired, restore peering",
2652 if ((peer_clear(peer
, NULL
) < 0) && bgp_debug_neighbor_events(peer
))
2653 zlog_debug("%s: %s peer_clear failed",
2654 __PRETTY_FUNCTION__
, peer
->host
);
2659 int bgp_maximum_prefix_overflow(struct peer
*peer
, afi_t afi
, safi_t safi
,
2663 iana_safi_t pkt_safi
;
2665 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX
))
2668 if (peer
->pcount
[afi
][safi
] > peer
->pmax
[afi
][safi
]) {
2669 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2670 PEER_STATUS_PREFIX_LIMIT
)
2675 "%%MAXPFXEXCEED: No. of %s prefix received from %s %ld exceed, "
2677 afi_safi_print(afi
, safi
), peer
->host
,
2678 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2679 SET_FLAG(peer
->af_sflags
[afi
][safi
], PEER_STATUS_PREFIX_LIMIT
);
2681 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2682 PEER_FLAG_MAX_PREFIX_WARNING
))
2685 /* Convert AFI, SAFI to values for packet. */
2686 pkt_afi
= afi_int2iana(afi
);
2687 pkt_safi
= safi_int2iana(safi
);
2691 ndata
[0] = (pkt_afi
>> 8);
2693 ndata
[2] = pkt_safi
;
2694 ndata
[3] = (peer
->pmax
[afi
][safi
] >> 24);
2695 ndata
[4] = (peer
->pmax
[afi
][safi
] >> 16);
2696 ndata
[5] = (peer
->pmax
[afi
][safi
] >> 8);
2697 ndata
[6] = (peer
->pmax
[afi
][safi
]);
2699 SET_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
);
2700 bgp_notify_send_with_data(peer
, BGP_NOTIFY_CEASE
,
2701 BGP_NOTIFY_CEASE_MAX_PREFIX
,
2705 /* Dynamic peers will just close their connection. */
2706 if (peer_dynamic_neighbor(peer
))
2709 /* restart timer start */
2710 if (peer
->pmax_restart
[afi
][safi
]) {
2711 peer
->v_pmax_restart
=
2712 peer
->pmax_restart
[afi
][safi
] * 60;
2714 if (bgp_debug_neighbor_events(peer
))
2716 "%s Maximum-prefix restart timer started for %d secs",
2717 peer
->host
, peer
->v_pmax_restart
);
2719 BGP_TIMER_ON(peer
->t_pmax_restart
,
2720 bgp_maximum_prefix_restart_timer
,
2721 peer
->v_pmax_restart
);
2726 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
2727 PEER_STATUS_PREFIX_LIMIT
);
2729 if (peer
->pcount
[afi
][safi
]
2730 > (peer
->pmax
[afi
][safi
] * peer
->pmax_threshold
[afi
][safi
] / 100)) {
2731 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2732 PEER_STATUS_PREFIX_THRESHOLD
)
2737 "%%MAXPFX: No. of %s prefix received from %s reaches %ld, max %ld",
2738 afi_safi_print(afi
, safi
), peer
->host
,
2739 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2740 SET_FLAG(peer
->af_sflags
[afi
][safi
],
2741 PEER_STATUS_PREFIX_THRESHOLD
);
2743 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
2744 PEER_STATUS_PREFIX_THRESHOLD
);
2748 /* Unconditionally remove the route from the RIB, without taking
2749 * damping into consideration (eg, because the session went down)
2751 void bgp_rib_remove(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
2752 struct peer
*peer
, afi_t afi
, safi_t safi
)
2754 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, pi
, afi
, safi
);
2756 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
2757 bgp_path_info_delete(rn
, pi
); /* keep historical info */
2759 bgp_process(peer
->bgp
, rn
, afi
, safi
);
2762 static void bgp_rib_withdraw(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
2763 struct peer
*peer
, afi_t afi
, safi_t safi
,
2764 struct prefix_rd
*prd
)
2766 /* apply dampening, if result is suppressed, we'll be retaining
2767 * the bgp_path_info in the RIB for historical reference.
2769 if (CHECK_FLAG(peer
->bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
2770 && peer
->sort
== BGP_PEER_EBGP
)
2771 if ((bgp_damp_withdraw(pi
, rn
, afi
, safi
, 0))
2772 == BGP_DAMP_SUPPRESSED
) {
2773 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, pi
, afi
,
2779 if (safi
== SAFI_MPLS_VPN
) {
2780 struct bgp_node
*prn
= NULL
;
2781 struct bgp_table
*table
= NULL
;
2783 prn
= bgp_node_get(peer
->bgp
->rib
[afi
][safi
],
2784 (struct prefix
*)prd
);
2785 if (bgp_node_has_bgp_path_info_data(prn
)) {
2786 table
= bgp_node_get_bgp_table_info(prn
);
2788 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
2789 peer
->bgp
, prd
, table
, &rn
->p
, pi
);
2791 bgp_unlock_node(prn
);
2793 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2794 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
2796 vnc_import_bgp_del_route(peer
->bgp
, &rn
->p
, pi
);
2797 vnc_import_bgp_exterior_del_route(peer
->bgp
, &rn
->p
,
2803 /* If this is an EVPN route, process for un-import. */
2804 if (safi
== SAFI_EVPN
)
2805 bgp_evpn_unimport_route(peer
->bgp
, afi
, safi
, &rn
->p
, pi
);
2807 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
2810 struct bgp_path_info
*info_make(int type
, int sub_type
, unsigned short instance
,
2811 struct peer
*peer
, struct attr
*attr
,
2812 struct bgp_node
*rn
)
2814 struct bgp_path_info
*new;
2816 /* Make new BGP info. */
2817 new = XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_path_info
));
2819 new->instance
= instance
;
2820 new->sub_type
= sub_type
;
2823 new->uptime
= bgp_clock();
2828 static void overlay_index_update(struct attr
*attr
,
2829 struct eth_segment_id
*eth_s_id
,
2830 union gw_addr
*gw_ip
)
2835 if (eth_s_id
== NULL
) {
2836 memset(&(attr
->evpn_overlay
.eth_s_id
), 0,
2837 sizeof(struct eth_segment_id
));
2839 memcpy(&(attr
->evpn_overlay
.eth_s_id
), eth_s_id
,
2840 sizeof(struct eth_segment_id
));
2842 if (gw_ip
== NULL
) {
2843 memset(&(attr
->evpn_overlay
.gw_ip
), 0, sizeof(union gw_addr
));
2845 memcpy(&(attr
->evpn_overlay
.gw_ip
), gw_ip
,
2846 sizeof(union gw_addr
));
2850 static bool overlay_index_equal(afi_t afi
, struct bgp_path_info
*path
,
2851 struct eth_segment_id
*eth_s_id
,
2852 union gw_addr
*gw_ip
)
2854 struct eth_segment_id
*path_eth_s_id
, *path_eth_s_id_remote
;
2855 union gw_addr
*path_gw_ip
, *path_gw_ip_remote
;
2857 struct eth_segment_id esi
;
2861 if (afi
!= AFI_L2VPN
)
2864 memset(&temp
, 0, sizeof(temp
));
2865 path_eth_s_id
= &temp
.esi
;
2866 path_gw_ip
= &temp
.ip
;
2868 if (eth_s_id
== NULL
&& gw_ip
== NULL
)
2871 path_eth_s_id
= &(path
->attr
->evpn_overlay
.eth_s_id
);
2872 path_gw_ip
= &(path
->attr
->evpn_overlay
.gw_ip
);
2875 if (gw_ip
== NULL
) {
2876 memset(&temp
, 0, sizeof(temp
));
2877 path_gw_ip_remote
= &temp
.ip
;
2879 path_gw_ip_remote
= gw_ip
;
2881 if (eth_s_id
== NULL
) {
2882 memset(&temp
, 0, sizeof(temp
));
2883 path_eth_s_id_remote
= &temp
.esi
;
2885 path_eth_s_id_remote
= eth_s_id
;
2887 if (!memcmp(path_gw_ip
, path_gw_ip_remote
, sizeof(union gw_addr
)))
2890 return !memcmp(path_eth_s_id
, path_eth_s_id_remote
,
2891 sizeof(struct eth_segment_id
));
2894 /* Check if received nexthop is valid or not. */
2895 static int bgp_update_martian_nexthop(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
2900 /* Only validated for unicast and multicast currently. */
2901 /* Also valid for EVPN where the nexthop is an IP address. */
2902 if (safi
!= SAFI_UNICAST
&& safi
!= SAFI_MULTICAST
&& safi
!= SAFI_EVPN
)
2905 /* If NEXT_HOP is present, validate it. */
2906 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
2907 if (attr
->nexthop
.s_addr
== 0
2908 || IPV4_CLASS_DE(ntohl(attr
->nexthop
.s_addr
))
2909 || bgp_nexthop_self(bgp
, attr
->nexthop
))
2913 /* If MP_NEXTHOP is present, validate it. */
2914 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
2915 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
2916 * it is not an IPv6 link-local address.
2918 if (attr
->mp_nexthop_len
) {
2919 switch (attr
->mp_nexthop_len
) {
2920 case BGP_ATTR_NHLEN_IPV4
:
2921 case BGP_ATTR_NHLEN_VPNV4
:
2922 ret
= (attr
->mp_nexthop_global_in
.s_addr
== 0
2923 || IPV4_CLASS_DE(ntohl(
2924 attr
->mp_nexthop_global_in
.s_addr
))
2925 || bgp_nexthop_self(bgp
,
2926 attr
->mp_nexthop_global_in
));
2929 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
2930 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
2931 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
2932 ret
= (IN6_IS_ADDR_UNSPECIFIED(&attr
->mp_nexthop_global
)
2933 || IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
2934 || IN6_IS_ADDR_MULTICAST(
2935 &attr
->mp_nexthop_global
));
2947 int bgp_update(struct peer
*peer
, struct prefix
*p
, uint32_t addpath_id
,
2948 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
2949 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
2950 uint32_t num_labels
, int soft_reconfig
,
2951 struct bgp_route_evpn
*evpn
)
2954 int aspath_loop_count
= 0;
2955 struct bgp_node
*rn
;
2957 struct attr new_attr
;
2958 struct attr
*attr_new
;
2959 struct bgp_path_info
*pi
;
2960 struct bgp_path_info
*new;
2961 struct bgp_path_info_extra
*extra
;
2963 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
2965 int do_loop_check
= 1;
2966 int has_valid_label
= 0;
2968 int vnc_implicit_withdraw
= 0;
2972 memset(&new_attr
, 0, sizeof(struct attr
));
2973 new_attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
2974 new_attr
.label
= MPLS_INVALID_LABEL
;
2977 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
2978 /* TODO: Check to see if we can get rid of "is_valid_label" */
2979 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
2980 has_valid_label
= (num_labels
> 0) ? 1 : 0;
2982 has_valid_label
= bgp_is_valid_label(label
);
2984 /* When peer's soft reconfiguration enabled. Record input packet in
2987 && CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
2988 && peer
!= bgp
->peer_self
)
2989 bgp_adj_in_set(rn
, peer
, attr
, addpath_id
);
2991 /* Check previously received route. */
2992 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
2993 if (pi
->peer
== peer
&& pi
->type
== type
2994 && pi
->sub_type
== sub_type
2995 && pi
->addpath_rx_id
== addpath_id
)
2998 /* AS path local-as loop check. */
2999 if (peer
->change_local_as
) {
3000 if (peer
->allowas_in
[afi
][safi
])
3001 aspath_loop_count
= peer
->allowas_in
[afi
][safi
];
3002 else if (!CHECK_FLAG(peer
->flags
,
3003 PEER_FLAG_LOCAL_AS_NO_PREPEND
))
3004 aspath_loop_count
= 1;
3006 if (aspath_loop_check(attr
->aspath
, peer
->change_local_as
)
3007 > aspath_loop_count
) {
3008 reason
= "as-path contains our own AS;";
3013 /* If the peer is configured for "allowas-in origin" and the last ASN in
3015 * as-path is our ASN then we do not need to call aspath_loop_check
3017 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN_ORIGIN
))
3018 if (aspath_get_last_as(attr
->aspath
) == bgp
->as
)
3021 /* AS path loop check. */
3022 if (do_loop_check
) {
3023 if (aspath_loop_check(attr
->aspath
, bgp
->as
)
3024 > peer
->allowas_in
[afi
][safi
]
3025 || (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)
3026 && aspath_loop_check(attr
->aspath
, bgp
->confed_id
)
3027 > peer
->allowas_in
[afi
][safi
])) {
3028 reason
= "as-path contains our own AS;";
3033 /* Route reflector originator ID check. */
3034 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
3035 && IPV4_ADDR_SAME(&bgp
->router_id
, &attr
->originator_id
)) {
3036 reason
= "originator is us;";
3040 /* Route reflector cluster ID check. */
3041 if (bgp_cluster_filter(peer
, attr
)) {
3042 reason
= "reflected from the same cluster;";
3046 /* Apply incoming filter. */
3047 if (bgp_input_filter(peer
, p
, attr
, afi
, safi
) == FILTER_DENY
) {
3052 bgp_attr_dup(&new_attr
, attr
);
3054 /* Apply incoming route-map.
3055 * NB: new_attr may now contain newly allocated values from route-map
3057 * commands, so we need bgp_attr_flush in the error paths, until we
3059 * the attr (which takes over the memory references) */
3060 if (bgp_input_modifier(peer
, p
, &new_attr
, afi
, safi
, NULL
)
3062 reason
= "route-map;";
3063 bgp_attr_flush(&new_attr
);
3067 if (peer
->sort
== BGP_PEER_EBGP
) {
3069 /* If we receive the graceful-shutdown community from an eBGP
3070 * peer we must lower local-preference */
3071 if (new_attr
.community
3072 && community_include(new_attr
.community
, COMMUNITY_GSHUT
)) {
3073 new_attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
3074 new_attr
.local_pref
= BGP_GSHUT_LOCAL_PREF
;
3076 /* If graceful-shutdown is configured then add the GSHUT
3077 * community to all paths received from eBGP peers */
3078 } else if (bgp_flag_check(peer
->bgp
,
3079 BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
3080 bgp_attr_add_gshut_community(&new_attr
);
3084 /* next hop check. */
3085 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
)
3086 && bgp_update_martian_nexthop(bgp
, afi
, safi
, &new_attr
)) {
3087 reason
= "martian or self next-hop;";
3088 bgp_attr_flush(&new_attr
);
3092 if (bgp_mac_entry_exists(p
) || bgp_mac_exist(&attr
->rmac
)) {
3093 reason
= "self mac;";
3097 attr_new
= bgp_attr_intern(&new_attr
);
3099 /* If the update is implicit withdraw. */
3101 pi
->uptime
= bgp_clock();
3102 same_attr
= attrhash_cmp(pi
->attr
, attr_new
);
3104 /* Same attribute comes in. */
3105 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
3106 && attrhash_cmp(pi
->attr
, attr_new
)
3107 && (!has_valid_label
3108 || memcmp(&(bgp_path_info_extra_get(pi
))->label
, label
,
3109 num_labels
* sizeof(mpls_label_t
))
3111 && (overlay_index_equal(
3112 afi
, pi
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3113 evpn
== NULL
? NULL
: &evpn
->gw_ip
))) {
3114 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
3115 BGP_CONFIG_DAMPENING
)
3116 && peer
->sort
== BGP_PEER_EBGP
3117 && CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3118 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3119 bgp_debug_rdpfxpath2str(
3120 afi
, safi
, prd
, p
, label
,
3121 num_labels
, addpath_id
? 1 : 0,
3122 addpath_id
, pfx_buf
,
3124 zlog_debug("%s rcvd %s", peer
->host
,
3128 if (bgp_damp_update(pi
, rn
, afi
, safi
)
3129 != BGP_DAMP_SUPPRESSED
) {
3130 bgp_aggregate_increment(bgp
, p
, pi
, afi
,
3132 bgp_process(bgp
, rn
, afi
, safi
);
3134 } else /* Duplicate - odd */
3136 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3137 if (!peer
->rcvd_attr_printed
) {
3139 "%s rcvd UPDATE w/ attr: %s",
3141 peer
->rcvd_attr_str
);
3142 peer
->rcvd_attr_printed
= 1;
3145 bgp_debug_rdpfxpath2str(
3146 afi
, safi
, prd
, p
, label
,
3147 num_labels
, addpath_id
? 1 : 0,
3148 addpath_id
, pfx_buf
,
3151 "%s rcvd %s...duplicate ignored",
3152 peer
->host
, pfx_buf
);
3155 /* graceful restart STALE flag unset. */
3156 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
3157 bgp_path_info_unset_flag(
3158 rn
, pi
, BGP_PATH_STALE
);
3159 bgp_process(bgp
, rn
, afi
, safi
);
3163 bgp_unlock_node(rn
);
3164 bgp_attr_unintern(&attr_new
);
3169 /* Withdraw/Announce before we fully processed the withdraw */
3170 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
3171 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3172 bgp_debug_rdpfxpath2str(
3173 afi
, safi
, prd
, p
, label
, num_labels
,
3174 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3177 "%s rcvd %s, flapped quicker than processing",
3178 peer
->host
, pfx_buf
);
3181 bgp_path_info_restore(rn
, pi
);
3184 /* Received Logging. */
3185 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3186 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
3187 num_labels
, addpath_id
? 1 : 0,
3188 addpath_id
, pfx_buf
,
3190 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3193 /* graceful restart STALE flag unset. */
3194 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
3195 bgp_path_info_unset_flag(rn
, pi
, BGP_PATH_STALE
);
3197 /* The attribute is changed. */
3198 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_ATTR_CHANGED
);
3200 /* implicit withdraw, decrement aggregate and pcount here.
3201 * only if update is accepted, they'll increment below.
3203 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
3205 /* Update bgp route dampening information. */
3206 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3207 && peer
->sort
== BGP_PEER_EBGP
) {
3208 /* This is implicit withdraw so we should update
3211 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
3212 bgp_damp_withdraw(pi
, rn
, afi
, safi
, 1);
3215 if (safi
== SAFI_MPLS_VPN
) {
3216 struct bgp_node
*prn
= NULL
;
3217 struct bgp_table
*table
= NULL
;
3219 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3220 (struct prefix
*)prd
);
3221 if (bgp_node_has_bgp_path_info_data(prn
)) {
3222 table
= bgp_node_get_bgp_table_info(prn
);
3224 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3225 bgp
, prd
, table
, p
, pi
);
3227 bgp_unlock_node(prn
);
3229 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3230 && (safi
== SAFI_UNICAST
)) {
3231 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
3233 * Implicit withdraw case.
3235 ++vnc_implicit_withdraw
;
3236 vnc_import_bgp_del_route(bgp
, p
, pi
);
3237 vnc_import_bgp_exterior_del_route(bgp
, p
, pi
);
3242 /* Special handling for EVPN update of an existing route. If the
3243 * extended community attribute has changed, we need to
3245 * the route using its existing extended community. It will be
3246 * subsequently processed for import with the new extended
3249 if (safi
== SAFI_EVPN
&& !same_attr
) {
3251 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))
3253 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
3256 cmp
= ecommunity_cmp(pi
->attr
->ecommunity
,
3257 attr_new
->ecommunity
);
3259 if (bgp_debug_update(peer
, p
, NULL
, 1))
3261 "Change in EXT-COMM, existing %s new %s",
3263 pi
->attr
->ecommunity
),
3265 attr_new
->ecommunity
));
3266 bgp_evpn_unimport_route(bgp
, afi
, safi
,
3272 /* Update to new attribute. */
3273 bgp_attr_unintern(&pi
->attr
);
3274 pi
->attr
= attr_new
;
3276 /* Update MPLS label */
3277 if (has_valid_label
) {
3278 extra
= bgp_path_info_extra_get(pi
);
3279 if (extra
->label
!= label
) {
3280 memcpy(&extra
->label
, label
,
3281 num_labels
* sizeof(mpls_label_t
));
3282 extra
->num_labels
= num_labels
;
3284 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3285 bgp_set_valid_label(&extra
->label
[0]);
3289 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3290 && (safi
== SAFI_UNICAST
)) {
3291 if (vnc_implicit_withdraw
) {
3293 * Add back the route with its new attributes
3295 * The route is still selected, until the route
3297 * queued by bgp_process actually runs. We have
3299 * update to the VNC side immediately to avoid
3301 * configuration changes (e.g., route-map
3303 * trigger re-importation of the entire RIB.
3305 vnc_import_bgp_add_route(bgp
, p
, pi
);
3306 vnc_import_bgp_exterior_add_route(bgp
, p
, pi
);
3310 /* Update Overlay Index */
3311 if (afi
== AFI_L2VPN
) {
3312 overlay_index_update(
3313 pi
->attr
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3314 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3317 /* Update bgp route dampening information. */
3318 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3319 && peer
->sort
== BGP_PEER_EBGP
) {
3320 /* Now we do normal update dampening. */
3321 ret
= bgp_damp_update(pi
, rn
, afi
, safi
);
3322 if (ret
== BGP_DAMP_SUPPRESSED
) {
3323 bgp_unlock_node(rn
);
3328 /* Nexthop reachability check - for unicast and
3329 * labeled-unicast.. */
3330 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3331 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
3332 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
3333 && !CHECK_FLAG(peer
->flags
,
3334 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3336 bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3341 struct bgp
*bgp_nexthop
= bgp
;
3343 if (pi
->extra
&& pi
->extra
->bgp_orig
)
3344 bgp_nexthop
= pi
->extra
->bgp_orig
;
3346 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
, afi
, pi
,
3348 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3349 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_VALID
);
3351 if (BGP_DEBUG(nht
, NHT
)) {
3352 char buf1
[INET6_ADDRSTRLEN
];
3354 (const void *)&attr_new
3356 buf1
, INET6_ADDRSTRLEN
);
3357 zlog_debug("%s(%s): NH unresolved",
3358 __FUNCTION__
, buf1
);
3360 bgp_path_info_unset_flag(rn
, pi
,
3364 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_VALID
);
3367 if (safi
== SAFI_MPLS_VPN
) {
3368 struct bgp_node
*prn
= NULL
;
3369 struct bgp_table
*table
= NULL
;
3371 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3372 (struct prefix
*)prd
);
3373 if (bgp_node_has_bgp_path_info_data(prn
)) {
3374 table
= bgp_node_get_bgp_table_info(prn
);
3376 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3377 bgp
, prd
, table
, p
, pi
);
3379 bgp_unlock_node(prn
);
3383 /* If this is an EVPN route and some attribute has changed,
3385 * route for import. If the extended community has changed, we
3387 * have done the un-import earlier and the import would result
3389 * route getting injected into appropriate L2 VNIs. If it is
3391 * some other attribute change, the import will result in
3393 * the attributes for the route in the VNI(s).
3395 if (safi
== SAFI_EVPN
&& !same_attr
)
3396 bgp_evpn_import_route(bgp
, afi
, safi
, p
, pi
);
3398 /* Process change. */
3399 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
3401 bgp_process(bgp
, rn
, afi
, safi
);
3402 bgp_unlock_node(rn
);
3404 if (SAFI_UNICAST
== safi
3405 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3406 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3408 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, pi
);
3410 if ((SAFI_MPLS_VPN
== safi
)
3411 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3413 vpn_leak_to_vrf_update(bgp
, pi
);
3417 if (SAFI_MPLS_VPN
== safi
) {
3418 mpls_label_t label_decoded
= decode_label(label
);
3420 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3421 type
, sub_type
, &label_decoded
);
3423 if (SAFI_ENCAP
== safi
) {
3424 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3425 type
, sub_type
, NULL
);
3430 } // End of implicit withdraw
3432 /* Received Logging. */
3433 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3434 if (!peer
->rcvd_attr_printed
) {
3435 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3436 peer
->rcvd_attr_str
);
3437 peer
->rcvd_attr_printed
= 1;
3440 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3441 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3443 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3446 /* Make new BGP info. */
3447 new = info_make(type
, sub_type
, 0, peer
, attr_new
, rn
);
3449 /* Update MPLS label */
3450 if (has_valid_label
) {
3451 extra
= bgp_path_info_extra_get(new);
3452 if (extra
->label
!= label
) {
3453 memcpy(&extra
->label
, label
,
3454 num_labels
* sizeof(mpls_label_t
));
3455 extra
->num_labels
= num_labels
;
3457 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3458 bgp_set_valid_label(&extra
->label
[0]);
3461 /* Update Overlay Index */
3462 if (afi
== AFI_L2VPN
) {
3463 overlay_index_update(new->attr
,
3464 evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3465 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3467 /* Nexthop reachability check. */
3468 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3469 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
3470 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
3471 && !CHECK_FLAG(peer
->flags
,
3472 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3473 && !bgp_flag_check(bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3478 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, new, NULL
, connected
)
3479 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3480 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
3482 if (BGP_DEBUG(nht
, NHT
)) {
3483 char buf1
[INET6_ADDRSTRLEN
];
3485 (const void *)&attr_new
->nexthop
,
3486 buf1
, INET6_ADDRSTRLEN
);
3487 zlog_debug("%s(%s): NH unresolved",
3488 __FUNCTION__
, buf1
);
3490 bgp_path_info_unset_flag(rn
, new, BGP_PATH_VALID
);
3493 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
3496 new->addpath_rx_id
= addpath_id
;
3498 /* Increment prefix */
3499 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
3501 /* Register new BGP information. */
3502 bgp_path_info_add(rn
, new);
3504 /* route_node_get lock */
3505 bgp_unlock_node(rn
);
3508 if (safi
== SAFI_MPLS_VPN
) {
3509 struct bgp_node
*prn
= NULL
;
3510 struct bgp_table
*table
= NULL
;
3512 prn
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
3513 if (bgp_node_has_bgp_path_info_data(prn
)) {
3514 table
= bgp_node_get_bgp_table_info(prn
);
3516 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3517 bgp
, prd
, table
, p
, new);
3519 bgp_unlock_node(prn
);
3523 /* If maximum prefix count is configured and current prefix
3525 if (bgp_maximum_prefix_overflow(peer
, afi
, safi
, 0))
3528 /* If this is an EVPN route, process for import. */
3529 if (safi
== SAFI_EVPN
)
3530 bgp_evpn_import_route(bgp
, afi
, safi
, p
, new);
3532 /* Process change. */
3533 bgp_process(bgp
, rn
, afi
, safi
);
3535 if (SAFI_UNICAST
== safi
3536 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3537 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3538 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
3540 if ((SAFI_MPLS_VPN
== safi
)
3541 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3543 vpn_leak_to_vrf_update(bgp
, new);
3546 if (SAFI_MPLS_VPN
== safi
) {
3547 mpls_label_t label_decoded
= decode_label(label
);
3549 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3550 sub_type
, &label_decoded
);
3552 if (SAFI_ENCAP
== safi
) {
3553 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3560 /* This BGP update is filtered. Log the reason then update BGP
3563 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3564 if (!peer
->rcvd_attr_printed
) {
3565 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3566 peer
->rcvd_attr_str
);
3567 peer
->rcvd_attr_printed
= 1;
3570 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3571 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3573 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
3574 peer
->host
, pfx_buf
, reason
);
3578 /* If this is an EVPN route, un-import it as it is now filtered.
3580 if (safi
== SAFI_EVPN
)
3581 bgp_evpn_unimport_route(bgp
, afi
, safi
, p
, pi
);
3583 if (SAFI_UNICAST
== safi
3584 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3585 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3587 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
3589 if ((SAFI_MPLS_VPN
== safi
)
3590 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3592 vpn_leak_to_vrf_withdraw(bgp
, pi
);
3595 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
3598 bgp_unlock_node(rn
);
3602 * Filtered update is treated as an implicit withdrawal (see
3604 * a few lines above)
3606 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3607 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3615 int bgp_withdraw(struct peer
*peer
, struct prefix
*p
, uint32_t addpath_id
,
3616 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
3617 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
3618 uint32_t num_labels
, struct bgp_route_evpn
*evpn
)
3621 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
3622 struct bgp_node
*rn
;
3623 struct bgp_path_info
*pi
;
3626 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3627 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3635 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
3637 /* If peer is soft reconfiguration enabled. Record input packet for
3638 * further calculation.
3640 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
3641 * routes that are filtered. This tanks out Quagga RS pretty badly due
3643 * the iteration over all RS clients.
3644 * Since we need to remove the entry from adj_in anyway, do that first
3646 * if there was no entry, we don't need to do anything more.
3648 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
3649 && peer
!= bgp
->peer_self
)
3650 if (!bgp_adj_in_unset(rn
, peer
, addpath_id
)) {
3651 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3652 bgp_debug_rdpfxpath2str(
3653 afi
, safi
, prd
, p
, label
, num_labels
,
3654 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3657 "%s withdrawing route %s not in adj-in",
3658 peer
->host
, pfx_buf
);
3660 bgp_unlock_node(rn
);
3664 /* Lookup withdrawn route. */
3665 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
3666 if (pi
->peer
== peer
&& pi
->type
== type
3667 && pi
->sub_type
== sub_type
3668 && pi
->addpath_rx_id
== addpath_id
)
3672 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3673 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3674 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3676 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer
->host
,
3680 /* Withdraw specified route from routing table. */
3681 if (pi
&& !CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3682 bgp_rib_withdraw(rn
, pi
, peer
, afi
, safi
, prd
);
3683 if (SAFI_UNICAST
== safi
3684 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3685 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3686 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
3688 if ((SAFI_MPLS_VPN
== safi
)
3689 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3691 vpn_leak_to_vrf_withdraw(bgp
, pi
);
3693 } else if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3694 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3695 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3697 zlog_debug("%s Can't find the route %s", peer
->host
, pfx_buf
);
3700 /* Unlock bgp_node_get() lock. */
3701 bgp_unlock_node(rn
);
3706 void bgp_default_originate(struct peer
*peer
, afi_t afi
, safi_t safi
,
3709 struct update_subgroup
*subgrp
;
3710 subgrp
= peer_subgroup(peer
, afi
, safi
);
3711 subgroup_default_originate(subgrp
, withdraw
);
3716 * bgp_stop_announce_route_timer
3718 void bgp_stop_announce_route_timer(struct peer_af
*paf
)
3720 if (!paf
->t_announce_route
)
3723 THREAD_TIMER_OFF(paf
->t_announce_route
);
3727 * bgp_announce_route_timer_expired
3729 * Callback that is invoked when the route announcement timer for a
3732 static int bgp_announce_route_timer_expired(struct thread
*t
)
3734 struct peer_af
*paf
;
3737 paf
= THREAD_ARG(t
);
3740 if (peer
->status
!= Established
)
3743 if (!peer
->afc_nego
[paf
->afi
][paf
->safi
])
3746 peer_af_announce_route(paf
, 1);
3751 * bgp_announce_route
3753 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
3755 void bgp_announce_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
3757 struct peer_af
*paf
;
3758 struct update_subgroup
*subgrp
;
3760 paf
= peer_af_find(peer
, afi
, safi
);
3763 subgrp
= PAF_SUBGRP(paf
);
3766 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
3767 * or a refresh has already been triggered.
3769 if (!subgrp
|| paf
->t_announce_route
)
3773 * Start a timer to stagger/delay the announce. This serves
3774 * two purposes - announcement can potentially be combined for
3775 * multiple peers and the announcement doesn't happen in the
3778 thread_add_timer_msec(bm
->master
, bgp_announce_route_timer_expired
, paf
,
3779 (subgrp
->peer_count
== 1)
3780 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
3781 : BGP_ANNOUNCE_ROUTE_DELAY_MS
,
3782 &paf
->t_announce_route
);
3786 * Announce routes from all AF tables to a peer.
3788 * This should ONLY be called when there is a need to refresh the
3789 * routes to the peer based on a policy change for this peer alone
3790 * or a route refresh request received from the peer.
3791 * The operation will result in splitting the peer from its existing
3792 * subgroups and putting it in new subgroups.
3794 void bgp_announce_route_all(struct peer
*peer
)
3799 FOREACH_AFI_SAFI (afi
, safi
)
3800 bgp_announce_route(peer
, afi
, safi
);
3803 static void bgp_soft_reconfig_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
3804 struct bgp_table
*table
,
3805 struct prefix_rd
*prd
)
3808 struct bgp_node
*rn
;
3809 struct bgp_adj_in
*ain
;
3812 table
= peer
->bgp
->rib
[afi
][safi
];
3814 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
3815 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
3816 if (ain
->peer
!= peer
)
3819 struct bgp_path_info
*pi
=
3820 bgp_node_get_bgp_path_info(rn
);
3821 uint32_t num_labels
= 0;
3822 mpls_label_t
*label_pnt
= NULL
;
3823 struct bgp_route_evpn evpn
;
3825 if (pi
&& pi
->extra
)
3826 num_labels
= pi
->extra
->num_labels
;
3828 label_pnt
= &pi
->extra
->label
[0];
3830 memcpy(&evpn
, &pi
->attr
->evpn_overlay
,
3833 memset(&evpn
, 0, sizeof(evpn
));
3835 ret
= bgp_update(peer
, &rn
->p
, ain
->addpath_rx_id
,
3836 ain
->attr
, afi
, safi
, ZEBRA_ROUTE_BGP
,
3837 BGP_ROUTE_NORMAL
, prd
, label_pnt
,
3838 num_labels
, 1, &evpn
);
3841 bgp_unlock_node(rn
);
3847 void bgp_soft_reconfig_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
3849 struct bgp_node
*rn
;
3850 struct bgp_table
*table
;
3852 if (peer
->status
!= Established
)
3855 if ((safi
!= SAFI_MPLS_VPN
) && (safi
!= SAFI_ENCAP
)
3856 && (safi
!= SAFI_EVPN
))
3857 bgp_soft_reconfig_table(peer
, afi
, safi
, NULL
, NULL
);
3859 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
3860 rn
= bgp_route_next(rn
)) {
3861 table
= bgp_node_get_bgp_table_info(rn
);
3862 if (table
!= NULL
) {
3863 struct prefix_rd prd
;
3865 prd
.family
= AF_UNSPEC
;
3867 memcpy(&prd
.val
, rn
->p
.u
.val
, 8);
3869 bgp_soft_reconfig_table(peer
, afi
, safi
, table
,
3876 struct bgp_clear_node_queue
{
3877 struct bgp_node
*rn
;
3880 static wq_item_status
bgp_clear_route_node(struct work_queue
*wq
, void *data
)
3882 struct bgp_clear_node_queue
*cnq
= data
;
3883 struct bgp_node
*rn
= cnq
->rn
;
3884 struct peer
*peer
= wq
->spec
.data
;
3885 struct bgp_path_info
*pi
;
3887 afi_t afi
= bgp_node_table(rn
)->afi
;
3888 safi_t safi
= bgp_node_table(rn
)->safi
;
3893 /* It is possible that we have multiple paths for a prefix from a peer
3894 * if that peer is using AddPath.
3896 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
3897 if (pi
->peer
!= peer
)
3900 /* graceful restart STALE flag set. */
3901 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_NSF_WAIT
)
3902 && peer
->nsf
[afi
][safi
]
3903 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
3904 && !CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
3905 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_STALE
);
3907 /* If this is an EVPN route, process for
3909 if (safi
== SAFI_EVPN
)
3910 bgp_evpn_unimport_route(bgp
, afi
, safi
, &rn
->p
,
3912 /* Handle withdraw for VRF route-leaking and L3VPN */
3913 if (SAFI_UNICAST
== safi
3914 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
||
3915 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3916 vpn_leak_from_vrf_withdraw(bgp_get_default(),
3919 if (SAFI_MPLS_VPN
== safi
&&
3920 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
3921 vpn_leak_to_vrf_withdraw(bgp
, pi
);
3924 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
3930 static void bgp_clear_node_queue_del(struct work_queue
*wq
, void *data
)
3932 struct bgp_clear_node_queue
*cnq
= data
;
3933 struct bgp_node
*rn
= cnq
->rn
;
3934 struct bgp_table
*table
= bgp_node_table(rn
);
3936 bgp_unlock_node(rn
);
3937 bgp_table_unlock(table
);
3938 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE
, cnq
);
3941 static void bgp_clear_node_complete(struct work_queue
*wq
)
3943 struct peer
*peer
= wq
->spec
.data
;
3945 /* Tickle FSM to start moving again */
3946 BGP_EVENT_ADD(peer
, Clearing_Completed
);
3948 peer_unlock(peer
); /* bgp_clear_route */
3951 static void bgp_clear_node_queue_init(struct peer
*peer
)
3953 char wname
[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
3955 snprintf(wname
, sizeof(wname
), "clear %s", peer
->host
);
3956 #undef CLEAR_QUEUE_NAME_LEN
3958 peer
->clear_node_queue
= work_queue_new(bm
->master
, wname
);
3959 peer
->clear_node_queue
->spec
.hold
= 10;
3960 peer
->clear_node_queue
->spec
.workfunc
= &bgp_clear_route_node
;
3961 peer
->clear_node_queue
->spec
.del_item_data
= &bgp_clear_node_queue_del
;
3962 peer
->clear_node_queue
->spec
.completion_func
= &bgp_clear_node_complete
;
3963 peer
->clear_node_queue
->spec
.max_retries
= 0;
3965 /* we only 'lock' this peer reference when the queue is actually active
3967 peer
->clear_node_queue
->spec
.data
= peer
;
3970 static void bgp_clear_route_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
3971 struct bgp_table
*table
)
3973 struct bgp_node
*rn
;
3974 int force
= bm
->process_main_queue
? 0 : 1;
3977 table
= peer
->bgp
->rib
[afi
][safi
];
3979 /* If still no table => afi/safi isn't configured at all or smth. */
3983 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
3984 struct bgp_path_info
*pi
, *next
;
3985 struct bgp_adj_in
*ain
;
3986 struct bgp_adj_in
*ain_next
;
3988 /* XXX:TODO: This is suboptimal, every non-empty route_node is
3989 * queued for every clearing peer, regardless of whether it is
3990 * relevant to the peer at hand.
3992 * Overview: There are 3 different indices which need to be
3993 * scrubbed, potentially, when a peer is removed:
3995 * 1 peer's routes visible via the RIB (ie accepted routes)
3996 * 2 peer's routes visible by the (optional) peer's adj-in index
3997 * 3 other routes visible by the peer's adj-out index
3999 * 3 there is no hurry in scrubbing, once the struct peer is
4000 * removed from bgp->peer, we could just GC such deleted peer's
4001 * adj-outs at our leisure.
4003 * 1 and 2 must be 'scrubbed' in some way, at least made
4004 * invisible via RIB index before peer session is allowed to be
4005 * brought back up. So one needs to know when such a 'search' is
4010 * - there'd be a single global queue or a single RIB walker
4011 * - rather than tracking which route_nodes still need to be
4012 * examined on a peer basis, we'd track which peers still
4015 * Given that our per-peer prefix-counts now should be reliable,
4016 * this may actually be achievable. It doesn't seem to be a huge
4017 * problem at this time,
4019 * It is possible that we have multiple paths for a prefix from
4021 * if that peer is using AddPath.
4025 ain_next
= ain
->next
;
4027 if (ain
->peer
== peer
) {
4028 bgp_adj_in_remove(rn
, ain
);
4029 bgp_unlock_node(rn
);
4035 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= next
) {
4037 if (pi
->peer
!= peer
)
4041 bgp_path_info_reap(rn
, pi
);
4043 struct bgp_clear_node_queue
*cnq
;
4045 /* both unlocked in bgp_clear_node_queue_del */
4046 bgp_table_lock(bgp_node_table(rn
));
4049 MTYPE_BGP_CLEAR_NODE_QUEUE
,
4050 sizeof(struct bgp_clear_node_queue
));
4052 work_queue_add(peer
->clear_node_queue
, cnq
);
4060 void bgp_clear_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4062 struct bgp_node
*rn
;
4063 struct bgp_table
*table
;
4065 if (peer
->clear_node_queue
== NULL
)
4066 bgp_clear_node_queue_init(peer
);
4068 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
4069 * Idle until it receives a Clearing_Completed event. This protects
4070 * against peers which flap faster than we can we clear, which could
4073 * a) race with routes from the new session being installed before
4074 * clear_route_node visits the node (to delete the route of that
4076 * b) resource exhaustion, clear_route_node likely leads to an entry
4077 * on the process_main queue. Fast-flapping could cause that queue
4081 /* lock peer in assumption that clear-node-queue will get nodes; if so,
4082 * the unlock will happen upon work-queue completion; other wise, the
4083 * unlock happens at the end of this function.
4085 if (!peer
->clear_node_queue
->thread
)
4088 if (safi
!= SAFI_MPLS_VPN
&& safi
!= SAFI_ENCAP
&& safi
!= SAFI_EVPN
)
4089 bgp_clear_route_table(peer
, afi
, safi
, NULL
);
4091 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4092 rn
= bgp_route_next(rn
)) {
4093 table
= bgp_node_get_bgp_table_info(rn
);
4097 bgp_clear_route_table(peer
, afi
, safi
, table
);
4100 /* unlock if no nodes got added to the clear-node-queue. */
4101 if (!peer
->clear_node_queue
->thread
)
4105 void bgp_clear_route_all(struct peer
*peer
)
4110 FOREACH_AFI_SAFI (afi
, safi
)
4111 bgp_clear_route(peer
, afi
, safi
);
4114 rfapiProcessPeerDown(peer
);
4118 void bgp_clear_adj_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
4120 struct bgp_table
*table
;
4121 struct bgp_node
*rn
;
4122 struct bgp_adj_in
*ain
;
4123 struct bgp_adj_in
*ain_next
;
4125 table
= peer
->bgp
->rib
[afi
][safi
];
4127 /* It is possible that we have multiple paths for a prefix from a peer
4128 * if that peer is using AddPath.
4130 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
4134 ain_next
= ain
->next
;
4136 if (ain
->peer
== peer
) {
4137 bgp_adj_in_remove(rn
, ain
);
4138 bgp_unlock_node(rn
);
4146 void bgp_clear_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4148 struct bgp_node
*rn
;
4149 struct bgp_path_info
*pi
;
4150 struct bgp_table
*table
;
4152 if (safi
== SAFI_MPLS_VPN
) {
4153 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4154 rn
= bgp_route_next(rn
)) {
4155 struct bgp_node
*rm
;
4157 /* look for neighbor in tables */
4158 table
= bgp_node_get_bgp_table_info(rn
);
4162 for (rm
= bgp_table_top(table
); rm
;
4163 rm
= bgp_route_next(rm
))
4164 for (pi
= bgp_node_get_bgp_path_info(rm
); pi
;
4166 if (pi
->peer
!= peer
)
4168 if (!CHECK_FLAG(pi
->flags
,
4172 bgp_rib_remove(rm
, pi
, peer
, afi
, safi
);
4177 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4178 rn
= bgp_route_next(rn
))
4179 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
;
4181 if (pi
->peer
!= peer
)
4183 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
4185 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
4191 int bgp_outbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
4193 if (peer
->sort
== BGP_PEER_EBGP
4194 && (ROUTE_MAP_OUT_NAME(filter
) || PREFIX_LIST_OUT_NAME(filter
)
4195 || FILTER_LIST_OUT_NAME(filter
)
4196 || DISTRIBUTE_OUT_NAME(filter
)))
4201 int bgp_inbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
4203 if (peer
->sort
== BGP_PEER_EBGP
4204 && (ROUTE_MAP_IN_NAME(filter
) || PREFIX_LIST_IN_NAME(filter
)
4205 || FILTER_LIST_IN_NAME(filter
)
4206 || DISTRIBUTE_IN_NAME(filter
)))
4211 static void bgp_cleanup_table(struct bgp
*bgp
, struct bgp_table
*table
,
4214 struct bgp_node
*rn
;
4215 struct bgp_path_info
*pi
;
4216 struct bgp_path_info
*next
;
4218 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
4219 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= next
) {
4222 /* Unimport EVPN routes from VRFs */
4223 if (safi
== SAFI_EVPN
)
4224 bgp_evpn_unimport_route(bgp
, AFI_L2VPN
,
4228 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)
4229 && pi
->type
== ZEBRA_ROUTE_BGP
4230 && (pi
->sub_type
== BGP_ROUTE_NORMAL
4231 || pi
->sub_type
== BGP_ROUTE_AGGREGATE
4232 || pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
4234 if (bgp_fibupd_safi(safi
))
4235 bgp_zebra_withdraw(&rn
->p
, pi
, bgp
,
4237 bgp_path_info_reap(rn
, pi
);
4242 /* Delete all kernel routes. */
4243 void bgp_cleanup_routes(struct bgp
*bgp
)
4246 struct bgp_node
*rn
;
4247 struct bgp_table
*table
;
4249 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
4250 if (afi
== AFI_L2VPN
)
4252 bgp_cleanup_table(bgp
, bgp
->rib
[afi
][SAFI_UNICAST
],
4255 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
4257 if (afi
!= AFI_L2VPN
) {
4259 safi
= SAFI_MPLS_VPN
;
4260 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4261 rn
= bgp_route_next(rn
)) {
4262 table
= bgp_node_get_bgp_table_info(rn
);
4263 if (table
!= NULL
) {
4264 bgp_cleanup_table(bgp
, table
, safi
);
4265 bgp_table_finish(&table
);
4266 bgp_node_set_bgp_table_info(rn
, NULL
);
4267 bgp_unlock_node(rn
);
4271 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4272 rn
= bgp_route_next(rn
)) {
4273 table
= bgp_node_get_bgp_table_info(rn
);
4274 if (table
!= NULL
) {
4275 bgp_cleanup_table(bgp
, table
, safi
);
4276 bgp_table_finish(&table
);
4277 bgp_node_set_bgp_table_info(rn
, NULL
);
4278 bgp_unlock_node(rn
);
4283 for (rn
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); rn
;
4284 rn
= bgp_route_next(rn
)) {
4285 table
= bgp_node_get_bgp_table_info(rn
);
4286 if (table
!= NULL
) {
4287 bgp_cleanup_table(bgp
, table
, SAFI_EVPN
);
4288 bgp_table_finish(&table
);
4289 bgp_node_set_bgp_table_info(rn
, NULL
);
4290 bgp_unlock_node(rn
);
4295 void bgp_reset(void)
4298 bgp_zclient_reset();
4299 access_list_reset();
4300 prefix_list_reset();
4303 static int bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
4305 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
4306 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
4307 PEER_CAP_ADDPATH_AF_TX_RCV
));
4310 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
4312 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
4313 struct bgp_nlri
*packet
)
4322 int addpath_encoded
;
4323 uint32_t addpath_id
;
4326 lim
= pnt
+ packet
->length
;
4328 safi
= packet
->safi
;
4330 addpath_encoded
= bgp_addpath_encode_rx(peer
, afi
, safi
);
4332 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
4333 syntactic validity. If the field is syntactically incorrect,
4334 then the Error Subcode is set to Invalid Network Field. */
4335 for (; pnt
< lim
; pnt
+= psize
) {
4336 /* Clear prefix structure. */
4337 memset(&p
, 0, sizeof(struct prefix
));
4339 if (addpath_encoded
) {
4341 /* When packet overflow occurs return immediately. */
4342 if (pnt
+ BGP_ADDPATH_ID_LEN
> lim
)
4343 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
4345 addpath_id
= ntohl(*((uint32_t *)pnt
));
4346 pnt
+= BGP_ADDPATH_ID_LEN
;
4349 /* Fetch prefix length. */
4350 p
.prefixlen
= *pnt
++;
4351 /* afi/safi validity already verified by caller,
4352 * bgp_update_receive */
4353 p
.family
= afi2family(afi
);
4355 /* Prefix length check. */
4356 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
4359 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
4360 peer
->host
, p
.prefixlen
, packet
->afi
);
4361 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH
;
4364 /* Packet size overflow check. */
4365 psize
= PSIZE(p
.prefixlen
);
4367 /* When packet overflow occur return immediately. */
4368 if (pnt
+ psize
> lim
) {
4371 "%s [Error] Update packet error (prefix length %d overflows packet)",
4372 peer
->host
, p
.prefixlen
);
4373 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
4376 /* Defensive coding, double-check the psize fits in a struct
4378 if (psize
> (ssize_t
)sizeof(p
.u
)) {
4381 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
4382 peer
->host
, p
.prefixlen
, sizeof(p
.u
));
4383 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
4386 /* Fetch prefix from NLRI packet. */
4387 memcpy(p
.u
.val
, pnt
, psize
);
4389 /* Check address. */
4390 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
4391 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
4392 /* From RFC4271 Section 6.3:
4394 * If a prefix in the NLRI field is semantically
4396 * (e.g., an unexpected multicast IP address),
4398 * be logged locally, and the prefix SHOULD be
4403 "%s: IPv4 unicast NLRI is multicast address %s, ignoring",
4404 peer
->host
, inet_ntoa(p
.u
.prefix4
));
4409 /* Check address. */
4410 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
4411 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4416 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
4418 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4423 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
4428 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
4430 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4437 /* Normal process. */
4439 ret
= bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
4440 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
4441 NULL
, NULL
, 0, 0, NULL
);
4443 ret
= bgp_withdraw(peer
, &p
, addpath_id
, attr
, afi
,
4444 safi
, ZEBRA_ROUTE_BGP
,
4445 BGP_ROUTE_NORMAL
, NULL
, NULL
, 0,
4448 /* Do not send BGP notification twice when maximum-prefix count
4450 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
))
4451 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW
;
4453 /* Address family configuration mismatch. */
4455 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY
;
4458 /* Packet length consistency check. */
4462 "%s [Error] Update packet error (prefix length mismatch with total length)",
4464 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
4467 return BGP_NLRI_PARSE_OK
;
4470 static struct bgp_static
*bgp_static_new(void)
4472 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
4475 static void bgp_static_free(struct bgp_static
*bgp_static
)
4477 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
4478 route_map_counter_decrement(bgp_static
->rmap
.map
);
4480 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
4481 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
4484 void bgp_static_update(struct bgp
*bgp
, struct prefix
*p
,
4485 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
4487 struct bgp_node
*rn
;
4488 struct bgp_path_info
*pi
;
4489 struct bgp_path_info
*new;
4490 struct bgp_path_info rmap_path
;
4492 struct attr
*attr_new
;
4495 int vnc_implicit_withdraw
= 0;
4502 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4504 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4506 attr
.nexthop
= bgp_static
->igpnexthop
;
4507 attr
.med
= bgp_static
->igpmetric
;
4508 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4510 if (bgp_static
->atomic
)
4511 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
4513 /* Store label index, if required. */
4514 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
4515 attr
.label_index
= bgp_static
->label_index
;
4516 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
4519 /* Apply route-map. */
4520 if (bgp_static
->rmap
.name
) {
4521 struct attr attr_tmp
= attr
;
4523 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
4524 rmap_path
.peer
= bgp
->peer_self
;
4525 rmap_path
.attr
= &attr_tmp
;
4527 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4529 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
,
4532 bgp
->peer_self
->rmap_type
= 0;
4534 if (ret
== RMAP_DENYMATCH
) {
4535 /* Free uninterned attribute. */
4536 bgp_attr_flush(&attr_tmp
);
4538 /* Unintern original. */
4539 aspath_unintern(&attr
.aspath
);
4540 bgp_static_withdraw(bgp
, p
, afi
, safi
);
4544 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4545 bgp_attr_add_gshut_community(&attr_tmp
);
4547 attr_new
= bgp_attr_intern(&attr_tmp
);
4550 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4551 bgp_attr_add_gshut_community(&attr
);
4553 attr_new
= bgp_attr_intern(&attr
);
4556 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4557 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4558 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4562 if (attrhash_cmp(pi
->attr
, attr_new
)
4563 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
4564 && !bgp_flag_check(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
4565 bgp_unlock_node(rn
);
4566 bgp_attr_unintern(&attr_new
);
4567 aspath_unintern(&attr
.aspath
);
4570 /* The attribute is changed. */
4571 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_ATTR_CHANGED
);
4573 /* Rewrite BGP route information. */
4574 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
4575 bgp_path_info_restore(rn
, pi
);
4577 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4579 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4580 && (safi
== SAFI_UNICAST
)) {
4581 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
4583 * Implicit withdraw case.
4584 * We have to do this before pi is
4587 ++vnc_implicit_withdraw
;
4588 vnc_import_bgp_del_route(bgp
, p
, pi
);
4589 vnc_import_bgp_exterior_del_route(
4594 bgp_attr_unintern(&pi
->attr
);
4595 pi
->attr
= attr_new
;
4596 pi
->uptime
= bgp_clock();
4598 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4599 && (safi
== SAFI_UNICAST
)) {
4600 if (vnc_implicit_withdraw
) {
4601 vnc_import_bgp_add_route(bgp
, p
, pi
);
4602 vnc_import_bgp_exterior_add_route(
4608 /* Nexthop reachability check. */
4609 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4610 && (safi
== SAFI_UNICAST
4611 || safi
== SAFI_LABELED_UNICAST
)) {
4613 struct bgp
*bgp_nexthop
= bgp
;
4615 if (pi
->extra
&& pi
->extra
->bgp_orig
)
4616 bgp_nexthop
= pi
->extra
->bgp_orig
;
4618 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
,
4620 bgp_path_info_set_flag(rn
, pi
,
4623 if (BGP_DEBUG(nht
, NHT
)) {
4624 char buf1
[INET6_ADDRSTRLEN
];
4625 inet_ntop(p
->family
,
4629 "%s(%s): Route not in table, not advertising",
4630 __FUNCTION__
, buf1
);
4632 bgp_path_info_unset_flag(
4633 rn
, pi
, BGP_PATH_VALID
);
4636 /* Delete the NHT structure if any, if we're
4638 * enabling/disabling import check. We
4639 * deregister the route
4640 * from NHT to avoid overloading NHT and the
4641 * process interaction
4643 bgp_unlink_nexthop(pi
);
4644 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_VALID
);
4646 /* Process change. */
4647 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
4648 bgp_process(bgp
, rn
, afi
, safi
);
4650 if (SAFI_UNICAST
== safi
4651 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4653 == BGP_INSTANCE_TYPE_DEFAULT
)) {
4654 vpn_leak_from_vrf_update(bgp_get_default(), bgp
,
4658 bgp_unlock_node(rn
);
4659 aspath_unintern(&attr
.aspath
);
4664 /* Make new BGP info. */
4665 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
4667 /* Nexthop reachability check. */
4668 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4669 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
4670 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, new, NULL
, 0))
4671 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
4673 if (BGP_DEBUG(nht
, NHT
)) {
4674 char buf1
[INET6_ADDRSTRLEN
];
4675 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
4678 "%s(%s): Route not in table, not advertising",
4679 __FUNCTION__
, buf1
);
4681 bgp_path_info_unset_flag(rn
, new, BGP_PATH_VALID
);
4684 /* Delete the NHT structure if any, if we're toggling between
4685 * enabling/disabling import check. We deregister the route
4686 * from NHT to avoid overloading NHT and the process interaction
4688 bgp_unlink_nexthop(new);
4690 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
4693 /* Aggregate address increment. */
4694 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4696 /* Register new BGP information. */
4697 bgp_path_info_add(rn
, new);
4699 /* route_node_get lock */
4700 bgp_unlock_node(rn
);
4702 /* Process change. */
4703 bgp_process(bgp
, rn
, afi
, safi
);
4705 if (SAFI_UNICAST
== safi
4706 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4707 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4708 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
4711 /* Unintern original. */
4712 aspath_unintern(&attr
.aspath
);
4715 void bgp_static_withdraw(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
4718 struct bgp_node
*rn
;
4719 struct bgp_path_info
*pi
;
4721 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4723 /* Check selected route and self inserted route. */
4724 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4725 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4726 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4729 /* Withdraw static BGP route from routing table. */
4731 if (SAFI_UNICAST
== safi
4732 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4733 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4734 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
4736 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4737 bgp_unlink_nexthop(pi
);
4738 bgp_path_info_delete(rn
, pi
);
4739 bgp_process(bgp
, rn
, afi
, safi
);
4742 /* Unlock bgp_node_lookup. */
4743 bgp_unlock_node(rn
);
4747 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
4749 static void bgp_static_withdraw_safi(struct bgp
*bgp
, struct prefix
*p
,
4750 afi_t afi
, safi_t safi
,
4751 struct prefix_rd
*prd
)
4753 struct bgp_node
*rn
;
4754 struct bgp_path_info
*pi
;
4756 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4758 /* Check selected route and self inserted route. */
4759 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4760 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4761 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4764 /* Withdraw static BGP route from routing table. */
4767 rfapiProcessWithdraw(
4768 pi
->peer
, NULL
, p
, prd
, pi
->attr
, afi
, safi
, pi
->type
,
4769 1); /* Kill, since it is an administrative change */
4771 if (SAFI_MPLS_VPN
== safi
4772 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4773 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4775 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4776 bgp_path_info_delete(rn
, pi
);
4777 bgp_process(bgp
, rn
, afi
, safi
);
4780 /* Unlock bgp_node_lookup. */
4781 bgp_unlock_node(rn
);
4784 static void bgp_static_update_safi(struct bgp
*bgp
, struct prefix
*p
,
4785 struct bgp_static
*bgp_static
, afi_t afi
,
4788 struct bgp_node
*rn
;
4789 struct bgp_path_info
*new;
4790 struct attr
*attr_new
;
4791 struct attr attr
= {0};
4792 struct bgp_path_info
*pi
;
4794 mpls_label_t label
= 0;
4796 uint32_t num_labels
= 0;
4801 if (bgp_static
->label
!= MPLS_INVALID_LABEL
)
4803 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
4806 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4808 attr
.nexthop
= bgp_static
->igpnexthop
;
4809 attr
.med
= bgp_static
->igpmetric
;
4810 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4812 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
4813 || (safi
== SAFI_ENCAP
)) {
4814 if (afi
== AFI_IP
) {
4815 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
4816 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
4819 if (afi
== AFI_L2VPN
) {
4820 if (bgp_static
->gatewayIp
.family
== AF_INET
)
4822 bgp_static
->gatewayIp
.u
.prefix4
.s_addr
;
4823 else if (bgp_static
->gatewayIp
.family
== AF_INET6
)
4824 memcpy(&(add
.ipv6
), &(bgp_static
->gatewayIp
.u
.prefix6
),
4825 sizeof(struct in6_addr
));
4826 overlay_index_update(&attr
, bgp_static
->eth_s_id
, &add
);
4827 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
4828 struct bgp_encap_type_vxlan bet
;
4829 memset(&bet
, 0, sizeof(struct bgp_encap_type_vxlan
));
4830 bet
.vnid
= p
->u
.prefix_evpn
.prefix_addr
.eth_tag
;
4831 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
4833 if (bgp_static
->router_mac
) {
4834 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
4837 /* Apply route-map. */
4838 if (bgp_static
->rmap
.name
) {
4839 struct attr attr_tmp
= attr
;
4840 struct bgp_path_info rmap_path
;
4843 rmap_path
.peer
= bgp
->peer_self
;
4844 rmap_path
.attr
= &attr_tmp
;
4846 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4848 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
,
4851 bgp
->peer_self
->rmap_type
= 0;
4853 if (ret
== RMAP_DENYMATCH
) {
4854 /* Free uninterned attribute. */
4855 bgp_attr_flush(&attr_tmp
);
4857 /* Unintern original. */
4858 aspath_unintern(&attr
.aspath
);
4859 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
4864 attr_new
= bgp_attr_intern(&attr_tmp
);
4866 attr_new
= bgp_attr_intern(&attr
);
4869 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4870 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4871 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4875 memset(&add
, 0, sizeof(union gw_addr
));
4876 if (attrhash_cmp(pi
->attr
, attr_new
)
4877 && overlay_index_equal(afi
, pi
, bgp_static
->eth_s_id
, &add
)
4878 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
4879 bgp_unlock_node(rn
);
4880 bgp_attr_unintern(&attr_new
);
4881 aspath_unintern(&attr
.aspath
);
4884 /* The attribute is changed. */
4885 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_ATTR_CHANGED
);
4887 /* Rewrite BGP route information. */
4888 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
4889 bgp_path_info_restore(rn
, pi
);
4891 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4892 bgp_attr_unintern(&pi
->attr
);
4893 pi
->attr
= attr_new
;
4894 pi
->uptime
= bgp_clock();
4897 label
= decode_label(&pi
->extra
->label
[0]);
4900 /* Process change. */
4901 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
4902 bgp_process(bgp
, rn
, afi
, safi
);
4904 if (SAFI_MPLS_VPN
== safi
4905 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4906 vpn_leak_to_vrf_update(bgp
, pi
);
4909 rfapiProcessUpdate(pi
->peer
, NULL
, p
, &bgp_static
->prd
,
4910 pi
->attr
, afi
, safi
, pi
->type
,
4911 pi
->sub_type
, &label
);
4913 bgp_unlock_node(rn
);
4914 aspath_unintern(&attr
.aspath
);
4920 /* Make new BGP info. */
4921 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
4923 SET_FLAG(new->flags
, BGP_PATH_VALID
);
4924 new->extra
= bgp_path_info_extra_new();
4926 new->extra
->label
[0] = bgp_static
->label
;
4927 new->extra
->num_labels
= num_labels
;
4930 label
= decode_label(&bgp_static
->label
);
4933 /* Aggregate address increment. */
4934 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4936 /* Register new BGP information. */
4937 bgp_path_info_add(rn
, new);
4938 /* route_node_get lock */
4939 bgp_unlock_node(rn
);
4941 /* Process change. */
4942 bgp_process(bgp
, rn
, afi
, safi
);
4944 if (SAFI_MPLS_VPN
== safi
4945 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4946 vpn_leak_to_vrf_update(bgp
, new);
4949 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
4950 safi
, new->type
, new->sub_type
, &label
);
4953 /* Unintern original. */
4954 aspath_unintern(&attr
.aspath
);
4957 /* Configure static BGP network. When user don't run zebra, static
4958 route should be installed as valid. */
4959 static int bgp_static_set(struct vty
*vty
, const char *negate
,
4960 const char *ip_str
, afi_t afi
, safi_t safi
,
4961 const char *rmap
, int backdoor
, uint32_t label_index
)
4963 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
4966 struct bgp_static
*bgp_static
;
4967 struct bgp_node
*rn
;
4968 uint8_t need_update
= 0;
4970 /* Convert IP prefix string to struct prefix. */
4971 ret
= str2prefix(ip_str
, &p
);
4973 vty_out(vty
, "%% Malformed prefix\n");
4974 return CMD_WARNING_CONFIG_FAILED
;
4976 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4977 vty_out(vty
, "%% Malformed prefix (link-local address)\n");
4978 return CMD_WARNING_CONFIG_FAILED
;
4985 /* Set BGP static route configuration. */
4986 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
4989 vty_out(vty
, "%% Can't find static route specified\n");
4990 return CMD_WARNING_CONFIG_FAILED
;
4993 bgp_static
= bgp_node_get_bgp_static_info(rn
);
4995 if ((label_index
!= BGP_INVALID_LABEL_INDEX
)
4996 && (label_index
!= bgp_static
->label_index
)) {
4998 "%% label-index doesn't match static route\n");
4999 return CMD_WARNING_CONFIG_FAILED
;
5002 if ((rmap
&& bgp_static
->rmap
.name
)
5003 && strcmp(rmap
, bgp_static
->rmap
.name
)) {
5005 "%% route-map name doesn't match static route\n");
5006 return CMD_WARNING_CONFIG_FAILED
;
5009 /* Update BGP RIB. */
5010 if (!bgp_static
->backdoor
)
5011 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
5013 /* Clear configuration. */
5014 bgp_static_free(bgp_static
);
5015 bgp_node_set_bgp_static_info(rn
, NULL
);
5016 bgp_unlock_node(rn
);
5017 bgp_unlock_node(rn
);
5020 /* Set BGP static route configuration. */
5021 rn
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
5023 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5025 /* Configuration change. */
5026 /* Label index cannot be changed. */
5027 if (bgp_static
->label_index
!= label_index
) {
5028 vty_out(vty
, "%% cannot change label-index\n");
5029 return CMD_WARNING_CONFIG_FAILED
;
5032 /* Check previous routes are installed into BGP. */
5033 if (bgp_static
->valid
5034 && bgp_static
->backdoor
!= backdoor
)
5037 bgp_static
->backdoor
= backdoor
;
5040 XFREE(MTYPE_ROUTE_MAP_NAME
,
5041 bgp_static
->rmap
.name
);
5042 route_map_counter_decrement(
5043 bgp_static
->rmap
.map
);
5044 bgp_static
->rmap
.name
=
5045 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
5046 bgp_static
->rmap
.map
=
5047 route_map_lookup_by_name(rmap
);
5048 route_map_counter_increment(
5049 bgp_static
->rmap
.map
);
5051 XFREE(MTYPE_ROUTE_MAP_NAME
,
5052 bgp_static
->rmap
.name
);
5053 route_map_counter_decrement(
5054 bgp_static
->rmap
.map
);
5055 bgp_static
->rmap
.name
= NULL
;
5056 bgp_static
->rmap
.map
= NULL
;
5057 bgp_static
->valid
= 0;
5059 bgp_unlock_node(rn
);
5061 /* New configuration. */
5062 bgp_static
= bgp_static_new();
5063 bgp_static
->backdoor
= backdoor
;
5064 bgp_static
->valid
= 0;
5065 bgp_static
->igpmetric
= 0;
5066 bgp_static
->igpnexthop
.s_addr
= 0;
5067 bgp_static
->label_index
= label_index
;
5070 XFREE(MTYPE_ROUTE_MAP_NAME
,
5071 bgp_static
->rmap
.name
);
5072 route_map_counter_decrement(
5073 bgp_static
->rmap
.map
);
5074 bgp_static
->rmap
.name
=
5075 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
5076 bgp_static
->rmap
.map
=
5077 route_map_lookup_by_name(rmap
);
5078 route_map_counter_increment(
5079 bgp_static
->rmap
.map
);
5081 bgp_node_set_bgp_static_info(rn
, bgp_static
);
5084 bgp_static
->valid
= 1;
5086 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
5088 if (!bgp_static
->backdoor
)
5089 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
5095 void bgp_static_add(struct bgp
*bgp
)
5099 struct bgp_node
*rn
;
5100 struct bgp_node
*rm
;
5101 struct bgp_table
*table
;
5102 struct bgp_static
*bgp_static
;
5104 FOREACH_AFI_SAFI (afi
, safi
)
5105 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5106 rn
= bgp_route_next(rn
)) {
5107 if (!bgp_node_has_bgp_path_info_data(rn
))
5110 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5111 || (safi
== SAFI_EVPN
)) {
5112 table
= bgp_node_get_bgp_table_info(rn
);
5114 for (rm
= bgp_table_top(table
); rm
;
5115 rm
= bgp_route_next(rm
)) {
5117 bgp_node_get_bgp_static_info(
5119 bgp_static_update_safi(bgp
, &rm
->p
,
5126 bgp_node_get_bgp_static_info(rn
), afi
,
5132 /* Called from bgp_delete(). Delete all static routes from the BGP
5134 void bgp_static_delete(struct bgp
*bgp
)
5138 struct bgp_node
*rn
;
5139 struct bgp_node
*rm
;
5140 struct bgp_table
*table
;
5141 struct bgp_static
*bgp_static
;
5143 FOREACH_AFI_SAFI (afi
, safi
)
5144 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5145 rn
= bgp_route_next(rn
)) {
5146 if (!bgp_node_has_bgp_path_info_data(rn
))
5149 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5150 || (safi
== SAFI_EVPN
)) {
5151 table
= bgp_node_get_bgp_table_info(rn
);
5153 for (rm
= bgp_table_top(table
); rm
;
5154 rm
= bgp_route_next(rm
)) {
5156 bgp_node_get_bgp_static_info(
5161 bgp_static_withdraw_safi(
5162 bgp
, &rm
->p
, AFI_IP
, safi
,
5163 (struct prefix_rd
*)&rn
->p
);
5164 bgp_static_free(bgp_static
);
5165 bgp_node_set_bgp_static_info(rn
, NULL
);
5166 bgp_unlock_node(rn
);
5169 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5170 bgp_static_withdraw(bgp
, &rn
->p
, afi
, safi
);
5171 bgp_static_free(bgp_static
);
5172 bgp_node_set_bgp_static_info(rn
, NULL
);
5173 bgp_unlock_node(rn
);
5178 void bgp_static_redo_import_check(struct bgp
*bgp
)
5182 struct bgp_node
*rn
;
5183 struct bgp_node
*rm
;
5184 struct bgp_table
*table
;
5185 struct bgp_static
*bgp_static
;
5187 /* Use this flag to force reprocessing of the route */
5188 bgp_flag_set(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5189 FOREACH_AFI_SAFI (afi
, safi
) {
5190 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5191 rn
= bgp_route_next(rn
)) {
5192 if (!bgp_node_has_bgp_path_info_data(rn
))
5195 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5196 || (safi
== SAFI_EVPN
)) {
5197 table
= bgp_node_get_bgp_table_info(rn
);
5199 for (rm
= bgp_table_top(table
); rm
;
5200 rm
= bgp_route_next(rm
)) {
5202 bgp_node_get_bgp_static_info(
5204 bgp_static_update_safi(bgp
, &rm
->p
,
5209 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5210 bgp_static_update(bgp
, &rn
->p
, bgp_static
, afi
,
5215 bgp_flag_unset(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5218 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
5221 struct bgp_table
*table
;
5222 struct bgp_node
*rn
;
5223 struct bgp_path_info
*pi
;
5225 table
= bgp
->rib
[afi
][safi
];
5226 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
5227 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
5228 if (pi
->peer
== bgp
->peer_self
5229 && ((pi
->type
== ZEBRA_ROUTE_BGP
5230 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5231 || (pi
->type
!= ZEBRA_ROUTE_BGP
5233 == BGP_ROUTE_REDISTRIBUTE
))) {
5234 bgp_aggregate_decrement(bgp
, &rn
->p
, pi
, afi
,
5236 bgp_unlink_nexthop(pi
);
5237 bgp_path_info_delete(rn
, pi
);
5238 bgp_process(bgp
, rn
, afi
, safi
);
5245 * Purge all networks and redistributed routes from routing table.
5246 * Invoked upon the instance going down.
5248 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
5253 FOREACH_AFI_SAFI (afi
, safi
)
5254 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
5259 * Currently this is used to set static routes for VPN and ENCAP.
5260 * I think it can probably be factored with bgp_static_set.
5262 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5263 const char *ip_str
, const char *rd_str
,
5264 const char *label_str
, const char *rmap_str
,
5265 int evpn_type
, const char *esi
, const char *gwip
,
5266 const char *ethtag
, const char *routermac
)
5268 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5271 struct prefix_rd prd
;
5272 struct bgp_node
*prn
;
5273 struct bgp_node
*rn
;
5274 struct bgp_table
*table
;
5275 struct bgp_static
*bgp_static
;
5276 mpls_label_t label
= MPLS_INVALID_LABEL
;
5277 struct prefix gw_ip
;
5279 /* validate ip prefix */
5280 ret
= str2prefix(ip_str
, &p
);
5282 vty_out(vty
, "%% Malformed prefix\n");
5283 return CMD_WARNING_CONFIG_FAILED
;
5286 if ((afi
== AFI_L2VPN
)
5287 && (bgp_build_evpn_prefix(evpn_type
,
5288 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5289 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5290 return CMD_WARNING_CONFIG_FAILED
;
5293 ret
= str2prefix_rd(rd_str
, &prd
);
5295 vty_out(vty
, "%% Malformed rd\n");
5296 return CMD_WARNING_CONFIG_FAILED
;
5300 unsigned long label_val
;
5301 label_val
= strtoul(label_str
, NULL
, 10);
5302 encode_label(label_val
, &label
);
5305 if (safi
== SAFI_EVPN
) {
5306 if (esi
&& str2esi(esi
, NULL
) == 0) {
5307 vty_out(vty
, "%% Malformed ESI\n");
5308 return CMD_WARNING_CONFIG_FAILED
;
5310 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
5311 vty_out(vty
, "%% Malformed Router MAC\n");
5312 return CMD_WARNING_CONFIG_FAILED
;
5315 memset(&gw_ip
, 0, sizeof(struct prefix
));
5316 ret
= str2prefix(gwip
, &gw_ip
);
5318 vty_out(vty
, "%% Malformed GatewayIp\n");
5319 return CMD_WARNING_CONFIG_FAILED
;
5321 if ((gw_ip
.family
== AF_INET
5322 && is_evpn_prefix_ipaddr_v6(
5323 (struct prefix_evpn
*)&p
))
5324 || (gw_ip
.family
== AF_INET6
5325 && is_evpn_prefix_ipaddr_v4(
5326 (struct prefix_evpn
*)&p
))) {
5328 "%% GatewayIp family differs with IP prefix\n");
5329 return CMD_WARNING_CONFIG_FAILED
;
5333 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5334 if (!bgp_node_has_bgp_path_info_data(prn
))
5335 bgp_node_set_bgp_table_info(prn
,
5336 bgp_table_init(bgp
, afi
, safi
));
5337 table
= bgp_node_get_bgp_table_info(prn
);
5339 rn
= bgp_node_get(table
, &p
);
5341 if (bgp_node_has_bgp_path_info_data(rn
)) {
5342 vty_out(vty
, "%% Same network configuration exists\n");
5343 bgp_unlock_node(rn
);
5345 /* New configuration. */
5346 bgp_static
= bgp_static_new();
5347 bgp_static
->backdoor
= 0;
5348 bgp_static
->valid
= 0;
5349 bgp_static
->igpmetric
= 0;
5350 bgp_static
->igpnexthop
.s_addr
= 0;
5351 bgp_static
->label
= label
;
5352 bgp_static
->prd
= prd
;
5355 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
5356 route_map_counter_decrement(bgp_static
->rmap
.map
);
5357 bgp_static
->rmap
.name
=
5358 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
5359 bgp_static
->rmap
.map
=
5360 route_map_lookup_by_name(rmap_str
);
5361 route_map_counter_increment(bgp_static
->rmap
.map
);
5364 if (safi
== SAFI_EVPN
) {
5366 bgp_static
->eth_s_id
=
5368 sizeof(struct eth_segment_id
));
5369 str2esi(esi
, bgp_static
->eth_s_id
);
5372 bgp_static
->router_mac
=
5373 XCALLOC(MTYPE_ATTR
, ETH_ALEN
+ 1);
5374 (void)prefix_str2mac(routermac
,
5375 bgp_static
->router_mac
);
5378 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
5380 bgp_node_set_bgp_static_info(rn
, bgp_static
);
5382 bgp_static
->valid
= 1;
5383 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
5389 /* Configure static BGP network. */
5390 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5391 const char *ip_str
, const char *rd_str
,
5392 const char *label_str
, int evpn_type
, const char *esi
,
5393 const char *gwip
, const char *ethtag
)
5395 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5398 struct prefix_rd prd
;
5399 struct bgp_node
*prn
;
5400 struct bgp_node
*rn
;
5401 struct bgp_table
*table
;
5402 struct bgp_static
*bgp_static
;
5403 mpls_label_t label
= MPLS_INVALID_LABEL
;
5405 /* Convert IP prefix string to struct prefix. */
5406 ret
= str2prefix(ip_str
, &p
);
5408 vty_out(vty
, "%% Malformed prefix\n");
5409 return CMD_WARNING_CONFIG_FAILED
;
5412 if ((afi
== AFI_L2VPN
)
5413 && (bgp_build_evpn_prefix(evpn_type
,
5414 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5415 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5416 return CMD_WARNING_CONFIG_FAILED
;
5418 ret
= str2prefix_rd(rd_str
, &prd
);
5420 vty_out(vty
, "%% Malformed rd\n");
5421 return CMD_WARNING_CONFIG_FAILED
;
5425 unsigned long label_val
;
5426 label_val
= strtoul(label_str
, NULL
, 10);
5427 encode_label(label_val
, &label
);
5430 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5431 if (!bgp_node_has_bgp_path_info_data(prn
))
5432 bgp_node_set_bgp_table_info(prn
,
5433 bgp_table_init(bgp
, afi
, safi
));
5435 bgp_unlock_node(prn
);
5436 table
= bgp_node_get_bgp_table_info(prn
);
5438 rn
= bgp_node_lookup(table
, &p
);
5441 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
5443 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5444 bgp_static_free(bgp_static
);
5445 bgp_node_set_bgp_static_info(rn
, NULL
);
5446 bgp_unlock_node(rn
);
5447 bgp_unlock_node(rn
);
5449 vty_out(vty
, "%% Can't find the route\n");
5454 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
5455 const char *rmap_name
)
5457 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5458 struct bgp_rmap
*rmap
;
5460 rmap
= &bgp
->table_map
[afi
][safi
];
5462 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5463 route_map_counter_decrement(rmap
->map
);
5464 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
5465 rmap
->map
= route_map_lookup_by_name(rmap_name
);
5466 route_map_counter_increment(rmap
->map
);
5468 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5469 route_map_counter_decrement(rmap
->map
);
5474 if (bgp_fibupd_safi(safi
))
5475 bgp_zebra_announce_table(bgp
, afi
, safi
);
5480 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
5481 const char *rmap_name
)
5483 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5484 struct bgp_rmap
*rmap
;
5486 rmap
= &bgp
->table_map
[afi
][safi
];
5487 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5488 route_map_counter_decrement(rmap
->map
);
5492 if (bgp_fibupd_safi(safi
))
5493 bgp_zebra_announce_table(bgp
, afi
, safi
);
5498 void bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
5501 if (bgp
->table_map
[afi
][safi
].name
) {
5502 vty_out(vty
, " table-map %s\n",
5503 bgp
->table_map
[afi
][safi
].name
);
5507 DEFUN (bgp_table_map
,
5510 "BGP table to RIB route download filter\n"
5511 "Name of the route map\n")
5514 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5515 argv
[idx_word
]->arg
);
5517 DEFUN (no_bgp_table_map
,
5518 no_bgp_table_map_cmd
,
5519 "no table-map WORD",
5521 "BGP table to RIB route download filter\n"
5522 "Name of the route map\n")
5525 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5526 argv
[idx_word
]->arg
);
5532 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
5533 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
5534 backdoor$backdoor}]",
5536 "Specify a network to announce via BGP\n"
5541 "Route-map to modify the attributes\n"
5542 "Name of the route map\n"
5543 "Label index to associate with the prefix\n"
5544 "Label index value\n"
5545 "Specify a BGP backdoor route\n")
5547 char addr_prefix_str
[BUFSIZ
];
5552 ret
= netmask_str2prefix_str(address_str
, netmask_str
,
5555 vty_out(vty
, "%% Inconsistent address and mask\n");
5556 return CMD_WARNING_CONFIG_FAILED
;
5560 return bgp_static_set(
5561 vty
, no
, address_str
? addr_prefix_str
: prefix_str
, AFI_IP
,
5562 bgp_node_safi(vty
), map_name
, backdoor
? 1 : 0,
5563 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5566 DEFPY(ipv6_bgp_network
,
5567 ipv6_bgp_network_cmd
,
5568 "[no] network X:X::X:X/M$prefix \
5569 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
5571 "Specify a network to announce via BGP\n"
5573 "Route-map to modify the attributes\n"
5574 "Name of the route map\n"
5575 "Label index to associate with the prefix\n"
5576 "Label index value\n")
5578 return bgp_static_set(
5579 vty
, no
, prefix_str
, AFI_IP6
, bgp_node_safi(vty
), map_name
, 0,
5580 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5583 static struct bgp_aggregate
*bgp_aggregate_new(void)
5585 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
5588 static void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
5590 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
5593 static int bgp_aggregate_info_same(struct bgp_path_info
*pi
, uint8_t origin
,
5594 struct aspath
*aspath
,
5595 struct community
*comm
,
5596 struct ecommunity
*ecomm
,
5597 struct lcommunity
*lcomm
)
5599 static struct aspath
*ae
= NULL
;
5602 ae
= aspath_empty();
5607 if (origin
!= pi
->attr
->origin
)
5610 if (!aspath_cmp(pi
->attr
->aspath
, (aspath
) ? aspath
: ae
))
5613 if (!community_cmp(pi
->attr
->community
, comm
))
5616 if (!ecommunity_cmp(pi
->attr
->ecommunity
, ecomm
))
5619 if (!lcommunity_cmp(pi
->attr
->lcommunity
, lcomm
))
5622 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
5628 static void bgp_aggregate_install(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
5629 struct prefix
*p
, uint8_t origin
,
5630 struct aspath
*aspath
,
5631 struct community
*community
,
5632 struct ecommunity
*ecommunity
,
5633 struct lcommunity
*lcommunity
,
5634 uint8_t atomic_aggregate
,
5635 struct bgp_aggregate
*aggregate
)
5637 struct bgp_node
*rn
;
5638 struct bgp_table
*table
;
5639 struct bgp_path_info
*pi
, *orig
, *new;
5641 table
= bgp
->rib
[afi
][safi
];
5643 rn
= bgp_node_get(table
, p
);
5645 for (orig
= pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
5646 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5647 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5650 if (aggregate
->count
> 0) {
5652 * If the aggregate information has not changed
5653 * no need to re-install it again.
5655 if (bgp_aggregate_info_same(orig
, origin
, aspath
, community
,
5656 ecommunity
, lcommunity
)) {
5657 bgp_unlock_node(rn
);
5660 aspath_free(aspath
);
5662 community_free(&community
);
5664 ecommunity_free(&ecommunity
);
5666 lcommunity_free(&lcommunity
);
5672 * Mark the old as unusable
5675 bgp_path_info_delete(rn
, pi
);
5677 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0,
5679 bgp_attr_aggregate_intern(bgp
, origin
, aspath
,
5680 community
, ecommunity
,
5685 SET_FLAG(new->flags
, BGP_PATH_VALID
);
5687 bgp_path_info_add(rn
, new);
5688 bgp_process(bgp
, rn
, afi
, safi
);
5690 for (pi
= orig
; pi
; pi
= pi
->next
)
5691 if (pi
->peer
== bgp
->peer_self
5692 && pi
->type
== ZEBRA_ROUTE_BGP
5693 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5696 /* Withdraw static BGP route from routing table. */
5698 bgp_path_info_delete(rn
, pi
);
5699 bgp_process(bgp
, rn
, afi
, safi
);
5703 bgp_unlock_node(rn
);
5706 /* Update an aggregate as routes are added/removed from the BGP table */
5707 static void bgp_aggregate_route(struct bgp
*bgp
, struct prefix
*p
,
5708 afi_t afi
, safi_t safi
,
5709 struct bgp_aggregate
*aggregate
)
5711 struct bgp_table
*table
;
5712 struct bgp_node
*top
;
5713 struct bgp_node
*rn
;
5715 struct aspath
*aspath
= NULL
;
5716 struct community
*community
= NULL
;
5717 struct ecommunity
*ecommunity
= NULL
;
5718 struct lcommunity
*lcommunity
= NULL
;
5719 struct bgp_path_info
*pi
;
5720 unsigned long match
= 0;
5721 uint8_t atomic_aggregate
= 0;
5723 /* ORIGIN attribute: If at least one route among routes that are
5724 aggregated has ORIGIN with the value INCOMPLETE, then the
5725 aggregated route must have the ORIGIN attribute with the value
5726 INCOMPLETE. Otherwise, if at least one route among routes that
5727 are aggregated has ORIGIN with the value EGP, then the aggregated
5728 route must have the origin attribute with the value EGP. In all
5729 other case the value of the ORIGIN attribute of the aggregated
5730 route is INTERNAL. */
5731 origin
= BGP_ORIGIN_IGP
;
5733 table
= bgp
->rib
[afi
][safi
];
5735 top
= bgp_node_get(table
, p
);
5736 for (rn
= bgp_node_get(table
, p
); rn
;
5737 rn
= bgp_route_next_until(rn
, top
)) {
5738 if (rn
->p
.prefixlen
<= p
->prefixlen
)
5743 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
5744 if (BGP_PATH_HOLDDOWN(pi
))
5748 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
5749 atomic_aggregate
= 1;
5751 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5755 * summary-only aggregate route suppress
5756 * aggregated route announcements.
5758 if (aggregate
->summary_only
) {
5759 (bgp_path_info_extra_get(pi
))->suppress
++;
5760 bgp_path_info_set_flag(rn
, pi
,
5761 BGP_PATH_ATTR_CHANGED
);
5768 * If at least one route among routes that are
5769 * aggregated has ORIGIN with the value INCOMPLETE,
5770 * then the aggregated route MUST have the ORIGIN
5771 * attribute with the value INCOMPLETE. Otherwise, if
5772 * at least one route among routes that are aggregated
5773 * has ORIGIN with the value EGP, then the aggregated
5774 * route MUST have the ORIGIN attribute with the value
5777 switch (pi
->attr
->origin
) {
5778 case BGP_ORIGIN_INCOMPLETE
:
5779 aggregate
->incomplete_origin_count
++;
5781 case BGP_ORIGIN_EGP
:
5782 aggregate
->egp_origin_count
++;
5790 if (!aggregate
->as_set
)
5794 * as-set aggregate route generate origin, as path,
5795 * and community aggregation.
5797 /* Compute aggregate route's as-path.
5799 bgp_compute_aggregate_aspath(aggregate
,
5802 /* Compute aggregate route's community.
5804 if (pi
->attr
->community
)
5805 bgp_compute_aggregate_community(
5807 pi
->attr
->community
);
5809 /* Compute aggregate route's extended community.
5811 if (pi
->attr
->ecommunity
)
5812 bgp_compute_aggregate_ecommunity(
5814 pi
->attr
->ecommunity
);
5816 /* Compute aggregate route's large community.
5818 if (pi
->attr
->lcommunity
)
5819 bgp_compute_aggregate_lcommunity(
5821 pi
->attr
->lcommunity
);
5824 bgp_process(bgp
, rn
, afi
, safi
);
5826 bgp_unlock_node(top
);
5829 if (aggregate
->incomplete_origin_count
> 0)
5830 origin
= BGP_ORIGIN_INCOMPLETE
;
5831 else if (aggregate
->egp_origin_count
> 0)
5832 origin
= BGP_ORIGIN_EGP
;
5834 if (aggregate
->as_set
) {
5835 if (aggregate
->aspath
)
5836 /* Retrieve aggregate route's as-path.
5838 aspath
= aspath_dup(aggregate
->aspath
);
5840 if (aggregate
->community
)
5841 /* Retrieve aggregate route's community.
5843 community
= community_dup(aggregate
->community
);
5845 if (aggregate
->ecommunity
)
5846 /* Retrieve aggregate route's ecommunity.
5848 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
5850 if (aggregate
->lcommunity
)
5851 /* Retrieve aggregate route's lcommunity.
5853 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
5856 bgp_aggregate_install(bgp
, afi
, safi
, p
, origin
, aspath
, community
,
5857 ecommunity
, lcommunity
, atomic_aggregate
,
5861 static void bgp_aggregate_delete(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
5862 safi_t safi
, struct bgp_aggregate
*aggregate
)
5864 struct bgp_table
*table
;
5865 struct bgp_node
*top
;
5866 struct bgp_node
*rn
;
5867 struct bgp_path_info
*pi
;
5868 unsigned long match
;
5870 table
= bgp
->rib
[afi
][safi
];
5872 /* If routes exists below this node, generate aggregate routes. */
5873 top
= bgp_node_get(table
, p
);
5874 for (rn
= bgp_node_get(table
, p
); rn
;
5875 rn
= bgp_route_next_until(rn
, top
)) {
5876 if (rn
->p
.prefixlen
<= p
->prefixlen
)
5880 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
5881 if (BGP_PATH_HOLDDOWN(pi
))
5884 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5887 if (aggregate
->summary_only
&& pi
->extra
) {
5888 pi
->extra
->suppress
--;
5890 if (pi
->extra
->suppress
== 0) {
5891 bgp_path_info_set_flag(
5892 rn
, pi
, BGP_PATH_ATTR_CHANGED
);
5898 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
5899 aggregate
->incomplete_origin_count
--;
5900 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
5901 aggregate
->egp_origin_count
--;
5903 if (aggregate
->as_set
) {
5904 /* Remove as-path from aggregate.
5906 bgp_remove_aspath_from_aggregate(
5910 if (pi
->attr
->community
)
5911 /* Remove community from aggregate.
5913 bgp_remove_community_from_aggregate(
5915 pi
->attr
->community
);
5917 if (pi
->attr
->ecommunity
)
5918 /* Remove ecommunity from aggregate.
5920 bgp_remove_ecommunity_from_aggregate(
5922 pi
->attr
->ecommunity
);
5924 if (pi
->attr
->lcommunity
)
5925 /* Remove lcommunity from aggregate.
5927 bgp_remove_lcommunity_from_aggregate(
5929 pi
->attr
->lcommunity
);
5934 /* If this node was suppressed, process the change. */
5936 bgp_process(bgp
, rn
, afi
, safi
);
5938 bgp_unlock_node(top
);
5941 static void bgp_add_route_to_aggregate(struct bgp
*bgp
, struct prefix
*aggr_p
,
5942 struct bgp_path_info
*pinew
, afi_t afi
,
5944 struct bgp_aggregate
*aggregate
)
5947 struct aspath
*aspath
= NULL
;
5948 uint8_t atomic_aggregate
= 0;
5949 struct community
*community
= NULL
;
5950 struct ecommunity
*ecommunity
= NULL
;
5951 struct lcommunity
*lcommunity
= NULL
;
5953 /* ORIGIN attribute: If at least one route among routes that are
5954 * aggregated has ORIGIN with the value INCOMPLETE, then the
5955 * aggregated route must have the ORIGIN attribute with the value
5956 * INCOMPLETE. Otherwise, if at least one route among routes that
5957 * are aggregated has ORIGIN with the value EGP, then the aggregated
5958 * route must have the origin attribute with the value EGP. In all
5959 * other case the value of the ORIGIN attribute of the aggregated
5960 * route is INTERNAL.
5962 origin
= BGP_ORIGIN_IGP
;
5966 if (aggregate
->summary_only
)
5967 (bgp_path_info_extra_get(pinew
))->suppress
++;
5969 switch (pinew
->attr
->origin
) {
5970 case BGP_ORIGIN_INCOMPLETE
:
5971 aggregate
->incomplete_origin_count
++;
5973 case BGP_ORIGIN_EGP
:
5974 aggregate
->egp_origin_count
++;
5982 if (aggregate
->incomplete_origin_count
> 0)
5983 origin
= BGP_ORIGIN_INCOMPLETE
;
5984 else if (aggregate
->egp_origin_count
> 0)
5985 origin
= BGP_ORIGIN_EGP
;
5987 if (aggregate
->as_set
) {
5988 /* Compute aggregate route's as-path.
5990 bgp_compute_aggregate_aspath(aggregate
,
5991 pinew
->attr
->aspath
);
5993 /* Compute aggregate route's community.
5995 if (pinew
->attr
->community
)
5996 bgp_compute_aggregate_community(
5998 pinew
->attr
->community
);
6000 /* Compute aggregate route's extended community.
6002 if (pinew
->attr
->ecommunity
)
6003 bgp_compute_aggregate_ecommunity(
6005 pinew
->attr
->ecommunity
);
6007 /* Compute aggregate route's large community.
6009 if (pinew
->attr
->lcommunity
)
6010 bgp_compute_aggregate_lcommunity(
6012 pinew
->attr
->lcommunity
);
6014 /* Retrieve aggregate route's as-path.
6016 if (aggregate
->aspath
)
6017 aspath
= aspath_dup(aggregate
->aspath
);
6019 /* Retrieve aggregate route's community.
6021 if (aggregate
->community
)
6022 community
= community_dup(aggregate
->community
);
6024 /* Retrieve aggregate route's ecommunity.
6026 if (aggregate
->ecommunity
)
6027 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
6029 /* Retrieve aggregate route's lcommunity.
6031 if (aggregate
->lcommunity
)
6032 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
6035 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
6036 aspath
, community
, ecommunity
,
6037 lcommunity
, atomic_aggregate
, aggregate
);
6040 static void bgp_remove_route_from_aggregate(struct bgp
*bgp
, afi_t afi
,
6042 struct bgp_path_info
*pi
,
6043 struct bgp_aggregate
*aggregate
,
6044 struct prefix
*aggr_p
)
6047 struct aspath
*aspath
= NULL
;
6048 uint8_t atomic_aggregate
= 0;
6049 struct community
*community
= NULL
;
6050 struct ecommunity
*ecommunity
= NULL
;
6051 struct lcommunity
*lcommunity
= NULL
;
6052 unsigned long match
= 0;
6054 if (BGP_PATH_HOLDDOWN(pi
))
6057 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6060 if (aggregate
->summary_only
6062 && pi
->extra
->suppress
> 0) {
6063 pi
->extra
->suppress
--;
6065 if (pi
->extra
->suppress
== 0) {
6066 bgp_path_info_set_flag(pi
->net
, pi
,
6067 BGP_PATH_ATTR_CHANGED
);
6072 if (aggregate
->count
> 0)
6075 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
6076 aggregate
->incomplete_origin_count
--;
6077 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
6078 aggregate
->egp_origin_count
--;
6080 if (aggregate
->as_set
) {
6081 /* Remove as-path from aggregate.
6083 bgp_remove_aspath_from_aggregate(aggregate
,
6086 if (pi
->attr
->community
)
6087 /* Remove community from aggregate.
6089 bgp_remove_community_from_aggregate(
6091 pi
->attr
->community
);
6093 if (pi
->attr
->ecommunity
)
6094 /* Remove ecommunity from aggregate.
6096 bgp_remove_ecommunity_from_aggregate(
6098 pi
->attr
->ecommunity
);
6100 if (pi
->attr
->lcommunity
)
6101 /* Remove lcommunity from aggregate.
6103 bgp_remove_lcommunity_from_aggregate(
6105 pi
->attr
->lcommunity
);
6108 /* If this node was suppressed, process the change. */
6110 bgp_process(bgp
, pi
->net
, afi
, safi
);
6112 origin
= BGP_ORIGIN_IGP
;
6113 if (aggregate
->incomplete_origin_count
> 0)
6114 origin
= BGP_ORIGIN_INCOMPLETE
;
6115 else if (aggregate
->egp_origin_count
> 0)
6116 origin
= BGP_ORIGIN_EGP
;
6118 if (aggregate
->as_set
) {
6119 /* Retrieve aggregate route's as-path.
6121 if (aggregate
->aspath
)
6122 aspath
= aspath_dup(aggregate
->aspath
);
6124 /* Retrieve aggregate route's community.
6126 if (aggregate
->community
)
6127 community
= community_dup(aggregate
->community
);
6129 /* Retrieve aggregate route's ecommunity.
6131 if (aggregate
->ecommunity
)
6132 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
6134 /* Retrieve aggregate route's lcommunity.
6136 if (aggregate
->lcommunity
)
6137 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
6140 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
6141 aspath
, community
, ecommunity
,
6142 lcommunity
, atomic_aggregate
, aggregate
);
6145 void bgp_aggregate_increment(struct bgp
*bgp
, struct prefix
*p
,
6146 struct bgp_path_info
*pi
, afi_t afi
, safi_t safi
)
6148 struct bgp_node
*child
;
6149 struct bgp_node
*rn
;
6150 struct bgp_aggregate
*aggregate
;
6151 struct bgp_table
*table
;
6153 table
= bgp
->aggregate
[afi
][safi
];
6155 /* No aggregates configured. */
6156 if (bgp_table_top_nolock(table
) == NULL
)
6159 if (p
->prefixlen
== 0)
6162 if (BGP_PATH_HOLDDOWN(pi
))
6165 child
= bgp_node_get(table
, p
);
6167 /* Aggregate address configuration check. */
6168 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
)) {
6169 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6170 if (aggregate
!= NULL
&& rn
->p
.prefixlen
< p
->prefixlen
) {
6171 bgp_add_route_to_aggregate(bgp
, &rn
->p
, pi
, afi
,
6175 bgp_unlock_node(child
);
6178 void bgp_aggregate_decrement(struct bgp
*bgp
, struct prefix
*p
,
6179 struct bgp_path_info
*del
, afi_t afi
, safi_t safi
)
6181 struct bgp_node
*child
;
6182 struct bgp_node
*rn
;
6183 struct bgp_aggregate
*aggregate
;
6184 struct bgp_table
*table
;
6186 table
= bgp
->aggregate
[afi
][safi
];
6188 /* No aggregates configured. */
6189 if (bgp_table_top_nolock(table
) == NULL
)
6192 if (p
->prefixlen
== 0)
6195 child
= bgp_node_get(table
, p
);
6197 /* Aggregate address configuration check. */
6198 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
)) {
6199 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6200 if (aggregate
!= NULL
&& rn
->p
.prefixlen
< p
->prefixlen
) {
6201 bgp_remove_route_from_aggregate(bgp
, afi
, safi
,
6202 del
, aggregate
, &rn
->p
);
6205 bgp_unlock_node(child
);
6208 /* Aggregate route attribute. */
6209 #define AGGREGATE_SUMMARY_ONLY 1
6210 #define AGGREGATE_AS_SET 1
6212 static int bgp_aggregate_unset(struct vty
*vty
, const char *prefix_str
,
6213 afi_t afi
, safi_t safi
)
6215 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6218 struct bgp_node
*rn
;
6219 struct bgp_aggregate
*aggregate
;
6221 /* Convert string to prefix structure. */
6222 ret
= str2prefix(prefix_str
, &p
);
6224 vty_out(vty
, "Malformed prefix\n");
6225 return CMD_WARNING_CONFIG_FAILED
;
6229 /* Old configuration check. */
6230 rn
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], &p
);
6233 "%% There is no aggregate-address configuration.\n");
6234 return CMD_WARNING_CONFIG_FAILED
;
6237 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6238 bgp_aggregate_delete(bgp
, &p
, afi
, safi
, aggregate
);
6239 bgp_aggregate_install(bgp
, afi
, safi
, &p
, 0, NULL
, NULL
,
6240 NULL
, NULL
, 0, aggregate
);
6242 /* Unlock aggregate address configuration. */
6243 bgp_node_set_bgp_aggregate_info(rn
, NULL
);
6245 if (aggregate
->community
)
6246 community_free(&aggregate
->community
);
6248 if (aggregate
->community_hash
) {
6249 /* Delete all communities in the hash.
6251 hash_clean(aggregate
->community_hash
,
6252 bgp_aggr_community_remove
);
6253 /* Free up the community_hash.
6255 hash_free(aggregate
->community_hash
);
6258 if (aggregate
->ecommunity
)
6259 ecommunity_free(&aggregate
->ecommunity
);
6261 if (aggregate
->ecommunity_hash
) {
6262 /* Delete all ecommunities in the hash.
6264 hash_clean(aggregate
->ecommunity_hash
,
6265 bgp_aggr_ecommunity_remove
);
6266 /* Free up the ecommunity_hash.
6268 hash_free(aggregate
->ecommunity_hash
);
6271 if (aggregate
->lcommunity
)
6272 lcommunity_free(&aggregate
->lcommunity
);
6274 if (aggregate
->lcommunity_hash
) {
6275 /* Delete all lcommunities in the hash.
6277 hash_clean(aggregate
->lcommunity_hash
,
6278 bgp_aggr_lcommunity_remove
);
6279 /* Free up the lcommunity_hash.
6281 hash_free(aggregate
->lcommunity_hash
);
6284 if (aggregate
->aspath
)
6285 aspath_free(aggregate
->aspath
);
6287 if (aggregate
->aspath_hash
) {
6288 /* Delete all as-paths in the hash.
6290 hash_clean(aggregate
->aspath_hash
,
6291 bgp_aggr_aspath_remove
);
6292 /* Free up the aspath_hash.
6294 hash_free(aggregate
->aspath_hash
);
6297 bgp_aggregate_free(aggregate
);
6298 bgp_unlock_node(rn
);
6299 bgp_unlock_node(rn
);
6304 static int bgp_aggregate_set(struct vty
*vty
, const char *prefix_str
, afi_t afi
,
6305 safi_t safi
, uint8_t summary_only
, uint8_t as_set
)
6307 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6310 struct bgp_node
*rn
;
6311 struct bgp_aggregate
*aggregate
;
6313 /* Convert string to prefix structure. */
6314 ret
= str2prefix(prefix_str
, &p
);
6316 vty_out(vty
, "Malformed prefix\n");
6317 return CMD_WARNING_CONFIG_FAILED
;
6321 if ((afi
== AFI_IP
&& p
.prefixlen
== IPV4_MAX_BITLEN
) ||
6322 (afi
== AFI_IP6
&& p
.prefixlen
== IPV6_MAX_BITLEN
)) {
6323 vty_out(vty
, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
6325 return CMD_WARNING_CONFIG_FAILED
;
6328 /* Old configuration check. */
6329 rn
= bgp_node_get(bgp
->aggregate
[afi
][safi
], &p
);
6331 if (bgp_node_has_bgp_path_info_data(rn
)) {
6332 vty_out(vty
, "There is already same aggregate network.\n");
6333 /* try to remove the old entry */
6334 ret
= bgp_aggregate_unset(vty
, prefix_str
, afi
, safi
);
6336 vty_out(vty
, "Error deleting aggregate.\n");
6337 bgp_unlock_node(rn
);
6338 return CMD_WARNING_CONFIG_FAILED
;
6342 /* Make aggregate address structure. */
6343 aggregate
= bgp_aggregate_new();
6344 aggregate
->summary_only
= summary_only
;
6345 aggregate
->as_set
= as_set
;
6346 aggregate
->safi
= safi
;
6347 bgp_node_set_bgp_aggregate_info(rn
, aggregate
);
6349 /* Aggregate address insert into BGP routing table. */
6350 bgp_aggregate_route(bgp
, &p
, afi
, safi
, aggregate
);
6355 DEFUN (aggregate_address
,
6356 aggregate_address_cmd
,
6357 "aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
6358 "Configure BGP aggregate entries\n"
6359 "Aggregate prefix\n"
6360 "Generate AS set path information\n"
6361 "Filter more specific routes from updates\n"
6362 "Filter more specific routes from updates\n"
6363 "Generate AS set path information\n")
6366 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
6367 char *prefix
= argv
[idx
]->arg
;
6369 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
6371 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6372 ? AGGREGATE_SUMMARY_ONLY
6375 return bgp_aggregate_set(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
),
6376 summary_only
, as_set
);
6379 DEFUN (aggregate_address_mask
,
6380 aggregate_address_mask_cmd
,
6381 "aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
6382 "Configure BGP aggregate entries\n"
6383 "Aggregate address\n"
6385 "Generate AS set path information\n"
6386 "Filter more specific routes from updates\n"
6387 "Filter more specific routes from updates\n"
6388 "Generate AS set path information\n")
6391 argv_find(argv
, argc
, "A.B.C.D", &idx
);
6392 char *prefix
= argv
[idx
]->arg
;
6393 char *mask
= argv
[idx
+ 1]->arg
;
6395 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
6397 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6398 ? AGGREGATE_SUMMARY_ONLY
6401 char prefix_str
[BUFSIZ
];
6402 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
6405 vty_out(vty
, "%% Inconsistent address and mask\n");
6406 return CMD_WARNING_CONFIG_FAILED
;
6409 return bgp_aggregate_set(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
),
6410 summary_only
, as_set
);
6413 DEFUN (no_aggregate_address
,
6414 no_aggregate_address_cmd
,
6415 "no aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
6417 "Configure BGP aggregate entries\n"
6418 "Aggregate prefix\n"
6419 "Generate AS set path information\n"
6420 "Filter more specific routes from updates\n"
6421 "Filter more specific routes from updates\n"
6422 "Generate AS set path information\n")
6425 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
6426 char *prefix
= argv
[idx
]->arg
;
6427 return bgp_aggregate_unset(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
));
6430 DEFUN (no_aggregate_address_mask
,
6431 no_aggregate_address_mask_cmd
,
6432 "no aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
6434 "Configure BGP aggregate entries\n"
6435 "Aggregate address\n"
6437 "Generate AS set path information\n"
6438 "Filter more specific routes from updates\n"
6439 "Filter more specific routes from updates\n"
6440 "Generate AS set path information\n")
6443 argv_find(argv
, argc
, "A.B.C.D", &idx
);
6444 char *prefix
= argv
[idx
]->arg
;
6445 char *mask
= argv
[idx
+ 1]->arg
;
6447 char prefix_str
[BUFSIZ
];
6448 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
6451 vty_out(vty
, "%% Inconsistent address and mask\n");
6452 return CMD_WARNING_CONFIG_FAILED
;
6455 return bgp_aggregate_unset(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
));
6458 DEFUN (ipv6_aggregate_address
,
6459 ipv6_aggregate_address_cmd
,
6460 "aggregate-address X:X::X:X/M [summary-only]",
6461 "Configure BGP aggregate entries\n"
6462 "Aggregate prefix\n"
6463 "Filter more specific routes from updates\n")
6466 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6467 char *prefix
= argv
[idx
]->arg
;
6468 int sum_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6469 ? AGGREGATE_SUMMARY_ONLY
6471 return bgp_aggregate_set(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
, sum_only
,
6475 DEFUN (no_ipv6_aggregate_address
,
6476 no_ipv6_aggregate_address_cmd
,
6477 "no aggregate-address X:X::X:X/M [summary-only]",
6479 "Configure BGP aggregate entries\n"
6480 "Aggregate prefix\n"
6481 "Filter more specific routes from updates\n")
6484 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6485 char *prefix
= argv
[idx
]->arg
;
6486 return bgp_aggregate_unset(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
);
6489 /* Redistribute route treatment. */
6490 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
6491 const union g_addr
*nexthop
, ifindex_t ifindex
,
6492 enum nexthop_types_t nhtype
, uint32_t metric
,
6493 uint8_t type
, unsigned short instance
,
6496 struct bgp_path_info
*new;
6497 struct bgp_path_info
*bpi
;
6498 struct bgp_path_info rmap_path
;
6499 struct bgp_node
*bn
;
6501 struct attr
*new_attr
;
6504 struct bgp_redist
*red
;
6506 /* Make default attribute. */
6507 bgp_attr_default_set(&attr
, BGP_ORIGIN_INCOMPLETE
);
6510 case NEXTHOP_TYPE_IFINDEX
:
6512 case NEXTHOP_TYPE_IPV4
:
6513 case NEXTHOP_TYPE_IPV4_IFINDEX
:
6514 attr
.nexthop
= nexthop
->ipv4
;
6516 case NEXTHOP_TYPE_IPV6
:
6517 case NEXTHOP_TYPE_IPV6_IFINDEX
:
6518 attr
.mp_nexthop_global
= nexthop
->ipv6
;
6519 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6521 case NEXTHOP_TYPE_BLACKHOLE
:
6522 switch (p
->family
) {
6524 attr
.nexthop
.s_addr
= INADDR_ANY
;
6527 memset(&attr
.mp_nexthop_global
, 0,
6528 sizeof(attr
.mp_nexthop_global
));
6529 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6534 attr
.nh_ifindex
= ifindex
;
6537 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6540 afi
= family2afi(p
->family
);
6542 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6544 struct attr attr_new
;
6546 /* Copy attribute for modification. */
6547 bgp_attr_dup(&attr_new
, &attr
);
6549 if (red
->redist_metric_flag
)
6550 attr_new
.med
= red
->redist_metric
;
6552 /* Apply route-map. */
6553 if (red
->rmap
.name
) {
6554 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
6555 rmap_path
.peer
= bgp
->peer_self
;
6556 rmap_path
.attr
= &attr_new
;
6558 SET_FLAG(bgp
->peer_self
->rmap_type
,
6559 PEER_RMAP_TYPE_REDISTRIBUTE
);
6561 ret
= route_map_apply(red
->rmap
.map
, p
, RMAP_BGP
,
6564 bgp
->peer_self
->rmap_type
= 0;
6566 if (ret
== RMAP_DENYMATCH
) {
6567 /* Free uninterned attribute. */
6568 bgp_attr_flush(&attr_new
);
6570 /* Unintern original. */
6571 aspath_unintern(&attr
.aspath
);
6572 bgp_redistribute_delete(bgp
, p
, type
, instance
);
6577 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
6578 bgp_attr_add_gshut_community(&attr_new
);
6580 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6581 SAFI_UNICAST
, p
, NULL
);
6583 new_attr
= bgp_attr_intern(&attr_new
);
6585 for (bpi
= bgp_node_get_bgp_path_info(bn
); bpi
;
6587 if (bpi
->peer
== bgp
->peer_self
6588 && bpi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
6592 /* Ensure the (source route) type is updated. */
6594 if (attrhash_cmp(bpi
->attr
, new_attr
)
6595 && !CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
)) {
6596 bgp_attr_unintern(&new_attr
);
6597 aspath_unintern(&attr
.aspath
);
6598 bgp_unlock_node(bn
);
6601 /* The attribute is changed. */
6602 bgp_path_info_set_flag(bn
, bpi
,
6603 BGP_PATH_ATTR_CHANGED
);
6605 /* Rewrite BGP route information. */
6606 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
6607 bgp_path_info_restore(bn
, bpi
);
6609 bgp_aggregate_decrement(
6610 bgp
, p
, bpi
, afi
, SAFI_UNICAST
);
6611 bgp_attr_unintern(&bpi
->attr
);
6612 bpi
->attr
= new_attr
;
6613 bpi
->uptime
= bgp_clock();
6615 /* Process change. */
6616 bgp_aggregate_increment(bgp
, p
, bpi
, afi
,
6618 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6619 bgp_unlock_node(bn
);
6620 aspath_unintern(&attr
.aspath
);
6622 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6624 == BGP_INSTANCE_TYPE_DEFAULT
)) {
6626 vpn_leak_from_vrf_update(
6627 bgp_get_default(), bgp
, bpi
);
6633 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
6634 bgp
->peer_self
, new_attr
, bn
);
6635 SET_FLAG(new->flags
, BGP_PATH_VALID
);
6637 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
6638 bgp_path_info_add(bn
, new);
6639 bgp_unlock_node(bn
);
6640 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6642 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6643 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6645 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
6649 /* Unintern original. */
6650 aspath_unintern(&attr
.aspath
);
6653 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, uint8_t type
,
6654 unsigned short instance
)
6657 struct bgp_node
*rn
;
6658 struct bgp_path_info
*pi
;
6659 struct bgp_redist
*red
;
6661 afi
= family2afi(p
->family
);
6663 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6665 rn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6666 SAFI_UNICAST
, p
, NULL
);
6668 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
6669 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
)
6673 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6674 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6676 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6679 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, SAFI_UNICAST
);
6680 bgp_path_info_delete(rn
, pi
);
6681 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6683 bgp_unlock_node(rn
);
6687 /* Withdraw specified route type's route. */
6688 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
6689 unsigned short instance
)
6691 struct bgp_node
*rn
;
6692 struct bgp_path_info
*pi
;
6693 struct bgp_table
*table
;
6695 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
6697 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
6698 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
6699 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
6700 && pi
->instance
== instance
)
6704 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6705 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6707 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6710 bgp_aggregate_decrement(bgp
, &rn
->p
, pi
, afi
,
6712 bgp_path_info_delete(rn
, pi
);
6713 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6718 /* Static function to display route. */
6719 static void route_vty_out_route(struct prefix
*p
, struct vty
*vty
,
6726 if (p
->family
== AF_INET
) {
6730 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
6733 json_object_string_add(json
, "prefix",
6734 inet_ntop(p
->family
,
6737 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
6738 prefix2str(p
, buf2
, PREFIX_STRLEN
);
6739 json_object_string_add(json
, "network", buf2
);
6741 } else if (p
->family
== AF_ETHERNET
) {
6742 prefix2str(p
, buf
, PREFIX_STRLEN
);
6743 len
= vty_out(vty
, "%s", buf
);
6744 } else if (p
->family
== AF_EVPN
) {
6748 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf
,
6751 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
6752 } else if (p
->family
== AF_FLOWSPEC
) {
6753 route_vty_out_flowspec(vty
, p
, NULL
,
6755 NLRI_STRING_FORMAT_JSON_SIMPLE
:
6756 NLRI_STRING_FORMAT_MIN
, json
);
6761 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
6764 json_object_string_add(json
, "prefix",
6765 inet_ntop(p
->family
,
6768 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
6769 prefix2str(p
, buf2
, PREFIX_STRLEN
);
6770 json_object_string_add(json
, "network", buf2
);
6777 vty_out(vty
, "\n%*s", 20, " ");
6779 vty_out(vty
, "%*s", len
, " ");
6783 enum bgp_display_type
{
6787 /* Print the short form route status for a bgp_path_info */
6788 static void route_vty_short_status_out(struct vty
*vty
,
6789 struct bgp_path_info
*path
,
6790 json_object
*json_path
)
6794 /* Route status display. */
6795 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
6796 json_object_boolean_true_add(json_path
, "removed");
6798 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
6799 json_object_boolean_true_add(json_path
, "stale");
6801 if (path
->extra
&& path
->extra
->suppress
)
6802 json_object_boolean_true_add(json_path
, "suppressed");
6804 if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
6805 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
6806 json_object_boolean_true_add(json_path
, "valid");
6809 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
6810 json_object_boolean_true_add(json_path
, "history");
6812 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
6813 json_object_boolean_true_add(json_path
, "damped");
6815 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
6816 json_object_boolean_true_add(json_path
, "bestpath");
6818 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
6819 json_object_boolean_true_add(json_path
, "multipath");
6821 /* Internal route. */
6822 if ((path
->peer
->as
)
6823 && (path
->peer
->as
== path
->peer
->local_as
))
6824 json_object_string_add(json_path
, "pathFrom",
6827 json_object_string_add(json_path
, "pathFrom",
6833 /* Route status display. */
6834 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
6836 else if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
6838 else if (path
->extra
&& path
->extra
->suppress
)
6840 else if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
6841 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
6847 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
6849 else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
6851 else if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
6853 else if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
6858 /* Internal route. */
6859 if (path
->peer
&& (path
->peer
->as
)
6860 && (path
->peer
->as
== path
->peer
->local_as
))
6866 static char *bgp_nexthop_fqdn(struct peer
*peer
)
6868 if (peer
->hostname
&& bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
))
6869 return peer
->hostname
;
6873 /* called from terminal list command */
6874 void route_vty_out(struct vty
*vty
, struct prefix
*p
,
6875 struct bgp_path_info
*path
, int display
, safi_t safi
,
6876 json_object
*json_paths
)
6879 json_object
*json_path
= NULL
;
6880 json_object
*json_nexthops
= NULL
;
6881 json_object
*json_nexthop_global
= NULL
;
6882 json_object
*json_nexthop_ll
= NULL
;
6883 char vrf_id_str
[VRF_NAMSIZ
] = {0};
6885 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
6886 bool nexthop_othervrf
= false;
6887 vrf_id_t nexthop_vrfid
= VRF_DEFAULT
;
6888 const char *nexthop_vrfname
= VRF_DEFAULT_NAME
;
6889 char *nexthop_fqdn
= bgp_nexthop_fqdn(path
->peer
);
6892 json_path
= json_object_new_object();
6894 /* short status lead text */
6895 route_vty_short_status_out(vty
, path
, json_path
);
6898 /* print prefix and mask */
6900 route_vty_out_route(p
, vty
, json_path
);
6902 vty_out(vty
, "%*s", 17, " ");
6904 route_vty_out_route(p
, vty
, json_path
);
6907 /* Print attribute */
6911 json_object_array_add(json_paths
, json_path
);
6919 * If vrf id of nexthop is different from that of prefix,
6920 * set up printable string to append
6922 if (path
->extra
&& path
->extra
->bgp_orig
) {
6923 const char *self
= "";
6928 nexthop_othervrf
= true;
6929 nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
6931 if (path
->extra
->bgp_orig
->vrf_id
== VRF_UNKNOWN
)
6932 snprintf(vrf_id_str
, sizeof(vrf_id_str
),
6933 "@%s%s", VRFID_NONE_STR
, self
);
6935 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "@%u%s",
6936 path
->extra
->bgp_orig
->vrf_id
, self
);
6938 if (path
->extra
->bgp_orig
->inst_type
6939 != BGP_INSTANCE_TYPE_DEFAULT
)
6941 nexthop_vrfname
= path
->extra
->bgp_orig
->name
;
6943 const char *self
= "";
6948 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "%s", self
);
6952 * For ENCAP and EVPN routes, nexthop address family is not
6953 * neccessarily the same as the prefix address family.
6954 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
6955 * EVPN routes are also exchanged with a MP nexthop. Currently,
6957 * is only IPv4, the value will be present in either
6959 * attr->mp_nexthop_global_in
6961 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
6964 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
6968 sprintf(nexthop
, "%s",
6969 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
6973 sprintf(nexthop
, "%s",
6974 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
6978 sprintf(nexthop
, "?");
6983 json_nexthop_global
= json_object_new_object();
6985 json_object_string_add(
6986 json_nexthop_global
, "afi",
6987 nexthop_fqdn
? "fqdn"
6988 : (af
== AF_INET
) ? "ip" : "ipv6");
6989 json_object_string_add(
6990 json_nexthop_global
,
6991 nexthop_fqdn
? "fqdn"
6992 : (af
== AF_INET
) ? "ip" : "ipv6",
6993 nexthop_fqdn
? nexthop_fqdn
: nexthop
);
6994 json_object_boolean_true_add(json_nexthop_global
,
6997 vty_out(vty
, "%s%s",
6998 nexthop_fqdn
? nexthop_fqdn
: nexthop
,
7000 } else if (safi
== SAFI_EVPN
) {
7002 json_nexthop_global
= json_object_new_object();
7004 json_object_string_add(
7005 json_nexthop_global
,
7006 nexthop_fqdn
? "fqdn" : "ip",
7007 nexthop_fqdn
? nexthop_fqdn
7008 : inet_ntoa(attr
->nexthop
));
7009 json_object_string_add(json_nexthop_global
, "afi",
7011 json_object_boolean_true_add(json_nexthop_global
,
7014 vty_out(vty
, "%-16s%s",
7015 nexthop_fqdn
?: inet_ntoa(attr
->nexthop
),
7017 } else if (safi
== SAFI_FLOWSPEC
) {
7018 if (attr
->nexthop
.s_addr
!= 0) {
7020 json_nexthop_global
= json_object_new_object();
7021 json_object_string_add(
7022 json_nexthop_global
,
7023 nexthop_fqdn
? "fqdn" : "ip",
7026 : inet_ntoa(attr
->nexthop
));
7027 json_object_string_add(json_nexthop_global
,
7029 json_object_boolean_true_add(
7030 json_nexthop_global
,
7033 vty_out(vty
, "%-16s",
7036 : inet_ntoa(attr
->nexthop
));
7039 } else if (p
->family
== AF_INET
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7041 json_nexthop_global
= json_object_new_object();
7043 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_EVPN
))
7044 json_object_string_add(
7045 json_nexthop_global
,
7046 nexthop_fqdn
? "fqdn" : "ip",
7050 attr
->mp_nexthop_global_in
));
7052 json_object_string_add(
7053 json_nexthop_global
,
7054 nexthop_fqdn
? "fqdn" : "ip",
7057 : inet_ntoa(attr
->nexthop
));
7059 json_object_string_add(json_nexthop_global
, "afi",
7061 json_object_boolean_true_add(json_nexthop_global
,
7066 snprintf(buf
, sizeof(buf
), "%s%s",
7067 nexthop_fqdn
? nexthop_fqdn
7068 : inet_ntoa(attr
->nexthop
),
7070 vty_out(vty
, "%-16s", buf
);
7075 else if (p
->family
== AF_INET6
|| BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7080 json_nexthop_global
= json_object_new_object();
7081 json_object_string_add(
7082 json_nexthop_global
,
7083 nexthop_fqdn
? "fqdn" : "ip",
7086 : inet_ntop(AF_INET6
,
7087 &attr
->mp_nexthop_global
,
7089 json_object_string_add(json_nexthop_global
, "afi",
7091 json_object_string_add(json_nexthop_global
, "scope",
7094 /* We display both LL & GL if both have been
7096 if ((attr
->mp_nexthop_len
== 32)
7097 || (path
->peer
->conf_if
)) {
7098 json_nexthop_ll
= json_object_new_object();
7099 json_object_string_add(
7101 nexthop_fqdn
? "fqdn" : "ip",
7106 &attr
->mp_nexthop_local
,
7108 json_object_string_add(json_nexthop_ll
, "afi",
7110 json_object_string_add(json_nexthop_ll
, "scope",
7113 if ((IPV6_ADDR_CMP(&attr
->mp_nexthop_global
,
7114 &attr
->mp_nexthop_local
)
7116 && !attr
->mp_nexthop_prefer_global
)
7117 json_object_boolean_true_add(
7118 json_nexthop_ll
, "used");
7120 json_object_boolean_true_add(
7121 json_nexthop_global
, "used");
7123 json_object_boolean_true_add(
7124 json_nexthop_global
, "used");
7126 /* Display LL if LL/Global both in table unless
7127 * prefer-global is set */
7128 if (((attr
->mp_nexthop_len
== 32)
7129 && !attr
->mp_nexthop_prefer_global
)
7130 || (path
->peer
->conf_if
)) {
7131 if (path
->peer
->conf_if
) {
7132 len
= vty_out(vty
, "%s",
7133 path
->peer
->conf_if
);
7134 len
= 16 - len
; /* len of IPv6
7140 vty_out(vty
, "\n%*s", 36, " ");
7142 vty_out(vty
, "%*s", len
, " ");
7150 &attr
->mp_nexthop_local
,
7156 vty_out(vty
, "\n%*s", 36, " ");
7158 vty_out(vty
, "%*s", len
, " ");
7167 &attr
->mp_nexthop_global
,
7173 vty_out(vty
, "\n%*s", 36, " ");
7175 vty_out(vty
, "%*s", len
, " ");
7181 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
7185 * Adding "metric" field to match with corresponding
7186 * CLI. "med" will be deprecated in future.
7188 json_object_int_add(json_path
, "med", attr
->med
);
7189 json_object_int_add(json_path
, "metric", attr
->med
);
7191 vty_out(vty
, "%10u", attr
->med
);
7192 else if (!json_paths
)
7196 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
7200 * Adding "locPrf" field to match with corresponding
7201 * CLI. "localPref" will be deprecated in future.
7203 json_object_int_add(json_path
, "localpref",
7205 json_object_int_add(json_path
, "locPrf",
7208 vty_out(vty
, "%7u", attr
->local_pref
);
7209 else if (!json_paths
)
7213 json_object_int_add(json_path
, "weight", attr
->weight
);
7215 vty_out(vty
, "%7u ", attr
->weight
);
7219 json_object_string_add(
7220 json_path
, "peerId",
7221 sockunion2str(&path
->peer
->su
, buf
, SU_ADDRSTRLEN
));
7229 * Adding "path" field to match with corresponding
7230 * CLI. "aspath" will be deprecated in future.
7232 json_object_string_add(json_path
, "aspath",
7234 json_object_string_add(json_path
, "path",
7237 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7242 json_object_string_add(json_path
, "origin",
7243 bgp_origin_long_str
[attr
->origin
]);
7245 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7249 json_object_boolean_true_add(json_path
,
7250 "announceNexthopSelf");
7251 if (nexthop_othervrf
) {
7252 json_object_string_add(json_path
, "nhVrfName",
7255 json_object_int_add(json_path
, "nhVrfId",
7256 ((nexthop_vrfid
== VRF_UNKNOWN
)
7258 : (int)nexthop_vrfid
));
7263 if (json_nexthop_global
|| json_nexthop_ll
) {
7264 json_nexthops
= json_object_new_array();
7266 if (json_nexthop_global
)
7267 json_object_array_add(json_nexthops
,
7268 json_nexthop_global
);
7270 if (json_nexthop_ll
)
7271 json_object_array_add(json_nexthops
,
7274 json_object_object_add(json_path
, "nexthops",
7278 json_object_array_add(json_paths
, json_path
);
7282 /* prints an additional line, indented, with VNC info, if
7284 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
7285 rfapi_vty_out_vncinfo(vty
, p
, path
, safi
);
7290 /* called from terminal list command */
7291 void route_vty_out_tmp(struct vty
*vty
, struct prefix
*p
, struct attr
*attr
,
7292 safi_t safi
, bool use_json
, json_object
*json_ar
)
7294 json_object
*json_status
= NULL
;
7295 json_object
*json_net
= NULL
;
7298 /* Route status display. */
7300 json_status
= json_object_new_object();
7301 json_net
= json_object_new_object();
7308 /* print prefix and mask */
7310 json_object_string_add(
7311 json_net
, "addrPrefix",
7312 inet_ntop(p
->family
, &p
->u
.prefix
, buff
, BUFSIZ
));
7313 json_object_int_add(json_net
, "prefixLen", p
->prefixlen
);
7314 prefix2str(p
, buf2
, PREFIX_STRLEN
);
7315 json_object_string_add(json_net
, "network", buf2
);
7317 route_vty_out_route(p
, vty
, NULL
);
7319 /* Print attribute */
7322 if (p
->family
== AF_INET
7323 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7324 || safi
== SAFI_EVPN
7325 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7326 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7327 || safi
== SAFI_EVPN
)
7328 json_object_string_add(
7329 json_net
, "nextHop",
7331 attr
->mp_nexthop_global_in
));
7333 json_object_string_add(
7334 json_net
, "nextHop",
7335 inet_ntoa(attr
->nexthop
));
7336 } else if (p
->family
== AF_INET6
7337 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7340 json_object_string_add(
7341 json_net
, "nextHopGlobal",
7343 &attr
->mp_nexthop_global
, buf
,
7348 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
7349 json_object_int_add(json_net
, "metric",
7352 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
7355 * Adding "locPrf" field to match with
7356 * corresponding CLI. "localPref" will be
7357 * deprecated in future.
7359 json_object_int_add(json_net
, "localPref",
7361 json_object_int_add(json_net
, "locPrf",
7365 json_object_int_add(json_net
, "weight", attr
->weight
);
7371 * Adding "path" field to match with
7372 * corresponding CLI. "localPref" will be
7373 * deprecated in future.
7375 json_object_string_add(json_net
, "asPath",
7377 json_object_string_add(json_net
, "path",
7382 json_object_string_add(json_net
, "bgpOriginCode",
7383 bgp_origin_str
[attr
->origin
]);
7385 if (p
->family
== AF_INET
7386 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7387 || safi
== SAFI_EVPN
7388 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7389 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7390 || safi
== SAFI_EVPN
)
7391 vty_out(vty
, "%-16s",
7393 attr
->mp_nexthop_global_in
));
7395 vty_out(vty
, "%-16s",
7396 inet_ntoa(attr
->nexthop
));
7397 } else if (p
->family
== AF_INET6
7398 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7405 &attr
->mp_nexthop_global
, buf
,
7409 vty_out(vty
, "\n%*s", 36, " ");
7411 vty_out(vty
, "%*s", len
, " ");
7414 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
7415 vty_out(vty
, "%10u", attr
->med
);
7419 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
7420 vty_out(vty
, "%7u", attr
->local_pref
);
7424 vty_out(vty
, "%7u ", attr
->weight
);
7428 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7431 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7435 json_object_boolean_true_add(json_status
, "*");
7436 json_object_boolean_true_add(json_status
, ">");
7437 json_object_object_add(json_net
, "appliedStatusSymbols",
7439 char buf_cut
[BUFSIZ
];
7440 json_object_object_add(
7442 inet_ntop(p
->family
, &p
->u
.prefix
, buf_cut
, BUFSIZ
),
7448 void route_vty_out_tag(struct vty
*vty
, struct prefix
*p
,
7449 struct bgp_path_info
*path
, int display
, safi_t safi
,
7452 json_object
*json_out
= NULL
;
7454 mpls_label_t label
= MPLS_INVALID_LABEL
;
7460 json_out
= json_object_new_object();
7462 /* short status lead text */
7463 route_vty_short_status_out(vty
, path
, json_out
);
7465 /* print prefix and mask */
7468 route_vty_out_route(p
, vty
, NULL
);
7470 vty_out(vty
, "%*s", 17, " ");
7473 /* Print attribute */
7476 if (((p
->family
== AF_INET
)
7477 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
7478 || (safi
== SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
7479 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7480 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7481 || safi
== SAFI_EVPN
) {
7483 json_object_string_add(
7484 json_out
, "mpNexthopGlobalIn",
7486 attr
->mp_nexthop_global_in
));
7488 vty_out(vty
, "%-16s",
7490 attr
->mp_nexthop_global_in
));
7493 json_object_string_add(
7494 json_out
, "nexthop",
7495 inet_ntoa(attr
->nexthop
));
7497 vty_out(vty
, "%-16s",
7498 inet_ntoa(attr
->nexthop
));
7500 } else if (((p
->family
== AF_INET6
)
7501 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
7502 || (safi
== SAFI_EVPN
7503 && BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
7504 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7508 if (attr
->mp_nexthop_len
7509 == BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
7511 json_object_string_add(
7512 json_out
, "mpNexthopGlobalIn",
7515 &attr
->mp_nexthop_global
,
7516 buf_a
, sizeof(buf_a
)));
7521 &attr
->mp_nexthop_global
,
7522 buf_a
, sizeof(buf_a
)));
7523 } else if (attr
->mp_nexthop_len
7524 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
7527 &attr
->mp_nexthop_global
,
7528 buf_a
, sizeof(buf_a
));
7530 &attr
->mp_nexthop_local
,
7531 buf_b
, sizeof(buf_b
));
7532 sprintf(buf_c
, "%s(%s)", buf_a
, buf_b
);
7533 json_object_string_add(
7535 "mpNexthopGlobalLocal", buf_c
);
7537 vty_out(vty
, "%s(%s)",
7540 &attr
->mp_nexthop_global
,
7541 buf_a
, sizeof(buf_a
)),
7544 &attr
->mp_nexthop_local
,
7545 buf_b
, sizeof(buf_b
)));
7550 label
= decode_label(&path
->extra
->label
[0]);
7552 if (bgp_is_valid_label(&label
)) {
7554 json_object_int_add(json_out
, "notag", label
);
7555 json_object_array_add(json
, json_out
);
7557 vty_out(vty
, "notag/%d", label
);
7563 void route_vty_out_overlay(struct vty
*vty
, struct prefix
*p
,
7564 struct bgp_path_info
*path
, int display
,
7565 json_object
*json_paths
)
7569 json_object
*json_path
= NULL
;
7572 json_path
= json_object_new_object();
7577 /* short status lead text */
7578 route_vty_short_status_out(vty
, path
, json_path
);
7580 /* print prefix and mask */
7582 route_vty_out_route(p
, vty
, NULL
);
7584 vty_out(vty
, "%*s", 17, " ");
7586 /* Print attribute */
7590 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
7594 vty_out(vty
, "%-16s",
7595 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
7599 vty_out(vty
, "%s(%s)",
7600 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
7602 inet_ntop(af
, &attr
->mp_nexthop_local
, buf1
,
7609 char *str
= esi2str(&(attr
->evpn_overlay
.eth_s_id
));
7611 vty_out(vty
, "%s", str
);
7612 XFREE(MTYPE_TMP
, str
);
7614 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn
*)p
)) {
7616 inet_ntoa(attr
->evpn_overlay
.gw_ip
.ipv4
));
7617 } else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn
*)p
)) {
7620 &(attr
->evpn_overlay
.gw_ip
.ipv6
), buf
,
7623 if (attr
->ecommunity
) {
7625 struct ecommunity_val
*routermac
= ecommunity_lookup(
7626 attr
->ecommunity
, ECOMMUNITY_ENCODE_EVPN
,
7627 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
7629 mac
= ecom_mac2str((char *)routermac
->val
);
7631 vty_out(vty
, "/%s", (char *)mac
);
7632 XFREE(MTYPE_TMP
, mac
);
7640 /* dampening route */
7641 static void damp_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7642 struct bgp_path_info
*path
, int display
,
7643 safi_t safi
, bool use_json
, json_object
*json
)
7647 char timebuf
[BGP_UPTIME_LEN
];
7649 /* short status lead text */
7650 route_vty_short_status_out(vty
, path
, json
);
7652 /* print prefix and mask */
7655 route_vty_out_route(p
, vty
, NULL
);
7657 vty_out(vty
, "%*s", 17, " ");
7660 len
= vty_out(vty
, "%s", path
->peer
->host
);
7664 vty_out(vty
, "\n%*s", 34, " ");
7667 json_object_int_add(json
, "peerHost", len
);
7669 vty_out(vty
, "%*s", len
, " ");
7673 bgp_damp_reuse_time_vty(vty
, path
, timebuf
, BGP_UPTIME_LEN
,
7677 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
7678 BGP_UPTIME_LEN
, use_json
,
7681 /* Print attribute */
7687 json_object_string_add(json
, "asPath",
7690 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7695 json_object_string_add(json
, "origin",
7696 bgp_origin_str
[attr
->origin
]);
7698 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7705 static void flap_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7706 struct bgp_path_info
*path
, int display
,
7707 safi_t safi
, bool use_json
, json_object
*json
)
7710 struct bgp_damp_info
*bdi
;
7711 char timebuf
[BGP_UPTIME_LEN
];
7717 bdi
= path
->extra
->damp_info
;
7719 /* short status lead text */
7720 route_vty_short_status_out(vty
, path
, json
);
7722 /* print prefix and mask */
7725 route_vty_out_route(p
, vty
, NULL
);
7727 vty_out(vty
, "%*s", 17, " ");
7730 len
= vty_out(vty
, "%s", path
->peer
->host
);
7734 vty_out(vty
, "\n%*s", 33, " ");
7737 json_object_int_add(json
, "peerHost", len
);
7739 vty_out(vty
, "%*s", len
, " ");
7742 len
= vty_out(vty
, "%d", bdi
->flap
);
7749 json_object_int_add(json
, "bdiFlap", len
);
7751 vty_out(vty
, "%*s", len
, " ");
7755 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
7758 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
7759 BGP_UPTIME_LEN
, 0, NULL
));
7761 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
7762 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
7764 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
7765 BGP_UPTIME_LEN
, use_json
, json
);
7768 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
7773 vty_out(vty
, "%*s ", 8, " ");
7776 /* Print attribute */
7782 json_object_string_add(json
, "asPath",
7785 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7790 json_object_string_add(json
, "origin",
7791 bgp_origin_str
[attr
->origin
]);
7793 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7799 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
7800 int *first
, const char *header
,
7801 json_object
*json_adv_to
)
7803 char buf1
[INET6_ADDRSTRLEN
];
7804 json_object
*json_peer
= NULL
;
7807 /* 'advertised-to' is a dictionary of peers we have advertised
7809 * prefix too. The key is the peer's IP or swpX, the value is
7811 * hostname if we know it and "" if not.
7813 json_peer
= json_object_new_object();
7816 json_object_string_add(json_peer
, "hostname",
7820 json_object_object_add(json_adv_to
, peer
->conf_if
,
7823 json_object_object_add(
7825 sockunion2str(&peer
->su
, buf1
, SU_ADDRSTRLEN
),
7829 vty_out(vty
, "%s", header
);
7834 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
7836 vty_out(vty
, " %s(%s)", peer
->hostname
,
7839 vty_out(vty
, " %s(%s)", peer
->hostname
,
7840 sockunion2str(&peer
->su
, buf1
,
7844 vty_out(vty
, " %s", peer
->conf_if
);
7847 sockunion2str(&peer
->su
, buf1
,
7853 static void route_vty_out_tx_ids(struct vty
*vty
,
7854 struct bgp_addpath_info_data
*d
)
7858 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
7859 vty_out(vty
, "TX-%s %u%s", bgp_addpath_names(i
)->human_name
,
7860 d
->addpath_tx_id
[i
],
7861 i
< BGP_ADDPATH_MAX
- 1 ? " " : "\n");
7865 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
, struct prefix
*p
,
7866 struct bgp_path_info
*path
, afi_t afi
, safi_t safi
,
7867 json_object
*json_paths
)
7869 char buf
[INET6_ADDRSTRLEN
];
7871 char buf2
[EVPN_ROUTE_STRLEN
];
7873 int sockunion_vty_out(struct vty
*, union sockunion
*);
7875 json_object
*json_bestpath
= NULL
;
7876 json_object
*json_cluster_list
= NULL
;
7877 json_object
*json_cluster_list_list
= NULL
;
7878 json_object
*json_ext_community
= NULL
;
7879 json_object
*json_last_update
= NULL
;
7880 json_object
*json_pmsi
= NULL
;
7881 json_object
*json_nexthop_global
= NULL
;
7882 json_object
*json_nexthop_ll
= NULL
;
7883 json_object
*json_nexthops
= NULL
;
7884 json_object
*json_path
= NULL
;
7885 json_object
*json_peer
= NULL
;
7886 json_object
*json_string
= NULL
;
7887 json_object
*json_adv_to
= NULL
;
7889 struct listnode
*node
, *nnode
;
7891 int addpath_capable
;
7893 unsigned int first_as
;
7895 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
7897 char *nexthop_fqdn
= bgp_nexthop_fqdn(path
->peer
);
7900 json_path
= json_object_new_object();
7901 json_peer
= json_object_new_object();
7902 json_nexthop_global
= json_object_new_object();
7905 if (!json_paths
&& safi
== SAFI_EVPN
) {
7908 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf2
, sizeof(buf2
));
7909 vty_out(vty
, " Route %s", buf2
);
7911 if (path
->extra
&& path
->extra
->num_labels
) {
7912 bgp_evpn_label2str(path
->extra
->label
,
7913 path
->extra
->num_labels
, tag_buf
,
7915 vty_out(vty
, " VNI %s", tag_buf
);
7918 if (path
->extra
&& path
->extra
->parent
) {
7919 struct bgp_path_info
*parent_ri
;
7920 struct bgp_node
*rn
, *prn
;
7922 parent_ri
= (struct bgp_path_info
*)path
->extra
->parent
;
7923 rn
= parent_ri
->net
;
7924 if (rn
&& rn
->prn
) {
7926 vty_out(vty
, " Imported from %s:%s\n",
7928 (struct prefix_rd
*)&prn
->p
,
7929 buf1
, sizeof(buf1
)),
7938 /* Line1 display AS-path, Aggregator */
7941 if (!attr
->aspath
->json
)
7942 aspath_str_update(attr
->aspath
, true);
7943 json_object_lock(attr
->aspath
->json
);
7944 json_object_object_add(json_path
, "aspath",
7945 attr
->aspath
->json
);
7947 if (attr
->aspath
->segments
)
7948 aspath_print_vty(vty
, " %s",
7951 vty_out(vty
, " Local");
7955 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
)) {
7957 json_object_boolean_true_add(json_path
,
7960 vty_out(vty
, ", (removed)");
7963 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
7965 json_object_boolean_true_add(json_path
,
7968 vty_out(vty
, ", (stale)");
7971 if (CHECK_FLAG(attr
->flag
,
7972 ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
7974 json_object_int_add(json_path
, "aggregatorAs",
7975 attr
->aggregator_as
);
7976 json_object_string_add(
7977 json_path
, "aggregatorId",
7978 inet_ntoa(attr
->aggregator_addr
));
7980 vty_out(vty
, ", (aggregated by %u %s)",
7981 attr
->aggregator_as
,
7982 inet_ntoa(attr
->aggregator_addr
));
7986 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
7987 PEER_FLAG_REFLECTOR_CLIENT
)) {
7989 json_object_boolean_true_add(
7990 json_path
, "rxedFromRrClient");
7992 vty_out(vty
, ", (Received from a RR-client)");
7995 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
7996 PEER_FLAG_RSERVER_CLIENT
)) {
7998 json_object_boolean_true_add(
7999 json_path
, "rxedFromRsClient");
8001 vty_out(vty
, ", (Received from a RS-client)");
8004 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
8006 json_object_boolean_true_add(
8007 json_path
, "dampeningHistoryEntry");
8009 vty_out(vty
, ", (history entry)");
8010 } else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)) {
8012 json_object_boolean_true_add(
8013 json_path
, "dampeningSuppressed");
8015 vty_out(vty
, ", (suppressed due to dampening)");
8021 /* Line2 display Next-hop, Neighbor, Router-id */
8022 /* Display the nexthop */
8023 if ((p
->family
== AF_INET
|| p
->family
== AF_ETHERNET
8024 || p
->family
== AF_EVPN
)
8025 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
8026 || safi
== SAFI_EVPN
8027 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
8028 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
8029 || safi
== SAFI_EVPN
) {
8031 json_object_string_add(
8032 json_nexthop_global
,
8033 nexthop_fqdn
? "fqdn" : "ip",
8037 attr
->mp_nexthop_global_in
));
8043 attr
->mp_nexthop_global_in
));
8046 json_object_string_add(
8047 json_nexthop_global
,
8048 nexthop_fqdn
? "fqdn" : "ip",
8062 json_object_string_add(json_nexthop_global
,
8066 json_object_string_add(
8067 json_nexthop_global
,
8068 nexthop_fqdn
? "fqdn" : "ip",
8073 &attr
->mp_nexthop_global
,
8076 json_object_string_add(json_nexthop_global
,
8078 json_object_string_add(json_nexthop_global
,
8086 &attr
->mp_nexthop_global
,
8092 /* Display the IGP cost or 'inaccessible' */
8093 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
8095 json_object_boolean_false_add(
8096 json_nexthop_global
, "accessible");
8098 vty_out(vty
, " (inaccessible)");
8100 if (path
->extra
&& path
->extra
->igpmetric
) {
8102 json_object_int_add(
8103 json_nexthop_global
, "metric",
8104 path
->extra
->igpmetric
);
8106 vty_out(vty
, " (metric %u)",
8107 path
->extra
->igpmetric
);
8110 /* IGP cost is 0, display this only for json */
8113 json_object_int_add(json_nexthop_global
,
8118 json_object_boolean_true_add(
8119 json_nexthop_global
, "accessible");
8122 /* Display peer "from" output */
8123 /* This path was originated locally */
8124 if (path
->peer
== bgp
->peer_self
) {
8126 if (safi
== SAFI_EVPN
8127 || (p
->family
== AF_INET
8128 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
8130 json_object_string_add(
8131 json_peer
, "peerId", "0.0.0.0");
8133 vty_out(vty
, " from 0.0.0.0 ");
8136 json_object_string_add(json_peer
,
8139 vty_out(vty
, " from :: ");
8143 json_object_string_add(
8144 json_peer
, "routerId",
8145 inet_ntoa(bgp
->router_id
));
8147 vty_out(vty
, "(%s)", inet_ntoa(bgp
->router_id
));
8150 /* We RXed this path from one of our peers */
8154 json_object_string_add(
8155 json_peer
, "peerId",
8156 sockunion2str(&path
->peer
->su
, buf
,
8158 json_object_string_add(
8159 json_peer
, "routerId",
8161 &path
->peer
->remote_id
, buf1
,
8164 if (path
->peer
->hostname
)
8165 json_object_string_add(
8166 json_peer
, "hostname",
8167 path
->peer
->hostname
);
8169 if (path
->peer
->domainname
)
8170 json_object_string_add(
8171 json_peer
, "domainname",
8172 path
->peer
->domainname
);
8174 if (path
->peer
->conf_if
)
8175 json_object_string_add(
8176 json_peer
, "interface",
8177 path
->peer
->conf_if
);
8179 if (path
->peer
->conf_if
) {
8180 if (path
->peer
->hostname
8183 BGP_FLAG_SHOW_HOSTNAME
))
8184 vty_out(vty
, " from %s(%s)",
8185 path
->peer
->hostname
,
8186 path
->peer
->conf_if
);
8188 vty_out(vty
, " from %s",
8189 path
->peer
->conf_if
);
8191 if (path
->peer
->hostname
8194 BGP_FLAG_SHOW_HOSTNAME
))
8195 vty_out(vty
, " from %s(%s)",
8196 path
->peer
->hostname
,
8199 vty_out(vty
, " from %s",
8207 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
8208 vty_out(vty
, " (%s)",
8209 inet_ntoa(attr
->originator_id
));
8211 vty_out(vty
, " (%s)",
8214 &path
->peer
->remote_id
,
8215 buf1
, sizeof(buf1
)));
8220 * Note when vrfid of nexthop is different from that of prefix
8222 if (path
->extra
&& path
->extra
->bgp_orig
) {
8223 vrf_id_t nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
8228 if (path
->extra
->bgp_orig
->inst_type
8229 == BGP_INSTANCE_TYPE_DEFAULT
)
8231 vn
= VRF_DEFAULT_NAME
;
8233 vn
= path
->extra
->bgp_orig
->name
;
8235 json_object_string_add(json_path
, "nhVrfName",
8238 if (nexthop_vrfid
== VRF_UNKNOWN
) {
8239 json_object_int_add(json_path
,
8242 json_object_int_add(json_path
,
8243 "nhVrfId", (int)nexthop_vrfid
);
8246 if (nexthop_vrfid
== VRF_UNKNOWN
)
8247 vty_out(vty
, " vrf ?");
8249 vty_out(vty
, " vrf %u", nexthop_vrfid
);
8255 json_object_boolean_true_add(json_path
,
8256 "announceNexthopSelf");
8258 vty_out(vty
, " announce-nh-self");
8265 /* display the link-local nexthop */
8266 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
8268 json_nexthop_ll
= json_object_new_object();
8269 json_object_string_add(
8271 nexthop_fqdn
? "fqdn" : "ip",
8276 &attr
->mp_nexthop_local
,
8279 json_object_string_add(json_nexthop_ll
, "afi",
8281 json_object_string_add(json_nexthop_ll
, "scope",
8284 json_object_boolean_true_add(json_nexthop_ll
,
8287 if (!attr
->mp_nexthop_prefer_global
)
8288 json_object_boolean_true_add(
8289 json_nexthop_ll
, "used");
8291 json_object_boolean_true_add(
8292 json_nexthop_global
, "used");
8294 vty_out(vty
, " (%s) %s\n",
8296 &attr
->mp_nexthop_local
, buf
,
8298 attr
->mp_nexthop_prefer_global
8303 /* If we do not have a link-local nexthop then we must flag the
8307 json_object_boolean_true_add(
8308 json_nexthop_global
, "used");
8311 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
8312 * Int/Ext/Local, Atomic, best */
8314 json_object_string_add(
8315 json_path
, "origin",
8316 bgp_origin_long_str
[attr
->origin
]);
8318 vty_out(vty
, " Origin %s",
8319 bgp_origin_long_str
[attr
->origin
]);
8321 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
8325 * Adding "metric" field to match with
8326 * corresponding CLI. "med" will be
8327 * deprecated in future.
8329 json_object_int_add(json_path
, "med",
8331 json_object_int_add(json_path
, "metric",
8334 vty_out(vty
, ", metric %u", attr
->med
);
8337 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
8339 json_object_int_add(json_path
, "localpref",
8342 vty_out(vty
, ", localpref %u",
8346 if (attr
->weight
!= 0) {
8348 json_object_int_add(json_path
, "weight",
8351 vty_out(vty
, ", weight %u", attr
->weight
);
8354 if (attr
->tag
!= 0) {
8356 json_object_int_add(json_path
, "tag",
8359 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
,
8363 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
8365 json_object_boolean_false_add(json_path
,
8368 vty_out(vty
, ", invalid");
8369 } else if (!CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
8371 json_object_boolean_true_add(json_path
,
8374 vty_out(vty
, ", valid");
8377 if (path
->peer
!= bgp
->peer_self
) {
8378 if (path
->peer
->as
== path
->peer
->local_as
) {
8379 if (CHECK_FLAG(bgp
->config
,
8380 BGP_CONFIG_CONFEDERATION
)) {
8382 json_object_string_add(
8387 ", confed-internal");
8390 json_object_string_add(
8394 vty_out(vty
, ", internal");
8397 if (bgp_confederation_peers_check(
8398 bgp
, path
->peer
->as
)) {
8400 json_object_string_add(
8405 ", confed-external");
8408 json_object_string_add(
8412 vty_out(vty
, ", external");
8415 } else if (path
->sub_type
== BGP_ROUTE_AGGREGATE
) {
8417 json_object_boolean_true_add(json_path
,
8419 json_object_boolean_true_add(json_path
,
8422 vty_out(vty
, ", aggregated, local");
8424 } else if (path
->type
!= ZEBRA_ROUTE_BGP
) {
8426 json_object_boolean_true_add(json_path
,
8429 vty_out(vty
, ", sourced");
8432 json_object_boolean_true_add(json_path
,
8434 json_object_boolean_true_add(json_path
,
8437 vty_out(vty
, ", sourced, local");
8441 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
8443 json_object_boolean_true_add(json_path
,
8446 vty_out(vty
, ", atomic-aggregate");
8449 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
)
8450 || (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)
8451 && bgp_path_info_mpath_count(path
))) {
8453 json_object_boolean_true_add(json_path
,
8456 vty_out(vty
, ", multipath");
8459 // Mark the bestpath(s)
8460 if (CHECK_FLAG(path
->flags
, BGP_PATH_DMED_SELECTED
)) {
8461 first_as
= aspath_get_first_as(attr
->aspath
);
8466 json_object_new_object();
8467 json_object_int_add(json_bestpath
,
8468 "bestpathFromAs", first_as
);
8471 vty_out(vty
, ", bestpath-from-AS %u",
8475 ", bestpath-from-AS Local");
8479 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
8483 json_object_new_object();
8484 json_object_boolean_true_add(json_bestpath
,
8487 vty_out(vty
, ", best");
8491 json_object_object_add(json_path
, "bestpath",
8497 /* Line 4 display Community */
8498 if (attr
->community
) {
8500 if (!attr
->community
->json
)
8501 community_str(attr
->community
, true);
8502 json_object_lock(attr
->community
->json
);
8503 json_object_object_add(json_path
, "community",
8504 attr
->community
->json
);
8506 vty_out(vty
, " Community: %s\n",
8507 attr
->community
->str
);
8511 /* Line 5 display Extended-community */
8512 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
8514 json_ext_community
= json_object_new_object();
8515 json_object_string_add(json_ext_community
,
8517 attr
->ecommunity
->str
);
8518 json_object_object_add(json_path
,
8519 "extendedCommunity",
8520 json_ext_community
);
8522 vty_out(vty
, " Extended Community: %s\n",
8523 attr
->ecommunity
->str
);
8527 /* Line 6 display Large community */
8528 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
8530 if (!attr
->lcommunity
->json
)
8531 lcommunity_str(attr
->lcommunity
, true);
8532 json_object_lock(attr
->lcommunity
->json
);
8533 json_object_object_add(json_path
,
8535 attr
->lcommunity
->json
);
8537 vty_out(vty
, " Large Community: %s\n",
8538 attr
->lcommunity
->str
);
8542 /* Line 7 display Originator, Cluster-id */
8543 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
8544 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
8546 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
8548 json_object_string_add(
8549 json_path
, "originatorId",
8550 inet_ntoa(attr
->originator_id
));
8552 vty_out(vty
, " Originator: %s",
8553 inet_ntoa(attr
->originator_id
));
8556 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
8561 json_object_new_object();
8562 json_cluster_list_list
=
8563 json_object_new_array();
8566 i
< attr
->cluster
->length
/ 4;
8568 json_string
= json_object_new_string(
8572 json_object_array_add(
8573 json_cluster_list_list
,
8577 /* struct cluster_list does not have
8579 * aspath and community do. Add this
8582 json_object_string_add(json_cluster_list,
8583 "string", attr->cluster->str);
8585 json_object_object_add(
8586 json_cluster_list
, "list",
8587 json_cluster_list_list
);
8588 json_object_object_add(
8589 json_path
, "clusterList",
8592 vty_out(vty
, ", Cluster list: ");
8595 i
< attr
->cluster
->length
/ 4;
8609 if (path
->extra
&& path
->extra
->damp_info
)
8610 bgp_damp_info_vty(vty
, path
, json_path
);
8613 if (path
->extra
&& bgp_is_valid_label(&path
->extra
->label
[0])
8614 && safi
!= SAFI_EVPN
) {
8615 mpls_label_t label
= label_pton(&path
->extra
->label
[0]);
8618 json_object_int_add(json_path
, "remoteLabel",
8621 vty_out(vty
, " Remote label: %d\n", label
);
8625 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
8627 json_object_int_add(json_path
, "labelIndex",
8630 vty_out(vty
, " Label Index: %d\n",
8634 /* Line 8 display Addpath IDs */
8635 if (path
->addpath_rx_id
8636 || bgp_addpath_info_has_ids(&path
->tx_addpath
)) {
8638 json_object_int_add(json_path
, "addpathRxId",
8639 path
->addpath_rx_id
);
8641 /* Keep backwards compatibility with the old API
8642 * by putting TX All's ID in the old field
8644 json_object_int_add(
8645 json_path
, "addpathTxId",
8646 path
->tx_addpath
.addpath_tx_id
8649 /* ... but create a specific field for each
8652 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
8653 json_object_int_add(
8655 bgp_addpath_names(i
)
8661 vty_out(vty
, " AddPath ID: RX %u, ",
8662 path
->addpath_rx_id
);
8664 route_vty_out_tx_ids(vty
, &path
->tx_addpath
);
8668 /* If we used addpath to TX a non-bestpath we need to display
8669 * "Advertised to" on a path-by-path basis
8671 if (bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
8674 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
8676 bgp_addpath_encode_tx(peer
, afi
, safi
);
8677 has_adj
= bgp_adj_out_lookup(
8679 bgp_addpath_id_for_peer(
8681 &path
->tx_addpath
));
8683 if ((addpath_capable
&& has_adj
)
8684 || (!addpath_capable
&& has_adj
8685 && CHECK_FLAG(path
->flags
,
8686 BGP_PATH_SELECTED
))) {
8687 if (json_path
&& !json_adv_to
)
8689 json_object_new_object();
8691 route_vty_out_advertised_to(
8700 json_object_object_add(json_path
,
8711 /* Line 9 display Uptime */
8712 tbuf
= time(NULL
) - (bgp_clock() - path
->uptime
);
8714 json_last_update
= json_object_new_object();
8715 json_object_int_add(json_last_update
, "epoch", tbuf
);
8716 json_object_string_add(json_last_update
, "string",
8718 json_object_object_add(json_path
, "lastUpdate",
8721 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
8723 /* Line 10 display PMSI tunnel attribute, if present */
8724 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
8725 const char *str
= lookup_msg(bgp_pmsi_tnltype_str
,
8726 attr
->pmsi_tnl_type
,
8727 PMSI_TNLTYPE_STR_DEFAULT
);
8730 json_pmsi
= json_object_new_object();
8731 json_object_string_add(json_pmsi
,
8733 json_object_int_add(json_pmsi
,
8735 label2vni(&attr
->label
));
8736 json_object_object_add(json_path
, "pmsi",
8740 " PMSI Tunnel Type: %s, label: %d\n",
8741 str
, label2vni(&attr
->label
));
8746 /* We've constructed the json object for this path, add it to the json
8750 if (json_nexthop_global
|| json_nexthop_ll
) {
8751 json_nexthops
= json_object_new_array();
8753 if (json_nexthop_global
)
8754 json_object_array_add(json_nexthops
,
8755 json_nexthop_global
);
8757 if (json_nexthop_ll
)
8758 json_object_array_add(json_nexthops
,
8761 json_object_object_add(json_path
, "nexthops",
8765 json_object_object_add(json_path
, "peer", json_peer
);
8766 json_object_array_add(json_paths
, json_path
);
8771 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
8772 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
8773 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
8775 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
8776 const char *prefix_list_str
, afi_t afi
,
8777 safi_t safi
, enum bgp_show_type type
);
8778 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
8779 const char *filter
, afi_t afi
, safi_t safi
,
8780 enum bgp_show_type type
);
8781 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
8782 const char *rmap_str
, afi_t afi
, safi_t safi
,
8783 enum bgp_show_type type
);
8784 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
8785 const char *com
, int exact
, afi_t afi
,
8787 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
8788 const char *prefix
, afi_t afi
, safi_t safi
,
8789 enum bgp_show_type type
);
8790 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
8791 afi_t afi
, safi_t safi
, enum bgp_show_type type
);
8792 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
8793 const char *comstr
, int exact
, afi_t afi
,
8794 safi_t safi
, bool use_json
);
8797 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
8798 struct bgp_table
*table
, enum bgp_show_type type
,
8799 void *output_arg
, bool use_json
, char *rd
,
8800 int is_last
, unsigned long *output_cum
,
8801 unsigned long *total_cum
,
8802 unsigned long *json_header_depth
)
8804 struct bgp_path_info
*pi
;
8805 struct bgp_node
*rn
;
8808 unsigned long output_count
= 0;
8809 unsigned long total_count
= 0;
8812 json_object
*json_paths
= NULL
;
8815 if (output_cum
&& *output_cum
!= 0)
8818 if (use_json
&& !*json_header_depth
) {
8820 "{\n \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
8821 ",\n \"routerId\": \"%s\",\n \"defaultLocPrf\": %u,\n"
8822 " \"localAS\": %u,\n \"routes\": { ",
8823 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
8824 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
8827 table
->version
, inet_ntoa(bgp
->router_id
),
8828 bgp
->default_local_pref
, bgp
->as
);
8829 *json_header_depth
= 2;
8831 vty_out(vty
, " \"routeDistinguishers\" : {");
8832 ++*json_header_depth
;
8836 if (use_json
&& rd
) {
8837 vty_out(vty
, " \"%s\" : { ", rd
);
8840 /* Start processing of routes. */
8841 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
8842 pi
= bgp_node_get_bgp_path_info(rn
);
8848 json_paths
= json_object_new_array();
8852 for (; pi
; pi
= pi
->next
) {
8854 if (type
== bgp_show_type_flap_statistics
8855 || type
== bgp_show_type_flap_neighbor
8856 || type
== bgp_show_type_dampend_paths
8857 || type
== bgp_show_type_damp_neighbor
) {
8858 if (!(pi
->extra
&& pi
->extra
->damp_info
))
8861 if (type
== bgp_show_type_regexp
) {
8862 regex_t
*regex
= output_arg
;
8864 if (bgp_regexec(regex
, pi
->attr
->aspath
)
8868 if (type
== bgp_show_type_prefix_list
) {
8869 struct prefix_list
*plist
= output_arg
;
8871 if (prefix_list_apply(plist
, &rn
->p
)
8875 if (type
== bgp_show_type_filter_list
) {
8876 struct as_list
*as_list
= output_arg
;
8878 if (as_list_apply(as_list
, pi
->attr
->aspath
)
8879 != AS_FILTER_PERMIT
)
8882 if (type
== bgp_show_type_route_map
) {
8883 struct route_map
*rmap
= output_arg
;
8884 struct bgp_path_info path
;
8885 struct attr dummy_attr
;
8888 bgp_attr_dup(&dummy_attr
, pi
->attr
);
8890 path
.peer
= pi
->peer
;
8891 path
.attr
= &dummy_attr
;
8893 ret
= route_map_apply(rmap
, &rn
->p
, RMAP_BGP
,
8895 if (ret
== RMAP_DENYMATCH
)
8898 if (type
== bgp_show_type_neighbor
8899 || type
== bgp_show_type_flap_neighbor
8900 || type
== bgp_show_type_damp_neighbor
) {
8901 union sockunion
*su
= output_arg
;
8903 if (pi
->peer
== NULL
8904 || pi
->peer
->su_remote
== NULL
8905 || !sockunion_same(pi
->peer
->su_remote
, su
))
8908 if (type
== bgp_show_type_cidr_only
) {
8909 uint32_t destination
;
8911 destination
= ntohl(rn
->p
.u
.prefix4
.s_addr
);
8912 if (IN_CLASSC(destination
)
8913 && rn
->p
.prefixlen
== 24)
8915 if (IN_CLASSB(destination
)
8916 && rn
->p
.prefixlen
== 16)
8918 if (IN_CLASSA(destination
)
8919 && rn
->p
.prefixlen
== 8)
8922 if (type
== bgp_show_type_prefix_longer
) {
8924 if (!prefix_match(p
, &rn
->p
))
8927 if (type
== bgp_show_type_community_all
) {
8928 if (!pi
->attr
->community
)
8931 if (type
== bgp_show_type_community
) {
8932 struct community
*com
= output_arg
;
8934 if (!pi
->attr
->community
8935 || !community_match(pi
->attr
->community
,
8939 if (type
== bgp_show_type_community_exact
) {
8940 struct community
*com
= output_arg
;
8942 if (!pi
->attr
->community
8943 || !community_cmp(pi
->attr
->community
, com
))
8946 if (type
== bgp_show_type_community_list
) {
8947 struct community_list
*list
= output_arg
;
8949 if (!community_list_match(pi
->attr
->community
,
8953 if (type
== bgp_show_type_community_list_exact
) {
8954 struct community_list
*list
= output_arg
;
8956 if (!community_list_exact_match(
8957 pi
->attr
->community
, list
))
8960 if (type
== bgp_show_type_lcommunity
) {
8961 struct lcommunity
*lcom
= output_arg
;
8963 if (!pi
->attr
->lcommunity
8964 || !lcommunity_match(pi
->attr
->lcommunity
,
8968 if (type
== bgp_show_type_lcommunity_list
) {
8969 struct community_list
*list
= output_arg
;
8971 if (!lcommunity_list_match(pi
->attr
->lcommunity
,
8975 if (type
== bgp_show_type_lcommunity_all
) {
8976 if (!pi
->attr
->lcommunity
)
8979 if (type
== bgp_show_type_dampend_paths
8980 || type
== bgp_show_type_damp_neighbor
) {
8981 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
)
8982 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
8986 if (!use_json
&& header
) {
8987 vty_out(vty
, "BGP table version is %" PRIu64
8988 ", local router ID is %s, vrf id ",
8990 inet_ntoa(bgp
->router_id
));
8991 if (bgp
->vrf_id
== VRF_UNKNOWN
)
8992 vty_out(vty
, "%s", VRFID_NONE_STR
);
8994 vty_out(vty
, "%u", bgp
->vrf_id
);
8996 vty_out(vty
, "Default local pref %u, ",
8997 bgp
->default_local_pref
);
8998 vty_out(vty
, "local AS %u\n", bgp
->as
);
8999 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
9000 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
9001 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
9002 if (type
== bgp_show_type_dampend_paths
9003 || type
== bgp_show_type_damp_neighbor
)
9004 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
9005 else if (type
== bgp_show_type_flap_statistics
9006 || type
== bgp_show_type_flap_neighbor
)
9007 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
9009 vty_out(vty
, BGP_SHOW_HEADER
);
9012 if (rd
!= NULL
&& !display
&& !output_count
) {
9015 "Route Distinguisher: %s\n",
9018 if (type
== bgp_show_type_dampend_paths
9019 || type
== bgp_show_type_damp_neighbor
)
9020 damp_route_vty_out(vty
, &rn
->p
, pi
, display
,
9021 safi
, use_json
, json_paths
);
9022 else if (type
== bgp_show_type_flap_statistics
9023 || type
== bgp_show_type_flap_neighbor
)
9024 flap_route_vty_out(vty
, &rn
->p
, pi
, display
,
9025 safi
, use_json
, json_paths
);
9027 route_vty_out(vty
, &rn
->p
, pi
, display
, safi
,
9039 if (p
->family
== AF_FLOWSPEC
) {
9040 char retstr
[BGP_FLOWSPEC_STRING_DISPLAY_MAX
];
9042 bgp_fs_nlri_get_string((unsigned char *)
9043 p
->u
.prefix_flowspec
.ptr
,
9044 p
->u
.prefix_flowspec
9047 NLRI_STRING_FORMAT_MIN
,
9050 vty_out(vty
, "\"%s/%d\": ",
9052 p
->u
.prefix_flowspec
.prefixlen
);
9054 vty_out(vty
, ",\"%s/%d\": ",
9056 p
->u
.prefix_flowspec
.prefixlen
);
9058 prefix2str(p
, buf2
, sizeof(buf2
));
9060 vty_out(vty
, "\"%s\": ", buf2
);
9062 vty_out(vty
, ",\"%s\": ", buf2
);
9065 json_object_to_json_string(json_paths
));
9066 json_object_free(json_paths
);
9073 output_count
+= *output_cum
;
9074 *output_cum
= output_count
;
9077 total_count
+= *total_cum
;
9078 *total_cum
= total_count
;
9082 vty_out(vty
, " }%s ", (is_last
? "" : ","));
9086 for (i
= 0; i
< *json_header_depth
; ++i
)
9087 vty_out(vty
, " } ");
9092 /* No route is displayed */
9093 if (output_count
== 0) {
9094 if (type
== bgp_show_type_normal
)
9096 "No BGP prefixes displayed, %ld exist\n",
9100 "\nDisplayed %ld routes and %ld total paths\n",
9101 output_count
, total_count
);
9108 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
9109 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
9110 enum bgp_show_type type
, void *output_arg
, bool use_json
)
9112 struct bgp_node
*rn
, *next
;
9113 unsigned long output_cum
= 0;
9114 unsigned long total_cum
= 0;
9115 unsigned long json_header_depth
= 0;
9116 struct bgp_table
*itable
;
9119 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
9121 for (rn
= bgp_table_top(table
); rn
; rn
= next
) {
9122 next
= bgp_route_next(rn
);
9123 if (prd_match
&& memcmp(rn
->p
.u
.val
, prd_match
->val
, 8) != 0)
9126 itable
= bgp_node_get_bgp_table_info(rn
);
9127 if (itable
!= NULL
) {
9128 struct prefix_rd prd
;
9129 char rd
[RD_ADDRSTRLEN
];
9131 memcpy(&prd
, &(rn
->p
), sizeof(struct prefix_rd
));
9132 prefix_rd2str(&prd
, rd
, sizeof(rd
));
9133 bgp_show_table(vty
, bgp
, safi
, itable
, type
, output_arg
,
9134 use_json
, rd
, next
== NULL
, &output_cum
,
9135 &total_cum
, &json_header_depth
);
9141 if (output_cum
== 0)
9142 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
9146 "\nDisplayed %ld routes and %ld total paths\n",
9147 output_cum
, total_cum
);
9151 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
9152 enum bgp_show_type type
, void *output_arg
, bool use_json
)
9154 struct bgp_table
*table
;
9155 unsigned long json_header_depth
= 0;
9158 bgp
= bgp_get_default();
9163 vty_out(vty
, "No BGP process is configured\n");
9165 vty_out(vty
, "{}\n");
9169 table
= bgp
->rib
[afi
][safi
];
9170 /* use MPLS and ENCAP specific shows until they are merged */
9171 if (safi
== SAFI_MPLS_VPN
) {
9172 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
9173 output_arg
, use_json
);
9176 if (safi
== SAFI_FLOWSPEC
&& type
== bgp_show_type_detail
) {
9177 return bgp_show_table_flowspec(vty
, bgp
, afi
, table
, type
,
9178 output_arg
, use_json
,
9181 /* labeled-unicast routes live in the unicast table */
9182 else if (safi
== SAFI_LABELED_UNICAST
)
9183 safi
= SAFI_UNICAST
;
9185 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, use_json
,
9186 NULL
, 1, NULL
, NULL
, &json_header_depth
);
9189 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
9190 safi_t safi
, bool use_json
)
9192 struct listnode
*node
, *nnode
;
9195 bool route_output
= false;
9198 vty_out(vty
, "{\n");
9200 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
9201 route_output
= true;
9204 vty_out(vty
, ",\n");
9208 vty_out(vty
, "\"%s\":",
9209 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
9213 vty_out(vty
, "\nInstance %s:\n",
9214 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
9218 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
9223 vty_out(vty
, "}\n");
9224 else if (!route_output
)
9225 vty_out(vty
, "%% BGP instance not found\n");
9228 /* Header of detailed BGP route information */
9229 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
9230 struct bgp_node
*rn
, struct prefix_rd
*prd
,
9231 afi_t afi
, safi_t safi
, json_object
*json
)
9233 struct bgp_path_info
*pi
;
9236 struct listnode
*node
, *nnode
;
9237 char buf1
[RD_ADDRSTRLEN
];
9238 char buf2
[INET6_ADDRSTRLEN
];
9239 char buf3
[EVPN_ROUTE_STRLEN
];
9240 char prefix_str
[BUFSIZ
];
9245 int route_filter_translated_v4
= 0;
9246 int route_filter_v4
= 0;
9247 int route_filter_translated_v6
= 0;
9248 int route_filter_v6
= 0;
9251 int accept_own_nexthop
= 0;
9254 int no_advertise
= 0;
9258 int has_valid_label
= 0;
9259 mpls_label_t label
= 0;
9260 json_object
*json_adv_to
= NULL
;
9263 has_valid_label
= bgp_is_valid_label(&rn
->local_label
);
9265 if (has_valid_label
)
9266 label
= label_pton(&rn
->local_label
);
9269 if (has_valid_label
)
9270 json_object_int_add(json
, "localLabel", label
);
9272 json_object_string_add(
9274 prefix2str(p
, prefix_str
, sizeof(prefix_str
)));
9276 if (safi
== SAFI_EVPN
)
9277 vty_out(vty
, "BGP routing table entry for %s%s%s\n",
9278 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
))
9281 bgp_evpn_route2str((struct prefix_evpn
*)p
,
9282 buf3
, sizeof(buf3
)));
9284 vty_out(vty
, "BGP routing table entry for %s%s%s/%d\n",
9285 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
9286 ? prefix_rd2str(prd
, buf1
,
9289 safi
== SAFI_MPLS_VPN
? ":" : "",
9290 inet_ntop(p
->family
, &p
->u
.prefix
, buf2
,
9294 if (has_valid_label
)
9295 vty_out(vty
, "Local label: %d\n", label
);
9296 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
9297 vty_out(vty
, "not allocated\n");
9300 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
9302 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
9304 if (pi
->extra
&& pi
->extra
->suppress
)
9307 if (pi
->attr
->community
== NULL
)
9310 no_advertise
+= community_include(
9311 pi
->attr
->community
, COMMUNITY_NO_ADVERTISE
);
9312 no_export
+= community_include(pi
->attr
->community
,
9313 COMMUNITY_NO_EXPORT
);
9314 local_as
+= community_include(pi
->attr
->community
,
9315 COMMUNITY_LOCAL_AS
);
9316 accept_own
+= community_include(pi
->attr
->community
,
9317 COMMUNITY_ACCEPT_OWN
);
9318 route_filter_translated_v4
+= community_include(
9319 pi
->attr
->community
,
9320 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4
);
9321 route_filter_translated_v6
+= community_include(
9322 pi
->attr
->community
,
9323 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6
);
9324 route_filter_v4
+= community_include(
9325 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v4
);
9326 route_filter_v6
+= community_include(
9327 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v6
);
9328 llgr_stale
+= community_include(pi
->attr
->community
,
9329 COMMUNITY_LLGR_STALE
);
9330 no_llgr
+= community_include(pi
->attr
->community
,
9332 accept_own_nexthop
+=
9333 community_include(pi
->attr
->community
,
9334 COMMUNITY_ACCEPT_OWN_NEXTHOP
);
9335 blackhole
+= community_include(pi
->attr
->community
,
9336 COMMUNITY_BLACKHOLE
);
9337 no_peer
+= community_include(pi
->attr
->community
,
9343 vty_out(vty
, "Paths: (%d available", count
);
9345 vty_out(vty
, ", best #%d", best
);
9346 if (safi
== SAFI_UNICAST
)
9347 vty_out(vty
, ", table %s",
9349 == BGP_INSTANCE_TYPE_DEFAULT
)
9353 vty_out(vty
, ", no best path");
9357 ", accept own local route exported and imported in different VRF");
9358 else if (route_filter_translated_v4
)
9360 ", mark translated RTs for VPNv4 route filtering");
9361 else if (route_filter_v4
)
9363 ", attach RT as-is for VPNv4 route filtering");
9364 else if (route_filter_translated_v6
)
9366 ", mark translated RTs for VPNv6 route filtering");
9367 else if (route_filter_v6
)
9369 ", attach RT as-is for VPNv6 route filtering");
9370 else if (llgr_stale
)
9372 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
9375 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
9376 else if (accept_own_nexthop
)
9378 ", accept local nexthop");
9380 vty_out(vty
, ", inform peer to blackhole prefix");
9382 vty_out(vty
, ", not advertised to EBGP peer");
9383 else if (no_advertise
)
9384 vty_out(vty
, ", not advertised to any peer");
9386 vty_out(vty
, ", not advertised outside local AS");
9389 ", inform EBGP peer not to advertise to their EBGP peers");
9393 ", Advertisements suppressed by an aggregate.");
9394 vty_out(vty
, ")\n");
9397 /* If we are not using addpath then we can display Advertised to and
9399 * show what peers we advertised the bestpath to. If we are using
9401 * though then we must display Advertised to on a path-by-path basis. */
9402 if (!bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
9403 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
9404 if (bgp_adj_out_lookup(peer
, rn
, 0)) {
9405 if (json
&& !json_adv_to
)
9406 json_adv_to
= json_object_new_object();
9408 route_vty_out_advertised_to(
9410 " Advertised to non peer-group peers:\n ",
9417 json_object_object_add(json
, "advertisedTo",
9422 vty_out(vty
, " Not advertised to any peer");
9428 /* Display specified route of BGP table. */
9429 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
9430 struct bgp_table
*rib
, const char *ip_str
,
9431 afi_t afi
, safi_t safi
,
9432 struct prefix_rd
*prd
, int prefix_check
,
9433 enum bgp_path_type pathtype
, bool use_json
)
9438 struct prefix match
;
9439 struct bgp_node
*rn
;
9440 struct bgp_node
*rm
;
9441 struct bgp_path_info
*pi
;
9442 struct bgp_table
*table
;
9443 json_object
*json
= NULL
;
9444 json_object
*json_paths
= NULL
;
9446 /* Check IP address argument. */
9447 ret
= str2prefix(ip_str
, &match
);
9449 vty_out(vty
, "address is malformed\n");
9453 match
.family
= afi2family(afi
);
9456 json
= json_object_new_object();
9457 json_paths
= json_object_new_array();
9460 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
9461 for (rn
= bgp_table_top(rib
); rn
; rn
= bgp_route_next(rn
)) {
9462 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
9464 table
= bgp_node_get_bgp_table_info(rn
);
9470 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
9474 && rm
->p
.prefixlen
!= match
.prefixlen
) {
9475 bgp_unlock_node(rm
);
9479 for (pi
= bgp_node_get_bgp_path_info(rm
); pi
;
9482 route_vty_out_detail_header(
9484 (struct prefix_rd
*)&rn
->p
,
9485 AFI_IP
, safi
, json
);
9490 if (pathtype
== BGP_PATH_SHOW_ALL
9491 || (pathtype
== BGP_PATH_SHOW_BESTPATH
9492 && CHECK_FLAG(pi
->flags
,
9494 || (pathtype
== BGP_PATH_SHOW_MULTIPATH
9495 && (CHECK_FLAG(pi
->flags
,
9497 || CHECK_FLAG(pi
->flags
,
9498 BGP_PATH_SELECTED
))))
9499 route_vty_out_detail(vty
, bgp
, &rm
->p
,
9504 bgp_unlock_node(rm
);
9506 } else if (safi
== SAFI_FLOWSPEC
) {
9507 display
= bgp_flowspec_display_match_per_ip(afi
, rib
,
9508 &match
, prefix_check
,
9515 if ((rn
= bgp_node_match(rib
, &match
)) != NULL
) {
9517 || rn
->p
.prefixlen
== match
.prefixlen
) {
9518 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
;
9521 route_vty_out_detail_header(
9522 vty
, bgp
, rn
, NULL
, afi
,
9528 if (pathtype
== BGP_PATH_SHOW_ALL
9530 == BGP_PATH_SHOW_BESTPATH
9535 == BGP_PATH_SHOW_MULTIPATH
9541 BGP_PATH_SELECTED
))))
9542 route_vty_out_detail(
9543 vty
, bgp
, &rn
->p
, pi
,
9544 afi
, safi
, json_paths
);
9548 bgp_unlock_node(rn
);
9554 json_object_object_add(json
, "paths", json_paths
);
9556 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
9557 json
, JSON_C_TO_STRING_PRETTY
));
9558 json_object_free(json
);
9561 vty_out(vty
, "%% Network not in table\n");
9569 /* Display specified route of Main RIB */
9570 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
9571 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
9572 int prefix_check
, enum bgp_path_type pathtype
,
9576 bgp
= bgp_get_default();
9579 vty_out(vty
, "No BGP process is configured\n");
9581 vty_out(vty
, "{}\n");
9586 /* labeled-unicast routes live in the unicast table */
9587 if (safi
== SAFI_LABELED_UNICAST
)
9588 safi
= SAFI_UNICAST
;
9590 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
9591 afi
, safi
, prd
, prefix_check
, pathtype
,
9595 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
9596 struct cmd_token
**argv
, afi_t afi
, safi_t safi
,
9599 struct lcommunity
*lcom
;
9605 b
= buffer_new(1024);
9606 for (i
= 0; i
< argc
; i
++) {
9608 buffer_putc(b
, ' ');
9610 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
9612 buffer_putstr(b
, argv
[i
]->arg
);
9616 buffer_putc(b
, '\0');
9618 str
= buffer_getstr(b
);
9621 lcom
= lcommunity_str2com(str
);
9622 XFREE(MTYPE_TMP
, str
);
9624 vty_out(vty
, "%% Large-community malformed\n");
9628 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_lcommunity
, lcom
,
9632 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
9633 const char *lcom
, afi_t afi
, safi_t safi
,
9636 struct community_list
*list
;
9638 list
= community_list_lookup(bgp_clist
, lcom
, 0,
9639 LARGE_COMMUNITY_LIST_MASTER
);
9641 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
9646 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_lcommunity_list
,
9650 DEFUN (show_ip_bgp_large_community_list
,
9651 show_ip_bgp_large_community_list_cmd
,
9652 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community-list <(1-500)|WORD> [json]",
9656 BGP_INSTANCE_HELP_STR
9658 BGP_SAFI_WITH_LABEL_HELP_STR
9659 "Display routes matching the large-community-list\n"
9660 "large-community-list number\n"
9661 "large-community-list name\n"
9665 afi_t afi
= AFI_IP6
;
9666 safi_t safi
= SAFI_UNICAST
;
9669 if (argv_find(argv
, argc
, "ip", &idx
))
9671 if (argv_find(argv
, argc
, "view", &idx
)
9672 || argv_find(argv
, argc
, "vrf", &idx
))
9673 vrf
= argv
[++idx
]->arg
;
9674 if (argv_find(argv
, argc
, "ipv4", &idx
)
9675 || argv_find(argv
, argc
, "ipv6", &idx
)) {
9676 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
9677 if (argv_find(argv
, argc
, "unicast", &idx
)
9678 || argv_find(argv
, argc
, "multicast", &idx
))
9679 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
9682 bool uj
= use_json(argc
, argv
);
9684 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
9686 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
9690 argv_find(argv
, argc
, "large-community-list", &idx
);
9691 return bgp_show_lcommunity_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
, safi
,
9694 DEFUN (show_ip_bgp_large_community
,
9695 show_ip_bgp_large_community_cmd
,
9696 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [AA:BB:CC] [json]",
9700 BGP_INSTANCE_HELP_STR
9702 BGP_SAFI_WITH_LABEL_HELP_STR
9703 "Display routes matching the large-communities\n"
9704 "List of large-community numbers\n"
9708 afi_t afi
= AFI_IP6
;
9709 safi_t safi
= SAFI_UNICAST
;
9712 if (argv_find(argv
, argc
, "ip", &idx
))
9714 if (argv_find(argv
, argc
, "view", &idx
)
9715 || argv_find(argv
, argc
, "vrf", &idx
))
9716 vrf
= argv
[++idx
]->arg
;
9717 if (argv_find(argv
, argc
, "ipv4", &idx
)
9718 || argv_find(argv
, argc
, "ipv6", &idx
)) {
9719 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
9720 if (argv_find(argv
, argc
, "unicast", &idx
)
9721 || argv_find(argv
, argc
, "multicast", &idx
))
9722 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
9725 bool uj
= use_json(argc
, argv
);
9727 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
9729 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
9733 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
))
9734 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
, afi
, safi
, uj
);
9736 return bgp_show(vty
, bgp
, afi
, safi
,
9737 bgp_show_type_lcommunity_all
, NULL
, uj
);
9740 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
9744 /* BGP route print out function without JSON */
9747 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
9748 <dampening <parameters>\
9753 |community-list <(1-500)|WORD> [exact-match]\
9754 |A.B.C.D/M longer-prefixes\
9755 |X:X::X:X/M longer-prefixes\
9760 BGP_INSTANCE_HELP_STR
9762 BGP_SAFI_WITH_LABEL_HELP_STR
9763 "Display detailed information about dampening\n"
9764 "Display detail of configured dampening parameters\n"
9765 "Display routes matching the route-map\n"
9766 "A route-map to match on\n"
9767 "Display routes conforming to the prefix-list\n"
9768 "Prefix-list name\n"
9769 "Display routes conforming to the filter-list\n"
9770 "Regular expression access list name\n"
9771 "BGP RIB advertisement statistics\n"
9772 "Display routes matching the community-list\n"
9773 "community-list number\n"
9774 "community-list name\n"
9775 "Exact match of the communities\n"
9777 "Display route and more specific routes\n"
9779 "Display route and more specific routes\n")
9781 afi_t afi
= AFI_IP6
;
9782 safi_t safi
= SAFI_UNICAST
;
9783 int exact_match
= 0;
9784 struct bgp
*bgp
= NULL
;
9787 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9792 if (argv_find(argv
, argc
, "dampening", &idx
)) {
9793 if (argv_find(argv
, argc
, "parameters", &idx
))
9794 return bgp_show_dampening_parameters(vty
, afi
, safi
);
9797 if (argv_find(argv
, argc
, "prefix-list", &idx
))
9798 return bgp_show_prefix_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9799 safi
, bgp_show_type_prefix_list
);
9801 if (argv_find(argv
, argc
, "filter-list", &idx
))
9802 return bgp_show_filter_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9803 safi
, bgp_show_type_filter_list
);
9805 if (argv_find(argv
, argc
, "statistics", &idx
))
9806 return bgp_table_stats(vty
, bgp
, afi
, safi
);
9808 if (argv_find(argv
, argc
, "route-map", &idx
))
9809 return bgp_show_route_map(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9810 safi
, bgp_show_type_route_map
);
9812 if (argv_find(argv
, argc
, "community-list", &idx
)) {
9813 const char *clist_number_or_name
= argv
[++idx
]->arg
;
9814 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
9816 return bgp_show_community_list(vty
, bgp
, clist_number_or_name
,
9817 exact_match
, afi
, safi
);
9820 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
9821 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
9822 return bgp_show_prefix_longer(vty
, bgp
, argv
[idx
]->arg
, afi
,
9824 bgp_show_type_prefix_longer
);
9829 /* BGP route print out function with JSON */
9830 DEFUN (show_ip_bgp_json
,
9831 show_ip_bgp_json_cmd
,
9832 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
9834 |dampening <flap-statistics|dampened-paths>\
9835 |community [AA:NN|local-AS|no-advertise|no-export\
9836 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
9837 |accept-own|accept-own-nexthop|route-filter-v6\
9838 |route-filter-v4|route-filter-translated-v6\
9839 |route-filter-translated-v4] [exact-match]\
9844 BGP_INSTANCE_HELP_STR
9846 BGP_SAFI_WITH_LABEL_HELP_STR
9847 "Display only routes with non-natural netmasks\n"
9848 "Display detailed information about dampening\n"
9849 "Display flap statistics of routes\n"
9850 "Display paths suppressed due to dampening\n"
9851 "Display routes matching the communities\n"
9853 "Do not send outside local AS (well-known community)\n"
9854 "Do not advertise to any peer (well-known community)\n"
9855 "Do not export to next AS (well-known community)\n"
9856 "Graceful shutdown (well-known community)\n"
9857 "Do not export to any peer (well-known community)\n"
9858 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
9859 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
9860 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
9861 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
9862 "Should accept VPN route with local nexthop (well-known community)\n"
9863 "RT VPNv6 route filtering (well-known community)\n"
9864 "RT VPNv4 route filtering (well-known community)\n"
9865 "RT translated VPNv6 route filtering (well-known community)\n"
9866 "RT translated VPNv4 route filtering (well-known community)\n"
9867 "Exact match of the communities\n"
9870 afi_t afi
= AFI_IP6
;
9871 safi_t safi
= SAFI_UNICAST
;
9872 enum bgp_show_type sh_type
= bgp_show_type_normal
;
9873 struct bgp
*bgp
= NULL
;
9875 int exact_match
= 0;
9876 bool uj
= use_json(argc
, argv
);
9881 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9886 if (argv_find(argv
, argc
, "cidr-only", &idx
))
9887 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_cidr_only
,
9890 if (argv_find(argv
, argc
, "dampening", &idx
)) {
9891 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
9892 return bgp_show(vty
, bgp
, afi
, safi
,
9893 bgp_show_type_dampend_paths
, NULL
, uj
);
9894 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
9895 return bgp_show(vty
, bgp
, afi
, safi
,
9896 bgp_show_type_flap_statistics
, NULL
,
9900 if (argv_find(argv
, argc
, "community", &idx
)) {
9901 char *maybecomm
= NULL
;
9902 char *community
= NULL
;
9904 if (idx
+ 1 < argc
) {
9905 if (argv
[idx
+ 1]->type
== VARIABLE_TKN
)
9906 maybecomm
= argv
[idx
+ 1]->arg
;
9908 maybecomm
= argv
[idx
+ 1]->text
;
9911 if (maybecomm
&& !strmatch(maybecomm
, "json")
9912 && !strmatch(maybecomm
, "exact-match"))
9913 community
= maybecomm
;
9915 if (argv_find(argv
, argc
, "exact-match", &idx
))
9919 return bgp_show_community(vty
, bgp
, community
,
9920 exact_match
, afi
, safi
, uj
);
9922 return (bgp_show(vty
, bgp
, afi
, safi
,
9923 bgp_show_type_community_all
, NULL
,
9927 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
, NULL
, uj
);
9930 DEFUN (show_ip_bgp_route
,
9931 show_ip_bgp_route_cmd
,
9932 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]"
9933 "<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [json]",
9937 BGP_INSTANCE_HELP_STR
9939 BGP_SAFI_WITH_LABEL_HELP_STR
9940 "Network in the BGP routing table to display\n"
9942 "Network in the BGP routing table to display\n"
9944 "Display only the bestpath\n"
9945 "Display only multipaths\n"
9948 int prefix_check
= 0;
9950 afi_t afi
= AFI_IP6
;
9951 safi_t safi
= SAFI_UNICAST
;
9952 char *prefix
= NULL
;
9953 struct bgp
*bgp
= NULL
;
9954 enum bgp_path_type path_type
;
9955 bool uj
= use_json(argc
, argv
);
9959 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9966 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
9970 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
9971 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
9972 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
9974 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
9975 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
9978 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
9979 && afi
!= AFI_IP6
) {
9981 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
9984 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
9987 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
9991 prefix
= argv
[idx
]->arg
;
9993 /* [<bestpath|multipath>] */
9994 if (argv_find(argv
, argc
, "bestpath", &idx
))
9995 path_type
= BGP_PATH_SHOW_BESTPATH
;
9996 else if (argv_find(argv
, argc
, "multipath", &idx
))
9997 path_type
= BGP_PATH_SHOW_MULTIPATH
;
9999 path_type
= BGP_PATH_SHOW_ALL
;
10001 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
10005 DEFUN (show_ip_bgp_regexp
,
10006 show_ip_bgp_regexp_cmd
,
10007 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX...",
10011 BGP_INSTANCE_HELP_STR
10013 BGP_SAFI_WITH_LABEL_HELP_STR
10014 "Display routes matching the AS path regular expression\n"
10015 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n")
10017 afi_t afi
= AFI_IP6
;
10018 safi_t safi
= SAFI_UNICAST
;
10019 struct bgp
*bgp
= NULL
;
10022 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10025 return CMD_WARNING
;
10027 // get index of regex
10028 argv_find(argv
, argc
, "regexp", &idx
);
10031 char *regstr
= argv_concat(argv
, argc
, idx
);
10032 int rc
= bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
10033 bgp_show_type_regexp
);
10034 XFREE(MTYPE_TMP
, regstr
);
10038 DEFUN (show_ip_bgp_instance_all
,
10039 show_ip_bgp_instance_all_cmd
,
10040 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json]",
10044 BGP_INSTANCE_ALL_HELP_STR
10046 BGP_SAFI_WITH_LABEL_HELP_STR
10049 afi_t afi
= AFI_IP
;
10050 safi_t safi
= SAFI_UNICAST
;
10051 struct bgp
*bgp
= NULL
;
10053 bool uj
= use_json(argc
, argv
);
10058 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10061 return CMD_WARNING
;
10063 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, uj
);
10064 return CMD_SUCCESS
;
10067 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
10068 afi_t afi
, safi_t safi
, enum bgp_show_type type
)
10073 if (!config_bgp_aspath_validate(regstr
)) {
10074 vty_out(vty
, "Invalid character in as-path access-list %s\n",
10076 return CMD_WARNING_CONFIG_FAILED
;
10079 regex
= bgp_regcomp(regstr
);
10081 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
10082 return CMD_WARNING
;
10085 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, 0);
10086 bgp_regex_free(regex
);
10090 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
10091 const char *prefix_list_str
, afi_t afi
,
10092 safi_t safi
, enum bgp_show_type type
)
10094 struct prefix_list
*plist
;
10096 plist
= prefix_list_lookup(afi
, prefix_list_str
);
10097 if (plist
== NULL
) {
10098 vty_out(vty
, "%% %s is not a valid prefix-list name\n",
10100 return CMD_WARNING
;
10103 return bgp_show(vty
, bgp
, afi
, safi
, type
, plist
, 0);
10106 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
10107 const char *filter
, afi_t afi
, safi_t safi
,
10108 enum bgp_show_type type
)
10110 struct as_list
*as_list
;
10112 as_list
= as_list_lookup(filter
);
10113 if (as_list
== NULL
) {
10114 vty_out(vty
, "%% %s is not a valid AS-path access-list name\n",
10116 return CMD_WARNING
;
10119 return bgp_show(vty
, bgp
, afi
, safi
, type
, as_list
, 0);
10122 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
10123 const char *rmap_str
, afi_t afi
, safi_t safi
,
10124 enum bgp_show_type type
)
10126 struct route_map
*rmap
;
10128 rmap
= route_map_lookup_by_name(rmap_str
);
10130 vty_out(vty
, "%% %s is not a valid route-map name\n", rmap_str
);
10131 return CMD_WARNING
;
10134 return bgp_show(vty
, bgp
, afi
, safi
, type
, rmap
, 0);
10137 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
10138 const char *comstr
, int exact
, afi_t afi
,
10139 safi_t safi
, bool use_json
)
10141 struct community
*com
;
10144 com
= community_str2com(comstr
);
10146 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
10147 return CMD_WARNING
;
10150 ret
= bgp_show(vty
, bgp
, afi
, safi
,
10151 (exact
? bgp_show_type_community_exact
10152 : bgp_show_type_community
),
10154 community_free(&com
);
10159 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
10160 const char *com
, int exact
, afi_t afi
,
10163 struct community_list
*list
;
10165 list
= community_list_lookup(bgp_clist
, com
, 0, COMMUNITY_LIST_MASTER
);
10166 if (list
== NULL
) {
10167 vty_out(vty
, "%% %s is not a valid community-list name\n", com
);
10168 return CMD_WARNING
;
10171 return bgp_show(vty
, bgp
, afi
, safi
,
10172 (exact
? bgp_show_type_community_list_exact
10173 : bgp_show_type_community_list
),
10177 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
10178 const char *prefix
, afi_t afi
, safi_t safi
,
10179 enum bgp_show_type type
)
10186 ret
= str2prefix(prefix
, p
);
10188 vty_out(vty
, "%% Malformed Prefix\n");
10189 return CMD_WARNING
;
10192 ret
= bgp_show(vty
, bgp
, afi
, safi
, type
, p
, 0);
10197 static struct peer
*peer_lookup_in_view(struct vty
*vty
, struct bgp
*bgp
,
10198 const char *ip_str
, bool use_json
)
10202 union sockunion su
;
10204 /* Get peer sockunion. */
10205 ret
= str2sockunion(ip_str
, &su
);
10207 peer
= peer_lookup_by_conf_if(bgp
, ip_str
);
10209 peer
= peer_lookup_by_hostname(bgp
, ip_str
);
10213 json_object
*json_no
= NULL
;
10214 json_no
= json_object_new_object();
10215 json_object_string_add(
10217 "malformedAddressOrName",
10219 vty_out(vty
, "%s\n",
10220 json_object_to_json_string_ext(
10222 JSON_C_TO_STRING_PRETTY
));
10223 json_object_free(json_no
);
10226 "%% Malformed address or name: %s\n",
10234 /* Peer structure lookup. */
10235 peer
= peer_lookup(bgp
, &su
);
10238 json_object
*json_no
= NULL
;
10239 json_no
= json_object_new_object();
10240 json_object_string_add(json_no
, "warning",
10241 "No such neighbor in this view/vrf");
10242 vty_out(vty
, "%s\n",
10243 json_object_to_json_string_ext(
10244 json_no
, JSON_C_TO_STRING_PRETTY
));
10245 json_object_free(json_no
);
10247 vty_out(vty
, "No such neighbor in this view/vrf\n");
10255 BGP_STATS_MAXBITLEN
= 0,
10257 BGP_STATS_PREFIXES
,
10259 BGP_STATS_UNAGGREGATEABLE
,
10260 BGP_STATS_MAX_AGGREGATEABLE
,
10261 BGP_STATS_AGGREGATES
,
10263 BGP_STATS_ASPATH_COUNT
,
10264 BGP_STATS_ASPATH_MAXHOPS
,
10265 BGP_STATS_ASPATH_TOTHOPS
,
10266 BGP_STATS_ASPATH_MAXSIZE
,
10267 BGP_STATS_ASPATH_TOTSIZE
,
10268 BGP_STATS_ASN_HIGHEST
,
10272 static const char *table_stats_strs
[] = {
10273 [BGP_STATS_PREFIXES
] = "Total Prefixes",
10274 [BGP_STATS_TOTPLEN
] = "Average prefix length",
10275 [BGP_STATS_RIB
] = "Total Advertisements",
10276 [BGP_STATS_UNAGGREGATEABLE
] = "Unaggregateable prefixes",
10277 [BGP_STATS_MAX_AGGREGATEABLE
] =
10278 "Maximum aggregateable prefixes",
10279 [BGP_STATS_AGGREGATES
] = "BGP Aggregate advertisements",
10280 [BGP_STATS_SPACE
] = "Address space advertised",
10281 [BGP_STATS_ASPATH_COUNT
] = "Advertisements with paths",
10282 [BGP_STATS_ASPATH_MAXHOPS
] = "Longest AS-Path (hops)",
10283 [BGP_STATS_ASPATH_MAXSIZE
] = "Largest AS-Path (bytes)",
10284 [BGP_STATS_ASPATH_TOTHOPS
] = "Average AS-Path length (hops)",
10285 [BGP_STATS_ASPATH_TOTSIZE
] = "Average AS-Path size (bytes)",
10286 [BGP_STATS_ASN_HIGHEST
] = "Highest public ASN",
10287 [BGP_STATS_MAX
] = NULL
,
10290 struct bgp_table_stats
{
10291 struct bgp_table
*table
;
10292 unsigned long long counts
[BGP_STATS_MAX
];
10293 double total_space
;
10297 #define TALLY_SIGFIG 100000
10298 static unsigned long
10299 ravg_tally (unsigned long count
, unsigned long oldavg
, unsigned long newval
)
10301 unsigned long newtot
= (count
-1) * oldavg
+ (newval
* TALLY_SIGFIG
);
10302 unsigned long res
= (newtot
* TALLY_SIGFIG
) / count
;
10303 unsigned long ret
= newtot
/ count
;
10305 if ((res
% TALLY_SIGFIG
) > (TALLY_SIGFIG
/2))
10312 static void bgp_table_stats_rn(struct bgp_node
*rn
, struct bgp_node
*top
,
10313 struct bgp_table_stats
*ts
, unsigned int space
)
10315 struct bgp_node
*prn
= bgp_node_parent_nolock(rn
);
10316 struct bgp_path_info
*pi
;
10321 if (!bgp_node_has_bgp_path_info_data(rn
))
10324 ts
->counts
[BGP_STATS_PREFIXES
]++;
10325 ts
->counts
[BGP_STATS_TOTPLEN
] += rn
->p
.prefixlen
;
10328 ts
->counts
[BGP_STATS_AVGPLEN
]
10329 = ravg_tally (ts
->counts
[BGP_STATS_PREFIXES
],
10330 ts
->counts
[BGP_STATS_AVGPLEN
],
10334 /* check if the prefix is included by any other announcements */
10335 while (prn
&& !bgp_node_has_bgp_path_info_data(prn
))
10336 prn
= bgp_node_parent_nolock(prn
);
10338 if (prn
== NULL
|| prn
== top
) {
10339 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
10340 /* announced address space */
10342 ts
->total_space
+= pow(2.0, space
- rn
->p
.prefixlen
);
10343 } else if (bgp_node_has_bgp_path_info_data(prn
))
10344 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
10347 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
10348 ts
->counts
[BGP_STATS_RIB
]++;
10351 && (CHECK_FLAG(pi
->attr
->flag
,
10352 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))))
10353 ts
->counts
[BGP_STATS_AGGREGATES
]++;
10355 /* as-path stats */
10356 if (pi
->attr
&& pi
->attr
->aspath
) {
10357 unsigned int hops
= aspath_count_hops(pi
->attr
->aspath
);
10358 unsigned int size
= aspath_size(pi
->attr
->aspath
);
10359 as_t highest
= aspath_highest(pi
->attr
->aspath
);
10361 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
10363 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
10364 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] = hops
;
10366 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
10367 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] = size
;
10369 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
10370 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
10372 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
]
10373 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
10374 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
],
10376 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
]
10377 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
10378 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
],
10381 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
10382 ts
->counts
[BGP_STATS_ASN_HIGHEST
] = highest
;
10387 static int bgp_table_stats_walker(struct thread
*t
)
10389 struct bgp_node
*rn
, *nrn
;
10390 struct bgp_node
*top
;
10391 struct bgp_table_stats
*ts
= THREAD_ARG(t
);
10392 unsigned int space
= 0;
10394 if (!(top
= bgp_table_top(ts
->table
)))
10397 switch (ts
->table
->afi
) {
10399 space
= IPV4_MAX_BITLEN
;
10402 space
= IPV6_MAX_BITLEN
;
10408 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
10410 for (rn
= top
; rn
; rn
= bgp_route_next(rn
)) {
10411 if (ts
->table
->safi
== SAFI_MPLS_VPN
) {
10412 struct bgp_table
*table
;
10414 table
= bgp_node_get_bgp_table_info(rn
);
10418 top
= bgp_table_top(table
);
10419 for (nrn
= bgp_table_top(table
); nrn
;
10420 nrn
= bgp_route_next(nrn
))
10421 bgp_table_stats_rn(nrn
, top
, ts
, space
);
10423 bgp_table_stats_rn(rn
, top
, ts
, space
);
10430 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
10433 struct bgp_table_stats ts
;
10436 if (!bgp
->rib
[afi
][safi
]) {
10437 vty_out(vty
, "%% No RIB exist's for the AFI(%d)/SAFI(%d)\n",
10439 return CMD_WARNING
;
10442 vty_out(vty
, "BGP %s RIB statistics\n", afi_safi_print(afi
, safi
));
10444 /* labeled-unicast routes live in the unicast table */
10445 if (safi
== SAFI_LABELED_UNICAST
)
10446 safi
= SAFI_UNICAST
;
10448 memset(&ts
, 0, sizeof(ts
));
10449 ts
.table
= bgp
->rib
[afi
][safi
];
10450 thread_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
10452 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
10453 if (!table_stats_strs
[i
])
10458 case BGP_STATS_ASPATH_AVGHOPS
:
10459 case BGP_STATS_ASPATH_AVGSIZE
:
10460 case BGP_STATS_AVGPLEN
:
10461 vty_out (vty
, "%-30s: ", table_stats_strs
[i
]);
10462 vty_out (vty
, "%12.2f",
10463 (float)ts
.counts
[i
] / (float)TALLY_SIGFIG
);
10466 case BGP_STATS_ASPATH_TOTHOPS
:
10467 case BGP_STATS_ASPATH_TOTSIZE
:
10468 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10469 vty_out(vty
, "%12.2f",
10471 ? (float)ts
.counts
[i
]
10473 [BGP_STATS_ASPATH_COUNT
]
10476 case BGP_STATS_TOTPLEN
:
10477 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10478 vty_out(vty
, "%12.2f",
10480 ? (float)ts
.counts
[i
]
10482 [BGP_STATS_PREFIXES
]
10485 case BGP_STATS_SPACE
:
10486 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10487 vty_out(vty
, "%12g\n", ts
.total_space
);
10489 if (afi
== AFI_IP6
) {
10490 vty_out(vty
, "%30s: ", "/32 equivalent ");
10491 vty_out(vty
, "%12g\n",
10492 ts
.total_space
* pow(2.0, -128 + 32));
10493 vty_out(vty
, "%30s: ", "/48 equivalent ");
10494 vty_out(vty
, "%12g\n",
10495 ts
.total_space
* pow(2.0, -128 + 48));
10497 vty_out(vty
, "%30s: ", "% announced ");
10498 vty_out(vty
, "%12.2f\n",
10499 ts
.total_space
* 100. * pow(2.0, -32));
10500 vty_out(vty
, "%30s: ", "/8 equivalent ");
10501 vty_out(vty
, "%12.2f\n",
10502 ts
.total_space
* pow(2.0, -32 + 8));
10503 vty_out(vty
, "%30s: ", "/24 equivalent ");
10504 vty_out(vty
, "%12.2f\n",
10505 ts
.total_space
* pow(2.0, -32 + 24));
10509 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10510 vty_out(vty
, "%12llu", ts
.counts
[i
]);
10513 vty_out(vty
, "\n");
10515 return CMD_SUCCESS
;
10527 PCOUNT_PFCNT
, /* the figure we display to users */
10531 static const char *pcount_strs
[] = {
10532 [PCOUNT_ADJ_IN
] = "Adj-in",
10533 [PCOUNT_DAMPED
] = "Damped",
10534 [PCOUNT_REMOVED
] = "Removed",
10535 [PCOUNT_HISTORY
] = "History",
10536 [PCOUNT_STALE
] = "Stale",
10537 [PCOUNT_VALID
] = "Valid",
10538 [PCOUNT_ALL
] = "All RIB",
10539 [PCOUNT_COUNTED
] = "PfxCt counted",
10540 [PCOUNT_PFCNT
] = "Useable",
10541 [PCOUNT_MAX
] = NULL
,
10544 struct peer_pcounts
{
10545 unsigned int count
[PCOUNT_MAX
];
10546 const struct peer
*peer
;
10547 const struct bgp_table
*table
;
10550 static int bgp_peer_count_walker(struct thread
*t
)
10552 struct bgp_node
*rn
;
10553 struct peer_pcounts
*pc
= THREAD_ARG(t
);
10554 const struct peer
*peer
= pc
->peer
;
10556 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
)) {
10557 struct bgp_adj_in
*ain
;
10558 struct bgp_path_info
*pi
;
10560 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
10561 if (ain
->peer
== peer
)
10562 pc
->count
[PCOUNT_ADJ_IN
]++;
10564 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
10566 if (pi
->peer
!= peer
)
10569 pc
->count
[PCOUNT_ALL
]++;
10571 if (CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
))
10572 pc
->count
[PCOUNT_DAMPED
]++;
10573 if (CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
10574 pc
->count
[PCOUNT_HISTORY
]++;
10575 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
10576 pc
->count
[PCOUNT_REMOVED
]++;
10577 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
10578 pc
->count
[PCOUNT_STALE
]++;
10579 if (CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
10580 pc
->count
[PCOUNT_VALID
]++;
10581 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
10582 pc
->count
[PCOUNT_PFCNT
]++;
10584 if (CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
10585 pc
->count
[PCOUNT_COUNTED
]++;
10586 if (CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
10588 EC_LIB_DEVELOPMENT
,
10589 "Attempting to count but flags say it is unusable");
10591 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
10593 EC_LIB_DEVELOPMENT
,
10594 "Not counted but flags say we should");
10601 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
10602 safi_t safi
, bool use_json
)
10604 struct peer_pcounts pcounts
= {.peer
= peer
};
10606 json_object
*json
= NULL
;
10607 json_object
*json_loop
= NULL
;
10610 json
= json_object_new_object();
10611 json_loop
= json_object_new_object();
10614 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
10615 || !peer
->bgp
->rib
[afi
][safi
]) {
10617 json_object_string_add(
10619 "No such neighbor or address family");
10620 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10621 json_object_free(json
);
10623 vty_out(vty
, "%% No such neighbor or address family\n");
10625 return CMD_WARNING
;
10628 memset(&pcounts
, 0, sizeof(pcounts
));
10629 pcounts
.peer
= peer
;
10630 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
10632 /* in-place call via thread subsystem so as to record execution time
10633 * stats for the thread-walk (i.e. ensure this can't be blamed on
10634 * on just vty_read()).
10636 thread_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
10639 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
10640 json_object_string_add(json
, "multiProtocol",
10641 afi_safi_print(afi
, safi
));
10642 json_object_int_add(json
, "pfxCounter",
10643 peer
->pcount
[afi
][safi
]);
10645 for (i
= 0; i
< PCOUNT_MAX
; i
++)
10646 json_object_int_add(json_loop
, pcount_strs
[i
],
10649 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
10651 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
10652 json_object_string_add(json
, "pfxctDriftFor",
10654 json_object_string_add(
10655 json
, "recommended",
10656 "Please report this bug, with the above command output");
10658 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
10659 json
, JSON_C_TO_STRING_PRETTY
));
10660 json_object_free(json
);
10664 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
10665 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
10666 peer
->hostname
, peer
->host
,
10667 afi_safi_print(afi
, safi
));
10669 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
10670 afi_safi_print(afi
, safi
));
10673 vty_out(vty
, "PfxCt: %ld\n", peer
->pcount
[afi
][safi
]);
10674 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
10676 for (i
= 0; i
< PCOUNT_MAX
; i
++)
10677 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
10680 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
10681 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
10683 "Please report this bug, with the above command output\n");
10687 return CMD_SUCCESS
;
10690 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
10691 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
10692 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_CMD_STR
"]] "
10693 "neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
10697 BGP_INSTANCE_HELP_STR
10700 "Detailed information on TCP and BGP neighbor connections\n"
10701 "Neighbor to display information about\n"
10702 "Neighbor to display information about\n"
10703 "Neighbor on BGP configured interface\n"
10704 "Display detailed prefix count information\n"
10707 afi_t afi
= AFI_IP6
;
10708 safi_t safi
= SAFI_UNICAST
;
10711 struct bgp
*bgp
= NULL
;
10712 bool uj
= use_json(argc
, argv
);
10717 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10720 return CMD_WARNING
;
10722 argv_find(argv
, argc
, "neighbors", &idx
);
10723 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
10725 return CMD_WARNING
;
10727 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_UNICAST
, uj
);
10730 #ifdef KEEP_OLD_VPN_COMMANDS
10731 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
10732 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
10733 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
10738 "Display information about all VPNv4 NLRIs\n"
10739 "Detailed information on TCP and BGP neighbor connections\n"
10740 "Neighbor to display information about\n"
10741 "Neighbor to display information about\n"
10742 "Neighbor on BGP configured interface\n"
10743 "Display detailed prefix count information\n"
10748 bool uj
= use_json(argc
, argv
);
10750 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
10752 return CMD_WARNING
;
10754 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
10757 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
10758 show_ip_bgp_vpn_all_route_prefix_cmd
,
10759 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
10764 "Display information about all VPNv4 NLRIs\n"
10765 "Network in the BGP routing table to display\n"
10766 "Network in the BGP routing table to display\n"
10770 char *network
= NULL
;
10771 struct bgp
*bgp
= bgp_get_default();
10773 vty_out(vty
, "Can't find default instance\n");
10774 return CMD_WARNING
;
10777 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
10778 network
= argv
[idx
]->arg
;
10779 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
10780 network
= argv
[idx
]->arg
;
10782 vty_out(vty
, "Unable to figure out Network\n");
10783 return CMD_WARNING
;
10786 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
10787 BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
10789 #endif /* KEEP_OLD_VPN_COMMANDS */
10791 DEFUN (show_ip_bgp_l2vpn_evpn_all_route_prefix
,
10792 show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd
,
10793 "show [ip] bgp l2vpn evpn all <A.B.C.D|A.B.C.D/M> [json]",
10799 "Display information about all EVPN NLRIs\n"
10800 "Network in the BGP routing table to display\n"
10801 "Network in the BGP routing table to display\n"
10805 char *network
= NULL
;
10807 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
10808 network
= argv
[idx
]->arg
;
10809 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
10810 network
= argv
[idx
]->arg
;
10812 vty_out(vty
, "Unable to figure out Network\n");
10813 return CMD_WARNING
;
10815 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
, 0,
10816 BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
10819 static void show_adj_route(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
10820 safi_t safi
, enum bgp_show_adj_route_type type
,
10821 const char *rmap_name
, bool use_json
,
10824 struct bgp_table
*table
;
10825 struct bgp_adj_in
*ain
;
10826 struct bgp_adj_out
*adj
;
10827 unsigned long output_count
;
10828 unsigned long filtered_count
;
10829 struct bgp_node
*rn
;
10835 struct update_subgroup
*subgrp
;
10836 json_object
*json_scode
= NULL
;
10837 json_object
*json_ocode
= NULL
;
10838 json_object
*json_ar
= NULL
;
10839 struct peer_af
*paf
;
10840 bool route_filtered
;
10843 json_scode
= json_object_new_object();
10844 json_ocode
= json_object_new_object();
10845 json_ar
= json_object_new_object();
10847 json_object_string_add(json_scode
, "suppressed", "s");
10848 json_object_string_add(json_scode
, "damped", "d");
10849 json_object_string_add(json_scode
, "history", "h");
10850 json_object_string_add(json_scode
, "valid", "*");
10851 json_object_string_add(json_scode
, "best", ">");
10852 json_object_string_add(json_scode
, "multipath", "=");
10853 json_object_string_add(json_scode
, "internal", "i");
10854 json_object_string_add(json_scode
, "ribFailure", "r");
10855 json_object_string_add(json_scode
, "stale", "S");
10856 json_object_string_add(json_scode
, "removed", "R");
10858 json_object_string_add(json_ocode
, "igp", "i");
10859 json_object_string_add(json_ocode
, "egp", "e");
10860 json_object_string_add(json_ocode
, "incomplete", "?");
10867 json_object_string_add(json
, "alert", "no BGP");
10868 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10869 json_object_free(json
);
10871 vty_out(vty
, "%% No bgp\n");
10875 /* labeled-unicast routes live in the unicast table */
10876 if (safi
== SAFI_LABELED_UNICAST
)
10877 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
10879 table
= bgp
->rib
[afi
][safi
];
10881 output_count
= filtered_count
= 0;
10882 subgrp
= peer_subgroup(peer
, afi
, safi
);
10884 if (type
== bgp_show_adj_route_advertised
&& subgrp
10885 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
10887 json_object_int_add(json
, "bgpTableVersion",
10889 json_object_string_add(json
, "bgpLocalRouterId",
10890 inet_ntoa(bgp
->router_id
));
10891 json_object_int_add(json
, "defaultLocPrf",
10892 bgp
->default_local_pref
);
10893 json_object_int_add(json
, "localAS", bgp
->as
);
10894 json_object_object_add(json
, "bgpStatusCodes",
10896 json_object_object_add(json
, "bgpOriginCodes",
10898 json_object_string_add(
10899 json
, "bgpOriginatingDefaultNetwork",
10900 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
10902 vty_out(vty
, "BGP table version is %" PRIu64
10903 ", local router ID is %s, vrf id ",
10904 table
->version
, inet_ntoa(bgp
->router_id
));
10905 if (bgp
->vrf_id
== VRF_UNKNOWN
)
10906 vty_out(vty
, "%s", VRFID_NONE_STR
);
10908 vty_out(vty
, "%u", bgp
->vrf_id
);
10909 vty_out(vty
, "\n");
10910 vty_out(vty
, "Default local pref %u, ",
10911 bgp
->default_local_pref
);
10912 vty_out(vty
, "local AS %u\n", bgp
->as
);
10913 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
10914 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
10915 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
10917 vty_out(vty
, "Originating default network %s\n\n",
10918 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
10923 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
10924 if (type
== bgp_show_adj_route_received
10925 || type
== bgp_show_adj_route_filtered
) {
10926 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
10927 if (ain
->peer
!= peer
|| !ain
->attr
)
10932 json_object_int_add(
10933 json
, "bgpTableVersion",
10935 json_object_string_add(
10937 "bgpLocalRouterId",
10940 json_object_int_add(json
,
10942 bgp
->default_local_pref
);
10943 json_object_int_add(json
,
10944 "localAS", bgp
->as
);
10945 json_object_object_add(
10946 json
, "bgpStatusCodes",
10948 json_object_object_add(
10949 json
, "bgpOriginCodes",
10953 "BGP table version is 0, local router ID is %s, vrf id ",
10956 if (bgp
->vrf_id
== VRF_UNKNOWN
)
10962 vty_out(vty
, "\n");
10964 "Default local pref %u, ",
10965 bgp
->default_local_pref
);
10966 vty_out(vty
, "local AS %u\n",
10969 BGP_SHOW_SCODE_HEADER
);
10971 BGP_SHOW_NCODE_HEADER
);
10973 BGP_SHOW_OCODE_HEADER
);
10979 vty_out(vty
, BGP_SHOW_HEADER
);
10983 bgp_attr_dup(&attr
, ain
->attr
);
10984 route_filtered
= false;
10986 /* Filter prefix using distribute list,
10987 * filter list or prefix list
10989 if ((bgp_input_filter(peer
, &rn
->p
, &attr
, afi
,
10990 safi
)) == FILTER_DENY
)
10991 route_filtered
= true;
10993 /* Filter prefix using route-map */
10994 ret
= bgp_input_modifier(peer
, &rn
->p
, &attr
,
10995 afi
, safi
, rmap_name
);
10997 if (type
== bgp_show_adj_route_filtered
&&
10998 !route_filtered
&& ret
!= RMAP_DENY
) {
10999 bgp_attr_undup(&attr
, ain
->attr
);
11003 if (type
== bgp_show_adj_route_received
&&
11004 (route_filtered
|| ret
== RMAP_DENY
))
11007 route_vty_out_tmp(vty
, &rn
->p
, &attr
, safi
,
11008 use_json
, json_ar
);
11009 bgp_attr_undup(&attr
, ain
->attr
);
11012 } else if (type
== bgp_show_adj_route_advertised
) {
11013 RB_FOREACH (adj
, bgp_adj_out_rb
, &rn
->adj_out
)
11014 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
11015 if (paf
->peer
!= peer
|| !adj
->attr
)
11020 json_object_int_add(
11024 json_object_string_add(
11026 "bgpLocalRouterId",
11029 json_object_int_add(
11030 json
, "defaultLocPrf",
11031 bgp
->default_local_pref
11033 json_object_int_add(
11036 json_object_object_add(
11040 json_object_object_add(
11046 "BGP table version is %" PRIu64
11047 ", local router ID is %s, vrf id ",
11060 vty_out(vty
, "\n");
11062 "Default local pref %u, ",
11063 bgp
->default_local_pref
11069 BGP_SHOW_SCODE_HEADER
);
11071 BGP_SHOW_NCODE_HEADER
);
11073 BGP_SHOW_OCODE_HEADER
);
11084 bgp_attr_dup(&attr
, adj
->attr
);
11085 ret
= bgp_output_modifier(
11086 peer
, &rn
->p
, &attr
, afi
, safi
,
11089 if (ret
!= RMAP_DENY
) {
11090 route_vty_out_tmp(vty
, &rn
->p
,
11099 bgp_attr_undup(&attr
, adj
->attr
);
11105 json_object_object_add(json
, "advertisedRoutes", json_ar
);
11106 json_object_int_add(json
, "totalPrefixCounter", output_count
);
11107 json_object_int_add(json
, "filteredPrefixCounter",
11110 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
11111 json
, JSON_C_TO_STRING_PRETTY
));
11112 json_object_free(json
);
11113 } else if (output_count
> 0) {
11114 if (filtered_count
> 0)
11116 "\nTotal number of prefixes %ld (%ld filtered)\n",
11117 output_count
, filtered_count
);
11119 vty_out(vty
, "\nTotal number of prefixes %ld\n",
11124 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
11125 safi_t safi
, enum bgp_show_adj_route_type type
,
11126 const char *rmap_name
, bool use_json
)
11128 json_object
*json
= NULL
;
11131 json
= json_object_new_object();
11133 if (!peer
|| !peer
->afc
[afi
][safi
]) {
11135 json_object_string_add(
11137 "No such neighbor or address family");
11138 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
11139 json_object_free(json
);
11141 vty_out(vty
, "%% No such neighbor or address family\n");
11143 return CMD_WARNING
;
11146 if ((type
== bgp_show_adj_route_received
11147 || type
== bgp_show_adj_route_filtered
)
11148 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
11149 PEER_FLAG_SOFT_RECONFIG
)) {
11151 json_object_string_add(
11153 "Inbound soft reconfiguration not enabled");
11154 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
11155 json_object_free(json
);
11158 "%% Inbound soft reconfiguration not enabled\n");
11160 return CMD_WARNING
;
11163 show_adj_route(vty
, peer
, afi
, safi
, type
, rmap_name
, use_json
, json
);
11165 return CMD_SUCCESS
;
11168 DEFUN (show_ip_bgp_instance_neighbor_advertised_route
,
11169 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
11170 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
11171 "neighbors <A.B.C.D|X:X::X:X|WORD> <advertised-routes|received-routes|filtered-routes> [route-map WORD] [json]",
11175 BGP_INSTANCE_HELP_STR
11177 BGP_SAFI_WITH_LABEL_HELP_STR
11178 "Detailed information on TCP and BGP neighbor connections\n"
11179 "Neighbor to display information about\n"
11180 "Neighbor to display information about\n"
11181 "Neighbor on BGP configured interface\n"
11182 "Display the routes advertised to a BGP neighbor\n"
11183 "Display the received routes from neighbor\n"
11184 "Display the filtered routes received from neighbor\n"
11185 "Route-map to modify the attributes\n"
11186 "Name of the route map\n"
11189 afi_t afi
= AFI_IP6
;
11190 safi_t safi
= SAFI_UNICAST
;
11191 char *rmap_name
= NULL
;
11192 char *peerstr
= NULL
;
11193 struct bgp
*bgp
= NULL
;
11195 enum bgp_show_adj_route_type type
= bgp_show_adj_route_advertised
;
11197 bool uj
= use_json(argc
, argv
);
11202 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11205 return CMD_WARNING
;
11207 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11208 argv_find(argv
, argc
, "neighbors", &idx
);
11209 peerstr
= argv
[++idx
]->arg
;
11211 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
11213 return CMD_WARNING
;
11215 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
11216 type
= bgp_show_adj_route_advertised
;
11217 else if (argv_find(argv
, argc
, "received-routes", &idx
))
11218 type
= bgp_show_adj_route_received
;
11219 else if (argv_find(argv
, argc
, "filtered-routes", &idx
))
11220 type
= bgp_show_adj_route_filtered
;
11222 if (argv_find(argv
, argc
, "route-map", &idx
))
11223 rmap_name
= argv
[++idx
]->arg
;
11225 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
, uj
);
11228 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
11229 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
11230 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
11236 "Address Family modifier\n"
11237 "Detailed information on TCP and BGP neighbor connections\n"
11238 "Neighbor to display information about\n"
11239 "Neighbor to display information about\n"
11240 "Neighbor on BGP configured interface\n"
11241 "Display information received from a BGP neighbor\n"
11242 "Display the prefixlist filter\n"
11245 afi_t afi
= AFI_IP6
;
11246 safi_t safi
= SAFI_UNICAST
;
11247 char *peerstr
= NULL
;
11250 union sockunion su
;
11256 /* show [ip] bgp */
11257 if (argv_find(argv
, argc
, "ip", &idx
))
11259 /* [<ipv4|ipv6> [unicast]] */
11260 if (argv_find(argv
, argc
, "ipv4", &idx
))
11262 if (argv_find(argv
, argc
, "ipv6", &idx
))
11264 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11265 argv_find(argv
, argc
, "neighbors", &idx
);
11266 peerstr
= argv
[++idx
]->arg
;
11268 bool uj
= use_json(argc
, argv
);
11270 ret
= str2sockunion(peerstr
, &su
);
11272 peer
= peer_lookup_by_conf_if(NULL
, peerstr
);
11275 vty_out(vty
, "{}\n");
11278 "%% Malformed address or name: %s\n",
11280 return CMD_WARNING
;
11283 peer
= peer_lookup(NULL
, &su
);
11286 vty_out(vty
, "{}\n");
11288 vty_out(vty
, "No peer\n");
11289 return CMD_WARNING
;
11293 sprintf(name
, "%s.%d.%d", peer
->host
, afi
, safi
);
11294 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
11297 vty_out(vty
, "Address Family: %s\n",
11298 afi_safi_print(afi
, safi
));
11299 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
11302 vty_out(vty
, "{}\n");
11304 vty_out(vty
, "No functional output\n");
11307 return CMD_SUCCESS
;
11310 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
11311 afi_t afi
, safi_t safi
,
11312 enum bgp_show_type type
, bool use_json
)
11314 /* labeled-unicast routes live in the unicast table */
11315 if (safi
== SAFI_LABELED_UNICAST
)
11316 safi
= SAFI_UNICAST
;
11318 if (!peer
|| !peer
->afc
[afi
][safi
]) {
11320 json_object
*json_no
= NULL
;
11321 json_no
= json_object_new_object();
11322 json_object_string_add(
11323 json_no
, "warning",
11324 "No such neighbor or address family");
11325 vty_out(vty
, "%s\n",
11326 json_object_to_json_string(json_no
));
11327 json_object_free(json_no
);
11329 vty_out(vty
, "%% No such neighbor or address family\n");
11330 return CMD_WARNING
;
11333 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, use_json
);
11336 DEFUN (show_ip_bgp_flowspec_routes_detailed
,
11337 show_ip_bgp_flowspec_routes_detailed_cmd
,
11338 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" flowspec] detail [json]",
11342 BGP_INSTANCE_HELP_STR
11345 "Detailed information on flowspec entries\n"
11348 afi_t afi
= AFI_IP
;
11349 safi_t safi
= SAFI_UNICAST
;
11350 struct bgp
*bgp
= NULL
;
11352 bool uj
= use_json(argc
, argv
);
11357 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11360 return CMD_WARNING
;
11362 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_detail
, NULL
, uj
);
11365 DEFUN (show_ip_bgp_neighbor_routes
,
11366 show_ip_bgp_neighbor_routes_cmd
,
11367 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
11368 "neighbors <A.B.C.D|X:X::X:X|WORD> <flap-statistics|dampened-routes|routes> [json]",
11372 BGP_INSTANCE_HELP_STR
11374 BGP_SAFI_WITH_LABEL_HELP_STR
11375 "Detailed information on TCP and BGP neighbor connections\n"
11376 "Neighbor to display information about\n"
11377 "Neighbor to display information about\n"
11378 "Neighbor on BGP configured interface\n"
11379 "Display flap statistics of the routes learned from neighbor\n"
11380 "Display the dampened routes received from neighbor\n"
11381 "Display routes learned from neighbor\n"
11384 char *peerstr
= NULL
;
11385 struct bgp
*bgp
= NULL
;
11386 afi_t afi
= AFI_IP6
;
11387 safi_t safi
= SAFI_UNICAST
;
11389 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
11391 bool uj
= use_json(argc
, argv
);
11396 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11399 return CMD_WARNING
;
11401 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11402 argv_find(argv
, argc
, "neighbors", &idx
);
11403 peerstr
= argv
[++idx
]->arg
;
11405 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
11407 return CMD_WARNING
;
11409 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
11410 sh_type
= bgp_show_type_flap_neighbor
;
11411 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
11412 sh_type
= bgp_show_type_damp_neighbor
;
11413 else if (argv_find(argv
, argc
, "routes", &idx
))
11414 sh_type
= bgp_show_type_neighbor
;
11416 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
11419 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
11421 struct bgp_distance
{
11422 /* Distance value for the IP source prefix. */
11425 /* Name of the access-list to be matched. */
11429 DEFUN (show_bgp_afi_vpn_rd_route
,
11430 show_bgp_afi_vpn_rd_route_cmd
,
11431 "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]",
11435 "Address Family modifier\n"
11436 "Display information for a route distinguisher\n"
11437 "Route Distinguisher\n"
11438 "Network in the BGP routing table to display\n"
11439 "Network in the BGP routing table to display\n"
11443 struct prefix_rd prd
;
11444 afi_t afi
= AFI_MAX
;
11447 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
11448 vty_out(vty
, "%% Malformed Address Family\n");
11449 return CMD_WARNING
;
11452 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
11454 vty_out(vty
, "%% Malformed Route Distinguisher\n");
11455 return CMD_WARNING
;
11458 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
11459 0, BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
11462 static struct bgp_distance
*bgp_distance_new(void)
11464 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
11467 static void bgp_distance_free(struct bgp_distance
*bdistance
)
11469 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
11472 static int bgp_distance_set(struct vty
*vty
, const char *distance_str
,
11473 const char *ip_str
, const char *access_list_str
)
11480 struct bgp_node
*rn
;
11481 struct bgp_distance
*bdistance
;
11483 afi
= bgp_node_afi(vty
);
11484 safi
= bgp_node_safi(vty
);
11486 ret
= str2prefix(ip_str
, &p
);
11488 vty_out(vty
, "Malformed prefix\n");
11489 return CMD_WARNING_CONFIG_FAILED
;
11492 distance
= atoi(distance_str
);
11494 /* Get BGP distance node. */
11495 rn
= bgp_node_get(bgp_distance_table
[afi
][safi
], (struct prefix
*)&p
);
11496 bdistance
= bgp_node_get_bgp_distance_info(rn
);
11498 bgp_unlock_node(rn
);
11500 bdistance
= bgp_distance_new();
11501 bgp_node_set_bgp_distance_info(rn
, bdistance
);
11504 /* Set distance value. */
11505 bdistance
->distance
= distance
;
11507 /* Reset access-list configuration. */
11508 if (bdistance
->access_list
) {
11509 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
11510 bdistance
->access_list
= NULL
;
11512 if (access_list_str
)
11513 bdistance
->access_list
=
11514 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
11516 return CMD_SUCCESS
;
11519 static int bgp_distance_unset(struct vty
*vty
, const char *distance_str
,
11520 const char *ip_str
, const char *access_list_str
)
11527 struct bgp_node
*rn
;
11528 struct bgp_distance
*bdistance
;
11530 afi
= bgp_node_afi(vty
);
11531 safi
= bgp_node_safi(vty
);
11533 ret
= str2prefix(ip_str
, &p
);
11535 vty_out(vty
, "Malformed prefix\n");
11536 return CMD_WARNING_CONFIG_FAILED
;
11539 rn
= bgp_node_lookup(bgp_distance_table
[afi
][safi
],
11540 (struct prefix
*)&p
);
11542 vty_out(vty
, "Can't find specified prefix\n");
11543 return CMD_WARNING_CONFIG_FAILED
;
11546 bdistance
= bgp_node_get_bgp_distance_info(rn
);
11547 distance
= atoi(distance_str
);
11549 if (bdistance
->distance
!= distance
) {
11550 vty_out(vty
, "Distance does not match configured\n");
11551 return CMD_WARNING_CONFIG_FAILED
;
11554 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
11555 bgp_distance_free(bdistance
);
11557 bgp_node_set_bgp_path_info(rn
, NULL
);
11558 bgp_unlock_node(rn
);
11559 bgp_unlock_node(rn
);
11561 return CMD_SUCCESS
;
11564 /* Apply BGP information to distance method. */
11565 uint8_t bgp_distance_apply(struct prefix
*p
, struct bgp_path_info
*pinfo
,
11566 afi_t afi
, safi_t safi
, struct bgp
*bgp
)
11568 struct bgp_node
*rn
;
11571 struct bgp_distance
*bdistance
;
11572 struct access_list
*alist
;
11573 struct bgp_static
*bgp_static
;
11578 peer
= pinfo
->peer
;
11580 /* Check source address. */
11581 sockunion2hostprefix(&peer
->su
, &q
);
11582 rn
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
11584 bdistance
= bgp_node_get_bgp_distance_info(rn
);
11585 bgp_unlock_node(rn
);
11587 if (bdistance
->access_list
) {
11588 alist
= access_list_lookup(afi
, bdistance
->access_list
);
11590 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
11591 return bdistance
->distance
;
11593 return bdistance
->distance
;
11596 /* Backdoor check. */
11597 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
11599 bgp_static
= bgp_node_get_bgp_static_info(rn
);
11600 bgp_unlock_node(rn
);
11602 if (bgp_static
->backdoor
) {
11603 if (bgp
->distance_local
[afi
][safi
])
11604 return bgp
->distance_local
[afi
][safi
];
11606 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
11610 if (peer
->sort
== BGP_PEER_EBGP
) {
11611 if (bgp
->distance_ebgp
[afi
][safi
])
11612 return bgp
->distance_ebgp
[afi
][safi
];
11613 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
11615 if (bgp
->distance_ibgp
[afi
][safi
])
11616 return bgp
->distance_ibgp
[afi
][safi
];
11617 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
11621 DEFUN (bgp_distance
,
11623 "distance bgp (1-255) (1-255) (1-255)",
11624 "Define an administrative distance\n"
11626 "Distance for routes external to the AS\n"
11627 "Distance for routes internal to the AS\n"
11628 "Distance for local routes\n")
11630 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11631 int idx_number
= 2;
11632 int idx_number_2
= 3;
11633 int idx_number_3
= 4;
11637 afi
= bgp_node_afi(vty
);
11638 safi
= bgp_node_safi(vty
);
11640 bgp
->distance_ebgp
[afi
][safi
] = atoi(argv
[idx_number
]->arg
);
11641 bgp
->distance_ibgp
[afi
][safi
] = atoi(argv
[idx_number_2
]->arg
);
11642 bgp
->distance_local
[afi
][safi
] = atoi(argv
[idx_number_3
]->arg
);
11643 return CMD_SUCCESS
;
11646 DEFUN (no_bgp_distance
,
11647 no_bgp_distance_cmd
,
11648 "no distance bgp [(1-255) (1-255) (1-255)]",
11650 "Define an administrative distance\n"
11652 "Distance for routes external to the AS\n"
11653 "Distance for routes internal to the AS\n"
11654 "Distance for local routes\n")
11656 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11660 afi
= bgp_node_afi(vty
);
11661 safi
= bgp_node_safi(vty
);
11663 bgp
->distance_ebgp
[afi
][safi
] = 0;
11664 bgp
->distance_ibgp
[afi
][safi
] = 0;
11665 bgp
->distance_local
[afi
][safi
] = 0;
11666 return CMD_SUCCESS
;
11670 DEFUN (bgp_distance_source
,
11671 bgp_distance_source_cmd
,
11672 "distance (1-255) A.B.C.D/M",
11673 "Define an administrative distance\n"
11674 "Administrative distance\n"
11675 "IP source prefix\n")
11677 int idx_number
= 1;
11678 int idx_ipv4_prefixlen
= 2;
11679 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
11680 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
11681 return CMD_SUCCESS
;
11684 DEFUN (no_bgp_distance_source
,
11685 no_bgp_distance_source_cmd
,
11686 "no distance (1-255) A.B.C.D/M",
11688 "Define an administrative distance\n"
11689 "Administrative distance\n"
11690 "IP source prefix\n")
11692 int idx_number
= 2;
11693 int idx_ipv4_prefixlen
= 3;
11694 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
11695 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
11696 return CMD_SUCCESS
;
11699 DEFUN (bgp_distance_source_access_list
,
11700 bgp_distance_source_access_list_cmd
,
11701 "distance (1-255) A.B.C.D/M WORD",
11702 "Define an administrative distance\n"
11703 "Administrative distance\n"
11704 "IP source prefix\n"
11705 "Access list name\n")
11707 int idx_number
= 1;
11708 int idx_ipv4_prefixlen
= 2;
11710 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
11711 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
11712 return CMD_SUCCESS
;
11715 DEFUN (no_bgp_distance_source_access_list
,
11716 no_bgp_distance_source_access_list_cmd
,
11717 "no distance (1-255) A.B.C.D/M WORD",
11719 "Define an administrative distance\n"
11720 "Administrative distance\n"
11721 "IP source prefix\n"
11722 "Access list name\n")
11724 int idx_number
= 2;
11725 int idx_ipv4_prefixlen
= 3;
11727 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
11728 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
11729 return CMD_SUCCESS
;
11732 DEFUN (ipv6_bgp_distance_source
,
11733 ipv6_bgp_distance_source_cmd
,
11734 "distance (1-255) X:X::X:X/M",
11735 "Define an administrative distance\n"
11736 "Administrative distance\n"
11737 "IP source prefix\n")
11739 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, NULL
);
11740 return CMD_SUCCESS
;
11743 DEFUN (no_ipv6_bgp_distance_source
,
11744 no_ipv6_bgp_distance_source_cmd
,
11745 "no distance (1-255) X:X::X:X/M",
11747 "Define an administrative distance\n"
11748 "Administrative distance\n"
11749 "IP source prefix\n")
11751 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, NULL
);
11752 return CMD_SUCCESS
;
11755 DEFUN (ipv6_bgp_distance_source_access_list
,
11756 ipv6_bgp_distance_source_access_list_cmd
,
11757 "distance (1-255) X:X::X:X/M WORD",
11758 "Define an administrative distance\n"
11759 "Administrative distance\n"
11760 "IP source prefix\n"
11761 "Access list name\n")
11763 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, argv
[3]->arg
);
11764 return CMD_SUCCESS
;
11767 DEFUN (no_ipv6_bgp_distance_source_access_list
,
11768 no_ipv6_bgp_distance_source_access_list_cmd
,
11769 "no distance (1-255) X:X::X:X/M WORD",
11771 "Define an administrative distance\n"
11772 "Administrative distance\n"
11773 "IP source prefix\n"
11774 "Access list name\n")
11776 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, argv
[4]->arg
);
11777 return CMD_SUCCESS
;
11780 DEFUN (bgp_damp_set
,
11782 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
11783 "BGP Specific commands\n"
11784 "Enable route-flap dampening\n"
11785 "Half-life time for the penalty\n"
11786 "Value to start reusing a route\n"
11787 "Value to start suppressing a route\n"
11788 "Maximum duration to suppress a stable route\n")
11790 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11791 int idx_half_life
= 2;
11793 int idx_suppress
= 4;
11794 int idx_max_suppress
= 5;
11795 int half
= DEFAULT_HALF_LIFE
* 60;
11796 int reuse
= DEFAULT_REUSE
;
11797 int suppress
= DEFAULT_SUPPRESS
;
11798 int max
= 4 * half
;
11801 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
11802 reuse
= atoi(argv
[idx_reuse
]->arg
);
11803 suppress
= atoi(argv
[idx_suppress
]->arg
);
11804 max
= atoi(argv
[idx_max_suppress
]->arg
) * 60;
11805 } else if (argc
== 3) {
11806 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
11810 if (suppress
< reuse
) {
11812 "Suppress value cannot be less than reuse value \n");
11816 return bgp_damp_enable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
), half
,
11817 reuse
, suppress
, max
);
11820 DEFUN (bgp_damp_unset
,
11821 bgp_damp_unset_cmd
,
11822 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
11824 "BGP Specific commands\n"
11825 "Enable route-flap dampening\n"
11826 "Half-life time for the penalty\n"
11827 "Value to start reusing a route\n"
11828 "Value to start suppressing a route\n"
11829 "Maximum duration to suppress a stable route\n")
11831 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11832 return bgp_damp_disable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
));
11835 /* Display specified route of BGP table. */
11836 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
11837 const char *ip_str
, afi_t afi
, safi_t safi
,
11838 struct prefix_rd
*prd
, int prefix_check
)
11841 struct prefix match
;
11842 struct bgp_node
*rn
;
11843 struct bgp_node
*rm
;
11844 struct bgp_path_info
*pi
;
11845 struct bgp_path_info
*pi_temp
;
11847 struct bgp_table
*table
;
11849 /* BGP structure lookup. */
11851 bgp
= bgp_lookup_by_name(view_name
);
11853 vty_out(vty
, "%% Can't find BGP instance %s\n",
11855 return CMD_WARNING
;
11858 bgp
= bgp_get_default();
11860 vty_out(vty
, "%% No BGP process is configured\n");
11861 return CMD_WARNING
;
11865 /* Check IP address argument. */
11866 ret
= str2prefix(ip_str
, &match
);
11868 vty_out(vty
, "%% address is malformed\n");
11869 return CMD_WARNING
;
11872 match
.family
= afi2family(afi
);
11874 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
11875 || (safi
== SAFI_EVPN
)) {
11876 for (rn
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); rn
;
11877 rn
= bgp_route_next(rn
)) {
11878 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
11880 table
= bgp_node_get_bgp_table_info(rn
);
11883 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
11887 || rm
->p
.prefixlen
== match
.prefixlen
) {
11888 pi
= bgp_node_get_bgp_path_info(rm
);
11890 if (pi
->extra
&& pi
->extra
->damp_info
) {
11891 pi_temp
= pi
->next
;
11892 bgp_damp_info_free(
11893 pi
->extra
->damp_info
,
11901 bgp_unlock_node(rm
);
11904 if ((rn
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
))
11907 || rn
->p
.prefixlen
== match
.prefixlen
) {
11908 pi
= bgp_node_get_bgp_path_info(rn
);
11910 if (pi
->extra
&& pi
->extra
->damp_info
) {
11911 pi_temp
= pi
->next
;
11912 bgp_damp_info_free(
11913 pi
->extra
->damp_info
,
11921 bgp_unlock_node(rn
);
11925 return CMD_SUCCESS
;
11928 DEFUN (clear_ip_bgp_dampening
,
11929 clear_ip_bgp_dampening_cmd
,
11930 "clear ip bgp dampening",
11934 "Clear route flap dampening information\n")
11936 bgp_damp_info_clean();
11937 return CMD_SUCCESS
;
11940 DEFUN (clear_ip_bgp_dampening_prefix
,
11941 clear_ip_bgp_dampening_prefix_cmd
,
11942 "clear ip bgp dampening A.B.C.D/M",
11946 "Clear route flap dampening information\n"
11949 int idx_ipv4_prefixlen
= 4;
11950 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
11951 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
11954 DEFUN (clear_ip_bgp_dampening_address
,
11955 clear_ip_bgp_dampening_address_cmd
,
11956 "clear ip bgp dampening A.B.C.D",
11960 "Clear route flap dampening information\n"
11961 "Network to clear damping information\n")
11964 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
11965 SAFI_UNICAST
, NULL
, 0);
11968 DEFUN (clear_ip_bgp_dampening_address_mask
,
11969 clear_ip_bgp_dampening_address_mask_cmd
,
11970 "clear ip bgp dampening A.B.C.D A.B.C.D",
11974 "Clear route flap dampening information\n"
11975 "Network to clear damping information\n"
11979 int idx_ipv4_2
= 5;
11981 char prefix_str
[BUFSIZ
];
11983 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
11986 vty_out(vty
, "%% Inconsistent address and mask\n");
11987 return CMD_WARNING
;
11990 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
11994 static void show_bgp_peerhash_entry(struct hash_bucket
*bucket
, void *arg
)
11996 struct vty
*vty
= arg
;
11997 struct peer
*peer
= bucket
->data
;
11998 char buf
[SU_ADDRSTRLEN
];
12000 vty_out(vty
, "\tPeer: %s %s\n", peer
->host
,
12001 sockunion2str(&peer
->su
, buf
, sizeof(buf
)));
12004 DEFUN (show_bgp_peerhash
,
12005 show_bgp_peerhash_cmd
,
12006 "show bgp peerhash",
12009 "Display information about the BGP peerhash\n")
12011 struct list
*instances
= bm
->bgp
;
12012 struct listnode
*node
;
12015 for (ALL_LIST_ELEMENTS_RO(instances
, node
, bgp
)) {
12016 vty_out(vty
, "BGP: %s\n", bgp
->name
);
12017 hash_iterate(bgp
->peerhash
, show_bgp_peerhash_entry
,
12021 return CMD_SUCCESS
;
12024 /* also used for encap safi */
12025 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
12026 afi_t afi
, safi_t safi
)
12028 struct bgp_node
*prn
;
12029 struct bgp_node
*rn
;
12030 struct bgp_table
*table
;
12032 struct prefix_rd
*prd
;
12033 struct bgp_static
*bgp_static
;
12034 mpls_label_t label
;
12035 char buf
[SU_ADDRSTRLEN
];
12036 char rdbuf
[RD_ADDRSTRLEN
];
12038 /* Network configuration. */
12039 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
12040 prn
= bgp_route_next(prn
)) {
12041 table
= bgp_node_get_bgp_table_info(prn
);
12045 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
12046 bgp_static
= bgp_node_get_bgp_static_info(rn
);
12047 if (bgp_static
== NULL
)
12051 prd
= (struct prefix_rd
*)&prn
->p
;
12053 /* "network" configuration display. */
12054 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
12055 label
= decode_label(&bgp_static
->label
);
12057 vty_out(vty
, " network %s/%d rd %s",
12058 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
12060 p
->prefixlen
, rdbuf
);
12061 if (safi
== SAFI_MPLS_VPN
)
12062 vty_out(vty
, " label %u", label
);
12064 if (bgp_static
->rmap
.name
)
12065 vty_out(vty
, " route-map %s",
12066 bgp_static
->rmap
.name
);
12068 if (bgp_static
->backdoor
)
12069 vty_out(vty
, " backdoor");
12071 vty_out(vty
, "\n");
12076 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
12077 afi_t afi
, safi_t safi
)
12079 struct bgp_node
*prn
;
12080 struct bgp_node
*rn
;
12081 struct bgp_table
*table
;
12083 struct prefix_rd
*prd
;
12084 struct bgp_static
*bgp_static
;
12085 char buf
[PREFIX_STRLEN
* 2];
12086 char buf2
[SU_ADDRSTRLEN
];
12087 char rdbuf
[RD_ADDRSTRLEN
];
12089 /* Network configuration. */
12090 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
12091 prn
= bgp_route_next(prn
)) {
12092 table
= bgp_node_get_bgp_table_info(prn
);
12096 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
12097 bgp_static
= bgp_node_get_bgp_static_info(rn
);
12098 if (bgp_static
== NULL
)
12101 char *macrouter
= NULL
;
12104 if (bgp_static
->router_mac
)
12105 macrouter
= prefix_mac2str(
12106 bgp_static
->router_mac
, NULL
, 0);
12107 if (bgp_static
->eth_s_id
)
12108 esi
= esi2str(bgp_static
->eth_s_id
);
12110 prd
= (struct prefix_rd
*)&prn
->p
;
12112 /* "network" configuration display. */
12113 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
12114 if (p
->u
.prefix_evpn
.route_type
== 5) {
12115 char local_buf
[PREFIX_STRLEN
];
12116 uint8_t family
= is_evpn_prefix_ipaddr_v4((
12117 struct prefix_evpn
*)p
)
12121 &p
->u
.prefix_evpn
.prefix_addr
.ip
.ip
.addr
,
12122 local_buf
, PREFIX_STRLEN
);
12123 sprintf(buf
, "%s/%u", local_buf
,
12124 p
->u
.prefix_evpn
.prefix_addr
.ip_prefix_length
);
12126 prefix2str(p
, buf
, sizeof(buf
));
12129 if (bgp_static
->gatewayIp
.family
== AF_INET
12130 || bgp_static
->gatewayIp
.family
== AF_INET6
)
12131 inet_ntop(bgp_static
->gatewayIp
.family
,
12132 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
12135 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
12137 p
->u
.prefix_evpn
.prefix_addr
.eth_tag
,
12138 decode_label(&bgp_static
->label
), esi
, buf2
,
12141 XFREE(MTYPE_TMP
, macrouter
);
12142 XFREE(MTYPE_TMP
, esi
);
12147 /* Configuration of static route announcement and aggregate
12149 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12152 struct bgp_node
*rn
;
12154 struct bgp_static
*bgp_static
;
12155 struct bgp_aggregate
*bgp_aggregate
;
12156 char buf
[SU_ADDRSTRLEN
];
12158 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
12159 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
12163 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
12164 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
12168 /* Network configuration. */
12169 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
12170 rn
= bgp_route_next(rn
)) {
12171 bgp_static
= bgp_node_get_bgp_static_info(rn
);
12172 if (bgp_static
== NULL
)
12177 /* "network" configuration display. */
12178 if (bgp_option_check(BGP_OPT_CONFIG_CISCO
) && afi
== AFI_IP
) {
12179 uint32_t destination
;
12180 struct in_addr netmask
;
12182 destination
= ntohl(p
->u
.prefix4
.s_addr
);
12183 masklen2ip(p
->prefixlen
, &netmask
);
12184 vty_out(vty
, " network %s",
12185 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
12188 if ((IN_CLASSC(destination
) && p
->prefixlen
== 24)
12189 || (IN_CLASSB(destination
) && p
->prefixlen
== 16)
12190 || (IN_CLASSA(destination
) && p
->prefixlen
== 8)
12191 || p
->u
.prefix4
.s_addr
== 0) {
12192 /* Natural mask is not display. */
12194 vty_out(vty
, " mask %s", inet_ntoa(netmask
));
12196 vty_out(vty
, " network %s/%d",
12197 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
12202 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
12203 vty_out(vty
, " label-index %u",
12204 bgp_static
->label_index
);
12206 if (bgp_static
->rmap
.name
)
12207 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
12209 if (bgp_static
->backdoor
)
12210 vty_out(vty
, " backdoor");
12212 vty_out(vty
, "\n");
12215 /* Aggregate-address configuration. */
12216 for (rn
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); rn
;
12217 rn
= bgp_route_next(rn
)) {
12218 bgp_aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
12219 if (bgp_aggregate
== NULL
)
12224 if (bgp_option_check(BGP_OPT_CONFIG_CISCO
) && afi
== AFI_IP
) {
12225 struct in_addr netmask
;
12227 masklen2ip(p
->prefixlen
, &netmask
);
12228 vty_out(vty
, " aggregate-address %s %s",
12229 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
12231 inet_ntoa(netmask
));
12233 vty_out(vty
, " aggregate-address %s/%d",
12234 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
12239 if (bgp_aggregate
->as_set
)
12240 vty_out(vty
, " as-set");
12242 if (bgp_aggregate
->summary_only
)
12243 vty_out(vty
, " summary-only");
12245 vty_out(vty
, "\n");
12249 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12252 struct bgp_node
*rn
;
12253 struct bgp_distance
*bdistance
;
12255 /* Distance configuration. */
12256 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
12257 && bgp
->distance_local
[afi
][safi
]
12258 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
12259 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
12260 || bgp
->distance_local
[afi
][safi
]
12261 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
12262 vty_out(vty
, " distance bgp %d %d %d\n",
12263 bgp
->distance_ebgp
[afi
][safi
],
12264 bgp
->distance_ibgp
[afi
][safi
],
12265 bgp
->distance_local
[afi
][safi
]);
12268 for (rn
= bgp_table_top(bgp_distance_table
[afi
][safi
]); rn
;
12269 rn
= bgp_route_next(rn
)) {
12270 bdistance
= bgp_node_get_bgp_distance_info(rn
);
12271 if (bdistance
!= NULL
) {
12272 char buf
[PREFIX_STRLEN
];
12274 vty_out(vty
, " distance %d %s %s\n",
12275 bdistance
->distance
,
12276 prefix2str(&rn
->p
, buf
, sizeof(buf
)),
12277 bdistance
->access_list
? bdistance
->access_list
12283 /* Allocate routing table structure and install commands. */
12284 void bgp_route_init(void)
12289 /* Init BGP distance table. */
12290 FOREACH_AFI_SAFI (afi
, safi
)
12291 bgp_distance_table
[afi
][safi
] = bgp_table_init(NULL
, afi
, safi
);
12293 /* IPv4 BGP commands. */
12294 install_element(BGP_NODE
, &bgp_table_map_cmd
);
12295 install_element(BGP_NODE
, &bgp_network_cmd
);
12296 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
12298 install_element(BGP_NODE
, &aggregate_address_cmd
);
12299 install_element(BGP_NODE
, &aggregate_address_mask_cmd
);
12300 install_element(BGP_NODE
, &no_aggregate_address_cmd
);
12301 install_element(BGP_NODE
, &no_aggregate_address_mask_cmd
);
12303 /* IPv4 unicast configuration. */
12304 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
12305 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
12306 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
12308 install_element(BGP_IPV4_NODE
, &aggregate_address_cmd
);
12309 install_element(BGP_IPV4_NODE
, &aggregate_address_mask_cmd
);
12310 install_element(BGP_IPV4_NODE
, &no_aggregate_address_cmd
);
12311 install_element(BGP_IPV4_NODE
, &no_aggregate_address_mask_cmd
);
12313 /* IPv4 multicast configuration. */
12314 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
12315 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
12316 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
12317 install_element(BGP_IPV4M_NODE
, &aggregate_address_cmd
);
12318 install_element(BGP_IPV4M_NODE
, &aggregate_address_mask_cmd
);
12319 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_cmd
);
12320 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_mask_cmd
);
12322 /* IPv4 labeled-unicast configuration. */
12323 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
12324 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
12325 install_element(VIEW_NODE
, &show_ip_bgp_json_cmd
);
12326 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
12327 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
12329 install_element(VIEW_NODE
,
12330 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
12331 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
12332 install_element(VIEW_NODE
,
12333 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
12334 #ifdef KEEP_OLD_VPN_COMMANDS
12335 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
12336 #endif /* KEEP_OLD_VPN_COMMANDS */
12337 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
12338 install_element(VIEW_NODE
,
12339 &show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd
);
12341 /* BGP dampening clear commands */
12342 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
12343 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
12345 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
12346 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
12349 install_element(ENABLE_NODE
,
12350 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
12351 #ifdef KEEP_OLD_VPN_COMMANDS
12352 install_element(ENABLE_NODE
,
12353 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
12354 #endif /* KEEP_OLD_VPN_COMMANDS */
12356 /* New config IPv6 BGP commands. */
12357 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
12358 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
12359 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
12361 install_element(BGP_IPV6_NODE
, &ipv6_aggregate_address_cmd
);
12362 install_element(BGP_IPV6_NODE
, &no_ipv6_aggregate_address_cmd
);
12364 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
12366 install_element(BGP_NODE
, &bgp_distance_cmd
);
12367 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
12368 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
12369 install_element(BGP_NODE
, &no_bgp_distance_source_cmd
);
12370 install_element(BGP_NODE
, &bgp_distance_source_access_list_cmd
);
12371 install_element(BGP_NODE
, &no_bgp_distance_source_access_list_cmd
);
12372 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
12373 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
12374 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
12375 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_cmd
);
12376 install_element(BGP_IPV4_NODE
, &bgp_distance_source_access_list_cmd
);
12377 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_access_list_cmd
);
12378 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
12379 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
12380 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
12381 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_source_cmd
);
12382 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_access_list_cmd
);
12383 install_element(BGP_IPV4M_NODE
,
12384 &no_bgp_distance_source_access_list_cmd
);
12385 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
12386 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
12387 install_element(BGP_IPV6_NODE
, &ipv6_bgp_distance_source_cmd
);
12388 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_distance_source_cmd
);
12389 install_element(BGP_IPV6_NODE
,
12390 &ipv6_bgp_distance_source_access_list_cmd
);
12391 install_element(BGP_IPV6_NODE
,
12392 &no_ipv6_bgp_distance_source_access_list_cmd
);
12393 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
12394 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
12395 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_distance_source_cmd
);
12396 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_distance_source_cmd
);
12397 install_element(BGP_IPV6M_NODE
,
12398 &ipv6_bgp_distance_source_access_list_cmd
);
12399 install_element(BGP_IPV6M_NODE
,
12400 &no_ipv6_bgp_distance_source_access_list_cmd
);
12402 install_element(BGP_NODE
, &bgp_damp_set_cmd
);
12403 install_element(BGP_NODE
, &bgp_damp_unset_cmd
);
12404 install_element(BGP_IPV4_NODE
, &bgp_damp_set_cmd
);
12405 install_element(BGP_IPV4_NODE
, &bgp_damp_unset_cmd
);
12407 /* IPv4 Multicast Mode */
12408 install_element(BGP_IPV4M_NODE
, &bgp_damp_set_cmd
);
12409 install_element(BGP_IPV4M_NODE
, &bgp_damp_unset_cmd
);
12411 /* Large Communities */
12412 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
12413 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
12415 /* show bgp ipv4 flowspec detailed */
12416 install_element(VIEW_NODE
, &show_ip_bgp_flowspec_routes_detailed_cmd
);
12418 install_element(VIEW_NODE
, &show_bgp_peerhash_cmd
);
12421 void bgp_route_finish(void)
12426 FOREACH_AFI_SAFI (afi
, safi
) {
12427 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
12428 bgp_distance_table
[afi
][safi
] = NULL
;