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 ((p
->family
== AF_INET
) &&
1858 (!bgp_subgrp_multiaccess_check_v4(
1861 subgroup_announce_reset_nhop(
1862 (peer_cap_enhe(peer
, afi
, safi
)
1867 if ((p
->family
== AF_INET6
) &&
1868 (!bgp_subgrp_multiaccess_check_v6(
1869 piattr
->mp_nexthop_global
,
1871 subgroup_announce_reset_nhop(
1872 (peer_cap_enhe(peer
, afi
, safi
)
1879 } else if (CHECK_FLAG(pi
->flags
, BGP_PATH_ANNC_NH_SELF
)) {
1881 * This flag is used for leaked vpn-vrf routes
1883 int family
= p
->family
;
1885 if (peer_cap_enhe(peer
, afi
, safi
))
1888 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1890 "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
1891 __func__
, family2str(family
));
1892 subgroup_announce_reset_nhop(family
, attr
);
1895 /* If IPv6/MP and nexthop does not have any override and happens
1897 * be a link-local address, reset it so that we don't pass along
1899 * source's link-local IPv6 address to recipients who may not be
1901 * the same interface.
1903 if (p
->family
== AF_INET6
|| peer_cap_enhe(peer
, afi
, safi
)) {
1904 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
))
1905 subgroup_announce_reset_nhop(AF_INET6
, attr
);
1912 void bgp_best_selection(struct bgp
*bgp
, struct bgp_node
*rn
,
1913 struct bgp_maxpaths_cfg
*mpath_cfg
,
1914 struct bgp_path_info_pair
*result
, afi_t afi
,
1917 struct bgp_path_info
*new_select
;
1918 struct bgp_path_info
*old_select
;
1919 struct bgp_path_info
*pi
;
1920 struct bgp_path_info
*pi1
;
1921 struct bgp_path_info
*pi2
;
1922 struct bgp_path_info
*nextpi
= NULL
;
1923 int paths_eq
, do_mpath
, debug
;
1924 struct list mp_list
;
1925 char pfx_buf
[PREFIX2STR_BUFFER
];
1926 char path_buf
[PATH_ADDPATH_STR_BUFFER
];
1928 bgp_mp_list_init(&mp_list
);
1930 (mpath_cfg
->maxpaths_ebgp
> 1 || mpath_cfg
->maxpaths_ibgp
> 1);
1932 debug
= bgp_debug_bestpath(&rn
->p
);
1935 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
1937 /* bgp deterministic-med */
1939 if (bgp_flag_check(bgp
, BGP_FLAG_DETERMINISTIC_MED
)) {
1941 /* Clear BGP_PATH_DMED_SELECTED for all paths */
1942 for (pi1
= bgp_node_get_bgp_path_info(rn
); pi1
;
1944 bgp_path_info_unset_flag(rn
, pi1
,
1945 BGP_PATH_DMED_SELECTED
);
1947 for (pi1
= bgp_node_get_bgp_path_info(rn
); pi1
;
1949 if (CHECK_FLAG(pi1
->flags
, BGP_PATH_DMED_CHECK
))
1951 if (BGP_PATH_HOLDDOWN(pi1
))
1953 if (pi1
->peer
!= bgp
->peer_self
)
1954 if (pi1
->peer
->status
!= Established
)
1959 for (pi2
= pi1
->next
; pi2
; pi2
= pi2
->next
) {
1960 if (CHECK_FLAG(pi2
->flags
,
1961 BGP_PATH_DMED_CHECK
))
1963 if (BGP_PATH_HOLDDOWN(pi2
))
1965 if (pi2
->peer
!= bgp
->peer_self
1968 PEER_STATUS_NSF_WAIT
))
1969 if (pi2
->peer
->status
1973 if (!aspath_cmp_left(pi1
->attr
->aspath
,
1975 && !aspath_cmp_left_confed(
1980 if (bgp_path_info_cmp(
1981 bgp
, pi2
, new_select
,
1982 &paths_eq
, mpath_cfg
, debug
,
1983 pfx_buf
, afi
, safi
)) {
1984 bgp_path_info_unset_flag(
1986 BGP_PATH_DMED_SELECTED
);
1990 bgp_path_info_set_flag(
1991 rn
, pi2
, BGP_PATH_DMED_CHECK
);
1994 bgp_path_info_set_flag(rn
, new_select
,
1995 BGP_PATH_DMED_CHECK
);
1996 bgp_path_info_set_flag(rn
, new_select
,
1997 BGP_PATH_DMED_SELECTED
);
2000 bgp_path_info_path_with_addpath_rx_str(
2001 new_select
, path_buf
);
2002 zlog_debug("%s: %s is the bestpath from AS %u",
2004 aspath_get_first_as(
2005 new_select
->attr
->aspath
));
2010 /* Check old selected route and new selected route. */
2013 for (pi
= bgp_node_get_bgp_path_info(rn
);
2014 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2015 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
2018 if (BGP_PATH_HOLDDOWN(pi
)) {
2019 /* reap REMOVED routes, if needs be
2020 * selected route must stay for a while longer though
2022 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
2023 && (pi
!= old_select
))
2024 bgp_path_info_reap(rn
, pi
);
2027 zlog_debug("%s: pi %p in holddown", __func__
,
2033 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2034 && !CHECK_FLAG(pi
->peer
->sflags
, PEER_STATUS_NSF_WAIT
))
2035 if (pi
->peer
->status
!= Established
) {
2039 "%s: pi %p non self peer %s not estab state",
2040 __func__
, pi
, pi
->peer
->host
);
2045 if (bgp_flag_check(bgp
, BGP_FLAG_DETERMINISTIC_MED
)
2046 && (!CHECK_FLAG(pi
->flags
, BGP_PATH_DMED_SELECTED
))) {
2047 bgp_path_info_unset_flag(rn
, pi
, BGP_PATH_DMED_CHECK
);
2049 zlog_debug("%s: pi %p dmed", __func__
, pi
);
2053 bgp_path_info_unset_flag(rn
, pi
, BGP_PATH_DMED_CHECK
);
2055 if (bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
, mpath_cfg
,
2056 debug
, pfx_buf
, afi
, safi
)) {
2061 /* Now that we know which path is the bestpath see if any of the other
2063 * qualify as multipaths
2067 bgp_path_info_path_with_addpath_rx_str(new_select
,
2070 sprintf(path_buf
, "NONE");
2072 "%s: After path selection, newbest is %s oldbest was %s",
2074 old_select
? old_select
->peer
->host
: "NONE");
2077 if (do_mpath
&& new_select
) {
2078 for (pi
= bgp_node_get_bgp_path_info(rn
);
2079 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2082 bgp_path_info_path_with_addpath_rx_str(
2085 if (pi
== new_select
) {
2088 "%s: %s is the bestpath, add to the multipath list",
2090 bgp_mp_list_add(&mp_list
, pi
);
2094 if (BGP_PATH_HOLDDOWN(pi
))
2097 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2098 && !CHECK_FLAG(pi
->peer
->sflags
,
2099 PEER_STATUS_NSF_WAIT
))
2100 if (pi
->peer
->status
!= Established
)
2103 if (!bgp_path_info_nexthop_cmp(pi
, new_select
)) {
2106 "%s: %s has the same nexthop as the bestpath, skip it",
2111 bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
,
2112 mpath_cfg
, debug
, pfx_buf
, afi
, safi
);
2117 "%s: %s is equivalent to the bestpath, add to the multipath list",
2119 bgp_mp_list_add(&mp_list
, pi
);
2124 bgp_path_info_mpath_update(rn
, new_select
, old_select
, &mp_list
,
2126 bgp_path_info_mpath_aggregate_update(new_select
, old_select
);
2127 bgp_mp_list_clear(&mp_list
);
2129 bgp_addpath_update_ids(bgp
, rn
, afi
, safi
);
2131 result
->old
= old_select
;
2132 result
->new = new_select
;
2138 * A new route/change in bestpath of an existing route. Evaluate the path
2139 * for advertisement to the subgroup.
2141 int subgroup_process_announce_selected(struct update_subgroup
*subgrp
,
2142 struct bgp_path_info
*selected
,
2143 struct bgp_node
*rn
,
2144 uint32_t addpath_tx_id
)
2147 struct peer
*onlypeer
;
2153 afi
= SUBGRP_AFI(subgrp
);
2154 safi
= SUBGRP_SAFI(subgrp
);
2155 onlypeer
= ((SUBGRP_PCOUNT(subgrp
) == 1) ? (SUBGRP_PFIRST(subgrp
))->peer
2158 if (BGP_DEBUG(update
, UPDATE_OUT
)) {
2159 char buf_prefix
[PREFIX_STRLEN
];
2160 prefix2str(p
, buf_prefix
, sizeof(buf_prefix
));
2161 zlog_debug("%s: p=%s, selected=%p", __func__
, buf_prefix
,
2165 /* First update is deferred until ORF or ROUTE-REFRESH is received */
2166 if (onlypeer
&& CHECK_FLAG(onlypeer
->af_sflags
[afi
][safi
],
2167 PEER_STATUS_ORF_WAIT_REFRESH
))
2170 memset(&attr
, 0, sizeof(struct attr
));
2171 /* It's initialized in bgp_announce_check() */
2173 /* Announcement to the subgroup. If the route is filtered withdraw it.
2176 if (subgroup_announce_check(rn
, selected
, subgrp
, p
, &attr
))
2177 bgp_adj_out_set_subgroup(rn
, subgrp
, &attr
, selected
);
2179 bgp_adj_out_unset_subgroup(rn
, subgrp
, 1,
2183 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2185 bgp_adj_out_unset_subgroup(rn
, subgrp
, 1, addpath_tx_id
);
2192 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2193 * This is called at the end of route processing.
2195 void bgp_zebra_clear_route_change_flags(struct bgp_node
*rn
)
2197 struct bgp_path_info
*pi
;
2199 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
2200 if (BGP_PATH_HOLDDOWN(pi
))
2202 UNSET_FLAG(pi
->flags
, BGP_PATH_IGP_CHANGED
);
2203 UNSET_FLAG(pi
->flags
, BGP_PATH_ATTR_CHANGED
);
2208 * Has the route changed from the RIB's perspective? This is invoked only
2209 * if the route selection returns the same best route as earlier - to
2210 * determine if we need to update zebra or not.
2212 int bgp_zebra_has_route_changed(struct bgp_node
*rn
,
2213 struct bgp_path_info
*selected
)
2215 struct bgp_path_info
*mpinfo
;
2217 /* If this is multipath, check all selected paths for any nexthop
2218 * change or attribute change. Some attribute changes (e.g., community)
2219 * aren't of relevance to the RIB, but we'll update zebra to ensure
2220 * we handle the case of BGP nexthop change. This is the behavior
2221 * when the best path has an attribute change anyway.
2223 if (CHECK_FLAG(selected
->flags
, BGP_PATH_IGP_CHANGED
)
2224 || CHECK_FLAG(selected
->flags
, BGP_PATH_MULTIPATH_CHG
))
2228 * If this is multipath, check all selected paths for any nexthop change
2230 for (mpinfo
= bgp_path_info_mpath_first(selected
); mpinfo
;
2231 mpinfo
= bgp_path_info_mpath_next(mpinfo
)) {
2232 if (CHECK_FLAG(mpinfo
->flags
, BGP_PATH_IGP_CHANGED
)
2233 || CHECK_FLAG(mpinfo
->flags
, BGP_PATH_ATTR_CHANGED
))
2237 /* Nothing has changed from the RIB's perspective. */
2241 struct bgp_process_queue
{
2243 STAILQ_HEAD(, bgp_node
) pqueue
;
2244 #define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2246 unsigned int queued
;
2250 * old_select = The old best path
2251 * new_select = the new best path
2253 * if (!old_select && new_select)
2254 * We are sending new information on.
2256 * if (old_select && new_select) {
2257 * if (new_select != old_select)
2258 * We have a new best path send a change
2260 * We've received a update with new attributes that needs
2264 * if (old_select && !new_select)
2265 * We have no eligible route that we can announce or the rn
2268 static void bgp_process_main_one(struct bgp
*bgp
, struct bgp_node
*rn
,
2269 afi_t afi
, safi_t safi
)
2271 struct bgp_path_info
*new_select
;
2272 struct bgp_path_info
*old_select
;
2273 struct bgp_path_info_pair old_and_new
;
2274 char pfx_buf
[PREFIX2STR_BUFFER
];
2277 /* Is it end of initial update? (after startup) */
2279 quagga_timestamp(3, bgp
->update_delay_zebra_resume_time
,
2280 sizeof(bgp
->update_delay_zebra_resume_time
));
2282 bgp
->main_zebra_update_hold
= 0;
2283 FOREACH_AFI_SAFI (afi
, safi
) {
2284 if (bgp_fibupd_safi(safi
))
2285 bgp_zebra_announce_table(bgp
, afi
, safi
);
2287 bgp
->main_peers_update_hold
= 0;
2289 bgp_start_routeadv(bgp
);
2293 struct prefix
*p
= &rn
->p
;
2295 debug
= bgp_debug_bestpath(&rn
->p
);
2297 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
2298 zlog_debug("%s: p=%s afi=%s, safi=%s start", __func__
, pfx_buf
,
2299 afi2str(afi
), safi2str(safi
));
2302 /* Best path selection. */
2303 bgp_best_selection(bgp
, rn
, &bgp
->maxpaths
[afi
][safi
], &old_and_new
,
2305 old_select
= old_and_new
.old
;
2306 new_select
= old_and_new
.new;
2308 /* Do we need to allocate or free labels?
2309 * Right now, since we only deal with per-prefix labels, it is not
2310 * necessary to do this upon changes to best path. Exceptions:
2311 * - label index has changed -> recalculate resulting label
2312 * - path_info sub_type changed -> switch to/from implicit-null
2313 * - no valid label (due to removed static label binding) -> get new one
2315 if (bgp
->allocate_mpls_labels
[afi
][safi
]) {
2318 || bgp_label_index_differs(new_select
, old_select
)
2319 || new_select
->sub_type
!= old_select
->sub_type
2320 || !bgp_is_valid_label(&rn
->local_label
)) {
2321 /* Enforced penultimate hop popping:
2322 * implicit-null for local routes, aggregate
2323 * and redistributed routes
2325 if (new_select
->sub_type
== BGP_ROUTE_STATIC
2326 || new_select
->sub_type
2327 == BGP_ROUTE_AGGREGATE
2328 || new_select
->sub_type
2329 == BGP_ROUTE_REDISTRIBUTE
) {
2332 BGP_NODE_REGISTERED_FOR_LABEL
))
2333 bgp_unregister_for_label(rn
);
2334 label_ntop(MPLS_LABEL_IMPLICIT_NULL
, 1,
2336 bgp_set_valid_label(&rn
->local_label
);
2338 bgp_register_for_label(rn
, new_select
);
2340 } else if (CHECK_FLAG(rn
->flags
,
2341 BGP_NODE_REGISTERED_FOR_LABEL
)) {
2342 bgp_unregister_for_label(rn
);
2344 } else if (CHECK_FLAG(rn
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
)) {
2345 bgp_unregister_for_label(rn
);
2349 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
2351 "%s: p=%s afi=%s, safi=%s, old_select=%p, new_select=%p",
2352 __func__
, pfx_buf
, afi2str(afi
), safi2str(safi
),
2353 old_select
, new_select
);
2356 /* If best route remains the same and this is not due to user-initiated
2357 * clear, see exactly what needs to be done.
2359 if (old_select
&& old_select
== new_select
2360 && !CHECK_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
)
2361 && !CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
2362 && !bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
2363 if (bgp_zebra_has_route_changed(rn
, old_select
)) {
2365 vnc_import_bgp_add_route(bgp
, p
, old_select
);
2366 vnc_import_bgp_exterior_add_route(bgp
, p
, old_select
);
2368 if (bgp_fibupd_safi(safi
)
2369 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2371 if (new_select
->type
== ZEBRA_ROUTE_BGP
2372 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2373 || new_select
->sub_type
2374 == BGP_ROUTE_IMPORTED
))
2376 bgp_zebra_announce(rn
, p
, old_select
,
2380 UNSET_FLAG(old_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
2381 bgp_zebra_clear_route_change_flags(rn
);
2383 /* If there is a change of interest to peers, reannounce the
2385 if (CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
2386 || CHECK_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
)) {
2387 group_announce_route(bgp
, afi
, safi
, rn
, new_select
);
2389 /* unicast routes must also be annouced to
2390 * labeled-unicast update-groups */
2391 if (safi
== SAFI_UNICAST
)
2392 group_announce_route(bgp
, afi
,
2393 SAFI_LABELED_UNICAST
, rn
,
2396 UNSET_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
);
2397 UNSET_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
);
2400 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2404 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2406 UNSET_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
);
2408 /* bestpath has changed; bump version */
2409 if (old_select
|| new_select
) {
2410 bgp_bump_version(rn
);
2412 if (!bgp
->t_rmap_def_originate_eval
) {
2416 update_group_refresh_default_originate_route_map
,
2417 bgp
, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER
,
2418 &bgp
->t_rmap_def_originate_eval
);
2423 bgp_path_info_unset_flag(rn
, old_select
, BGP_PATH_SELECTED
);
2426 zlog_debug("%s: setting SELECTED flag", __func__
);
2427 bgp_path_info_set_flag(rn
, new_select
, BGP_PATH_SELECTED
);
2428 bgp_path_info_unset_flag(rn
, new_select
, BGP_PATH_ATTR_CHANGED
);
2429 UNSET_FLAG(new_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
2433 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2434 if (old_select
!= new_select
) {
2436 vnc_import_bgp_exterior_del_route(bgp
, p
,
2438 vnc_import_bgp_del_route(bgp
, p
, old_select
);
2441 vnc_import_bgp_exterior_add_route(bgp
, p
,
2443 vnc_import_bgp_add_route(bgp
, p
, new_select
);
2449 group_announce_route(bgp
, afi
, safi
, rn
, new_select
);
2451 /* unicast routes must also be annouced to labeled-unicast update-groups
2453 if (safi
== SAFI_UNICAST
)
2454 group_announce_route(bgp
, afi
, SAFI_LABELED_UNICAST
, rn
,
2458 if (bgp_fibupd_safi(safi
) && (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VIEW
)
2459 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2460 if (new_select
&& new_select
->type
== ZEBRA_ROUTE_BGP
2461 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2462 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
2463 || new_select
->sub_type
== BGP_ROUTE_IMPORTED
)) {
2465 /* if this is an evpn imported type-5 prefix,
2466 * we need to withdraw the route first to clear
2467 * the nh neigh and the RMAC entry.
2470 is_route_parent_evpn(old_select
))
2471 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2473 bgp_zebra_announce(rn
, p
, new_select
, bgp
, afi
, safi
);
2475 /* Withdraw the route from the kernel. */
2476 if (old_select
&& old_select
->type
== ZEBRA_ROUTE_BGP
2477 && (old_select
->sub_type
== BGP_ROUTE_NORMAL
2478 || old_select
->sub_type
== BGP_ROUTE_AGGREGATE
2479 || old_select
->sub_type
== BGP_ROUTE_IMPORTED
))
2481 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2485 /* advertise/withdraw type-5 routes */
2486 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2487 if (advertise_type5_routes(bgp
, afi
) &&
2489 is_route_injectable_into_evpn(new_select
)) {
2491 /* apply the route-map */
2492 if (bgp
->adv_cmd_rmap
[afi
][safi
].map
) {
2495 ret
= route_map_apply(
2496 bgp
->adv_cmd_rmap
[afi
][safi
].map
,
2497 &rn
->p
, RMAP_BGP
, new_select
);
2498 if (ret
== RMAP_MATCH
)
2499 bgp_evpn_advertise_type5_route(
2500 bgp
, &rn
->p
, new_select
->attr
,
2503 bgp_evpn_withdraw_type5_route(
2504 bgp
, &rn
->p
, afi
, safi
);
2506 bgp_evpn_advertise_type5_route(bgp
,
2512 } else if (advertise_type5_routes(bgp
, afi
) &&
2514 is_route_injectable_into_evpn(old_select
))
2515 bgp_evpn_withdraw_type5_route(bgp
, &rn
->p
, afi
, safi
);
2518 /* Clear any route change flags. */
2519 bgp_zebra_clear_route_change_flags(rn
);
2521 /* Reap old select bgp_path_info, if it has been removed */
2522 if (old_select
&& CHECK_FLAG(old_select
->flags
, BGP_PATH_REMOVED
))
2523 bgp_path_info_reap(rn
, old_select
);
2525 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2529 static wq_item_status
bgp_process_wq(struct work_queue
*wq
, void *data
)
2531 struct bgp_process_queue
*pqnode
= data
;
2532 struct bgp
*bgp
= pqnode
->bgp
;
2533 struct bgp_table
*table
;
2534 struct bgp_node
*rn
;
2537 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)) {
2538 bgp_process_main_one(bgp
, NULL
, 0, 0);
2539 /* should always have dedicated wq call */
2540 assert(STAILQ_FIRST(&pqnode
->pqueue
) == NULL
);
2544 while (!STAILQ_EMPTY(&pqnode
->pqueue
)) {
2545 rn
= STAILQ_FIRST(&pqnode
->pqueue
);
2546 STAILQ_REMOVE_HEAD(&pqnode
->pqueue
, pq
);
2547 STAILQ_NEXT(rn
, pq
) = NULL
; /* complete unlink */
2548 table
= bgp_node_table(rn
);
2549 /* note, new RNs may be added as part of processing */
2550 bgp_process_main_one(bgp
, rn
, table
->afi
, table
->safi
);
2552 bgp_unlock_node(rn
);
2553 bgp_table_unlock(table
);
2559 static void bgp_processq_del(struct work_queue
*wq
, void *data
)
2561 struct bgp_process_queue
*pqnode
= data
;
2563 bgp_unlock(pqnode
->bgp
);
2565 XFREE(MTYPE_BGP_PROCESS_QUEUE
, pqnode
);
2568 void bgp_process_queue_init(void)
2570 if (!bm
->process_main_queue
)
2571 bm
->process_main_queue
=
2572 work_queue_new(bm
->master
, "process_main_queue");
2574 bm
->process_main_queue
->spec
.workfunc
= &bgp_process_wq
;
2575 bm
->process_main_queue
->spec
.del_item_data
= &bgp_processq_del
;
2576 bm
->process_main_queue
->spec
.max_retries
= 0;
2577 bm
->process_main_queue
->spec
.hold
= 50;
2578 /* Use a higher yield value of 50ms for main queue processing */
2579 bm
->process_main_queue
->spec
.yield
= 50 * 1000L;
2582 static struct bgp_process_queue
*bgp_processq_alloc(struct bgp
*bgp
)
2584 struct bgp_process_queue
*pqnode
;
2586 pqnode
= XCALLOC(MTYPE_BGP_PROCESS_QUEUE
,
2587 sizeof(struct bgp_process_queue
));
2589 /* unlocked in bgp_processq_del */
2590 pqnode
->bgp
= bgp_lock(bgp
);
2591 STAILQ_INIT(&pqnode
->pqueue
);
2596 void bgp_process(struct bgp
*bgp
, struct bgp_node
*rn
, afi_t afi
, safi_t safi
)
2598 #define ARBITRARY_PROCESS_QLEN 10000
2599 struct work_queue
*wq
= bm
->process_main_queue
;
2600 struct bgp_process_queue
*pqnode
;
2601 int pqnode_reuse
= 0;
2603 /* already scheduled for processing? */
2604 if (CHECK_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
2610 /* Add route nodes to an existing work queue item until reaching the
2611 limit only if is from the same BGP view and it's not an EOIU marker
2613 if (work_queue_item_count(wq
)) {
2614 struct work_queue_item
*item
= work_queue_last_item(wq
);
2615 pqnode
= item
->data
;
2617 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)
2618 || pqnode
->bgp
!= bgp
2619 || pqnode
->queued
>= ARBITRARY_PROCESS_QLEN
)
2620 pqnode
= bgp_processq_alloc(bgp
);
2624 pqnode
= bgp_processq_alloc(bgp
);
2625 /* all unlocked in bgp_process_wq */
2626 bgp_table_lock(bgp_node_table(rn
));
2628 SET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2631 /* can't be enqueued twice */
2632 assert(STAILQ_NEXT(rn
, pq
) == NULL
);
2633 STAILQ_INSERT_TAIL(&pqnode
->pqueue
, rn
, pq
);
2637 work_queue_add(wq
, pqnode
);
2642 void bgp_add_eoiu_mark(struct bgp
*bgp
)
2644 struct bgp_process_queue
*pqnode
;
2646 if (bm
->process_main_queue
== NULL
)
2649 pqnode
= bgp_processq_alloc(bgp
);
2651 SET_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
);
2652 work_queue_add(bm
->process_main_queue
, pqnode
);
2655 static int bgp_maximum_prefix_restart_timer(struct thread
*thread
)
2659 peer
= THREAD_ARG(thread
);
2660 peer
->t_pmax_restart
= NULL
;
2662 if (bgp_debug_neighbor_events(peer
))
2664 "%s Maximum-prefix restart timer expired, restore peering",
2667 if ((peer_clear(peer
, NULL
) < 0) && bgp_debug_neighbor_events(peer
))
2668 zlog_debug("%s: %s peer_clear failed",
2669 __PRETTY_FUNCTION__
, peer
->host
);
2674 int bgp_maximum_prefix_overflow(struct peer
*peer
, afi_t afi
, safi_t safi
,
2678 iana_safi_t pkt_safi
;
2680 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX
))
2683 if (peer
->pcount
[afi
][safi
] > peer
->pmax
[afi
][safi
]) {
2684 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2685 PEER_STATUS_PREFIX_LIMIT
)
2690 "%%MAXPFXEXCEED: No. of %s prefix received from %s %ld exceed, "
2692 afi_safi_print(afi
, safi
), peer
->host
,
2693 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2694 SET_FLAG(peer
->af_sflags
[afi
][safi
], PEER_STATUS_PREFIX_LIMIT
);
2696 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2697 PEER_FLAG_MAX_PREFIX_WARNING
))
2700 /* Convert AFI, SAFI to values for packet. */
2701 pkt_afi
= afi_int2iana(afi
);
2702 pkt_safi
= safi_int2iana(safi
);
2706 ndata
[0] = (pkt_afi
>> 8);
2708 ndata
[2] = pkt_safi
;
2709 ndata
[3] = (peer
->pmax
[afi
][safi
] >> 24);
2710 ndata
[4] = (peer
->pmax
[afi
][safi
] >> 16);
2711 ndata
[5] = (peer
->pmax
[afi
][safi
] >> 8);
2712 ndata
[6] = (peer
->pmax
[afi
][safi
]);
2714 SET_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
);
2715 bgp_notify_send_with_data(peer
, BGP_NOTIFY_CEASE
,
2716 BGP_NOTIFY_CEASE_MAX_PREFIX
,
2720 /* Dynamic peers will just close their connection. */
2721 if (peer_dynamic_neighbor(peer
))
2724 /* restart timer start */
2725 if (peer
->pmax_restart
[afi
][safi
]) {
2726 peer
->v_pmax_restart
=
2727 peer
->pmax_restart
[afi
][safi
] * 60;
2729 if (bgp_debug_neighbor_events(peer
))
2731 "%s Maximum-prefix restart timer started for %d secs",
2732 peer
->host
, peer
->v_pmax_restart
);
2734 BGP_TIMER_ON(peer
->t_pmax_restart
,
2735 bgp_maximum_prefix_restart_timer
,
2736 peer
->v_pmax_restart
);
2741 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
2742 PEER_STATUS_PREFIX_LIMIT
);
2744 if (peer
->pcount
[afi
][safi
]
2745 > (peer
->pmax
[afi
][safi
] * peer
->pmax_threshold
[afi
][safi
] / 100)) {
2746 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2747 PEER_STATUS_PREFIX_THRESHOLD
)
2752 "%%MAXPFX: No. of %s prefix received from %s reaches %ld, max %ld",
2753 afi_safi_print(afi
, safi
), peer
->host
,
2754 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2755 SET_FLAG(peer
->af_sflags
[afi
][safi
],
2756 PEER_STATUS_PREFIX_THRESHOLD
);
2758 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
2759 PEER_STATUS_PREFIX_THRESHOLD
);
2763 /* Unconditionally remove the route from the RIB, without taking
2764 * damping into consideration (eg, because the session went down)
2766 void bgp_rib_remove(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
2767 struct peer
*peer
, afi_t afi
, safi_t safi
)
2769 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, pi
, afi
, safi
);
2771 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
2772 bgp_path_info_delete(rn
, pi
); /* keep historical info */
2774 bgp_process(peer
->bgp
, rn
, afi
, safi
);
2777 static void bgp_rib_withdraw(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
2778 struct peer
*peer
, afi_t afi
, safi_t safi
,
2779 struct prefix_rd
*prd
)
2781 /* apply dampening, if result is suppressed, we'll be retaining
2782 * the bgp_path_info in the RIB for historical reference.
2784 if (CHECK_FLAG(peer
->bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
2785 && peer
->sort
== BGP_PEER_EBGP
)
2786 if ((bgp_damp_withdraw(pi
, rn
, afi
, safi
, 0))
2787 == BGP_DAMP_SUPPRESSED
) {
2788 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, pi
, afi
,
2794 if (safi
== SAFI_MPLS_VPN
) {
2795 struct bgp_node
*prn
= NULL
;
2796 struct bgp_table
*table
= NULL
;
2798 prn
= bgp_node_get(peer
->bgp
->rib
[afi
][safi
],
2799 (struct prefix
*)prd
);
2800 if (bgp_node_has_bgp_path_info_data(prn
)) {
2801 table
= bgp_node_get_bgp_table_info(prn
);
2803 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
2804 peer
->bgp
, prd
, table
, &rn
->p
, pi
);
2806 bgp_unlock_node(prn
);
2808 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2809 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
2811 vnc_import_bgp_del_route(peer
->bgp
, &rn
->p
, pi
);
2812 vnc_import_bgp_exterior_del_route(peer
->bgp
, &rn
->p
,
2818 /* If this is an EVPN route, process for un-import. */
2819 if (safi
== SAFI_EVPN
)
2820 bgp_evpn_unimport_route(peer
->bgp
, afi
, safi
, &rn
->p
, pi
);
2822 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
2825 struct bgp_path_info
*info_make(int type
, int sub_type
, unsigned short instance
,
2826 struct peer
*peer
, struct attr
*attr
,
2827 struct bgp_node
*rn
)
2829 struct bgp_path_info
*new;
2831 /* Make new BGP info. */
2832 new = XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_path_info
));
2834 new->instance
= instance
;
2835 new->sub_type
= sub_type
;
2838 new->uptime
= bgp_clock();
2843 static void overlay_index_update(struct attr
*attr
,
2844 struct eth_segment_id
*eth_s_id
,
2845 union gw_addr
*gw_ip
)
2850 if (eth_s_id
== NULL
) {
2851 memset(&(attr
->evpn_overlay
.eth_s_id
), 0,
2852 sizeof(struct eth_segment_id
));
2854 memcpy(&(attr
->evpn_overlay
.eth_s_id
), eth_s_id
,
2855 sizeof(struct eth_segment_id
));
2857 if (gw_ip
== NULL
) {
2858 memset(&(attr
->evpn_overlay
.gw_ip
), 0, sizeof(union gw_addr
));
2860 memcpy(&(attr
->evpn_overlay
.gw_ip
), gw_ip
,
2861 sizeof(union gw_addr
));
2865 static bool overlay_index_equal(afi_t afi
, struct bgp_path_info
*path
,
2866 struct eth_segment_id
*eth_s_id
,
2867 union gw_addr
*gw_ip
)
2869 struct eth_segment_id
*path_eth_s_id
, *path_eth_s_id_remote
;
2870 union gw_addr
*path_gw_ip
, *path_gw_ip_remote
;
2872 struct eth_segment_id esi
;
2876 if (afi
!= AFI_L2VPN
)
2879 memset(&temp
, 0, sizeof(temp
));
2880 path_eth_s_id
= &temp
.esi
;
2881 path_gw_ip
= &temp
.ip
;
2883 if (eth_s_id
== NULL
&& gw_ip
== NULL
)
2886 path_eth_s_id
= &(path
->attr
->evpn_overlay
.eth_s_id
);
2887 path_gw_ip
= &(path
->attr
->evpn_overlay
.gw_ip
);
2890 if (gw_ip
== NULL
) {
2891 memset(&temp
, 0, sizeof(temp
));
2892 path_gw_ip_remote
= &temp
.ip
;
2894 path_gw_ip_remote
= gw_ip
;
2896 if (eth_s_id
== NULL
) {
2897 memset(&temp
, 0, sizeof(temp
));
2898 path_eth_s_id_remote
= &temp
.esi
;
2900 path_eth_s_id_remote
= eth_s_id
;
2902 if (!memcmp(path_gw_ip
, path_gw_ip_remote
, sizeof(union gw_addr
)))
2905 return !memcmp(path_eth_s_id
, path_eth_s_id_remote
,
2906 sizeof(struct eth_segment_id
));
2909 /* Check if received nexthop is valid or not. */
2910 static int bgp_update_martian_nexthop(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
2915 /* Only validated for unicast and multicast currently. */
2916 /* Also valid for EVPN where the nexthop is an IP address. */
2917 if (safi
!= SAFI_UNICAST
&& safi
!= SAFI_MULTICAST
&& safi
!= SAFI_EVPN
)
2920 /* If NEXT_HOP is present, validate it. */
2921 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
2922 if (attr
->nexthop
.s_addr
== 0
2923 || IPV4_CLASS_DE(ntohl(attr
->nexthop
.s_addr
))
2924 || bgp_nexthop_self(bgp
, attr
->nexthop
))
2928 /* If MP_NEXTHOP is present, validate it. */
2929 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
2930 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
2931 * it is not an IPv6 link-local address.
2933 if (attr
->mp_nexthop_len
) {
2934 switch (attr
->mp_nexthop_len
) {
2935 case BGP_ATTR_NHLEN_IPV4
:
2936 case BGP_ATTR_NHLEN_VPNV4
:
2937 ret
= (attr
->mp_nexthop_global_in
.s_addr
== 0
2938 || IPV4_CLASS_DE(ntohl(
2939 attr
->mp_nexthop_global_in
.s_addr
))
2940 || bgp_nexthop_self(bgp
,
2941 attr
->mp_nexthop_global_in
));
2944 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
2945 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
2946 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
2947 ret
= (IN6_IS_ADDR_UNSPECIFIED(&attr
->mp_nexthop_global
)
2948 || IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
2949 || IN6_IS_ADDR_MULTICAST(
2950 &attr
->mp_nexthop_global
));
2962 int bgp_update(struct peer
*peer
, struct prefix
*p
, uint32_t addpath_id
,
2963 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
2964 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
2965 uint32_t num_labels
, int soft_reconfig
,
2966 struct bgp_route_evpn
*evpn
)
2969 int aspath_loop_count
= 0;
2970 struct bgp_node
*rn
;
2972 struct attr new_attr
;
2973 struct attr
*attr_new
;
2974 struct bgp_path_info
*pi
;
2975 struct bgp_path_info
*new;
2976 struct bgp_path_info_extra
*extra
;
2978 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
2980 int do_loop_check
= 1;
2981 int has_valid_label
= 0;
2983 int vnc_implicit_withdraw
= 0;
2987 memset(&new_attr
, 0, sizeof(struct attr
));
2988 new_attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
2989 new_attr
.label
= MPLS_INVALID_LABEL
;
2992 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
2993 /* TODO: Check to see if we can get rid of "is_valid_label" */
2994 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
2995 has_valid_label
= (num_labels
> 0) ? 1 : 0;
2997 has_valid_label
= bgp_is_valid_label(label
);
2999 /* When peer's soft reconfiguration enabled. Record input packet in
3002 && CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
3003 && peer
!= bgp
->peer_self
)
3004 bgp_adj_in_set(rn
, peer
, attr
, addpath_id
);
3006 /* Check previously received route. */
3007 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
3008 if (pi
->peer
== peer
&& pi
->type
== type
3009 && pi
->sub_type
== sub_type
3010 && pi
->addpath_rx_id
== addpath_id
)
3013 /* AS path local-as loop check. */
3014 if (peer
->change_local_as
) {
3015 if (peer
->allowas_in
[afi
][safi
])
3016 aspath_loop_count
= peer
->allowas_in
[afi
][safi
];
3017 else if (!CHECK_FLAG(peer
->flags
,
3018 PEER_FLAG_LOCAL_AS_NO_PREPEND
))
3019 aspath_loop_count
= 1;
3021 if (aspath_loop_check(attr
->aspath
, peer
->change_local_as
)
3022 > aspath_loop_count
) {
3023 reason
= "as-path contains our own AS;";
3028 /* If the peer is configured for "allowas-in origin" and the last ASN in
3030 * as-path is our ASN then we do not need to call aspath_loop_check
3032 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN_ORIGIN
))
3033 if (aspath_get_last_as(attr
->aspath
) == bgp
->as
)
3036 /* AS path loop check. */
3037 if (do_loop_check
) {
3038 if (aspath_loop_check(attr
->aspath
, bgp
->as
)
3039 > peer
->allowas_in
[afi
][safi
]
3040 || (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)
3041 && aspath_loop_check(attr
->aspath
, bgp
->confed_id
)
3042 > peer
->allowas_in
[afi
][safi
])) {
3043 reason
= "as-path contains our own AS;";
3048 /* Route reflector originator ID check. */
3049 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
3050 && IPV4_ADDR_SAME(&bgp
->router_id
, &attr
->originator_id
)) {
3051 reason
= "originator is us;";
3055 /* Route reflector cluster ID check. */
3056 if (bgp_cluster_filter(peer
, attr
)) {
3057 reason
= "reflected from the same cluster;";
3061 /* Apply incoming filter. */
3062 if (bgp_input_filter(peer
, p
, attr
, afi
, safi
) == FILTER_DENY
) {
3067 bgp_attr_dup(&new_attr
, attr
);
3069 /* Apply incoming route-map.
3070 * NB: new_attr may now contain newly allocated values from route-map
3072 * commands, so we need bgp_attr_flush in the error paths, until we
3074 * the attr (which takes over the memory references) */
3075 if (bgp_input_modifier(peer
, p
, &new_attr
, afi
, safi
, NULL
)
3077 reason
= "route-map;";
3078 bgp_attr_flush(&new_attr
);
3082 if (peer
->sort
== BGP_PEER_EBGP
) {
3084 /* If we receive the graceful-shutdown community from an eBGP
3085 * peer we must lower local-preference */
3086 if (new_attr
.community
3087 && community_include(new_attr
.community
, COMMUNITY_GSHUT
)) {
3088 new_attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
3089 new_attr
.local_pref
= BGP_GSHUT_LOCAL_PREF
;
3091 /* If graceful-shutdown is configured then add the GSHUT
3092 * community to all paths received from eBGP peers */
3093 } else if (bgp_flag_check(peer
->bgp
,
3094 BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
3095 bgp_attr_add_gshut_community(&new_attr
);
3099 /* next hop check. */
3100 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
)
3101 && bgp_update_martian_nexthop(bgp
, afi
, safi
, &new_attr
)) {
3102 reason
= "martian or self next-hop;";
3103 bgp_attr_flush(&new_attr
);
3107 if (bgp_mac_entry_exists(p
) || bgp_mac_exist(&attr
->rmac
)) {
3108 reason
= "self mac;";
3112 attr_new
= bgp_attr_intern(&new_attr
);
3114 /* If the update is implicit withdraw. */
3116 pi
->uptime
= bgp_clock();
3117 same_attr
= attrhash_cmp(pi
->attr
, attr_new
);
3119 /* Same attribute comes in. */
3120 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
3121 && attrhash_cmp(pi
->attr
, attr_new
)
3122 && (!has_valid_label
3123 || memcmp(&(bgp_path_info_extra_get(pi
))->label
, label
,
3124 num_labels
* sizeof(mpls_label_t
))
3126 && (overlay_index_equal(
3127 afi
, pi
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3128 evpn
== NULL
? NULL
: &evpn
->gw_ip
))) {
3129 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
3130 BGP_CONFIG_DAMPENING
)
3131 && peer
->sort
== BGP_PEER_EBGP
3132 && CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3133 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3134 bgp_debug_rdpfxpath2str(
3135 afi
, safi
, prd
, p
, label
,
3136 num_labels
, addpath_id
? 1 : 0,
3137 addpath_id
, pfx_buf
,
3139 zlog_debug("%s rcvd %s", peer
->host
,
3143 if (bgp_damp_update(pi
, rn
, afi
, safi
)
3144 != BGP_DAMP_SUPPRESSED
) {
3145 bgp_aggregate_increment(bgp
, p
, pi
, afi
,
3147 bgp_process(bgp
, rn
, afi
, safi
);
3149 } else /* Duplicate - odd */
3151 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3152 if (!peer
->rcvd_attr_printed
) {
3154 "%s rcvd UPDATE w/ attr: %s",
3156 peer
->rcvd_attr_str
);
3157 peer
->rcvd_attr_printed
= 1;
3160 bgp_debug_rdpfxpath2str(
3161 afi
, safi
, prd
, p
, label
,
3162 num_labels
, addpath_id
? 1 : 0,
3163 addpath_id
, pfx_buf
,
3166 "%s rcvd %s...duplicate ignored",
3167 peer
->host
, pfx_buf
);
3170 /* graceful restart STALE flag unset. */
3171 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
3172 bgp_path_info_unset_flag(
3173 rn
, pi
, BGP_PATH_STALE
);
3174 bgp_process(bgp
, rn
, afi
, safi
);
3178 bgp_unlock_node(rn
);
3179 bgp_attr_unintern(&attr_new
);
3184 /* Withdraw/Announce before we fully processed the withdraw */
3185 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
3186 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3187 bgp_debug_rdpfxpath2str(
3188 afi
, safi
, prd
, p
, label
, num_labels
,
3189 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3192 "%s rcvd %s, flapped quicker than processing",
3193 peer
->host
, pfx_buf
);
3196 bgp_path_info_restore(rn
, pi
);
3199 /* Received Logging. */
3200 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3201 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
3202 num_labels
, addpath_id
? 1 : 0,
3203 addpath_id
, pfx_buf
,
3205 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3208 /* graceful restart STALE flag unset. */
3209 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
3210 bgp_path_info_unset_flag(rn
, pi
, BGP_PATH_STALE
);
3212 /* The attribute is changed. */
3213 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_ATTR_CHANGED
);
3215 /* implicit withdraw, decrement aggregate and pcount here.
3216 * only if update is accepted, they'll increment below.
3218 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
3220 /* Update bgp route dampening information. */
3221 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3222 && peer
->sort
== BGP_PEER_EBGP
) {
3223 /* This is implicit withdraw so we should update
3226 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
3227 bgp_damp_withdraw(pi
, rn
, afi
, safi
, 1);
3230 if (safi
== SAFI_MPLS_VPN
) {
3231 struct bgp_node
*prn
= NULL
;
3232 struct bgp_table
*table
= NULL
;
3234 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3235 (struct prefix
*)prd
);
3236 if (bgp_node_has_bgp_path_info_data(prn
)) {
3237 table
= bgp_node_get_bgp_table_info(prn
);
3239 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3240 bgp
, prd
, table
, p
, pi
);
3242 bgp_unlock_node(prn
);
3244 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3245 && (safi
== SAFI_UNICAST
)) {
3246 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
3248 * Implicit withdraw case.
3250 ++vnc_implicit_withdraw
;
3251 vnc_import_bgp_del_route(bgp
, p
, pi
);
3252 vnc_import_bgp_exterior_del_route(bgp
, p
, pi
);
3257 /* Special handling for EVPN update of an existing route. If the
3258 * extended community attribute has changed, we need to
3260 * the route using its existing extended community. It will be
3261 * subsequently processed for import with the new extended
3264 if (safi
== SAFI_EVPN
&& !same_attr
) {
3266 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))
3268 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
3271 cmp
= ecommunity_cmp(pi
->attr
->ecommunity
,
3272 attr_new
->ecommunity
);
3274 if (bgp_debug_update(peer
, p
, NULL
, 1))
3276 "Change in EXT-COMM, existing %s new %s",
3278 pi
->attr
->ecommunity
),
3280 attr_new
->ecommunity
));
3281 bgp_evpn_unimport_route(bgp
, afi
, safi
,
3287 /* Update to new attribute. */
3288 bgp_attr_unintern(&pi
->attr
);
3289 pi
->attr
= attr_new
;
3291 /* Update MPLS label */
3292 if (has_valid_label
) {
3293 extra
= bgp_path_info_extra_get(pi
);
3294 if (extra
->label
!= label
) {
3295 memcpy(&extra
->label
, label
,
3296 num_labels
* sizeof(mpls_label_t
));
3297 extra
->num_labels
= num_labels
;
3299 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3300 bgp_set_valid_label(&extra
->label
[0]);
3304 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3305 && (safi
== SAFI_UNICAST
)) {
3306 if (vnc_implicit_withdraw
) {
3308 * Add back the route with its new attributes
3310 * The route is still selected, until the route
3312 * queued by bgp_process actually runs. We have
3314 * update to the VNC side immediately to avoid
3316 * configuration changes (e.g., route-map
3318 * trigger re-importation of the entire RIB.
3320 vnc_import_bgp_add_route(bgp
, p
, pi
);
3321 vnc_import_bgp_exterior_add_route(bgp
, p
, pi
);
3325 /* Update Overlay Index */
3326 if (afi
== AFI_L2VPN
) {
3327 overlay_index_update(
3328 pi
->attr
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3329 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3332 /* Update bgp route dampening information. */
3333 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3334 && peer
->sort
== BGP_PEER_EBGP
) {
3335 /* Now we do normal update dampening. */
3336 ret
= bgp_damp_update(pi
, rn
, afi
, safi
);
3337 if (ret
== BGP_DAMP_SUPPRESSED
) {
3338 bgp_unlock_node(rn
);
3343 /* Nexthop reachability check - for unicast and
3344 * labeled-unicast.. */
3345 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3346 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
3347 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
3348 && !CHECK_FLAG(peer
->flags
,
3349 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3351 bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3356 struct bgp
*bgp_nexthop
= bgp
;
3358 if (pi
->extra
&& pi
->extra
->bgp_orig
)
3359 bgp_nexthop
= pi
->extra
->bgp_orig
;
3361 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
, afi
, pi
,
3363 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3364 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_VALID
);
3366 if (BGP_DEBUG(nht
, NHT
)) {
3367 char buf1
[INET6_ADDRSTRLEN
];
3369 (const void *)&attr_new
3371 buf1
, INET6_ADDRSTRLEN
);
3372 zlog_debug("%s(%s): NH unresolved",
3373 __FUNCTION__
, buf1
);
3375 bgp_path_info_unset_flag(rn
, pi
,
3379 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_VALID
);
3382 if (safi
== SAFI_MPLS_VPN
) {
3383 struct bgp_node
*prn
= NULL
;
3384 struct bgp_table
*table
= NULL
;
3386 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3387 (struct prefix
*)prd
);
3388 if (bgp_node_has_bgp_path_info_data(prn
)) {
3389 table
= bgp_node_get_bgp_table_info(prn
);
3391 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3392 bgp
, prd
, table
, p
, pi
);
3394 bgp_unlock_node(prn
);
3398 /* If this is an EVPN route and some attribute has changed,
3400 * route for import. If the extended community has changed, we
3402 * have done the un-import earlier and the import would result
3404 * route getting injected into appropriate L2 VNIs. If it is
3406 * some other attribute change, the import will result in
3408 * the attributes for the route in the VNI(s).
3410 if (safi
== SAFI_EVPN
&& !same_attr
)
3411 bgp_evpn_import_route(bgp
, afi
, safi
, p
, pi
);
3413 /* Process change. */
3414 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
3416 bgp_process(bgp
, rn
, afi
, safi
);
3417 bgp_unlock_node(rn
);
3419 if (SAFI_UNICAST
== safi
3420 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3421 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3423 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, pi
);
3425 if ((SAFI_MPLS_VPN
== safi
)
3426 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3428 vpn_leak_to_vrf_update(bgp
, pi
);
3432 if (SAFI_MPLS_VPN
== safi
) {
3433 mpls_label_t label_decoded
= decode_label(label
);
3435 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3436 type
, sub_type
, &label_decoded
);
3438 if (SAFI_ENCAP
== safi
) {
3439 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3440 type
, sub_type
, NULL
);
3445 } // End of implicit withdraw
3447 /* Received Logging. */
3448 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3449 if (!peer
->rcvd_attr_printed
) {
3450 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3451 peer
->rcvd_attr_str
);
3452 peer
->rcvd_attr_printed
= 1;
3455 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3456 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3458 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3461 /* Make new BGP info. */
3462 new = info_make(type
, sub_type
, 0, peer
, attr_new
, rn
);
3464 /* Update MPLS label */
3465 if (has_valid_label
) {
3466 extra
= bgp_path_info_extra_get(new);
3467 if (extra
->label
!= label
) {
3468 memcpy(&extra
->label
, label
,
3469 num_labels
* sizeof(mpls_label_t
));
3470 extra
->num_labels
= num_labels
;
3472 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3473 bgp_set_valid_label(&extra
->label
[0]);
3476 /* Update Overlay Index */
3477 if (afi
== AFI_L2VPN
) {
3478 overlay_index_update(new->attr
,
3479 evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3480 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3482 /* Nexthop reachability check. */
3483 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3484 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
3485 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
3486 && !CHECK_FLAG(peer
->flags
,
3487 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3488 && !bgp_flag_check(bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3493 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, new, NULL
, connected
)
3494 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3495 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
3497 if (BGP_DEBUG(nht
, NHT
)) {
3498 char buf1
[INET6_ADDRSTRLEN
];
3500 (const void *)&attr_new
->nexthop
,
3501 buf1
, INET6_ADDRSTRLEN
);
3502 zlog_debug("%s(%s): NH unresolved",
3503 __FUNCTION__
, buf1
);
3505 bgp_path_info_unset_flag(rn
, new, BGP_PATH_VALID
);
3508 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
3511 new->addpath_rx_id
= addpath_id
;
3513 /* Increment prefix */
3514 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
3516 /* Register new BGP information. */
3517 bgp_path_info_add(rn
, new);
3519 /* route_node_get lock */
3520 bgp_unlock_node(rn
);
3523 if (safi
== SAFI_MPLS_VPN
) {
3524 struct bgp_node
*prn
= NULL
;
3525 struct bgp_table
*table
= NULL
;
3527 prn
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
3528 if (bgp_node_has_bgp_path_info_data(prn
)) {
3529 table
= bgp_node_get_bgp_table_info(prn
);
3531 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3532 bgp
, prd
, table
, p
, new);
3534 bgp_unlock_node(prn
);
3538 /* If maximum prefix count is configured and current prefix
3540 if (bgp_maximum_prefix_overflow(peer
, afi
, safi
, 0))
3543 /* If this is an EVPN route, process for import. */
3544 if (safi
== SAFI_EVPN
)
3545 bgp_evpn_import_route(bgp
, afi
, safi
, p
, new);
3547 /* Process change. */
3548 bgp_process(bgp
, rn
, afi
, safi
);
3550 if (SAFI_UNICAST
== safi
3551 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3552 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3553 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
3555 if ((SAFI_MPLS_VPN
== safi
)
3556 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3558 vpn_leak_to_vrf_update(bgp
, new);
3561 if (SAFI_MPLS_VPN
== safi
) {
3562 mpls_label_t label_decoded
= decode_label(label
);
3564 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3565 sub_type
, &label_decoded
);
3567 if (SAFI_ENCAP
== safi
) {
3568 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3575 /* This BGP update is filtered. Log the reason then update BGP
3578 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3579 if (!peer
->rcvd_attr_printed
) {
3580 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3581 peer
->rcvd_attr_str
);
3582 peer
->rcvd_attr_printed
= 1;
3585 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3586 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3588 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
3589 peer
->host
, pfx_buf
, reason
);
3593 /* If this is an EVPN route, un-import it as it is now filtered.
3595 if (safi
== SAFI_EVPN
)
3596 bgp_evpn_unimport_route(bgp
, afi
, safi
, p
, pi
);
3598 if (SAFI_UNICAST
== safi
3599 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3600 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3602 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
3604 if ((SAFI_MPLS_VPN
== safi
)
3605 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3607 vpn_leak_to_vrf_withdraw(bgp
, pi
);
3610 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
3613 bgp_unlock_node(rn
);
3617 * Filtered update is treated as an implicit withdrawal (see
3619 * a few lines above)
3621 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3622 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3630 int bgp_withdraw(struct peer
*peer
, struct prefix
*p
, uint32_t addpath_id
,
3631 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
3632 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
3633 uint32_t num_labels
, struct bgp_route_evpn
*evpn
)
3636 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
3637 struct bgp_node
*rn
;
3638 struct bgp_path_info
*pi
;
3641 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3642 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3650 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
3652 /* If peer is soft reconfiguration enabled. Record input packet for
3653 * further calculation.
3655 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
3656 * routes that are filtered. This tanks out Quagga RS pretty badly due
3658 * the iteration over all RS clients.
3659 * Since we need to remove the entry from adj_in anyway, do that first
3661 * if there was no entry, we don't need to do anything more.
3663 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
3664 && peer
!= bgp
->peer_self
)
3665 if (!bgp_adj_in_unset(rn
, peer
, addpath_id
)) {
3666 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3667 bgp_debug_rdpfxpath2str(
3668 afi
, safi
, prd
, p
, label
, num_labels
,
3669 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3672 "%s withdrawing route %s not in adj-in",
3673 peer
->host
, pfx_buf
);
3675 bgp_unlock_node(rn
);
3679 /* Lookup withdrawn route. */
3680 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
3681 if (pi
->peer
== peer
&& pi
->type
== type
3682 && pi
->sub_type
== sub_type
3683 && pi
->addpath_rx_id
== addpath_id
)
3687 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3688 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3689 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3691 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer
->host
,
3695 /* Withdraw specified route from routing table. */
3696 if (pi
&& !CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3697 bgp_rib_withdraw(rn
, pi
, peer
, afi
, safi
, prd
);
3698 if (SAFI_UNICAST
== safi
3699 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3700 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3701 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
3703 if ((SAFI_MPLS_VPN
== safi
)
3704 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3706 vpn_leak_to_vrf_withdraw(bgp
, pi
);
3708 } else if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3709 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3710 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3712 zlog_debug("%s Can't find the route %s", peer
->host
, pfx_buf
);
3715 /* Unlock bgp_node_get() lock. */
3716 bgp_unlock_node(rn
);
3721 void bgp_default_originate(struct peer
*peer
, afi_t afi
, safi_t safi
,
3724 struct update_subgroup
*subgrp
;
3725 subgrp
= peer_subgroup(peer
, afi
, safi
);
3726 subgroup_default_originate(subgrp
, withdraw
);
3731 * bgp_stop_announce_route_timer
3733 void bgp_stop_announce_route_timer(struct peer_af
*paf
)
3735 if (!paf
->t_announce_route
)
3738 THREAD_TIMER_OFF(paf
->t_announce_route
);
3742 * bgp_announce_route_timer_expired
3744 * Callback that is invoked when the route announcement timer for a
3747 static int bgp_announce_route_timer_expired(struct thread
*t
)
3749 struct peer_af
*paf
;
3752 paf
= THREAD_ARG(t
);
3755 if (peer
->status
!= Established
)
3758 if (!peer
->afc_nego
[paf
->afi
][paf
->safi
])
3761 peer_af_announce_route(paf
, 1);
3766 * bgp_announce_route
3768 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
3770 void bgp_announce_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
3772 struct peer_af
*paf
;
3773 struct update_subgroup
*subgrp
;
3775 paf
= peer_af_find(peer
, afi
, safi
);
3778 subgrp
= PAF_SUBGRP(paf
);
3781 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
3782 * or a refresh has already been triggered.
3784 if (!subgrp
|| paf
->t_announce_route
)
3788 * Start a timer to stagger/delay the announce. This serves
3789 * two purposes - announcement can potentially be combined for
3790 * multiple peers and the announcement doesn't happen in the
3793 thread_add_timer_msec(bm
->master
, bgp_announce_route_timer_expired
, paf
,
3794 (subgrp
->peer_count
== 1)
3795 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
3796 : BGP_ANNOUNCE_ROUTE_DELAY_MS
,
3797 &paf
->t_announce_route
);
3801 * Announce routes from all AF tables to a peer.
3803 * This should ONLY be called when there is a need to refresh the
3804 * routes to the peer based on a policy change for this peer alone
3805 * or a route refresh request received from the peer.
3806 * The operation will result in splitting the peer from its existing
3807 * subgroups and putting it in new subgroups.
3809 void bgp_announce_route_all(struct peer
*peer
)
3814 FOREACH_AFI_SAFI (afi
, safi
)
3815 bgp_announce_route(peer
, afi
, safi
);
3818 static void bgp_soft_reconfig_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
3819 struct bgp_table
*table
,
3820 struct prefix_rd
*prd
)
3823 struct bgp_node
*rn
;
3824 struct bgp_adj_in
*ain
;
3827 table
= peer
->bgp
->rib
[afi
][safi
];
3829 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
3830 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
3831 if (ain
->peer
!= peer
)
3834 struct bgp_path_info
*pi
=
3835 bgp_node_get_bgp_path_info(rn
);
3836 uint32_t num_labels
= 0;
3837 mpls_label_t
*label_pnt
= NULL
;
3838 struct bgp_route_evpn evpn
;
3840 if (pi
&& pi
->extra
)
3841 num_labels
= pi
->extra
->num_labels
;
3843 label_pnt
= &pi
->extra
->label
[0];
3845 memcpy(&evpn
, &pi
->attr
->evpn_overlay
,
3848 memset(&evpn
, 0, sizeof(evpn
));
3850 ret
= bgp_update(peer
, &rn
->p
, ain
->addpath_rx_id
,
3851 ain
->attr
, afi
, safi
, ZEBRA_ROUTE_BGP
,
3852 BGP_ROUTE_NORMAL
, prd
, label_pnt
,
3853 num_labels
, 1, &evpn
);
3856 bgp_unlock_node(rn
);
3862 void bgp_soft_reconfig_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
3864 struct bgp_node
*rn
;
3865 struct bgp_table
*table
;
3867 if (peer
->status
!= Established
)
3870 if ((safi
!= SAFI_MPLS_VPN
) && (safi
!= SAFI_ENCAP
)
3871 && (safi
!= SAFI_EVPN
))
3872 bgp_soft_reconfig_table(peer
, afi
, safi
, NULL
, NULL
);
3874 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
3875 rn
= bgp_route_next(rn
)) {
3876 table
= bgp_node_get_bgp_table_info(rn
);
3877 if (table
!= NULL
) {
3878 struct prefix_rd prd
;
3880 prd
.family
= AF_UNSPEC
;
3882 memcpy(&prd
.val
, rn
->p
.u
.val
, 8);
3884 bgp_soft_reconfig_table(peer
, afi
, safi
, table
,
3891 struct bgp_clear_node_queue
{
3892 struct bgp_node
*rn
;
3895 static wq_item_status
bgp_clear_route_node(struct work_queue
*wq
, void *data
)
3897 struct bgp_clear_node_queue
*cnq
= data
;
3898 struct bgp_node
*rn
= cnq
->rn
;
3899 struct peer
*peer
= wq
->spec
.data
;
3900 struct bgp_path_info
*pi
;
3902 afi_t afi
= bgp_node_table(rn
)->afi
;
3903 safi_t safi
= bgp_node_table(rn
)->safi
;
3908 /* It is possible that we have multiple paths for a prefix from a peer
3909 * if that peer is using AddPath.
3911 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
3912 if (pi
->peer
!= peer
)
3915 /* graceful restart STALE flag set. */
3916 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_NSF_WAIT
)
3917 && peer
->nsf
[afi
][safi
]
3918 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
3919 && !CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
3920 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_STALE
);
3922 /* If this is an EVPN route, process for
3924 if (safi
== SAFI_EVPN
)
3925 bgp_evpn_unimport_route(bgp
, afi
, safi
, &rn
->p
,
3927 /* Handle withdraw for VRF route-leaking and L3VPN */
3928 if (SAFI_UNICAST
== safi
3929 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
||
3930 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3931 vpn_leak_from_vrf_withdraw(bgp_get_default(),
3934 if (SAFI_MPLS_VPN
== safi
&&
3935 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
3936 vpn_leak_to_vrf_withdraw(bgp
, pi
);
3939 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
3945 static void bgp_clear_node_queue_del(struct work_queue
*wq
, void *data
)
3947 struct bgp_clear_node_queue
*cnq
= data
;
3948 struct bgp_node
*rn
= cnq
->rn
;
3949 struct bgp_table
*table
= bgp_node_table(rn
);
3951 bgp_unlock_node(rn
);
3952 bgp_table_unlock(table
);
3953 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE
, cnq
);
3956 static void bgp_clear_node_complete(struct work_queue
*wq
)
3958 struct peer
*peer
= wq
->spec
.data
;
3960 /* Tickle FSM to start moving again */
3961 BGP_EVENT_ADD(peer
, Clearing_Completed
);
3963 peer_unlock(peer
); /* bgp_clear_route */
3966 static void bgp_clear_node_queue_init(struct peer
*peer
)
3968 char wname
[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
3970 snprintf(wname
, sizeof(wname
), "clear %s", peer
->host
);
3971 #undef CLEAR_QUEUE_NAME_LEN
3973 peer
->clear_node_queue
= work_queue_new(bm
->master
, wname
);
3974 peer
->clear_node_queue
->spec
.hold
= 10;
3975 peer
->clear_node_queue
->spec
.workfunc
= &bgp_clear_route_node
;
3976 peer
->clear_node_queue
->spec
.del_item_data
= &bgp_clear_node_queue_del
;
3977 peer
->clear_node_queue
->spec
.completion_func
= &bgp_clear_node_complete
;
3978 peer
->clear_node_queue
->spec
.max_retries
= 0;
3980 /* we only 'lock' this peer reference when the queue is actually active
3982 peer
->clear_node_queue
->spec
.data
= peer
;
3985 static void bgp_clear_route_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
3986 struct bgp_table
*table
)
3988 struct bgp_node
*rn
;
3989 int force
= bm
->process_main_queue
? 0 : 1;
3992 table
= peer
->bgp
->rib
[afi
][safi
];
3994 /* If still no table => afi/safi isn't configured at all or smth. */
3998 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
3999 struct bgp_path_info
*pi
, *next
;
4000 struct bgp_adj_in
*ain
;
4001 struct bgp_adj_in
*ain_next
;
4003 /* XXX:TODO: This is suboptimal, every non-empty route_node is
4004 * queued for every clearing peer, regardless of whether it is
4005 * relevant to the peer at hand.
4007 * Overview: There are 3 different indices which need to be
4008 * scrubbed, potentially, when a peer is removed:
4010 * 1 peer's routes visible via the RIB (ie accepted routes)
4011 * 2 peer's routes visible by the (optional) peer's adj-in index
4012 * 3 other routes visible by the peer's adj-out index
4014 * 3 there is no hurry in scrubbing, once the struct peer is
4015 * removed from bgp->peer, we could just GC such deleted peer's
4016 * adj-outs at our leisure.
4018 * 1 and 2 must be 'scrubbed' in some way, at least made
4019 * invisible via RIB index before peer session is allowed to be
4020 * brought back up. So one needs to know when such a 'search' is
4025 * - there'd be a single global queue or a single RIB walker
4026 * - rather than tracking which route_nodes still need to be
4027 * examined on a peer basis, we'd track which peers still
4030 * Given that our per-peer prefix-counts now should be reliable,
4031 * this may actually be achievable. It doesn't seem to be a huge
4032 * problem at this time,
4034 * It is possible that we have multiple paths for a prefix from
4036 * if that peer is using AddPath.
4040 ain_next
= ain
->next
;
4042 if (ain
->peer
== peer
) {
4043 bgp_adj_in_remove(rn
, ain
);
4044 bgp_unlock_node(rn
);
4050 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= next
) {
4052 if (pi
->peer
!= peer
)
4056 bgp_path_info_reap(rn
, pi
);
4058 struct bgp_clear_node_queue
*cnq
;
4060 /* both unlocked in bgp_clear_node_queue_del */
4061 bgp_table_lock(bgp_node_table(rn
));
4064 MTYPE_BGP_CLEAR_NODE_QUEUE
,
4065 sizeof(struct bgp_clear_node_queue
));
4067 work_queue_add(peer
->clear_node_queue
, cnq
);
4075 void bgp_clear_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4077 struct bgp_node
*rn
;
4078 struct bgp_table
*table
;
4080 if (peer
->clear_node_queue
== NULL
)
4081 bgp_clear_node_queue_init(peer
);
4083 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
4084 * Idle until it receives a Clearing_Completed event. This protects
4085 * against peers which flap faster than we can we clear, which could
4088 * a) race with routes from the new session being installed before
4089 * clear_route_node visits the node (to delete the route of that
4091 * b) resource exhaustion, clear_route_node likely leads to an entry
4092 * on the process_main queue. Fast-flapping could cause that queue
4096 /* lock peer in assumption that clear-node-queue will get nodes; if so,
4097 * the unlock will happen upon work-queue completion; other wise, the
4098 * unlock happens at the end of this function.
4100 if (!peer
->clear_node_queue
->thread
)
4103 if (safi
!= SAFI_MPLS_VPN
&& safi
!= SAFI_ENCAP
&& safi
!= SAFI_EVPN
)
4104 bgp_clear_route_table(peer
, afi
, safi
, NULL
);
4106 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4107 rn
= bgp_route_next(rn
)) {
4108 table
= bgp_node_get_bgp_table_info(rn
);
4112 bgp_clear_route_table(peer
, afi
, safi
, table
);
4115 /* unlock if no nodes got added to the clear-node-queue. */
4116 if (!peer
->clear_node_queue
->thread
)
4120 void bgp_clear_route_all(struct peer
*peer
)
4125 FOREACH_AFI_SAFI (afi
, safi
)
4126 bgp_clear_route(peer
, afi
, safi
);
4129 rfapiProcessPeerDown(peer
);
4133 void bgp_clear_adj_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
4135 struct bgp_table
*table
;
4136 struct bgp_node
*rn
;
4137 struct bgp_adj_in
*ain
;
4138 struct bgp_adj_in
*ain_next
;
4140 table
= peer
->bgp
->rib
[afi
][safi
];
4142 /* It is possible that we have multiple paths for a prefix from a peer
4143 * if that peer is using AddPath.
4145 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
4149 ain_next
= ain
->next
;
4151 if (ain
->peer
== peer
) {
4152 bgp_adj_in_remove(rn
, ain
);
4153 bgp_unlock_node(rn
);
4161 void bgp_clear_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4163 struct bgp_node
*rn
;
4164 struct bgp_path_info
*pi
;
4165 struct bgp_table
*table
;
4167 if (safi
== SAFI_MPLS_VPN
) {
4168 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4169 rn
= bgp_route_next(rn
)) {
4170 struct bgp_node
*rm
;
4172 /* look for neighbor in tables */
4173 table
= bgp_node_get_bgp_table_info(rn
);
4177 for (rm
= bgp_table_top(table
); rm
;
4178 rm
= bgp_route_next(rm
))
4179 for (pi
= bgp_node_get_bgp_path_info(rm
); pi
;
4181 if (pi
->peer
!= peer
)
4183 if (!CHECK_FLAG(pi
->flags
,
4187 bgp_rib_remove(rm
, pi
, peer
, afi
, safi
);
4192 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4193 rn
= bgp_route_next(rn
))
4194 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
;
4196 if (pi
->peer
!= peer
)
4198 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
4200 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
4206 int bgp_outbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
4208 if (peer
->sort
== BGP_PEER_EBGP
4209 && (ROUTE_MAP_OUT_NAME(filter
) || PREFIX_LIST_OUT_NAME(filter
)
4210 || FILTER_LIST_OUT_NAME(filter
)
4211 || DISTRIBUTE_OUT_NAME(filter
)))
4216 int bgp_inbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
4218 if (peer
->sort
== BGP_PEER_EBGP
4219 && (ROUTE_MAP_IN_NAME(filter
) || PREFIX_LIST_IN_NAME(filter
)
4220 || FILTER_LIST_IN_NAME(filter
)
4221 || DISTRIBUTE_IN_NAME(filter
)))
4226 static void bgp_cleanup_table(struct bgp
*bgp
, struct bgp_table
*table
,
4229 struct bgp_node
*rn
;
4230 struct bgp_path_info
*pi
;
4231 struct bgp_path_info
*next
;
4233 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
4234 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= next
) {
4237 /* Unimport EVPN routes from VRFs */
4238 if (safi
== SAFI_EVPN
)
4239 bgp_evpn_unimport_route(bgp
, AFI_L2VPN
,
4243 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)
4244 && pi
->type
== ZEBRA_ROUTE_BGP
4245 && (pi
->sub_type
== BGP_ROUTE_NORMAL
4246 || pi
->sub_type
== BGP_ROUTE_AGGREGATE
4247 || pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
4249 if (bgp_fibupd_safi(safi
))
4250 bgp_zebra_withdraw(&rn
->p
, pi
, bgp
,
4252 bgp_path_info_reap(rn
, pi
);
4257 /* Delete all kernel routes. */
4258 void bgp_cleanup_routes(struct bgp
*bgp
)
4261 struct bgp_node
*rn
;
4262 struct bgp_table
*table
;
4264 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
4265 if (afi
== AFI_L2VPN
)
4267 bgp_cleanup_table(bgp
, bgp
->rib
[afi
][SAFI_UNICAST
],
4270 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
4272 if (afi
!= AFI_L2VPN
) {
4274 safi
= SAFI_MPLS_VPN
;
4275 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4276 rn
= bgp_route_next(rn
)) {
4277 table
= bgp_node_get_bgp_table_info(rn
);
4278 if (table
!= NULL
) {
4279 bgp_cleanup_table(bgp
, table
, safi
);
4280 bgp_table_finish(&table
);
4281 bgp_node_set_bgp_table_info(rn
, NULL
);
4282 bgp_unlock_node(rn
);
4286 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4287 rn
= bgp_route_next(rn
)) {
4288 table
= bgp_node_get_bgp_table_info(rn
);
4289 if (table
!= NULL
) {
4290 bgp_cleanup_table(bgp
, table
, safi
);
4291 bgp_table_finish(&table
);
4292 bgp_node_set_bgp_table_info(rn
, NULL
);
4293 bgp_unlock_node(rn
);
4298 for (rn
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); rn
;
4299 rn
= bgp_route_next(rn
)) {
4300 table
= bgp_node_get_bgp_table_info(rn
);
4301 if (table
!= NULL
) {
4302 bgp_cleanup_table(bgp
, table
, SAFI_EVPN
);
4303 bgp_table_finish(&table
);
4304 bgp_node_set_bgp_table_info(rn
, NULL
);
4305 bgp_unlock_node(rn
);
4310 void bgp_reset(void)
4313 bgp_zclient_reset();
4314 access_list_reset();
4315 prefix_list_reset();
4318 static int bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
4320 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
4321 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
4322 PEER_CAP_ADDPATH_AF_TX_RCV
));
4325 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
4327 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
4328 struct bgp_nlri
*packet
)
4337 int addpath_encoded
;
4338 uint32_t addpath_id
;
4341 lim
= pnt
+ packet
->length
;
4343 safi
= packet
->safi
;
4345 addpath_encoded
= bgp_addpath_encode_rx(peer
, afi
, safi
);
4347 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
4348 syntactic validity. If the field is syntactically incorrect,
4349 then the Error Subcode is set to Invalid Network Field. */
4350 for (; pnt
< lim
; pnt
+= psize
) {
4351 /* Clear prefix structure. */
4352 memset(&p
, 0, sizeof(struct prefix
));
4354 if (addpath_encoded
) {
4356 /* When packet overflow occurs return immediately. */
4357 if (pnt
+ BGP_ADDPATH_ID_LEN
> lim
)
4358 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
4360 addpath_id
= ntohl(*((uint32_t *)pnt
));
4361 pnt
+= BGP_ADDPATH_ID_LEN
;
4364 /* Fetch prefix length. */
4365 p
.prefixlen
= *pnt
++;
4366 /* afi/safi validity already verified by caller,
4367 * bgp_update_receive */
4368 p
.family
= afi2family(afi
);
4370 /* Prefix length check. */
4371 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
4374 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
4375 peer
->host
, p
.prefixlen
, packet
->afi
);
4376 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH
;
4379 /* Packet size overflow check. */
4380 psize
= PSIZE(p
.prefixlen
);
4382 /* When packet overflow occur return immediately. */
4383 if (pnt
+ psize
> lim
) {
4386 "%s [Error] Update packet error (prefix length %d overflows packet)",
4387 peer
->host
, p
.prefixlen
);
4388 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
4391 /* Defensive coding, double-check the psize fits in a struct
4393 if (psize
> (ssize_t
)sizeof(p
.u
)) {
4396 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
4397 peer
->host
, p
.prefixlen
, sizeof(p
.u
));
4398 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
4401 /* Fetch prefix from NLRI packet. */
4402 memcpy(p
.u
.val
, pnt
, psize
);
4404 /* Check address. */
4405 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
4406 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
4407 /* From RFC4271 Section 6.3:
4409 * If a prefix in the NLRI field is semantically
4411 * (e.g., an unexpected multicast IP address),
4413 * be logged locally, and the prefix SHOULD be
4418 "%s: IPv4 unicast NLRI is multicast address %s, ignoring",
4419 peer
->host
, inet_ntoa(p
.u
.prefix4
));
4424 /* Check address. */
4425 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
4426 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4431 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
4433 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4438 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
4443 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
4445 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4452 /* Normal process. */
4454 ret
= bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
4455 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
4456 NULL
, NULL
, 0, 0, NULL
);
4458 ret
= bgp_withdraw(peer
, &p
, addpath_id
, attr
, afi
,
4459 safi
, ZEBRA_ROUTE_BGP
,
4460 BGP_ROUTE_NORMAL
, NULL
, NULL
, 0,
4463 /* Do not send BGP notification twice when maximum-prefix count
4465 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
))
4466 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW
;
4468 /* Address family configuration mismatch. */
4470 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY
;
4473 /* Packet length consistency check. */
4477 "%s [Error] Update packet error (prefix length mismatch with total length)",
4479 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
4482 return BGP_NLRI_PARSE_OK
;
4485 static struct bgp_static
*bgp_static_new(void)
4487 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
4490 static void bgp_static_free(struct bgp_static
*bgp_static
)
4492 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
4493 route_map_counter_decrement(bgp_static
->rmap
.map
);
4495 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
4496 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
4499 void bgp_static_update(struct bgp
*bgp
, struct prefix
*p
,
4500 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
4502 struct bgp_node
*rn
;
4503 struct bgp_path_info
*pi
;
4504 struct bgp_path_info
*new;
4505 struct bgp_path_info rmap_path
;
4507 struct attr
*attr_new
;
4510 int vnc_implicit_withdraw
= 0;
4517 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4519 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4521 attr
.nexthop
= bgp_static
->igpnexthop
;
4522 attr
.med
= bgp_static
->igpmetric
;
4523 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4525 if (bgp_static
->atomic
)
4526 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
4528 /* Store label index, if required. */
4529 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
4530 attr
.label_index
= bgp_static
->label_index
;
4531 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
4534 /* Apply route-map. */
4535 if (bgp_static
->rmap
.name
) {
4536 struct attr attr_tmp
= attr
;
4538 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
4539 rmap_path
.peer
= bgp
->peer_self
;
4540 rmap_path
.attr
= &attr_tmp
;
4542 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4544 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
,
4547 bgp
->peer_self
->rmap_type
= 0;
4549 if (ret
== RMAP_DENYMATCH
) {
4550 /* Free uninterned attribute. */
4551 bgp_attr_flush(&attr_tmp
);
4553 /* Unintern original. */
4554 aspath_unintern(&attr
.aspath
);
4555 bgp_static_withdraw(bgp
, p
, afi
, safi
);
4559 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4560 bgp_attr_add_gshut_community(&attr_tmp
);
4562 attr_new
= bgp_attr_intern(&attr_tmp
);
4565 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4566 bgp_attr_add_gshut_community(&attr
);
4568 attr_new
= bgp_attr_intern(&attr
);
4571 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4572 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4573 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4577 if (attrhash_cmp(pi
->attr
, attr_new
)
4578 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
4579 && !bgp_flag_check(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
4580 bgp_unlock_node(rn
);
4581 bgp_attr_unintern(&attr_new
);
4582 aspath_unintern(&attr
.aspath
);
4585 /* The attribute is changed. */
4586 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_ATTR_CHANGED
);
4588 /* Rewrite BGP route information. */
4589 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
4590 bgp_path_info_restore(rn
, pi
);
4592 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4594 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4595 && (safi
== SAFI_UNICAST
)) {
4596 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
4598 * Implicit withdraw case.
4599 * We have to do this before pi is
4602 ++vnc_implicit_withdraw
;
4603 vnc_import_bgp_del_route(bgp
, p
, pi
);
4604 vnc_import_bgp_exterior_del_route(
4609 bgp_attr_unintern(&pi
->attr
);
4610 pi
->attr
= attr_new
;
4611 pi
->uptime
= bgp_clock();
4613 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4614 && (safi
== SAFI_UNICAST
)) {
4615 if (vnc_implicit_withdraw
) {
4616 vnc_import_bgp_add_route(bgp
, p
, pi
);
4617 vnc_import_bgp_exterior_add_route(
4623 /* Nexthop reachability check. */
4624 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4625 && (safi
== SAFI_UNICAST
4626 || safi
== SAFI_LABELED_UNICAST
)) {
4628 struct bgp
*bgp_nexthop
= bgp
;
4630 if (pi
->extra
&& pi
->extra
->bgp_orig
)
4631 bgp_nexthop
= pi
->extra
->bgp_orig
;
4633 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
,
4635 bgp_path_info_set_flag(rn
, pi
,
4638 if (BGP_DEBUG(nht
, NHT
)) {
4639 char buf1
[INET6_ADDRSTRLEN
];
4640 inet_ntop(p
->family
,
4644 "%s(%s): Route not in table, not advertising",
4645 __FUNCTION__
, buf1
);
4647 bgp_path_info_unset_flag(
4648 rn
, pi
, BGP_PATH_VALID
);
4651 /* Delete the NHT structure if any, if we're
4653 * enabling/disabling import check. We
4654 * deregister the route
4655 * from NHT to avoid overloading NHT and the
4656 * process interaction
4658 bgp_unlink_nexthop(pi
);
4659 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_VALID
);
4661 /* Process change. */
4662 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
4663 bgp_process(bgp
, rn
, afi
, safi
);
4665 if (SAFI_UNICAST
== safi
4666 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4668 == BGP_INSTANCE_TYPE_DEFAULT
)) {
4669 vpn_leak_from_vrf_update(bgp_get_default(), bgp
,
4673 bgp_unlock_node(rn
);
4674 aspath_unintern(&attr
.aspath
);
4679 /* Make new BGP info. */
4680 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
4682 /* Nexthop reachability check. */
4683 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4684 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
4685 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, new, NULL
, 0))
4686 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
4688 if (BGP_DEBUG(nht
, NHT
)) {
4689 char buf1
[INET6_ADDRSTRLEN
];
4690 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
4693 "%s(%s): Route not in table, not advertising",
4694 __FUNCTION__
, buf1
);
4696 bgp_path_info_unset_flag(rn
, new, BGP_PATH_VALID
);
4699 /* Delete the NHT structure if any, if we're toggling between
4700 * enabling/disabling import check. We deregister the route
4701 * from NHT to avoid overloading NHT and the process interaction
4703 bgp_unlink_nexthop(new);
4705 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
4708 /* Aggregate address increment. */
4709 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4711 /* Register new BGP information. */
4712 bgp_path_info_add(rn
, new);
4714 /* route_node_get lock */
4715 bgp_unlock_node(rn
);
4717 /* Process change. */
4718 bgp_process(bgp
, rn
, afi
, safi
);
4720 if (SAFI_UNICAST
== safi
4721 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4722 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4723 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
4726 /* Unintern original. */
4727 aspath_unintern(&attr
.aspath
);
4730 void bgp_static_withdraw(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
4733 struct bgp_node
*rn
;
4734 struct bgp_path_info
*pi
;
4736 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4738 /* Check selected route and self inserted route. */
4739 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4740 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4741 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4744 /* Withdraw static BGP route from routing table. */
4746 if (SAFI_UNICAST
== safi
4747 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4748 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4749 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
4751 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4752 bgp_unlink_nexthop(pi
);
4753 bgp_path_info_delete(rn
, pi
);
4754 bgp_process(bgp
, rn
, afi
, safi
);
4757 /* Unlock bgp_node_lookup. */
4758 bgp_unlock_node(rn
);
4762 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
4764 static void bgp_static_withdraw_safi(struct bgp
*bgp
, struct prefix
*p
,
4765 afi_t afi
, safi_t safi
,
4766 struct prefix_rd
*prd
)
4768 struct bgp_node
*rn
;
4769 struct bgp_path_info
*pi
;
4771 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4773 /* Check selected route and self inserted route. */
4774 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4775 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4776 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4779 /* Withdraw static BGP route from routing table. */
4782 rfapiProcessWithdraw(
4783 pi
->peer
, NULL
, p
, prd
, pi
->attr
, afi
, safi
, pi
->type
,
4784 1); /* Kill, since it is an administrative change */
4786 if (SAFI_MPLS_VPN
== safi
4787 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4788 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4790 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4791 bgp_path_info_delete(rn
, pi
);
4792 bgp_process(bgp
, rn
, afi
, safi
);
4795 /* Unlock bgp_node_lookup. */
4796 bgp_unlock_node(rn
);
4799 static void bgp_static_update_safi(struct bgp
*bgp
, struct prefix
*p
,
4800 struct bgp_static
*bgp_static
, afi_t afi
,
4803 struct bgp_node
*rn
;
4804 struct bgp_path_info
*new;
4805 struct attr
*attr_new
;
4806 struct attr attr
= {0};
4807 struct bgp_path_info
*pi
;
4809 mpls_label_t label
= 0;
4811 uint32_t num_labels
= 0;
4816 if (bgp_static
->label
!= MPLS_INVALID_LABEL
)
4818 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
4821 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4823 attr
.nexthop
= bgp_static
->igpnexthop
;
4824 attr
.med
= bgp_static
->igpmetric
;
4825 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4827 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
4828 || (safi
== SAFI_ENCAP
)) {
4829 if (afi
== AFI_IP
) {
4830 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
4831 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
4834 if (afi
== AFI_L2VPN
) {
4835 if (bgp_static
->gatewayIp
.family
== AF_INET
)
4837 bgp_static
->gatewayIp
.u
.prefix4
.s_addr
;
4838 else if (bgp_static
->gatewayIp
.family
== AF_INET6
)
4839 memcpy(&(add
.ipv6
), &(bgp_static
->gatewayIp
.u
.prefix6
),
4840 sizeof(struct in6_addr
));
4841 overlay_index_update(&attr
, bgp_static
->eth_s_id
, &add
);
4842 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
4843 struct bgp_encap_type_vxlan bet
;
4844 memset(&bet
, 0, sizeof(struct bgp_encap_type_vxlan
));
4845 bet
.vnid
= p
->u
.prefix_evpn
.prefix_addr
.eth_tag
;
4846 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
4848 if (bgp_static
->router_mac
) {
4849 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
4852 /* Apply route-map. */
4853 if (bgp_static
->rmap
.name
) {
4854 struct attr attr_tmp
= attr
;
4855 struct bgp_path_info rmap_path
;
4858 rmap_path
.peer
= bgp
->peer_self
;
4859 rmap_path
.attr
= &attr_tmp
;
4861 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4863 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
,
4866 bgp
->peer_self
->rmap_type
= 0;
4868 if (ret
== RMAP_DENYMATCH
) {
4869 /* Free uninterned attribute. */
4870 bgp_attr_flush(&attr_tmp
);
4872 /* Unintern original. */
4873 aspath_unintern(&attr
.aspath
);
4874 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
4879 attr_new
= bgp_attr_intern(&attr_tmp
);
4881 attr_new
= bgp_attr_intern(&attr
);
4884 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4885 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4886 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4890 memset(&add
, 0, sizeof(union gw_addr
));
4891 if (attrhash_cmp(pi
->attr
, attr_new
)
4892 && overlay_index_equal(afi
, pi
, bgp_static
->eth_s_id
, &add
)
4893 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
4894 bgp_unlock_node(rn
);
4895 bgp_attr_unintern(&attr_new
);
4896 aspath_unintern(&attr
.aspath
);
4899 /* The attribute is changed. */
4900 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_ATTR_CHANGED
);
4902 /* Rewrite BGP route information. */
4903 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
4904 bgp_path_info_restore(rn
, pi
);
4906 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4907 bgp_attr_unintern(&pi
->attr
);
4908 pi
->attr
= attr_new
;
4909 pi
->uptime
= bgp_clock();
4912 label
= decode_label(&pi
->extra
->label
[0]);
4915 /* Process change. */
4916 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
4917 bgp_process(bgp
, rn
, afi
, safi
);
4919 if (SAFI_MPLS_VPN
== safi
4920 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4921 vpn_leak_to_vrf_update(bgp
, pi
);
4924 rfapiProcessUpdate(pi
->peer
, NULL
, p
, &bgp_static
->prd
,
4925 pi
->attr
, afi
, safi
, pi
->type
,
4926 pi
->sub_type
, &label
);
4928 bgp_unlock_node(rn
);
4929 aspath_unintern(&attr
.aspath
);
4935 /* Make new BGP info. */
4936 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
4938 SET_FLAG(new->flags
, BGP_PATH_VALID
);
4939 new->extra
= bgp_path_info_extra_new();
4941 new->extra
->label
[0] = bgp_static
->label
;
4942 new->extra
->num_labels
= num_labels
;
4945 label
= decode_label(&bgp_static
->label
);
4948 /* Aggregate address increment. */
4949 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4951 /* Register new BGP information. */
4952 bgp_path_info_add(rn
, new);
4953 /* route_node_get lock */
4954 bgp_unlock_node(rn
);
4956 /* Process change. */
4957 bgp_process(bgp
, rn
, afi
, safi
);
4959 if (SAFI_MPLS_VPN
== safi
4960 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4961 vpn_leak_to_vrf_update(bgp
, new);
4964 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
4965 safi
, new->type
, new->sub_type
, &label
);
4968 /* Unintern original. */
4969 aspath_unintern(&attr
.aspath
);
4972 /* Configure static BGP network. When user don't run zebra, static
4973 route should be installed as valid. */
4974 static int bgp_static_set(struct vty
*vty
, const char *negate
,
4975 const char *ip_str
, afi_t afi
, safi_t safi
,
4976 const char *rmap
, int backdoor
, uint32_t label_index
)
4978 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
4981 struct bgp_static
*bgp_static
;
4982 struct bgp_node
*rn
;
4983 uint8_t need_update
= 0;
4985 /* Convert IP prefix string to struct prefix. */
4986 ret
= str2prefix(ip_str
, &p
);
4988 vty_out(vty
, "%% Malformed prefix\n");
4989 return CMD_WARNING_CONFIG_FAILED
;
4991 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4992 vty_out(vty
, "%% Malformed prefix (link-local address)\n");
4993 return CMD_WARNING_CONFIG_FAILED
;
5000 /* Set BGP static route configuration. */
5001 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
5004 vty_out(vty
, "%% Can't find static route specified\n");
5005 return CMD_WARNING_CONFIG_FAILED
;
5008 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5010 if ((label_index
!= BGP_INVALID_LABEL_INDEX
)
5011 && (label_index
!= bgp_static
->label_index
)) {
5013 "%% label-index doesn't match static route\n");
5014 return CMD_WARNING_CONFIG_FAILED
;
5017 if ((rmap
&& bgp_static
->rmap
.name
)
5018 && strcmp(rmap
, bgp_static
->rmap
.name
)) {
5020 "%% route-map name doesn't match static route\n");
5021 return CMD_WARNING_CONFIG_FAILED
;
5024 /* Update BGP RIB. */
5025 if (!bgp_static
->backdoor
)
5026 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
5028 /* Clear configuration. */
5029 bgp_static_free(bgp_static
);
5030 bgp_node_set_bgp_static_info(rn
, NULL
);
5031 bgp_unlock_node(rn
);
5032 bgp_unlock_node(rn
);
5035 /* Set BGP static route configuration. */
5036 rn
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
5038 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5040 /* Configuration change. */
5041 /* Label index cannot be changed. */
5042 if (bgp_static
->label_index
!= label_index
) {
5043 vty_out(vty
, "%% cannot change label-index\n");
5044 return CMD_WARNING_CONFIG_FAILED
;
5047 /* Check previous routes are installed into BGP. */
5048 if (bgp_static
->valid
5049 && bgp_static
->backdoor
!= backdoor
)
5052 bgp_static
->backdoor
= backdoor
;
5055 XFREE(MTYPE_ROUTE_MAP_NAME
,
5056 bgp_static
->rmap
.name
);
5057 route_map_counter_decrement(
5058 bgp_static
->rmap
.map
);
5059 bgp_static
->rmap
.name
=
5060 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
5061 bgp_static
->rmap
.map
=
5062 route_map_lookup_by_name(rmap
);
5063 route_map_counter_increment(
5064 bgp_static
->rmap
.map
);
5066 XFREE(MTYPE_ROUTE_MAP_NAME
,
5067 bgp_static
->rmap
.name
);
5068 route_map_counter_decrement(
5069 bgp_static
->rmap
.map
);
5070 bgp_static
->rmap
.name
= NULL
;
5071 bgp_static
->rmap
.map
= NULL
;
5072 bgp_static
->valid
= 0;
5074 bgp_unlock_node(rn
);
5076 /* New configuration. */
5077 bgp_static
= bgp_static_new();
5078 bgp_static
->backdoor
= backdoor
;
5079 bgp_static
->valid
= 0;
5080 bgp_static
->igpmetric
= 0;
5081 bgp_static
->igpnexthop
.s_addr
= 0;
5082 bgp_static
->label_index
= label_index
;
5085 XFREE(MTYPE_ROUTE_MAP_NAME
,
5086 bgp_static
->rmap
.name
);
5087 route_map_counter_decrement(
5088 bgp_static
->rmap
.map
);
5089 bgp_static
->rmap
.name
=
5090 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
5091 bgp_static
->rmap
.map
=
5092 route_map_lookup_by_name(rmap
);
5093 route_map_counter_increment(
5094 bgp_static
->rmap
.map
);
5096 bgp_node_set_bgp_static_info(rn
, bgp_static
);
5099 bgp_static
->valid
= 1;
5101 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
5103 if (!bgp_static
->backdoor
)
5104 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
5110 void bgp_static_add(struct bgp
*bgp
)
5114 struct bgp_node
*rn
;
5115 struct bgp_node
*rm
;
5116 struct bgp_table
*table
;
5117 struct bgp_static
*bgp_static
;
5119 FOREACH_AFI_SAFI (afi
, safi
)
5120 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5121 rn
= bgp_route_next(rn
)) {
5122 if (!bgp_node_has_bgp_path_info_data(rn
))
5125 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5126 || (safi
== SAFI_EVPN
)) {
5127 table
= bgp_node_get_bgp_table_info(rn
);
5129 for (rm
= bgp_table_top(table
); rm
;
5130 rm
= bgp_route_next(rm
)) {
5132 bgp_node_get_bgp_static_info(
5134 bgp_static_update_safi(bgp
, &rm
->p
,
5141 bgp_node_get_bgp_static_info(rn
), afi
,
5147 /* Called from bgp_delete(). Delete all static routes from the BGP
5149 void bgp_static_delete(struct bgp
*bgp
)
5153 struct bgp_node
*rn
;
5154 struct bgp_node
*rm
;
5155 struct bgp_table
*table
;
5156 struct bgp_static
*bgp_static
;
5158 FOREACH_AFI_SAFI (afi
, safi
)
5159 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5160 rn
= bgp_route_next(rn
)) {
5161 if (!bgp_node_has_bgp_path_info_data(rn
))
5164 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5165 || (safi
== SAFI_EVPN
)) {
5166 table
= bgp_node_get_bgp_table_info(rn
);
5168 for (rm
= bgp_table_top(table
); rm
;
5169 rm
= bgp_route_next(rm
)) {
5171 bgp_node_get_bgp_static_info(
5176 bgp_static_withdraw_safi(
5177 bgp
, &rm
->p
, AFI_IP
, safi
,
5178 (struct prefix_rd
*)&rn
->p
);
5179 bgp_static_free(bgp_static
);
5180 bgp_node_set_bgp_static_info(rn
, NULL
);
5181 bgp_unlock_node(rn
);
5184 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5185 bgp_static_withdraw(bgp
, &rn
->p
, afi
, safi
);
5186 bgp_static_free(bgp_static
);
5187 bgp_node_set_bgp_static_info(rn
, NULL
);
5188 bgp_unlock_node(rn
);
5193 void bgp_static_redo_import_check(struct bgp
*bgp
)
5197 struct bgp_node
*rn
;
5198 struct bgp_node
*rm
;
5199 struct bgp_table
*table
;
5200 struct bgp_static
*bgp_static
;
5202 /* Use this flag to force reprocessing of the route */
5203 bgp_flag_set(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5204 FOREACH_AFI_SAFI (afi
, safi
) {
5205 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5206 rn
= bgp_route_next(rn
)) {
5207 if (!bgp_node_has_bgp_path_info_data(rn
))
5210 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5211 || (safi
== SAFI_EVPN
)) {
5212 table
= bgp_node_get_bgp_table_info(rn
);
5214 for (rm
= bgp_table_top(table
); rm
;
5215 rm
= bgp_route_next(rm
)) {
5217 bgp_node_get_bgp_static_info(
5219 bgp_static_update_safi(bgp
, &rm
->p
,
5224 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5225 bgp_static_update(bgp
, &rn
->p
, bgp_static
, afi
,
5230 bgp_flag_unset(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5233 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
5236 struct bgp_table
*table
;
5237 struct bgp_node
*rn
;
5238 struct bgp_path_info
*pi
;
5240 table
= bgp
->rib
[afi
][safi
];
5241 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
5242 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
5243 if (pi
->peer
== bgp
->peer_self
5244 && ((pi
->type
== ZEBRA_ROUTE_BGP
5245 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5246 || (pi
->type
!= ZEBRA_ROUTE_BGP
5248 == BGP_ROUTE_REDISTRIBUTE
))) {
5249 bgp_aggregate_decrement(bgp
, &rn
->p
, pi
, afi
,
5251 bgp_unlink_nexthop(pi
);
5252 bgp_path_info_delete(rn
, pi
);
5253 bgp_process(bgp
, rn
, afi
, safi
);
5260 * Purge all networks and redistributed routes from routing table.
5261 * Invoked upon the instance going down.
5263 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
5268 FOREACH_AFI_SAFI (afi
, safi
)
5269 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
5274 * Currently this is used to set static routes for VPN and ENCAP.
5275 * I think it can probably be factored with bgp_static_set.
5277 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5278 const char *ip_str
, const char *rd_str
,
5279 const char *label_str
, const char *rmap_str
,
5280 int evpn_type
, const char *esi
, const char *gwip
,
5281 const char *ethtag
, const char *routermac
)
5283 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5286 struct prefix_rd prd
;
5287 struct bgp_node
*prn
;
5288 struct bgp_node
*rn
;
5289 struct bgp_table
*table
;
5290 struct bgp_static
*bgp_static
;
5291 mpls_label_t label
= MPLS_INVALID_LABEL
;
5292 struct prefix gw_ip
;
5294 /* validate ip prefix */
5295 ret
= str2prefix(ip_str
, &p
);
5297 vty_out(vty
, "%% Malformed prefix\n");
5298 return CMD_WARNING_CONFIG_FAILED
;
5301 if ((afi
== AFI_L2VPN
)
5302 && (bgp_build_evpn_prefix(evpn_type
,
5303 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5304 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5305 return CMD_WARNING_CONFIG_FAILED
;
5308 ret
= str2prefix_rd(rd_str
, &prd
);
5310 vty_out(vty
, "%% Malformed rd\n");
5311 return CMD_WARNING_CONFIG_FAILED
;
5315 unsigned long label_val
;
5316 label_val
= strtoul(label_str
, NULL
, 10);
5317 encode_label(label_val
, &label
);
5320 if (safi
== SAFI_EVPN
) {
5321 if (esi
&& str2esi(esi
, NULL
) == 0) {
5322 vty_out(vty
, "%% Malformed ESI\n");
5323 return CMD_WARNING_CONFIG_FAILED
;
5325 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
5326 vty_out(vty
, "%% Malformed Router MAC\n");
5327 return CMD_WARNING_CONFIG_FAILED
;
5330 memset(&gw_ip
, 0, sizeof(struct prefix
));
5331 ret
= str2prefix(gwip
, &gw_ip
);
5333 vty_out(vty
, "%% Malformed GatewayIp\n");
5334 return CMD_WARNING_CONFIG_FAILED
;
5336 if ((gw_ip
.family
== AF_INET
5337 && is_evpn_prefix_ipaddr_v6(
5338 (struct prefix_evpn
*)&p
))
5339 || (gw_ip
.family
== AF_INET6
5340 && is_evpn_prefix_ipaddr_v4(
5341 (struct prefix_evpn
*)&p
))) {
5343 "%% GatewayIp family differs with IP prefix\n");
5344 return CMD_WARNING_CONFIG_FAILED
;
5348 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5349 if (!bgp_node_has_bgp_path_info_data(prn
))
5350 bgp_node_set_bgp_table_info(prn
,
5351 bgp_table_init(bgp
, afi
, safi
));
5352 table
= bgp_node_get_bgp_table_info(prn
);
5354 rn
= bgp_node_get(table
, &p
);
5356 if (bgp_node_has_bgp_path_info_data(rn
)) {
5357 vty_out(vty
, "%% Same network configuration exists\n");
5358 bgp_unlock_node(rn
);
5360 /* New configuration. */
5361 bgp_static
= bgp_static_new();
5362 bgp_static
->backdoor
= 0;
5363 bgp_static
->valid
= 0;
5364 bgp_static
->igpmetric
= 0;
5365 bgp_static
->igpnexthop
.s_addr
= 0;
5366 bgp_static
->label
= label
;
5367 bgp_static
->prd
= prd
;
5370 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
5371 route_map_counter_decrement(bgp_static
->rmap
.map
);
5372 bgp_static
->rmap
.name
=
5373 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
5374 bgp_static
->rmap
.map
=
5375 route_map_lookup_by_name(rmap_str
);
5376 route_map_counter_increment(bgp_static
->rmap
.map
);
5379 if (safi
== SAFI_EVPN
) {
5381 bgp_static
->eth_s_id
=
5383 sizeof(struct eth_segment_id
));
5384 str2esi(esi
, bgp_static
->eth_s_id
);
5387 bgp_static
->router_mac
=
5388 XCALLOC(MTYPE_ATTR
, ETH_ALEN
+ 1);
5389 (void)prefix_str2mac(routermac
,
5390 bgp_static
->router_mac
);
5393 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
5395 bgp_node_set_bgp_static_info(rn
, bgp_static
);
5397 bgp_static
->valid
= 1;
5398 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
5404 /* Configure static BGP network. */
5405 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5406 const char *ip_str
, const char *rd_str
,
5407 const char *label_str
, int evpn_type
, const char *esi
,
5408 const char *gwip
, const char *ethtag
)
5410 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5413 struct prefix_rd prd
;
5414 struct bgp_node
*prn
;
5415 struct bgp_node
*rn
;
5416 struct bgp_table
*table
;
5417 struct bgp_static
*bgp_static
;
5418 mpls_label_t label
= MPLS_INVALID_LABEL
;
5420 /* Convert IP prefix string to struct prefix. */
5421 ret
= str2prefix(ip_str
, &p
);
5423 vty_out(vty
, "%% Malformed prefix\n");
5424 return CMD_WARNING_CONFIG_FAILED
;
5427 if ((afi
== AFI_L2VPN
)
5428 && (bgp_build_evpn_prefix(evpn_type
,
5429 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5430 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5431 return CMD_WARNING_CONFIG_FAILED
;
5433 ret
= str2prefix_rd(rd_str
, &prd
);
5435 vty_out(vty
, "%% Malformed rd\n");
5436 return CMD_WARNING_CONFIG_FAILED
;
5440 unsigned long label_val
;
5441 label_val
= strtoul(label_str
, NULL
, 10);
5442 encode_label(label_val
, &label
);
5445 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5446 if (!bgp_node_has_bgp_path_info_data(prn
))
5447 bgp_node_set_bgp_table_info(prn
,
5448 bgp_table_init(bgp
, afi
, safi
));
5450 bgp_unlock_node(prn
);
5451 table
= bgp_node_get_bgp_table_info(prn
);
5453 rn
= bgp_node_lookup(table
, &p
);
5456 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
5458 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5459 bgp_static_free(bgp_static
);
5460 bgp_node_set_bgp_static_info(rn
, NULL
);
5461 bgp_unlock_node(rn
);
5462 bgp_unlock_node(rn
);
5464 vty_out(vty
, "%% Can't find the route\n");
5469 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
5470 const char *rmap_name
)
5472 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5473 struct bgp_rmap
*rmap
;
5475 rmap
= &bgp
->table_map
[afi
][safi
];
5477 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5478 route_map_counter_decrement(rmap
->map
);
5479 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
5480 rmap
->map
= route_map_lookup_by_name(rmap_name
);
5481 route_map_counter_increment(rmap
->map
);
5483 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5484 route_map_counter_decrement(rmap
->map
);
5489 if (bgp_fibupd_safi(safi
))
5490 bgp_zebra_announce_table(bgp
, afi
, safi
);
5495 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
5496 const char *rmap_name
)
5498 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5499 struct bgp_rmap
*rmap
;
5501 rmap
= &bgp
->table_map
[afi
][safi
];
5502 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5503 route_map_counter_decrement(rmap
->map
);
5507 if (bgp_fibupd_safi(safi
))
5508 bgp_zebra_announce_table(bgp
, afi
, safi
);
5513 void bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
5516 if (bgp
->table_map
[afi
][safi
].name
) {
5517 vty_out(vty
, " table-map %s\n",
5518 bgp
->table_map
[afi
][safi
].name
);
5522 DEFUN (bgp_table_map
,
5525 "BGP table to RIB route download filter\n"
5526 "Name of the route map\n")
5529 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5530 argv
[idx_word
]->arg
);
5532 DEFUN (no_bgp_table_map
,
5533 no_bgp_table_map_cmd
,
5534 "no table-map WORD",
5536 "BGP table to RIB route download filter\n"
5537 "Name of the route map\n")
5540 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5541 argv
[idx_word
]->arg
);
5547 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
5548 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
5549 backdoor$backdoor}]",
5551 "Specify a network to announce via BGP\n"
5556 "Route-map to modify the attributes\n"
5557 "Name of the route map\n"
5558 "Label index to associate with the prefix\n"
5559 "Label index value\n"
5560 "Specify a BGP backdoor route\n")
5562 char addr_prefix_str
[BUFSIZ
];
5567 ret
= netmask_str2prefix_str(address_str
, netmask_str
,
5570 vty_out(vty
, "%% Inconsistent address and mask\n");
5571 return CMD_WARNING_CONFIG_FAILED
;
5575 return bgp_static_set(
5576 vty
, no
, address_str
? addr_prefix_str
: prefix_str
, AFI_IP
,
5577 bgp_node_safi(vty
), map_name
, backdoor
? 1 : 0,
5578 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5581 DEFPY(ipv6_bgp_network
,
5582 ipv6_bgp_network_cmd
,
5583 "[no] network X:X::X:X/M$prefix \
5584 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
5586 "Specify a network to announce via BGP\n"
5588 "Route-map to modify the attributes\n"
5589 "Name of the route map\n"
5590 "Label index to associate with the prefix\n"
5591 "Label index value\n")
5593 return bgp_static_set(
5594 vty
, no
, prefix_str
, AFI_IP6
, bgp_node_safi(vty
), map_name
, 0,
5595 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5598 static struct bgp_aggregate
*bgp_aggregate_new(void)
5600 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
5603 static void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
5605 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
5608 static int bgp_aggregate_info_same(struct bgp_path_info
*pi
, uint8_t origin
,
5609 struct aspath
*aspath
,
5610 struct community
*comm
,
5611 struct ecommunity
*ecomm
,
5612 struct lcommunity
*lcomm
)
5614 static struct aspath
*ae
= NULL
;
5617 ae
= aspath_empty();
5622 if (origin
!= pi
->attr
->origin
)
5625 if (!aspath_cmp(pi
->attr
->aspath
, (aspath
) ? aspath
: ae
))
5628 if (!community_cmp(pi
->attr
->community
, comm
))
5631 if (!ecommunity_cmp(pi
->attr
->ecommunity
, ecomm
))
5634 if (!lcommunity_cmp(pi
->attr
->lcommunity
, lcomm
))
5637 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
5643 static void bgp_aggregate_install(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
5644 struct prefix
*p
, uint8_t origin
,
5645 struct aspath
*aspath
,
5646 struct community
*community
,
5647 struct ecommunity
*ecommunity
,
5648 struct lcommunity
*lcommunity
,
5649 uint8_t atomic_aggregate
,
5650 struct bgp_aggregate
*aggregate
)
5652 struct bgp_node
*rn
;
5653 struct bgp_table
*table
;
5654 struct bgp_path_info
*pi
, *orig
, *new;
5656 table
= bgp
->rib
[afi
][safi
];
5658 rn
= bgp_node_get(table
, p
);
5660 for (orig
= pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
5661 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5662 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5665 if (aggregate
->count
> 0) {
5667 * If the aggregate information has not changed
5668 * no need to re-install it again.
5670 if (bgp_aggregate_info_same(orig
, origin
, aspath
, community
,
5671 ecommunity
, lcommunity
)) {
5672 bgp_unlock_node(rn
);
5675 aspath_free(aspath
);
5677 community_free(&community
);
5679 ecommunity_free(&ecommunity
);
5681 lcommunity_free(&lcommunity
);
5687 * Mark the old as unusable
5690 bgp_path_info_delete(rn
, pi
);
5692 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0,
5694 bgp_attr_aggregate_intern(bgp
, origin
, aspath
,
5695 community
, ecommunity
,
5700 SET_FLAG(new->flags
, BGP_PATH_VALID
);
5702 bgp_path_info_add(rn
, new);
5703 bgp_process(bgp
, rn
, afi
, safi
);
5705 for (pi
= orig
; pi
; pi
= pi
->next
)
5706 if (pi
->peer
== bgp
->peer_self
5707 && pi
->type
== ZEBRA_ROUTE_BGP
5708 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5711 /* Withdraw static BGP route from routing table. */
5713 bgp_path_info_delete(rn
, pi
);
5714 bgp_process(bgp
, rn
, afi
, safi
);
5718 bgp_unlock_node(rn
);
5721 /* Update an aggregate as routes are added/removed from the BGP table */
5722 static void bgp_aggregate_route(struct bgp
*bgp
, struct prefix
*p
,
5723 afi_t afi
, safi_t safi
,
5724 struct bgp_aggregate
*aggregate
)
5726 struct bgp_table
*table
;
5727 struct bgp_node
*top
;
5728 struct bgp_node
*rn
;
5730 struct aspath
*aspath
= NULL
;
5731 struct community
*community
= NULL
;
5732 struct ecommunity
*ecommunity
= NULL
;
5733 struct lcommunity
*lcommunity
= NULL
;
5734 struct bgp_path_info
*pi
;
5735 unsigned long match
= 0;
5736 uint8_t atomic_aggregate
= 0;
5738 /* ORIGIN attribute: If at least one route among routes that are
5739 aggregated has ORIGIN with the value INCOMPLETE, then the
5740 aggregated route must have the ORIGIN attribute with the value
5741 INCOMPLETE. Otherwise, if at least one route among routes that
5742 are aggregated has ORIGIN with the value EGP, then the aggregated
5743 route must have the origin attribute with the value EGP. In all
5744 other case the value of the ORIGIN attribute of the aggregated
5745 route is INTERNAL. */
5746 origin
= BGP_ORIGIN_IGP
;
5748 table
= bgp
->rib
[afi
][safi
];
5750 top
= bgp_node_get(table
, p
);
5751 for (rn
= bgp_node_get(table
, p
); rn
;
5752 rn
= bgp_route_next_until(rn
, top
)) {
5753 if (rn
->p
.prefixlen
<= p
->prefixlen
)
5758 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
5759 if (BGP_PATH_HOLDDOWN(pi
))
5763 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
5764 atomic_aggregate
= 1;
5766 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5770 * summary-only aggregate route suppress
5771 * aggregated route announcements.
5773 if (aggregate
->summary_only
) {
5774 (bgp_path_info_extra_get(pi
))->suppress
++;
5775 bgp_path_info_set_flag(rn
, pi
,
5776 BGP_PATH_ATTR_CHANGED
);
5783 * If at least one route among routes that are
5784 * aggregated has ORIGIN with the value INCOMPLETE,
5785 * then the aggregated route MUST have the ORIGIN
5786 * attribute with the value INCOMPLETE. Otherwise, if
5787 * at least one route among routes that are aggregated
5788 * has ORIGIN with the value EGP, then the aggregated
5789 * route MUST have the ORIGIN attribute with the value
5792 switch (pi
->attr
->origin
) {
5793 case BGP_ORIGIN_INCOMPLETE
:
5794 aggregate
->incomplete_origin_count
++;
5796 case BGP_ORIGIN_EGP
:
5797 aggregate
->egp_origin_count
++;
5805 if (!aggregate
->as_set
)
5809 * as-set aggregate route generate origin, as path,
5810 * and community aggregation.
5812 /* Compute aggregate route's as-path.
5814 bgp_compute_aggregate_aspath(aggregate
,
5817 /* Compute aggregate route's community.
5819 if (pi
->attr
->community
)
5820 bgp_compute_aggregate_community(
5822 pi
->attr
->community
);
5824 /* Compute aggregate route's extended community.
5826 if (pi
->attr
->ecommunity
)
5827 bgp_compute_aggregate_ecommunity(
5829 pi
->attr
->ecommunity
);
5831 /* Compute aggregate route's large community.
5833 if (pi
->attr
->lcommunity
)
5834 bgp_compute_aggregate_lcommunity(
5836 pi
->attr
->lcommunity
);
5839 bgp_process(bgp
, rn
, afi
, safi
);
5841 bgp_unlock_node(top
);
5844 if (aggregate
->incomplete_origin_count
> 0)
5845 origin
= BGP_ORIGIN_INCOMPLETE
;
5846 else if (aggregate
->egp_origin_count
> 0)
5847 origin
= BGP_ORIGIN_EGP
;
5849 if (aggregate
->as_set
) {
5850 if (aggregate
->aspath
)
5851 /* Retrieve aggregate route's as-path.
5853 aspath
= aspath_dup(aggregate
->aspath
);
5855 if (aggregate
->community
)
5856 /* Retrieve aggregate route's community.
5858 community
= community_dup(aggregate
->community
);
5860 if (aggregate
->ecommunity
)
5861 /* Retrieve aggregate route's ecommunity.
5863 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
5865 if (aggregate
->lcommunity
)
5866 /* Retrieve aggregate route's lcommunity.
5868 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
5871 bgp_aggregate_install(bgp
, afi
, safi
, p
, origin
, aspath
, community
,
5872 ecommunity
, lcommunity
, atomic_aggregate
,
5876 static void bgp_aggregate_delete(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
5877 safi_t safi
, struct bgp_aggregate
*aggregate
)
5879 struct bgp_table
*table
;
5880 struct bgp_node
*top
;
5881 struct bgp_node
*rn
;
5882 struct bgp_path_info
*pi
;
5883 unsigned long match
;
5885 table
= bgp
->rib
[afi
][safi
];
5887 /* If routes exists below this node, generate aggregate routes. */
5888 top
= bgp_node_get(table
, p
);
5889 for (rn
= bgp_node_get(table
, p
); rn
;
5890 rn
= bgp_route_next_until(rn
, top
)) {
5891 if (rn
->p
.prefixlen
<= p
->prefixlen
)
5895 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
5896 if (BGP_PATH_HOLDDOWN(pi
))
5899 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5902 if (aggregate
->summary_only
&& pi
->extra
) {
5903 pi
->extra
->suppress
--;
5905 if (pi
->extra
->suppress
== 0) {
5906 bgp_path_info_set_flag(
5907 rn
, pi
, BGP_PATH_ATTR_CHANGED
);
5913 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
5914 aggregate
->incomplete_origin_count
--;
5915 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
5916 aggregate
->egp_origin_count
--;
5918 if (aggregate
->as_set
) {
5919 /* Remove as-path from aggregate.
5921 bgp_remove_aspath_from_aggregate(
5925 if (pi
->attr
->community
)
5926 /* Remove community from aggregate.
5928 bgp_remove_community_from_aggregate(
5930 pi
->attr
->community
);
5932 if (pi
->attr
->ecommunity
)
5933 /* Remove ecommunity from aggregate.
5935 bgp_remove_ecommunity_from_aggregate(
5937 pi
->attr
->ecommunity
);
5939 if (pi
->attr
->lcommunity
)
5940 /* Remove lcommunity from aggregate.
5942 bgp_remove_lcommunity_from_aggregate(
5944 pi
->attr
->lcommunity
);
5949 /* If this node was suppressed, process the change. */
5951 bgp_process(bgp
, rn
, afi
, safi
);
5953 bgp_unlock_node(top
);
5956 static void bgp_add_route_to_aggregate(struct bgp
*bgp
, struct prefix
*aggr_p
,
5957 struct bgp_path_info
*pinew
, afi_t afi
,
5959 struct bgp_aggregate
*aggregate
)
5962 struct aspath
*aspath
= NULL
;
5963 uint8_t atomic_aggregate
= 0;
5964 struct community
*community
= NULL
;
5965 struct ecommunity
*ecommunity
= NULL
;
5966 struct lcommunity
*lcommunity
= NULL
;
5968 /* ORIGIN attribute: If at least one route among routes that are
5969 * aggregated has ORIGIN with the value INCOMPLETE, then the
5970 * aggregated route must have the ORIGIN attribute with the value
5971 * INCOMPLETE. Otherwise, if at least one route among routes that
5972 * are aggregated has ORIGIN with the value EGP, then the aggregated
5973 * route must have the origin attribute with the value EGP. In all
5974 * other case the value of the ORIGIN attribute of the aggregated
5975 * route is INTERNAL.
5977 origin
= BGP_ORIGIN_IGP
;
5981 if (aggregate
->summary_only
)
5982 (bgp_path_info_extra_get(pinew
))->suppress
++;
5984 switch (pinew
->attr
->origin
) {
5985 case BGP_ORIGIN_INCOMPLETE
:
5986 aggregate
->incomplete_origin_count
++;
5988 case BGP_ORIGIN_EGP
:
5989 aggregate
->egp_origin_count
++;
5997 if (aggregate
->incomplete_origin_count
> 0)
5998 origin
= BGP_ORIGIN_INCOMPLETE
;
5999 else if (aggregate
->egp_origin_count
> 0)
6000 origin
= BGP_ORIGIN_EGP
;
6002 if (aggregate
->as_set
) {
6003 /* Compute aggregate route's as-path.
6005 bgp_compute_aggregate_aspath(aggregate
,
6006 pinew
->attr
->aspath
);
6008 /* Compute aggregate route's community.
6010 if (pinew
->attr
->community
)
6011 bgp_compute_aggregate_community(
6013 pinew
->attr
->community
);
6015 /* Compute aggregate route's extended community.
6017 if (pinew
->attr
->ecommunity
)
6018 bgp_compute_aggregate_ecommunity(
6020 pinew
->attr
->ecommunity
);
6022 /* Compute aggregate route's large community.
6024 if (pinew
->attr
->lcommunity
)
6025 bgp_compute_aggregate_lcommunity(
6027 pinew
->attr
->lcommunity
);
6029 /* Retrieve aggregate route's as-path.
6031 if (aggregate
->aspath
)
6032 aspath
= aspath_dup(aggregate
->aspath
);
6034 /* Retrieve aggregate route's community.
6036 if (aggregate
->community
)
6037 community
= community_dup(aggregate
->community
);
6039 /* Retrieve aggregate route's ecommunity.
6041 if (aggregate
->ecommunity
)
6042 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
6044 /* Retrieve aggregate route's lcommunity.
6046 if (aggregate
->lcommunity
)
6047 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
6050 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
6051 aspath
, community
, ecommunity
,
6052 lcommunity
, atomic_aggregate
, aggregate
);
6055 static void bgp_remove_route_from_aggregate(struct bgp
*bgp
, afi_t afi
,
6057 struct bgp_path_info
*pi
,
6058 struct bgp_aggregate
*aggregate
,
6059 struct prefix
*aggr_p
)
6062 struct aspath
*aspath
= NULL
;
6063 uint8_t atomic_aggregate
= 0;
6064 struct community
*community
= NULL
;
6065 struct ecommunity
*ecommunity
= NULL
;
6066 struct lcommunity
*lcommunity
= NULL
;
6067 unsigned long match
= 0;
6069 if (BGP_PATH_HOLDDOWN(pi
))
6072 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6075 if (aggregate
->summary_only
6077 && pi
->extra
->suppress
> 0) {
6078 pi
->extra
->suppress
--;
6080 if (pi
->extra
->suppress
== 0) {
6081 bgp_path_info_set_flag(pi
->net
, pi
,
6082 BGP_PATH_ATTR_CHANGED
);
6087 if (aggregate
->count
> 0)
6090 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
6091 aggregate
->incomplete_origin_count
--;
6092 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
6093 aggregate
->egp_origin_count
--;
6095 if (aggregate
->as_set
) {
6096 /* Remove as-path from aggregate.
6098 bgp_remove_aspath_from_aggregate(aggregate
,
6101 if (pi
->attr
->community
)
6102 /* Remove community from aggregate.
6104 bgp_remove_community_from_aggregate(
6106 pi
->attr
->community
);
6108 if (pi
->attr
->ecommunity
)
6109 /* Remove ecommunity from aggregate.
6111 bgp_remove_ecommunity_from_aggregate(
6113 pi
->attr
->ecommunity
);
6115 if (pi
->attr
->lcommunity
)
6116 /* Remove lcommunity from aggregate.
6118 bgp_remove_lcommunity_from_aggregate(
6120 pi
->attr
->lcommunity
);
6123 /* If this node was suppressed, process the change. */
6125 bgp_process(bgp
, pi
->net
, afi
, safi
);
6127 origin
= BGP_ORIGIN_IGP
;
6128 if (aggregate
->incomplete_origin_count
> 0)
6129 origin
= BGP_ORIGIN_INCOMPLETE
;
6130 else if (aggregate
->egp_origin_count
> 0)
6131 origin
= BGP_ORIGIN_EGP
;
6133 if (aggregate
->as_set
) {
6134 /* Retrieve aggregate route's as-path.
6136 if (aggregate
->aspath
)
6137 aspath
= aspath_dup(aggregate
->aspath
);
6139 /* Retrieve aggregate route's community.
6141 if (aggregate
->community
)
6142 community
= community_dup(aggregate
->community
);
6144 /* Retrieve aggregate route's ecommunity.
6146 if (aggregate
->ecommunity
)
6147 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
6149 /* Retrieve aggregate route's lcommunity.
6151 if (aggregate
->lcommunity
)
6152 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
6155 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
6156 aspath
, community
, ecommunity
,
6157 lcommunity
, atomic_aggregate
, aggregate
);
6160 void bgp_aggregate_increment(struct bgp
*bgp
, struct prefix
*p
,
6161 struct bgp_path_info
*pi
, afi_t afi
, safi_t safi
)
6163 struct bgp_node
*child
;
6164 struct bgp_node
*rn
;
6165 struct bgp_aggregate
*aggregate
;
6166 struct bgp_table
*table
;
6168 table
= bgp
->aggregate
[afi
][safi
];
6170 /* No aggregates configured. */
6171 if (bgp_table_top_nolock(table
) == NULL
)
6174 if (p
->prefixlen
== 0)
6177 if (BGP_PATH_HOLDDOWN(pi
))
6180 child
= bgp_node_get(table
, p
);
6182 /* Aggregate address configuration check. */
6183 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
)) {
6184 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6185 if (aggregate
!= NULL
&& rn
->p
.prefixlen
< p
->prefixlen
) {
6186 bgp_add_route_to_aggregate(bgp
, &rn
->p
, pi
, afi
,
6190 bgp_unlock_node(child
);
6193 void bgp_aggregate_decrement(struct bgp
*bgp
, struct prefix
*p
,
6194 struct bgp_path_info
*del
, afi_t afi
, safi_t safi
)
6196 struct bgp_node
*child
;
6197 struct bgp_node
*rn
;
6198 struct bgp_aggregate
*aggregate
;
6199 struct bgp_table
*table
;
6201 table
= bgp
->aggregate
[afi
][safi
];
6203 /* No aggregates configured. */
6204 if (bgp_table_top_nolock(table
) == NULL
)
6207 if (p
->prefixlen
== 0)
6210 child
= bgp_node_get(table
, p
);
6212 /* Aggregate address configuration check. */
6213 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
)) {
6214 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6215 if (aggregate
!= NULL
&& rn
->p
.prefixlen
< p
->prefixlen
) {
6216 bgp_remove_route_from_aggregate(bgp
, afi
, safi
,
6217 del
, aggregate
, &rn
->p
);
6220 bgp_unlock_node(child
);
6223 /* Aggregate route attribute. */
6224 #define AGGREGATE_SUMMARY_ONLY 1
6225 #define AGGREGATE_AS_SET 1
6227 static int bgp_aggregate_unset(struct vty
*vty
, const char *prefix_str
,
6228 afi_t afi
, safi_t safi
)
6230 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6233 struct bgp_node
*rn
;
6234 struct bgp_aggregate
*aggregate
;
6236 /* Convert string to prefix structure. */
6237 ret
= str2prefix(prefix_str
, &p
);
6239 vty_out(vty
, "Malformed prefix\n");
6240 return CMD_WARNING_CONFIG_FAILED
;
6244 /* Old configuration check. */
6245 rn
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], &p
);
6248 "%% There is no aggregate-address configuration.\n");
6249 return CMD_WARNING_CONFIG_FAILED
;
6252 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6253 bgp_aggregate_delete(bgp
, &p
, afi
, safi
, aggregate
);
6254 bgp_aggregate_install(bgp
, afi
, safi
, &p
, 0, NULL
, NULL
,
6255 NULL
, NULL
, 0, aggregate
);
6257 /* Unlock aggregate address configuration. */
6258 bgp_node_set_bgp_aggregate_info(rn
, NULL
);
6260 if (aggregate
->community
)
6261 community_free(&aggregate
->community
);
6263 if (aggregate
->community_hash
) {
6264 /* Delete all communities in the hash.
6266 hash_clean(aggregate
->community_hash
,
6267 bgp_aggr_community_remove
);
6268 /* Free up the community_hash.
6270 hash_free(aggregate
->community_hash
);
6273 if (aggregate
->ecommunity
)
6274 ecommunity_free(&aggregate
->ecommunity
);
6276 if (aggregate
->ecommunity_hash
) {
6277 /* Delete all ecommunities in the hash.
6279 hash_clean(aggregate
->ecommunity_hash
,
6280 bgp_aggr_ecommunity_remove
);
6281 /* Free up the ecommunity_hash.
6283 hash_free(aggregate
->ecommunity_hash
);
6286 if (aggregate
->lcommunity
)
6287 lcommunity_free(&aggregate
->lcommunity
);
6289 if (aggregate
->lcommunity_hash
) {
6290 /* Delete all lcommunities in the hash.
6292 hash_clean(aggregate
->lcommunity_hash
,
6293 bgp_aggr_lcommunity_remove
);
6294 /* Free up the lcommunity_hash.
6296 hash_free(aggregate
->lcommunity_hash
);
6299 if (aggregate
->aspath
)
6300 aspath_free(aggregate
->aspath
);
6302 if (aggregate
->aspath_hash
) {
6303 /* Delete all as-paths in the hash.
6305 hash_clean(aggregate
->aspath_hash
,
6306 bgp_aggr_aspath_remove
);
6307 /* Free up the aspath_hash.
6309 hash_free(aggregate
->aspath_hash
);
6312 bgp_aggregate_free(aggregate
);
6313 bgp_unlock_node(rn
);
6314 bgp_unlock_node(rn
);
6319 static int bgp_aggregate_set(struct vty
*vty
, const char *prefix_str
, afi_t afi
,
6320 safi_t safi
, uint8_t summary_only
, uint8_t as_set
)
6322 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6325 struct bgp_node
*rn
;
6326 struct bgp_aggregate
*aggregate
;
6328 /* Convert string to prefix structure. */
6329 ret
= str2prefix(prefix_str
, &p
);
6331 vty_out(vty
, "Malformed prefix\n");
6332 return CMD_WARNING_CONFIG_FAILED
;
6336 if ((afi
== AFI_IP
&& p
.prefixlen
== IPV4_MAX_BITLEN
) ||
6337 (afi
== AFI_IP6
&& p
.prefixlen
== IPV6_MAX_BITLEN
)) {
6338 vty_out(vty
, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
6340 return CMD_WARNING_CONFIG_FAILED
;
6343 /* Old configuration check. */
6344 rn
= bgp_node_get(bgp
->aggregate
[afi
][safi
], &p
);
6346 if (bgp_node_has_bgp_path_info_data(rn
)) {
6347 vty_out(vty
, "There is already same aggregate network.\n");
6348 /* try to remove the old entry */
6349 ret
= bgp_aggregate_unset(vty
, prefix_str
, afi
, safi
);
6351 vty_out(vty
, "Error deleting aggregate.\n");
6352 bgp_unlock_node(rn
);
6353 return CMD_WARNING_CONFIG_FAILED
;
6357 /* Make aggregate address structure. */
6358 aggregate
= bgp_aggregate_new();
6359 aggregate
->summary_only
= summary_only
;
6360 aggregate
->as_set
= as_set
;
6361 aggregate
->safi
= safi
;
6362 bgp_node_set_bgp_aggregate_info(rn
, aggregate
);
6364 /* Aggregate address insert into BGP routing table. */
6365 bgp_aggregate_route(bgp
, &p
, afi
, safi
, aggregate
);
6370 DEFUN (aggregate_address
,
6371 aggregate_address_cmd
,
6372 "aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
6373 "Configure BGP aggregate entries\n"
6374 "Aggregate prefix\n"
6375 "Generate AS set path information\n"
6376 "Filter more specific routes from updates\n"
6377 "Filter more specific routes from updates\n"
6378 "Generate AS set path information\n")
6381 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
6382 char *prefix
= argv
[idx
]->arg
;
6384 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
6386 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6387 ? AGGREGATE_SUMMARY_ONLY
6390 return bgp_aggregate_set(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
),
6391 summary_only
, as_set
);
6394 DEFUN (aggregate_address_mask
,
6395 aggregate_address_mask_cmd
,
6396 "aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
6397 "Configure BGP aggregate entries\n"
6398 "Aggregate address\n"
6400 "Generate AS set path information\n"
6401 "Filter more specific routes from updates\n"
6402 "Filter more specific routes from updates\n"
6403 "Generate AS set path information\n")
6406 argv_find(argv
, argc
, "A.B.C.D", &idx
);
6407 char *prefix
= argv
[idx
]->arg
;
6408 char *mask
= argv
[idx
+ 1]->arg
;
6410 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
6412 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6413 ? AGGREGATE_SUMMARY_ONLY
6416 char prefix_str
[BUFSIZ
];
6417 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
6420 vty_out(vty
, "%% Inconsistent address and mask\n");
6421 return CMD_WARNING_CONFIG_FAILED
;
6424 return bgp_aggregate_set(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
),
6425 summary_only
, as_set
);
6428 DEFUN (no_aggregate_address
,
6429 no_aggregate_address_cmd
,
6430 "no aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
6432 "Configure BGP aggregate entries\n"
6433 "Aggregate prefix\n"
6434 "Generate AS set path information\n"
6435 "Filter more specific routes from updates\n"
6436 "Filter more specific routes from updates\n"
6437 "Generate AS set path information\n")
6440 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
6441 char *prefix
= argv
[idx
]->arg
;
6442 return bgp_aggregate_unset(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
));
6445 DEFUN (no_aggregate_address_mask
,
6446 no_aggregate_address_mask_cmd
,
6447 "no aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
6449 "Configure BGP aggregate entries\n"
6450 "Aggregate address\n"
6452 "Generate AS set path information\n"
6453 "Filter more specific routes from updates\n"
6454 "Filter more specific routes from updates\n"
6455 "Generate AS set path information\n")
6458 argv_find(argv
, argc
, "A.B.C.D", &idx
);
6459 char *prefix
= argv
[idx
]->arg
;
6460 char *mask
= argv
[idx
+ 1]->arg
;
6462 char prefix_str
[BUFSIZ
];
6463 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
6466 vty_out(vty
, "%% Inconsistent address and mask\n");
6467 return CMD_WARNING_CONFIG_FAILED
;
6470 return bgp_aggregate_unset(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
));
6473 DEFUN (ipv6_aggregate_address
,
6474 ipv6_aggregate_address_cmd
,
6475 "aggregate-address X:X::X:X/M [summary-only]",
6476 "Configure BGP aggregate entries\n"
6477 "Aggregate prefix\n"
6478 "Filter more specific routes from updates\n")
6481 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6482 char *prefix
= argv
[idx
]->arg
;
6483 int sum_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6484 ? AGGREGATE_SUMMARY_ONLY
6486 return bgp_aggregate_set(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
, sum_only
,
6490 DEFUN (no_ipv6_aggregate_address
,
6491 no_ipv6_aggregate_address_cmd
,
6492 "no aggregate-address X:X::X:X/M [summary-only]",
6494 "Configure BGP aggregate entries\n"
6495 "Aggregate prefix\n"
6496 "Filter more specific routes from updates\n")
6499 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6500 char *prefix
= argv
[idx
]->arg
;
6501 return bgp_aggregate_unset(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
);
6504 /* Redistribute route treatment. */
6505 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
6506 const union g_addr
*nexthop
, ifindex_t ifindex
,
6507 enum nexthop_types_t nhtype
, uint32_t metric
,
6508 uint8_t type
, unsigned short instance
,
6511 struct bgp_path_info
*new;
6512 struct bgp_path_info
*bpi
;
6513 struct bgp_path_info rmap_path
;
6514 struct bgp_node
*bn
;
6516 struct attr
*new_attr
;
6519 struct bgp_redist
*red
;
6521 /* Make default attribute. */
6522 bgp_attr_default_set(&attr
, BGP_ORIGIN_INCOMPLETE
);
6525 case NEXTHOP_TYPE_IFINDEX
:
6527 case NEXTHOP_TYPE_IPV4
:
6528 case NEXTHOP_TYPE_IPV4_IFINDEX
:
6529 attr
.nexthop
= nexthop
->ipv4
;
6531 case NEXTHOP_TYPE_IPV6
:
6532 case NEXTHOP_TYPE_IPV6_IFINDEX
:
6533 attr
.mp_nexthop_global
= nexthop
->ipv6
;
6534 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6536 case NEXTHOP_TYPE_BLACKHOLE
:
6537 switch (p
->family
) {
6539 attr
.nexthop
.s_addr
= INADDR_ANY
;
6542 memset(&attr
.mp_nexthop_global
, 0,
6543 sizeof(attr
.mp_nexthop_global
));
6544 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6549 attr
.nh_ifindex
= ifindex
;
6552 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6555 afi
= family2afi(p
->family
);
6557 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6559 struct attr attr_new
;
6561 /* Copy attribute for modification. */
6562 bgp_attr_dup(&attr_new
, &attr
);
6564 if (red
->redist_metric_flag
)
6565 attr_new
.med
= red
->redist_metric
;
6567 /* Apply route-map. */
6568 if (red
->rmap
.name
) {
6569 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
6570 rmap_path
.peer
= bgp
->peer_self
;
6571 rmap_path
.attr
= &attr_new
;
6573 SET_FLAG(bgp
->peer_self
->rmap_type
,
6574 PEER_RMAP_TYPE_REDISTRIBUTE
);
6576 ret
= route_map_apply(red
->rmap
.map
, p
, RMAP_BGP
,
6579 bgp
->peer_self
->rmap_type
= 0;
6581 if (ret
== RMAP_DENYMATCH
) {
6582 /* Free uninterned attribute. */
6583 bgp_attr_flush(&attr_new
);
6585 /* Unintern original. */
6586 aspath_unintern(&attr
.aspath
);
6587 bgp_redistribute_delete(bgp
, p
, type
, instance
);
6592 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
6593 bgp_attr_add_gshut_community(&attr_new
);
6595 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6596 SAFI_UNICAST
, p
, NULL
);
6598 new_attr
= bgp_attr_intern(&attr_new
);
6600 for (bpi
= bgp_node_get_bgp_path_info(bn
); bpi
;
6602 if (bpi
->peer
== bgp
->peer_self
6603 && bpi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
6607 /* Ensure the (source route) type is updated. */
6609 if (attrhash_cmp(bpi
->attr
, new_attr
)
6610 && !CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
)) {
6611 bgp_attr_unintern(&new_attr
);
6612 aspath_unintern(&attr
.aspath
);
6613 bgp_unlock_node(bn
);
6616 /* The attribute is changed. */
6617 bgp_path_info_set_flag(bn
, bpi
,
6618 BGP_PATH_ATTR_CHANGED
);
6620 /* Rewrite BGP route information. */
6621 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
6622 bgp_path_info_restore(bn
, bpi
);
6624 bgp_aggregate_decrement(
6625 bgp
, p
, bpi
, afi
, SAFI_UNICAST
);
6626 bgp_attr_unintern(&bpi
->attr
);
6627 bpi
->attr
= new_attr
;
6628 bpi
->uptime
= bgp_clock();
6630 /* Process change. */
6631 bgp_aggregate_increment(bgp
, p
, bpi
, afi
,
6633 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6634 bgp_unlock_node(bn
);
6635 aspath_unintern(&attr
.aspath
);
6637 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6639 == BGP_INSTANCE_TYPE_DEFAULT
)) {
6641 vpn_leak_from_vrf_update(
6642 bgp_get_default(), bgp
, bpi
);
6648 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
6649 bgp
->peer_self
, new_attr
, bn
);
6650 SET_FLAG(new->flags
, BGP_PATH_VALID
);
6652 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
6653 bgp_path_info_add(bn
, new);
6654 bgp_unlock_node(bn
);
6655 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6657 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6658 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6660 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
6664 /* Unintern original. */
6665 aspath_unintern(&attr
.aspath
);
6668 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, uint8_t type
,
6669 unsigned short instance
)
6672 struct bgp_node
*rn
;
6673 struct bgp_path_info
*pi
;
6674 struct bgp_redist
*red
;
6676 afi
= family2afi(p
->family
);
6678 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6680 rn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6681 SAFI_UNICAST
, p
, NULL
);
6683 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
6684 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
)
6688 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6689 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6691 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6694 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, SAFI_UNICAST
);
6695 bgp_path_info_delete(rn
, pi
);
6696 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6698 bgp_unlock_node(rn
);
6702 /* Withdraw specified route type's route. */
6703 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
6704 unsigned short instance
)
6706 struct bgp_node
*rn
;
6707 struct bgp_path_info
*pi
;
6708 struct bgp_table
*table
;
6710 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
6712 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
6713 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
6714 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
6715 && pi
->instance
== instance
)
6719 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6720 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6722 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6725 bgp_aggregate_decrement(bgp
, &rn
->p
, pi
, afi
,
6727 bgp_path_info_delete(rn
, pi
);
6728 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6733 /* Static function to display route. */
6734 static void route_vty_out_route(struct prefix
*p
, struct vty
*vty
,
6741 if (p
->family
== AF_INET
) {
6745 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
6748 json_object_string_add(json
, "prefix",
6749 inet_ntop(p
->family
,
6752 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
6753 prefix2str(p
, buf2
, PREFIX_STRLEN
);
6754 json_object_string_add(json
, "network", buf2
);
6756 } else if (p
->family
== AF_ETHERNET
) {
6757 prefix2str(p
, buf
, PREFIX_STRLEN
);
6758 len
= vty_out(vty
, "%s", buf
);
6759 } else if (p
->family
== AF_EVPN
) {
6763 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf
,
6766 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
6767 } else if (p
->family
== AF_FLOWSPEC
) {
6768 route_vty_out_flowspec(vty
, p
, NULL
,
6770 NLRI_STRING_FORMAT_JSON_SIMPLE
:
6771 NLRI_STRING_FORMAT_MIN
, json
);
6776 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
6779 json_object_string_add(json
, "prefix",
6780 inet_ntop(p
->family
,
6783 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
6784 prefix2str(p
, buf2
, PREFIX_STRLEN
);
6785 json_object_string_add(json
, "network", buf2
);
6792 vty_out(vty
, "\n%*s", 20, " ");
6794 vty_out(vty
, "%*s", len
, " ");
6798 enum bgp_display_type
{
6802 /* Print the short form route status for a bgp_path_info */
6803 static void route_vty_short_status_out(struct vty
*vty
,
6804 struct bgp_path_info
*path
,
6805 json_object
*json_path
)
6809 /* Route status display. */
6810 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
6811 json_object_boolean_true_add(json_path
, "removed");
6813 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
6814 json_object_boolean_true_add(json_path
, "stale");
6816 if (path
->extra
&& path
->extra
->suppress
)
6817 json_object_boolean_true_add(json_path
, "suppressed");
6819 if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
6820 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
6821 json_object_boolean_true_add(json_path
, "valid");
6824 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
6825 json_object_boolean_true_add(json_path
, "history");
6827 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
6828 json_object_boolean_true_add(json_path
, "damped");
6830 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
6831 json_object_boolean_true_add(json_path
, "bestpath");
6833 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
6834 json_object_boolean_true_add(json_path
, "multipath");
6836 /* Internal route. */
6837 if ((path
->peer
->as
)
6838 && (path
->peer
->as
== path
->peer
->local_as
))
6839 json_object_string_add(json_path
, "pathFrom",
6842 json_object_string_add(json_path
, "pathFrom",
6848 /* Route status display. */
6849 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
6851 else if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
6853 else if (path
->extra
&& path
->extra
->suppress
)
6855 else if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
6856 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
6862 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
6864 else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
6866 else if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
6868 else if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
6873 /* Internal route. */
6874 if (path
->peer
&& (path
->peer
->as
)
6875 && (path
->peer
->as
== path
->peer
->local_as
))
6881 /* called from terminal list command */
6882 void route_vty_out(struct vty
*vty
, struct prefix
*p
,
6883 struct bgp_path_info
*path
, int display
, safi_t safi
,
6884 json_object
*json_paths
)
6887 json_object
*json_path
= NULL
;
6888 json_object
*json_nexthops
= NULL
;
6889 json_object
*json_nexthop_global
= NULL
;
6890 json_object
*json_nexthop_ll
= NULL
;
6891 char vrf_id_str
[VRF_NAMSIZ
] = {0};
6893 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
6894 bool nexthop_othervrf
= false;
6895 vrf_id_t nexthop_vrfid
= VRF_DEFAULT
;
6896 const char *nexthop_vrfname
= VRF_DEFAULT_NAME
;
6899 json_path
= json_object_new_object();
6901 /* short status lead text */
6902 route_vty_short_status_out(vty
, path
, json_path
);
6905 /* print prefix and mask */
6907 route_vty_out_route(p
, vty
, json_path
);
6909 vty_out(vty
, "%*s", 17, " ");
6911 route_vty_out_route(p
, vty
, json_path
);
6914 /* Print attribute */
6918 json_object_array_add(json_paths
, json_path
);
6926 * If vrf id of nexthop is different from that of prefix,
6927 * set up printable string to append
6929 if (path
->extra
&& path
->extra
->bgp_orig
) {
6930 const char *self
= "";
6935 nexthop_othervrf
= true;
6936 nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
6938 if (path
->extra
->bgp_orig
->vrf_id
== VRF_UNKNOWN
)
6939 snprintf(vrf_id_str
, sizeof(vrf_id_str
),
6940 "@%s%s", VRFID_NONE_STR
, self
);
6942 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "@%u%s",
6943 path
->extra
->bgp_orig
->vrf_id
, self
);
6945 if (path
->extra
->bgp_orig
->inst_type
6946 != BGP_INSTANCE_TYPE_DEFAULT
)
6948 nexthop_vrfname
= path
->extra
->bgp_orig
->name
;
6950 const char *self
= "";
6955 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "%s", self
);
6959 * For ENCAP and EVPN routes, nexthop address family is not
6960 * neccessarily the same as the prefix address family.
6961 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
6962 * EVPN routes are also exchanged with a MP nexthop. Currently,
6964 * is only IPv4, the value will be present in either
6966 * attr->mp_nexthop_global_in
6968 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
6971 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
6975 sprintf(nexthop
, "%s",
6976 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
6980 sprintf(nexthop
, "%s",
6981 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
6985 sprintf(nexthop
, "?");
6990 json_nexthop_global
= json_object_new_object();
6992 json_object_string_add(json_nexthop_global
, "afi",
6993 (af
== AF_INET
) ? "ip" : "ipv6");
6994 json_object_string_add(json_nexthop_global
,
6995 (af
== AF_INET
) ? "ip" : "ipv6",
6997 json_object_boolean_true_add(json_nexthop_global
,
7000 vty_out(vty
, "%s%s", nexthop
, vrf_id_str
);
7001 } else if (safi
== SAFI_EVPN
) {
7003 json_nexthop_global
= json_object_new_object();
7005 json_object_string_add(json_nexthop_global
, "ip",
7006 inet_ntoa(attr
->nexthop
));
7007 json_object_string_add(json_nexthop_global
, "afi",
7009 json_object_boolean_true_add(json_nexthop_global
,
7012 vty_out(vty
, "%-16s%s", inet_ntoa(attr
->nexthop
),
7014 } else if (safi
== SAFI_FLOWSPEC
) {
7015 if (attr
->nexthop
.s_addr
!= 0) {
7017 json_nexthop_global
= json_object_new_object();
7018 json_object_string_add(
7019 json_nexthop_global
, "ip",
7020 inet_ntoa(attr
->nexthop
));
7021 json_object_string_add(json_nexthop_global
,
7023 json_object_boolean_true_add(
7024 json_nexthop_global
,
7027 vty_out(vty
, "%-16s", inet_ntoa(attr
->nexthop
));
7030 } else if (p
->family
== AF_INET
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7032 json_nexthop_global
= json_object_new_object();
7034 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_EVPN
))
7035 json_object_string_add(
7036 json_nexthop_global
, "ip",
7037 inet_ntoa(attr
->mp_nexthop_global_in
));
7039 json_object_string_add(
7040 json_nexthop_global
, "ip",
7041 inet_ntoa(attr
->nexthop
));
7043 json_object_string_add(json_nexthop_global
, "afi",
7045 json_object_boolean_true_add(json_nexthop_global
,
7050 snprintf(buf
, sizeof(buf
), "%s%s",
7051 inet_ntoa(attr
->nexthop
), vrf_id_str
);
7052 vty_out(vty
, "%-16s", buf
);
7057 else if (p
->family
== AF_INET6
|| BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7062 json_nexthop_global
= json_object_new_object();
7063 json_object_string_add(
7064 json_nexthop_global
, "ip",
7065 inet_ntop(AF_INET6
, &attr
->mp_nexthop_global
,
7067 json_object_string_add(json_nexthop_global
, "afi",
7069 json_object_string_add(json_nexthop_global
, "scope",
7072 /* We display both LL & GL if both have been
7074 if ((attr
->mp_nexthop_len
== 32)
7075 || (path
->peer
->conf_if
)) {
7076 json_nexthop_ll
= json_object_new_object();
7077 json_object_string_add(
7078 json_nexthop_ll
, "ip",
7080 &attr
->mp_nexthop_local
, buf
,
7082 json_object_string_add(json_nexthop_ll
, "afi",
7084 json_object_string_add(json_nexthop_ll
, "scope",
7087 if ((IPV6_ADDR_CMP(&attr
->mp_nexthop_global
,
7088 &attr
->mp_nexthop_local
)
7090 && !attr
->mp_nexthop_prefer_global
)
7091 json_object_boolean_true_add(
7092 json_nexthop_ll
, "used");
7094 json_object_boolean_true_add(
7095 json_nexthop_global
, "used");
7097 json_object_boolean_true_add(
7098 json_nexthop_global
, "used");
7100 /* Display LL if LL/Global both in table unless
7101 * prefer-global is set */
7102 if (((attr
->mp_nexthop_len
== 32)
7103 && !attr
->mp_nexthop_prefer_global
)
7104 || (path
->peer
->conf_if
)) {
7105 if (path
->peer
->conf_if
) {
7106 len
= vty_out(vty
, "%s",
7107 path
->peer
->conf_if
);
7108 len
= 16 - len
; /* len of IPv6
7114 vty_out(vty
, "\n%*s", 36, " ");
7116 vty_out(vty
, "%*s", len
, " ");
7122 &attr
->mp_nexthop_local
,
7128 vty_out(vty
, "\n%*s", 36, " ");
7130 vty_out(vty
, "%*s", len
, " ");
7136 &attr
->mp_nexthop_global
, buf
,
7142 vty_out(vty
, "\n%*s", 36, " ");
7144 vty_out(vty
, "%*s", len
, " ");
7150 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
7154 * Adding "metric" field to match with corresponding
7155 * CLI. "med" will be deprecated in future.
7157 json_object_int_add(json_path
, "med", attr
->med
);
7158 json_object_int_add(json_path
, "metric", attr
->med
);
7160 vty_out(vty
, "%10u", attr
->med
);
7161 else if (!json_paths
)
7165 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
7169 * Adding "locPrf" field to match with corresponding
7170 * CLI. "localPref" will be deprecated in future.
7172 json_object_int_add(json_path
, "localpref",
7174 json_object_int_add(json_path
, "locPrf",
7177 vty_out(vty
, "%7u", attr
->local_pref
);
7178 else if (!json_paths
)
7182 json_object_int_add(json_path
, "weight", attr
->weight
);
7184 vty_out(vty
, "%7u ", attr
->weight
);
7188 json_object_string_add(
7189 json_path
, "peerId",
7190 sockunion2str(&path
->peer
->su
, buf
, SU_ADDRSTRLEN
));
7198 * Adding "path" field to match with corresponding
7199 * CLI. "aspath" will be deprecated in future.
7201 json_object_string_add(json_path
, "aspath",
7203 json_object_string_add(json_path
, "path",
7206 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7211 json_object_string_add(json_path
, "origin",
7212 bgp_origin_long_str
[attr
->origin
]);
7214 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7218 json_object_boolean_true_add(json_path
,
7219 "announceNexthopSelf");
7220 if (nexthop_othervrf
) {
7221 json_object_string_add(json_path
, "nhVrfName",
7224 json_object_int_add(json_path
, "nhVrfId",
7225 ((nexthop_vrfid
== VRF_UNKNOWN
)
7227 : (int)nexthop_vrfid
));
7232 if (json_nexthop_global
|| json_nexthop_ll
) {
7233 json_nexthops
= json_object_new_array();
7235 if (json_nexthop_global
)
7236 json_object_array_add(json_nexthops
,
7237 json_nexthop_global
);
7239 if (json_nexthop_ll
)
7240 json_object_array_add(json_nexthops
,
7243 json_object_object_add(json_path
, "nexthops",
7247 json_object_array_add(json_paths
, json_path
);
7251 /* prints an additional line, indented, with VNC info, if
7253 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
7254 rfapi_vty_out_vncinfo(vty
, p
, path
, safi
);
7259 /* called from terminal list command */
7260 void route_vty_out_tmp(struct vty
*vty
, struct prefix
*p
, struct attr
*attr
,
7261 safi_t safi
, bool use_json
, json_object
*json_ar
)
7263 json_object
*json_status
= NULL
;
7264 json_object
*json_net
= NULL
;
7267 /* Route status display. */
7269 json_status
= json_object_new_object();
7270 json_net
= json_object_new_object();
7277 /* print prefix and mask */
7279 json_object_string_add(
7280 json_net
, "addrPrefix",
7281 inet_ntop(p
->family
, &p
->u
.prefix
, buff
, BUFSIZ
));
7282 json_object_int_add(json_net
, "prefixLen", p
->prefixlen
);
7283 prefix2str(p
, buf2
, PREFIX_STRLEN
);
7284 json_object_string_add(json_net
, "network", buf2
);
7286 route_vty_out_route(p
, vty
, NULL
);
7288 /* Print attribute */
7291 if (p
->family
== AF_INET
7292 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7293 || safi
== SAFI_EVPN
7294 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7295 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7296 || safi
== SAFI_EVPN
)
7297 json_object_string_add(
7298 json_net
, "nextHop",
7300 attr
->mp_nexthop_global_in
));
7302 json_object_string_add(
7303 json_net
, "nextHop",
7304 inet_ntoa(attr
->nexthop
));
7305 } else if (p
->family
== AF_INET6
7306 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7309 json_object_string_add(
7310 json_net
, "nextHopGlobal",
7312 &attr
->mp_nexthop_global
, buf
,
7317 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
7318 json_object_int_add(json_net
, "metric",
7321 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
7324 * Adding "locPrf" field to match with
7325 * corresponding CLI. "localPref" will be
7326 * deprecated in future.
7328 json_object_int_add(json_net
, "localPref",
7330 json_object_int_add(json_net
, "locPrf",
7334 json_object_int_add(json_net
, "weight", attr
->weight
);
7340 * Adding "path" field to match with
7341 * corresponding CLI. "localPref" will be
7342 * deprecated in future.
7344 json_object_string_add(json_net
, "asPath",
7346 json_object_string_add(json_net
, "path",
7351 json_object_string_add(json_net
, "bgpOriginCode",
7352 bgp_origin_str
[attr
->origin
]);
7354 if (p
->family
== AF_INET
7355 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7356 || safi
== SAFI_EVPN
7357 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7358 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7359 || safi
== SAFI_EVPN
)
7360 vty_out(vty
, "%-16s",
7362 attr
->mp_nexthop_global_in
));
7364 vty_out(vty
, "%-16s",
7365 inet_ntoa(attr
->nexthop
));
7366 } else if (p
->family
== AF_INET6
7367 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7374 &attr
->mp_nexthop_global
, buf
,
7378 vty_out(vty
, "\n%*s", 36, " ");
7380 vty_out(vty
, "%*s", len
, " ");
7383 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
7384 vty_out(vty
, "%10u", attr
->med
);
7388 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
7389 vty_out(vty
, "%7u", attr
->local_pref
);
7393 vty_out(vty
, "%7u ", attr
->weight
);
7397 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7400 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7404 json_object_boolean_true_add(json_status
, "*");
7405 json_object_boolean_true_add(json_status
, ">");
7406 json_object_object_add(json_net
, "appliedStatusSymbols",
7408 char buf_cut
[BUFSIZ
];
7409 json_object_object_add(
7411 inet_ntop(p
->family
, &p
->u
.prefix
, buf_cut
, BUFSIZ
),
7417 void route_vty_out_tag(struct vty
*vty
, struct prefix
*p
,
7418 struct bgp_path_info
*path
, int display
, safi_t safi
,
7421 json_object
*json_out
= NULL
;
7423 mpls_label_t label
= MPLS_INVALID_LABEL
;
7429 json_out
= json_object_new_object();
7431 /* short status lead text */
7432 route_vty_short_status_out(vty
, path
, json_out
);
7434 /* print prefix and mask */
7437 route_vty_out_route(p
, vty
, NULL
);
7439 vty_out(vty
, "%*s", 17, " ");
7442 /* Print attribute */
7445 if (((p
->family
== AF_INET
)
7446 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
7447 || (safi
== SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
7448 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7449 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7450 || safi
== SAFI_EVPN
) {
7452 json_object_string_add(
7453 json_out
, "mpNexthopGlobalIn",
7455 attr
->mp_nexthop_global_in
));
7457 vty_out(vty
, "%-16s",
7459 attr
->mp_nexthop_global_in
));
7462 json_object_string_add(
7463 json_out
, "nexthop",
7464 inet_ntoa(attr
->nexthop
));
7466 vty_out(vty
, "%-16s",
7467 inet_ntoa(attr
->nexthop
));
7469 } else if (((p
->family
== AF_INET6
)
7470 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
7471 || (safi
== SAFI_EVPN
7472 && BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
7473 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7477 if (attr
->mp_nexthop_len
7478 == BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
7480 json_object_string_add(
7481 json_out
, "mpNexthopGlobalIn",
7484 &attr
->mp_nexthop_global
,
7485 buf_a
, sizeof(buf_a
)));
7490 &attr
->mp_nexthop_global
,
7491 buf_a
, sizeof(buf_a
)));
7492 } else if (attr
->mp_nexthop_len
7493 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
7496 &attr
->mp_nexthop_global
,
7497 buf_a
, sizeof(buf_a
));
7499 &attr
->mp_nexthop_local
,
7500 buf_b
, sizeof(buf_b
));
7501 sprintf(buf_c
, "%s(%s)", buf_a
, buf_b
);
7502 json_object_string_add(
7504 "mpNexthopGlobalLocal", buf_c
);
7506 vty_out(vty
, "%s(%s)",
7509 &attr
->mp_nexthop_global
,
7510 buf_a
, sizeof(buf_a
)),
7513 &attr
->mp_nexthop_local
,
7514 buf_b
, sizeof(buf_b
)));
7519 label
= decode_label(&path
->extra
->label
[0]);
7521 if (bgp_is_valid_label(&label
)) {
7523 json_object_int_add(json_out
, "notag", label
);
7524 json_object_array_add(json
, json_out
);
7526 vty_out(vty
, "notag/%d", label
);
7532 void route_vty_out_overlay(struct vty
*vty
, struct prefix
*p
,
7533 struct bgp_path_info
*path
, int display
,
7534 json_object
*json_paths
)
7538 json_object
*json_path
= NULL
;
7541 json_path
= json_object_new_object();
7546 /* short status lead text */
7547 route_vty_short_status_out(vty
, path
, json_path
);
7549 /* print prefix and mask */
7551 route_vty_out_route(p
, vty
, NULL
);
7553 vty_out(vty
, "%*s", 17, " ");
7555 /* Print attribute */
7559 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
7563 vty_out(vty
, "%-16s",
7564 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
7568 vty_out(vty
, "%s(%s)",
7569 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
7571 inet_ntop(af
, &attr
->mp_nexthop_local
, buf1
,
7578 char *str
= esi2str(&(attr
->evpn_overlay
.eth_s_id
));
7580 vty_out(vty
, "%s", str
);
7581 XFREE(MTYPE_TMP
, str
);
7583 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn
*)p
)) {
7585 inet_ntoa(attr
->evpn_overlay
.gw_ip
.ipv4
));
7586 } else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn
*)p
)) {
7589 &(attr
->evpn_overlay
.gw_ip
.ipv6
), buf
,
7592 if (attr
->ecommunity
) {
7594 struct ecommunity_val
*routermac
= ecommunity_lookup(
7595 attr
->ecommunity
, ECOMMUNITY_ENCODE_EVPN
,
7596 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
7598 mac
= ecom_mac2str((char *)routermac
->val
);
7600 vty_out(vty
, "/%s", (char *)mac
);
7601 XFREE(MTYPE_TMP
, mac
);
7609 /* dampening route */
7610 static void damp_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7611 struct bgp_path_info
*path
, int display
,
7612 safi_t safi
, bool use_json
, json_object
*json
)
7616 char timebuf
[BGP_UPTIME_LEN
];
7618 /* short status lead text */
7619 route_vty_short_status_out(vty
, path
, json
);
7621 /* print prefix and mask */
7624 route_vty_out_route(p
, vty
, NULL
);
7626 vty_out(vty
, "%*s", 17, " ");
7629 len
= vty_out(vty
, "%s", path
->peer
->host
);
7633 vty_out(vty
, "\n%*s", 34, " ");
7636 json_object_int_add(json
, "peerHost", len
);
7638 vty_out(vty
, "%*s", len
, " ");
7642 bgp_damp_reuse_time_vty(vty
, path
, timebuf
, BGP_UPTIME_LEN
,
7646 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
7647 BGP_UPTIME_LEN
, use_json
,
7650 /* Print attribute */
7656 json_object_string_add(json
, "asPath",
7659 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7664 json_object_string_add(json
, "origin",
7665 bgp_origin_str
[attr
->origin
]);
7667 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7674 static void flap_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7675 struct bgp_path_info
*path
, int display
,
7676 safi_t safi
, bool use_json
, json_object
*json
)
7679 struct bgp_damp_info
*bdi
;
7680 char timebuf
[BGP_UPTIME_LEN
];
7686 bdi
= path
->extra
->damp_info
;
7688 /* short status lead text */
7689 route_vty_short_status_out(vty
, path
, json
);
7691 /* print prefix and mask */
7694 route_vty_out_route(p
, vty
, NULL
);
7696 vty_out(vty
, "%*s", 17, " ");
7699 len
= vty_out(vty
, "%s", path
->peer
->host
);
7703 vty_out(vty
, "\n%*s", 33, " ");
7706 json_object_int_add(json
, "peerHost", len
);
7708 vty_out(vty
, "%*s", len
, " ");
7711 len
= vty_out(vty
, "%d", bdi
->flap
);
7718 json_object_int_add(json
, "bdiFlap", len
);
7720 vty_out(vty
, "%*s", len
, " ");
7724 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
7727 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
7728 BGP_UPTIME_LEN
, 0, NULL
));
7730 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
7731 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
7733 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
7734 BGP_UPTIME_LEN
, use_json
, json
);
7737 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
7742 vty_out(vty
, "%*s ", 8, " ");
7745 /* Print attribute */
7751 json_object_string_add(json
, "asPath",
7754 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7759 json_object_string_add(json
, "origin",
7760 bgp_origin_str
[attr
->origin
]);
7762 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7768 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
7769 int *first
, const char *header
,
7770 json_object
*json_adv_to
)
7772 char buf1
[INET6_ADDRSTRLEN
];
7773 json_object
*json_peer
= NULL
;
7776 /* 'advertised-to' is a dictionary of peers we have advertised
7778 * prefix too. The key is the peer's IP or swpX, the value is
7780 * hostname if we know it and "" if not.
7782 json_peer
= json_object_new_object();
7785 json_object_string_add(json_peer
, "hostname",
7789 json_object_object_add(json_adv_to
, peer
->conf_if
,
7792 json_object_object_add(
7794 sockunion2str(&peer
->su
, buf1
, SU_ADDRSTRLEN
),
7798 vty_out(vty
, "%s", header
);
7803 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
7805 vty_out(vty
, " %s(%s)", peer
->hostname
,
7808 vty_out(vty
, " %s(%s)", peer
->hostname
,
7809 sockunion2str(&peer
->su
, buf1
,
7813 vty_out(vty
, " %s", peer
->conf_if
);
7816 sockunion2str(&peer
->su
, buf1
,
7822 static void route_vty_out_tx_ids(struct vty
*vty
,
7823 struct bgp_addpath_info_data
*d
)
7827 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
7828 vty_out(vty
, "TX-%s %u%s", bgp_addpath_names(i
)->human_name
,
7829 d
->addpath_tx_id
[i
],
7830 i
< BGP_ADDPATH_MAX
- 1 ? " " : "\n");
7834 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
, struct prefix
*p
,
7835 struct bgp_path_info
*path
, afi_t afi
, safi_t safi
,
7836 json_object
*json_paths
)
7838 char buf
[INET6_ADDRSTRLEN
];
7840 char buf2
[EVPN_ROUTE_STRLEN
];
7842 int sockunion_vty_out(struct vty
*, union sockunion
*);
7844 json_object
*json_bestpath
= NULL
;
7845 json_object
*json_cluster_list
= NULL
;
7846 json_object
*json_cluster_list_list
= NULL
;
7847 json_object
*json_ext_community
= NULL
;
7848 json_object
*json_last_update
= NULL
;
7849 json_object
*json_pmsi
= NULL
;
7850 json_object
*json_nexthop_global
= NULL
;
7851 json_object
*json_nexthop_ll
= NULL
;
7852 json_object
*json_nexthops
= NULL
;
7853 json_object
*json_path
= NULL
;
7854 json_object
*json_peer
= NULL
;
7855 json_object
*json_string
= NULL
;
7856 json_object
*json_adv_to
= NULL
;
7858 struct listnode
*node
, *nnode
;
7860 int addpath_capable
;
7862 unsigned int first_as
;
7864 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
7868 json_path
= json_object_new_object();
7869 json_peer
= json_object_new_object();
7870 json_nexthop_global
= json_object_new_object();
7873 if (!json_paths
&& safi
== SAFI_EVPN
) {
7876 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf2
, sizeof(buf2
));
7877 vty_out(vty
, " Route %s", buf2
);
7879 if (path
->extra
&& path
->extra
->num_labels
) {
7880 bgp_evpn_label2str(path
->extra
->label
,
7881 path
->extra
->num_labels
, tag_buf
,
7883 vty_out(vty
, " VNI %s", tag_buf
);
7886 if (path
->extra
&& path
->extra
->parent
) {
7887 struct bgp_path_info
*parent_ri
;
7888 struct bgp_node
*rn
, *prn
;
7890 parent_ri
= (struct bgp_path_info
*)path
->extra
->parent
;
7891 rn
= parent_ri
->net
;
7892 if (rn
&& rn
->prn
) {
7894 vty_out(vty
, " Imported from %s:%s\n",
7896 (struct prefix_rd
*)&prn
->p
,
7897 buf1
, sizeof(buf1
)),
7906 /* Line1 display AS-path, Aggregator */
7909 if (!attr
->aspath
->json
)
7910 aspath_str_update(attr
->aspath
, true);
7911 json_object_lock(attr
->aspath
->json
);
7912 json_object_object_add(json_path
, "aspath",
7913 attr
->aspath
->json
);
7915 if (attr
->aspath
->segments
)
7916 aspath_print_vty(vty
, " %s",
7919 vty_out(vty
, " Local");
7923 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
)) {
7925 json_object_boolean_true_add(json_path
,
7928 vty_out(vty
, ", (removed)");
7931 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
7933 json_object_boolean_true_add(json_path
,
7936 vty_out(vty
, ", (stale)");
7939 if (CHECK_FLAG(attr
->flag
,
7940 ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
7942 json_object_int_add(json_path
, "aggregatorAs",
7943 attr
->aggregator_as
);
7944 json_object_string_add(
7945 json_path
, "aggregatorId",
7946 inet_ntoa(attr
->aggregator_addr
));
7948 vty_out(vty
, ", (aggregated by %u %s)",
7949 attr
->aggregator_as
,
7950 inet_ntoa(attr
->aggregator_addr
));
7954 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
7955 PEER_FLAG_REFLECTOR_CLIENT
)) {
7957 json_object_boolean_true_add(
7958 json_path
, "rxedFromRrClient");
7960 vty_out(vty
, ", (Received from a RR-client)");
7963 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
7964 PEER_FLAG_RSERVER_CLIENT
)) {
7966 json_object_boolean_true_add(
7967 json_path
, "rxedFromRsClient");
7969 vty_out(vty
, ", (Received from a RS-client)");
7972 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
7974 json_object_boolean_true_add(
7975 json_path
, "dampeningHistoryEntry");
7977 vty_out(vty
, ", (history entry)");
7978 } else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)) {
7980 json_object_boolean_true_add(
7981 json_path
, "dampeningSuppressed");
7983 vty_out(vty
, ", (suppressed due to dampening)");
7989 /* Line2 display Next-hop, Neighbor, Router-id */
7990 /* Display the nexthop */
7991 if ((p
->family
== AF_INET
|| p
->family
== AF_ETHERNET
7992 || p
->family
== AF_EVPN
)
7993 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7994 || safi
== SAFI_EVPN
7995 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7996 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7997 || safi
== SAFI_EVPN
) {
7999 json_object_string_add(
8000 json_nexthop_global
, "ip",
8002 attr
->mp_nexthop_global_in
));
8006 attr
->mp_nexthop_global_in
));
8009 json_object_string_add(
8010 json_nexthop_global
, "ip",
8011 inet_ntoa(attr
->nexthop
));
8014 inet_ntoa(attr
->nexthop
));
8018 json_object_string_add(json_nexthop_global
,
8022 json_object_string_add(
8023 json_nexthop_global
, "ip",
8025 &attr
->mp_nexthop_global
, buf
,
8027 json_object_string_add(json_nexthop_global
,
8029 json_object_string_add(json_nexthop_global
,
8034 &attr
->mp_nexthop_global
, buf
,
8039 /* Display the IGP cost or 'inaccessible' */
8040 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
8042 json_object_boolean_false_add(
8043 json_nexthop_global
, "accessible");
8045 vty_out(vty
, " (inaccessible)");
8047 if (path
->extra
&& path
->extra
->igpmetric
) {
8049 json_object_int_add(
8050 json_nexthop_global
, "metric",
8051 path
->extra
->igpmetric
);
8053 vty_out(vty
, " (metric %u)",
8054 path
->extra
->igpmetric
);
8057 /* IGP cost is 0, display this only for json */
8060 json_object_int_add(json_nexthop_global
,
8065 json_object_boolean_true_add(
8066 json_nexthop_global
, "accessible");
8069 /* Display peer "from" output */
8070 /* This path was originated locally */
8071 if (path
->peer
== bgp
->peer_self
) {
8073 if (safi
== SAFI_EVPN
8074 || (p
->family
== AF_INET
8075 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
8077 json_object_string_add(
8078 json_peer
, "peerId", "0.0.0.0");
8080 vty_out(vty
, " from 0.0.0.0 ");
8083 json_object_string_add(json_peer
,
8086 vty_out(vty
, " from :: ");
8090 json_object_string_add(
8091 json_peer
, "routerId",
8092 inet_ntoa(bgp
->router_id
));
8094 vty_out(vty
, "(%s)", inet_ntoa(bgp
->router_id
));
8097 /* We RXed this path from one of our peers */
8101 json_object_string_add(
8102 json_peer
, "peerId",
8103 sockunion2str(&path
->peer
->su
, buf
,
8105 json_object_string_add(
8106 json_peer
, "routerId",
8108 &path
->peer
->remote_id
, buf1
,
8111 if (path
->peer
->hostname
)
8112 json_object_string_add(
8113 json_peer
, "hostname",
8114 path
->peer
->hostname
);
8116 if (path
->peer
->domainname
)
8117 json_object_string_add(
8118 json_peer
, "domainname",
8119 path
->peer
->domainname
);
8121 if (path
->peer
->conf_if
)
8122 json_object_string_add(
8123 json_peer
, "interface",
8124 path
->peer
->conf_if
);
8126 if (path
->peer
->conf_if
) {
8127 if (path
->peer
->hostname
8130 BGP_FLAG_SHOW_HOSTNAME
))
8131 vty_out(vty
, " from %s(%s)",
8132 path
->peer
->hostname
,
8133 path
->peer
->conf_if
);
8135 vty_out(vty
, " from %s",
8136 path
->peer
->conf_if
);
8138 if (path
->peer
->hostname
8141 BGP_FLAG_SHOW_HOSTNAME
))
8142 vty_out(vty
, " from %s(%s)",
8143 path
->peer
->hostname
,
8146 vty_out(vty
, " from %s",
8154 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
8155 vty_out(vty
, " (%s)",
8156 inet_ntoa(attr
->originator_id
));
8158 vty_out(vty
, " (%s)",
8161 &path
->peer
->remote_id
,
8162 buf1
, sizeof(buf1
)));
8167 * Note when vrfid of nexthop is different from that of prefix
8169 if (path
->extra
&& path
->extra
->bgp_orig
) {
8170 vrf_id_t nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
8175 if (path
->extra
->bgp_orig
->inst_type
8176 == BGP_INSTANCE_TYPE_DEFAULT
)
8178 vn
= VRF_DEFAULT_NAME
;
8180 vn
= path
->extra
->bgp_orig
->name
;
8182 json_object_string_add(json_path
, "nhVrfName",
8185 if (nexthop_vrfid
== VRF_UNKNOWN
) {
8186 json_object_int_add(json_path
,
8189 json_object_int_add(json_path
,
8190 "nhVrfId", (int)nexthop_vrfid
);
8193 if (nexthop_vrfid
== VRF_UNKNOWN
)
8194 vty_out(vty
, " vrf ?");
8196 vty_out(vty
, " vrf %u", nexthop_vrfid
);
8202 json_object_boolean_true_add(json_path
,
8203 "announceNexthopSelf");
8205 vty_out(vty
, " announce-nh-self");
8212 /* display the link-local nexthop */
8213 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
8215 json_nexthop_ll
= json_object_new_object();
8216 json_object_string_add(
8217 json_nexthop_ll
, "ip",
8219 &attr
->mp_nexthop_local
, buf
,
8221 json_object_string_add(json_nexthop_ll
, "afi",
8223 json_object_string_add(json_nexthop_ll
, "scope",
8226 json_object_boolean_true_add(json_nexthop_ll
,
8229 if (!attr
->mp_nexthop_prefer_global
)
8230 json_object_boolean_true_add(
8231 json_nexthop_ll
, "used");
8233 json_object_boolean_true_add(
8234 json_nexthop_global
, "used");
8236 vty_out(vty
, " (%s) %s\n",
8238 &attr
->mp_nexthop_local
, buf
,
8240 attr
->mp_nexthop_prefer_global
8245 /* If we do not have a link-local nexthop then we must flag the
8249 json_object_boolean_true_add(
8250 json_nexthop_global
, "used");
8253 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
8254 * Int/Ext/Local, Atomic, best */
8256 json_object_string_add(
8257 json_path
, "origin",
8258 bgp_origin_long_str
[attr
->origin
]);
8260 vty_out(vty
, " Origin %s",
8261 bgp_origin_long_str
[attr
->origin
]);
8263 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
8267 * Adding "metric" field to match with
8268 * corresponding CLI. "med" will be
8269 * deprecated in future.
8271 json_object_int_add(json_path
, "med",
8273 json_object_int_add(json_path
, "metric",
8276 vty_out(vty
, ", metric %u", attr
->med
);
8279 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
8281 json_object_int_add(json_path
, "localpref",
8284 vty_out(vty
, ", localpref %u",
8288 if (attr
->weight
!= 0) {
8290 json_object_int_add(json_path
, "weight",
8293 vty_out(vty
, ", weight %u", attr
->weight
);
8296 if (attr
->tag
!= 0) {
8298 json_object_int_add(json_path
, "tag",
8301 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
,
8305 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
8307 json_object_boolean_false_add(json_path
,
8310 vty_out(vty
, ", invalid");
8311 } else if (!CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
8313 json_object_boolean_true_add(json_path
,
8316 vty_out(vty
, ", valid");
8319 if (path
->peer
!= bgp
->peer_self
) {
8320 if (path
->peer
->as
== path
->peer
->local_as
) {
8321 if (CHECK_FLAG(bgp
->config
,
8322 BGP_CONFIG_CONFEDERATION
)) {
8324 json_object_string_add(
8329 ", confed-internal");
8332 json_object_string_add(
8336 vty_out(vty
, ", internal");
8339 if (bgp_confederation_peers_check(
8340 bgp
, path
->peer
->as
)) {
8342 json_object_string_add(
8347 ", confed-external");
8350 json_object_string_add(
8354 vty_out(vty
, ", external");
8357 } else if (path
->sub_type
== BGP_ROUTE_AGGREGATE
) {
8359 json_object_boolean_true_add(json_path
,
8361 json_object_boolean_true_add(json_path
,
8364 vty_out(vty
, ", aggregated, local");
8366 } else if (path
->type
!= ZEBRA_ROUTE_BGP
) {
8368 json_object_boolean_true_add(json_path
,
8371 vty_out(vty
, ", sourced");
8374 json_object_boolean_true_add(json_path
,
8376 json_object_boolean_true_add(json_path
,
8379 vty_out(vty
, ", sourced, local");
8383 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
8385 json_object_boolean_true_add(json_path
,
8388 vty_out(vty
, ", atomic-aggregate");
8391 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
)
8392 || (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)
8393 && bgp_path_info_mpath_count(path
))) {
8395 json_object_boolean_true_add(json_path
,
8398 vty_out(vty
, ", multipath");
8401 // Mark the bestpath(s)
8402 if (CHECK_FLAG(path
->flags
, BGP_PATH_DMED_SELECTED
)) {
8403 first_as
= aspath_get_first_as(attr
->aspath
);
8408 json_object_new_object();
8409 json_object_int_add(json_bestpath
,
8410 "bestpathFromAs", first_as
);
8413 vty_out(vty
, ", bestpath-from-AS %u",
8417 ", bestpath-from-AS Local");
8421 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
8425 json_object_new_object();
8426 json_object_boolean_true_add(json_bestpath
,
8429 vty_out(vty
, ", best");
8433 json_object_object_add(json_path
, "bestpath",
8439 /* Line 4 display Community */
8440 if (attr
->community
) {
8442 if (!attr
->community
->json
)
8443 community_str(attr
->community
, true);
8444 json_object_lock(attr
->community
->json
);
8445 json_object_object_add(json_path
, "community",
8446 attr
->community
->json
);
8448 vty_out(vty
, " Community: %s\n",
8449 attr
->community
->str
);
8453 /* Line 5 display Extended-community */
8454 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
8456 json_ext_community
= json_object_new_object();
8457 json_object_string_add(json_ext_community
,
8459 attr
->ecommunity
->str
);
8460 json_object_object_add(json_path
,
8461 "extendedCommunity",
8462 json_ext_community
);
8464 vty_out(vty
, " Extended Community: %s\n",
8465 attr
->ecommunity
->str
);
8469 /* Line 6 display Large community */
8470 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
8472 if (!attr
->lcommunity
->json
)
8473 lcommunity_str(attr
->lcommunity
, true);
8474 json_object_lock(attr
->lcommunity
->json
);
8475 json_object_object_add(json_path
,
8477 attr
->lcommunity
->json
);
8479 vty_out(vty
, " Large Community: %s\n",
8480 attr
->lcommunity
->str
);
8484 /* Line 7 display Originator, Cluster-id */
8485 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
8486 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
8488 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
8490 json_object_string_add(
8491 json_path
, "originatorId",
8492 inet_ntoa(attr
->originator_id
));
8494 vty_out(vty
, " Originator: %s",
8495 inet_ntoa(attr
->originator_id
));
8498 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
8503 json_object_new_object();
8504 json_cluster_list_list
=
8505 json_object_new_array();
8508 i
< attr
->cluster
->length
/ 4;
8510 json_string
= json_object_new_string(
8514 json_object_array_add(
8515 json_cluster_list_list
,
8519 /* struct cluster_list does not have
8521 * aspath and community do. Add this
8524 json_object_string_add(json_cluster_list,
8525 "string", attr->cluster->str);
8527 json_object_object_add(
8528 json_cluster_list
, "list",
8529 json_cluster_list_list
);
8530 json_object_object_add(
8531 json_path
, "clusterList",
8534 vty_out(vty
, ", Cluster list: ");
8537 i
< attr
->cluster
->length
/ 4;
8551 if (path
->extra
&& path
->extra
->damp_info
)
8552 bgp_damp_info_vty(vty
, path
, json_path
);
8555 if (path
->extra
&& bgp_is_valid_label(&path
->extra
->label
[0])
8556 && safi
!= SAFI_EVPN
) {
8557 mpls_label_t label
= label_pton(&path
->extra
->label
[0]);
8560 json_object_int_add(json_path
, "remoteLabel",
8563 vty_out(vty
, " Remote label: %d\n", label
);
8567 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
8569 json_object_int_add(json_path
, "labelIndex",
8572 vty_out(vty
, " Label Index: %d\n",
8576 /* Line 8 display Addpath IDs */
8577 if (path
->addpath_rx_id
8578 || bgp_addpath_info_has_ids(&path
->tx_addpath
)) {
8580 json_object_int_add(json_path
, "addpathRxId",
8581 path
->addpath_rx_id
);
8583 /* Keep backwards compatibility with the old API
8584 * by putting TX All's ID in the old field
8586 json_object_int_add(
8587 json_path
, "addpathTxId",
8588 path
->tx_addpath
.addpath_tx_id
8591 /* ... but create a specific field for each
8594 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
8595 json_object_int_add(
8597 bgp_addpath_names(i
)
8603 vty_out(vty
, " AddPath ID: RX %u, ",
8604 path
->addpath_rx_id
);
8606 route_vty_out_tx_ids(vty
, &path
->tx_addpath
);
8610 /* If we used addpath to TX a non-bestpath we need to display
8611 * "Advertised to" on a path-by-path basis
8613 if (bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
8616 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
8618 bgp_addpath_encode_tx(peer
, afi
, safi
);
8619 has_adj
= bgp_adj_out_lookup(
8621 bgp_addpath_id_for_peer(
8623 &path
->tx_addpath
));
8625 if ((addpath_capable
&& has_adj
)
8626 || (!addpath_capable
&& has_adj
8627 && CHECK_FLAG(path
->flags
,
8628 BGP_PATH_SELECTED
))) {
8629 if (json_path
&& !json_adv_to
)
8631 json_object_new_object();
8633 route_vty_out_advertised_to(
8642 json_object_object_add(json_path
,
8653 /* Line 9 display Uptime */
8654 tbuf
= time(NULL
) - (bgp_clock() - path
->uptime
);
8656 json_last_update
= json_object_new_object();
8657 json_object_int_add(json_last_update
, "epoch", tbuf
);
8658 json_object_string_add(json_last_update
, "string",
8660 json_object_object_add(json_path
, "lastUpdate",
8663 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
8665 /* Line 10 display PMSI tunnel attribute, if present */
8666 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
8667 const char *str
= lookup_msg(bgp_pmsi_tnltype_str
,
8668 attr
->pmsi_tnl_type
,
8669 PMSI_TNLTYPE_STR_DEFAULT
);
8672 json_pmsi
= json_object_new_object();
8673 json_object_string_add(json_pmsi
,
8675 json_object_int_add(json_pmsi
,
8677 label2vni(&attr
->label
));
8678 json_object_object_add(json_path
, "pmsi",
8682 " PMSI Tunnel Type: %s, label: %d\n",
8683 str
, label2vni(&attr
->label
));
8688 /* We've constructed the json object for this path, add it to the json
8692 if (json_nexthop_global
|| json_nexthop_ll
) {
8693 json_nexthops
= json_object_new_array();
8695 if (json_nexthop_global
)
8696 json_object_array_add(json_nexthops
,
8697 json_nexthop_global
);
8699 if (json_nexthop_ll
)
8700 json_object_array_add(json_nexthops
,
8703 json_object_object_add(json_path
, "nexthops",
8707 json_object_object_add(json_path
, "peer", json_peer
);
8708 json_object_array_add(json_paths
, json_path
);
8713 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
8714 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
8715 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
8717 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
8718 const char *prefix_list_str
, afi_t afi
,
8719 safi_t safi
, enum bgp_show_type type
);
8720 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
8721 const char *filter
, afi_t afi
, safi_t safi
,
8722 enum bgp_show_type type
);
8723 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
8724 const char *rmap_str
, afi_t afi
, safi_t safi
,
8725 enum bgp_show_type type
);
8726 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
8727 const char *com
, int exact
, afi_t afi
,
8729 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
8730 const char *prefix
, afi_t afi
, safi_t safi
,
8731 enum bgp_show_type type
);
8732 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
8733 afi_t afi
, safi_t safi
, enum bgp_show_type type
);
8734 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
8735 const char *comstr
, int exact
, afi_t afi
,
8736 safi_t safi
, bool use_json
);
8739 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
8740 struct bgp_table
*table
, enum bgp_show_type type
,
8741 void *output_arg
, bool use_json
, char *rd
,
8742 int is_last
, unsigned long *output_cum
,
8743 unsigned long *total_cum
,
8744 unsigned long *json_header_depth
)
8746 struct bgp_path_info
*pi
;
8747 struct bgp_node
*rn
;
8750 unsigned long output_count
= 0;
8751 unsigned long total_count
= 0;
8754 json_object
*json_paths
= NULL
;
8757 if (output_cum
&& *output_cum
!= 0)
8760 if (use_json
&& !*json_header_depth
) {
8762 "{\n \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
8763 ",\n \"routerId\": \"%s\",\n \"defaultLocPrf\": %u,\n"
8764 " \"localAS\": %u,\n \"routes\": { ",
8765 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
8766 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
8769 table
->version
, inet_ntoa(bgp
->router_id
),
8770 bgp
->default_local_pref
, bgp
->as
);
8771 *json_header_depth
= 2;
8773 vty_out(vty
, " \"routeDistinguishers\" : {");
8774 ++*json_header_depth
;
8778 if (use_json
&& rd
) {
8779 vty_out(vty
, " \"%s\" : { ", rd
);
8782 /* Start processing of routes. */
8783 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
8784 pi
= bgp_node_get_bgp_path_info(rn
);
8790 json_paths
= json_object_new_array();
8794 for (; pi
; pi
= pi
->next
) {
8796 if (type
== bgp_show_type_flap_statistics
8797 || type
== bgp_show_type_flap_neighbor
8798 || type
== bgp_show_type_dampend_paths
8799 || type
== bgp_show_type_damp_neighbor
) {
8800 if (!(pi
->extra
&& pi
->extra
->damp_info
))
8803 if (type
== bgp_show_type_regexp
) {
8804 regex_t
*regex
= output_arg
;
8806 if (bgp_regexec(regex
, pi
->attr
->aspath
)
8810 if (type
== bgp_show_type_prefix_list
) {
8811 struct prefix_list
*plist
= output_arg
;
8813 if (prefix_list_apply(plist
, &rn
->p
)
8817 if (type
== bgp_show_type_filter_list
) {
8818 struct as_list
*as_list
= output_arg
;
8820 if (as_list_apply(as_list
, pi
->attr
->aspath
)
8821 != AS_FILTER_PERMIT
)
8824 if (type
== bgp_show_type_route_map
) {
8825 struct route_map
*rmap
= output_arg
;
8826 struct bgp_path_info path
;
8827 struct attr dummy_attr
;
8830 bgp_attr_dup(&dummy_attr
, pi
->attr
);
8832 path
.peer
= pi
->peer
;
8833 path
.attr
= &dummy_attr
;
8835 ret
= route_map_apply(rmap
, &rn
->p
, RMAP_BGP
,
8837 if (ret
== RMAP_DENYMATCH
)
8840 if (type
== bgp_show_type_neighbor
8841 || type
== bgp_show_type_flap_neighbor
8842 || type
== bgp_show_type_damp_neighbor
) {
8843 union sockunion
*su
= output_arg
;
8845 if (pi
->peer
== NULL
8846 || pi
->peer
->su_remote
== NULL
8847 || !sockunion_same(pi
->peer
->su_remote
, su
))
8850 if (type
== bgp_show_type_cidr_only
) {
8851 uint32_t destination
;
8853 destination
= ntohl(rn
->p
.u
.prefix4
.s_addr
);
8854 if (IN_CLASSC(destination
)
8855 && rn
->p
.prefixlen
== 24)
8857 if (IN_CLASSB(destination
)
8858 && rn
->p
.prefixlen
== 16)
8860 if (IN_CLASSA(destination
)
8861 && rn
->p
.prefixlen
== 8)
8864 if (type
== bgp_show_type_prefix_longer
) {
8866 if (!prefix_match(p
, &rn
->p
))
8869 if (type
== bgp_show_type_community_all
) {
8870 if (!pi
->attr
->community
)
8873 if (type
== bgp_show_type_community
) {
8874 struct community
*com
= output_arg
;
8876 if (!pi
->attr
->community
8877 || !community_match(pi
->attr
->community
,
8881 if (type
== bgp_show_type_community_exact
) {
8882 struct community
*com
= output_arg
;
8884 if (!pi
->attr
->community
8885 || !community_cmp(pi
->attr
->community
, com
))
8888 if (type
== bgp_show_type_community_list
) {
8889 struct community_list
*list
= output_arg
;
8891 if (!community_list_match(pi
->attr
->community
,
8895 if (type
== bgp_show_type_community_list_exact
) {
8896 struct community_list
*list
= output_arg
;
8898 if (!community_list_exact_match(
8899 pi
->attr
->community
, list
))
8902 if (type
== bgp_show_type_lcommunity
) {
8903 struct lcommunity
*lcom
= output_arg
;
8905 if (!pi
->attr
->lcommunity
8906 || !lcommunity_match(pi
->attr
->lcommunity
,
8910 if (type
== bgp_show_type_lcommunity_list
) {
8911 struct community_list
*list
= output_arg
;
8913 if (!lcommunity_list_match(pi
->attr
->lcommunity
,
8917 if (type
== bgp_show_type_lcommunity_all
) {
8918 if (!pi
->attr
->lcommunity
)
8921 if (type
== bgp_show_type_dampend_paths
8922 || type
== bgp_show_type_damp_neighbor
) {
8923 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
)
8924 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
8928 if (!use_json
&& header
) {
8929 vty_out(vty
, "BGP table version is %" PRIu64
8930 ", local router ID is %s, vrf id ",
8932 inet_ntoa(bgp
->router_id
));
8933 if (bgp
->vrf_id
== VRF_UNKNOWN
)
8934 vty_out(vty
, "%s", VRFID_NONE_STR
);
8936 vty_out(vty
, "%u", bgp
->vrf_id
);
8938 vty_out(vty
, "Default local pref %u, ",
8939 bgp
->default_local_pref
);
8940 vty_out(vty
, "local AS %u\n", bgp
->as
);
8941 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
8942 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
8943 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
8944 if (type
== bgp_show_type_dampend_paths
8945 || type
== bgp_show_type_damp_neighbor
)
8946 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
8947 else if (type
== bgp_show_type_flap_statistics
8948 || type
== bgp_show_type_flap_neighbor
)
8949 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
8951 vty_out(vty
, BGP_SHOW_HEADER
);
8954 if (rd
!= NULL
&& !display
&& !output_count
) {
8957 "Route Distinguisher: %s\n",
8960 if (type
== bgp_show_type_dampend_paths
8961 || type
== bgp_show_type_damp_neighbor
)
8962 damp_route_vty_out(vty
, &rn
->p
, pi
, display
,
8963 safi
, use_json
, json_paths
);
8964 else if (type
== bgp_show_type_flap_statistics
8965 || type
== bgp_show_type_flap_neighbor
)
8966 flap_route_vty_out(vty
, &rn
->p
, pi
, display
,
8967 safi
, use_json
, json_paths
);
8969 route_vty_out(vty
, &rn
->p
, pi
, display
, safi
,
8981 if (p
->family
== AF_FLOWSPEC
) {
8982 char retstr
[BGP_FLOWSPEC_STRING_DISPLAY_MAX
];
8984 bgp_fs_nlri_get_string((unsigned char *)
8985 p
->u
.prefix_flowspec
.ptr
,
8986 p
->u
.prefix_flowspec
8989 NLRI_STRING_FORMAT_MIN
,
8992 vty_out(vty
, "\"%s/%d\": ",
8994 p
->u
.prefix_flowspec
.prefixlen
);
8996 vty_out(vty
, ",\"%s/%d\": ",
8998 p
->u
.prefix_flowspec
.prefixlen
);
9000 prefix2str(p
, buf2
, sizeof(buf2
));
9002 vty_out(vty
, "\"%s\": ", buf2
);
9004 vty_out(vty
, ",\"%s\": ", buf2
);
9007 json_object_to_json_string(json_paths
));
9008 json_object_free(json_paths
);
9015 output_count
+= *output_cum
;
9016 *output_cum
= output_count
;
9019 total_count
+= *total_cum
;
9020 *total_cum
= total_count
;
9024 vty_out(vty
, " }%s ", (is_last
? "" : ","));
9028 for (i
= 0; i
< *json_header_depth
; ++i
)
9029 vty_out(vty
, " } ");
9033 /* No route is displayed */
9034 if (output_count
== 0) {
9035 if (type
== bgp_show_type_normal
)
9037 "No BGP prefixes displayed, %ld exist\n",
9041 "\nDisplayed %ld routes and %ld total paths\n",
9042 output_count
, total_count
);
9049 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
9050 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
9051 enum bgp_show_type type
, void *output_arg
, bool use_json
)
9053 struct bgp_node
*rn
, *next
;
9054 unsigned long output_cum
= 0;
9055 unsigned long total_cum
= 0;
9056 unsigned long json_header_depth
= 0;
9057 struct bgp_table
*itable
;
9060 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
9062 for (rn
= bgp_table_top(table
); rn
; rn
= next
) {
9063 next
= bgp_route_next(rn
);
9064 if (prd_match
&& memcmp(rn
->p
.u
.val
, prd_match
->val
, 8) != 0)
9067 itable
= bgp_node_get_bgp_table_info(rn
);
9068 if (itable
!= NULL
) {
9069 struct prefix_rd prd
;
9070 char rd
[RD_ADDRSTRLEN
];
9072 memcpy(&prd
, &(rn
->p
), sizeof(struct prefix_rd
));
9073 prefix_rd2str(&prd
, rd
, sizeof(rd
));
9074 bgp_show_table(vty
, bgp
, safi
, itable
, type
, output_arg
,
9075 use_json
, rd
, next
== NULL
, &output_cum
,
9076 &total_cum
, &json_header_depth
);
9082 if (output_cum
== 0)
9083 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
9087 "\nDisplayed %ld routes and %ld total paths\n",
9088 output_cum
, total_cum
);
9092 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
9093 enum bgp_show_type type
, void *output_arg
, bool use_json
)
9095 struct bgp_table
*table
;
9096 unsigned long json_header_depth
= 0;
9099 bgp
= bgp_get_default();
9104 vty_out(vty
, "No BGP process is configured\n");
9106 vty_out(vty
, "{}\n");
9110 table
= bgp
->rib
[afi
][safi
];
9111 /* use MPLS and ENCAP specific shows until they are merged */
9112 if (safi
== SAFI_MPLS_VPN
) {
9113 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
9114 output_arg
, use_json
);
9117 if (safi
== SAFI_FLOWSPEC
&& type
== bgp_show_type_detail
) {
9118 return bgp_show_table_flowspec(vty
, bgp
, afi
, table
, type
,
9119 output_arg
, use_json
,
9122 /* labeled-unicast routes live in the unicast table */
9123 else if (safi
== SAFI_LABELED_UNICAST
)
9124 safi
= SAFI_UNICAST
;
9126 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, use_json
,
9127 NULL
, 1, NULL
, NULL
, &json_header_depth
);
9130 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
9131 safi_t safi
, bool use_json
)
9133 struct listnode
*node
, *nnode
;
9136 bool route_output
= false;
9139 vty_out(vty
, "{\n");
9141 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
9142 route_output
= true;
9145 vty_out(vty
, ",\n");
9149 vty_out(vty
, "\"%s\":",
9150 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
9154 vty_out(vty
, "\nInstance %s:\n",
9155 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
9159 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
9164 vty_out(vty
, "}\n");
9165 else if (!route_output
)
9166 vty_out(vty
, "%% BGP instance not found\n");
9169 /* Header of detailed BGP route information */
9170 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
9171 struct bgp_node
*rn
, struct prefix_rd
*prd
,
9172 afi_t afi
, safi_t safi
, json_object
*json
)
9174 struct bgp_path_info
*pi
;
9177 struct listnode
*node
, *nnode
;
9178 char buf1
[RD_ADDRSTRLEN
];
9179 char buf2
[INET6_ADDRSTRLEN
];
9180 char buf3
[EVPN_ROUTE_STRLEN
];
9181 char prefix_str
[BUFSIZ
];
9186 int route_filter_translated_v4
= 0;
9187 int route_filter_v4
= 0;
9188 int route_filter_translated_v6
= 0;
9189 int route_filter_v6
= 0;
9192 int accept_own_nexthop
= 0;
9195 int no_advertise
= 0;
9199 int has_valid_label
= 0;
9200 mpls_label_t label
= 0;
9201 json_object
*json_adv_to
= NULL
;
9204 has_valid_label
= bgp_is_valid_label(&rn
->local_label
);
9206 if (has_valid_label
)
9207 label
= label_pton(&rn
->local_label
);
9210 if (has_valid_label
)
9211 json_object_int_add(json
, "localLabel", label
);
9213 json_object_string_add(
9215 prefix2str(p
, prefix_str
, sizeof(prefix_str
)));
9217 if (safi
== SAFI_EVPN
)
9218 vty_out(vty
, "BGP routing table entry for %s%s%s\n",
9219 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
))
9222 bgp_evpn_route2str((struct prefix_evpn
*)p
,
9223 buf3
, sizeof(buf3
)));
9225 vty_out(vty
, "BGP routing table entry for %s%s%s/%d\n",
9226 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
9227 ? prefix_rd2str(prd
, buf1
,
9230 safi
== SAFI_MPLS_VPN
? ":" : "",
9231 inet_ntop(p
->family
, &p
->u
.prefix
, buf2
,
9235 if (has_valid_label
)
9236 vty_out(vty
, "Local label: %d\n", label
);
9237 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
9238 vty_out(vty
, "not allocated\n");
9241 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
9243 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
9245 if (pi
->extra
&& pi
->extra
->suppress
)
9248 if (pi
->attr
->community
== NULL
)
9251 no_advertise
+= community_include(
9252 pi
->attr
->community
, COMMUNITY_NO_ADVERTISE
);
9253 no_export
+= community_include(pi
->attr
->community
,
9254 COMMUNITY_NO_EXPORT
);
9255 local_as
+= community_include(pi
->attr
->community
,
9256 COMMUNITY_LOCAL_AS
);
9257 accept_own
+= community_include(pi
->attr
->community
,
9258 COMMUNITY_ACCEPT_OWN
);
9259 route_filter_translated_v4
+= community_include(
9260 pi
->attr
->community
,
9261 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4
);
9262 route_filter_translated_v6
+= community_include(
9263 pi
->attr
->community
,
9264 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6
);
9265 route_filter_v4
+= community_include(
9266 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v4
);
9267 route_filter_v6
+= community_include(
9268 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v6
);
9269 llgr_stale
+= community_include(pi
->attr
->community
,
9270 COMMUNITY_LLGR_STALE
);
9271 no_llgr
+= community_include(pi
->attr
->community
,
9273 accept_own_nexthop
+=
9274 community_include(pi
->attr
->community
,
9275 COMMUNITY_ACCEPT_OWN_NEXTHOP
);
9276 blackhole
+= community_include(pi
->attr
->community
,
9277 COMMUNITY_BLACKHOLE
);
9278 no_peer
+= community_include(pi
->attr
->community
,
9284 vty_out(vty
, "Paths: (%d available", count
);
9286 vty_out(vty
, ", best #%d", best
);
9287 if (safi
== SAFI_UNICAST
)
9288 vty_out(vty
, ", table %s",
9290 == BGP_INSTANCE_TYPE_DEFAULT
)
9294 vty_out(vty
, ", no best path");
9298 ", accept own local route exported and imported in different VRF");
9299 else if (route_filter_translated_v4
)
9301 ", mark translated RTs for VPNv4 route filtering");
9302 else if (route_filter_v4
)
9304 ", attach RT as-is for VPNv4 route filtering");
9305 else if (route_filter_translated_v6
)
9307 ", mark translated RTs for VPNv6 route filtering");
9308 else if (route_filter_v6
)
9310 ", attach RT as-is for VPNv6 route filtering");
9311 else if (llgr_stale
)
9313 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
9316 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
9317 else if (accept_own_nexthop
)
9319 ", accept local nexthop");
9321 vty_out(vty
, ", inform peer to blackhole prefix");
9323 vty_out(vty
, ", not advertised to EBGP peer");
9324 else if (no_advertise
)
9325 vty_out(vty
, ", not advertised to any peer");
9327 vty_out(vty
, ", not advertised outside local AS");
9330 ", inform EBGP peer not to advertise to their EBGP peers");
9334 ", Advertisements suppressed by an aggregate.");
9335 vty_out(vty
, ")\n");
9338 /* If we are not using addpath then we can display Advertised to and
9340 * show what peers we advertised the bestpath to. If we are using
9342 * though then we must display Advertised to on a path-by-path basis. */
9343 if (!bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
9344 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
9345 if (bgp_adj_out_lookup(peer
, rn
, 0)) {
9346 if (json
&& !json_adv_to
)
9347 json_adv_to
= json_object_new_object();
9349 route_vty_out_advertised_to(
9351 " Advertised to non peer-group peers:\n ",
9358 json_object_object_add(json
, "advertisedTo",
9363 vty_out(vty
, " Not advertised to any peer");
9369 /* Display specified route of BGP table. */
9370 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
9371 struct bgp_table
*rib
, const char *ip_str
,
9372 afi_t afi
, safi_t safi
,
9373 struct prefix_rd
*prd
, int prefix_check
,
9374 enum bgp_path_type pathtype
, bool use_json
)
9379 struct prefix match
;
9380 struct bgp_node
*rn
;
9381 struct bgp_node
*rm
;
9382 struct bgp_path_info
*pi
;
9383 struct bgp_table
*table
;
9384 json_object
*json
= NULL
;
9385 json_object
*json_paths
= NULL
;
9387 /* Check IP address argument. */
9388 ret
= str2prefix(ip_str
, &match
);
9390 vty_out(vty
, "address is malformed\n");
9394 match
.family
= afi2family(afi
);
9397 json
= json_object_new_object();
9398 json_paths
= json_object_new_array();
9401 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
9402 for (rn
= bgp_table_top(rib
); rn
; rn
= bgp_route_next(rn
)) {
9403 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
9405 table
= bgp_node_get_bgp_table_info(rn
);
9411 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
9415 && rm
->p
.prefixlen
!= match
.prefixlen
) {
9416 bgp_unlock_node(rm
);
9420 for (pi
= bgp_node_get_bgp_path_info(rm
); pi
;
9423 route_vty_out_detail_header(
9425 (struct prefix_rd
*)&rn
->p
,
9426 AFI_IP
, safi
, json
);
9431 if (pathtype
== BGP_PATH_SHOW_ALL
9432 || (pathtype
== BGP_PATH_SHOW_BESTPATH
9433 && CHECK_FLAG(pi
->flags
,
9435 || (pathtype
== BGP_PATH_SHOW_MULTIPATH
9436 && (CHECK_FLAG(pi
->flags
,
9438 || CHECK_FLAG(pi
->flags
,
9439 BGP_PATH_SELECTED
))))
9440 route_vty_out_detail(vty
, bgp
, &rm
->p
,
9445 bgp_unlock_node(rm
);
9447 } else if (safi
== SAFI_FLOWSPEC
) {
9448 display
= bgp_flowspec_display_match_per_ip(afi
, rib
,
9449 &match
, prefix_check
,
9456 if ((rn
= bgp_node_match(rib
, &match
)) != NULL
) {
9458 || rn
->p
.prefixlen
== match
.prefixlen
) {
9459 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
;
9462 route_vty_out_detail_header(
9463 vty
, bgp
, rn
, NULL
, afi
,
9469 if (pathtype
== BGP_PATH_SHOW_ALL
9471 == BGP_PATH_SHOW_BESTPATH
9476 == BGP_PATH_SHOW_MULTIPATH
9482 BGP_PATH_SELECTED
))))
9483 route_vty_out_detail(
9484 vty
, bgp
, &rn
->p
, pi
,
9485 afi
, safi
, json_paths
);
9489 bgp_unlock_node(rn
);
9495 json_object_object_add(json
, "paths", json_paths
);
9497 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
9498 json
, JSON_C_TO_STRING_PRETTY
));
9499 json_object_free(json
);
9502 vty_out(vty
, "%% Network not in table\n");
9510 /* Display specified route of Main RIB */
9511 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
9512 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
9513 int prefix_check
, enum bgp_path_type pathtype
,
9517 bgp
= bgp_get_default();
9520 vty_out(vty
, "No BGP process is configured\n");
9522 vty_out(vty
, "{}\n");
9527 /* labeled-unicast routes live in the unicast table */
9528 if (safi
== SAFI_LABELED_UNICAST
)
9529 safi
= SAFI_UNICAST
;
9531 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
9532 afi
, safi
, prd
, prefix_check
, pathtype
,
9536 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
9537 struct cmd_token
**argv
, afi_t afi
, safi_t safi
,
9540 struct lcommunity
*lcom
;
9546 b
= buffer_new(1024);
9547 for (i
= 0; i
< argc
; i
++) {
9549 buffer_putc(b
, ' ');
9551 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
9553 buffer_putstr(b
, argv
[i
]->arg
);
9557 buffer_putc(b
, '\0');
9559 str
= buffer_getstr(b
);
9562 lcom
= lcommunity_str2com(str
);
9563 XFREE(MTYPE_TMP
, str
);
9565 vty_out(vty
, "%% Large-community malformed\n");
9569 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_lcommunity
, lcom
,
9573 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
9574 const char *lcom
, afi_t afi
, safi_t safi
,
9577 struct community_list
*list
;
9579 list
= community_list_lookup(bgp_clist
, lcom
, 0,
9580 LARGE_COMMUNITY_LIST_MASTER
);
9582 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
9587 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_lcommunity_list
,
9591 DEFUN (show_ip_bgp_large_community_list
,
9592 show_ip_bgp_large_community_list_cmd
,
9593 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community-list <(1-500)|WORD> [json]",
9597 BGP_INSTANCE_HELP_STR
9599 BGP_SAFI_WITH_LABEL_HELP_STR
9600 "Display routes matching the large-community-list\n"
9601 "large-community-list number\n"
9602 "large-community-list name\n"
9606 afi_t afi
= AFI_IP6
;
9607 safi_t safi
= SAFI_UNICAST
;
9610 if (argv_find(argv
, argc
, "ip", &idx
))
9612 if (argv_find(argv
, argc
, "view", &idx
)
9613 || argv_find(argv
, argc
, "vrf", &idx
))
9614 vrf
= argv
[++idx
]->arg
;
9615 if (argv_find(argv
, argc
, "ipv4", &idx
)
9616 || argv_find(argv
, argc
, "ipv6", &idx
)) {
9617 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
9618 if (argv_find(argv
, argc
, "unicast", &idx
)
9619 || argv_find(argv
, argc
, "multicast", &idx
))
9620 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
9623 bool uj
= use_json(argc
, argv
);
9625 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
9627 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
9631 argv_find(argv
, argc
, "large-community-list", &idx
);
9632 return bgp_show_lcommunity_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
, safi
,
9635 DEFUN (show_ip_bgp_large_community
,
9636 show_ip_bgp_large_community_cmd
,
9637 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [AA:BB:CC] [json]",
9641 BGP_INSTANCE_HELP_STR
9643 BGP_SAFI_WITH_LABEL_HELP_STR
9644 "Display routes matching the large-communities\n"
9645 "List of large-community numbers\n"
9649 afi_t afi
= AFI_IP6
;
9650 safi_t safi
= SAFI_UNICAST
;
9653 if (argv_find(argv
, argc
, "ip", &idx
))
9655 if (argv_find(argv
, argc
, "view", &idx
)
9656 || argv_find(argv
, argc
, "vrf", &idx
))
9657 vrf
= argv
[++idx
]->arg
;
9658 if (argv_find(argv
, argc
, "ipv4", &idx
)
9659 || argv_find(argv
, argc
, "ipv6", &idx
)) {
9660 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
9661 if (argv_find(argv
, argc
, "unicast", &idx
)
9662 || argv_find(argv
, argc
, "multicast", &idx
))
9663 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
9666 bool uj
= use_json(argc
, argv
);
9668 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
9670 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
9674 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
))
9675 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
, afi
, safi
, uj
);
9677 return bgp_show(vty
, bgp
, afi
, safi
,
9678 bgp_show_type_lcommunity_all
, NULL
, uj
);
9681 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
9685 /* BGP route print out function without JSON */
9688 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
9689 <dampening <parameters>\
9694 |community-list <(1-500)|WORD> [exact-match]\
9695 |A.B.C.D/M longer-prefixes\
9696 |X:X::X:X/M longer-prefixes\
9701 BGP_INSTANCE_HELP_STR
9703 BGP_SAFI_WITH_LABEL_HELP_STR
9704 "Display detailed information about dampening\n"
9705 "Display detail of configured dampening parameters\n"
9706 "Display routes matching the route-map\n"
9707 "A route-map to match on\n"
9708 "Display routes conforming to the prefix-list\n"
9709 "Prefix-list name\n"
9710 "Display routes conforming to the filter-list\n"
9711 "Regular expression access list name\n"
9712 "BGP RIB advertisement statistics\n"
9713 "Display routes matching the community-list\n"
9714 "community-list number\n"
9715 "community-list name\n"
9716 "Exact match of the communities\n"
9718 "Display route and more specific routes\n"
9720 "Display route and more specific routes\n")
9722 afi_t afi
= AFI_IP6
;
9723 safi_t safi
= SAFI_UNICAST
;
9724 int exact_match
= 0;
9725 struct bgp
*bgp
= NULL
;
9728 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9733 if (argv_find(argv
, argc
, "dampening", &idx
)) {
9734 if (argv_find(argv
, argc
, "parameters", &idx
))
9735 return bgp_show_dampening_parameters(vty
, afi
, safi
);
9738 if (argv_find(argv
, argc
, "prefix-list", &idx
))
9739 return bgp_show_prefix_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9740 safi
, bgp_show_type_prefix_list
);
9742 if (argv_find(argv
, argc
, "filter-list", &idx
))
9743 return bgp_show_filter_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9744 safi
, bgp_show_type_filter_list
);
9746 if (argv_find(argv
, argc
, "statistics", &idx
))
9747 return bgp_table_stats(vty
, bgp
, afi
, safi
);
9749 if (argv_find(argv
, argc
, "route-map", &idx
))
9750 return bgp_show_route_map(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9751 safi
, bgp_show_type_route_map
);
9753 if (argv_find(argv
, argc
, "community-list", &idx
)) {
9754 const char *clist_number_or_name
= argv
[++idx
]->arg
;
9755 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
9757 return bgp_show_community_list(vty
, bgp
, clist_number_or_name
,
9758 exact_match
, afi
, safi
);
9761 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
9762 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
9763 return bgp_show_prefix_longer(vty
, bgp
, argv
[idx
]->arg
, afi
,
9765 bgp_show_type_prefix_longer
);
9770 /* BGP route print out function with JSON */
9771 DEFUN (show_ip_bgp_json
,
9772 show_ip_bgp_json_cmd
,
9773 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
9775 |dampening <flap-statistics|dampened-paths>\
9776 |community [AA:NN|local-AS|no-advertise|no-export\
9777 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
9778 |accept-own|accept-own-nexthop|route-filter-v6\
9779 |route-filter-v4|route-filter-translated-v6\
9780 |route-filter-translated-v4] [exact-match]\
9785 BGP_INSTANCE_HELP_STR
9787 BGP_SAFI_WITH_LABEL_HELP_STR
9788 "Display only routes with non-natural netmasks\n"
9789 "Display detailed information about dampening\n"
9790 "Display flap statistics of routes\n"
9791 "Display paths suppressed due to dampening\n"
9792 "Display routes matching the communities\n"
9794 "Do not send outside local AS (well-known community)\n"
9795 "Do not advertise to any peer (well-known community)\n"
9796 "Do not export to next AS (well-known community)\n"
9797 "Graceful shutdown (well-known community)\n"
9798 "Do not export to any peer (well-known community)\n"
9799 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
9800 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
9801 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
9802 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
9803 "Should accept VPN route with local nexthop (well-known community)\n"
9804 "RT VPNv6 route filtering (well-known community)\n"
9805 "RT VPNv4 route filtering (well-known community)\n"
9806 "RT translated VPNv6 route filtering (well-known community)\n"
9807 "RT translated VPNv4 route filtering (well-known community)\n"
9808 "Exact match of the communities\n"
9811 afi_t afi
= AFI_IP6
;
9812 safi_t safi
= SAFI_UNICAST
;
9813 enum bgp_show_type sh_type
= bgp_show_type_normal
;
9814 struct bgp
*bgp
= NULL
;
9816 int exact_match
= 0;
9817 bool uj
= use_json(argc
, argv
);
9822 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9827 if (argv_find(argv
, argc
, "cidr-only", &idx
))
9828 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_cidr_only
,
9831 if (argv_find(argv
, argc
, "dampening", &idx
)) {
9832 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
9833 return bgp_show(vty
, bgp
, afi
, safi
,
9834 bgp_show_type_dampend_paths
, NULL
, uj
);
9835 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
9836 return bgp_show(vty
, bgp
, afi
, safi
,
9837 bgp_show_type_flap_statistics
, NULL
,
9841 if (argv_find(argv
, argc
, "community", &idx
)) {
9842 char *maybecomm
= NULL
;
9843 char *community
= NULL
;
9845 if (idx
+ 1 < argc
) {
9846 if (argv
[idx
+ 1]->type
== VARIABLE_TKN
)
9847 maybecomm
= argv
[idx
+ 1]->arg
;
9849 maybecomm
= argv
[idx
+ 1]->text
;
9852 if (maybecomm
&& !strmatch(maybecomm
, "json")
9853 && !strmatch(maybecomm
, "exact-match"))
9854 community
= maybecomm
;
9856 if (argv_find(argv
, argc
, "exact-match", &idx
))
9860 return bgp_show_community(vty
, bgp
, community
,
9861 exact_match
, afi
, safi
, uj
);
9863 return (bgp_show(vty
, bgp
, afi
, safi
,
9864 bgp_show_type_community_all
, NULL
,
9868 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
, NULL
, uj
);
9871 DEFUN (show_ip_bgp_route
,
9872 show_ip_bgp_route_cmd
,
9873 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]"
9874 "<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [json]",
9878 BGP_INSTANCE_HELP_STR
9880 BGP_SAFI_WITH_LABEL_HELP_STR
9881 "Network in the BGP routing table to display\n"
9883 "Network in the BGP routing table to display\n"
9885 "Display only the bestpath\n"
9886 "Display only multipaths\n"
9889 int prefix_check
= 0;
9891 afi_t afi
= AFI_IP6
;
9892 safi_t safi
= SAFI_UNICAST
;
9893 char *prefix
= NULL
;
9894 struct bgp
*bgp
= NULL
;
9895 enum bgp_path_type path_type
;
9896 bool uj
= use_json(argc
, argv
);
9900 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9907 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
9911 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
9912 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
9913 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
9915 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
9916 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
9919 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
9920 && afi
!= AFI_IP6
) {
9922 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
9925 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
9928 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
9932 prefix
= argv
[idx
]->arg
;
9934 /* [<bestpath|multipath>] */
9935 if (argv_find(argv
, argc
, "bestpath", &idx
))
9936 path_type
= BGP_PATH_SHOW_BESTPATH
;
9937 else if (argv_find(argv
, argc
, "multipath", &idx
))
9938 path_type
= BGP_PATH_SHOW_MULTIPATH
;
9940 path_type
= BGP_PATH_SHOW_ALL
;
9942 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
9946 DEFUN (show_ip_bgp_regexp
,
9947 show_ip_bgp_regexp_cmd
,
9948 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX...",
9952 BGP_INSTANCE_HELP_STR
9954 BGP_SAFI_WITH_LABEL_HELP_STR
9955 "Display routes matching the AS path regular expression\n"
9956 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n")
9958 afi_t afi
= AFI_IP6
;
9959 safi_t safi
= SAFI_UNICAST
;
9960 struct bgp
*bgp
= NULL
;
9963 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9968 // get index of regex
9969 argv_find(argv
, argc
, "regexp", &idx
);
9972 char *regstr
= argv_concat(argv
, argc
, idx
);
9973 int rc
= bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
9974 bgp_show_type_regexp
);
9975 XFREE(MTYPE_TMP
, regstr
);
9979 DEFUN (show_ip_bgp_instance_all
,
9980 show_ip_bgp_instance_all_cmd
,
9981 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json]",
9985 BGP_INSTANCE_ALL_HELP_STR
9987 BGP_SAFI_WITH_LABEL_HELP_STR
9991 safi_t safi
= SAFI_UNICAST
;
9992 struct bgp
*bgp
= NULL
;
9994 bool uj
= use_json(argc
, argv
);
9999 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10002 return CMD_WARNING
;
10004 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, uj
);
10005 return CMD_SUCCESS
;
10008 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
10009 afi_t afi
, safi_t safi
, enum bgp_show_type type
)
10014 if (!config_bgp_aspath_validate(regstr
)) {
10015 vty_out(vty
, "Invalid character in as-path access-list %s\n",
10017 return CMD_WARNING_CONFIG_FAILED
;
10020 regex
= bgp_regcomp(regstr
);
10022 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
10023 return CMD_WARNING
;
10026 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, 0);
10027 bgp_regex_free(regex
);
10031 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
10032 const char *prefix_list_str
, afi_t afi
,
10033 safi_t safi
, enum bgp_show_type type
)
10035 struct prefix_list
*plist
;
10037 plist
= prefix_list_lookup(afi
, prefix_list_str
);
10038 if (plist
== NULL
) {
10039 vty_out(vty
, "%% %s is not a valid prefix-list name\n",
10041 return CMD_WARNING
;
10044 return bgp_show(vty
, bgp
, afi
, safi
, type
, plist
, 0);
10047 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
10048 const char *filter
, afi_t afi
, safi_t safi
,
10049 enum bgp_show_type type
)
10051 struct as_list
*as_list
;
10053 as_list
= as_list_lookup(filter
);
10054 if (as_list
== NULL
) {
10055 vty_out(vty
, "%% %s is not a valid AS-path access-list name\n",
10057 return CMD_WARNING
;
10060 return bgp_show(vty
, bgp
, afi
, safi
, type
, as_list
, 0);
10063 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
10064 const char *rmap_str
, afi_t afi
, safi_t safi
,
10065 enum bgp_show_type type
)
10067 struct route_map
*rmap
;
10069 rmap
= route_map_lookup_by_name(rmap_str
);
10071 vty_out(vty
, "%% %s is not a valid route-map name\n", rmap_str
);
10072 return CMD_WARNING
;
10075 return bgp_show(vty
, bgp
, afi
, safi
, type
, rmap
, 0);
10078 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
10079 const char *comstr
, int exact
, afi_t afi
,
10080 safi_t safi
, bool use_json
)
10082 struct community
*com
;
10085 com
= community_str2com(comstr
);
10087 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
10088 return CMD_WARNING
;
10091 ret
= bgp_show(vty
, bgp
, afi
, safi
,
10092 (exact
? bgp_show_type_community_exact
10093 : bgp_show_type_community
),
10095 community_free(&com
);
10100 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
10101 const char *com
, int exact
, afi_t afi
,
10104 struct community_list
*list
;
10106 list
= community_list_lookup(bgp_clist
, com
, 0, COMMUNITY_LIST_MASTER
);
10107 if (list
== NULL
) {
10108 vty_out(vty
, "%% %s is not a valid community-list name\n", com
);
10109 return CMD_WARNING
;
10112 return bgp_show(vty
, bgp
, afi
, safi
,
10113 (exact
? bgp_show_type_community_list_exact
10114 : bgp_show_type_community_list
),
10118 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
10119 const char *prefix
, afi_t afi
, safi_t safi
,
10120 enum bgp_show_type type
)
10127 ret
= str2prefix(prefix
, p
);
10129 vty_out(vty
, "%% Malformed Prefix\n");
10130 return CMD_WARNING
;
10133 ret
= bgp_show(vty
, bgp
, afi
, safi
, type
, p
, 0);
10138 static struct peer
*peer_lookup_in_view(struct vty
*vty
, struct bgp
*bgp
,
10139 const char *ip_str
, bool use_json
)
10143 union sockunion su
;
10145 /* Get peer sockunion. */
10146 ret
= str2sockunion(ip_str
, &su
);
10148 peer
= peer_lookup_by_conf_if(bgp
, ip_str
);
10150 peer
= peer_lookup_by_hostname(bgp
, ip_str
);
10154 json_object
*json_no
= NULL
;
10155 json_no
= json_object_new_object();
10156 json_object_string_add(
10158 "malformedAddressOrName",
10160 vty_out(vty
, "%s\n",
10161 json_object_to_json_string_ext(
10163 JSON_C_TO_STRING_PRETTY
));
10164 json_object_free(json_no
);
10167 "%% Malformed address or name: %s\n",
10175 /* Peer structure lookup. */
10176 peer
= peer_lookup(bgp
, &su
);
10179 json_object
*json_no
= NULL
;
10180 json_no
= json_object_new_object();
10181 json_object_string_add(json_no
, "warning",
10182 "No such neighbor in this view/vrf");
10183 vty_out(vty
, "%s\n",
10184 json_object_to_json_string_ext(
10185 json_no
, JSON_C_TO_STRING_PRETTY
));
10186 json_object_free(json_no
);
10188 vty_out(vty
, "No such neighbor in this view/vrf\n");
10196 BGP_STATS_MAXBITLEN
= 0,
10198 BGP_STATS_PREFIXES
,
10200 BGP_STATS_UNAGGREGATEABLE
,
10201 BGP_STATS_MAX_AGGREGATEABLE
,
10202 BGP_STATS_AGGREGATES
,
10204 BGP_STATS_ASPATH_COUNT
,
10205 BGP_STATS_ASPATH_MAXHOPS
,
10206 BGP_STATS_ASPATH_TOTHOPS
,
10207 BGP_STATS_ASPATH_MAXSIZE
,
10208 BGP_STATS_ASPATH_TOTSIZE
,
10209 BGP_STATS_ASN_HIGHEST
,
10213 static const char *table_stats_strs
[] = {
10214 [BGP_STATS_PREFIXES
] = "Total Prefixes",
10215 [BGP_STATS_TOTPLEN
] = "Average prefix length",
10216 [BGP_STATS_RIB
] = "Total Advertisements",
10217 [BGP_STATS_UNAGGREGATEABLE
] = "Unaggregateable prefixes",
10218 [BGP_STATS_MAX_AGGREGATEABLE
] =
10219 "Maximum aggregateable prefixes",
10220 [BGP_STATS_AGGREGATES
] = "BGP Aggregate advertisements",
10221 [BGP_STATS_SPACE
] = "Address space advertised",
10222 [BGP_STATS_ASPATH_COUNT
] = "Advertisements with paths",
10223 [BGP_STATS_ASPATH_MAXHOPS
] = "Longest AS-Path (hops)",
10224 [BGP_STATS_ASPATH_MAXSIZE
] = "Largest AS-Path (bytes)",
10225 [BGP_STATS_ASPATH_TOTHOPS
] = "Average AS-Path length (hops)",
10226 [BGP_STATS_ASPATH_TOTSIZE
] = "Average AS-Path size (bytes)",
10227 [BGP_STATS_ASN_HIGHEST
] = "Highest public ASN",
10228 [BGP_STATS_MAX
] = NULL
,
10231 struct bgp_table_stats
{
10232 struct bgp_table
*table
;
10233 unsigned long long counts
[BGP_STATS_MAX
];
10234 double total_space
;
10238 #define TALLY_SIGFIG 100000
10239 static unsigned long
10240 ravg_tally (unsigned long count
, unsigned long oldavg
, unsigned long newval
)
10242 unsigned long newtot
= (count
-1) * oldavg
+ (newval
* TALLY_SIGFIG
);
10243 unsigned long res
= (newtot
* TALLY_SIGFIG
) / count
;
10244 unsigned long ret
= newtot
/ count
;
10246 if ((res
% TALLY_SIGFIG
) > (TALLY_SIGFIG
/2))
10253 static void bgp_table_stats_rn(struct bgp_node
*rn
, struct bgp_node
*top
,
10254 struct bgp_table_stats
*ts
, unsigned int space
)
10256 struct bgp_node
*prn
= bgp_node_parent_nolock(rn
);
10257 struct bgp_path_info
*pi
;
10262 if (!bgp_node_has_bgp_path_info_data(rn
))
10265 ts
->counts
[BGP_STATS_PREFIXES
]++;
10266 ts
->counts
[BGP_STATS_TOTPLEN
] += rn
->p
.prefixlen
;
10269 ts
->counts
[BGP_STATS_AVGPLEN
]
10270 = ravg_tally (ts
->counts
[BGP_STATS_PREFIXES
],
10271 ts
->counts
[BGP_STATS_AVGPLEN
],
10275 /* check if the prefix is included by any other announcements */
10276 while (prn
&& !bgp_node_has_bgp_path_info_data(prn
))
10277 prn
= bgp_node_parent_nolock(prn
);
10279 if (prn
== NULL
|| prn
== top
) {
10280 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
10281 /* announced address space */
10283 ts
->total_space
+= pow(2.0, space
- rn
->p
.prefixlen
);
10284 } else if (bgp_node_has_bgp_path_info_data(prn
))
10285 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
10288 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
10289 ts
->counts
[BGP_STATS_RIB
]++;
10292 && (CHECK_FLAG(pi
->attr
->flag
,
10293 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))))
10294 ts
->counts
[BGP_STATS_AGGREGATES
]++;
10296 /* as-path stats */
10297 if (pi
->attr
&& pi
->attr
->aspath
) {
10298 unsigned int hops
= aspath_count_hops(pi
->attr
->aspath
);
10299 unsigned int size
= aspath_size(pi
->attr
->aspath
);
10300 as_t highest
= aspath_highest(pi
->attr
->aspath
);
10302 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
10304 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
10305 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] = hops
;
10307 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
10308 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] = size
;
10310 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
10311 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
10313 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
]
10314 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
10315 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
],
10317 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
]
10318 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
10319 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
],
10322 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
10323 ts
->counts
[BGP_STATS_ASN_HIGHEST
] = highest
;
10328 static int bgp_table_stats_walker(struct thread
*t
)
10330 struct bgp_node
*rn
, *nrn
;
10331 struct bgp_node
*top
;
10332 struct bgp_table_stats
*ts
= THREAD_ARG(t
);
10333 unsigned int space
= 0;
10335 if (!(top
= bgp_table_top(ts
->table
)))
10338 switch (ts
->table
->afi
) {
10340 space
= IPV4_MAX_BITLEN
;
10343 space
= IPV6_MAX_BITLEN
;
10349 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
10351 for (rn
= top
; rn
; rn
= bgp_route_next(rn
)) {
10352 if (ts
->table
->safi
== SAFI_MPLS_VPN
) {
10353 struct bgp_table
*table
;
10355 table
= bgp_node_get_bgp_table_info(rn
);
10359 top
= bgp_table_top(table
);
10360 for (nrn
= bgp_table_top(table
); nrn
;
10361 nrn
= bgp_route_next(nrn
))
10362 bgp_table_stats_rn(nrn
, top
, ts
, space
);
10364 bgp_table_stats_rn(rn
, top
, ts
, space
);
10371 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
10374 struct bgp_table_stats ts
;
10377 if (!bgp
->rib
[afi
][safi
]) {
10378 vty_out(vty
, "%% No RIB exist's for the AFI(%d)/SAFI(%d)\n",
10380 return CMD_WARNING
;
10383 vty_out(vty
, "BGP %s RIB statistics\n", afi_safi_print(afi
, safi
));
10385 /* labeled-unicast routes live in the unicast table */
10386 if (safi
== SAFI_LABELED_UNICAST
)
10387 safi
= SAFI_UNICAST
;
10389 memset(&ts
, 0, sizeof(ts
));
10390 ts
.table
= bgp
->rib
[afi
][safi
];
10391 thread_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
10393 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
10394 if (!table_stats_strs
[i
])
10399 case BGP_STATS_ASPATH_AVGHOPS
:
10400 case BGP_STATS_ASPATH_AVGSIZE
:
10401 case BGP_STATS_AVGPLEN
:
10402 vty_out (vty
, "%-30s: ", table_stats_strs
[i
]);
10403 vty_out (vty
, "%12.2f",
10404 (float)ts
.counts
[i
] / (float)TALLY_SIGFIG
);
10407 case BGP_STATS_ASPATH_TOTHOPS
:
10408 case BGP_STATS_ASPATH_TOTSIZE
:
10409 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10410 vty_out(vty
, "%12.2f",
10412 ? (float)ts
.counts
[i
]
10414 [BGP_STATS_ASPATH_COUNT
]
10417 case BGP_STATS_TOTPLEN
:
10418 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10419 vty_out(vty
, "%12.2f",
10421 ? (float)ts
.counts
[i
]
10423 [BGP_STATS_PREFIXES
]
10426 case BGP_STATS_SPACE
:
10427 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10428 vty_out(vty
, "%12g\n", ts
.total_space
);
10430 if (afi
== AFI_IP6
) {
10431 vty_out(vty
, "%30s: ", "/32 equivalent ");
10432 vty_out(vty
, "%12g\n",
10433 ts
.total_space
* pow(2.0, -128 + 32));
10434 vty_out(vty
, "%30s: ", "/48 equivalent ");
10435 vty_out(vty
, "%12g\n",
10436 ts
.total_space
* pow(2.0, -128 + 48));
10438 vty_out(vty
, "%30s: ", "% announced ");
10439 vty_out(vty
, "%12.2f\n",
10440 ts
.total_space
* 100. * pow(2.0, -32));
10441 vty_out(vty
, "%30s: ", "/8 equivalent ");
10442 vty_out(vty
, "%12.2f\n",
10443 ts
.total_space
* pow(2.0, -32 + 8));
10444 vty_out(vty
, "%30s: ", "/24 equivalent ");
10445 vty_out(vty
, "%12.2f\n",
10446 ts
.total_space
* pow(2.0, -32 + 24));
10450 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10451 vty_out(vty
, "%12llu", ts
.counts
[i
]);
10454 vty_out(vty
, "\n");
10456 return CMD_SUCCESS
;
10468 PCOUNT_PFCNT
, /* the figure we display to users */
10472 static const char *pcount_strs
[] = {
10473 [PCOUNT_ADJ_IN
] = "Adj-in",
10474 [PCOUNT_DAMPED
] = "Damped",
10475 [PCOUNT_REMOVED
] = "Removed",
10476 [PCOUNT_HISTORY
] = "History",
10477 [PCOUNT_STALE
] = "Stale",
10478 [PCOUNT_VALID
] = "Valid",
10479 [PCOUNT_ALL
] = "All RIB",
10480 [PCOUNT_COUNTED
] = "PfxCt counted",
10481 [PCOUNT_PFCNT
] = "Useable",
10482 [PCOUNT_MAX
] = NULL
,
10485 struct peer_pcounts
{
10486 unsigned int count
[PCOUNT_MAX
];
10487 const struct peer
*peer
;
10488 const struct bgp_table
*table
;
10491 static int bgp_peer_count_walker(struct thread
*t
)
10493 struct bgp_node
*rn
;
10494 struct peer_pcounts
*pc
= THREAD_ARG(t
);
10495 const struct peer
*peer
= pc
->peer
;
10497 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
)) {
10498 struct bgp_adj_in
*ain
;
10499 struct bgp_path_info
*pi
;
10501 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
10502 if (ain
->peer
== peer
)
10503 pc
->count
[PCOUNT_ADJ_IN
]++;
10505 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
10507 if (pi
->peer
!= peer
)
10510 pc
->count
[PCOUNT_ALL
]++;
10512 if (CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
))
10513 pc
->count
[PCOUNT_DAMPED
]++;
10514 if (CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
10515 pc
->count
[PCOUNT_HISTORY
]++;
10516 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
10517 pc
->count
[PCOUNT_REMOVED
]++;
10518 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
10519 pc
->count
[PCOUNT_STALE
]++;
10520 if (CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
10521 pc
->count
[PCOUNT_VALID
]++;
10522 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
10523 pc
->count
[PCOUNT_PFCNT
]++;
10525 if (CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
10526 pc
->count
[PCOUNT_COUNTED
]++;
10527 if (CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
10529 EC_LIB_DEVELOPMENT
,
10530 "Attempting to count but flags say it is unusable");
10532 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
10534 EC_LIB_DEVELOPMENT
,
10535 "Not counted but flags say we should");
10542 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
10543 safi_t safi
, bool use_json
)
10545 struct peer_pcounts pcounts
= {.peer
= peer
};
10547 json_object
*json
= NULL
;
10548 json_object
*json_loop
= NULL
;
10551 json
= json_object_new_object();
10552 json_loop
= json_object_new_object();
10555 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
10556 || !peer
->bgp
->rib
[afi
][safi
]) {
10558 json_object_string_add(
10560 "No such neighbor or address family");
10561 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10562 json_object_free(json
);
10564 vty_out(vty
, "%% No such neighbor or address family\n");
10566 return CMD_WARNING
;
10569 memset(&pcounts
, 0, sizeof(pcounts
));
10570 pcounts
.peer
= peer
;
10571 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
10573 /* in-place call via thread subsystem so as to record execution time
10574 * stats for the thread-walk (i.e. ensure this can't be blamed on
10575 * on just vty_read()).
10577 thread_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
10580 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
10581 json_object_string_add(json
, "multiProtocol",
10582 afi_safi_print(afi
, safi
));
10583 json_object_int_add(json
, "pfxCounter",
10584 peer
->pcount
[afi
][safi
]);
10586 for (i
= 0; i
< PCOUNT_MAX
; i
++)
10587 json_object_int_add(json_loop
, pcount_strs
[i
],
10590 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
10592 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
10593 json_object_string_add(json
, "pfxctDriftFor",
10595 json_object_string_add(
10596 json
, "recommended",
10597 "Please report this bug, with the above command output");
10599 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
10600 json
, JSON_C_TO_STRING_PRETTY
));
10601 json_object_free(json
);
10605 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
10606 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
10607 peer
->hostname
, peer
->host
,
10608 afi_safi_print(afi
, safi
));
10610 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
10611 afi_safi_print(afi
, safi
));
10614 vty_out(vty
, "PfxCt: %ld\n", peer
->pcount
[afi
][safi
]);
10615 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
10617 for (i
= 0; i
< PCOUNT_MAX
; i
++)
10618 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
10621 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
10622 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
10624 "Please report this bug, with the above command output\n");
10628 return CMD_SUCCESS
;
10631 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
10632 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
10633 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_CMD_STR
"]] "
10634 "neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
10638 BGP_INSTANCE_HELP_STR
10641 "Detailed information on TCP and BGP neighbor connections\n"
10642 "Neighbor to display information about\n"
10643 "Neighbor to display information about\n"
10644 "Neighbor on BGP configured interface\n"
10645 "Display detailed prefix count information\n"
10648 afi_t afi
= AFI_IP6
;
10649 safi_t safi
= SAFI_UNICAST
;
10652 struct bgp
*bgp
= NULL
;
10653 bool uj
= use_json(argc
, argv
);
10658 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10661 return CMD_WARNING
;
10663 argv_find(argv
, argc
, "neighbors", &idx
);
10664 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
10666 return CMD_WARNING
;
10668 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_UNICAST
, uj
);
10671 #ifdef KEEP_OLD_VPN_COMMANDS
10672 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
10673 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
10674 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
10679 "Display information about all VPNv4 NLRIs\n"
10680 "Detailed information on TCP and BGP neighbor connections\n"
10681 "Neighbor to display information about\n"
10682 "Neighbor to display information about\n"
10683 "Neighbor on BGP configured interface\n"
10684 "Display detailed prefix count information\n"
10689 bool uj
= use_json(argc
, argv
);
10691 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
10693 return CMD_WARNING
;
10695 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
10698 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
10699 show_ip_bgp_vpn_all_route_prefix_cmd
,
10700 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
10705 "Display information about all VPNv4 NLRIs\n"
10706 "Network in the BGP routing table to display\n"
10707 "Network in the BGP routing table to display\n"
10711 char *network
= NULL
;
10712 struct bgp
*bgp
= bgp_get_default();
10714 vty_out(vty
, "Can't find default instance\n");
10715 return CMD_WARNING
;
10718 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
10719 network
= argv
[idx
]->arg
;
10720 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
10721 network
= argv
[idx
]->arg
;
10723 vty_out(vty
, "Unable to figure out Network\n");
10724 return CMD_WARNING
;
10727 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
10728 BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
10730 #endif /* KEEP_OLD_VPN_COMMANDS */
10732 DEFUN (show_ip_bgp_l2vpn_evpn_all_route_prefix
,
10733 show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd
,
10734 "show [ip] bgp l2vpn evpn all <A.B.C.D|A.B.C.D/M> [json]",
10740 "Display information about all EVPN NLRIs\n"
10741 "Network in the BGP routing table to display\n"
10742 "Network in the BGP routing table to display\n"
10746 char *network
= NULL
;
10748 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
10749 network
= argv
[idx
]->arg
;
10750 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
10751 network
= argv
[idx
]->arg
;
10753 vty_out(vty
, "Unable to figure out Network\n");
10754 return CMD_WARNING
;
10756 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
, 0,
10757 BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
10760 static void show_adj_route(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
10761 safi_t safi
, enum bgp_show_adj_route_type type
,
10762 const char *rmap_name
, bool use_json
,
10765 struct bgp_table
*table
;
10766 struct bgp_adj_in
*ain
;
10767 struct bgp_adj_out
*adj
;
10768 unsigned long output_count
;
10769 unsigned long filtered_count
;
10770 struct bgp_node
*rn
;
10776 struct update_subgroup
*subgrp
;
10777 json_object
*json_scode
= NULL
;
10778 json_object
*json_ocode
= NULL
;
10779 json_object
*json_ar
= NULL
;
10780 struct peer_af
*paf
;
10781 bool route_filtered
;
10784 json_scode
= json_object_new_object();
10785 json_ocode
= json_object_new_object();
10786 json_ar
= json_object_new_object();
10788 json_object_string_add(json_scode
, "suppressed", "s");
10789 json_object_string_add(json_scode
, "damped", "d");
10790 json_object_string_add(json_scode
, "history", "h");
10791 json_object_string_add(json_scode
, "valid", "*");
10792 json_object_string_add(json_scode
, "best", ">");
10793 json_object_string_add(json_scode
, "multipath", "=");
10794 json_object_string_add(json_scode
, "internal", "i");
10795 json_object_string_add(json_scode
, "ribFailure", "r");
10796 json_object_string_add(json_scode
, "stale", "S");
10797 json_object_string_add(json_scode
, "removed", "R");
10799 json_object_string_add(json_ocode
, "igp", "i");
10800 json_object_string_add(json_ocode
, "egp", "e");
10801 json_object_string_add(json_ocode
, "incomplete", "?");
10808 json_object_string_add(json
, "alert", "no BGP");
10809 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10810 json_object_free(json
);
10812 vty_out(vty
, "%% No bgp\n");
10816 /* labeled-unicast routes live in the unicast table */
10817 if (safi
== SAFI_LABELED_UNICAST
)
10818 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
10820 table
= bgp
->rib
[afi
][safi
];
10822 output_count
= filtered_count
= 0;
10823 subgrp
= peer_subgroup(peer
, afi
, safi
);
10825 if (type
== bgp_show_adj_route_advertised
&& subgrp
10826 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
10828 json_object_int_add(json
, "bgpTableVersion",
10830 json_object_string_add(json
, "bgpLocalRouterId",
10831 inet_ntoa(bgp
->router_id
));
10832 json_object_int_add(json
, "defaultLocPrf",
10833 bgp
->default_local_pref
);
10834 json_object_int_add(json
, "localAS", bgp
->as
);
10835 json_object_object_add(json
, "bgpStatusCodes",
10837 json_object_object_add(json
, "bgpOriginCodes",
10839 json_object_string_add(
10840 json
, "bgpOriginatingDefaultNetwork",
10841 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
10843 vty_out(vty
, "BGP table version is %" PRIu64
10844 ", local router ID is %s, vrf id ",
10845 table
->version
, inet_ntoa(bgp
->router_id
));
10846 if (bgp
->vrf_id
== VRF_UNKNOWN
)
10847 vty_out(vty
, "%s", VRFID_NONE_STR
);
10849 vty_out(vty
, "%u", bgp
->vrf_id
);
10850 vty_out(vty
, "\n");
10851 vty_out(vty
, "Default local pref %u, ",
10852 bgp
->default_local_pref
);
10853 vty_out(vty
, "local AS %u\n", bgp
->as
);
10854 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
10855 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
10856 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
10858 vty_out(vty
, "Originating default network %s\n\n",
10859 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
10864 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
10865 if (type
== bgp_show_adj_route_received
10866 || type
== bgp_show_adj_route_filtered
) {
10867 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
10868 if (ain
->peer
!= peer
|| !ain
->attr
)
10873 json_object_int_add(
10874 json
, "bgpTableVersion",
10876 json_object_string_add(
10878 "bgpLocalRouterId",
10881 json_object_int_add(json
,
10883 bgp
->default_local_pref
);
10884 json_object_int_add(json
,
10885 "localAS", bgp
->as
);
10886 json_object_object_add(
10887 json
, "bgpStatusCodes",
10889 json_object_object_add(
10890 json
, "bgpOriginCodes",
10894 "BGP table version is 0, local router ID is %s, vrf id ",
10897 if (bgp
->vrf_id
== VRF_UNKNOWN
)
10903 vty_out(vty
, "\n");
10905 "Default local pref %u, ",
10906 bgp
->default_local_pref
);
10907 vty_out(vty
, "local AS %u\n",
10910 BGP_SHOW_SCODE_HEADER
);
10912 BGP_SHOW_NCODE_HEADER
);
10914 BGP_SHOW_OCODE_HEADER
);
10920 vty_out(vty
, BGP_SHOW_HEADER
);
10924 bgp_attr_dup(&attr
, ain
->attr
);
10925 route_filtered
= false;
10927 /* Filter prefix using distribute list,
10928 * filter list or prefix list
10930 if ((bgp_input_filter(peer
, &rn
->p
, &attr
, afi
,
10931 safi
)) == FILTER_DENY
)
10932 route_filtered
= true;
10934 /* Filter prefix using route-map */
10935 ret
= bgp_input_modifier(peer
, &rn
->p
, &attr
,
10936 afi
, safi
, rmap_name
);
10938 if (type
== bgp_show_adj_route_filtered
&&
10939 !route_filtered
&& ret
!= RMAP_DENY
) {
10940 bgp_attr_undup(&attr
, ain
->attr
);
10944 if (type
== bgp_show_adj_route_received
&&
10945 (route_filtered
|| ret
== RMAP_DENY
))
10948 route_vty_out_tmp(vty
, &rn
->p
, &attr
, safi
,
10949 use_json
, json_ar
);
10950 bgp_attr_undup(&attr
, ain
->attr
);
10953 } else if (type
== bgp_show_adj_route_advertised
) {
10954 RB_FOREACH (adj
, bgp_adj_out_rb
, &rn
->adj_out
)
10955 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
10956 if (paf
->peer
!= peer
|| !adj
->attr
)
10961 json_object_int_add(
10965 json_object_string_add(
10967 "bgpLocalRouterId",
10970 json_object_int_add(
10971 json
, "defaultLocPrf",
10972 bgp
->default_local_pref
10974 json_object_int_add(
10977 json_object_object_add(
10981 json_object_object_add(
10987 "BGP table version is %" PRIu64
10988 ", local router ID is %s, vrf id ",
11001 vty_out(vty
, "\n");
11003 "Default local pref %u, ",
11004 bgp
->default_local_pref
11010 BGP_SHOW_SCODE_HEADER
);
11012 BGP_SHOW_NCODE_HEADER
);
11014 BGP_SHOW_OCODE_HEADER
);
11025 bgp_attr_dup(&attr
, adj
->attr
);
11026 ret
= bgp_output_modifier(
11027 peer
, &rn
->p
, &attr
, afi
, safi
,
11030 if (ret
!= RMAP_DENY
) {
11031 route_vty_out_tmp(vty
, &rn
->p
,
11040 bgp_attr_undup(&attr
, adj
->attr
);
11046 json_object_object_add(json
, "advertisedRoutes", json_ar
);
11047 json_object_int_add(json
, "totalPrefixCounter", output_count
);
11048 json_object_int_add(json
, "filteredPrefixCounter",
11051 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
11052 json
, JSON_C_TO_STRING_PRETTY
));
11053 json_object_free(json
);
11054 } else if (output_count
> 0) {
11055 if (filtered_count
> 0)
11057 "\nTotal number of prefixes %ld (%ld filtered)\n",
11058 output_count
, filtered_count
);
11060 vty_out(vty
, "\nTotal number of prefixes %ld\n",
11065 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
11066 safi_t safi
, enum bgp_show_adj_route_type type
,
11067 const char *rmap_name
, bool use_json
)
11069 json_object
*json
= NULL
;
11072 json
= json_object_new_object();
11074 if (!peer
|| !peer
->afc
[afi
][safi
]) {
11076 json_object_string_add(
11078 "No such neighbor or address family");
11079 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
11080 json_object_free(json
);
11082 vty_out(vty
, "%% No such neighbor or address family\n");
11084 return CMD_WARNING
;
11087 if ((type
== bgp_show_adj_route_received
11088 || type
== bgp_show_adj_route_filtered
)
11089 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
11090 PEER_FLAG_SOFT_RECONFIG
)) {
11092 json_object_string_add(
11094 "Inbound soft reconfiguration not enabled");
11095 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
11096 json_object_free(json
);
11099 "%% Inbound soft reconfiguration not enabled\n");
11101 return CMD_WARNING
;
11104 show_adj_route(vty
, peer
, afi
, safi
, type
, rmap_name
, use_json
, json
);
11106 return CMD_SUCCESS
;
11109 DEFUN (show_ip_bgp_instance_neighbor_advertised_route
,
11110 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
11111 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
11112 "neighbors <A.B.C.D|X:X::X:X|WORD> <advertised-routes|received-routes|filtered-routes> [route-map WORD] [json]",
11116 BGP_INSTANCE_HELP_STR
11118 BGP_SAFI_WITH_LABEL_HELP_STR
11119 "Detailed information on TCP and BGP neighbor connections\n"
11120 "Neighbor to display information about\n"
11121 "Neighbor to display information about\n"
11122 "Neighbor on BGP configured interface\n"
11123 "Display the routes advertised to a BGP neighbor\n"
11124 "Display the received routes from neighbor\n"
11125 "Display the filtered routes received from neighbor\n"
11126 "Route-map to modify the attributes\n"
11127 "Name of the route map\n"
11130 afi_t afi
= AFI_IP6
;
11131 safi_t safi
= SAFI_UNICAST
;
11132 char *rmap_name
= NULL
;
11133 char *peerstr
= NULL
;
11134 struct bgp
*bgp
= NULL
;
11136 enum bgp_show_adj_route_type type
= bgp_show_adj_route_advertised
;
11138 bool uj
= use_json(argc
, argv
);
11143 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11146 return CMD_WARNING
;
11148 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11149 argv_find(argv
, argc
, "neighbors", &idx
);
11150 peerstr
= argv
[++idx
]->arg
;
11152 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
11154 return CMD_WARNING
;
11156 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
11157 type
= bgp_show_adj_route_advertised
;
11158 else if (argv_find(argv
, argc
, "received-routes", &idx
))
11159 type
= bgp_show_adj_route_received
;
11160 else if (argv_find(argv
, argc
, "filtered-routes", &idx
))
11161 type
= bgp_show_adj_route_filtered
;
11163 if (argv_find(argv
, argc
, "route-map", &idx
))
11164 rmap_name
= argv
[++idx
]->arg
;
11166 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
, uj
);
11169 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
11170 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
11171 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
11177 "Address Family modifier\n"
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 information received from a BGP neighbor\n"
11183 "Display the prefixlist filter\n"
11186 afi_t afi
= AFI_IP6
;
11187 safi_t safi
= SAFI_UNICAST
;
11188 char *peerstr
= NULL
;
11191 union sockunion su
;
11197 /* show [ip] bgp */
11198 if (argv_find(argv
, argc
, "ip", &idx
))
11200 /* [<ipv4|ipv6> [unicast]] */
11201 if (argv_find(argv
, argc
, "ipv4", &idx
))
11203 if (argv_find(argv
, argc
, "ipv6", &idx
))
11205 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11206 argv_find(argv
, argc
, "neighbors", &idx
);
11207 peerstr
= argv
[++idx
]->arg
;
11209 bool uj
= use_json(argc
, argv
);
11211 ret
= str2sockunion(peerstr
, &su
);
11213 peer
= peer_lookup_by_conf_if(NULL
, peerstr
);
11216 vty_out(vty
, "{}\n");
11219 "%% Malformed address or name: %s\n",
11221 return CMD_WARNING
;
11224 peer
= peer_lookup(NULL
, &su
);
11227 vty_out(vty
, "{}\n");
11229 vty_out(vty
, "No peer\n");
11230 return CMD_WARNING
;
11234 sprintf(name
, "%s.%d.%d", peer
->host
, afi
, safi
);
11235 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
11238 vty_out(vty
, "Address Family: %s\n",
11239 afi_safi_print(afi
, safi
));
11240 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
11243 vty_out(vty
, "{}\n");
11245 vty_out(vty
, "No functional output\n");
11248 return CMD_SUCCESS
;
11251 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
11252 afi_t afi
, safi_t safi
,
11253 enum bgp_show_type type
, bool use_json
)
11255 /* labeled-unicast routes live in the unicast table */
11256 if (safi
== SAFI_LABELED_UNICAST
)
11257 safi
= SAFI_UNICAST
;
11259 if (!peer
|| !peer
->afc
[afi
][safi
]) {
11261 json_object
*json_no
= NULL
;
11262 json_no
= json_object_new_object();
11263 json_object_string_add(
11264 json_no
, "warning",
11265 "No such neighbor or address family");
11266 vty_out(vty
, "%s\n",
11267 json_object_to_json_string(json_no
));
11268 json_object_free(json_no
);
11270 vty_out(vty
, "%% No such neighbor or address family\n");
11271 return CMD_WARNING
;
11274 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, use_json
);
11277 DEFUN (show_ip_bgp_flowspec_routes_detailed
,
11278 show_ip_bgp_flowspec_routes_detailed_cmd
,
11279 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" flowspec] detail [json]",
11283 BGP_INSTANCE_HELP_STR
11286 "Detailed information on flowspec entries\n"
11289 afi_t afi
= AFI_IP
;
11290 safi_t safi
= SAFI_UNICAST
;
11291 struct bgp
*bgp
= NULL
;
11293 bool uj
= use_json(argc
, argv
);
11298 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11301 return CMD_WARNING
;
11303 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_detail
, NULL
, uj
);
11306 DEFUN (show_ip_bgp_neighbor_routes
,
11307 show_ip_bgp_neighbor_routes_cmd
,
11308 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
11309 "neighbors <A.B.C.D|X:X::X:X|WORD> <flap-statistics|dampened-routes|routes> [json]",
11313 BGP_INSTANCE_HELP_STR
11315 BGP_SAFI_WITH_LABEL_HELP_STR
11316 "Detailed information on TCP and BGP neighbor connections\n"
11317 "Neighbor to display information about\n"
11318 "Neighbor to display information about\n"
11319 "Neighbor on BGP configured interface\n"
11320 "Display flap statistics of the routes learned from neighbor\n"
11321 "Display the dampened routes received from neighbor\n"
11322 "Display routes learned from neighbor\n"
11325 char *peerstr
= NULL
;
11326 struct bgp
*bgp
= NULL
;
11327 afi_t afi
= AFI_IP6
;
11328 safi_t safi
= SAFI_UNICAST
;
11330 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
11332 bool uj
= use_json(argc
, argv
);
11337 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11340 return CMD_WARNING
;
11342 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11343 argv_find(argv
, argc
, "neighbors", &idx
);
11344 peerstr
= argv
[++idx
]->arg
;
11346 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
11348 return CMD_WARNING
;
11350 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
11351 sh_type
= bgp_show_type_flap_neighbor
;
11352 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
11353 sh_type
= bgp_show_type_damp_neighbor
;
11354 else if (argv_find(argv
, argc
, "routes", &idx
))
11355 sh_type
= bgp_show_type_neighbor
;
11357 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
11360 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
11362 struct bgp_distance
{
11363 /* Distance value for the IP source prefix. */
11366 /* Name of the access-list to be matched. */
11370 DEFUN (show_bgp_afi_vpn_rd_route
,
11371 show_bgp_afi_vpn_rd_route_cmd
,
11372 "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]",
11376 "Address Family modifier\n"
11377 "Display information for a route distinguisher\n"
11378 "Route Distinguisher\n"
11379 "Network in the BGP routing table to display\n"
11380 "Network in the BGP routing table to display\n"
11384 struct prefix_rd prd
;
11385 afi_t afi
= AFI_MAX
;
11388 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
11389 vty_out(vty
, "%% Malformed Address Family\n");
11390 return CMD_WARNING
;
11393 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
11395 vty_out(vty
, "%% Malformed Route Distinguisher\n");
11396 return CMD_WARNING
;
11399 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
11400 0, BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
11403 static struct bgp_distance
*bgp_distance_new(void)
11405 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
11408 static void bgp_distance_free(struct bgp_distance
*bdistance
)
11410 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
11413 static int bgp_distance_set(struct vty
*vty
, const char *distance_str
,
11414 const char *ip_str
, const char *access_list_str
)
11421 struct bgp_node
*rn
;
11422 struct bgp_distance
*bdistance
;
11424 afi
= bgp_node_afi(vty
);
11425 safi
= bgp_node_safi(vty
);
11427 ret
= str2prefix(ip_str
, &p
);
11429 vty_out(vty
, "Malformed prefix\n");
11430 return CMD_WARNING_CONFIG_FAILED
;
11433 distance
= atoi(distance_str
);
11435 /* Get BGP distance node. */
11436 rn
= bgp_node_get(bgp_distance_table
[afi
][safi
], (struct prefix
*)&p
);
11437 bdistance
= bgp_node_get_bgp_distance_info(rn
);
11439 bgp_unlock_node(rn
);
11441 bdistance
= bgp_distance_new();
11442 bgp_node_set_bgp_distance_info(rn
, bdistance
);
11445 /* Set distance value. */
11446 bdistance
->distance
= distance
;
11448 /* Reset access-list configuration. */
11449 if (bdistance
->access_list
) {
11450 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
11451 bdistance
->access_list
= NULL
;
11453 if (access_list_str
)
11454 bdistance
->access_list
=
11455 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
11457 return CMD_SUCCESS
;
11460 static int bgp_distance_unset(struct vty
*vty
, const char *distance_str
,
11461 const char *ip_str
, const char *access_list_str
)
11468 struct bgp_node
*rn
;
11469 struct bgp_distance
*bdistance
;
11471 afi
= bgp_node_afi(vty
);
11472 safi
= bgp_node_safi(vty
);
11474 ret
= str2prefix(ip_str
, &p
);
11476 vty_out(vty
, "Malformed prefix\n");
11477 return CMD_WARNING_CONFIG_FAILED
;
11480 rn
= bgp_node_lookup(bgp_distance_table
[afi
][safi
],
11481 (struct prefix
*)&p
);
11483 vty_out(vty
, "Can't find specified prefix\n");
11484 return CMD_WARNING_CONFIG_FAILED
;
11487 bdistance
= bgp_node_get_bgp_distance_info(rn
);
11488 distance
= atoi(distance_str
);
11490 if (bdistance
->distance
!= distance
) {
11491 vty_out(vty
, "Distance does not match configured\n");
11492 return CMD_WARNING_CONFIG_FAILED
;
11495 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
11496 bgp_distance_free(bdistance
);
11498 bgp_node_set_bgp_path_info(rn
, NULL
);
11499 bgp_unlock_node(rn
);
11500 bgp_unlock_node(rn
);
11502 return CMD_SUCCESS
;
11505 /* Apply BGP information to distance method. */
11506 uint8_t bgp_distance_apply(struct prefix
*p
, struct bgp_path_info
*pinfo
,
11507 afi_t afi
, safi_t safi
, struct bgp
*bgp
)
11509 struct bgp_node
*rn
;
11512 struct bgp_distance
*bdistance
;
11513 struct access_list
*alist
;
11514 struct bgp_static
*bgp_static
;
11519 peer
= pinfo
->peer
;
11521 /* Check source address. */
11522 sockunion2hostprefix(&peer
->su
, &q
);
11523 rn
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
11525 bdistance
= bgp_node_get_bgp_distance_info(rn
);
11526 bgp_unlock_node(rn
);
11528 if (bdistance
->access_list
) {
11529 alist
= access_list_lookup(afi
, bdistance
->access_list
);
11531 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
11532 return bdistance
->distance
;
11534 return bdistance
->distance
;
11537 /* Backdoor check. */
11538 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
11540 bgp_static
= bgp_node_get_bgp_static_info(rn
);
11541 bgp_unlock_node(rn
);
11543 if (bgp_static
->backdoor
) {
11544 if (bgp
->distance_local
[afi
][safi
])
11545 return bgp
->distance_local
[afi
][safi
];
11547 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
11551 if (peer
->sort
== BGP_PEER_EBGP
) {
11552 if (bgp
->distance_ebgp
[afi
][safi
])
11553 return bgp
->distance_ebgp
[afi
][safi
];
11554 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
11556 if (bgp
->distance_ibgp
[afi
][safi
])
11557 return bgp
->distance_ibgp
[afi
][safi
];
11558 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
11562 DEFUN (bgp_distance
,
11564 "distance bgp (1-255) (1-255) (1-255)",
11565 "Define an administrative distance\n"
11567 "Distance for routes external to the AS\n"
11568 "Distance for routes internal to the AS\n"
11569 "Distance for local routes\n")
11571 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11572 int idx_number
= 2;
11573 int idx_number_2
= 3;
11574 int idx_number_3
= 4;
11578 afi
= bgp_node_afi(vty
);
11579 safi
= bgp_node_safi(vty
);
11581 bgp
->distance_ebgp
[afi
][safi
] = atoi(argv
[idx_number
]->arg
);
11582 bgp
->distance_ibgp
[afi
][safi
] = atoi(argv
[idx_number_2
]->arg
);
11583 bgp
->distance_local
[afi
][safi
] = atoi(argv
[idx_number_3
]->arg
);
11584 return CMD_SUCCESS
;
11587 DEFUN (no_bgp_distance
,
11588 no_bgp_distance_cmd
,
11589 "no distance bgp [(1-255) (1-255) (1-255)]",
11591 "Define an administrative distance\n"
11593 "Distance for routes external to the AS\n"
11594 "Distance for routes internal to the AS\n"
11595 "Distance for local routes\n")
11597 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11601 afi
= bgp_node_afi(vty
);
11602 safi
= bgp_node_safi(vty
);
11604 bgp
->distance_ebgp
[afi
][safi
] = 0;
11605 bgp
->distance_ibgp
[afi
][safi
] = 0;
11606 bgp
->distance_local
[afi
][safi
] = 0;
11607 return CMD_SUCCESS
;
11611 DEFUN (bgp_distance_source
,
11612 bgp_distance_source_cmd
,
11613 "distance (1-255) A.B.C.D/M",
11614 "Define an administrative distance\n"
11615 "Administrative distance\n"
11616 "IP source prefix\n")
11618 int idx_number
= 1;
11619 int idx_ipv4_prefixlen
= 2;
11620 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
11621 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
11622 return CMD_SUCCESS
;
11625 DEFUN (no_bgp_distance_source
,
11626 no_bgp_distance_source_cmd
,
11627 "no distance (1-255) A.B.C.D/M",
11629 "Define an administrative distance\n"
11630 "Administrative distance\n"
11631 "IP source prefix\n")
11633 int idx_number
= 2;
11634 int idx_ipv4_prefixlen
= 3;
11635 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
11636 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
11637 return CMD_SUCCESS
;
11640 DEFUN (bgp_distance_source_access_list
,
11641 bgp_distance_source_access_list_cmd
,
11642 "distance (1-255) A.B.C.D/M WORD",
11643 "Define an administrative distance\n"
11644 "Administrative distance\n"
11645 "IP source prefix\n"
11646 "Access list name\n")
11648 int idx_number
= 1;
11649 int idx_ipv4_prefixlen
= 2;
11651 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
11652 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
11653 return CMD_SUCCESS
;
11656 DEFUN (no_bgp_distance_source_access_list
,
11657 no_bgp_distance_source_access_list_cmd
,
11658 "no distance (1-255) A.B.C.D/M WORD",
11660 "Define an administrative distance\n"
11661 "Administrative distance\n"
11662 "IP source prefix\n"
11663 "Access list name\n")
11665 int idx_number
= 2;
11666 int idx_ipv4_prefixlen
= 3;
11668 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
11669 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
11670 return CMD_SUCCESS
;
11673 DEFUN (ipv6_bgp_distance_source
,
11674 ipv6_bgp_distance_source_cmd
,
11675 "distance (1-255) X:X::X:X/M",
11676 "Define an administrative distance\n"
11677 "Administrative distance\n"
11678 "IP source prefix\n")
11680 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, NULL
);
11681 return CMD_SUCCESS
;
11684 DEFUN (no_ipv6_bgp_distance_source
,
11685 no_ipv6_bgp_distance_source_cmd
,
11686 "no distance (1-255) X:X::X:X/M",
11688 "Define an administrative distance\n"
11689 "Administrative distance\n"
11690 "IP source prefix\n")
11692 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, NULL
);
11693 return CMD_SUCCESS
;
11696 DEFUN (ipv6_bgp_distance_source_access_list
,
11697 ipv6_bgp_distance_source_access_list_cmd
,
11698 "distance (1-255) X:X::X:X/M WORD",
11699 "Define an administrative distance\n"
11700 "Administrative distance\n"
11701 "IP source prefix\n"
11702 "Access list name\n")
11704 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, argv
[3]->arg
);
11705 return CMD_SUCCESS
;
11708 DEFUN (no_ipv6_bgp_distance_source_access_list
,
11709 no_ipv6_bgp_distance_source_access_list_cmd
,
11710 "no distance (1-255) X:X::X:X/M WORD",
11712 "Define an administrative distance\n"
11713 "Administrative distance\n"
11714 "IP source prefix\n"
11715 "Access list name\n")
11717 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, argv
[4]->arg
);
11718 return CMD_SUCCESS
;
11721 DEFUN (bgp_damp_set
,
11723 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
11724 "BGP Specific commands\n"
11725 "Enable route-flap dampening\n"
11726 "Half-life time for the penalty\n"
11727 "Value to start reusing a route\n"
11728 "Value to start suppressing a route\n"
11729 "Maximum duration to suppress a stable route\n")
11731 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11732 int idx_half_life
= 2;
11734 int idx_suppress
= 4;
11735 int idx_max_suppress
= 5;
11736 int half
= DEFAULT_HALF_LIFE
* 60;
11737 int reuse
= DEFAULT_REUSE
;
11738 int suppress
= DEFAULT_SUPPRESS
;
11739 int max
= 4 * half
;
11742 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
11743 reuse
= atoi(argv
[idx_reuse
]->arg
);
11744 suppress
= atoi(argv
[idx_suppress
]->arg
);
11745 max
= atoi(argv
[idx_max_suppress
]->arg
) * 60;
11746 } else if (argc
== 3) {
11747 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
11751 if (suppress
< reuse
) {
11753 "Suppress value cannot be less than reuse value \n");
11757 return bgp_damp_enable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
), half
,
11758 reuse
, suppress
, max
);
11761 DEFUN (bgp_damp_unset
,
11762 bgp_damp_unset_cmd
,
11763 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
11765 "BGP Specific commands\n"
11766 "Enable route-flap dampening\n"
11767 "Half-life time for the penalty\n"
11768 "Value to start reusing a route\n"
11769 "Value to start suppressing a route\n"
11770 "Maximum duration to suppress a stable route\n")
11772 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11773 return bgp_damp_disable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
));
11776 /* Display specified route of BGP table. */
11777 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
11778 const char *ip_str
, afi_t afi
, safi_t safi
,
11779 struct prefix_rd
*prd
, int prefix_check
)
11782 struct prefix match
;
11783 struct bgp_node
*rn
;
11784 struct bgp_node
*rm
;
11785 struct bgp_path_info
*pi
;
11786 struct bgp_path_info
*pi_temp
;
11788 struct bgp_table
*table
;
11790 /* BGP structure lookup. */
11792 bgp
= bgp_lookup_by_name(view_name
);
11794 vty_out(vty
, "%% Can't find BGP instance %s\n",
11796 return CMD_WARNING
;
11799 bgp
= bgp_get_default();
11801 vty_out(vty
, "%% No BGP process is configured\n");
11802 return CMD_WARNING
;
11806 /* Check IP address argument. */
11807 ret
= str2prefix(ip_str
, &match
);
11809 vty_out(vty
, "%% address is malformed\n");
11810 return CMD_WARNING
;
11813 match
.family
= afi2family(afi
);
11815 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
11816 || (safi
== SAFI_EVPN
)) {
11817 for (rn
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); rn
;
11818 rn
= bgp_route_next(rn
)) {
11819 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
11821 table
= bgp_node_get_bgp_table_info(rn
);
11824 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
11828 || rm
->p
.prefixlen
== match
.prefixlen
) {
11829 pi
= bgp_node_get_bgp_path_info(rm
);
11831 if (pi
->extra
&& pi
->extra
->damp_info
) {
11832 pi_temp
= pi
->next
;
11833 bgp_damp_info_free(
11834 pi
->extra
->damp_info
,
11842 bgp_unlock_node(rm
);
11845 if ((rn
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
))
11848 || rn
->p
.prefixlen
== match
.prefixlen
) {
11849 pi
= bgp_node_get_bgp_path_info(rn
);
11851 if (pi
->extra
&& pi
->extra
->damp_info
) {
11852 pi_temp
= pi
->next
;
11853 bgp_damp_info_free(
11854 pi
->extra
->damp_info
,
11862 bgp_unlock_node(rn
);
11866 return CMD_SUCCESS
;
11869 DEFUN (clear_ip_bgp_dampening
,
11870 clear_ip_bgp_dampening_cmd
,
11871 "clear ip bgp dampening",
11875 "Clear route flap dampening information\n")
11877 bgp_damp_info_clean();
11878 return CMD_SUCCESS
;
11881 DEFUN (clear_ip_bgp_dampening_prefix
,
11882 clear_ip_bgp_dampening_prefix_cmd
,
11883 "clear ip bgp dampening A.B.C.D/M",
11887 "Clear route flap dampening information\n"
11890 int idx_ipv4_prefixlen
= 4;
11891 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
11892 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
11895 DEFUN (clear_ip_bgp_dampening_address
,
11896 clear_ip_bgp_dampening_address_cmd
,
11897 "clear ip bgp dampening A.B.C.D",
11901 "Clear route flap dampening information\n"
11902 "Network to clear damping information\n")
11905 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
11906 SAFI_UNICAST
, NULL
, 0);
11909 DEFUN (clear_ip_bgp_dampening_address_mask
,
11910 clear_ip_bgp_dampening_address_mask_cmd
,
11911 "clear ip bgp dampening A.B.C.D A.B.C.D",
11915 "Clear route flap dampening information\n"
11916 "Network to clear damping information\n"
11920 int idx_ipv4_2
= 5;
11922 char prefix_str
[BUFSIZ
];
11924 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
11927 vty_out(vty
, "%% Inconsistent address and mask\n");
11928 return CMD_WARNING
;
11931 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
11935 static void show_bgp_peerhash_entry(struct hash_bucket
*bucket
, void *arg
)
11937 struct vty
*vty
= arg
;
11938 struct peer
*peer
= bucket
->data
;
11939 char buf
[SU_ADDRSTRLEN
];
11941 vty_out(vty
, "\tPeer: %s %s\n", peer
->host
,
11942 sockunion2str(&peer
->su
, buf
, sizeof(buf
)));
11945 DEFUN (show_bgp_peerhash
,
11946 show_bgp_peerhash_cmd
,
11947 "show bgp peerhash",
11950 "Display information about the BGP peerhash\n")
11952 struct list
*instances
= bm
->bgp
;
11953 struct listnode
*node
;
11956 for (ALL_LIST_ELEMENTS_RO(instances
, node
, bgp
)) {
11957 vty_out(vty
, "BGP: %s\n", bgp
->name
);
11958 hash_iterate(bgp
->peerhash
, show_bgp_peerhash_entry
,
11962 return CMD_SUCCESS
;
11965 /* also used for encap safi */
11966 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
11967 afi_t afi
, safi_t safi
)
11969 struct bgp_node
*prn
;
11970 struct bgp_node
*rn
;
11971 struct bgp_table
*table
;
11973 struct prefix_rd
*prd
;
11974 struct bgp_static
*bgp_static
;
11975 mpls_label_t label
;
11976 char buf
[SU_ADDRSTRLEN
];
11977 char rdbuf
[RD_ADDRSTRLEN
];
11979 /* Network configuration. */
11980 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
11981 prn
= bgp_route_next(prn
)) {
11982 table
= bgp_node_get_bgp_table_info(prn
);
11986 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
11987 bgp_static
= bgp_node_get_bgp_static_info(rn
);
11988 if (bgp_static
== NULL
)
11992 prd
= (struct prefix_rd
*)&prn
->p
;
11994 /* "network" configuration display. */
11995 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
11996 label
= decode_label(&bgp_static
->label
);
11998 vty_out(vty
, " network %s/%d rd %s",
11999 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
12001 p
->prefixlen
, rdbuf
);
12002 if (safi
== SAFI_MPLS_VPN
)
12003 vty_out(vty
, " label %u", label
);
12005 if (bgp_static
->rmap
.name
)
12006 vty_out(vty
, " route-map %s",
12007 bgp_static
->rmap
.name
);
12009 if (bgp_static
->backdoor
)
12010 vty_out(vty
, " backdoor");
12012 vty_out(vty
, "\n");
12017 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
12018 afi_t afi
, safi_t safi
)
12020 struct bgp_node
*prn
;
12021 struct bgp_node
*rn
;
12022 struct bgp_table
*table
;
12024 struct prefix_rd
*prd
;
12025 struct bgp_static
*bgp_static
;
12026 char buf
[PREFIX_STRLEN
* 2];
12027 char buf2
[SU_ADDRSTRLEN
];
12028 char rdbuf
[RD_ADDRSTRLEN
];
12030 /* Network configuration. */
12031 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
12032 prn
= bgp_route_next(prn
)) {
12033 table
= bgp_node_get_bgp_table_info(prn
);
12037 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
12038 bgp_static
= bgp_node_get_bgp_static_info(rn
);
12039 if (bgp_static
== NULL
)
12042 char *macrouter
= NULL
;
12045 if (bgp_static
->router_mac
)
12046 macrouter
= prefix_mac2str(
12047 bgp_static
->router_mac
, NULL
, 0);
12048 if (bgp_static
->eth_s_id
)
12049 esi
= esi2str(bgp_static
->eth_s_id
);
12051 prd
= (struct prefix_rd
*)&prn
->p
;
12053 /* "network" configuration display. */
12054 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
12055 if (p
->u
.prefix_evpn
.route_type
== 5) {
12056 char local_buf
[PREFIX_STRLEN
];
12057 uint8_t family
= is_evpn_prefix_ipaddr_v4((
12058 struct prefix_evpn
*)p
)
12062 &p
->u
.prefix_evpn
.prefix_addr
.ip
.ip
.addr
,
12063 local_buf
, PREFIX_STRLEN
);
12064 sprintf(buf
, "%s/%u", local_buf
,
12065 p
->u
.prefix_evpn
.prefix_addr
.ip_prefix_length
);
12067 prefix2str(p
, buf
, sizeof(buf
));
12070 if (bgp_static
->gatewayIp
.family
== AF_INET
12071 || bgp_static
->gatewayIp
.family
== AF_INET6
)
12072 inet_ntop(bgp_static
->gatewayIp
.family
,
12073 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
12076 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
12078 p
->u
.prefix_evpn
.prefix_addr
.eth_tag
,
12079 decode_label(&bgp_static
->label
), esi
, buf2
,
12082 XFREE(MTYPE_TMP
, macrouter
);
12083 XFREE(MTYPE_TMP
, esi
);
12088 /* Configuration of static route announcement and aggregate
12090 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12093 struct bgp_node
*rn
;
12095 struct bgp_static
*bgp_static
;
12096 struct bgp_aggregate
*bgp_aggregate
;
12097 char buf
[SU_ADDRSTRLEN
];
12099 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
12100 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
12104 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
12105 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
12109 /* Network configuration. */
12110 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
12111 rn
= bgp_route_next(rn
)) {
12112 bgp_static
= bgp_node_get_bgp_static_info(rn
);
12113 if (bgp_static
== NULL
)
12118 /* "network" configuration display. */
12119 if (bgp_option_check(BGP_OPT_CONFIG_CISCO
) && afi
== AFI_IP
) {
12120 uint32_t destination
;
12121 struct in_addr netmask
;
12123 destination
= ntohl(p
->u
.prefix4
.s_addr
);
12124 masklen2ip(p
->prefixlen
, &netmask
);
12125 vty_out(vty
, " network %s",
12126 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
12129 if ((IN_CLASSC(destination
) && p
->prefixlen
== 24)
12130 || (IN_CLASSB(destination
) && p
->prefixlen
== 16)
12131 || (IN_CLASSA(destination
) && p
->prefixlen
== 8)
12132 || p
->u
.prefix4
.s_addr
== 0) {
12133 /* Natural mask is not display. */
12135 vty_out(vty
, " mask %s", inet_ntoa(netmask
));
12137 vty_out(vty
, " network %s/%d",
12138 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
12143 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
12144 vty_out(vty
, " label-index %u",
12145 bgp_static
->label_index
);
12147 if (bgp_static
->rmap
.name
)
12148 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
12150 if (bgp_static
->backdoor
)
12151 vty_out(vty
, " backdoor");
12153 vty_out(vty
, "\n");
12156 /* Aggregate-address configuration. */
12157 for (rn
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); rn
;
12158 rn
= bgp_route_next(rn
)) {
12159 bgp_aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
12160 if (bgp_aggregate
== NULL
)
12165 if (bgp_option_check(BGP_OPT_CONFIG_CISCO
) && afi
== AFI_IP
) {
12166 struct in_addr netmask
;
12168 masklen2ip(p
->prefixlen
, &netmask
);
12169 vty_out(vty
, " aggregate-address %s %s",
12170 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
12172 inet_ntoa(netmask
));
12174 vty_out(vty
, " aggregate-address %s/%d",
12175 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
12180 if (bgp_aggregate
->as_set
)
12181 vty_out(vty
, " as-set");
12183 if (bgp_aggregate
->summary_only
)
12184 vty_out(vty
, " summary-only");
12186 vty_out(vty
, "\n");
12190 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12193 struct bgp_node
*rn
;
12194 struct bgp_distance
*bdistance
;
12196 /* Distance configuration. */
12197 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
12198 && bgp
->distance_local
[afi
][safi
]
12199 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
12200 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
12201 || bgp
->distance_local
[afi
][safi
]
12202 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
12203 vty_out(vty
, " distance bgp %d %d %d\n",
12204 bgp
->distance_ebgp
[afi
][safi
],
12205 bgp
->distance_ibgp
[afi
][safi
],
12206 bgp
->distance_local
[afi
][safi
]);
12209 for (rn
= bgp_table_top(bgp_distance_table
[afi
][safi
]); rn
;
12210 rn
= bgp_route_next(rn
)) {
12211 bdistance
= bgp_node_get_bgp_distance_info(rn
);
12212 if (bdistance
!= NULL
) {
12213 char buf
[PREFIX_STRLEN
];
12215 vty_out(vty
, " distance %d %s %s\n",
12216 bdistance
->distance
,
12217 prefix2str(&rn
->p
, buf
, sizeof(buf
)),
12218 bdistance
->access_list
? bdistance
->access_list
12224 /* Allocate routing table structure and install commands. */
12225 void bgp_route_init(void)
12230 /* Init BGP distance table. */
12231 FOREACH_AFI_SAFI (afi
, safi
)
12232 bgp_distance_table
[afi
][safi
] = bgp_table_init(NULL
, afi
, safi
);
12234 /* IPv4 BGP commands. */
12235 install_element(BGP_NODE
, &bgp_table_map_cmd
);
12236 install_element(BGP_NODE
, &bgp_network_cmd
);
12237 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
12239 install_element(BGP_NODE
, &aggregate_address_cmd
);
12240 install_element(BGP_NODE
, &aggregate_address_mask_cmd
);
12241 install_element(BGP_NODE
, &no_aggregate_address_cmd
);
12242 install_element(BGP_NODE
, &no_aggregate_address_mask_cmd
);
12244 /* IPv4 unicast configuration. */
12245 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
12246 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
12247 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
12249 install_element(BGP_IPV4_NODE
, &aggregate_address_cmd
);
12250 install_element(BGP_IPV4_NODE
, &aggregate_address_mask_cmd
);
12251 install_element(BGP_IPV4_NODE
, &no_aggregate_address_cmd
);
12252 install_element(BGP_IPV4_NODE
, &no_aggregate_address_mask_cmd
);
12254 /* IPv4 multicast configuration. */
12255 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
12256 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
12257 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
12258 install_element(BGP_IPV4M_NODE
, &aggregate_address_cmd
);
12259 install_element(BGP_IPV4M_NODE
, &aggregate_address_mask_cmd
);
12260 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_cmd
);
12261 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_mask_cmd
);
12263 /* IPv4 labeled-unicast configuration. */
12264 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
12265 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
12266 install_element(VIEW_NODE
, &show_ip_bgp_json_cmd
);
12267 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
12268 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
12270 install_element(VIEW_NODE
,
12271 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
12272 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
12273 install_element(VIEW_NODE
,
12274 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
12275 #ifdef KEEP_OLD_VPN_COMMANDS
12276 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
12277 #endif /* KEEP_OLD_VPN_COMMANDS */
12278 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
12279 install_element(VIEW_NODE
,
12280 &show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd
);
12282 /* BGP dampening clear commands */
12283 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
12284 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
12286 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
12287 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
12290 install_element(ENABLE_NODE
,
12291 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
12292 #ifdef KEEP_OLD_VPN_COMMANDS
12293 install_element(ENABLE_NODE
,
12294 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
12295 #endif /* KEEP_OLD_VPN_COMMANDS */
12297 /* New config IPv6 BGP commands. */
12298 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
12299 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
12300 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
12302 install_element(BGP_IPV6_NODE
, &ipv6_aggregate_address_cmd
);
12303 install_element(BGP_IPV6_NODE
, &no_ipv6_aggregate_address_cmd
);
12305 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
12307 install_element(BGP_NODE
, &bgp_distance_cmd
);
12308 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
12309 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
12310 install_element(BGP_NODE
, &no_bgp_distance_source_cmd
);
12311 install_element(BGP_NODE
, &bgp_distance_source_access_list_cmd
);
12312 install_element(BGP_NODE
, &no_bgp_distance_source_access_list_cmd
);
12313 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
12314 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
12315 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
12316 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_cmd
);
12317 install_element(BGP_IPV4_NODE
, &bgp_distance_source_access_list_cmd
);
12318 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_access_list_cmd
);
12319 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
12320 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
12321 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
12322 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_source_cmd
);
12323 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_access_list_cmd
);
12324 install_element(BGP_IPV4M_NODE
,
12325 &no_bgp_distance_source_access_list_cmd
);
12326 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
12327 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
12328 install_element(BGP_IPV6_NODE
, &ipv6_bgp_distance_source_cmd
);
12329 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_distance_source_cmd
);
12330 install_element(BGP_IPV6_NODE
,
12331 &ipv6_bgp_distance_source_access_list_cmd
);
12332 install_element(BGP_IPV6_NODE
,
12333 &no_ipv6_bgp_distance_source_access_list_cmd
);
12334 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
12335 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
12336 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_distance_source_cmd
);
12337 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_distance_source_cmd
);
12338 install_element(BGP_IPV6M_NODE
,
12339 &ipv6_bgp_distance_source_access_list_cmd
);
12340 install_element(BGP_IPV6M_NODE
,
12341 &no_ipv6_bgp_distance_source_access_list_cmd
);
12343 install_element(BGP_NODE
, &bgp_damp_set_cmd
);
12344 install_element(BGP_NODE
, &bgp_damp_unset_cmd
);
12345 install_element(BGP_IPV4_NODE
, &bgp_damp_set_cmd
);
12346 install_element(BGP_IPV4_NODE
, &bgp_damp_unset_cmd
);
12348 /* IPv4 Multicast Mode */
12349 install_element(BGP_IPV4M_NODE
, &bgp_damp_set_cmd
);
12350 install_element(BGP_IPV4M_NODE
, &bgp_damp_unset_cmd
);
12352 /* Large Communities */
12353 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
12354 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
12356 /* show bgp ipv4 flowspec detailed */
12357 install_element(VIEW_NODE
, &show_ip_bgp_flowspec_routes_detailed_cmd
);
12359 install_element(VIEW_NODE
, &show_bgp_peerhash_cmd
);
12362 void bgp_route_finish(void)
12367 FOREACH_AFI_SAFI (afi
, safi
) {
12368 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
12369 bgp_distance_table
[afi
][safi
] = NULL
;