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"
70 #include "bgpd/rfapi/rfapi_backend.h"
71 #include "bgpd/rfapi/vnc_import_bgp.h"
72 #include "bgpd/rfapi/vnc_export_bgp.h"
74 #include "bgpd/bgp_encap_types.h"
75 #include "bgpd/bgp_encap_tlv.h"
76 #include "bgpd/bgp_evpn.h"
77 #include "bgpd/bgp_evpn_vty.h"
78 #include "bgpd/bgp_flowspec.h"
79 #include "bgpd/bgp_flowspec_util.h"
80 #include "bgpd/bgp_pbr.h"
82 #ifndef VTYSH_EXTRACT_PL
83 #include "bgpd/bgp_route_clippy.c"
86 /* Extern from bgp_dump.c */
87 extern const char *bgp_origin_str
[];
88 extern const char *bgp_origin_long_str
[];
91 #define PMSI_TNLTYPE_STR_NO_INFO "No info"
92 #define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
93 static const struct message bgp_pmsi_tnltype_str
[] = {
94 {PMSI_TNLTYPE_NO_INFO
, PMSI_TNLTYPE_STR_NO_INFO
},
95 {PMSI_TNLTYPE_RSVP_TE_P2MP
, "RSVP-TE P2MP"},
96 {PMSI_TNLTYPE_MLDP_P2MP
, "mLDP P2MP"},
97 {PMSI_TNLTYPE_PIM_SSM
, "PIM-SSM"},
98 {PMSI_TNLTYPE_PIM_SM
, "PIM-SM"},
99 {PMSI_TNLTYPE_PIM_BIDIR
, "PIM-BIDIR"},
100 {PMSI_TNLTYPE_INGR_REPL
, "Ingress Replication"},
101 {PMSI_TNLTYPE_MLDP_MP2MP
, "mLDP MP2MP"},
105 #define VRFID_NONE_STR "-"
107 struct bgp_node
*bgp_afi_node_get(struct bgp_table
*table
, afi_t afi
,
108 safi_t safi
, struct prefix
*p
,
109 struct prefix_rd
*prd
)
112 struct bgp_node
*prn
= NULL
;
118 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
119 || (safi
== SAFI_EVPN
)) {
120 prn
= bgp_node_get(table
, (struct prefix
*)prd
);
122 if (prn
->info
== NULL
)
123 prn
->info
= bgp_table_init(table
->bgp
, afi
, safi
);
125 bgp_unlock_node(prn
);
129 rn
= bgp_node_get(table
, p
);
131 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
132 || (safi
== SAFI_EVPN
))
138 struct bgp_node
*bgp_afi_node_lookup(struct bgp_table
*table
, afi_t afi
,
139 safi_t safi
, struct prefix
*p
,
140 struct prefix_rd
*prd
)
143 struct bgp_node
*prn
= NULL
;
148 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
149 || (safi
== SAFI_EVPN
)) {
150 prn
= bgp_node_lookup(table
, (struct prefix
*)prd
);
154 if (prn
->info
== NULL
) {
155 bgp_unlock_node(prn
);
162 rn
= bgp_node_lookup(table
, p
);
167 /* Allocate bgp_info_extra */
168 static struct bgp_info_extra
*bgp_info_extra_new(void)
170 struct bgp_info_extra
*new;
171 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA
, sizeof(struct bgp_info_extra
));
172 new->label
[0] = MPLS_INVALID_LABEL
;
177 static void bgp_info_extra_free(struct bgp_info_extra
**extra
)
179 struct bgp_info_extra
*e
;
181 if (!extra
|| !*extra
)
186 bgp_damp_info_free(e
->damp_info
, 0);
190 struct bgp_info
*bi
= (struct bgp_info
*)e
->parent
;
193 /* FIXME: since multiple e may have the same e->parent
194 * and e->parent->net is holding a refcount for each
195 * of them, we need to do some fudging here.
197 * WARNING: if bi->net->lock drops to 0, bi may be
198 * freed as well (because bi->net was holding the
199 * last reference to bi) => write after free!
203 bi
= bgp_info_lock(bi
);
204 refcount
= bi
->net
->lock
- 1;
205 bgp_unlock_node((struct bgp_node
*)bi
->net
);
210 bgp_info_unlock(e
->parent
);
215 bgp_unlock(e
->bgp_orig
);
217 if ((*extra
)->bgp_fs_pbr
)
218 list_delete(&((*extra
)->bgp_fs_pbr
));
219 XFREE(MTYPE_BGP_ROUTE_EXTRA
, *extra
);
224 /* Get bgp_info extra information for the given bgp_info, lazy allocated
227 struct bgp_info_extra
*bgp_info_extra_get(struct bgp_info
*ri
)
230 ri
->extra
= bgp_info_extra_new();
234 /* Allocate new bgp info structure. */
235 struct bgp_info
*bgp_info_new(void)
237 return XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_info
));
240 /* Free bgp route information. */
241 static void bgp_info_free(struct bgp_info
*binfo
)
244 bgp_attr_unintern(&binfo
->attr
);
246 bgp_unlink_nexthop(binfo
);
247 bgp_info_extra_free(&binfo
->extra
);
248 bgp_info_mpath_free(&binfo
->mpath
);
250 peer_unlock(binfo
->peer
); /* bgp_info peer reference */
252 XFREE(MTYPE_BGP_ROUTE
, binfo
);
255 struct bgp_info
*bgp_info_lock(struct bgp_info
*binfo
)
261 struct bgp_info
*bgp_info_unlock(struct bgp_info
*binfo
)
263 assert(binfo
&& binfo
->lock
> 0);
266 if (binfo
->lock
== 0) {
268 zlog_debug ("%s: unlocked and freeing", __func__
);
269 zlog_backtrace (LOG_DEBUG
);
271 bgp_info_free(binfo
);
276 if (binfo
->lock
== 1)
278 zlog_debug ("%s: unlocked to 1", __func__
);
279 zlog_backtrace (LOG_DEBUG
);
286 void bgp_info_add(struct bgp_node
*rn
, struct bgp_info
*ri
)
288 struct bgp_info
*top
;
300 peer_lock(ri
->peer
); /* bgp_info peer reference */
303 /* Do the actual removal of info from RIB, for use by bgp_process
304 completion callback *only* */
305 void bgp_info_reap(struct bgp_node
*rn
, struct bgp_info
*ri
)
308 ri
->next
->prev
= ri
->prev
;
310 ri
->prev
->next
= ri
->next
;
314 bgp_info_mpath_dequeue(ri
);
319 void bgp_info_delete(struct bgp_node
*rn
, struct bgp_info
*ri
)
321 bgp_info_set_flag(rn
, ri
, BGP_INFO_REMOVED
);
322 /* set of previous already took care of pcount */
323 UNSET_FLAG(ri
->flags
, BGP_INFO_VALID
);
326 /* undo the effects of a previous call to bgp_info_delete; typically
327 called when a route is deleted and then quickly re-added before the
328 deletion has been processed */
329 void bgp_info_restore(struct bgp_node
*rn
, struct bgp_info
*ri
)
331 bgp_info_unset_flag(rn
, ri
, BGP_INFO_REMOVED
);
332 /* unset of previous already took care of pcount */
333 SET_FLAG(ri
->flags
, BGP_INFO_VALID
);
336 /* Adjust pcount as required */
337 static void bgp_pcount_adjust(struct bgp_node
*rn
, struct bgp_info
*ri
)
339 struct bgp_table
*table
;
341 assert(rn
&& bgp_node_table(rn
));
342 assert(ri
&& ri
->peer
&& ri
->peer
->bgp
);
344 table
= bgp_node_table(rn
);
346 if (ri
->peer
== ri
->peer
->bgp
->peer_self
)
349 if (!BGP_INFO_COUNTABLE(ri
)
350 && CHECK_FLAG(ri
->flags
, BGP_INFO_COUNTED
)) {
352 UNSET_FLAG(ri
->flags
, BGP_INFO_COUNTED
);
354 /* slight hack, but more robust against errors. */
355 if (ri
->peer
->pcount
[table
->afi
][table
->safi
])
356 ri
->peer
->pcount
[table
->afi
][table
->safi
]--;
358 flog_err(EC_LIB_DEVELOPMENT
,
359 "Asked to decrement 0 prefix count for peer");
360 } else if (BGP_INFO_COUNTABLE(ri
)
361 && !CHECK_FLAG(ri
->flags
, BGP_INFO_COUNTED
)) {
362 SET_FLAG(ri
->flags
, BGP_INFO_COUNTED
);
363 ri
->peer
->pcount
[table
->afi
][table
->safi
]++;
367 static int bgp_label_index_differs(struct bgp_info
*ri1
, struct bgp_info
*ri2
)
369 return (!(ri1
->attr
->label_index
== ri2
->attr
->label_index
));
372 /* Set/unset bgp_info flags, adjusting any other state as needed.
373 * This is here primarily to keep prefix-count in check.
375 void bgp_info_set_flag(struct bgp_node
*rn
, struct bgp_info
*ri
, uint32_t flag
)
377 SET_FLAG(ri
->flags
, flag
);
379 /* early bath if we know it's not a flag that changes countability state
381 if (!CHECK_FLAG(flag
,
382 BGP_INFO_VALID
| BGP_INFO_HISTORY
| BGP_INFO_REMOVED
))
385 bgp_pcount_adjust(rn
, ri
);
388 void bgp_info_unset_flag(struct bgp_node
*rn
, struct bgp_info
*ri
,
391 UNSET_FLAG(ri
->flags
, flag
);
393 /* early bath if we know it's not a flag that changes countability state
395 if (!CHECK_FLAG(flag
,
396 BGP_INFO_VALID
| BGP_INFO_HISTORY
| BGP_INFO_REMOVED
))
399 bgp_pcount_adjust(rn
, ri
);
402 /* Get MED value. If MED value is missing and "bgp bestpath
403 missing-as-worst" is specified, treat it as the worst value. */
404 static uint32_t bgp_med_value(struct attr
*attr
, struct bgp
*bgp
)
406 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
409 if (bgp_flag_check(bgp
, BGP_FLAG_MED_MISSING_AS_WORST
))
416 void bgp_info_path_with_addpath_rx_str(struct bgp_info
*ri
, char *buf
)
418 if (ri
->addpath_rx_id
)
419 sprintf(buf
, "path %s (addpath rxid %d)", ri
->peer
->host
,
422 sprintf(buf
, "path %s", ri
->peer
->host
);
425 /* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
427 static int bgp_info_cmp(struct bgp
*bgp
, struct bgp_info
*new,
428 struct bgp_info
*exist
, int *paths_eq
,
429 struct bgp_maxpaths_cfg
*mpath_cfg
, int debug
,
430 char *pfx_buf
, afi_t afi
, safi_t safi
)
432 struct attr
*newattr
, *existattr
;
433 bgp_peer_sort_t new_sort
;
434 bgp_peer_sort_t exist_sort
;
440 uint32_t exist_weight
;
441 uint32_t newm
, existm
;
442 struct in_addr new_id
;
443 struct in_addr exist_id
;
446 int internal_as_route
;
449 char new_buf
[PATH_ADDPATH_STR_BUFFER
];
450 char exist_buf
[PATH_ADDPATH_STR_BUFFER
];
452 uint32_t exist_mm_seq
;
459 zlog_debug("%s: new is NULL", pfx_buf
);
464 bgp_info_path_with_addpath_rx_str(new, new_buf
);
468 zlog_debug("%s: %s is the initial bestpath", pfx_buf
,
474 bgp_info_path_with_addpath_rx_str(exist
, exist_buf
);
475 zlog_debug("%s: Comparing %s flags 0x%x with %s flags 0x%x",
476 pfx_buf
, new_buf
, new->flags
, exist_buf
,
481 existattr
= exist
->attr
;
483 /* For EVPN routes, we cannot just go by local vs remote, we have to
484 * look at the MAC mobility sequence number, if present.
486 if (safi
== SAFI_EVPN
) {
487 /* This is an error condition described in RFC 7432 Section
489 * states that in this scenario "the PE MUST alert the operator"
491 * does not state what other action to take. In order to provide
493 * consistency in this scenario we are going to prefer the path
497 if (newattr
->sticky
!= existattr
->sticky
) {
499 prefix2str(&new->net
->p
, pfx_buf
,
501 * PREFIX2STR_BUFFER
);
502 bgp_info_path_with_addpath_rx_str(new, new_buf
);
503 bgp_info_path_with_addpath_rx_str(exist
,
507 if (newattr
->sticky
&& !existattr
->sticky
) {
510 "%s: %s wins over %s due to sticky MAC flag",
511 pfx_buf
, new_buf
, exist_buf
);
515 if (!newattr
->sticky
&& existattr
->sticky
) {
518 "%s: %s loses to %s due to sticky MAC flag",
519 pfx_buf
, new_buf
, exist_buf
);
524 new_mm_seq
= mac_mobility_seqnum(newattr
);
525 exist_mm_seq
= mac_mobility_seqnum(existattr
);
527 if (new_mm_seq
> exist_mm_seq
) {
530 "%s: %s wins over %s due to MM seq %u > %u",
531 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
536 if (new_mm_seq
< exist_mm_seq
) {
539 "%s: %s loses to %s due to MM seq %u < %u",
540 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
546 /* 1. Weight check. */
547 new_weight
= newattr
->weight
;
548 exist_weight
= existattr
->weight
;
550 if (new_weight
> exist_weight
) {
552 zlog_debug("%s: %s wins over %s due to weight %d > %d",
553 pfx_buf
, new_buf
, exist_buf
, new_weight
,
558 if (new_weight
< exist_weight
) {
560 zlog_debug("%s: %s loses to %s due to weight %d < %d",
561 pfx_buf
, new_buf
, exist_buf
, new_weight
,
566 /* 2. Local preference check. */
567 new_pref
= exist_pref
= bgp
->default_local_pref
;
569 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
570 new_pref
= newattr
->local_pref
;
571 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
572 exist_pref
= existattr
->local_pref
;
574 if (new_pref
> exist_pref
) {
577 "%s: %s wins over %s due to localpref %d > %d",
578 pfx_buf
, new_buf
, exist_buf
, new_pref
,
583 if (new_pref
< exist_pref
) {
586 "%s: %s loses to %s due to localpref %d < %d",
587 pfx_buf
, new_buf
, exist_buf
, new_pref
,
592 /* 3. Local route check. We prefer:
594 * - BGP_ROUTE_AGGREGATE
595 * - BGP_ROUTE_REDISTRIBUTE
597 if (!(new->sub_type
== BGP_ROUTE_NORMAL
||
598 new->sub_type
== BGP_ROUTE_IMPORTED
)) {
601 "%s: %s wins over %s due to preferred BGP_ROUTE type",
602 pfx_buf
, new_buf
, exist_buf
);
606 if (!(exist
->sub_type
== BGP_ROUTE_NORMAL
||
607 exist
->sub_type
== BGP_ROUTE_IMPORTED
)) {
610 "%s: %s loses to %s due to preferred BGP_ROUTE type",
611 pfx_buf
, new_buf
, exist_buf
);
615 /* 4. AS path length check. */
616 if (!bgp_flag_check(bgp
, BGP_FLAG_ASPATH_IGNORE
)) {
617 int exist_hops
= aspath_count_hops(existattr
->aspath
);
618 int exist_confeds
= aspath_count_confeds(existattr
->aspath
);
620 if (bgp_flag_check(bgp
, BGP_FLAG_ASPATH_CONFED
)) {
623 aspath_hops
= aspath_count_hops(newattr
->aspath
);
624 aspath_hops
+= aspath_count_confeds(newattr
->aspath
);
626 if (aspath_hops
< (exist_hops
+ exist_confeds
)) {
629 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
630 pfx_buf
, new_buf
, exist_buf
,
632 (exist_hops
+ exist_confeds
));
636 if (aspath_hops
> (exist_hops
+ exist_confeds
)) {
639 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
640 pfx_buf
, new_buf
, exist_buf
,
642 (exist_hops
+ exist_confeds
));
646 int newhops
= aspath_count_hops(newattr
->aspath
);
648 if (newhops
< exist_hops
) {
651 "%s: %s wins over %s due to aspath hopcount %d < %d",
652 pfx_buf
, new_buf
, exist_buf
,
653 newhops
, exist_hops
);
657 if (newhops
> exist_hops
) {
660 "%s: %s loses to %s due to aspath hopcount %d > %d",
661 pfx_buf
, new_buf
, exist_buf
,
662 newhops
, exist_hops
);
668 /* 5. Origin check. */
669 if (newattr
->origin
< existattr
->origin
) {
671 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
672 pfx_buf
, new_buf
, exist_buf
,
673 bgp_origin_long_str
[newattr
->origin
],
674 bgp_origin_long_str
[existattr
->origin
]);
678 if (newattr
->origin
> existattr
->origin
) {
680 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
681 pfx_buf
, new_buf
, exist_buf
,
682 bgp_origin_long_str
[newattr
->origin
],
683 bgp_origin_long_str
[existattr
->origin
]);
688 internal_as_route
= (aspath_count_hops(newattr
->aspath
) == 0
689 && aspath_count_hops(existattr
->aspath
) == 0);
690 confed_as_route
= (aspath_count_confeds(newattr
->aspath
) > 0
691 && aspath_count_confeds(existattr
->aspath
) > 0
692 && aspath_count_hops(newattr
->aspath
) == 0
693 && aspath_count_hops(existattr
->aspath
) == 0);
695 if (bgp_flag_check(bgp
, BGP_FLAG_ALWAYS_COMPARE_MED
)
696 || (bgp_flag_check(bgp
, BGP_FLAG_MED_CONFED
) && confed_as_route
)
697 || aspath_cmp_left(newattr
->aspath
, existattr
->aspath
)
698 || aspath_cmp_left_confed(newattr
->aspath
, existattr
->aspath
)
699 || internal_as_route
) {
700 new_med
= bgp_med_value(new->attr
, bgp
);
701 exist_med
= bgp_med_value(exist
->attr
, bgp
);
703 if (new_med
< exist_med
) {
706 "%s: %s wins over %s due to MED %d < %d",
707 pfx_buf
, new_buf
, exist_buf
, new_med
,
712 if (new_med
> exist_med
) {
715 "%s: %s loses to %s due to MED %d > %d",
716 pfx_buf
, new_buf
, exist_buf
, new_med
,
722 /* 7. Peer type check. */
723 new_sort
= new->peer
->sort
;
724 exist_sort
= exist
->peer
->sort
;
726 if (new_sort
== BGP_PEER_EBGP
727 && (exist_sort
== BGP_PEER_IBGP
|| exist_sort
== BGP_PEER_CONFED
)) {
730 "%s: %s wins over %s due to eBGP peer > iBGP peer",
731 pfx_buf
, new_buf
, exist_buf
);
735 if (exist_sort
== BGP_PEER_EBGP
736 && (new_sort
== BGP_PEER_IBGP
|| new_sort
== BGP_PEER_CONFED
)) {
739 "%s: %s loses to %s due to iBGP peer < eBGP peer",
740 pfx_buf
, new_buf
, exist_buf
);
744 /* 8. IGP metric check. */
748 newm
= new->extra
->igpmetric
;
750 existm
= exist
->extra
->igpmetric
;
755 "%s: %s wins over %s due to IGP metric %d < %d",
756 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
763 "%s: %s loses to %s due to IGP metric %d > %d",
764 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
768 /* 9. Same IGP metric. Compare the cluster list length as
769 representative of IGP hops metric. Rewrite the metric value
770 pair (newm, existm) with the cluster list length. Prefer the
771 path with smaller cluster list length. */
772 if (newm
== existm
) {
773 if (peer_sort(new->peer
) == BGP_PEER_IBGP
774 && peer_sort(exist
->peer
) == BGP_PEER_IBGP
775 && (mpath_cfg
== NULL
777 mpath_cfg
->ibgp_flags
,
778 BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN
))) {
779 newm
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
780 existm
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
785 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
786 pfx_buf
, new_buf
, exist_buf
,
794 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
795 pfx_buf
, new_buf
, exist_buf
,
802 /* 10. confed-external vs. confed-internal */
803 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
804 if (new_sort
== BGP_PEER_CONFED
805 && exist_sort
== BGP_PEER_IBGP
) {
808 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
809 pfx_buf
, new_buf
, exist_buf
);
813 if (exist_sort
== BGP_PEER_CONFED
814 && new_sort
== BGP_PEER_IBGP
) {
817 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
818 pfx_buf
, new_buf
, exist_buf
);
823 /* 11. Maximum path check. */
824 if (newm
== existm
) {
825 /* If one path has a label but the other does not, do not treat
826 * them as equals for multipath
828 if ((new->extra
&&bgp_is_valid_label(&new->extra
->label
[0]))
830 && bgp_is_valid_label(&exist
->extra
->label
[0]))) {
833 "%s: %s and %s cannot be multipath, one has a label while the other does not",
834 pfx_buf
, new_buf
, exist_buf
);
835 } else if (bgp_flag_check(bgp
,
836 BGP_FLAG_ASPATH_MULTIPATH_RELAX
)) {
839 * For the two paths, all comparison steps till IGP
841 * have succeeded - including AS_PATH hop count. Since
843 * bestpath as-path multipath-relax' knob is on, we
845 * an exact match of AS_PATH. Thus, mark the paths are
847 * That will trigger both these paths to get into the
855 "%s: %s and %s are equal via multipath-relax",
856 pfx_buf
, new_buf
, exist_buf
);
857 } else if (new->peer
->sort
== BGP_PEER_IBGP
) {
858 if (aspath_cmp(new->attr
->aspath
,
859 exist
->attr
->aspath
)) {
864 "%s: %s and %s are equal via matching aspaths",
865 pfx_buf
, new_buf
, exist_buf
);
867 } else if (new->peer
->as
== exist
->peer
->as
) {
872 "%s: %s and %s are equal via same remote-as",
873 pfx_buf
, new_buf
, exist_buf
);
877 * TODO: If unequal cost ibgp multipath is enabled we can
878 * mark the paths as equal here instead of returning
883 "%s: %s wins over %s after IGP metric comparison",
884 pfx_buf
, new_buf
, exist_buf
);
887 "%s: %s loses to %s after IGP metric comparison",
888 pfx_buf
, new_buf
, exist_buf
);
893 /* 12. If both paths are external, prefer the path that was received
894 first (the oldest one). This step minimizes route-flap, since a
895 newer path won't displace an older one, even if it was the
896 preferred route based on the additional decision criteria below. */
897 if (!bgp_flag_check(bgp
, BGP_FLAG_COMPARE_ROUTER_ID
)
898 && new_sort
== BGP_PEER_EBGP
&& exist_sort
== BGP_PEER_EBGP
) {
899 if (CHECK_FLAG(new->flags
, BGP_INFO_SELECTED
)) {
902 "%s: %s wins over %s due to oldest external",
903 pfx_buf
, new_buf
, exist_buf
);
907 if (CHECK_FLAG(exist
->flags
, BGP_INFO_SELECTED
)) {
910 "%s: %s loses to %s due to oldest external",
911 pfx_buf
, new_buf
, exist_buf
);
916 /* 13. Router-ID comparision. */
917 /* If one of the paths is "stale", the corresponding peer router-id will
918 * be 0 and would always win over the other path. If originator id is
919 * used for the comparision, it will decide which path is better.
921 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
922 new_id
.s_addr
= newattr
->originator_id
.s_addr
;
924 new_id
.s_addr
= new->peer
->remote_id
.s_addr
;
925 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
926 exist_id
.s_addr
= existattr
->originator_id
.s_addr
;
928 exist_id
.s_addr
= exist
->peer
->remote_id
.s_addr
;
930 if (ntohl(new_id
.s_addr
) < ntohl(exist_id
.s_addr
)) {
933 "%s: %s wins over %s due to Router-ID comparison",
934 pfx_buf
, new_buf
, exist_buf
);
938 if (ntohl(new_id
.s_addr
) > ntohl(exist_id
.s_addr
)) {
941 "%s: %s loses to %s due to Router-ID comparison",
942 pfx_buf
, new_buf
, exist_buf
);
946 /* 14. Cluster length comparision. */
947 new_cluster
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
948 exist_cluster
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
950 if (new_cluster
< exist_cluster
) {
953 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
954 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
959 if (new_cluster
> exist_cluster
) {
962 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
963 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
968 /* 15. Neighbor address comparision. */
969 /* Do this only if neither path is "stale" as stale paths do not have
970 * valid peer information (as the connection may or may not be up).
972 if (CHECK_FLAG(exist
->flags
, BGP_INFO_STALE
)) {
975 "%s: %s wins over %s due to latter path being STALE",
976 pfx_buf
, new_buf
, exist_buf
);
980 if (CHECK_FLAG(new->flags
, BGP_INFO_STALE
)) {
983 "%s: %s loses to %s due to former path being STALE",
984 pfx_buf
, new_buf
, exist_buf
);
988 /* locally configured routes to advertise do not have su_remote */
989 if (new->peer
->su_remote
== NULL
)
991 if (exist
->peer
->su_remote
== NULL
)
994 ret
= sockunion_cmp(new->peer
->su_remote
, exist
->peer
->su_remote
);
999 "%s: %s loses to %s due to Neighor IP comparison",
1000 pfx_buf
, new_buf
, exist_buf
);
1007 "%s: %s wins over %s due to Neighor IP comparison",
1008 pfx_buf
, new_buf
, exist_buf
);
1013 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1014 pfx_buf
, new_buf
, exist_buf
);
1019 /* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1020 * is preferred, or 0 if they are the same (usually will only occur if
1021 * multipath is enabled
1022 * This version is compatible with */
1023 int bgp_info_cmp_compatible(struct bgp
*bgp
, struct bgp_info
*new,
1024 struct bgp_info
*exist
, char *pfx_buf
, afi_t afi
,
1029 ret
= bgp_info_cmp(bgp
, new, exist
, &paths_eq
, NULL
, 0, pfx_buf
, afi
,
1043 static enum filter_type
bgp_input_filter(struct peer
*peer
, struct prefix
*p
,
1044 struct attr
*attr
, afi_t afi
,
1047 struct bgp_filter
*filter
;
1049 filter
= &peer
->filter
[afi
][safi
];
1051 #define FILTER_EXIST_WARN(F, f, filter) \
1052 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
1053 zlog_debug("%s: Could not find configured input %s-list %s!", \
1054 peer->host, #f, F##_IN_NAME(filter));
1056 if (DISTRIBUTE_IN_NAME(filter
)) {
1057 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1059 if (access_list_apply(DISTRIBUTE_IN(filter
), p
) == FILTER_DENY
)
1063 if (PREFIX_LIST_IN_NAME(filter
)) {
1064 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1066 if (prefix_list_apply(PREFIX_LIST_IN(filter
), p
) == PREFIX_DENY
)
1070 if (FILTER_LIST_IN_NAME(filter
)) {
1071 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1073 if (as_list_apply(FILTER_LIST_IN(filter
), attr
->aspath
)
1078 return FILTER_PERMIT
;
1079 #undef FILTER_EXIST_WARN
1082 static enum filter_type
bgp_output_filter(struct peer
*peer
, struct prefix
*p
,
1083 struct attr
*attr
, afi_t afi
,
1086 struct bgp_filter
*filter
;
1088 filter
= &peer
->filter
[afi
][safi
];
1090 #define FILTER_EXIST_WARN(F, f, filter) \
1091 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
1092 zlog_debug("%s: Could not find configured output %s-list %s!", \
1093 peer->host, #f, F##_OUT_NAME(filter));
1095 if (DISTRIBUTE_OUT_NAME(filter
)) {
1096 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1098 if (access_list_apply(DISTRIBUTE_OUT(filter
), p
) == FILTER_DENY
)
1102 if (PREFIX_LIST_OUT_NAME(filter
)) {
1103 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1105 if (prefix_list_apply(PREFIX_LIST_OUT(filter
), p
)
1110 if (FILTER_LIST_OUT_NAME(filter
)) {
1111 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1113 if (as_list_apply(FILTER_LIST_OUT(filter
), attr
->aspath
)
1118 return FILTER_PERMIT
;
1119 #undef FILTER_EXIST_WARN
1122 /* If community attribute includes no_export then return 1. */
1123 static int bgp_community_filter(struct peer
*peer
, struct attr
*attr
)
1125 if (attr
->community
) {
1126 /* NO_ADVERTISE check. */
1127 if (community_include(attr
->community
, COMMUNITY_NO_ADVERTISE
))
1130 /* NO_EXPORT check. */
1131 if (peer
->sort
== BGP_PEER_EBGP
1132 && community_include(attr
->community
, COMMUNITY_NO_EXPORT
))
1135 /* NO_EXPORT_SUBCONFED check. */
1136 if (peer
->sort
== BGP_PEER_EBGP
1137 || peer
->sort
== BGP_PEER_CONFED
)
1138 if (community_include(attr
->community
,
1139 COMMUNITY_NO_EXPORT_SUBCONFED
))
1145 /* Route reflection loop check. */
1146 static int bgp_cluster_filter(struct peer
*peer
, struct attr
*attr
)
1148 struct in_addr cluster_id
;
1150 if (attr
->cluster
) {
1151 if (peer
->bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
1152 cluster_id
= peer
->bgp
->cluster_id
;
1154 cluster_id
= peer
->bgp
->router_id
;
1156 if (cluster_loop_check(attr
->cluster
, cluster_id
))
1162 static int bgp_input_modifier(struct peer
*peer
, struct prefix
*p
,
1163 struct attr
*attr
, afi_t afi
, safi_t safi
,
1164 const char *rmap_name
)
1166 struct bgp_filter
*filter
;
1167 struct bgp_info info
;
1168 route_map_result_t ret
;
1169 struct route_map
*rmap
= NULL
;
1171 filter
= &peer
->filter
[afi
][safi
];
1173 /* Apply default weight value. */
1174 if (peer
->weight
[afi
][safi
])
1175 attr
->weight
= peer
->weight
[afi
][safi
];
1178 rmap
= route_map_lookup_by_name(rmap_name
);
1183 if (ROUTE_MAP_IN_NAME(filter
)) {
1184 rmap
= ROUTE_MAP_IN(filter
);
1191 /* Route map apply. */
1193 memset(&info
, 0, sizeof(struct bgp_info
));
1194 /* Duplicate current value to new strucutre for modification. */
1198 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_IN
);
1200 /* Apply BGP route map to the attribute. */
1201 ret
= route_map_apply(rmap
, p
, RMAP_BGP
, &info
);
1203 peer
->rmap_type
= 0;
1205 if (ret
== RMAP_DENYMATCH
)
1211 static int bgp_output_modifier(struct peer
*peer
, struct prefix
*p
,
1212 struct attr
*attr
, afi_t afi
, safi_t safi
,
1213 const char *rmap_name
)
1215 struct bgp_info info
;
1216 route_map_result_t ret
;
1217 struct route_map
*rmap
= NULL
;
1221 * So if we get to this point and have no rmap_name
1222 * we want to just show the output as it currently
1228 /* Apply default weight value. */
1229 if (peer
->weight
[afi
][safi
])
1230 attr
->weight
= peer
->weight
[afi
][safi
];
1232 rmap
= route_map_lookup_by_name(rmap_name
);
1235 * If we have a route map name and we do not find
1236 * the routemap that means we have an implicit
1242 memset(&info
, 0, sizeof(struct bgp_info
));
1243 /* Route map apply. */
1244 /* Duplicate current value to new strucutre for modification. */
1248 rmap_type
= peer
->rmap_type
;
1249 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1251 /* Apply BGP route map to the attribute. */
1252 ret
= route_map_apply(rmap
, p
, RMAP_BGP
, &info
);
1254 peer
->rmap_type
= rmap_type
;
1256 if (ret
== RMAP_DENYMATCH
)
1258 * caller has multiple error paths with bgp_attr_flush()
1265 /* If this is an EBGP peer with remove-private-AS */
1266 static void bgp_peer_remove_private_as(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1267 struct peer
*peer
, struct attr
*attr
)
1269 if (peer
->sort
== BGP_PEER_EBGP
1270 && (peer_af_flag_check(peer
, afi
, safi
,
1271 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1272 || peer_af_flag_check(peer
, afi
, safi
,
1273 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
)
1274 || peer_af_flag_check(peer
, afi
, safi
,
1275 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)
1276 || peer_af_flag_check(peer
, afi
, safi
,
1277 PEER_FLAG_REMOVE_PRIVATE_AS
))) {
1278 // Take action on the entire aspath
1279 if (peer_af_flag_check(peer
, afi
, safi
,
1280 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1281 || peer_af_flag_check(peer
, afi
, safi
,
1282 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)) {
1283 if (peer_af_flag_check(
1285 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
))
1286 attr
->aspath
= aspath_replace_private_asns(
1287 attr
->aspath
, bgp
->as
);
1289 // The entire aspath consists of private ASNs so create
1291 else if (aspath_private_as_check(attr
->aspath
))
1292 attr
->aspath
= aspath_empty_get();
1294 // There are some public and some private ASNs, remove
1297 attr
->aspath
= aspath_remove_private_asns(
1301 // 'all' was not specified so the entire aspath must be private
1303 // for us to do anything
1304 else if (aspath_private_as_check(attr
->aspath
)) {
1305 if (peer_af_flag_check(
1307 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
))
1308 attr
->aspath
= aspath_replace_private_asns(
1309 attr
->aspath
, bgp
->as
);
1311 attr
->aspath
= aspath_empty_get();
1316 /* If this is an EBGP peer with as-override */
1317 static void bgp_peer_as_override(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1318 struct peer
*peer
, struct attr
*attr
)
1320 if (peer
->sort
== BGP_PEER_EBGP
1321 && peer_af_flag_check(peer
, afi
, safi
, PEER_FLAG_AS_OVERRIDE
)) {
1322 if (aspath_single_asn_check(attr
->aspath
, peer
->as
))
1323 attr
->aspath
= aspath_replace_specific_asn(
1324 attr
->aspath
, peer
->as
, bgp
->as
);
1328 void bgp_attr_add_gshut_community(struct attr
*attr
)
1330 struct community
*old
;
1331 struct community
*new;
1332 struct community
*merge
;
1333 struct community
*gshut
;
1335 old
= attr
->community
;
1336 gshut
= community_str2com("graceful-shutdown");
1341 merge
= community_merge(community_dup(old
), gshut
);
1343 if (old
->refcnt
== 0)
1344 community_free(old
);
1346 new = community_uniq_sort(merge
);
1347 community_free(merge
);
1349 new = community_dup(gshut
);
1352 community_free(gshut
);
1353 attr
->community
= new;
1354 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
1356 /* When we add the graceful-shutdown community we must also
1357 * lower the local-preference */
1358 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1359 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1363 static void subgroup_announce_reset_nhop(uint8_t family
, struct attr
*attr
)
1365 if (family
== AF_INET
) {
1366 attr
->nexthop
.s_addr
= 0;
1367 attr
->mp_nexthop_global_in
.s_addr
= 0;
1369 if (family
== AF_INET6
)
1370 memset(&attr
->mp_nexthop_global
, 0, IPV6_MAX_BYTELEN
);
1371 if (family
== AF_EVPN
)
1372 memset(&attr
->mp_nexthop_global_in
, 0, BGP_ATTR_NHLEN_IPV4
);
1375 int subgroup_announce_check(struct bgp_node
*rn
, struct bgp_info
*ri
,
1376 struct update_subgroup
*subgrp
, struct prefix
*p
,
1379 struct bgp_filter
*filter
;
1382 struct peer
*onlypeer
;
1384 struct attr
*riattr
;
1385 char buf
[PREFIX_STRLEN
];
1391 int samepeer_safe
= 0; /* for synthetic mplsvpns routes */
1393 if (DISABLE_BGP_ANNOUNCE
)
1396 afi
= SUBGRP_AFI(subgrp
);
1397 safi
= SUBGRP_SAFI(subgrp
);
1398 peer
= SUBGRP_PEER(subgrp
);
1400 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_LONESOUL
))
1401 onlypeer
= SUBGRP_PFIRST(subgrp
)->peer
;
1404 filter
= &peer
->filter
[afi
][safi
];
1405 bgp
= SUBGRP_INST(subgrp
);
1406 riattr
= bgp_info_mpath_count(ri
) ? bgp_info_mpath_attr(ri
) : ri
->attr
;
1409 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
)) && (safi
== SAFI_MPLS_VPN
)
1410 && ((ri
->type
== ZEBRA_ROUTE_BGP_DIRECT
)
1411 || (ri
->type
== ZEBRA_ROUTE_BGP_DIRECT_EXT
))) {
1414 * direct and direct_ext type routes originate internally even
1415 * though they can have peer pointers that reference other
1418 prefix2str(p
, buf
, PREFIX_STRLEN
);
1419 zlog_debug("%s: pfx %s bgp_direct->vpn route peer safe",
1425 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
))
1426 && ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_UNICAST
))
1427 && (ri
->type
== ZEBRA_ROUTE_BGP
)
1428 && (ri
->sub_type
== BGP_ROUTE_IMPORTED
)) {
1430 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1435 /* With addpath we may be asked to TX all kinds of paths so make sure
1437 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_VALID
)
1438 || CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
)
1439 || CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)) {
1443 /* If this is not the bestpath then check to see if there is an enabled
1445 * feature that requires us to advertise it */
1446 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
1447 if (!bgp_addpath_tx_path(peer
, afi
, safi
, ri
)) {
1452 /* Aggregate-address suppress check. */
1453 if (ri
->extra
&& ri
->extra
->suppress
)
1454 if (!UNSUPPRESS_MAP_NAME(filter
)) {
1459 * If we are doing VRF 2 VRF leaking via the import
1460 * statement, we want to prevent the route going
1461 * off box as that the RT and RD created are localy
1462 * significant and globaly useless.
1464 if (safi
== SAFI_MPLS_VPN
&& ri
->extra
&& ri
->extra
->num_labels
1465 && ri
->extra
->label
[0] == BGP_PREVENT_VRF_2_VRF_LEAK
)
1468 /* If it's labeled safi, make sure the route has a valid label. */
1469 if (safi
== SAFI_LABELED_UNICAST
) {
1470 mpls_label_t label
= bgp_adv_label(rn
, ri
, peer
, afi
, safi
);
1471 if (!bgp_is_valid_label(&label
)) {
1472 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1473 zlog_debug("u%" PRIu64
":s%" PRIu64
1474 " %s/%d is filtered - no label (%p)",
1475 subgrp
->update_group
->id
, subgrp
->id
,
1476 inet_ntop(p
->family
, &p
->u
.prefix
,
1477 buf
, SU_ADDRSTRLEN
),
1478 p
->prefixlen
, &label
);
1483 /* Do not send back route to sender. */
1484 if (onlypeer
&& from
== onlypeer
) {
1488 /* Do not send the default route in the BGP table if the neighbor is
1489 * configured for default-originate */
1490 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1491 PEER_FLAG_DEFAULT_ORIGINATE
)) {
1492 if (p
->family
== AF_INET
&& p
->u
.prefix4
.s_addr
== INADDR_ANY
)
1494 else if (p
->family
== AF_INET6
&& p
->prefixlen
== 0)
1498 /* Transparency check. */
1499 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
)
1500 && CHECK_FLAG(from
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
))
1505 /* If community is not disabled check the no-export and local. */
1506 if (!transparent
&& bgp_community_filter(peer
, riattr
)) {
1507 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1509 "subgrpannouncecheck: community filter check fail");
1513 /* If the attribute has originator-id and it is same as remote
1515 if (onlypeer
&& riattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
1516 && (IPV4_ADDR_SAME(&onlypeer
->remote_id
, &riattr
->originator_id
))) {
1517 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1519 "%s [Update:SEND] %s originator-id is same as "
1522 prefix2str(p
, buf
, sizeof(buf
)));
1526 /* ORF prefix-list filter check */
1527 if (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_RM_ADV
)
1528 && (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_SM_RCV
)
1529 || CHECK_FLAG(peer
->af_cap
[afi
][safi
],
1530 PEER_CAP_ORF_PREFIX_SM_OLD_RCV
)))
1531 if (peer
->orf_plist
[afi
][safi
]) {
1532 if (prefix_list_apply(peer
->orf_plist
[afi
][safi
], p
)
1534 if (bgp_debug_update(NULL
, p
,
1535 subgrp
->update_group
, 0))
1537 "%s [Update:SEND] %s is filtered via ORF",
1545 /* Output filter check. */
1546 if (bgp_output_filter(peer
, p
, riattr
, afi
, safi
) == FILTER_DENY
) {
1547 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1548 zlog_debug("%s [Update:SEND] %s is filtered",
1549 peer
->host
, prefix2str(p
, buf
, sizeof(buf
)));
1553 #ifdef BGP_SEND_ASPATH_CHECK
1554 /* AS path loop check. */
1555 if (onlypeer
&& aspath_loop_check(riattr
->aspath
, onlypeer
->as
)) {
1556 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1558 "%s [Update:SEND] suppress announcement to peer AS %u "
1559 "that is part of AS path.",
1560 onlypeer
->host
, onlypeer
->as
);
1563 #endif /* BGP_SEND_ASPATH_CHECK */
1565 /* If we're a CONFED we need to loop check the CONFED ID too */
1566 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
1567 if (aspath_loop_check(riattr
->aspath
, bgp
->confed_id
)) {
1568 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1570 "%s [Update:SEND] suppress announcement to peer AS %u"
1572 peer
->host
, bgp
->confed_id
);
1577 /* Route-Reflect check. */
1578 if (from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1583 /* IBGP reflection check. */
1584 if (reflect
&& !samepeer_safe
) {
1585 /* A route from a Client peer. */
1586 if (CHECK_FLAG(from
->af_flags
[afi
][safi
],
1587 PEER_FLAG_REFLECTOR_CLIENT
)) {
1588 /* Reflect to all the Non-Client peers and also to the
1589 Client peers other than the originator. Originator
1591 is already done. So there is noting to do. */
1592 /* no bgp client-to-client reflection check. */
1593 if (bgp_flag_check(bgp
, BGP_FLAG_NO_CLIENT_TO_CLIENT
))
1594 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1595 PEER_FLAG_REFLECTOR_CLIENT
))
1598 /* A route from a Non-client peer. Reflect to all other
1600 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1601 PEER_FLAG_REFLECTOR_CLIENT
))
1606 /* For modify attribute, copy it to temporary structure. */
1607 bgp_attr_dup(attr
, riattr
);
1609 /* If local-preference is not set. */
1610 if ((peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
)
1611 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))) {
1612 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1613 attr
->local_pref
= bgp
->default_local_pref
;
1616 /* If originator-id is not set and the route is to be reflected,
1617 set the originator id */
1619 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)))) {
1620 IPV4_ADDR_COPY(&(attr
->originator_id
), &(from
->remote_id
));
1621 SET_FLAG(attr
->flag
, BGP_ATTR_ORIGINATOR_ID
);
1624 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
1626 if (peer
->sort
== BGP_PEER_EBGP
1627 && attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
1628 if (from
!= bgp
->peer_self
&& !transparent
1629 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1630 PEER_FLAG_MED_UNCHANGED
))
1632 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
));
1635 /* Since the nexthop attribute can vary per peer, it is not explicitly
1637 * in announce check, only certain flags and length (or number of
1639 * -- for IPv6/MP_REACH) are set here in order to guide the update
1641 * code in setting the nexthop(s) on a per peer basis in
1643 * Typically, the source nexthop in the attribute is preserved but in
1645 * scenarios where we know it will always be overwritten, we reset the
1646 * nexthop to "0" in an attempt to achieve better Update packing. An
1647 * example of this is when a prefix from each of 2 IBGP peers needs to
1649 * announced to an EBGP peer (and they have the same attributes barring
1653 SET_FLAG(attr
->rmap_change_flags
, BATTR_REFLECTED
);
1655 #define NEXTHOP_IS_V6 \
1656 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
1657 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
1658 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
1659 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
1661 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
1663 * the peer (group) is configured to receive link-local nexthop
1665 * and it is available in the prefix OR we're not reflecting the route
1667 * the peer (group) to whom we're going to announce is on a shared
1669 * and this is either a self-originated route or the peer is EBGP.
1671 if (NEXTHOP_IS_V6
) {
1672 attr
->mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
1673 if ((CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1674 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)
1675 && IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
))
1676 || (!reflect
&& peer
->shared_network
1677 && (from
== bgp
->peer_self
1678 || peer
->sort
== BGP_PEER_EBGP
))) {
1679 attr
->mp_nexthop_len
=
1680 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
;
1683 /* Clear off link-local nexthop in source, whenever it is not
1685 * ensure more prefixes share the same attribute for
1688 if (!(CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1689 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)))
1690 memset(&attr
->mp_nexthop_local
, 0, IPV6_MAX_BYTELEN
);
1693 bgp_peer_remove_private_as(bgp
, afi
, safi
, peer
, attr
);
1694 bgp_peer_as_override(bgp
, afi
, safi
, peer
, attr
);
1696 /* Route map & unsuppress-map apply. */
1697 if (ROUTE_MAP_OUT_NAME(filter
) || (ri
->extra
&& ri
->extra
->suppress
)) {
1698 struct bgp_info info
;
1699 struct bgp_info_extra dummy_info_extra
;
1700 struct attr dummy_attr
;
1702 memset(&info
, 0, sizeof(struct bgp_info
));
1707 memcpy(&dummy_info_extra
, ri
->extra
,
1708 sizeof(struct bgp_info_extra
));
1709 info
.extra
= &dummy_info_extra
;
1712 /* don't confuse inbound and outbound setting */
1713 RESET_FLAG(attr
->rmap_change_flags
);
1716 * The route reflector is not allowed to modify the attributes
1717 * of the reflected IBGP routes unless explicitly allowed.
1719 if ((from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1720 && !bgp_flag_check(bgp
,
1721 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY
)) {
1722 bgp_attr_dup(&dummy_attr
, attr
);
1723 info
.attr
= &dummy_attr
;
1726 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1728 if (ri
->extra
&& ri
->extra
->suppress
)
1729 ret
= route_map_apply(UNSUPPRESS_MAP(filter
), p
,
1732 ret
= route_map_apply(ROUTE_MAP_OUT(filter
), p
,
1735 peer
->rmap_type
= 0;
1737 if (ret
== RMAP_DENYMATCH
) {
1738 bgp_attr_flush(attr
);
1743 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
1744 if (peer
->sort
== BGP_PEER_IBGP
1745 || peer
->sort
== BGP_PEER_CONFED
) {
1746 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1747 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1749 bgp_attr_add_gshut_community(attr
);
1753 /* After route-map has been applied, we check to see if the nexthop to
1754 * be carried in the attribute (that is used for the announcement) can
1755 * be cleared off or not. We do this in all cases where we would be
1756 * setting the nexthop to "ourselves". For IPv6, we only need to
1758 * the global nexthop here; the link-local nexthop would have been
1760 * already, and if not, it is required by the update formation code.
1761 * Also see earlier comments in this function.
1764 * If route-map has performed some operation on the nexthop or the peer
1765 * configuration says to pass it unchanged, we cannot reset the nexthop
1766 * here, so only attempt to do it if these aren't true. Note that the
1767 * route-map handler itself might have cleared the nexthop, if for
1769 * it is configured as 'peer-address'.
1771 if (!bgp_rmap_nhop_changed(attr
->rmap_change_flags
,
1772 riattr
->rmap_change_flags
)
1774 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1775 PEER_FLAG_NEXTHOP_UNCHANGED
)) {
1776 /* We can reset the nexthop, if setting (or forcing) it to
1778 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1779 PEER_FLAG_NEXTHOP_SELF
)
1780 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1781 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
1783 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1784 PEER_FLAG_FORCE_NEXTHOP_SELF
))
1785 subgroup_announce_reset_nhop(
1786 (peer_cap_enhe(peer
, afi
, safi
)
1790 } else if (peer
->sort
== BGP_PEER_EBGP
) {
1791 /* Can also reset the nexthop if announcing to EBGP, but
1793 * no peer in the subgroup is on a shared subnet.
1794 * Note: 3rd party nexthop currently implemented for
1797 if (!bgp_subgrp_multiaccess_check_v4(riattr
->nexthop
,
1799 subgroup_announce_reset_nhop(
1800 (peer_cap_enhe(peer
, afi
, safi
)
1804 } else if (CHECK_FLAG(ri
->flags
, BGP_INFO_ANNC_NH_SELF
)) {
1806 * This flag is used for leaked vpn-vrf routes
1808 int family
= p
->family
;
1810 if (peer_cap_enhe(peer
, afi
, safi
))
1813 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1815 "%s: BGP_INFO_ANNC_NH_SELF, family=%s",
1816 __func__
, family2str(family
));
1817 subgroup_announce_reset_nhop(family
, attr
);
1820 /* If IPv6/MP and nexthop does not have any override and happens
1822 * be a link-local address, reset it so that we don't pass along
1824 * source's link-local IPv6 address to recipients who may not be
1826 * the same interface.
1828 if (p
->family
== AF_INET6
|| peer_cap_enhe(peer
, afi
, safi
)) {
1829 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
))
1830 subgroup_announce_reset_nhop(AF_INET6
, attr
);
1837 void bgp_best_selection(struct bgp
*bgp
, struct bgp_node
*rn
,
1838 struct bgp_maxpaths_cfg
*mpath_cfg
,
1839 struct bgp_info_pair
*result
, afi_t afi
, safi_t safi
)
1841 struct bgp_info
*new_select
;
1842 struct bgp_info
*old_select
;
1843 struct bgp_info
*ri
;
1844 struct bgp_info
*ri1
;
1845 struct bgp_info
*ri2
;
1846 struct bgp_info
*nextri
= NULL
;
1847 int paths_eq
, do_mpath
, debug
;
1848 struct list mp_list
;
1849 char pfx_buf
[PREFIX2STR_BUFFER
];
1850 char path_buf
[PATH_ADDPATH_STR_BUFFER
];
1852 bgp_mp_list_init(&mp_list
);
1854 (mpath_cfg
->maxpaths_ebgp
> 1 || mpath_cfg
->maxpaths_ibgp
> 1);
1856 debug
= bgp_debug_bestpath(&rn
->p
);
1859 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
1861 /* bgp deterministic-med */
1863 if (bgp_flag_check(bgp
, BGP_FLAG_DETERMINISTIC_MED
)) {
1865 /* Clear BGP_INFO_DMED_SELECTED for all paths */
1866 for (ri1
= rn
->info
; ri1
; ri1
= ri1
->next
)
1867 bgp_info_unset_flag(rn
, ri1
, BGP_INFO_DMED_SELECTED
);
1869 for (ri1
= rn
->info
; ri1
; ri1
= ri1
->next
) {
1870 if (CHECK_FLAG(ri1
->flags
, BGP_INFO_DMED_CHECK
))
1872 if (BGP_INFO_HOLDDOWN(ri1
))
1874 if (ri1
->peer
&& ri1
->peer
!= bgp
->peer_self
)
1875 if (ri1
->peer
->status
!= Established
)
1880 for (ri2
= ri1
->next
; ri2
; ri2
= ri2
->next
) {
1881 if (CHECK_FLAG(ri2
->flags
,
1882 BGP_INFO_DMED_CHECK
))
1884 if (BGP_INFO_HOLDDOWN(ri2
))
1887 && ri2
->peer
!= bgp
->peer_self
1890 PEER_STATUS_NSF_WAIT
))
1891 if (ri2
->peer
->status
1895 if (aspath_cmp_left(ri1
->attr
->aspath
,
1897 || aspath_cmp_left_confed(
1899 ri2
->attr
->aspath
)) {
1900 if (bgp_info_cmp(bgp
, ri2
,
1906 bgp_info_unset_flag(
1908 BGP_INFO_DMED_SELECTED
);
1914 BGP_INFO_DMED_CHECK
);
1918 bgp_info_set_flag(rn
, new_select
, BGP_INFO_DMED_CHECK
);
1919 bgp_info_set_flag(rn
, new_select
,
1920 BGP_INFO_DMED_SELECTED
);
1923 bgp_info_path_with_addpath_rx_str(new_select
,
1925 zlog_debug("%s: %s is the bestpath from AS %u",
1927 aspath_get_first_as(
1928 new_select
->attr
->aspath
));
1933 /* Check old selected route and new selected route. */
1936 for (ri
= rn
->info
; (ri
!= NULL
) && (nextri
= ri
->next
, 1);
1938 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
))
1941 if (BGP_INFO_HOLDDOWN(ri
)) {
1942 /* reap REMOVED routes, if needs be
1943 * selected route must stay for a while longer though
1945 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)
1946 && (ri
!= old_select
))
1947 bgp_info_reap(rn
, ri
);
1950 zlog_debug("%s: ri %p in holddown", __func__
,
1956 if (ri
->peer
&& ri
->peer
!= bgp
->peer_self
1957 && !CHECK_FLAG(ri
->peer
->sflags
, PEER_STATUS_NSF_WAIT
))
1958 if (ri
->peer
->status
!= Established
) {
1962 "%s: ri %p non self peer %s not estab state",
1963 __func__
, ri
, ri
->peer
->host
);
1968 if (bgp_flag_check(bgp
, BGP_FLAG_DETERMINISTIC_MED
)
1969 && (!CHECK_FLAG(ri
->flags
, BGP_INFO_DMED_SELECTED
))) {
1970 bgp_info_unset_flag(rn
, ri
, BGP_INFO_DMED_CHECK
);
1972 zlog_debug("%s: ri %p dmed", __func__
, ri
);
1976 bgp_info_unset_flag(rn
, ri
, BGP_INFO_DMED_CHECK
);
1978 if (bgp_info_cmp(bgp
, ri
, new_select
, &paths_eq
, mpath_cfg
,
1979 debug
, pfx_buf
, afi
, safi
)) {
1984 /* Now that we know which path is the bestpath see if any of the other
1986 * qualify as multipaths
1990 bgp_info_path_with_addpath_rx_str(new_select
, path_buf
);
1992 sprintf(path_buf
, "NONE");
1994 "%s: After path selection, newbest is %s oldbest was %s",
1996 old_select
? old_select
->peer
->host
: "NONE");
1999 if (do_mpath
&& new_select
) {
2000 for (ri
= rn
->info
; (ri
!= NULL
) && (nextri
= ri
->next
, 1);
2004 bgp_info_path_with_addpath_rx_str(ri
, path_buf
);
2006 if (ri
== new_select
) {
2009 "%s: %s is the bestpath, add to the multipath list",
2011 bgp_mp_list_add(&mp_list
, ri
);
2015 if (BGP_INFO_HOLDDOWN(ri
))
2018 if (ri
->peer
&& ri
->peer
!= bgp
->peer_self
2019 && !CHECK_FLAG(ri
->peer
->sflags
,
2020 PEER_STATUS_NSF_WAIT
))
2021 if (ri
->peer
->status
!= Established
)
2024 if (!bgp_info_nexthop_cmp(ri
, new_select
)) {
2027 "%s: %s has the same nexthop as the bestpath, skip it",
2032 bgp_info_cmp(bgp
, ri
, new_select
, &paths_eq
, mpath_cfg
,
2033 debug
, pfx_buf
, afi
, safi
);
2038 "%s: %s is equivalent to the bestpath, add to the multipath list",
2040 bgp_mp_list_add(&mp_list
, ri
);
2045 bgp_info_mpath_update(rn
, new_select
, old_select
, &mp_list
, mpath_cfg
);
2046 bgp_info_mpath_aggregate_update(new_select
, old_select
);
2047 bgp_mp_list_clear(&mp_list
);
2049 result
->old
= old_select
;
2050 result
->new = new_select
;
2056 * A new route/change in bestpath of an existing route. Evaluate the path
2057 * for advertisement to the subgroup.
2059 int subgroup_process_announce_selected(struct update_subgroup
*subgrp
,
2060 struct bgp_info
*selected
,
2061 struct bgp_node
*rn
,
2062 uint32_t addpath_tx_id
)
2065 struct peer
*onlypeer
;
2071 afi
= SUBGRP_AFI(subgrp
);
2072 safi
= SUBGRP_SAFI(subgrp
);
2073 onlypeer
= ((SUBGRP_PCOUNT(subgrp
) == 1) ? (SUBGRP_PFIRST(subgrp
))->peer
2076 if (BGP_DEBUG(update
, UPDATE_OUT
)) {
2077 char buf_prefix
[PREFIX_STRLEN
];
2078 prefix2str(p
, buf_prefix
, sizeof(buf_prefix
));
2079 zlog_debug("%s: p=%s, selected=%p", __func__
, buf_prefix
,
2083 /* First update is deferred until ORF or ROUTE-REFRESH is received */
2084 if (onlypeer
&& CHECK_FLAG(onlypeer
->af_sflags
[afi
][safi
],
2085 PEER_STATUS_ORF_WAIT_REFRESH
))
2088 memset(&attr
, 0, sizeof(struct attr
));
2089 /* It's initialized in bgp_announce_check() */
2091 /* Announcement to the subgroup. If the route is filtered withdraw it.
2094 if (subgroup_announce_check(rn
, selected
, subgrp
, p
, &attr
))
2095 bgp_adj_out_set_subgroup(rn
, subgrp
, &attr
, selected
);
2097 bgp_adj_out_unset_subgroup(rn
, subgrp
, 1,
2098 selected
->addpath_tx_id
);
2101 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2103 bgp_adj_out_unset_subgroup(rn
, subgrp
, 1, addpath_tx_id
);
2110 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2111 * This is called at the end of route processing.
2113 void bgp_zebra_clear_route_change_flags(struct bgp_node
*rn
)
2115 struct bgp_info
*ri
;
2117 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
2118 if (BGP_INFO_HOLDDOWN(ri
))
2120 UNSET_FLAG(ri
->flags
, BGP_INFO_IGP_CHANGED
);
2121 UNSET_FLAG(ri
->flags
, BGP_INFO_ATTR_CHANGED
);
2126 * Has the route changed from the RIB's perspective? This is invoked only
2127 * if the route selection returns the same best route as earlier - to
2128 * determine if we need to update zebra or not.
2130 int bgp_zebra_has_route_changed(struct bgp_node
*rn
, struct bgp_info
*selected
)
2132 struct bgp_info
*mpinfo
;
2134 /* If this is multipath, check all selected paths for any nexthop
2135 * change or attribute change. Some attribute changes (e.g., community)
2136 * aren't of relevance to the RIB, but we'll update zebra to ensure
2137 * we handle the case of BGP nexthop change. This is the behavior
2138 * when the best path has an attribute change anyway.
2140 if (CHECK_FLAG(selected
->flags
, BGP_INFO_IGP_CHANGED
)
2141 || CHECK_FLAG(selected
->flags
, BGP_INFO_MULTIPATH_CHG
))
2145 * If this is multipath, check all selected paths for any nexthop change
2147 for (mpinfo
= bgp_info_mpath_first(selected
); mpinfo
;
2148 mpinfo
= bgp_info_mpath_next(mpinfo
)) {
2149 if (CHECK_FLAG(mpinfo
->flags
, BGP_INFO_IGP_CHANGED
)
2150 || CHECK_FLAG(mpinfo
->flags
, BGP_INFO_ATTR_CHANGED
))
2154 /* Nothing has changed from the RIB's perspective. */
2158 struct bgp_process_queue
{
2160 STAILQ_HEAD(, bgp_node
) pqueue
;
2161 #define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2163 unsigned int queued
;
2167 * old_select = The old best path
2168 * new_select = the new best path
2170 * if (!old_select && new_select)
2171 * We are sending new information on.
2173 * if (old_select && new_select) {
2174 * if (new_select != old_select)
2175 * We have a new best path send a change
2177 * We've received a update with new attributes that needs
2181 * if (old_select && !new_select)
2182 * We have no eligible route that we can announce or the rn
2185 static void bgp_process_main_one(struct bgp
*bgp
, struct bgp_node
*rn
,
2186 afi_t afi
, safi_t safi
)
2188 struct bgp_info
*new_select
;
2189 struct bgp_info
*old_select
;
2190 struct bgp_info_pair old_and_new
;
2191 char pfx_buf
[PREFIX2STR_BUFFER
];
2194 /* Is it end of initial update? (after startup) */
2196 quagga_timestamp(3, bgp
->update_delay_zebra_resume_time
,
2197 sizeof(bgp
->update_delay_zebra_resume_time
));
2199 bgp
->main_zebra_update_hold
= 0;
2200 FOREACH_AFI_SAFI (afi
, safi
) {
2201 if (bgp_fibupd_safi(safi
))
2202 bgp_zebra_announce_table(bgp
, afi
, safi
);
2204 bgp
->main_peers_update_hold
= 0;
2206 bgp_start_routeadv(bgp
);
2210 struct prefix
*p
= &rn
->p
;
2212 debug
= bgp_debug_bestpath(&rn
->p
);
2214 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
2215 zlog_debug("%s: p=%s afi=%s, safi=%s start", __func__
, pfx_buf
,
2216 afi2str(afi
), safi2str(safi
));
2219 /* Best path selection. */
2220 bgp_best_selection(bgp
, rn
, &bgp
->maxpaths
[afi
][safi
], &old_and_new
,
2222 old_select
= old_and_new
.old
;
2223 new_select
= old_and_new
.new;
2225 /* Do we need to allocate or free labels?
2226 * Right now, since we only deal with per-prefix labels, it is not
2227 * necessary to do this upon changes to best path except if the label
2230 if (bgp
->allocate_mpls_labels
[afi
][safi
]) {
2233 || bgp_label_index_differs(new_select
, old_select
)
2234 || new_select
->sub_type
!= old_select
->sub_type
) {
2235 if (new_select
->sub_type
== BGP_ROUTE_STATIC
2236 && new_select
->attr
->flag
2238 BGP_ATTR_PREFIX_SID
)
2239 && new_select
->attr
->label_index
2240 != BGP_INVALID_LABEL_INDEX
) {
2243 BGP_NODE_REGISTERED_FOR_LABEL
))
2244 bgp_unregister_for_label(rn
);
2245 label_ntop(MPLS_LABEL_IMPLICIT_NULL
, 1,
2247 bgp_set_valid_label(&rn
->local_label
);
2249 bgp_register_for_label(rn
, new_select
);
2251 } else if (CHECK_FLAG(rn
->flags
,
2252 BGP_NODE_REGISTERED_FOR_LABEL
)) {
2253 bgp_unregister_for_label(rn
);
2255 } else if (CHECK_FLAG(rn
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
)) {
2256 bgp_unregister_for_label(rn
);
2260 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
2262 "%s: p=%s afi=%s, safi=%s, old_select=%p, new_select=%p",
2263 __func__
, pfx_buf
, afi2str(afi
), safi2str(safi
),
2264 old_select
, new_select
);
2267 /* If best route remains the same and this is not due to user-initiated
2268 * clear, see exactly what needs to be done.
2270 if (old_select
&& old_select
== new_select
2271 && !CHECK_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
)
2272 && !CHECK_FLAG(old_select
->flags
, BGP_INFO_ATTR_CHANGED
)
2273 && !bgp
->addpath_tx_used
[afi
][safi
]) {
2274 if (bgp_zebra_has_route_changed(rn
, old_select
)) {
2276 vnc_import_bgp_add_route(bgp
, p
, old_select
);
2277 vnc_import_bgp_exterior_add_route(bgp
, p
, old_select
);
2279 if (bgp_fibupd_safi(safi
)
2280 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2282 if (new_select
->type
== ZEBRA_ROUTE_BGP
2283 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2284 || new_select
->sub_type
2285 == BGP_ROUTE_IMPORTED
))
2287 bgp_zebra_announce(rn
, p
, old_select
,
2291 UNSET_FLAG(old_select
->flags
, BGP_INFO_MULTIPATH_CHG
);
2292 bgp_zebra_clear_route_change_flags(rn
);
2294 /* If there is a change of interest to peers, reannounce the
2296 if (CHECK_FLAG(old_select
->flags
, BGP_INFO_ATTR_CHANGED
)
2297 || CHECK_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
)) {
2298 group_announce_route(bgp
, afi
, safi
, rn
, new_select
);
2300 /* unicast routes must also be annouced to
2301 * labeled-unicast update-groups */
2302 if (safi
== SAFI_UNICAST
)
2303 group_announce_route(bgp
, afi
,
2304 SAFI_LABELED_UNICAST
, rn
,
2307 UNSET_FLAG(old_select
->flags
, BGP_INFO_ATTR_CHANGED
);
2308 UNSET_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
);
2311 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2315 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2317 UNSET_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
);
2319 /* bestpath has changed; bump version */
2320 if (old_select
|| new_select
) {
2321 bgp_bump_version(rn
);
2323 if (!bgp
->t_rmap_def_originate_eval
) {
2327 update_group_refresh_default_originate_route_map
,
2328 bgp
, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER
,
2329 &bgp
->t_rmap_def_originate_eval
);
2334 bgp_info_unset_flag(rn
, old_select
, BGP_INFO_SELECTED
);
2337 zlog_debug("%s: setting SELECTED flag", __func__
);
2338 bgp_info_set_flag(rn
, new_select
, BGP_INFO_SELECTED
);
2339 bgp_info_unset_flag(rn
, new_select
, BGP_INFO_ATTR_CHANGED
);
2340 UNSET_FLAG(new_select
->flags
, BGP_INFO_MULTIPATH_CHG
);
2344 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2345 if (old_select
!= new_select
) {
2347 vnc_import_bgp_exterior_del_route(bgp
, p
,
2349 vnc_import_bgp_del_route(bgp
, p
, old_select
);
2352 vnc_import_bgp_exterior_add_route(bgp
, p
,
2354 vnc_import_bgp_add_route(bgp
, p
, new_select
);
2360 group_announce_route(bgp
, afi
, safi
, rn
, new_select
);
2362 /* unicast routes must also be annouced to labeled-unicast update-groups
2364 if (safi
== SAFI_UNICAST
)
2365 group_announce_route(bgp
, afi
, SAFI_LABELED_UNICAST
, rn
,
2369 if (bgp_fibupd_safi(safi
) && (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VIEW
)
2370 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2371 if (new_select
&& new_select
->type
== ZEBRA_ROUTE_BGP
2372 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2373 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
2374 || new_select
->sub_type
== BGP_ROUTE_IMPORTED
)) {
2376 /* if this is an evpn imported type-5 prefix,
2377 * we need to withdraw the route first to clear
2378 * the nh neigh and the RMAC entry.
2381 is_route_parent_evpn(old_select
))
2382 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2384 bgp_zebra_announce(rn
, p
, new_select
, bgp
, afi
, safi
);
2386 /* Withdraw the route from the kernel. */
2387 if (old_select
&& old_select
->type
== ZEBRA_ROUTE_BGP
2388 && (old_select
->sub_type
== BGP_ROUTE_NORMAL
2389 || old_select
->sub_type
== BGP_ROUTE_AGGREGATE
2390 || old_select
->sub_type
== BGP_ROUTE_IMPORTED
))
2392 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2396 /* advertise/withdraw type-5 routes */
2397 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2398 if (advertise_type5_routes(bgp
, afi
) && new_select
&&
2399 (!new_select
->extra
|| !new_select
->extra
->parent
)) {
2401 /* apply the route-map */
2402 if (bgp
->adv_cmd_rmap
[afi
][safi
].map
) {
2405 ret
= route_map_apply(
2406 bgp
->adv_cmd_rmap
[afi
][safi
].map
,
2407 &rn
->p
, RMAP_BGP
, new_select
);
2408 if (ret
== RMAP_MATCH
)
2409 bgp_evpn_advertise_type5_route(
2410 bgp
, &rn
->p
, new_select
->attr
,
2413 bgp_evpn_advertise_type5_route(bgp
,
2419 } else if (advertise_type5_routes(bgp
, afi
) && old_select
&&
2420 (!old_select
->extra
|| !old_select
->extra
->parent
))
2421 bgp_evpn_withdraw_type5_route(bgp
, &rn
->p
, afi
, safi
);
2424 /* Clear any route change flags. */
2425 bgp_zebra_clear_route_change_flags(rn
);
2427 /* Reap old select bgp_info, if it has been removed */
2428 if (old_select
&& CHECK_FLAG(old_select
->flags
, BGP_INFO_REMOVED
))
2429 bgp_info_reap(rn
, old_select
);
2431 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2435 static wq_item_status
bgp_process_wq(struct work_queue
*wq
, void *data
)
2437 struct bgp_process_queue
*pqnode
= data
;
2438 struct bgp
*bgp
= pqnode
->bgp
;
2439 struct bgp_table
*table
;
2440 struct bgp_node
*rn
;
2443 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)) {
2444 bgp_process_main_one(bgp
, NULL
, 0, 0);
2445 /* should always have dedicated wq call */
2446 assert(STAILQ_FIRST(&pqnode
->pqueue
) == NULL
);
2450 while (!STAILQ_EMPTY(&pqnode
->pqueue
)) {
2451 rn
= STAILQ_FIRST(&pqnode
->pqueue
);
2452 STAILQ_REMOVE_HEAD(&pqnode
->pqueue
, pq
);
2453 STAILQ_NEXT(rn
, pq
) = NULL
; /* complete unlink */
2454 table
= bgp_node_table(rn
);
2455 /* note, new RNs may be added as part of processing */
2456 bgp_process_main_one(bgp
, rn
, table
->afi
, table
->safi
);
2458 bgp_unlock_node(rn
);
2459 bgp_table_unlock(table
);
2465 static void bgp_processq_del(struct work_queue
*wq
, void *data
)
2467 struct bgp_process_queue
*pqnode
= data
;
2469 bgp_unlock(pqnode
->bgp
);
2471 XFREE(MTYPE_BGP_PROCESS_QUEUE
, pqnode
);
2474 void bgp_process_queue_init(void)
2476 if (!bm
->process_main_queue
)
2477 bm
->process_main_queue
=
2478 work_queue_new(bm
->master
, "process_main_queue");
2480 bm
->process_main_queue
->spec
.workfunc
= &bgp_process_wq
;
2481 bm
->process_main_queue
->spec
.del_item_data
= &bgp_processq_del
;
2482 bm
->process_main_queue
->spec
.max_retries
= 0;
2483 bm
->process_main_queue
->spec
.hold
= 50;
2484 /* Use a higher yield value of 50ms for main queue processing */
2485 bm
->process_main_queue
->spec
.yield
= 50 * 1000L;
2488 static struct bgp_process_queue
*bgp_processq_alloc(struct bgp
*bgp
)
2490 struct bgp_process_queue
*pqnode
;
2492 pqnode
= XCALLOC(MTYPE_BGP_PROCESS_QUEUE
,
2493 sizeof(struct bgp_process_queue
));
2495 /* unlocked in bgp_processq_del */
2496 pqnode
->bgp
= bgp_lock(bgp
);
2497 STAILQ_INIT(&pqnode
->pqueue
);
2502 void bgp_process(struct bgp
*bgp
, struct bgp_node
*rn
, afi_t afi
, safi_t safi
)
2504 #define ARBITRARY_PROCESS_QLEN 10000
2505 struct work_queue
*wq
= bm
->process_main_queue
;
2506 struct bgp_process_queue
*pqnode
;
2507 int pqnode_reuse
= 0;
2509 /* already scheduled for processing? */
2510 if (CHECK_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
2516 /* Add route nodes to an existing work queue item until reaching the
2517 limit only if is from the same BGP view and it's not an EOIU marker
2519 if (work_queue_item_count(wq
)) {
2520 struct work_queue_item
*item
= work_queue_last_item(wq
);
2521 pqnode
= item
->data
;
2523 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)
2524 || pqnode
->bgp
!= bgp
2525 || pqnode
->queued
>= ARBITRARY_PROCESS_QLEN
)
2526 pqnode
= bgp_processq_alloc(bgp
);
2530 pqnode
= bgp_processq_alloc(bgp
);
2531 /* all unlocked in bgp_process_wq */
2532 bgp_table_lock(bgp_node_table(rn
));
2534 SET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2537 /* can't be enqueued twice */
2538 assert(STAILQ_NEXT(rn
, pq
) == NULL
);
2539 STAILQ_INSERT_TAIL(&pqnode
->pqueue
, rn
, pq
);
2543 work_queue_add(wq
, pqnode
);
2548 void bgp_add_eoiu_mark(struct bgp
*bgp
)
2550 struct bgp_process_queue
*pqnode
;
2552 if (bm
->process_main_queue
== NULL
)
2555 pqnode
= bgp_processq_alloc(bgp
);
2557 SET_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
);
2558 work_queue_add(bm
->process_main_queue
, pqnode
);
2561 static int bgp_maximum_prefix_restart_timer(struct thread
*thread
)
2565 peer
= THREAD_ARG(thread
);
2566 peer
->t_pmax_restart
= NULL
;
2568 if (bgp_debug_neighbor_events(peer
))
2570 "%s Maximum-prefix restart timer expired, restore peering",
2573 if ((peer_clear(peer
, NULL
) < 0) && bgp_debug_neighbor_events(peer
))
2574 zlog_debug("%s: %s peer_clear failed",
2575 __PRETTY_FUNCTION__
, peer
->host
);
2580 int bgp_maximum_prefix_overflow(struct peer
*peer
, afi_t afi
, safi_t safi
,
2584 iana_safi_t pkt_safi
;
2586 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX
))
2589 if (peer
->pcount
[afi
][safi
] > peer
->pmax
[afi
][safi
]) {
2590 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2591 PEER_STATUS_PREFIX_LIMIT
)
2596 "%%MAXPFXEXCEED: No. of %s prefix received from %s %ld exceed, "
2598 afi_safi_print(afi
, safi
), peer
->host
,
2599 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2600 SET_FLAG(peer
->af_sflags
[afi
][safi
], PEER_STATUS_PREFIX_LIMIT
);
2602 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2603 PEER_FLAG_MAX_PREFIX_WARNING
))
2606 /* Convert AFI, SAFI to values for packet. */
2607 pkt_afi
= afi_int2iana(afi
);
2608 pkt_safi
= safi_int2iana(safi
);
2612 ndata
[0] = (pkt_afi
>> 8);
2614 ndata
[2] = pkt_safi
;
2615 ndata
[3] = (peer
->pmax
[afi
][safi
] >> 24);
2616 ndata
[4] = (peer
->pmax
[afi
][safi
] >> 16);
2617 ndata
[5] = (peer
->pmax
[afi
][safi
] >> 8);
2618 ndata
[6] = (peer
->pmax
[afi
][safi
]);
2620 SET_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
);
2621 bgp_notify_send_with_data(peer
, BGP_NOTIFY_CEASE
,
2622 BGP_NOTIFY_CEASE_MAX_PREFIX
,
2626 /* Dynamic peers will just close their connection. */
2627 if (peer_dynamic_neighbor(peer
))
2630 /* restart timer start */
2631 if (peer
->pmax_restart
[afi
][safi
]) {
2632 peer
->v_pmax_restart
=
2633 peer
->pmax_restart
[afi
][safi
] * 60;
2635 if (bgp_debug_neighbor_events(peer
))
2637 "%s Maximum-prefix restart timer started for %d secs",
2638 peer
->host
, peer
->v_pmax_restart
);
2640 BGP_TIMER_ON(peer
->t_pmax_restart
,
2641 bgp_maximum_prefix_restart_timer
,
2642 peer
->v_pmax_restart
);
2647 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
2648 PEER_STATUS_PREFIX_LIMIT
);
2650 if (peer
->pcount
[afi
][safi
]
2651 > (peer
->pmax
[afi
][safi
] * peer
->pmax_threshold
[afi
][safi
] / 100)) {
2652 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2653 PEER_STATUS_PREFIX_THRESHOLD
)
2658 "%%MAXPFX: No. of %s prefix received from %s reaches %ld, max %ld",
2659 afi_safi_print(afi
, safi
), peer
->host
,
2660 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2661 SET_FLAG(peer
->af_sflags
[afi
][safi
],
2662 PEER_STATUS_PREFIX_THRESHOLD
);
2664 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
2665 PEER_STATUS_PREFIX_THRESHOLD
);
2669 /* Unconditionally remove the route from the RIB, without taking
2670 * damping into consideration (eg, because the session went down)
2672 void bgp_rib_remove(struct bgp_node
*rn
, struct bgp_info
*ri
, struct peer
*peer
,
2673 afi_t afi
, safi_t safi
)
2675 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, ri
, afi
, safi
);
2677 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
2678 bgp_info_delete(rn
, ri
); /* keep historical info */
2680 bgp_process(peer
->bgp
, rn
, afi
, safi
);
2683 static void bgp_rib_withdraw(struct bgp_node
*rn
, struct bgp_info
*ri
,
2684 struct peer
*peer
, afi_t afi
, safi_t safi
,
2685 struct prefix_rd
*prd
)
2687 /* apply dampening, if result is suppressed, we'll be retaining
2688 * the bgp_info in the RIB for historical reference.
2690 if (CHECK_FLAG(peer
->bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
2691 && peer
->sort
== BGP_PEER_EBGP
)
2692 if ((bgp_damp_withdraw(ri
, rn
, afi
, safi
, 0))
2693 == BGP_DAMP_SUPPRESSED
) {
2694 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, ri
, afi
,
2700 if (safi
== SAFI_MPLS_VPN
) {
2701 struct bgp_node
*prn
= NULL
;
2702 struct bgp_table
*table
= NULL
;
2704 prn
= bgp_node_get(peer
->bgp
->rib
[afi
][safi
],
2705 (struct prefix
*)prd
);
2707 table
= (struct bgp_table
*)(prn
->info
);
2709 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
2710 peer
->bgp
, prd
, table
, &rn
->p
, ri
);
2712 bgp_unlock_node(prn
);
2714 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2715 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
2717 vnc_import_bgp_del_route(peer
->bgp
, &rn
->p
, ri
);
2718 vnc_import_bgp_exterior_del_route(peer
->bgp
, &rn
->p
,
2724 /* If this is an EVPN route, process for un-import. */
2725 if (safi
== SAFI_EVPN
)
2726 bgp_evpn_unimport_route(peer
->bgp
, afi
, safi
, &rn
->p
, ri
);
2728 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
2731 struct bgp_info
*info_make(int type
, int sub_type
, unsigned short instance
,
2732 struct peer
*peer
, struct attr
*attr
,
2733 struct bgp_node
*rn
)
2735 struct bgp_info
*new;
2737 /* Make new BGP info. */
2738 new = XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_info
));
2740 new->instance
= instance
;
2741 new->sub_type
= sub_type
;
2744 new->uptime
= bgp_clock();
2746 new->addpath_tx_id
= ++peer
->bgp
->addpath_tx_id
;
2750 static void overlay_index_update(struct attr
*attr
,
2751 struct eth_segment_id
*eth_s_id
,
2752 union gw_addr
*gw_ip
)
2757 if (eth_s_id
== NULL
) {
2758 memset(&(attr
->evpn_overlay
.eth_s_id
), 0,
2759 sizeof(struct eth_segment_id
));
2761 memcpy(&(attr
->evpn_overlay
.eth_s_id
), eth_s_id
,
2762 sizeof(struct eth_segment_id
));
2764 if (gw_ip
== NULL
) {
2765 memset(&(attr
->evpn_overlay
.gw_ip
), 0, sizeof(union gw_addr
));
2767 memcpy(&(attr
->evpn_overlay
.gw_ip
), gw_ip
,
2768 sizeof(union gw_addr
));
2772 static bool overlay_index_equal(afi_t afi
, struct bgp_info
*info
,
2773 struct eth_segment_id
*eth_s_id
,
2774 union gw_addr
*gw_ip
)
2776 struct eth_segment_id
*info_eth_s_id
, *info_eth_s_id_remote
;
2777 union gw_addr
*info_gw_ip
, *info_gw_ip_remote
;
2779 struct eth_segment_id esi
;
2783 if (afi
!= AFI_L2VPN
)
2786 memset(&temp
, 0, sizeof(temp
));
2787 info_eth_s_id
= &temp
.esi
;
2788 info_gw_ip
= &temp
.ip
;
2790 if (eth_s_id
== NULL
&& gw_ip
== NULL
)
2793 info_eth_s_id
= &(info
->attr
->evpn_overlay
.eth_s_id
);
2794 info_gw_ip
= &(info
->attr
->evpn_overlay
.gw_ip
);
2797 if (gw_ip
== NULL
) {
2798 memset(&temp
, 0, sizeof(temp
));
2799 info_gw_ip_remote
= &temp
.ip
;
2801 info_gw_ip_remote
= gw_ip
;
2803 if (eth_s_id
== NULL
) {
2804 memset(&temp
, 0, sizeof(temp
));
2805 info_eth_s_id_remote
= &temp
.esi
;
2807 info_eth_s_id_remote
= eth_s_id
;
2809 if (!memcmp(info_gw_ip
, info_gw_ip_remote
, sizeof(union gw_addr
)))
2812 return !memcmp(info_eth_s_id
, info_eth_s_id_remote
,
2813 sizeof(struct eth_segment_id
));
2816 /* Check if received nexthop is valid or not. */
2817 static int bgp_update_martian_nexthop(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
2822 /* Only validated for unicast and multicast currently. */
2823 /* Also valid for EVPN where the nexthop is an IP address. */
2824 if (safi
!= SAFI_UNICAST
&& safi
!= SAFI_MULTICAST
&& safi
!= SAFI_EVPN
)
2827 /* If NEXT_HOP is present, validate it. */
2828 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
2829 if (attr
->nexthop
.s_addr
== 0
2830 || IPV4_CLASS_DE(ntohl(attr
->nexthop
.s_addr
))
2831 || bgp_nexthop_self(bgp
, attr
->nexthop
))
2835 /* If MP_NEXTHOP is present, validate it. */
2836 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
2837 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
2838 * it is not an IPv6 link-local address.
2840 if (attr
->mp_nexthop_len
) {
2841 switch (attr
->mp_nexthop_len
) {
2842 case BGP_ATTR_NHLEN_IPV4
:
2843 case BGP_ATTR_NHLEN_VPNV4
:
2844 ret
= (attr
->mp_nexthop_global_in
.s_addr
== 0
2845 || IPV4_CLASS_DE(ntohl(
2846 attr
->mp_nexthop_global_in
.s_addr
))
2847 || bgp_nexthop_self(bgp
,
2848 attr
->mp_nexthop_global_in
));
2851 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
2852 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
2853 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
2854 ret
= (IN6_IS_ADDR_UNSPECIFIED(&attr
->mp_nexthop_global
)
2855 || IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
2856 || IN6_IS_ADDR_MULTICAST(
2857 &attr
->mp_nexthop_global
));
2869 int bgp_update(struct peer
*peer
, struct prefix
*p
, uint32_t addpath_id
,
2870 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
2871 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
2872 uint32_t num_labels
, int soft_reconfig
,
2873 struct bgp_route_evpn
*evpn
)
2876 int aspath_loop_count
= 0;
2877 struct bgp_node
*rn
;
2879 struct attr new_attr
;
2880 struct attr
*attr_new
;
2881 struct bgp_info
*ri
;
2882 struct bgp_info
*new;
2883 struct bgp_info_extra
*extra
;
2885 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
2887 int do_loop_check
= 1;
2888 int has_valid_label
= 0;
2890 int vnc_implicit_withdraw
= 0;
2894 memset(&new_attr
, 0, sizeof(struct attr
));
2895 new_attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
2896 new_attr
.label
= MPLS_INVALID_LABEL
;
2899 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
2900 /* TODO: Check to see if we can get rid of "is_valid_label" */
2901 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
2902 has_valid_label
= (num_labels
> 0) ? 1 : 0;
2904 has_valid_label
= bgp_is_valid_label(label
);
2906 /* When peer's soft reconfiguration enabled. Record input packet in
2909 && CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
2910 && peer
!= bgp
->peer_self
)
2911 bgp_adj_in_set(rn
, peer
, attr
, addpath_id
);
2913 /* Check previously received route. */
2914 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
2915 if (ri
->peer
== peer
&& ri
->type
== type
2916 && ri
->sub_type
== sub_type
2917 && ri
->addpath_rx_id
== addpath_id
)
2920 /* AS path local-as loop check. */
2921 if (peer
->change_local_as
) {
2922 if (peer
->allowas_in
[afi
][safi
])
2923 aspath_loop_count
= peer
->allowas_in
[afi
][safi
];
2924 else if (!CHECK_FLAG(peer
->flags
,
2925 PEER_FLAG_LOCAL_AS_NO_PREPEND
))
2926 aspath_loop_count
= 1;
2928 if (aspath_loop_check(attr
->aspath
, peer
->change_local_as
)
2929 > aspath_loop_count
) {
2930 reason
= "as-path contains our own AS;";
2935 /* If the peer is configured for "allowas-in origin" and the last ASN in
2937 * as-path is our ASN then we do not need to call aspath_loop_check
2939 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN_ORIGIN
))
2940 if (aspath_get_last_as(attr
->aspath
) == bgp
->as
)
2943 /* AS path loop check. */
2944 if (do_loop_check
) {
2945 if (aspath_loop_check(attr
->aspath
, bgp
->as
)
2946 > peer
->allowas_in
[afi
][safi
]
2947 || (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)
2948 && aspath_loop_check(attr
->aspath
, bgp
->confed_id
)
2949 > peer
->allowas_in
[afi
][safi
])) {
2950 reason
= "as-path contains our own AS;";
2955 /* Route reflector originator ID check. */
2956 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
2957 && IPV4_ADDR_SAME(&bgp
->router_id
, &attr
->originator_id
)) {
2958 reason
= "originator is us;";
2962 /* Route reflector cluster ID check. */
2963 if (bgp_cluster_filter(peer
, attr
)) {
2964 reason
= "reflected from the same cluster;";
2968 /* Apply incoming filter. */
2969 if (bgp_input_filter(peer
, p
, attr
, afi
, safi
) == FILTER_DENY
) {
2974 bgp_attr_dup(&new_attr
, attr
);
2976 /* Apply incoming route-map.
2977 * NB: new_attr may now contain newly allocated values from route-map
2979 * commands, so we need bgp_attr_flush in the error paths, until we
2981 * the attr (which takes over the memory references) */
2982 if (bgp_input_modifier(peer
, p
, &new_attr
, afi
, safi
, NULL
)
2984 reason
= "route-map;";
2985 bgp_attr_flush(&new_attr
);
2989 if (peer
->sort
== BGP_PEER_EBGP
) {
2991 /* If we receive the graceful-shutdown community from an eBGP
2992 * peer we must lower local-preference */
2993 if (new_attr
.community
2994 && community_include(new_attr
.community
, COMMUNITY_GSHUT
)) {
2995 new_attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
2996 new_attr
.local_pref
= BGP_GSHUT_LOCAL_PREF
;
2998 /* If graceful-shutdown is configured then add the GSHUT
2999 * community to all paths received from eBGP peers */
3000 } else if (bgp_flag_check(peer
->bgp
,
3001 BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
3002 bgp_attr_add_gshut_community(&new_attr
);
3006 /* next hop check. */
3007 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
)
3008 && bgp_update_martian_nexthop(bgp
, afi
, safi
, &new_attr
)) {
3009 reason
= "martian or self next-hop;";
3010 bgp_attr_flush(&new_attr
);
3014 attr_new
= bgp_attr_intern(&new_attr
);
3016 /* If the update is implicit withdraw. */
3018 ri
->uptime
= bgp_clock();
3019 same_attr
= attrhash_cmp(ri
->attr
, attr_new
);
3021 /* Same attribute comes in. */
3022 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)
3023 && attrhash_cmp(ri
->attr
, attr_new
)
3024 && (!has_valid_label
3025 || memcmp(&(bgp_info_extra_get(ri
))->label
, label
,
3026 num_labels
* sizeof(mpls_label_t
))
3028 && (overlay_index_equal(
3029 afi
, ri
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3030 evpn
== NULL
? NULL
: &evpn
->gw_ip
))) {
3031 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
3032 BGP_CONFIG_DAMPENING
)
3033 && peer
->sort
== BGP_PEER_EBGP
3034 && CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
)) {
3035 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3036 bgp_debug_rdpfxpath2str(
3037 afi
, safi
, prd
, p
, label
,
3038 num_labels
, addpath_id
? 1 : 0,
3039 addpath_id
, pfx_buf
,
3041 zlog_debug("%s rcvd %s", peer
->host
,
3045 if (bgp_damp_update(ri
, rn
, afi
, safi
)
3046 != BGP_DAMP_SUPPRESSED
) {
3047 bgp_aggregate_increment(bgp
, p
, ri
, afi
,
3049 bgp_process(bgp
, rn
, afi
, safi
);
3051 } else /* Duplicate - odd */
3053 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3054 if (!peer
->rcvd_attr_printed
) {
3056 "%s rcvd UPDATE w/ attr: %s",
3058 peer
->rcvd_attr_str
);
3059 peer
->rcvd_attr_printed
= 1;
3062 bgp_debug_rdpfxpath2str(
3063 afi
, safi
, prd
, p
, label
,
3064 num_labels
, addpath_id
? 1 : 0,
3065 addpath_id
, pfx_buf
,
3068 "%s rcvd %s...duplicate ignored",
3069 peer
->host
, pfx_buf
);
3072 /* graceful restart STALE flag unset. */
3073 if (CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
)) {
3074 bgp_info_unset_flag(rn
, ri
,
3076 bgp_process(bgp
, rn
, afi
, safi
);
3080 bgp_unlock_node(rn
);
3081 bgp_attr_unintern(&attr_new
);
3086 /* Withdraw/Announce before we fully processed the withdraw */
3087 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)) {
3088 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3089 bgp_debug_rdpfxpath2str(
3090 afi
, safi
, prd
, p
, label
, num_labels
,
3091 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3094 "%s rcvd %s, flapped quicker than processing",
3095 peer
->host
, pfx_buf
);
3098 bgp_info_restore(rn
, ri
);
3101 /* Received Logging. */
3102 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3103 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
3104 num_labels
, addpath_id
? 1 : 0,
3105 addpath_id
, pfx_buf
,
3107 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3110 /* graceful restart STALE flag unset. */
3111 if (CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
))
3112 bgp_info_unset_flag(rn
, ri
, BGP_INFO_STALE
);
3114 /* The attribute is changed. */
3115 bgp_info_set_flag(rn
, ri
, BGP_INFO_ATTR_CHANGED
);
3117 /* implicit withdraw, decrement aggregate and pcount here.
3118 * only if update is accepted, they'll increment below.
3120 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
3122 /* Update bgp route dampening information. */
3123 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3124 && peer
->sort
== BGP_PEER_EBGP
) {
3125 /* This is implicit withdraw so we should update
3128 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
3129 bgp_damp_withdraw(ri
, rn
, afi
, safi
, 1);
3132 if (safi
== SAFI_MPLS_VPN
) {
3133 struct bgp_node
*prn
= NULL
;
3134 struct bgp_table
*table
= NULL
;
3136 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3137 (struct prefix
*)prd
);
3139 table
= (struct bgp_table
*)(prn
->info
);
3141 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3142 bgp
, prd
, table
, p
, ri
);
3144 bgp_unlock_node(prn
);
3146 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3147 && (safi
== SAFI_UNICAST
)) {
3148 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
3150 * Implicit withdraw case.
3152 ++vnc_implicit_withdraw
;
3153 vnc_import_bgp_del_route(bgp
, p
, ri
);
3154 vnc_import_bgp_exterior_del_route(bgp
, p
, ri
);
3159 /* Special handling for EVPN update of an existing route. If the
3160 * extended community attribute has changed, we need to
3162 * the route using its existing extended community. It will be
3163 * subsequently processed for import with the new extended
3166 if (safi
== SAFI_EVPN
&& !same_attr
) {
3168 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))
3170 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
3173 cmp
= ecommunity_cmp(ri
->attr
->ecommunity
,
3174 attr_new
->ecommunity
);
3176 if (bgp_debug_update(peer
, p
, NULL
, 1))
3178 "Change in EXT-COMM, existing %s new %s",
3180 ri
->attr
->ecommunity
),
3182 attr_new
->ecommunity
));
3183 bgp_evpn_unimport_route(bgp
, afi
, safi
,
3189 /* Update to new attribute. */
3190 bgp_attr_unintern(&ri
->attr
);
3191 ri
->attr
= attr_new
;
3193 /* Update MPLS label */
3194 if (has_valid_label
) {
3195 extra
= bgp_info_extra_get(ri
);
3196 memcpy(&extra
->label
, label
,
3197 num_labels
* sizeof(mpls_label_t
));
3198 extra
->num_labels
= num_labels
;
3199 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3200 bgp_set_valid_label(&extra
->label
[0]);
3204 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3205 && (safi
== SAFI_UNICAST
)) {
3206 if (vnc_implicit_withdraw
) {
3208 * Add back the route with its new attributes
3210 * The route is still selected, until the route
3212 * queued by bgp_process actually runs. We have
3214 * update to the VNC side immediately to avoid
3216 * configuration changes (e.g., route-map
3218 * trigger re-importation of the entire RIB.
3220 vnc_import_bgp_add_route(bgp
, p
, ri
);
3221 vnc_import_bgp_exterior_add_route(bgp
, p
, ri
);
3225 /* Update Overlay Index */
3226 if (afi
== AFI_L2VPN
) {
3227 overlay_index_update(
3228 ri
->attr
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3229 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3232 /* Update bgp route dampening information. */
3233 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3234 && peer
->sort
== BGP_PEER_EBGP
) {
3235 /* Now we do normal update dampening. */
3236 ret
= bgp_damp_update(ri
, rn
, afi
, safi
);
3237 if (ret
== BGP_DAMP_SUPPRESSED
) {
3238 bgp_unlock_node(rn
);
3243 /* Nexthop reachability check - for unicast and
3244 * labeled-unicast.. */
3245 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3246 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
3247 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
3248 && !CHECK_FLAG(peer
->flags
,
3249 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3251 bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3256 struct bgp
*bgp_nexthop
= bgp
;
3258 if (ri
->extra
&& ri
->extra
->bgp_orig
)
3259 bgp_nexthop
= ri
->extra
->bgp_orig
;
3261 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
, afi
,
3262 ri
, NULL
, connected
)
3263 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3264 bgp_info_set_flag(rn
, ri
, BGP_INFO_VALID
);
3266 if (BGP_DEBUG(nht
, NHT
)) {
3267 char buf1
[INET6_ADDRSTRLEN
];
3269 (const void *)&attr_new
3271 buf1
, INET6_ADDRSTRLEN
);
3272 zlog_debug("%s(%s): NH unresolved",
3273 __FUNCTION__
, buf1
);
3275 bgp_info_unset_flag(rn
, ri
, BGP_INFO_VALID
);
3278 bgp_info_set_flag(rn
, ri
, BGP_INFO_VALID
);
3281 if (safi
== SAFI_MPLS_VPN
) {
3282 struct bgp_node
*prn
= NULL
;
3283 struct bgp_table
*table
= NULL
;
3285 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3286 (struct prefix
*)prd
);
3288 table
= (struct bgp_table
*)(prn
->info
);
3290 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3291 bgp
, prd
, table
, p
, ri
);
3293 bgp_unlock_node(prn
);
3297 /* If this is an EVPN route and some attribute has changed,
3299 * route for import. If the extended community has changed, we
3301 * have done the un-import earlier and the import would result
3303 * route getting injected into appropriate L2 VNIs. If it is
3305 * some other attribute change, the import will result in
3307 * the attributes for the route in the VNI(s).
3309 if (safi
== SAFI_EVPN
&& !same_attr
)
3310 bgp_evpn_import_route(bgp
, afi
, safi
, p
, ri
);
3312 /* Process change. */
3313 bgp_aggregate_increment(bgp
, p
, ri
, afi
, safi
);
3315 bgp_process(bgp
, rn
, afi
, safi
);
3316 bgp_unlock_node(rn
);
3318 if (SAFI_UNICAST
== safi
3319 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3320 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3322 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, ri
);
3324 if ((SAFI_MPLS_VPN
== safi
)
3325 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3327 vpn_leak_to_vrf_update(bgp
, ri
);
3331 if (SAFI_MPLS_VPN
== safi
) {
3332 mpls_label_t label_decoded
= decode_label(label
);
3334 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3335 type
, sub_type
, &label_decoded
);
3337 if (SAFI_ENCAP
== safi
) {
3338 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3339 type
, sub_type
, NULL
);
3344 } // End of implicit withdraw
3346 /* Received Logging. */
3347 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3348 if (!peer
->rcvd_attr_printed
) {
3349 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3350 peer
->rcvd_attr_str
);
3351 peer
->rcvd_attr_printed
= 1;
3354 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3355 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3357 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3360 /* Make new BGP info. */
3361 new = info_make(type
, sub_type
, 0, peer
, attr_new
, rn
);
3363 /* Update MPLS label */
3364 if (has_valid_label
) {
3365 extra
= bgp_info_extra_get(new);
3366 memcpy(&extra
->label
, label
, num_labels
* sizeof(mpls_label_t
));
3367 extra
->num_labels
= num_labels
;
3368 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3369 bgp_set_valid_label(&extra
->label
[0]);
3372 /* Update Overlay Index */
3373 if (afi
== AFI_L2VPN
) {
3374 overlay_index_update(new->attr
,
3375 evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3376 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3378 /* Nexthop reachability check. */
3379 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3380 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
3381 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
3382 && !CHECK_FLAG(peer
->flags
,
3383 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3384 && !bgp_flag_check(bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3389 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, new, NULL
, connected
)
3390 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3391 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
3393 if (BGP_DEBUG(nht
, NHT
)) {
3394 char buf1
[INET6_ADDRSTRLEN
];
3396 (const void *)&attr_new
->nexthop
,
3397 buf1
, INET6_ADDRSTRLEN
);
3398 zlog_debug("%s(%s): NH unresolved",
3399 __FUNCTION__
, buf1
);
3401 bgp_info_unset_flag(rn
, new, BGP_INFO_VALID
);
3404 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
3407 new->addpath_rx_id
= addpath_id
;
3409 /* Increment prefix */
3410 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
3412 /* Register new BGP information. */
3413 bgp_info_add(rn
, new);
3415 /* route_node_get lock */
3416 bgp_unlock_node(rn
);
3419 if (safi
== SAFI_MPLS_VPN
) {
3420 struct bgp_node
*prn
= NULL
;
3421 struct bgp_table
*table
= NULL
;
3423 prn
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
3425 table
= (struct bgp_table
*)(prn
->info
);
3427 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3428 bgp
, prd
, table
, p
, new);
3430 bgp_unlock_node(prn
);
3434 /* If maximum prefix count is configured and current prefix
3436 if (bgp_maximum_prefix_overflow(peer
, afi
, safi
, 0))
3439 /* If this is an EVPN route, process for import. */
3440 if (safi
== SAFI_EVPN
)
3441 bgp_evpn_import_route(bgp
, afi
, safi
, p
, new);
3443 /* Process change. */
3444 bgp_process(bgp
, rn
, afi
, safi
);
3446 if (SAFI_UNICAST
== safi
3447 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3448 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3449 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
3451 if ((SAFI_MPLS_VPN
== safi
)
3452 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3454 vpn_leak_to_vrf_update(bgp
, new);
3457 if (SAFI_MPLS_VPN
== safi
) {
3458 mpls_label_t label_decoded
= decode_label(label
);
3460 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3461 sub_type
, &label_decoded
);
3463 if (SAFI_ENCAP
== safi
) {
3464 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3471 /* This BGP update is filtered. Log the reason then update BGP
3474 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3475 if (!peer
->rcvd_attr_printed
) {
3476 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3477 peer
->rcvd_attr_str
);
3478 peer
->rcvd_attr_printed
= 1;
3481 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3482 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3484 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
3485 peer
->host
, pfx_buf
, reason
);
3489 /* If this is an EVPN route, un-import it as it is now filtered.
3491 if (safi
== SAFI_EVPN
)
3492 bgp_evpn_unimport_route(bgp
, afi
, safi
, p
, ri
);
3494 if (SAFI_UNICAST
== safi
3495 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3496 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3498 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, ri
);
3500 if ((SAFI_MPLS_VPN
== safi
)
3501 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3503 vpn_leak_to_vrf_withdraw(bgp
, ri
);
3506 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
3509 bgp_unlock_node(rn
);
3513 * Filtered update is treated as an implicit withdrawal (see
3515 * a few lines above)
3517 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3518 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3526 int bgp_withdraw(struct peer
*peer
, struct prefix
*p
, uint32_t addpath_id
,
3527 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
3528 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
3529 uint32_t num_labels
, struct bgp_route_evpn
*evpn
)
3532 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
3533 struct bgp_node
*rn
;
3534 struct bgp_info
*ri
;
3537 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3538 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3546 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
3548 /* If peer is soft reconfiguration enabled. Record input packet for
3549 * further calculation.
3551 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
3552 * routes that are filtered. This tanks out Quagga RS pretty badly due
3554 * the iteration over all RS clients.
3555 * Since we need to remove the entry from adj_in anyway, do that first
3557 * if there was no entry, we don't need to do anything more.
3559 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
3560 && peer
!= bgp
->peer_self
)
3561 if (!bgp_adj_in_unset(rn
, peer
, addpath_id
)) {
3562 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3563 bgp_debug_rdpfxpath2str(
3564 afi
, safi
, prd
, p
, label
, num_labels
,
3565 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3568 "%s withdrawing route %s not in adj-in",
3569 peer
->host
, pfx_buf
);
3571 bgp_unlock_node(rn
);
3575 /* Lookup withdrawn route. */
3576 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
3577 if (ri
->peer
== peer
&& ri
->type
== type
3578 && ri
->sub_type
== sub_type
3579 && ri
->addpath_rx_id
== addpath_id
)
3583 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3584 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3585 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3587 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer
->host
,
3591 /* Withdraw specified route from routing table. */
3592 if (ri
&& !CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
)) {
3593 bgp_rib_withdraw(rn
, ri
, peer
, afi
, safi
, prd
);
3594 if (SAFI_UNICAST
== safi
3595 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3596 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3597 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, ri
);
3599 if ((SAFI_MPLS_VPN
== safi
)
3600 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3602 vpn_leak_to_vrf_withdraw(bgp
, ri
);
3604 } else if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3605 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3606 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3608 zlog_debug("%s Can't find the route %s", peer
->host
, pfx_buf
);
3611 /* Unlock bgp_node_get() lock. */
3612 bgp_unlock_node(rn
);
3617 void bgp_default_originate(struct peer
*peer
, afi_t afi
, safi_t safi
,
3620 struct update_subgroup
*subgrp
;
3621 subgrp
= peer_subgroup(peer
, afi
, safi
);
3622 subgroup_default_originate(subgrp
, withdraw
);
3627 * bgp_stop_announce_route_timer
3629 void bgp_stop_announce_route_timer(struct peer_af
*paf
)
3631 if (!paf
->t_announce_route
)
3634 THREAD_TIMER_OFF(paf
->t_announce_route
);
3638 * bgp_announce_route_timer_expired
3640 * Callback that is invoked when the route announcement timer for a
3643 static int bgp_announce_route_timer_expired(struct thread
*t
)
3645 struct peer_af
*paf
;
3648 paf
= THREAD_ARG(t
);
3651 if (peer
->status
!= Established
)
3654 if (!peer
->afc_nego
[paf
->afi
][paf
->safi
])
3657 peer_af_announce_route(paf
, 1);
3662 * bgp_announce_route
3664 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
3666 void bgp_announce_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
3668 struct peer_af
*paf
;
3669 struct update_subgroup
*subgrp
;
3671 paf
= peer_af_find(peer
, afi
, safi
);
3674 subgrp
= PAF_SUBGRP(paf
);
3677 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
3678 * or a refresh has already been triggered.
3680 if (!subgrp
|| paf
->t_announce_route
)
3684 * Start a timer to stagger/delay the announce. This serves
3685 * two purposes - announcement can potentially be combined for
3686 * multiple peers and the announcement doesn't happen in the
3689 thread_add_timer_msec(bm
->master
, bgp_announce_route_timer_expired
, paf
,
3690 (subgrp
->peer_count
== 1)
3691 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
3692 : BGP_ANNOUNCE_ROUTE_DELAY_MS
,
3693 &paf
->t_announce_route
);
3697 * Announce routes from all AF tables to a peer.
3699 * This should ONLY be called when there is a need to refresh the
3700 * routes to the peer based on a policy change for this peer alone
3701 * or a route refresh request received from the peer.
3702 * The operation will result in splitting the peer from its existing
3703 * subgroups and putting it in new subgroups.
3705 void bgp_announce_route_all(struct peer
*peer
)
3710 FOREACH_AFI_SAFI (afi
, safi
)
3711 bgp_announce_route(peer
, afi
, safi
);
3714 static void bgp_soft_reconfig_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
3715 struct bgp_table
*table
,
3716 struct prefix_rd
*prd
)
3719 struct bgp_node
*rn
;
3720 struct bgp_adj_in
*ain
;
3723 table
= peer
->bgp
->rib
[afi
][safi
];
3725 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
3726 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
3727 if (ain
->peer
!= peer
)
3730 struct bgp_info
*ri
= rn
->info
;
3731 uint32_t num_labels
= 0;
3732 mpls_label_t
*label_pnt
= NULL
;
3734 if (ri
&& ri
->extra
)
3735 num_labels
= ri
->extra
->num_labels
;
3737 label_pnt
= &ri
->extra
->label
[0];
3739 ret
= bgp_update(peer
, &rn
->p
, ain
->addpath_rx_id
,
3740 ain
->attr
, afi
, safi
, ZEBRA_ROUTE_BGP
,
3741 BGP_ROUTE_NORMAL
, prd
, label_pnt
,
3742 num_labels
, 1, NULL
);
3745 bgp_unlock_node(rn
);
3751 void bgp_soft_reconfig_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
3753 struct bgp_node
*rn
;
3754 struct bgp_table
*table
;
3756 if (peer
->status
!= Established
)
3759 if ((safi
!= SAFI_MPLS_VPN
) && (safi
!= SAFI_ENCAP
)
3760 && (safi
!= SAFI_EVPN
))
3761 bgp_soft_reconfig_table(peer
, afi
, safi
, NULL
, NULL
);
3763 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
3764 rn
= bgp_route_next(rn
))
3765 if ((table
= rn
->info
) != NULL
) {
3766 struct prefix_rd prd
;
3767 prd
.family
= AF_UNSPEC
;
3769 memcpy(&prd
.val
, rn
->p
.u
.val
, 8);
3771 bgp_soft_reconfig_table(peer
, afi
, safi
, table
,
3777 struct bgp_clear_node_queue
{
3778 struct bgp_node
*rn
;
3781 static wq_item_status
bgp_clear_route_node(struct work_queue
*wq
, void *data
)
3783 struct bgp_clear_node_queue
*cnq
= data
;
3784 struct bgp_node
*rn
= cnq
->rn
;
3785 struct peer
*peer
= wq
->spec
.data
;
3786 struct bgp_info
*ri
;
3788 afi_t afi
= bgp_node_table(rn
)->afi
;
3789 safi_t safi
= bgp_node_table(rn
)->safi
;
3794 /* It is possible that we have multiple paths for a prefix from a peer
3795 * if that peer is using AddPath.
3797 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
3798 if (ri
->peer
!= peer
)
3801 /* graceful restart STALE flag set. */
3802 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_NSF_WAIT
)
3803 && peer
->nsf
[afi
][safi
]
3804 && !CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
)
3805 && !CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
3806 bgp_info_set_flag(rn
, ri
, BGP_INFO_STALE
);
3808 /* If this is an EVPN route, process for
3810 if (safi
== SAFI_EVPN
)
3811 bgp_evpn_unimport_route(bgp
, afi
, safi
,
3813 /* Handle withdraw for VRF route-leaking and L3VPN */
3814 if (SAFI_UNICAST
== safi
3815 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
||
3816 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3817 vpn_leak_from_vrf_withdraw(bgp_get_default(),
3820 if (SAFI_MPLS_VPN
== safi
&&
3821 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
3822 vpn_leak_to_vrf_withdraw(bgp
, ri
);
3825 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
3831 static void bgp_clear_node_queue_del(struct work_queue
*wq
, void *data
)
3833 struct bgp_clear_node_queue
*cnq
= data
;
3834 struct bgp_node
*rn
= cnq
->rn
;
3835 struct bgp_table
*table
= bgp_node_table(rn
);
3837 bgp_unlock_node(rn
);
3838 bgp_table_unlock(table
);
3839 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE
, cnq
);
3842 static void bgp_clear_node_complete(struct work_queue
*wq
)
3844 struct peer
*peer
= wq
->spec
.data
;
3846 /* Tickle FSM to start moving again */
3847 BGP_EVENT_ADD(peer
, Clearing_Completed
);
3849 peer_unlock(peer
); /* bgp_clear_route */
3852 static void bgp_clear_node_queue_init(struct peer
*peer
)
3854 char wname
[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
3856 snprintf(wname
, sizeof(wname
), "clear %s", peer
->host
);
3857 #undef CLEAR_QUEUE_NAME_LEN
3859 peer
->clear_node_queue
= work_queue_new(bm
->master
, wname
);
3860 peer
->clear_node_queue
->spec
.hold
= 10;
3861 peer
->clear_node_queue
->spec
.workfunc
= &bgp_clear_route_node
;
3862 peer
->clear_node_queue
->spec
.del_item_data
= &bgp_clear_node_queue_del
;
3863 peer
->clear_node_queue
->spec
.completion_func
= &bgp_clear_node_complete
;
3864 peer
->clear_node_queue
->spec
.max_retries
= 0;
3866 /* we only 'lock' this peer reference when the queue is actually active
3868 peer
->clear_node_queue
->spec
.data
= peer
;
3871 static void bgp_clear_route_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
3872 struct bgp_table
*table
)
3874 struct bgp_node
*rn
;
3875 int force
= bm
->process_main_queue
? 0 : 1;
3878 table
= peer
->bgp
->rib
[afi
][safi
];
3880 /* If still no table => afi/safi isn't configured at all or smth. */
3884 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
3885 struct bgp_info
*ri
, *next
;
3886 struct bgp_adj_in
*ain
;
3887 struct bgp_adj_in
*ain_next
;
3889 /* XXX:TODO: This is suboptimal, every non-empty route_node is
3890 * queued for every clearing peer, regardless of whether it is
3891 * relevant to the peer at hand.
3893 * Overview: There are 3 different indices which need to be
3894 * scrubbed, potentially, when a peer is removed:
3896 * 1 peer's routes visible via the RIB (ie accepted routes)
3897 * 2 peer's routes visible by the (optional) peer's adj-in index
3898 * 3 other routes visible by the peer's adj-out index
3900 * 3 there is no hurry in scrubbing, once the struct peer is
3901 * removed from bgp->peer, we could just GC such deleted peer's
3902 * adj-outs at our leisure.
3904 * 1 and 2 must be 'scrubbed' in some way, at least made
3905 * invisible via RIB index before peer session is allowed to be
3906 * brought back up. So one needs to know when such a 'search' is
3911 * - there'd be a single global queue or a single RIB walker
3912 * - rather than tracking which route_nodes still need to be
3913 * examined on a peer basis, we'd track which peers still
3916 * Given that our per-peer prefix-counts now should be reliable,
3917 * this may actually be achievable. It doesn't seem to be a huge
3918 * problem at this time,
3920 * It is possible that we have multiple paths for a prefix from
3922 * if that peer is using AddPath.
3926 ain_next
= ain
->next
;
3928 if (ain
->peer
== peer
) {
3929 bgp_adj_in_remove(rn
, ain
);
3930 bgp_unlock_node(rn
);
3936 for (ri
= rn
->info
; ri
; ri
= next
) {
3938 if (ri
->peer
!= peer
)
3942 bgp_info_reap(rn
, ri
);
3944 struct bgp_clear_node_queue
*cnq
;
3946 /* both unlocked in bgp_clear_node_queue_del */
3947 bgp_table_lock(bgp_node_table(rn
));
3950 MTYPE_BGP_CLEAR_NODE_QUEUE
,
3951 sizeof(struct bgp_clear_node_queue
));
3953 work_queue_add(peer
->clear_node_queue
, cnq
);
3961 void bgp_clear_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
3963 struct bgp_node
*rn
;
3964 struct bgp_table
*table
;
3966 if (peer
->clear_node_queue
== NULL
)
3967 bgp_clear_node_queue_init(peer
);
3969 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
3970 * Idle until it receives a Clearing_Completed event. This protects
3971 * against peers which flap faster than we can we clear, which could
3974 * a) race with routes from the new session being installed before
3975 * clear_route_node visits the node (to delete the route of that
3977 * b) resource exhaustion, clear_route_node likely leads to an entry
3978 * on the process_main queue. Fast-flapping could cause that queue
3982 /* lock peer in assumption that clear-node-queue will get nodes; if so,
3983 * the unlock will happen upon work-queue completion; other wise, the
3984 * unlock happens at the end of this function.
3986 if (!peer
->clear_node_queue
->thread
)
3989 if (safi
!= SAFI_MPLS_VPN
&& safi
!= SAFI_ENCAP
&& safi
!= SAFI_EVPN
)
3990 bgp_clear_route_table(peer
, afi
, safi
, NULL
);
3992 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
3993 rn
= bgp_route_next(rn
))
3994 if ((table
= rn
->info
) != NULL
)
3995 bgp_clear_route_table(peer
, afi
, safi
, table
);
3997 /* unlock if no nodes got added to the clear-node-queue. */
3998 if (!peer
->clear_node_queue
->thread
)
4002 void bgp_clear_route_all(struct peer
*peer
)
4007 FOREACH_AFI_SAFI (afi
, safi
)
4008 bgp_clear_route(peer
, afi
, safi
);
4011 rfapiProcessPeerDown(peer
);
4015 void bgp_clear_adj_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
4017 struct bgp_table
*table
;
4018 struct bgp_node
*rn
;
4019 struct bgp_adj_in
*ain
;
4020 struct bgp_adj_in
*ain_next
;
4022 table
= peer
->bgp
->rib
[afi
][safi
];
4024 /* It is possible that we have multiple paths for a prefix from a peer
4025 * if that peer is using AddPath.
4027 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
4031 ain_next
= ain
->next
;
4033 if (ain
->peer
== peer
) {
4034 bgp_adj_in_remove(rn
, ain
);
4035 bgp_unlock_node(rn
);
4043 void bgp_clear_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4045 struct bgp_node
*rn
;
4046 struct bgp_info
*ri
;
4047 struct bgp_table
*table
;
4049 if (safi
== SAFI_MPLS_VPN
) {
4050 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4051 rn
= bgp_route_next(rn
)) {
4052 struct bgp_node
*rm
;
4054 /* look for neighbor in tables */
4055 if ((table
= rn
->info
) == NULL
)
4058 for (rm
= bgp_table_top(table
); rm
;
4059 rm
= bgp_route_next(rm
))
4060 for (ri
= rm
->info
; ri
; ri
= ri
->next
) {
4061 if (ri
->peer
!= peer
)
4063 if (!CHECK_FLAG(ri
->flags
,
4067 bgp_rib_remove(rm
, ri
, peer
, afi
, safi
);
4072 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4073 rn
= bgp_route_next(rn
))
4074 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
4075 if (ri
->peer
!= peer
)
4077 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
))
4079 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
4085 static void bgp_cleanup_table(struct bgp
*bgp
, struct bgp_table
*table
,
4088 struct bgp_node
*rn
;
4089 struct bgp_info
*ri
;
4090 struct bgp_info
*next
;
4092 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
4093 for (ri
= rn
->info
; ri
; ri
= next
) {
4095 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)
4096 && ri
->type
== ZEBRA_ROUTE_BGP
4097 && (ri
->sub_type
== BGP_ROUTE_NORMAL
4098 || ri
->sub_type
== BGP_ROUTE_AGGREGATE
4099 || ri
->sub_type
== BGP_ROUTE_IMPORTED
)) {
4101 if (bgp_fibupd_safi(safi
))
4102 bgp_zebra_withdraw(&rn
->p
, ri
,
4104 bgp_info_reap(rn
, ri
);
4109 /* Delete all kernel routes. */
4110 void bgp_cleanup_routes(struct bgp
*bgp
)
4113 struct bgp_node
*rn
;
4115 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
4116 if (afi
== AFI_L2VPN
)
4118 bgp_cleanup_table(bgp
, bgp
->rib
[afi
][SAFI_UNICAST
],
4121 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
4123 if (afi
!= AFI_L2VPN
) {
4125 safi
= SAFI_MPLS_VPN
;
4126 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4127 rn
= bgp_route_next(rn
)) {
4129 bgp_cleanup_table(bgp
,
4130 (struct bgp_table
*)(rn
->info
),
4132 bgp_table_finish((struct bgp_table
**)&(
4135 bgp_unlock_node(rn
);
4139 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4140 rn
= bgp_route_next(rn
)) {
4142 bgp_cleanup_table(bgp
,
4143 (struct bgp_table
*)(rn
->info
),
4145 bgp_table_finish((struct bgp_table
**)&(
4148 bgp_unlock_node(rn
);
4153 for (rn
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); rn
;
4154 rn
= bgp_route_next(rn
)) {
4156 bgp_cleanup_table(bgp
,
4157 (struct bgp_table
*)(rn
->info
),
4159 bgp_table_finish((struct bgp_table
**)&(rn
->info
));
4161 bgp_unlock_node(rn
);
4166 void bgp_reset(void)
4169 bgp_zclient_reset();
4170 access_list_reset();
4171 prefix_list_reset();
4174 static int bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
4176 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
4177 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
4178 PEER_CAP_ADDPATH_AF_TX_RCV
));
4181 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
4183 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
4184 struct bgp_nlri
*packet
)
4193 int addpath_encoded
;
4194 uint32_t addpath_id
;
4197 lim
= pnt
+ packet
->length
;
4199 safi
= packet
->safi
;
4201 addpath_encoded
= bgp_addpath_encode_rx(peer
, afi
, safi
);
4203 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
4204 syntactic validity. If the field is syntactically incorrect,
4205 then the Error Subcode is set to Invalid Network Field. */
4206 for (; pnt
< lim
; pnt
+= psize
) {
4207 /* Clear prefix structure. */
4208 memset(&p
, 0, sizeof(struct prefix
));
4210 if (addpath_encoded
) {
4212 /* When packet overflow occurs return immediately. */
4213 if (pnt
+ BGP_ADDPATH_ID_LEN
> lim
)
4216 addpath_id
= ntohl(*((uint32_t *)pnt
));
4217 pnt
+= BGP_ADDPATH_ID_LEN
;
4220 /* Fetch prefix length. */
4221 p
.prefixlen
= *pnt
++;
4222 /* afi/safi validity already verified by caller,
4223 * bgp_update_receive */
4224 p
.family
= afi2family(afi
);
4226 /* Prefix length check. */
4227 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
4230 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
4231 peer
->host
, p
.prefixlen
, packet
->afi
);
4235 /* Packet size overflow check. */
4236 psize
= PSIZE(p
.prefixlen
);
4238 /* When packet overflow occur return immediately. */
4239 if (pnt
+ psize
> lim
) {
4242 "%s [Error] Update packet error (prefix length %d overflows packet)",
4243 peer
->host
, p
.prefixlen
);
4247 /* Defensive coding, double-check the psize fits in a struct
4249 if (psize
> (ssize_t
)sizeof(p
.u
)) {
4252 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
4253 peer
->host
, p
.prefixlen
, sizeof(p
.u
));
4257 /* Fetch prefix from NLRI packet. */
4258 memcpy(p
.u
.val
, pnt
, psize
);
4260 /* Check address. */
4261 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
4262 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
4263 /* From RFC4271 Section 6.3:
4265 * If a prefix in the NLRI field is semantically
4267 * (e.g., an unexpected multicast IP address),
4269 * be logged locally, and the prefix SHOULD be
4274 "%s: IPv4 unicast NLRI is multicast address %s, ignoring",
4275 peer
->host
, inet_ntoa(p
.u
.prefix4
));
4280 /* Check address. */
4281 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
4282 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4287 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
4289 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4294 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
4299 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
4301 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4308 /* Normal process. */
4310 ret
= bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
4311 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
4312 NULL
, NULL
, 0, 0, NULL
);
4314 ret
= bgp_withdraw(peer
, &p
, addpath_id
, attr
, afi
,
4315 safi
, ZEBRA_ROUTE_BGP
,
4316 BGP_ROUTE_NORMAL
, NULL
, NULL
, 0,
4319 /* Address family configuration mismatch or maximum-prefix count
4325 /* Packet length consistency check. */
4329 "%s [Error] Update packet error (prefix length mismatch with total length)",
4337 static struct bgp_static
*bgp_static_new(void)
4339 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
4342 static void bgp_static_free(struct bgp_static
*bgp_static
)
4344 if (bgp_static
->rmap
.name
)
4345 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
4346 if (bgp_static
->eth_s_id
)
4347 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
4348 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
4351 void bgp_static_update(struct bgp
*bgp
, struct prefix
*p
,
4352 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
4354 struct bgp_node
*rn
;
4355 struct bgp_info
*ri
;
4356 struct bgp_info
*new;
4357 struct bgp_info info
;
4359 struct attr
*attr_new
;
4362 int vnc_implicit_withdraw
= 0;
4369 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4371 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4373 attr
.nexthop
= bgp_static
->igpnexthop
;
4374 attr
.med
= bgp_static
->igpmetric
;
4375 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4377 if (bgp_static
->atomic
)
4378 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
4380 /* Store label index, if required. */
4381 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
4382 attr
.label_index
= bgp_static
->label_index
;
4383 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
4386 /* Apply route-map. */
4387 if (bgp_static
->rmap
.name
) {
4388 struct attr attr_tmp
= attr
;
4390 memset(&info
, 0, sizeof(struct bgp_info
));
4391 info
.peer
= bgp
->peer_self
;
4392 info
.attr
= &attr_tmp
;
4394 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4396 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
, &info
);
4398 bgp
->peer_self
->rmap_type
= 0;
4400 if (ret
== RMAP_DENYMATCH
) {
4401 /* Free uninterned attribute. */
4402 bgp_attr_flush(&attr_tmp
);
4404 /* Unintern original. */
4405 aspath_unintern(&attr
.aspath
);
4406 bgp_static_withdraw(bgp
, p
, afi
, safi
);
4410 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4411 bgp_attr_add_gshut_community(&attr_tmp
);
4413 attr_new
= bgp_attr_intern(&attr_tmp
);
4416 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4417 bgp_attr_add_gshut_community(&attr
);
4419 attr_new
= bgp_attr_intern(&attr
);
4422 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4423 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4424 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4428 if (attrhash_cmp(ri
->attr
, attr_new
)
4429 && !CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)
4430 && !bgp_flag_check(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
4431 bgp_unlock_node(rn
);
4432 bgp_attr_unintern(&attr_new
);
4433 aspath_unintern(&attr
.aspath
);
4436 /* The attribute is changed. */
4437 bgp_info_set_flag(rn
, ri
, BGP_INFO_ATTR_CHANGED
);
4439 /* Rewrite BGP route information. */
4440 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
))
4441 bgp_info_restore(rn
, ri
);
4443 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4445 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4446 && (safi
== SAFI_UNICAST
)) {
4447 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
4449 * Implicit withdraw case.
4450 * We have to do this before ri is
4453 ++vnc_implicit_withdraw
;
4454 vnc_import_bgp_del_route(bgp
, p
, ri
);
4455 vnc_import_bgp_exterior_del_route(
4460 bgp_attr_unintern(&ri
->attr
);
4461 ri
->attr
= attr_new
;
4462 ri
->uptime
= bgp_clock();
4464 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4465 && (safi
== SAFI_UNICAST
)) {
4466 if (vnc_implicit_withdraw
) {
4467 vnc_import_bgp_add_route(bgp
, p
, ri
);
4468 vnc_import_bgp_exterior_add_route(
4474 /* Nexthop reachability check. */
4475 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4476 && (safi
== SAFI_UNICAST
4477 || safi
== SAFI_LABELED_UNICAST
)) {
4479 struct bgp
*bgp_nexthop
= bgp
;
4481 if (ri
->extra
&& ri
->extra
->bgp_orig
)
4482 bgp_nexthop
= ri
->extra
->bgp_orig
;
4484 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
,
4486 bgp_info_set_flag(rn
, ri
,
4489 if (BGP_DEBUG(nht
, NHT
)) {
4490 char buf1
[INET6_ADDRSTRLEN
];
4491 inet_ntop(p
->family
,
4495 "%s(%s): Route not in table, not advertising",
4496 __FUNCTION__
, buf1
);
4498 bgp_info_unset_flag(rn
, ri
,
4502 /* Delete the NHT structure if any, if we're
4504 * enabling/disabling import check. We
4505 * deregister the route
4506 * from NHT to avoid overloading NHT and the
4507 * process interaction
4509 bgp_unlink_nexthop(ri
);
4510 bgp_info_set_flag(rn
, ri
, BGP_INFO_VALID
);
4512 /* Process change. */
4513 bgp_aggregate_increment(bgp
, p
, ri
, afi
, safi
);
4514 bgp_process(bgp
, rn
, afi
, safi
);
4516 if (SAFI_UNICAST
== safi
4517 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4519 == BGP_INSTANCE_TYPE_DEFAULT
)) {
4520 vpn_leak_from_vrf_update(bgp_get_default(), bgp
,
4524 bgp_unlock_node(rn
);
4525 aspath_unintern(&attr
.aspath
);
4530 /* Make new BGP info. */
4531 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
4533 /* Nexthop reachability check. */
4534 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4535 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
4536 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, new, NULL
, 0))
4537 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
4539 if (BGP_DEBUG(nht
, NHT
)) {
4540 char buf1
[INET6_ADDRSTRLEN
];
4541 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
4544 "%s(%s): Route not in table, not advertising",
4545 __FUNCTION__
, buf1
);
4547 bgp_info_unset_flag(rn
, new, BGP_INFO_VALID
);
4550 /* Delete the NHT structure if any, if we're toggling between
4551 * enabling/disabling import check. We deregister the route
4552 * from NHT to avoid overloading NHT and the process interaction
4554 bgp_unlink_nexthop(new);
4556 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
4559 /* Aggregate address increment. */
4560 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4562 /* Register new BGP information. */
4563 bgp_info_add(rn
, new);
4565 /* route_node_get lock */
4566 bgp_unlock_node(rn
);
4568 /* Process change. */
4569 bgp_process(bgp
, rn
, afi
, safi
);
4571 if (SAFI_UNICAST
== safi
4572 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4573 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4574 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
4577 /* Unintern original. */
4578 aspath_unintern(&attr
.aspath
);
4581 void bgp_static_withdraw(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
4584 struct bgp_node
*rn
;
4585 struct bgp_info
*ri
;
4587 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4589 /* Check selected route and self inserted route. */
4590 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4591 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4592 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4595 /* Withdraw static BGP route from routing table. */
4597 if (SAFI_UNICAST
== safi
4598 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4599 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4600 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, ri
);
4602 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4603 bgp_unlink_nexthop(ri
);
4604 bgp_info_delete(rn
, ri
);
4605 bgp_process(bgp
, rn
, afi
, safi
);
4608 /* Unlock bgp_node_lookup. */
4609 bgp_unlock_node(rn
);
4613 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
4615 static void bgp_static_withdraw_safi(struct bgp
*bgp
, struct prefix
*p
,
4616 afi_t afi
, safi_t safi
,
4617 struct prefix_rd
*prd
)
4619 struct bgp_node
*rn
;
4620 struct bgp_info
*ri
;
4622 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4624 /* Check selected route and self inserted route. */
4625 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4626 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4627 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4630 /* Withdraw static BGP route from routing table. */
4633 rfapiProcessWithdraw(
4634 ri
->peer
, NULL
, p
, prd
, ri
->attr
, afi
, safi
, ri
->type
,
4635 1); /* Kill, since it is an administrative change */
4637 if (SAFI_MPLS_VPN
== safi
4638 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4639 vpn_leak_to_vrf_withdraw(bgp
, ri
);
4641 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4642 bgp_info_delete(rn
, ri
);
4643 bgp_process(bgp
, rn
, afi
, safi
);
4646 /* Unlock bgp_node_lookup. */
4647 bgp_unlock_node(rn
);
4650 static void bgp_static_update_safi(struct bgp
*bgp
, struct prefix
*p
,
4651 struct bgp_static
*bgp_static
, afi_t afi
,
4654 struct bgp_node
*rn
;
4655 struct bgp_info
*new;
4656 struct attr
*attr_new
;
4657 struct attr attr
= {0};
4658 struct bgp_info
*ri
;
4660 mpls_label_t label
= 0;
4662 uint32_t num_labels
= 0;
4667 if (bgp_static
->label
!= MPLS_INVALID_LABEL
)
4669 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
4672 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4674 attr
.nexthop
= bgp_static
->igpnexthop
;
4675 attr
.med
= bgp_static
->igpmetric
;
4676 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4678 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
4679 || (safi
== SAFI_ENCAP
)) {
4680 if (afi
== AFI_IP
) {
4681 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
4682 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
4685 if (afi
== AFI_L2VPN
) {
4686 if (bgp_static
->gatewayIp
.family
== AF_INET
)
4688 bgp_static
->gatewayIp
.u
.prefix4
.s_addr
;
4689 else if (bgp_static
->gatewayIp
.family
== AF_INET6
)
4690 memcpy(&(add
.ipv6
), &(bgp_static
->gatewayIp
.u
.prefix6
),
4691 sizeof(struct in6_addr
));
4692 overlay_index_update(&attr
, bgp_static
->eth_s_id
, &add
);
4693 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
4694 struct bgp_encap_type_vxlan bet
;
4695 memset(&bet
, 0, sizeof(struct bgp_encap_type_vxlan
));
4696 bet
.vnid
= p
->u
.prefix_evpn
.prefix_addr
.eth_tag
;
4697 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
4699 if (bgp_static
->router_mac
) {
4700 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
4703 /* Apply route-map. */
4704 if (bgp_static
->rmap
.name
) {
4705 struct attr attr_tmp
= attr
;
4706 struct bgp_info info
;
4709 info
.peer
= bgp
->peer_self
;
4710 info
.attr
= &attr_tmp
;
4712 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4714 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
, &info
);
4716 bgp
->peer_self
->rmap_type
= 0;
4718 if (ret
== RMAP_DENYMATCH
) {
4719 /* Free uninterned attribute. */
4720 bgp_attr_flush(&attr_tmp
);
4722 /* Unintern original. */
4723 aspath_unintern(&attr
.aspath
);
4724 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
4729 attr_new
= bgp_attr_intern(&attr_tmp
);
4731 attr_new
= bgp_attr_intern(&attr
);
4734 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4735 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4736 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4740 memset(&add
, 0, sizeof(union gw_addr
));
4741 if (attrhash_cmp(ri
->attr
, attr_new
)
4742 && overlay_index_equal(afi
, ri
, bgp_static
->eth_s_id
, &add
)
4743 && !CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)) {
4744 bgp_unlock_node(rn
);
4745 bgp_attr_unintern(&attr_new
);
4746 aspath_unintern(&attr
.aspath
);
4749 /* The attribute is changed. */
4750 bgp_info_set_flag(rn
, ri
, BGP_INFO_ATTR_CHANGED
);
4752 /* Rewrite BGP route information. */
4753 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
))
4754 bgp_info_restore(rn
, ri
);
4756 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4757 bgp_attr_unintern(&ri
->attr
);
4758 ri
->attr
= attr_new
;
4759 ri
->uptime
= bgp_clock();
4762 label
= decode_label(&ri
->extra
->label
[0]);
4765 /* Process change. */
4766 bgp_aggregate_increment(bgp
, p
, ri
, afi
, safi
);
4767 bgp_process(bgp
, rn
, afi
, safi
);
4769 if (SAFI_MPLS_VPN
== safi
4770 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4771 vpn_leak_to_vrf_update(bgp
, ri
);
4774 rfapiProcessUpdate(ri
->peer
, NULL
, p
, &bgp_static
->prd
,
4775 ri
->attr
, afi
, safi
, ri
->type
,
4776 ri
->sub_type
, &label
);
4778 bgp_unlock_node(rn
);
4779 aspath_unintern(&attr
.aspath
);
4785 /* Make new BGP info. */
4786 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
4788 SET_FLAG(new->flags
, BGP_INFO_VALID
);
4789 new->extra
= bgp_info_extra_new();
4791 new->extra
->label
[0] = bgp_static
->label
;
4792 new->extra
->num_labels
= num_labels
;
4795 label
= decode_label(&bgp_static
->label
);
4798 /* Aggregate address increment. */
4799 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4801 /* Register new BGP information. */
4802 bgp_info_add(rn
, new);
4803 /* route_node_get lock */
4804 bgp_unlock_node(rn
);
4806 /* Process change. */
4807 bgp_process(bgp
, rn
, afi
, safi
);
4809 if (SAFI_MPLS_VPN
== safi
4810 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4811 vpn_leak_to_vrf_update(bgp
, new);
4814 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
4815 safi
, new->type
, new->sub_type
, &label
);
4818 /* Unintern original. */
4819 aspath_unintern(&attr
.aspath
);
4822 /* Configure static BGP network. When user don't run zebra, static
4823 route should be installed as valid. */
4824 static int bgp_static_set(struct vty
*vty
, const char *negate
,
4825 const char *ip_str
, afi_t afi
, safi_t safi
,
4826 const char *rmap
, int backdoor
, uint32_t label_index
)
4828 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
4831 struct bgp_static
*bgp_static
;
4832 struct bgp_node
*rn
;
4833 uint8_t need_update
= 0;
4835 /* Convert IP prefix string to struct prefix. */
4836 ret
= str2prefix(ip_str
, &p
);
4838 vty_out(vty
, "%% Malformed prefix\n");
4839 return CMD_WARNING_CONFIG_FAILED
;
4841 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4842 vty_out(vty
, "%% Malformed prefix (link-local address)\n");
4843 return CMD_WARNING_CONFIG_FAILED
;
4850 /* Set BGP static route configuration. */
4851 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
4854 vty_out(vty
, "%% Can't find static route specified\n");
4855 return CMD_WARNING_CONFIG_FAILED
;
4858 bgp_static
= bgp_static_get_node_info(rn
);
4860 if ((label_index
!= BGP_INVALID_LABEL_INDEX
)
4861 && (label_index
!= bgp_static
->label_index
)) {
4863 "%% label-index doesn't match static route\n");
4864 return CMD_WARNING_CONFIG_FAILED
;
4867 if ((rmap
&& bgp_static
->rmap
.name
)
4868 && strcmp(rmap
, bgp_static
->rmap
.name
)) {
4870 "%% route-map name doesn't match static route\n");
4871 return CMD_WARNING_CONFIG_FAILED
;
4874 /* Update BGP RIB. */
4875 if (!bgp_static
->backdoor
)
4876 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
4878 /* Clear configuration. */
4879 bgp_static_free(bgp_static
);
4880 bgp_static_set_node_info(rn
, NULL
);
4881 bgp_unlock_node(rn
);
4882 bgp_unlock_node(rn
);
4885 /* Set BGP static route configuration. */
4886 rn
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
4888 bgp_static
= bgp_static_get_node_info(rn
);
4890 /* Configuration change. */
4891 /* Label index cannot be changed. */
4892 if (bgp_static
->label_index
!= label_index
) {
4893 vty_out(vty
, "%% cannot change label-index\n");
4894 return CMD_WARNING_CONFIG_FAILED
;
4897 /* Check previous routes are installed into BGP. */
4898 if (bgp_static
->valid
4899 && bgp_static
->backdoor
!= backdoor
)
4902 bgp_static
->backdoor
= backdoor
;
4905 if (bgp_static
->rmap
.name
)
4906 XFREE(MTYPE_ROUTE_MAP_NAME
,
4907 bgp_static
->rmap
.name
);
4908 bgp_static
->rmap
.name
=
4909 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
4910 bgp_static
->rmap
.map
=
4911 route_map_lookup_by_name(rmap
);
4913 if (bgp_static
->rmap
.name
)
4914 XFREE(MTYPE_ROUTE_MAP_NAME
,
4915 bgp_static
->rmap
.name
);
4916 bgp_static
->rmap
.name
= NULL
;
4917 bgp_static
->rmap
.map
= NULL
;
4918 bgp_static
->valid
= 0;
4920 bgp_unlock_node(rn
);
4922 /* New configuration. */
4923 bgp_static
= bgp_static_new();
4924 bgp_static
->backdoor
= backdoor
;
4925 bgp_static
->valid
= 0;
4926 bgp_static
->igpmetric
= 0;
4927 bgp_static
->igpnexthop
.s_addr
= 0;
4928 bgp_static
->label_index
= label_index
;
4931 if (bgp_static
->rmap
.name
)
4932 XFREE(MTYPE_ROUTE_MAP_NAME
,
4933 bgp_static
->rmap
.name
);
4934 bgp_static
->rmap
.name
=
4935 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
4936 bgp_static
->rmap
.map
=
4937 route_map_lookup_by_name(rmap
);
4939 bgp_static_set_node_info(rn
, bgp_static
);
4942 bgp_static
->valid
= 1;
4944 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
4946 if (!bgp_static
->backdoor
)
4947 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
4953 void bgp_static_add(struct bgp
*bgp
)
4957 struct bgp_node
*rn
;
4958 struct bgp_node
*rm
;
4959 struct bgp_table
*table
;
4960 struct bgp_static
*bgp_static
;
4962 FOREACH_AFI_SAFI (afi
, safi
)
4963 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
4964 rn
= bgp_route_next(rn
)) {
4965 if (rn
->info
== NULL
)
4968 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
4969 || (safi
== SAFI_EVPN
)) {
4972 for (rm
= bgp_table_top(table
); rm
;
4973 rm
= bgp_route_next(rm
)) {
4975 bgp_static_get_node_info(rm
);
4976 bgp_static_update_safi(bgp
, &rm
->p
,
4981 bgp_static_update(bgp
, &rn
->p
,
4982 bgp_static_get_node_info(rn
),
4988 /* Called from bgp_delete(). Delete all static routes from the BGP
4990 void bgp_static_delete(struct bgp
*bgp
)
4994 struct bgp_node
*rn
;
4995 struct bgp_node
*rm
;
4996 struct bgp_table
*table
;
4997 struct bgp_static
*bgp_static
;
4999 FOREACH_AFI_SAFI (afi
, safi
)
5000 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5001 rn
= bgp_route_next(rn
)) {
5002 if (rn
->info
== NULL
)
5005 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5006 || (safi
== SAFI_EVPN
)) {
5009 for (rm
= bgp_table_top(table
); rm
;
5010 rm
= bgp_route_next(rm
)) {
5012 bgp_static_get_node_info(rm
);
5013 bgp_static_withdraw_safi(
5014 bgp
, &rm
->p
, AFI_IP
, safi
,
5015 (struct prefix_rd
*)&rn
->p
);
5016 bgp_static_free(bgp_static
);
5017 bgp_static_set_node_info(rn
, NULL
);
5018 bgp_unlock_node(rn
);
5021 bgp_static
= bgp_static_get_node_info(rn
);
5022 bgp_static_withdraw(bgp
, &rn
->p
, afi
, safi
);
5023 bgp_static_free(bgp_static
);
5024 bgp_static_set_node_info(rn
, NULL
);
5025 bgp_unlock_node(rn
);
5030 void bgp_static_redo_import_check(struct bgp
*bgp
)
5034 struct bgp_node
*rn
;
5035 struct bgp_node
*rm
;
5036 struct bgp_table
*table
;
5037 struct bgp_static
*bgp_static
;
5039 /* Use this flag to force reprocessing of the route */
5040 bgp_flag_set(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5041 FOREACH_AFI_SAFI (afi
, safi
) {
5042 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5043 rn
= bgp_route_next(rn
)) {
5044 if (rn
->info
== NULL
)
5047 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5048 || (safi
== SAFI_EVPN
)) {
5051 for (rm
= bgp_table_top(table
); rm
;
5052 rm
= bgp_route_next(rm
)) {
5054 bgp_static_get_node_info(rm
);
5055 bgp_static_update_safi(bgp
, &rm
->p
,
5060 bgp_static
= bgp_static_get_node_info(rn
);
5061 bgp_static_update(bgp
, &rn
->p
, bgp_static
, afi
,
5066 bgp_flag_unset(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5069 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
5072 struct bgp_table
*table
;
5073 struct bgp_node
*rn
;
5074 struct bgp_info
*ri
;
5076 table
= bgp
->rib
[afi
][safi
];
5077 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
5078 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
5079 if (ri
->peer
== bgp
->peer_self
5080 && ((ri
->type
== ZEBRA_ROUTE_BGP
5081 && ri
->sub_type
== BGP_ROUTE_STATIC
)
5082 || (ri
->type
!= ZEBRA_ROUTE_BGP
5084 == BGP_ROUTE_REDISTRIBUTE
))) {
5085 bgp_aggregate_decrement(bgp
, &rn
->p
, ri
, afi
,
5087 bgp_unlink_nexthop(ri
);
5088 bgp_info_delete(rn
, ri
);
5089 bgp_process(bgp
, rn
, afi
, safi
);
5096 * Purge all networks and redistributed routes from routing table.
5097 * Invoked upon the instance going down.
5099 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
5104 FOREACH_AFI_SAFI (afi
, safi
)
5105 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
5110 * Currently this is used to set static routes for VPN and ENCAP.
5111 * I think it can probably be factored with bgp_static_set.
5113 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5114 const char *ip_str
, const char *rd_str
,
5115 const char *label_str
, const char *rmap_str
,
5116 int evpn_type
, const char *esi
, const char *gwip
,
5117 const char *ethtag
, const char *routermac
)
5119 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5122 struct prefix_rd prd
;
5123 struct bgp_node
*prn
;
5124 struct bgp_node
*rn
;
5125 struct bgp_table
*table
;
5126 struct bgp_static
*bgp_static
;
5127 mpls_label_t label
= MPLS_INVALID_LABEL
;
5128 struct prefix gw_ip
;
5130 /* validate ip prefix */
5131 ret
= str2prefix(ip_str
, &p
);
5133 vty_out(vty
, "%% Malformed prefix\n");
5134 return CMD_WARNING_CONFIG_FAILED
;
5137 if ((afi
== AFI_L2VPN
)
5138 && (bgp_build_evpn_prefix(evpn_type
,
5139 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5140 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5141 return CMD_WARNING_CONFIG_FAILED
;
5144 ret
= str2prefix_rd(rd_str
, &prd
);
5146 vty_out(vty
, "%% Malformed rd\n");
5147 return CMD_WARNING_CONFIG_FAILED
;
5151 unsigned long label_val
;
5152 label_val
= strtoul(label_str
, NULL
, 10);
5153 encode_label(label_val
, &label
);
5156 if (safi
== SAFI_EVPN
) {
5157 if (esi
&& str2esi(esi
, NULL
) == 0) {
5158 vty_out(vty
, "%% Malformed ESI\n");
5159 return CMD_WARNING_CONFIG_FAILED
;
5161 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
5162 vty_out(vty
, "%% Malformed Router MAC\n");
5163 return CMD_WARNING_CONFIG_FAILED
;
5166 memset(&gw_ip
, 0, sizeof(struct prefix
));
5167 ret
= str2prefix(gwip
, &gw_ip
);
5169 vty_out(vty
, "%% Malformed GatewayIp\n");
5170 return CMD_WARNING_CONFIG_FAILED
;
5172 if ((gw_ip
.family
== AF_INET
5173 && is_evpn_prefix_ipaddr_v6(
5174 (struct prefix_evpn
*)&p
))
5175 || (gw_ip
.family
== AF_INET6
5176 && is_evpn_prefix_ipaddr_v4(
5177 (struct prefix_evpn
*)&p
))) {
5179 "%% GatewayIp family differs with IP prefix\n");
5180 return CMD_WARNING_CONFIG_FAILED
;
5184 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5185 if (prn
->info
== NULL
)
5186 prn
->info
= bgp_table_init(bgp
, afi
, safi
);
5188 bgp_unlock_node(prn
);
5191 rn
= bgp_node_get(table
, &p
);
5194 vty_out(vty
, "%% Same network configuration exists\n");
5195 bgp_unlock_node(rn
);
5197 /* New configuration. */
5198 bgp_static
= bgp_static_new();
5199 bgp_static
->backdoor
= 0;
5200 bgp_static
->valid
= 0;
5201 bgp_static
->igpmetric
= 0;
5202 bgp_static
->igpnexthop
.s_addr
= 0;
5203 bgp_static
->label
= label
;
5204 bgp_static
->prd
= prd
;
5207 if (bgp_static
->rmap
.name
)
5208 XFREE(MTYPE_ROUTE_MAP_NAME
,
5209 bgp_static
->rmap
.name
);
5210 bgp_static
->rmap
.name
=
5211 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
5212 bgp_static
->rmap
.map
=
5213 route_map_lookup_by_name(rmap_str
);
5216 if (safi
== SAFI_EVPN
) {
5218 bgp_static
->eth_s_id
=
5220 sizeof(struct eth_segment_id
));
5221 str2esi(esi
, bgp_static
->eth_s_id
);
5224 bgp_static
->router_mac
=
5225 XCALLOC(MTYPE_ATTR
, ETH_ALEN
+ 1);
5226 (void)prefix_str2mac(routermac
,
5227 bgp_static
->router_mac
);
5230 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
5232 bgp_static_set_node_info(rn
, bgp_static
);
5234 bgp_static
->valid
= 1;
5235 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
5241 /* Configure static BGP network. */
5242 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5243 const char *ip_str
, const char *rd_str
,
5244 const char *label_str
, int evpn_type
, const char *esi
,
5245 const char *gwip
, const char *ethtag
)
5247 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5250 struct prefix_rd prd
;
5251 struct bgp_node
*prn
;
5252 struct bgp_node
*rn
;
5253 struct bgp_table
*table
;
5254 struct bgp_static
*bgp_static
;
5255 mpls_label_t label
= MPLS_INVALID_LABEL
;
5257 /* Convert IP prefix string to struct prefix. */
5258 ret
= str2prefix(ip_str
, &p
);
5260 vty_out(vty
, "%% Malformed prefix\n");
5261 return CMD_WARNING_CONFIG_FAILED
;
5264 if ((afi
== AFI_L2VPN
)
5265 && (bgp_build_evpn_prefix(evpn_type
,
5266 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5267 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5268 return CMD_WARNING_CONFIG_FAILED
;
5270 ret
= str2prefix_rd(rd_str
, &prd
);
5272 vty_out(vty
, "%% Malformed rd\n");
5273 return CMD_WARNING_CONFIG_FAILED
;
5277 unsigned long label_val
;
5278 label_val
= strtoul(label_str
, NULL
, 10);
5279 encode_label(label_val
, &label
);
5282 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5283 if (prn
->info
== NULL
)
5284 prn
->info
= bgp_table_init(bgp
, afi
, safi
);
5286 bgp_unlock_node(prn
);
5289 rn
= bgp_node_lookup(table
, &p
);
5292 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
5294 bgp_static
= bgp_static_get_node_info(rn
);
5295 bgp_static_free(bgp_static
);
5296 bgp_static_set_node_info(rn
, NULL
);
5297 bgp_unlock_node(rn
);
5298 bgp_unlock_node(rn
);
5300 vty_out(vty
, "%% Can't find the route\n");
5305 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
5306 const char *rmap_name
)
5308 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5309 struct bgp_rmap
*rmap
;
5311 rmap
= &bgp
->table_map
[afi
][safi
];
5314 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5315 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
5316 rmap
->map
= route_map_lookup_by_name(rmap_name
);
5319 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5324 if (bgp_fibupd_safi(safi
))
5325 bgp_zebra_announce_table(bgp
, afi
, safi
);
5330 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
5331 const char *rmap_name
)
5333 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5334 struct bgp_rmap
*rmap
;
5336 rmap
= &bgp
->table_map
[afi
][safi
];
5338 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5342 if (bgp_fibupd_safi(safi
))
5343 bgp_zebra_announce_table(bgp
, afi
, safi
);
5348 void bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
5351 if (bgp
->table_map
[afi
][safi
].name
) {
5352 vty_out(vty
, " table-map %s\n",
5353 bgp
->table_map
[afi
][safi
].name
);
5357 DEFUN (bgp_table_map
,
5360 "BGP table to RIB route download filter\n"
5361 "Name of the route map\n")
5364 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5365 argv
[idx_word
]->arg
);
5367 DEFUN (no_bgp_table_map
,
5368 no_bgp_table_map_cmd
,
5369 "no table-map WORD",
5371 "BGP table to RIB route download filter\n"
5372 "Name of the route map\n")
5375 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5376 argv
[idx_word
]->arg
);
5382 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
5383 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
5384 backdoor$backdoor}]",
5386 "Specify a network to announce via BGP\n"
5391 "Route-map to modify the attributes\n"
5392 "Name of the route map\n"
5393 "Label index to associate with the prefix\n"
5394 "Label index value\n"
5395 "Specify a BGP backdoor route\n")
5397 char addr_prefix_str
[BUFSIZ
];
5402 ret
= netmask_str2prefix_str(address_str
, netmask_str
,
5405 vty_out(vty
, "%% Inconsistent address and mask\n");
5406 return CMD_WARNING_CONFIG_FAILED
;
5410 return bgp_static_set(
5411 vty
, no
, address_str
? addr_prefix_str
: prefix_str
, AFI_IP
,
5412 bgp_node_safi(vty
), map_name
, backdoor
? 1 : 0,
5413 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5416 DEFPY(ipv6_bgp_network
,
5417 ipv6_bgp_network_cmd
,
5418 "[no] network X:X::X:X/M$prefix \
5419 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
5421 "Specify a network to announce via BGP\n"
5423 "Route-map to modify the attributes\n"
5424 "Name of the route map\n"
5425 "Label index to associate with the prefix\n"
5426 "Label index value\n")
5428 return bgp_static_set(
5429 vty
, no
, prefix_str
, AFI_IP6
, bgp_node_safi(vty
), map_name
, 0,
5430 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5433 /* Aggreagete address:
5435 advertise-map Set condition to advertise attribute
5436 as-set Generate AS set path information
5437 attribute-map Set attributes of aggregate
5438 route-map Set parameters of aggregate
5439 summary-only Filter more specific routes from updates
5440 suppress-map Conditionally filter more specific routes from updates
5443 struct bgp_aggregate
{
5444 /* Summary-only flag. */
5445 uint8_t summary_only
;
5447 /* AS set generation. */
5450 /* Route-map for aggregated route. */
5451 struct route_map
*map
;
5453 /* Suppress-count. */
5454 unsigned long count
;
5456 /* SAFI configuration. */
5460 static struct bgp_aggregate
*bgp_aggregate_new(void)
5462 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
5465 static void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
5467 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
5470 static int bgp_aggregate_info_same(struct bgp_info
*ri
, uint8_t origin
,
5471 struct aspath
*aspath
,
5472 struct community
*comm
)
5474 static struct aspath
*ae
= NULL
;
5477 ae
= aspath_empty();
5482 if (origin
!= ri
->attr
->origin
)
5485 if (!aspath_cmp(ri
->attr
->aspath
, (aspath
) ? aspath
: ae
))
5488 if (!community_cmp(ri
->attr
->community
, comm
))
5491 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_VALID
))
5497 static void bgp_aggregate_install(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
5498 struct prefix
*p
, uint8_t origin
,
5499 struct aspath
*aspath
,
5500 struct community
*community
,
5501 uint8_t atomic_aggregate
,
5502 struct bgp_aggregate
*aggregate
)
5504 struct bgp_node
*rn
;
5505 struct bgp_table
*table
;
5506 struct bgp_info
*ri
, *new;
5508 table
= bgp
->rib
[afi
][safi
];
5510 rn
= bgp_node_get(table
, p
);
5512 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
5513 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
5514 && ri
->sub_type
== BGP_ROUTE_AGGREGATE
)
5517 if (aggregate
->count
> 0) {
5519 * If the aggregate information has not changed
5520 * no need to re-install it again.
5522 if (bgp_aggregate_info_same(rn
->info
, origin
, aspath
,
5524 bgp_unlock_node(rn
);
5527 aspath_free(aspath
);
5529 community_free(community
);
5535 * Mark the old as unusable
5538 bgp_info_delete(rn
, ri
);
5541 ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0, bgp
->peer_self
,
5542 bgp_attr_aggregate_intern(bgp
, origin
, aspath
,
5543 community
, aggregate
->as_set
,
5546 SET_FLAG(new->flags
, BGP_INFO_VALID
);
5548 bgp_info_add(rn
, new);
5549 bgp_process(bgp
, rn
, afi
, safi
);
5551 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
5552 if (ri
->peer
== bgp
->peer_self
5553 && ri
->type
== ZEBRA_ROUTE_BGP
5554 && ri
->sub_type
== BGP_ROUTE_AGGREGATE
)
5557 /* Withdraw static BGP route from routing table. */
5559 bgp_info_delete(rn
, ri
);
5560 bgp_process(bgp
, rn
, afi
, safi
);
5564 bgp_unlock_node(rn
);
5567 /* Update an aggregate as routes are added/removed from the BGP table */
5568 static void bgp_aggregate_route(struct bgp
*bgp
, struct prefix
*p
,
5569 struct bgp_info
*rinew
, afi_t afi
, safi_t safi
,
5570 struct bgp_info
*del
,
5571 struct bgp_aggregate
*aggregate
)
5573 struct bgp_table
*table
;
5574 struct bgp_node
*top
;
5575 struct bgp_node
*rn
;
5577 struct aspath
*aspath
= NULL
;
5578 struct aspath
*asmerge
= NULL
;
5579 struct community
*community
= NULL
;
5580 struct community
*commerge
= NULL
;
5581 struct bgp_info
*ri
;
5582 unsigned long match
= 0;
5583 uint8_t atomic_aggregate
= 0;
5585 /* ORIGIN attribute: If at least one route among routes that are
5586 aggregated has ORIGIN with the value INCOMPLETE, then the
5587 aggregated route must have the ORIGIN attribute with the value
5588 INCOMPLETE. Otherwise, if at least one route among routes that
5589 are aggregated has ORIGIN with the value EGP, then the aggregated
5590 route must have the origin attribute with the value EGP. In all
5591 other case the value of the ORIGIN attribute of the aggregated
5592 route is INTERNAL. */
5593 origin
= BGP_ORIGIN_IGP
;
5595 table
= bgp
->rib
[afi
][safi
];
5597 top
= bgp_node_get(table
, p
);
5598 for (rn
= bgp_node_get(table
, p
); rn
;
5599 rn
= bgp_route_next_until(rn
, top
)) {
5600 if (rn
->p
.prefixlen
<= p
->prefixlen
)
5605 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
5606 if (BGP_INFO_HOLDDOWN(ri
))
5609 if (del
&& ri
== del
)
5613 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
5614 atomic_aggregate
= 1;
5616 if (ri
->sub_type
== BGP_ROUTE_AGGREGATE
)
5620 * summary-only aggregate route suppress
5621 * aggregated route announcements.
5623 if (aggregate
->summary_only
) {
5624 (bgp_info_extra_get(ri
))->suppress
++;
5625 bgp_info_set_flag(rn
, ri
,
5626 BGP_INFO_ATTR_CHANGED
);
5633 * If at least one route among routes that are
5634 * aggregated has ORIGIN with the value INCOMPLETE,
5635 * then the aggregated route MUST have the ORIGIN
5636 * attribute with the value INCOMPLETE. Otherwise, if
5637 * at least one route among routes that are aggregated
5638 * has ORIGIN with the value EGP, then the aggregated
5639 * route MUST have the ORIGIN attribute with the value
5642 if (origin
< ri
->attr
->origin
)
5643 origin
= ri
->attr
->origin
;
5645 if (!aggregate
->as_set
)
5649 * as-set aggregate route generate origin, as path,
5650 * and community aggregation.
5653 asmerge
= aspath_aggregate(aspath
,
5655 aspath_free(aspath
);
5658 aspath
= aspath_dup(ri
->attr
->aspath
);
5660 if (!ri
->attr
->community
)
5664 commerge
= community_merge(community
,
5665 ri
->attr
->community
);
5666 community
= community_uniq_sort(commerge
);
5667 community_free(commerge
);
5669 community
= community_dup(ri
->attr
->community
);
5672 bgp_process(bgp
, rn
, afi
, safi
);
5674 bgp_unlock_node(top
);
5679 if (aggregate
->summary_only
)
5680 (bgp_info_extra_get(rinew
))->suppress
++;
5682 if (origin
< rinew
->attr
->origin
)
5683 origin
= rinew
->attr
->origin
;
5685 if (aggregate
->as_set
) {
5687 asmerge
= aspath_aggregate(aspath
,
5688 rinew
->attr
->aspath
);
5689 aspath_free(aspath
);
5692 aspath
= aspath_dup(rinew
->attr
->aspath
);
5694 if (rinew
->attr
->community
) {
5696 commerge
= community_merge(
5698 rinew
->attr
->community
);
5700 community_uniq_sort(commerge
);
5701 community_free(commerge
);
5703 community
= community_dup(
5704 rinew
->attr
->community
);
5709 bgp_aggregate_install(bgp
, afi
, safi
, p
, origin
, aspath
, community
,
5710 atomic_aggregate
, aggregate
);
5712 if (aggregate
->count
== 0) {
5714 aspath_free(aspath
);
5716 community_free(community
);
5720 static void bgp_aggregate_delete(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
5721 safi_t safi
, struct bgp_aggregate
*aggregate
)
5723 struct bgp_table
*table
;
5724 struct bgp_node
*top
;
5725 struct bgp_node
*rn
;
5726 struct bgp_info
*ri
;
5727 unsigned long match
;
5729 table
= bgp
->rib
[afi
][safi
];
5731 /* If routes exists below this node, generate aggregate routes. */
5732 top
= bgp_node_get(table
, p
);
5733 for (rn
= bgp_node_get(table
, p
); rn
;
5734 rn
= bgp_route_next_until(rn
, top
)) {
5735 if (rn
->p
.prefixlen
<= p
->prefixlen
)
5739 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
5740 if (BGP_INFO_HOLDDOWN(ri
))
5743 if (ri
->sub_type
== BGP_ROUTE_AGGREGATE
)
5746 if (aggregate
->summary_only
&& ri
->extra
) {
5747 ri
->extra
->suppress
--;
5749 if (ri
->extra
->suppress
== 0) {
5751 rn
, ri
, BGP_INFO_ATTR_CHANGED
);
5758 /* If this node was suppressed, process the change. */
5760 bgp_process(bgp
, rn
, afi
, safi
);
5762 bgp_unlock_node(top
);
5765 void bgp_aggregate_increment(struct bgp
*bgp
, struct prefix
*p
,
5766 struct bgp_info
*ri
, afi_t afi
, safi_t safi
)
5768 struct bgp_node
*child
;
5769 struct bgp_node
*rn
;
5770 struct bgp_aggregate
*aggregate
;
5771 struct bgp_table
*table
;
5773 table
= bgp
->aggregate
[afi
][safi
];
5775 /* No aggregates configured. */
5776 if (bgp_table_top_nolock(table
) == NULL
)
5779 if (p
->prefixlen
== 0)
5782 if (BGP_INFO_HOLDDOWN(ri
))
5785 child
= bgp_node_get(table
, p
);
5787 /* Aggregate address configuration check. */
5788 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
)) {
5789 aggregate
= bgp_aggregate_get_node_info(rn
);
5790 if (aggregate
!= NULL
&& rn
->p
.prefixlen
< p
->prefixlen
) {
5791 bgp_aggregate_delete(bgp
, &rn
->p
, afi
, safi
, aggregate
);
5792 bgp_aggregate_route(bgp
, &rn
->p
, ri
, afi
, safi
, NULL
,
5796 bgp_unlock_node(child
);
5799 void bgp_aggregate_decrement(struct bgp
*bgp
, struct prefix
*p
,
5800 struct bgp_info
*del
, afi_t afi
, safi_t safi
)
5802 struct bgp_node
*child
;
5803 struct bgp_node
*rn
;
5804 struct bgp_aggregate
*aggregate
;
5805 struct bgp_table
*table
;
5807 table
= bgp
->aggregate
[afi
][safi
];
5809 /* No aggregates configured. */
5810 if (bgp_table_top_nolock(table
) == NULL
)
5813 if (p
->prefixlen
== 0)
5816 child
= bgp_node_get(table
, p
);
5818 /* Aggregate address configuration check. */
5819 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
)) {
5820 aggregate
= bgp_aggregate_get_node_info(rn
);
5821 if (aggregate
!= NULL
&& rn
->p
.prefixlen
< p
->prefixlen
) {
5822 bgp_aggregate_delete(bgp
, &rn
->p
, afi
, safi
, aggregate
);
5823 bgp_aggregate_route(bgp
, &rn
->p
, NULL
, afi
, safi
, del
,
5827 bgp_unlock_node(child
);
5830 /* Aggregate route attribute. */
5831 #define AGGREGATE_SUMMARY_ONLY 1
5832 #define AGGREGATE_AS_SET 1
5834 static int bgp_aggregate_unset(struct vty
*vty
, const char *prefix_str
,
5835 afi_t afi
, safi_t safi
)
5837 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5840 struct bgp_node
*rn
;
5841 struct bgp_aggregate
*aggregate
;
5843 /* Convert string to prefix structure. */
5844 ret
= str2prefix(prefix_str
, &p
);
5846 vty_out(vty
, "Malformed prefix\n");
5847 return CMD_WARNING_CONFIG_FAILED
;
5851 /* Old configuration check. */
5852 rn
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], &p
);
5855 "%% There is no aggregate-address configuration.\n");
5856 return CMD_WARNING_CONFIG_FAILED
;
5859 aggregate
= bgp_aggregate_get_node_info(rn
);
5860 bgp_aggregate_delete(bgp
, &p
, afi
, safi
, aggregate
);
5861 bgp_aggregate_install(bgp
, afi
, safi
, &p
, 0, NULL
, NULL
, 0, aggregate
);
5863 /* Unlock aggregate address configuration. */
5864 bgp_aggregate_set_node_info(rn
, NULL
);
5865 bgp_aggregate_free(aggregate
);
5866 bgp_unlock_node(rn
);
5867 bgp_unlock_node(rn
);
5872 static int bgp_aggregate_set(struct vty
*vty
, const char *prefix_str
, afi_t afi
,
5873 safi_t safi
, uint8_t summary_only
, uint8_t as_set
)
5875 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5878 struct bgp_node
*rn
;
5879 struct bgp_aggregate
*aggregate
;
5881 /* Convert string to prefix structure. */
5882 ret
= str2prefix(prefix_str
, &p
);
5884 vty_out(vty
, "Malformed prefix\n");
5885 return CMD_WARNING_CONFIG_FAILED
;
5889 if ((afi
== AFI_IP
&& p
.prefixlen
== IPV4_MAX_BITLEN
) ||
5890 (afi
== AFI_IP6
&& p
.prefixlen
== IPV6_MAX_BITLEN
)) {
5891 vty_out(vty
, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
5893 return CMD_WARNING_CONFIG_FAILED
;
5896 /* Old configuration check. */
5897 rn
= bgp_node_get(bgp
->aggregate
[afi
][safi
], &p
);
5900 vty_out(vty
, "There is already same aggregate network.\n");
5901 /* try to remove the old entry */
5902 ret
= bgp_aggregate_unset(vty
, prefix_str
, afi
, safi
);
5904 vty_out(vty
, "Error deleting aggregate.\n");
5905 bgp_unlock_node(rn
);
5906 return CMD_WARNING_CONFIG_FAILED
;
5910 /* Make aggregate address structure. */
5911 aggregate
= bgp_aggregate_new();
5912 aggregate
->summary_only
= summary_only
;
5913 aggregate
->as_set
= as_set
;
5914 aggregate
->safi
= safi
;
5915 bgp_aggregate_set_node_info(rn
, aggregate
);
5917 /* Aggregate address insert into BGP routing table. */
5918 bgp_aggregate_route(bgp
, &p
, NULL
, afi
, safi
, NULL
, aggregate
);
5923 DEFUN (aggregate_address
,
5924 aggregate_address_cmd
,
5925 "aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
5926 "Configure BGP aggregate entries\n"
5927 "Aggregate prefix\n"
5928 "Generate AS set path information\n"
5929 "Filter more specific routes from updates\n"
5930 "Filter more specific routes from updates\n"
5931 "Generate AS set path information\n")
5934 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
5935 char *prefix
= argv
[idx
]->arg
;
5937 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
5939 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
5940 ? AGGREGATE_SUMMARY_ONLY
5943 return bgp_aggregate_set(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
),
5944 summary_only
, as_set
);
5947 DEFUN (aggregate_address_mask
,
5948 aggregate_address_mask_cmd
,
5949 "aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
5950 "Configure BGP aggregate entries\n"
5951 "Aggregate address\n"
5953 "Generate AS set path information\n"
5954 "Filter more specific routes from updates\n"
5955 "Filter more specific routes from updates\n"
5956 "Generate AS set path information\n")
5959 argv_find(argv
, argc
, "A.B.C.D", &idx
);
5960 char *prefix
= argv
[idx
]->arg
;
5961 char *mask
= argv
[idx
+ 1]->arg
;
5963 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
5965 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
5966 ? AGGREGATE_SUMMARY_ONLY
5969 char prefix_str
[BUFSIZ
];
5970 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
5973 vty_out(vty
, "%% Inconsistent address and mask\n");
5974 return CMD_WARNING_CONFIG_FAILED
;
5977 return bgp_aggregate_set(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
),
5978 summary_only
, as_set
);
5981 DEFUN (no_aggregate_address
,
5982 no_aggregate_address_cmd
,
5983 "no aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
5985 "Configure BGP aggregate entries\n"
5986 "Aggregate prefix\n"
5987 "Generate AS set path information\n"
5988 "Filter more specific routes from updates\n"
5989 "Filter more specific routes from updates\n"
5990 "Generate AS set path information\n")
5993 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
5994 char *prefix
= argv
[idx
]->arg
;
5995 return bgp_aggregate_unset(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
));
5998 DEFUN (no_aggregate_address_mask
,
5999 no_aggregate_address_mask_cmd
,
6000 "no aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
6002 "Configure BGP aggregate entries\n"
6003 "Aggregate address\n"
6005 "Generate AS set path information\n"
6006 "Filter more specific routes from updates\n"
6007 "Filter more specific routes from updates\n"
6008 "Generate AS set path information\n")
6011 argv_find(argv
, argc
, "A.B.C.D", &idx
);
6012 char *prefix
= argv
[idx
]->arg
;
6013 char *mask
= argv
[idx
+ 1]->arg
;
6015 char prefix_str
[BUFSIZ
];
6016 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
6019 vty_out(vty
, "%% Inconsistent address and mask\n");
6020 return CMD_WARNING_CONFIG_FAILED
;
6023 return bgp_aggregate_unset(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
));
6026 DEFUN (ipv6_aggregate_address
,
6027 ipv6_aggregate_address_cmd
,
6028 "aggregate-address X:X::X:X/M [summary-only]",
6029 "Configure BGP aggregate entries\n"
6030 "Aggregate prefix\n"
6031 "Filter more specific routes from updates\n")
6034 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6035 char *prefix
= argv
[idx
]->arg
;
6036 int sum_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6037 ? AGGREGATE_SUMMARY_ONLY
6039 return bgp_aggregate_set(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
, sum_only
,
6043 DEFUN (no_ipv6_aggregate_address
,
6044 no_ipv6_aggregate_address_cmd
,
6045 "no aggregate-address X:X::X:X/M [summary-only]",
6047 "Configure BGP aggregate entries\n"
6048 "Aggregate prefix\n"
6049 "Filter more specific routes from updates\n")
6052 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6053 char *prefix
= argv
[idx
]->arg
;
6054 return bgp_aggregate_unset(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
);
6057 /* Redistribute route treatment. */
6058 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
6059 const union g_addr
*nexthop
, ifindex_t ifindex
,
6060 enum nexthop_types_t nhtype
, uint32_t metric
,
6061 uint8_t type
, unsigned short instance
,
6064 struct bgp_info
*new;
6065 struct bgp_info
*bi
;
6066 struct bgp_info info
;
6067 struct bgp_node
*bn
;
6069 struct attr
*new_attr
;
6072 struct bgp_redist
*red
;
6074 /* Make default attribute. */
6075 bgp_attr_default_set(&attr
, BGP_ORIGIN_INCOMPLETE
);
6078 case NEXTHOP_TYPE_IFINDEX
:
6080 case NEXTHOP_TYPE_IPV4
:
6081 case NEXTHOP_TYPE_IPV4_IFINDEX
:
6082 attr
.nexthop
= nexthop
->ipv4
;
6084 case NEXTHOP_TYPE_IPV6
:
6085 case NEXTHOP_TYPE_IPV6_IFINDEX
:
6086 attr
.mp_nexthop_global
= nexthop
->ipv6
;
6087 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6089 case NEXTHOP_TYPE_BLACKHOLE
:
6090 switch (p
->family
) {
6092 attr
.nexthop
.s_addr
= INADDR_ANY
;
6095 memset(&attr
.mp_nexthop_global
, 0,
6096 sizeof(attr
.mp_nexthop_global
));
6097 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6102 attr
.nh_ifindex
= ifindex
;
6105 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6108 afi
= family2afi(p
->family
);
6110 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6112 struct attr attr_new
;
6114 /* Copy attribute for modification. */
6115 bgp_attr_dup(&attr_new
, &attr
);
6117 if (red
->redist_metric_flag
)
6118 attr_new
.med
= red
->redist_metric
;
6120 /* Apply route-map. */
6121 if (red
->rmap
.name
) {
6122 memset(&info
, 0, sizeof(struct bgp_info
));
6123 info
.peer
= bgp
->peer_self
;
6124 info
.attr
= &attr_new
;
6126 SET_FLAG(bgp
->peer_self
->rmap_type
,
6127 PEER_RMAP_TYPE_REDISTRIBUTE
);
6129 ret
= route_map_apply(red
->rmap
.map
, p
, RMAP_BGP
,
6132 bgp
->peer_self
->rmap_type
= 0;
6134 if (ret
== RMAP_DENYMATCH
) {
6135 /* Free uninterned attribute. */
6136 bgp_attr_flush(&attr_new
);
6138 /* Unintern original. */
6139 aspath_unintern(&attr
.aspath
);
6140 bgp_redistribute_delete(bgp
, p
, type
, instance
);
6145 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
6146 bgp_attr_add_gshut_community(&attr_new
);
6148 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6149 SAFI_UNICAST
, p
, NULL
);
6151 new_attr
= bgp_attr_intern(&attr_new
);
6153 for (bi
= bn
->info
; bi
; bi
= bi
->next
)
6154 if (bi
->peer
== bgp
->peer_self
6155 && bi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
6159 /* Ensure the (source route) type is updated. */
6161 if (attrhash_cmp(bi
->attr
, new_attr
)
6162 && !CHECK_FLAG(bi
->flags
, BGP_INFO_REMOVED
)) {
6163 bgp_attr_unintern(&new_attr
);
6164 aspath_unintern(&attr
.aspath
);
6165 bgp_unlock_node(bn
);
6168 /* The attribute is changed. */
6169 bgp_info_set_flag(bn
, bi
,
6170 BGP_INFO_ATTR_CHANGED
);
6172 /* Rewrite BGP route information. */
6173 if (CHECK_FLAG(bi
->flags
, BGP_INFO_REMOVED
))
6174 bgp_info_restore(bn
, bi
);
6176 bgp_aggregate_decrement(bgp
, p
, bi
, afi
,
6178 bgp_attr_unintern(&bi
->attr
);
6179 bi
->attr
= new_attr
;
6180 bi
->uptime
= bgp_clock();
6182 /* Process change. */
6183 bgp_aggregate_increment(bgp
, p
, bi
, afi
,
6185 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6186 bgp_unlock_node(bn
);
6187 aspath_unintern(&attr
.aspath
);
6189 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6191 == BGP_INSTANCE_TYPE_DEFAULT
)) {
6193 vpn_leak_from_vrf_update(
6194 bgp_get_default(), bgp
, bi
);
6200 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
6201 bgp
->peer_self
, new_attr
, bn
);
6202 SET_FLAG(new->flags
, BGP_INFO_VALID
);
6204 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
6205 bgp_info_add(bn
, new);
6206 bgp_unlock_node(bn
);
6207 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6209 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6210 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6212 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
6216 /* Unintern original. */
6217 aspath_unintern(&attr
.aspath
);
6220 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, uint8_t type
,
6221 unsigned short instance
)
6224 struct bgp_node
*rn
;
6225 struct bgp_info
*ri
;
6226 struct bgp_redist
*red
;
6228 afi
= family2afi(p
->family
);
6230 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6232 rn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6233 SAFI_UNICAST
, p
, NULL
);
6235 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
6236 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== type
)
6240 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6241 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6243 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6246 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, SAFI_UNICAST
);
6247 bgp_info_delete(rn
, ri
);
6248 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6250 bgp_unlock_node(rn
);
6254 /* Withdraw specified route type's route. */
6255 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
6256 unsigned short instance
)
6258 struct bgp_node
*rn
;
6259 struct bgp_info
*ri
;
6260 struct bgp_table
*table
;
6262 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
6264 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
6265 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
6266 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== type
6267 && ri
->instance
== instance
)
6271 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6272 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6274 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6277 bgp_aggregate_decrement(bgp
, &rn
->p
, ri
, afi
,
6279 bgp_info_delete(rn
, ri
);
6280 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6285 /* Static function to display route. */
6286 static void route_vty_out_route(struct prefix
*p
, struct vty
*vty
,
6293 if (p
->family
== AF_INET
) {
6297 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
6300 json_object_string_add(json
, "prefix",
6301 inet_ntop(p
->family
,
6304 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
6305 sprintf(buf2
, "%s/%d",
6306 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
6307 BUFSIZ
), p
->prefixlen
);
6308 json_object_string_add(json
, "network", buf2
);
6310 } else if (p
->family
== AF_ETHERNET
) {
6311 prefix2str(p
, buf
, PREFIX_STRLEN
);
6312 len
= vty_out(vty
, "%s", buf
);
6313 } else if (p
->family
== AF_EVPN
) {
6317 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf
,
6320 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
6321 } else if (p
->family
== AF_FLOWSPEC
) {
6322 route_vty_out_flowspec(vty
, p
, NULL
,
6324 NLRI_STRING_FORMAT_JSON_SIMPLE
:
6325 NLRI_STRING_FORMAT_MIN
, json
);
6330 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
6333 json_object_string_add(json
, "prefix",
6334 inet_ntop(p
->family
,
6337 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
6338 sprintf(buf2
, "%s/%d",
6339 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
6340 BUFSIZ
), p
->prefixlen
);
6341 json_object_string_add(json
, "network", buf2
); }
6347 vty_out(vty
, "\n%*s", 20, " ");
6349 vty_out(vty
, "%*s", len
, " ");
6353 enum bgp_display_type
{
6357 /* Print the short form route status for a bgp_info */
6358 static void route_vty_short_status_out(struct vty
*vty
, struct bgp_info
*binfo
,
6359 json_object
*json_path
)
6363 /* Route status display. */
6364 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_REMOVED
))
6365 json_object_boolean_true_add(json_path
, "removed");
6367 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_STALE
))
6368 json_object_boolean_true_add(json_path
, "stale");
6370 if (binfo
->extra
&& binfo
->extra
->suppress
)
6371 json_object_boolean_true_add(json_path
, "suppressed");
6373 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)
6374 && !CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6375 json_object_boolean_true_add(json_path
, "valid");
6378 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6379 json_object_boolean_true_add(json_path
, "history");
6381 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
))
6382 json_object_boolean_true_add(json_path
, "damped");
6384 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
))
6385 json_object_boolean_true_add(json_path
, "bestpath");
6387 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_MULTIPATH
))
6388 json_object_boolean_true_add(json_path
, "multipath");
6390 /* Internal route. */
6391 if ((binfo
->peer
->as
)
6392 && (binfo
->peer
->as
== binfo
->peer
->local_as
))
6393 json_object_string_add(json_path
, "pathFrom",
6396 json_object_string_add(json_path
, "pathFrom",
6402 /* Route status display. */
6403 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_REMOVED
))
6405 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_STALE
))
6407 else if (binfo
->extra
&& binfo
->extra
->suppress
)
6409 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)
6410 && !CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6416 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6418 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
))
6420 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
))
6422 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_MULTIPATH
))
6427 /* Internal route. */
6428 if (binfo
->peer
&& (binfo
->peer
->as
)
6429 && (binfo
->peer
->as
== binfo
->peer
->local_as
))
6435 /* called from terminal list command */
6436 void route_vty_out(struct vty
*vty
, struct prefix
*p
, struct bgp_info
*binfo
,
6437 int display
, safi_t safi
, json_object
*json_paths
)
6440 json_object
*json_path
= NULL
;
6441 json_object
*json_nexthops
= NULL
;
6442 json_object
*json_nexthop_global
= NULL
;
6443 json_object
*json_nexthop_ll
= NULL
;
6444 char vrf_id_str
[VRF_NAMSIZ
] = {0};
6445 bool nexthop_self
= CHECK_FLAG(binfo
->flags
, BGP_INFO_ANNC_NH_SELF
)
6448 bool nexthop_othervrf
= false;
6449 vrf_id_t nexthop_vrfid
= VRF_DEFAULT
;
6450 const char *nexthop_vrfname
= "Default";
6453 json_path
= json_object_new_object();
6455 /* short status lead text */
6456 route_vty_short_status_out(vty
, binfo
, json_path
);
6459 /* print prefix and mask */
6461 route_vty_out_route(p
, vty
, json_path
);
6463 vty_out(vty
, "%*s", 17, " ");
6465 route_vty_out_route(p
, vty
, json_path
);
6468 /* Print attribute */
6472 json_object_array_add(json_paths
, json_path
);
6480 * If vrf id of nexthop is different from that of prefix,
6481 * set up printable string to append
6483 if (binfo
->extra
&& binfo
->extra
->bgp_orig
) {
6484 const char *self
= "";
6489 nexthop_othervrf
= true;
6490 nexthop_vrfid
= binfo
->extra
->bgp_orig
->vrf_id
;
6492 if (binfo
->extra
->bgp_orig
->vrf_id
== VRF_UNKNOWN
)
6493 snprintf(vrf_id_str
, sizeof(vrf_id_str
),
6494 "@%s%s", VRFID_NONE_STR
, self
);
6496 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "@%u%s",
6497 binfo
->extra
->bgp_orig
->vrf_id
, self
);
6499 if (binfo
->extra
->bgp_orig
->inst_type
!=
6500 BGP_INSTANCE_TYPE_DEFAULT
)
6502 nexthop_vrfname
= binfo
->extra
->bgp_orig
->name
;
6504 const char *self
= "";
6509 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "%s", self
);
6513 * For ENCAP and EVPN routes, nexthop address family is not
6514 * neccessarily the same as the prefix address family.
6515 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
6516 * EVPN routes are also exchanged with a MP nexthop. Currently,
6518 * is only IPv4, the value will be present in either
6520 * attr->mp_nexthop_global_in
6522 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
6525 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
6529 sprintf(nexthop
, "%s",
6530 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
6534 sprintf(nexthop
, "%s",
6535 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
6539 sprintf(nexthop
, "?");
6544 json_nexthop_global
= json_object_new_object();
6546 json_object_string_add(json_nexthop_global
, "afi",
6547 (af
== AF_INET
) ? "ip" : "ipv6");
6548 json_object_string_add(json_nexthop_global
,
6549 (af
== AF_INET
) ? "ip" : "ipv6",
6551 json_object_boolean_true_add(json_nexthop_global
,
6554 vty_out(vty
, "%s%s", nexthop
, vrf_id_str
);
6555 } else if (safi
== SAFI_EVPN
) {
6557 json_nexthop_global
= json_object_new_object();
6559 json_object_string_add(json_nexthop_global
, "ip",
6560 inet_ntoa(attr
->nexthop
));
6561 json_object_string_add(json_nexthop_global
, "afi",
6563 json_object_boolean_true_add(json_nexthop_global
,
6566 vty_out(vty
, "%-16s%s", inet_ntoa(attr
->nexthop
),
6568 } else if (safi
== SAFI_FLOWSPEC
) {
6569 if (attr
->nexthop
.s_addr
!= 0) {
6571 json_nexthop_global
= json_object_new_object();
6572 json_object_string_add(
6573 json_nexthop_global
, "ip",
6574 inet_ntoa(attr
->nexthop
));
6575 json_object_string_add(json_nexthop_global
,
6577 json_object_boolean_true_add(
6578 json_nexthop_global
,
6581 vty_out(vty
, "%-16s", inet_ntoa(attr
->nexthop
));
6584 } else if (p
->family
== AF_INET
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6586 json_nexthop_global
= json_object_new_object();
6588 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_EVPN
))
6589 json_object_string_add(
6590 json_nexthop_global
, "ip",
6591 inet_ntoa(attr
->mp_nexthop_global_in
));
6593 json_object_string_add(
6594 json_nexthop_global
, "ip",
6595 inet_ntoa(attr
->nexthop
));
6597 json_object_string_add(json_nexthop_global
, "afi",
6599 json_object_boolean_true_add(json_nexthop_global
,
6604 snprintf(buf
, sizeof(buf
), "%s%s",
6605 inet_ntoa(attr
->nexthop
), vrf_id_str
);
6606 vty_out(vty
, "%-16s", buf
);
6611 else if (p
->family
== AF_INET6
|| BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6616 json_nexthop_global
= json_object_new_object();
6617 json_object_string_add(
6618 json_nexthop_global
, "ip",
6619 inet_ntop(AF_INET6
, &attr
->mp_nexthop_global
,
6621 json_object_string_add(json_nexthop_global
, "afi",
6623 json_object_string_add(json_nexthop_global
, "scope",
6626 /* We display both LL & GL if both have been
6628 if ((attr
->mp_nexthop_len
== 32)
6629 || (binfo
->peer
->conf_if
)) {
6630 json_nexthop_ll
= json_object_new_object();
6631 json_object_string_add(
6632 json_nexthop_ll
, "ip",
6634 &attr
->mp_nexthop_local
, buf
,
6636 json_object_string_add(json_nexthop_ll
, "afi",
6638 json_object_string_add(json_nexthop_ll
, "scope",
6641 if ((IPV6_ADDR_CMP(&attr
->mp_nexthop_global
,
6642 &attr
->mp_nexthop_local
)
6644 && !attr
->mp_nexthop_prefer_global
)
6645 json_object_boolean_true_add(
6646 json_nexthop_ll
, "used");
6648 json_object_boolean_true_add(
6649 json_nexthop_global
, "used");
6651 json_object_boolean_true_add(
6652 json_nexthop_global
, "used");
6654 /* Display LL if LL/Global both in table unless
6655 * prefer-global is set */
6656 if (((attr
->mp_nexthop_len
== 32)
6657 && !attr
->mp_nexthop_prefer_global
)
6658 || (binfo
->peer
->conf_if
)) {
6659 if (binfo
->peer
->conf_if
) {
6660 len
= vty_out(vty
, "%s",
6661 binfo
->peer
->conf_if
);
6662 len
= 16 - len
; /* len of IPv6
6668 vty_out(vty
, "\n%*s", 36, " ");
6670 vty_out(vty
, "%*s", len
, " ");
6676 &attr
->mp_nexthop_local
,
6682 vty_out(vty
, "\n%*s", 36, " ");
6684 vty_out(vty
, "%*s", len
, " ");
6690 &attr
->mp_nexthop_global
, buf
,
6696 vty_out(vty
, "\n%*s", 36, " ");
6698 vty_out(vty
, "%*s", len
, " ");
6704 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
6708 * Adding "metric" field to match with corresponding
6709 * CLI. "med" will be deprecated in future.
6711 json_object_int_add(json_path
, "med", attr
->med
);
6712 json_object_int_add(json_path
, "metric", attr
->med
);
6714 vty_out(vty
, "%10u", attr
->med
);
6715 else if (!json_paths
)
6719 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
6723 * Adding "locPrf" field to match with corresponding
6724 * CLI. "localPref" will be deprecated in future.
6726 json_object_int_add(json_path
, "localpref",
6728 json_object_int_add(json_path
, "locPrf",
6731 vty_out(vty
, "%7u", attr
->local_pref
);
6732 else if (!json_paths
)
6736 json_object_int_add(json_path
, "weight", attr
->weight
);
6738 vty_out(vty
, "%7u ", attr
->weight
);
6742 json_object_string_add(
6743 json_path
, "peerId",
6744 sockunion2str(&binfo
->peer
->su
, buf
, SU_ADDRSTRLEN
));
6752 * Adding "path" field to match with corresponding
6753 * CLI. "aspath" will be deprecated in future.
6755 json_object_string_add(json_path
, "aspath",
6757 json_object_string_add(json_path
, "path",
6760 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
6765 json_object_string_add(json_path
, "origin",
6766 bgp_origin_long_str
[attr
->origin
]);
6768 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
6772 json_object_boolean_true_add(json_path
,
6773 "announceNexthopSelf");
6774 if (nexthop_othervrf
) {
6775 json_object_string_add(json_path
, "nhVrfName",
6778 json_object_int_add(json_path
, "nhVrfId",
6779 ((nexthop_vrfid
== VRF_UNKNOWN
)
6781 : (int)nexthop_vrfid
));
6786 if (json_nexthop_global
|| json_nexthop_ll
) {
6787 json_nexthops
= json_object_new_array();
6789 if (json_nexthop_global
)
6790 json_object_array_add(json_nexthops
,
6791 json_nexthop_global
);
6793 if (json_nexthop_ll
)
6794 json_object_array_add(json_nexthops
,
6797 json_object_object_add(json_path
, "nexthops",
6801 json_object_array_add(json_paths
, json_path
);
6805 /* prints an additional line, indented, with VNC info, if
6807 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
6808 rfapi_vty_out_vncinfo(vty
, p
, binfo
, safi
);
6813 /* called from terminal list command */
6814 void route_vty_out_tmp(struct vty
*vty
, struct prefix
*p
, struct attr
*attr
,
6815 safi_t safi
, bool use_json
, json_object
*json_ar
)
6817 json_object
*json_status
= NULL
;
6818 json_object
*json_net
= NULL
;
6821 /* Route status display. */
6823 json_status
= json_object_new_object();
6824 json_net
= json_object_new_object();
6831 /* print prefix and mask */
6833 json_object_string_add(
6834 json_net
, "addrPrefix",
6835 inet_ntop(p
->family
, &p
->u
.prefix
, buff
, BUFSIZ
));
6836 json_object_int_add(json_net
, "prefixLen", p
->prefixlen
);
6837 sprintf(buf2
, "%s/%d",
6838 inet_ntop(p
->family
, &p
->u
.prefix
, buff
,
6839 BUFSIZ
), p
->prefixlen
);
6840 json_object_string_add(json_net
, "network", buf2
);
6842 route_vty_out_route(p
, vty
, NULL
);
6844 /* Print attribute */
6847 if (p
->family
== AF_INET
6848 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6849 || safi
== SAFI_EVPN
6850 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6851 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6852 || safi
== SAFI_EVPN
)
6853 json_object_string_add(
6854 json_net
, "nextHop",
6856 attr
->mp_nexthop_global_in
));
6858 json_object_string_add(
6859 json_net
, "nextHop",
6860 inet_ntoa(attr
->nexthop
));
6861 } else if (p
->family
== AF_INET6
6862 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6865 json_object_string_add(
6866 json_net
, "netHopGloabal",
6868 &attr
->mp_nexthop_global
, buf
,
6873 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
6874 json_object_int_add(json_net
, "metric",
6877 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
6880 * Adding "locPrf" field to match with
6881 * corresponding CLI. "localPref" will be
6882 * deprecated in future.
6884 json_object_int_add(json_net
, "localPref",
6886 json_object_int_add(json_net
, "locPrf",
6890 json_object_int_add(json_net
, "weight", attr
->weight
);
6896 * Adding "path" field to match with
6897 * corresponding CLI. "localPref" will be
6898 * deprecated in future.
6900 json_object_string_add(json_net
, "asPath",
6902 json_object_string_add(json_net
, "path",
6907 json_object_string_add(json_net
, "bgpOriginCode",
6908 bgp_origin_str
[attr
->origin
]);
6910 if (p
->family
== AF_INET
6911 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6912 || safi
== SAFI_EVPN
6913 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6914 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6915 || safi
== SAFI_EVPN
)
6916 vty_out(vty
, "%-16s",
6918 attr
->mp_nexthop_global_in
));
6920 vty_out(vty
, "%-16s",
6921 inet_ntoa(attr
->nexthop
));
6922 } else if (p
->family
== AF_INET6
6923 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6930 &attr
->mp_nexthop_global
, buf
,
6934 vty_out(vty
, "\n%*s", 36, " ");
6936 vty_out(vty
, "%*s", len
, " ");
6939 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
6940 vty_out(vty
, "%10u", attr
->med
);
6944 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
6945 vty_out(vty
, "%7u", attr
->local_pref
);
6949 vty_out(vty
, "%7u ", attr
->weight
);
6953 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
6956 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
6960 json_object_boolean_true_add(json_status
, "*");
6961 json_object_boolean_true_add(json_status
, ">");
6962 json_object_object_add(json_net
, "appliedStatusSymbols",
6964 char buf_cut
[BUFSIZ
];
6965 json_object_object_add(
6967 inet_ntop(p
->family
, &p
->u
.prefix
, buf_cut
, BUFSIZ
),
6973 void route_vty_out_tag(struct vty
*vty
, struct prefix
*p
,
6974 struct bgp_info
*binfo
, int display
, safi_t safi
,
6977 json_object
*json_out
= NULL
;
6979 mpls_label_t label
= MPLS_INVALID_LABEL
;
6985 json_out
= json_object_new_object();
6987 /* short status lead text */
6988 route_vty_short_status_out(vty
, binfo
, json_out
);
6990 /* print prefix and mask */
6993 route_vty_out_route(p
, vty
, NULL
);
6995 vty_out(vty
, "%*s", 17, " ");
6998 /* Print attribute */
7001 if (((p
->family
== AF_INET
)
7002 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
7003 || (safi
== SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
7004 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7005 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7006 || safi
== SAFI_EVPN
) {
7008 json_object_string_add(
7009 json_out
, "mpNexthopGlobalIn",
7011 attr
->mp_nexthop_global_in
));
7013 vty_out(vty
, "%-16s",
7015 attr
->mp_nexthop_global_in
));
7018 json_object_string_add(
7019 json_out
, "nexthop",
7020 inet_ntoa(attr
->nexthop
));
7022 vty_out(vty
, "%-16s",
7023 inet_ntoa(attr
->nexthop
));
7025 } else if (((p
->family
== AF_INET6
)
7026 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
7027 || (safi
== SAFI_EVPN
7028 && BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
7029 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7033 if (attr
->mp_nexthop_len
7034 == BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
7036 json_object_string_add(
7037 json_out
, "mpNexthopGlobalIn",
7040 &attr
->mp_nexthop_global
,
7041 buf_a
, sizeof(buf_a
)));
7046 &attr
->mp_nexthop_global
,
7047 buf_a
, sizeof(buf_a
)));
7048 } else if (attr
->mp_nexthop_len
7049 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
7052 &attr
->mp_nexthop_global
,
7053 buf_a
, sizeof(buf_a
));
7055 &attr
->mp_nexthop_local
,
7056 buf_b
, sizeof(buf_b
));
7057 sprintf(buf_c
, "%s(%s)", buf_a
, buf_b
);
7058 json_object_string_add(
7060 "mpNexthopGlobalLocal", buf_c
);
7062 vty_out(vty
, "%s(%s)",
7065 &attr
->mp_nexthop_global
,
7066 buf_a
, sizeof(buf_a
)),
7069 &attr
->mp_nexthop_local
,
7070 buf_b
, sizeof(buf_b
)));
7075 label
= decode_label(&binfo
->extra
->label
[0]);
7077 if (bgp_is_valid_label(&label
)) {
7079 json_object_int_add(json_out
, "notag", label
);
7080 json_object_array_add(json
, json_out
);
7082 vty_out(vty
, "notag/%d", label
);
7088 void route_vty_out_overlay(struct vty
*vty
, struct prefix
*p
,
7089 struct bgp_info
*binfo
, int display
,
7090 json_object
*json_paths
)
7094 json_object
*json_path
= NULL
;
7097 json_path
= json_object_new_object();
7102 /* short status lead text */
7103 route_vty_short_status_out(vty
, binfo
, json_path
);
7105 /* print prefix and mask */
7107 route_vty_out_route(p
, vty
, NULL
);
7109 vty_out(vty
, "%*s", 17, " ");
7111 /* Print attribute */
7115 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
7119 vty_out(vty
, "%-16s",
7120 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
7124 vty_out(vty
, "%s(%s)",
7125 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
7127 inet_ntop(af
, &attr
->mp_nexthop_local
, buf1
,
7134 char *str
= esi2str(&(attr
->evpn_overlay
.eth_s_id
));
7136 vty_out(vty
, "%s", str
);
7137 XFREE(MTYPE_TMP
, str
);
7139 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn
*)p
)) {
7141 inet_ntoa(attr
->evpn_overlay
.gw_ip
.ipv4
));
7142 } else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn
*)p
)) {
7145 &(attr
->evpn_overlay
.gw_ip
.ipv6
), buf
,
7148 if (attr
->ecommunity
) {
7150 struct ecommunity_val
*routermac
= ecommunity_lookup(
7151 attr
->ecommunity
, ECOMMUNITY_ENCODE_EVPN
,
7152 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
7154 mac
= ecom_mac2str((char *)routermac
->val
);
7156 vty_out(vty
, "/%s", (char *)mac
);
7157 XFREE(MTYPE_TMP
, mac
);
7165 /* dampening route */
7166 static void damp_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7167 struct bgp_info
*binfo
, int display
, safi_t safi
,
7168 bool use_json
, json_object
*json
)
7172 char timebuf
[BGP_UPTIME_LEN
];
7174 /* short status lead text */
7175 route_vty_short_status_out(vty
, binfo
, json
);
7177 /* print prefix and mask */
7180 route_vty_out_route(p
, vty
, NULL
);
7182 vty_out(vty
, "%*s", 17, " ");
7185 len
= vty_out(vty
, "%s", binfo
->peer
->host
);
7189 vty_out(vty
, "\n%*s", 34, " ");
7192 json_object_int_add(json
, "peerHost", len
);
7194 vty_out(vty
, "%*s", len
, " ");
7198 bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
, BGP_UPTIME_LEN
,
7201 vty_out(vty
, "%s ", bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
,
7205 /* Print attribute */
7211 json_object_string_add(json
, "asPath",
7214 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7219 json_object_string_add(json
, "origin",
7220 bgp_origin_str
[attr
->origin
]);
7222 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7229 static void flap_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7230 struct bgp_info
*binfo
, int display
, safi_t safi
,
7231 bool use_json
, json_object
*json
)
7234 struct bgp_damp_info
*bdi
;
7235 char timebuf
[BGP_UPTIME_LEN
];
7241 bdi
= binfo
->extra
->damp_info
;
7243 /* short status lead text */
7244 route_vty_short_status_out(vty
, binfo
, json
);
7246 /* print prefix and mask */
7249 route_vty_out_route(p
, vty
, NULL
);
7251 vty_out(vty
, "%*s", 17, " ");
7254 len
= vty_out(vty
, "%s", binfo
->peer
->host
);
7258 vty_out(vty
, "\n%*s", 33, " ");
7261 json_object_int_add(json
, "peerHost", len
);
7263 vty_out(vty
, "%*s", len
, " ");
7266 len
= vty_out(vty
, "%d", bdi
->flap
);
7273 json_object_int_add(json
, "bdiFlap", len
);
7275 vty_out(vty
, "%*s", len
, " ");
7279 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
7282 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
7283 BGP_UPTIME_LEN
, 0, NULL
));
7285 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
)
7286 && !CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
)) {
7288 bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
,
7289 BGP_UPTIME_LEN
, use_json
, json
);
7292 bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
,
7297 vty_out(vty
, "%*s ", 8, " ");
7300 /* Print attribute */
7306 json_object_string_add(json
, "asPath",
7309 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7314 json_object_string_add(json
, "origin",
7315 bgp_origin_str
[attr
->origin
]);
7317 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7323 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
7324 int *first
, const char *header
,
7325 json_object
*json_adv_to
)
7327 char buf1
[INET6_ADDRSTRLEN
];
7328 json_object
*json_peer
= NULL
;
7331 /* 'advertised-to' is a dictionary of peers we have advertised
7333 * prefix too. The key is the peer's IP or swpX, the value is
7335 * hostname if we know it and "" if not.
7337 json_peer
= json_object_new_object();
7340 json_object_string_add(json_peer
, "hostname",
7344 json_object_object_add(json_adv_to
, peer
->conf_if
,
7347 json_object_object_add(
7349 sockunion2str(&peer
->su
, buf1
, SU_ADDRSTRLEN
),
7353 vty_out(vty
, "%s", header
);
7358 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
7360 vty_out(vty
, " %s(%s)", peer
->hostname
,
7363 vty_out(vty
, " %s(%s)", peer
->hostname
,
7364 sockunion2str(&peer
->su
, buf1
,
7368 vty_out(vty
, " %s", peer
->conf_if
);
7371 sockunion2str(&peer
->su
, buf1
,
7377 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
, struct prefix
*p
,
7378 struct bgp_info
*binfo
, afi_t afi
, safi_t safi
,
7379 json_object
*json_paths
)
7381 char buf
[INET6_ADDRSTRLEN
];
7383 char buf2
[EVPN_ROUTE_STRLEN
];
7385 int sockunion_vty_out(struct vty
*, union sockunion
*);
7387 json_object
*json_bestpath
= NULL
;
7388 json_object
*json_cluster_list
= NULL
;
7389 json_object
*json_cluster_list_list
= NULL
;
7390 json_object
*json_ext_community
= NULL
;
7391 json_object
*json_last_update
= NULL
;
7392 json_object
*json_pmsi
= NULL
;
7393 json_object
*json_nexthop_global
= NULL
;
7394 json_object
*json_nexthop_ll
= NULL
;
7395 json_object
*json_nexthops
= NULL
;
7396 json_object
*json_path
= NULL
;
7397 json_object
*json_peer
= NULL
;
7398 json_object
*json_string
= NULL
;
7399 json_object
*json_adv_to
= NULL
;
7401 struct listnode
*node
, *nnode
;
7403 int addpath_capable
;
7405 unsigned int first_as
;
7406 bool nexthop_self
= CHECK_FLAG(binfo
->flags
, BGP_INFO_ANNC_NH_SELF
)
7411 json_path
= json_object_new_object();
7412 json_peer
= json_object_new_object();
7413 json_nexthop_global
= json_object_new_object();
7416 if (!json_paths
&& safi
== SAFI_EVPN
) {
7419 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf2
, sizeof(buf2
));
7420 vty_out(vty
, " Route %s", buf2
);
7422 if (binfo
->extra
&& binfo
->extra
->num_labels
) {
7423 bgp_evpn_label2str(binfo
->extra
->label
,
7424 binfo
->extra
->num_labels
, tag_buf
,
7426 vty_out(vty
, " VNI %s", tag_buf
);
7429 if (binfo
->extra
&& binfo
->extra
->parent
) {
7430 struct bgp_info
*parent_ri
;
7431 struct bgp_node
*rn
, *prn
;
7433 parent_ri
= (struct bgp_info
*)binfo
->extra
->parent
;
7434 rn
= parent_ri
->net
;
7435 if (rn
&& rn
->prn
) {
7437 vty_out(vty
, " Imported from %s:%s\n",
7439 (struct prefix_rd
*)&prn
->p
,
7440 buf1
, sizeof(buf1
)),
7449 /* Line1 display AS-path, Aggregator */
7452 if (!attr
->aspath
->json
)
7453 aspath_str_update(attr
->aspath
, true);
7454 json_object_lock(attr
->aspath
->json
);
7455 json_object_object_add(json_path
, "aspath",
7456 attr
->aspath
->json
);
7458 if (attr
->aspath
->segments
)
7459 aspath_print_vty(vty
, " %s",
7462 vty_out(vty
, " Local");
7466 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_REMOVED
)) {
7468 json_object_boolean_true_add(json_path
,
7471 vty_out(vty
, ", (removed)");
7474 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_STALE
)) {
7476 json_object_boolean_true_add(json_path
,
7479 vty_out(vty
, ", (stale)");
7482 if (CHECK_FLAG(attr
->flag
,
7483 ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
7485 json_object_int_add(json_path
, "aggregatorAs",
7486 attr
->aggregator_as
);
7487 json_object_string_add(
7488 json_path
, "aggregatorId",
7489 inet_ntoa(attr
->aggregator_addr
));
7491 vty_out(vty
, ", (aggregated by %u %s)",
7492 attr
->aggregator_as
,
7493 inet_ntoa(attr
->aggregator_addr
));
7497 if (CHECK_FLAG(binfo
->peer
->af_flags
[afi
][safi
],
7498 PEER_FLAG_REFLECTOR_CLIENT
)) {
7500 json_object_boolean_true_add(
7501 json_path
, "rxedFromRrClient");
7503 vty_out(vty
, ", (Received from a RR-client)");
7506 if (CHECK_FLAG(binfo
->peer
->af_flags
[afi
][safi
],
7507 PEER_FLAG_RSERVER_CLIENT
)) {
7509 json_object_boolean_true_add(
7510 json_path
, "rxedFromRsClient");
7512 vty_out(vty
, ", (Received from a RS-client)");
7515 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
)) {
7517 json_object_boolean_true_add(
7518 json_path
, "dampeningHistoryEntry");
7520 vty_out(vty
, ", (history entry)");
7521 } else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
)) {
7523 json_object_boolean_true_add(
7524 json_path
, "dampeningSuppressed");
7526 vty_out(vty
, ", (suppressed due to dampening)");
7532 /* Line2 display Next-hop, Neighbor, Router-id */
7533 /* Display the nexthop */
7534 if ((p
->family
== AF_INET
|| p
->family
== AF_ETHERNET
7535 || p
->family
== AF_EVPN
)
7536 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7537 || safi
== SAFI_EVPN
7538 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7539 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7540 || safi
== SAFI_EVPN
) {
7542 json_object_string_add(
7543 json_nexthop_global
, "ip",
7545 attr
->mp_nexthop_global_in
));
7549 attr
->mp_nexthop_global_in
));
7552 json_object_string_add(
7553 json_nexthop_global
, "ip",
7554 inet_ntoa(attr
->nexthop
));
7557 inet_ntoa(attr
->nexthop
));
7561 json_object_string_add(json_nexthop_global
,
7565 json_object_string_add(
7566 json_nexthop_global
, "ip",
7568 &attr
->mp_nexthop_global
, buf
,
7570 json_object_string_add(json_nexthop_global
,
7572 json_object_string_add(json_nexthop_global
,
7577 &attr
->mp_nexthop_global
, buf
,
7582 /* Display the IGP cost or 'inaccessible' */
7583 if (!CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)) {
7585 json_object_boolean_false_add(
7586 json_nexthop_global
, "accessible");
7588 vty_out(vty
, " (inaccessible)");
7590 if (binfo
->extra
&& binfo
->extra
->igpmetric
) {
7592 json_object_int_add(
7593 json_nexthop_global
, "metric",
7594 binfo
->extra
->igpmetric
);
7596 vty_out(vty
, " (metric %u)",
7597 binfo
->extra
->igpmetric
);
7600 /* IGP cost is 0, display this only for json */
7603 json_object_int_add(json_nexthop_global
,
7608 json_object_boolean_true_add(
7609 json_nexthop_global
, "accessible");
7612 /* Display peer "from" output */
7613 /* This path was originated locally */
7614 if (binfo
->peer
== bgp
->peer_self
) {
7616 if (safi
== SAFI_EVPN
7617 || (p
->family
== AF_INET
7618 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7620 json_object_string_add(
7621 json_peer
, "peerId", "0.0.0.0");
7623 vty_out(vty
, " from 0.0.0.0 ");
7626 json_object_string_add(json_peer
,
7629 vty_out(vty
, " from :: ");
7633 json_object_string_add(
7634 json_peer
, "routerId",
7635 inet_ntoa(bgp
->router_id
));
7637 vty_out(vty
, "(%s)", inet_ntoa(bgp
->router_id
));
7640 /* We RXed this path from one of our peers */
7644 json_object_string_add(
7645 json_peer
, "peerId",
7646 sockunion2str(&binfo
->peer
->su
, buf
,
7648 json_object_string_add(
7649 json_peer
, "routerId",
7651 &binfo
->peer
->remote_id
, buf1
,
7654 if (binfo
->peer
->hostname
)
7655 json_object_string_add(
7656 json_peer
, "hostname",
7657 binfo
->peer
->hostname
);
7659 if (binfo
->peer
->domainname
)
7660 json_object_string_add(
7661 json_peer
, "domainname",
7662 binfo
->peer
->domainname
);
7664 if (binfo
->peer
->conf_if
)
7665 json_object_string_add(
7666 json_peer
, "interface",
7667 binfo
->peer
->conf_if
);
7669 if (binfo
->peer
->conf_if
) {
7670 if (binfo
->peer
->hostname
7673 BGP_FLAG_SHOW_HOSTNAME
))
7674 vty_out(vty
, " from %s(%s)",
7675 binfo
->peer
->hostname
,
7676 binfo
->peer
->conf_if
);
7678 vty_out(vty
, " from %s",
7679 binfo
->peer
->conf_if
);
7681 if (binfo
->peer
->hostname
7684 BGP_FLAG_SHOW_HOSTNAME
))
7685 vty_out(vty
, " from %s(%s)",
7686 binfo
->peer
->hostname
,
7689 vty_out(vty
, " from %s",
7698 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
7699 vty_out(vty
, " (%s)",
7700 inet_ntoa(attr
->originator_id
));
7702 vty_out(vty
, " (%s)",
7705 &binfo
->peer
->remote_id
,
7706 buf1
, sizeof(buf1
)));
7711 * Note when vrfid of nexthop is different from that of prefix
7713 if (binfo
->extra
&& binfo
->extra
->bgp_orig
) {
7714 vrf_id_t nexthop_vrfid
= binfo
->extra
->bgp_orig
->vrf_id
;
7719 if (binfo
->extra
->bgp_orig
->inst_type
==
7720 BGP_INSTANCE_TYPE_DEFAULT
)
7724 vn
= binfo
->extra
->bgp_orig
->name
;
7726 json_object_string_add(json_path
, "nhVrfName",
7729 if (nexthop_vrfid
== VRF_UNKNOWN
) {
7730 json_object_int_add(json_path
,
7733 json_object_int_add(json_path
,
7734 "nhVrfId", (int)nexthop_vrfid
);
7737 if (nexthop_vrfid
== VRF_UNKNOWN
)
7738 vty_out(vty
, " vrf ?");
7740 vty_out(vty
, " vrf %u", nexthop_vrfid
);
7746 json_object_boolean_true_add(json_path
,
7747 "announceNexthopSelf");
7749 vty_out(vty
, " announce-nh-self");
7756 /* display the link-local nexthop */
7757 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
7759 json_nexthop_ll
= json_object_new_object();
7760 json_object_string_add(
7761 json_nexthop_ll
, "ip",
7763 &attr
->mp_nexthop_local
, buf
,
7765 json_object_string_add(json_nexthop_ll
, "afi",
7767 json_object_string_add(json_nexthop_ll
, "scope",
7770 json_object_boolean_true_add(json_nexthop_ll
,
7773 if (!attr
->mp_nexthop_prefer_global
)
7774 json_object_boolean_true_add(
7775 json_nexthop_ll
, "used");
7777 json_object_boolean_true_add(
7778 json_nexthop_global
, "used");
7780 vty_out(vty
, " (%s) %s\n",
7782 &attr
->mp_nexthop_local
, buf
,
7784 attr
->mp_nexthop_prefer_global
7789 /* If we do not have a link-local nexthop then we must flag the
7793 json_object_boolean_true_add(
7794 json_nexthop_global
, "used");
7797 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
7798 * Int/Ext/Local, Atomic, best */
7800 json_object_string_add(
7801 json_path
, "origin",
7802 bgp_origin_long_str
[attr
->origin
]);
7804 vty_out(vty
, " Origin %s",
7805 bgp_origin_long_str
[attr
->origin
]);
7807 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
7811 * Adding "metric" field to match with
7812 * corresponding CLI. "med" will be
7813 * deprecated in future.
7815 json_object_int_add(json_path
, "med",
7817 json_object_int_add(json_path
, "metric",
7820 vty_out(vty
, ", metric %u", attr
->med
);
7823 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
7825 json_object_int_add(json_path
, "localpref",
7828 vty_out(vty
, ", localpref %u",
7832 if (attr
->weight
!= 0) {
7834 json_object_int_add(json_path
, "weight",
7837 vty_out(vty
, ", weight %u", attr
->weight
);
7840 if (attr
->tag
!= 0) {
7842 json_object_int_add(json_path
, "tag",
7845 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
,
7849 if (!CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)) {
7851 json_object_boolean_false_add(json_path
,
7854 vty_out(vty
, ", invalid");
7855 } else if (!CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
)) {
7857 json_object_boolean_true_add(json_path
,
7860 vty_out(vty
, ", valid");
7863 if (binfo
->peer
!= bgp
->peer_self
) {
7864 if (binfo
->peer
->as
== binfo
->peer
->local_as
) {
7865 if (CHECK_FLAG(bgp
->config
,
7866 BGP_CONFIG_CONFEDERATION
)) {
7868 json_object_string_add(
7873 ", confed-internal");
7876 json_object_string_add(
7880 vty_out(vty
, ", internal");
7883 if (bgp_confederation_peers_check(
7884 bgp
, binfo
->peer
->as
)) {
7886 json_object_string_add(
7891 ", confed-external");
7894 json_object_string_add(
7898 vty_out(vty
, ", external");
7901 } else if (binfo
->sub_type
== BGP_ROUTE_AGGREGATE
) {
7903 json_object_boolean_true_add(json_path
,
7905 json_object_boolean_true_add(json_path
,
7908 vty_out(vty
, ", aggregated, local");
7910 } else if (binfo
->type
!= ZEBRA_ROUTE_BGP
) {
7912 json_object_boolean_true_add(json_path
,
7915 vty_out(vty
, ", sourced");
7918 json_object_boolean_true_add(json_path
,
7920 json_object_boolean_true_add(json_path
,
7923 vty_out(vty
, ", sourced, local");
7927 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
7929 json_object_boolean_true_add(json_path
,
7932 vty_out(vty
, ", atomic-aggregate");
7935 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_MULTIPATH
)
7936 || (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
)
7937 && bgp_info_mpath_count(binfo
))) {
7939 json_object_boolean_true_add(json_path
,
7942 vty_out(vty
, ", multipath");
7945 // Mark the bestpath(s)
7946 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DMED_SELECTED
)) {
7947 first_as
= aspath_get_first_as(attr
->aspath
);
7952 json_object_new_object();
7953 json_object_int_add(json_bestpath
,
7954 "bestpathFromAs", first_as
);
7957 vty_out(vty
, ", bestpath-from-AS %u",
7961 ", bestpath-from-AS Local");
7965 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
)) {
7969 json_object_new_object();
7970 json_object_boolean_true_add(json_bestpath
,
7973 vty_out(vty
, ", best");
7977 json_object_object_add(json_path
, "bestpath",
7983 /* Line 4 display Community */
7984 if (attr
->community
) {
7986 if (!attr
->community
->json
)
7987 community_str(attr
->community
, true);
7988 json_object_lock(attr
->community
->json
);
7989 json_object_object_add(json_path
, "community",
7990 attr
->community
->json
);
7992 vty_out(vty
, " Community: %s\n",
7993 attr
->community
->str
);
7997 /* Line 5 display Extended-community */
7998 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
8000 json_ext_community
= json_object_new_object();
8001 json_object_string_add(json_ext_community
,
8003 attr
->ecommunity
->str
);
8004 json_object_object_add(json_path
,
8005 "extendedCommunity",
8006 json_ext_community
);
8008 vty_out(vty
, " Extended Community: %s\n",
8009 attr
->ecommunity
->str
);
8013 /* Line 6 display Large community */
8014 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
8016 if (!attr
->lcommunity
->json
)
8017 lcommunity_str(attr
->lcommunity
, true);
8018 json_object_lock(attr
->lcommunity
->json
);
8019 json_object_object_add(json_path
,
8021 attr
->lcommunity
->json
);
8023 vty_out(vty
, " Large Community: %s\n",
8024 attr
->lcommunity
->str
);
8028 /* Line 7 display Originator, Cluster-id */
8029 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
8030 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
8032 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
8034 json_object_string_add(
8035 json_path
, "originatorId",
8036 inet_ntoa(attr
->originator_id
));
8038 vty_out(vty
, " Originator: %s",
8039 inet_ntoa(attr
->originator_id
));
8042 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
8047 json_object_new_object();
8048 json_cluster_list_list
=
8049 json_object_new_array();
8052 i
< attr
->cluster
->length
/ 4;
8054 json_string
= json_object_new_string(
8058 json_object_array_add(
8059 json_cluster_list_list
,
8063 /* struct cluster_list does not have
8065 * aspath and community do. Add this
8068 json_object_string_add(json_cluster_list,
8069 "string", attr->cluster->str);
8071 json_object_object_add(
8072 json_cluster_list
, "list",
8073 json_cluster_list_list
);
8074 json_object_object_add(
8075 json_path
, "clusterList",
8078 vty_out(vty
, ", Cluster list: ");
8081 i
< attr
->cluster
->length
/ 4;
8095 if (binfo
->extra
&& binfo
->extra
->damp_info
)
8096 bgp_damp_info_vty(vty
, binfo
, json_path
);
8099 if (binfo
->extra
&& bgp_is_valid_label(&binfo
->extra
->label
[0])
8100 && safi
!= SAFI_EVPN
) {
8101 mpls_label_t label
=
8102 label_pton(&binfo
->extra
->label
[0]);
8104 json_object_int_add(json_path
, "remoteLabel",
8107 vty_out(vty
, " Remote label: %d\n", label
);
8111 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
8113 json_object_int_add(json_path
, "labelIndex",
8116 vty_out(vty
, " Label Index: %d\n",
8120 /* Line 8 display Addpath IDs */
8121 if (binfo
->addpath_rx_id
|| binfo
->addpath_tx_id
) {
8123 json_object_int_add(json_path
, "addpathRxId",
8124 binfo
->addpath_rx_id
);
8125 json_object_int_add(json_path
, "addpathTxId",
8126 binfo
->addpath_tx_id
);
8128 vty_out(vty
, " AddPath ID: RX %u, TX %u\n",
8129 binfo
->addpath_rx_id
,
8130 binfo
->addpath_tx_id
);
8134 /* If we used addpath to TX a non-bestpath we need to display
8135 * "Advertised to" on a path-by-path basis */
8136 if (bgp
->addpath_tx_used
[afi
][safi
]) {
8139 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
8141 bgp_addpath_encode_tx(peer
, afi
, safi
);
8142 has_adj
= bgp_adj_out_lookup(
8143 peer
, binfo
->net
, binfo
->addpath_tx_id
);
8145 if ((addpath_capable
&& has_adj
)
8146 || (!addpath_capable
&& has_adj
8147 && CHECK_FLAG(binfo
->flags
,
8148 BGP_INFO_SELECTED
))) {
8149 if (json_path
&& !json_adv_to
)
8151 json_object_new_object();
8153 route_vty_out_advertised_to(
8162 json_object_object_add(json_path
,
8173 /* Line 9 display Uptime */
8174 tbuf
= time(NULL
) - (bgp_clock() - binfo
->uptime
);
8176 json_last_update
= json_object_new_object();
8177 json_object_int_add(json_last_update
, "epoch", tbuf
);
8178 json_object_string_add(json_last_update
, "string",
8180 json_object_object_add(json_path
, "lastUpdate",
8183 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
8185 /* Line 10 display PMSI tunnel attribute, if present */
8186 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
8187 const char *str
= lookup_msg(bgp_pmsi_tnltype_str
,
8188 attr
->pmsi_tnl_type
,
8189 PMSI_TNLTYPE_STR_DEFAULT
);
8192 json_pmsi
= json_object_new_object();
8193 json_object_string_add(json_pmsi
,
8195 json_object_object_add(json_path
, "pmsi",
8198 vty_out(vty
, " PMSI Tunnel Type: %s\n",
8204 /* We've constructed the json object for this path, add it to the json
8208 if (json_nexthop_global
|| json_nexthop_ll
) {
8209 json_nexthops
= json_object_new_array();
8211 if (json_nexthop_global
)
8212 json_object_array_add(json_nexthops
,
8213 json_nexthop_global
);
8215 if (json_nexthop_ll
)
8216 json_object_array_add(json_nexthops
,
8219 json_object_object_add(json_path
, "nexthops",
8223 json_object_object_add(json_path
, "peer", json_peer
);
8224 json_object_array_add(json_paths
, json_path
);
8229 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
8230 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
8231 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
8233 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
8234 const char *prefix_list_str
, afi_t afi
,
8235 safi_t safi
, enum bgp_show_type type
);
8236 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
8237 const char *filter
, afi_t afi
, safi_t safi
,
8238 enum bgp_show_type type
);
8239 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
8240 const char *rmap_str
, afi_t afi
, safi_t safi
,
8241 enum bgp_show_type type
);
8242 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
8243 const char *com
, int exact
, afi_t afi
,
8245 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
8246 const char *prefix
, afi_t afi
, safi_t safi
,
8247 enum bgp_show_type type
);
8248 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
8249 afi_t afi
, safi_t safi
, enum bgp_show_type type
);
8250 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
8251 const char *comstr
, int exact
, afi_t afi
,
8252 safi_t safi
, bool use_json
);
8255 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
8256 struct bgp_table
*table
, enum bgp_show_type type
,
8257 void *output_arg
, bool use_json
, char *rd
,
8258 int is_last
, unsigned long *output_cum
,
8259 unsigned long *total_cum
,
8260 unsigned long *json_header_depth
)
8262 struct bgp_info
*ri
;
8263 struct bgp_node
*rn
;
8266 unsigned long output_count
= 0;
8267 unsigned long total_count
= 0;
8271 json_object
*json_paths
= NULL
;
8274 if (output_cum
&& *output_cum
!= 0)
8277 if (use_json
&& !*json_header_depth
) {
8279 "{\n \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
8280 ",\n \"routerId\": \"%s\",\n \"routes\": { ",
8281 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
8282 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
? "Default"
8284 table
->version
, inet_ntoa(bgp
->router_id
));
8285 *json_header_depth
= 2;
8287 vty_out(vty
, " \"routeDistinguishers\" : {");
8288 ++*json_header_depth
;
8292 if (use_json
&& rd
) {
8293 vty_out(vty
, " \"%s\" : { ", rd
);
8296 /* Start processing of routes. */
8297 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
8298 if (rn
->info
== NULL
)
8303 json_paths
= json_object_new_array();
8307 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
8309 if (type
== bgp_show_type_flap_statistics
8310 || type
== bgp_show_type_flap_neighbor
8311 || type
== bgp_show_type_dampend_paths
8312 || type
== bgp_show_type_damp_neighbor
) {
8313 if (!(ri
->extra
&& ri
->extra
->damp_info
))
8316 if (type
== bgp_show_type_regexp
) {
8317 regex_t
*regex
= output_arg
;
8319 if (bgp_regexec(regex
, ri
->attr
->aspath
)
8323 if (type
== bgp_show_type_prefix_list
) {
8324 struct prefix_list
*plist
= output_arg
;
8326 if (prefix_list_apply(plist
, &rn
->p
)
8330 if (type
== bgp_show_type_filter_list
) {
8331 struct as_list
*as_list
= output_arg
;
8333 if (as_list_apply(as_list
, ri
->attr
->aspath
)
8334 != AS_FILTER_PERMIT
)
8337 if (type
== bgp_show_type_route_map
) {
8338 struct route_map
*rmap
= output_arg
;
8339 struct bgp_info binfo
;
8340 struct attr dummy_attr
;
8343 bgp_attr_dup(&dummy_attr
, ri
->attr
);
8345 binfo
.peer
= ri
->peer
;
8346 binfo
.attr
= &dummy_attr
;
8348 ret
= route_map_apply(rmap
, &rn
->p
, RMAP_BGP
,
8350 if (ret
== RMAP_DENYMATCH
)
8353 if (type
== bgp_show_type_neighbor
8354 || type
== bgp_show_type_flap_neighbor
8355 || type
== bgp_show_type_damp_neighbor
) {
8356 union sockunion
*su
= output_arg
;
8358 if (ri
->peer
== NULL
8359 || ri
->peer
->su_remote
== NULL
8360 || !sockunion_same(ri
->peer
->su_remote
, su
))
8363 if (type
== bgp_show_type_cidr_only
) {
8364 uint32_t destination
;
8366 destination
= ntohl(rn
->p
.u
.prefix4
.s_addr
);
8367 if (IN_CLASSC(destination
)
8368 && rn
->p
.prefixlen
== 24)
8370 if (IN_CLASSB(destination
)
8371 && rn
->p
.prefixlen
== 16)
8373 if (IN_CLASSA(destination
)
8374 && rn
->p
.prefixlen
== 8)
8377 if (type
== bgp_show_type_prefix_longer
) {
8379 if (!prefix_match(p
, &rn
->p
))
8382 if (type
== bgp_show_type_community_all
) {
8383 if (!ri
->attr
->community
)
8386 if (type
== bgp_show_type_community
) {
8387 struct community
*com
= output_arg
;
8389 if (!ri
->attr
->community
8390 || !community_match(ri
->attr
->community
,
8394 if (type
== bgp_show_type_community_exact
) {
8395 struct community
*com
= output_arg
;
8397 if (!ri
->attr
->community
8398 || !community_cmp(ri
->attr
->community
, com
))
8401 if (type
== bgp_show_type_community_list
) {
8402 struct community_list
*list
= output_arg
;
8404 if (!community_list_match(ri
->attr
->community
,
8408 if (type
== bgp_show_type_community_list_exact
) {
8409 struct community_list
*list
= output_arg
;
8411 if (!community_list_exact_match(
8412 ri
->attr
->community
, list
))
8415 if (type
== bgp_show_type_lcommunity
) {
8416 struct lcommunity
*lcom
= output_arg
;
8418 if (!ri
->attr
->lcommunity
8419 || !lcommunity_match(ri
->attr
->lcommunity
,
8423 if (type
== bgp_show_type_lcommunity_list
) {
8424 struct community_list
*list
= output_arg
;
8426 if (!lcommunity_list_match(ri
->attr
->lcommunity
,
8430 if (type
== bgp_show_type_lcommunity_all
) {
8431 if (!ri
->attr
->lcommunity
)
8434 if (type
== bgp_show_type_dampend_paths
8435 || type
== bgp_show_type_damp_neighbor
) {
8436 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_DAMPED
)
8437 || CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
8441 if (!use_json
&& header
) {
8442 vty_out(vty
, "BGP table version is %" PRIu64
8443 ", local router ID is %s, vrf id ",
8445 inet_ntoa(bgp
->router_id
));
8446 if (bgp
->vrf_id
== VRF_UNKNOWN
)
8447 vty_out(vty
, "%s", VRFID_NONE_STR
);
8449 vty_out(vty
, "%u", bgp
->vrf_id
);
8451 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
8452 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
8453 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
8454 if (type
== bgp_show_type_dampend_paths
8455 || type
== bgp_show_type_damp_neighbor
)
8456 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
8457 else if (type
== bgp_show_type_flap_statistics
8458 || type
== bgp_show_type_flap_neighbor
)
8459 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
8461 vty_out(vty
, BGP_SHOW_HEADER
);
8464 if (rd
!= NULL
&& !display
&& !output_count
) {
8467 "Route Distinguisher: %s\n",
8470 if (type
== bgp_show_type_dampend_paths
8471 || type
== bgp_show_type_damp_neighbor
)
8472 damp_route_vty_out(vty
, &rn
->p
, ri
, display
,
8473 safi
, use_json
, json_paths
);
8474 else if (type
== bgp_show_type_flap_statistics
8475 || type
== bgp_show_type_flap_neighbor
)
8476 flap_route_vty_out(vty
, &rn
->p
, ri
, display
,
8477 safi
, use_json
, json_paths
);
8479 route_vty_out(vty
, &rn
->p
, ri
, display
, safi
,
8490 sprintf(buf2
, "%s/%d",
8491 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
8494 vty_out(vty
, "\"%s\": ", buf2
);
8496 vty_out(vty
, ",\"%s\": ", buf2
);
8499 json_object_to_json_string(json_paths
));
8500 json_object_free(json_paths
);
8507 output_count
+= *output_cum
;
8508 *output_cum
= output_count
;
8511 total_count
+= *total_cum
;
8512 *total_cum
= total_count
;
8516 vty_out(vty
, " }%s ", (is_last
? "" : ","));
8520 for (i
= 0; i
< *json_header_depth
; ++i
)
8521 vty_out(vty
, " } ");
8525 /* No route is displayed */
8526 if (output_count
== 0) {
8527 if (type
== bgp_show_type_normal
)
8529 "No BGP prefixes displayed, %ld exist\n",
8533 "\nDisplayed %ld routes and %ld total paths\n",
8534 output_count
, total_count
);
8541 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
8542 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
8543 enum bgp_show_type type
, void *output_arg
, bool use_json
)
8545 struct bgp_node
*rn
, *next
;
8546 unsigned long output_cum
= 0;
8547 unsigned long total_cum
= 0;
8548 unsigned long json_header_depth
= 0;
8551 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
8553 for (rn
= bgp_table_top(table
); rn
; rn
= next
) {
8554 next
= bgp_route_next(rn
);
8555 if (prd_match
&& memcmp(rn
->p
.u
.val
, prd_match
->val
, 8) != 0)
8557 if (rn
->info
!= NULL
) {
8558 struct prefix_rd prd
;
8559 char rd
[RD_ADDRSTRLEN
];
8561 memcpy(&prd
, &(rn
->p
), sizeof(struct prefix_rd
));
8562 prefix_rd2str(&prd
, rd
, sizeof(rd
));
8563 bgp_show_table(vty
, bgp
, safi
, rn
->info
, type
,
8564 output_arg
, use_json
, rd
, next
== NULL
,
8565 &output_cum
, &total_cum
,
8566 &json_header_depth
);
8572 if (output_cum
== 0)
8573 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
8577 "\nDisplayed %ld routes and %ld total paths\n",
8578 output_cum
, total_cum
);
8582 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
8583 enum bgp_show_type type
, void *output_arg
, bool use_json
)
8585 struct bgp_table
*table
;
8586 unsigned long json_header_depth
= 0;
8589 bgp
= bgp_get_default();
8594 vty_out(vty
, "No BGP process is configured\n");
8596 vty_out(vty
, "{}\n");
8600 table
= bgp
->rib
[afi
][safi
];
8601 /* use MPLS and ENCAP specific shows until they are merged */
8602 if (safi
== SAFI_MPLS_VPN
) {
8603 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
8604 output_arg
, use_json
);
8607 if (safi
== SAFI_FLOWSPEC
&& type
== bgp_show_type_detail
) {
8608 return bgp_show_table_flowspec(vty
, bgp
, afi
, table
, type
,
8609 output_arg
, use_json
,
8612 /* labeled-unicast routes live in the unicast table */
8613 else if (safi
== SAFI_LABELED_UNICAST
)
8614 safi
= SAFI_UNICAST
;
8616 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, use_json
,
8617 NULL
, 1, NULL
, NULL
, &json_header_depth
);
8620 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
8621 safi_t safi
, bool use_json
)
8623 struct listnode
*node
, *nnode
;
8626 bool route_output
= false;
8629 vty_out(vty
, "{\n");
8631 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
8632 route_output
= true;
8635 vty_out(vty
, ",\n");
8639 vty_out(vty
, "\"%s\":",
8640 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
8644 vty_out(vty
, "\nInstance %s:\n",
8645 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
8649 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
8654 vty_out(vty
, "}\n");
8655 else if (!route_output
)
8656 vty_out(vty
, "%% BGP instance not found\n");
8659 /* Header of detailed BGP route information */
8660 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
8661 struct bgp_node
*rn
, struct prefix_rd
*prd
,
8662 afi_t afi
, safi_t safi
, json_object
*json
)
8664 struct bgp_info
*ri
;
8667 struct listnode
*node
, *nnode
;
8668 char buf1
[RD_ADDRSTRLEN
];
8669 char buf2
[INET6_ADDRSTRLEN
];
8670 char buf3
[EVPN_ROUTE_STRLEN
];
8671 char prefix_str
[BUFSIZ
];
8676 int route_filter_translated_v4
= 0;
8677 int route_filter_v4
= 0;
8678 int route_filter_translated_v6
= 0;
8679 int route_filter_v6
= 0;
8682 int accept_own_nexthop
= 0;
8685 int no_advertise
= 0;
8689 int has_valid_label
= 0;
8690 mpls_label_t label
= 0;
8691 json_object
*json_adv_to
= NULL
;
8694 has_valid_label
= bgp_is_valid_label(&rn
->local_label
);
8696 if (has_valid_label
)
8697 label
= label_pton(&rn
->local_label
);
8700 if (has_valid_label
)
8701 json_object_int_add(json
, "localLabel", label
);
8703 json_object_string_add(
8705 prefix2str(p
, prefix_str
, sizeof(prefix_str
)));
8707 if (safi
== SAFI_EVPN
)
8708 vty_out(vty
, "BGP routing table entry for %s%s%s\n",
8709 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
))
8712 bgp_evpn_route2str((struct prefix_evpn
*)p
,
8713 buf3
, sizeof(buf3
)));
8715 vty_out(vty
, "BGP routing table entry for %s%s%s/%d\n",
8716 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
8717 ? prefix_rd2str(prd
, buf1
,
8720 safi
== SAFI_MPLS_VPN
? ":" : "",
8721 inet_ntop(p
->family
, &p
->u
.prefix
, buf2
,
8725 if (has_valid_label
)
8726 vty_out(vty
, "Local label: %d\n", label
);
8727 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
8728 vty_out(vty
, "not allocated\n");
8731 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
8733 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
8735 if (ri
->extra
&& ri
->extra
->suppress
)
8737 if (ri
->attr
->community
!= NULL
) {
8738 if (community_include(ri
->attr
->community
,
8739 COMMUNITY_NO_ADVERTISE
))
8741 if (community_include(ri
->attr
->community
,
8742 COMMUNITY_NO_EXPORT
))
8744 if (community_include(ri
->attr
->community
,
8745 COMMUNITY_LOCAL_AS
))
8752 vty_out(vty
, "Paths: (%d available", count
);
8754 vty_out(vty
, ", best #%d", best
);
8755 if (safi
== SAFI_UNICAST
)
8756 vty_out(vty
, ", table %s",
8758 == BGP_INSTANCE_TYPE_DEFAULT
)
8759 ? "Default-IP-Routing-Table"
8762 vty_out(vty
, ", no best path");
8766 ", accept own local route exported and imported in different VRF");
8767 else if (route_filter_translated_v4
)
8769 ", mark translated RTs for VPNv4 route filtering");
8770 else if (route_filter_v4
)
8772 ", attach RT as-is for VPNv4 route filtering");
8773 else if (route_filter_translated_v6
)
8775 ", mark translated RTs for VPNv6 route filtering");
8776 else if (route_filter_v6
)
8778 ", attach RT as-is for VPNv6 route filtering");
8779 else if (llgr_stale
)
8781 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
8784 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
8785 else if (accept_own_nexthop
)
8787 ", accept local nexthop");
8789 vty_out(vty
, ", inform peer to blackhole prefix");
8791 vty_out(vty
, ", not advertised to EBGP peer");
8792 else if (no_advertise
)
8793 vty_out(vty
, ", not advertised to any peer");
8795 vty_out(vty
, ", not advertised outside local AS");
8798 ", inform EBGP peer not to advertise to their EBGP peers");
8802 ", Advertisements suppressed by an aggregate.");
8803 vty_out(vty
, ")\n");
8806 /* If we are not using addpath then we can display Advertised to and
8808 * show what peers we advertised the bestpath to. If we are using
8810 * though then we must display Advertised to on a path-by-path basis. */
8811 if (!bgp
->addpath_tx_used
[afi
][safi
]) {
8812 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
8813 if (bgp_adj_out_lookup(peer
, rn
, 0)) {
8814 if (json
&& !json_adv_to
)
8815 json_adv_to
= json_object_new_object();
8817 route_vty_out_advertised_to(
8819 " Advertised to non peer-group peers:\n ",
8826 json_object_object_add(json
, "advertisedTo",
8831 vty_out(vty
, " Not advertised to any peer");
8837 /* Display specified route of BGP table. */
8838 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
8839 struct bgp_table
*rib
, const char *ip_str
,
8840 afi_t afi
, safi_t safi
,
8841 struct prefix_rd
*prd
, int prefix_check
,
8842 enum bgp_path_type pathtype
, bool use_json
)
8847 struct prefix match
;
8848 struct bgp_node
*rn
;
8849 struct bgp_node
*rm
;
8850 struct bgp_info
*ri
;
8851 struct bgp_table
*table
;
8852 json_object
*json
= NULL
;
8853 json_object
*json_paths
= NULL
;
8855 /* Check IP address argument. */
8856 ret
= str2prefix(ip_str
, &match
);
8858 vty_out(vty
, "address is malformed\n");
8862 match
.family
= afi2family(afi
);
8865 json
= json_object_new_object();
8866 json_paths
= json_object_new_array();
8869 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
8870 for (rn
= bgp_table_top(rib
); rn
; rn
= bgp_route_next(rn
)) {
8871 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
8874 if ((table
= rn
->info
) == NULL
)
8879 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
8883 && rm
->p
.prefixlen
!= match
.prefixlen
) {
8884 bgp_unlock_node(rm
);
8888 for (ri
= rm
->info
; ri
; ri
= ri
->next
) {
8890 route_vty_out_detail_header(
8892 (struct prefix_rd
*)&rn
->p
,
8893 AFI_IP
, safi
, json
);
8898 if (pathtype
== BGP_PATH_ALL
8899 || (pathtype
== BGP_PATH_BESTPATH
8900 && CHECK_FLAG(ri
->flags
,
8902 || (pathtype
== BGP_PATH_MULTIPATH
8903 && (CHECK_FLAG(ri
->flags
,
8905 || CHECK_FLAG(ri
->flags
,
8906 BGP_INFO_SELECTED
))))
8907 route_vty_out_detail(vty
, bgp
, &rm
->p
,
8912 bgp_unlock_node(rm
);
8914 } else if (safi
== SAFI_FLOWSPEC
) {
8915 display
= bgp_flowspec_display_match_per_ip(afi
, rib
,
8916 &match
, prefix_check
,
8923 if ((rn
= bgp_node_match(rib
, &match
)) != NULL
) {
8925 || rn
->p
.prefixlen
== match
.prefixlen
) {
8926 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
8928 route_vty_out_detail_header(
8929 vty
, bgp
, rn
, NULL
, afi
,
8935 if (pathtype
== BGP_PATH_ALL
8936 || (pathtype
== BGP_PATH_BESTPATH
8940 || (pathtype
== BGP_PATH_MULTIPATH
8946 BGP_INFO_SELECTED
))))
8947 route_vty_out_detail(
8948 vty
, bgp
, &rn
->p
, ri
,
8949 afi
, safi
, json_paths
);
8953 bgp_unlock_node(rn
);
8959 json_object_object_add(json
, "paths", json_paths
);
8961 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
8962 json
, JSON_C_TO_STRING_PRETTY
));
8963 json_object_free(json
);
8966 vty_out(vty
, "%% Network not in table\n");
8974 /* Display specified route of Main RIB */
8975 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
8976 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
8977 int prefix_check
, enum bgp_path_type pathtype
,
8981 bgp
= bgp_get_default();
8984 vty_out(vty
, "No BGP process is configured\n");
8986 vty_out(vty
, "{}\n");
8991 /* labeled-unicast routes live in the unicast table */
8992 if (safi
== SAFI_LABELED_UNICAST
)
8993 safi
= SAFI_UNICAST
;
8995 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
8996 afi
, safi
, prd
, prefix_check
, pathtype
,
9000 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
9001 struct cmd_token
**argv
, afi_t afi
, safi_t safi
,
9004 struct lcommunity
*lcom
;
9010 b
= buffer_new(1024);
9011 for (i
= 0; i
< argc
; i
++) {
9013 buffer_putc(b
, ' ');
9015 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
9017 buffer_putstr(b
, argv
[i
]->arg
);
9021 buffer_putc(b
, '\0');
9023 str
= buffer_getstr(b
);
9026 lcom
= lcommunity_str2com(str
);
9027 XFREE(MTYPE_TMP
, str
);
9029 vty_out(vty
, "%% Large-community malformed\n");
9033 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_lcommunity
, lcom
,
9037 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
9038 const char *lcom
, afi_t afi
, safi_t safi
,
9041 struct community_list
*list
;
9043 list
= community_list_lookup(bgp_clist
, lcom
,
9044 LARGE_COMMUNITY_LIST_MASTER
);
9046 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
9051 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_lcommunity_list
,
9055 DEFUN (show_ip_bgp_large_community_list
,
9056 show_ip_bgp_large_community_list_cmd
,
9057 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community-list <(1-500)|WORD> [json]",
9061 BGP_INSTANCE_HELP_STR
9063 BGP_SAFI_WITH_LABEL_HELP_STR
9064 "Display routes matching the large-community-list\n"
9065 "large-community-list number\n"
9066 "large-community-list name\n"
9070 afi_t afi
= AFI_IP6
;
9071 safi_t safi
= SAFI_UNICAST
;
9074 if (argv_find(argv
, argc
, "ip", &idx
))
9076 if (argv_find(argv
, argc
, "view", &idx
)
9077 || argv_find(argv
, argc
, "vrf", &idx
))
9078 vrf
= argv
[++idx
]->arg
;
9079 if (argv_find(argv
, argc
, "ipv4", &idx
)
9080 || argv_find(argv
, argc
, "ipv6", &idx
)) {
9081 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
9082 if (argv_find(argv
, argc
, "unicast", &idx
)
9083 || argv_find(argv
, argc
, "multicast", &idx
))
9084 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
9087 bool uj
= use_json(argc
, argv
);
9089 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
9091 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
9095 argv_find(argv
, argc
, "large-community-list", &idx
);
9096 return bgp_show_lcommunity_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
, safi
,
9099 DEFUN (show_ip_bgp_large_community
,
9100 show_ip_bgp_large_community_cmd
,
9101 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [AA:BB:CC] [json]",
9105 BGP_INSTANCE_HELP_STR
9107 BGP_SAFI_WITH_LABEL_HELP_STR
9108 "Display routes matching the large-communities\n"
9109 "List of large-community numbers\n"
9113 afi_t afi
= AFI_IP6
;
9114 safi_t safi
= SAFI_UNICAST
;
9117 if (argv_find(argv
, argc
, "ip", &idx
))
9119 if (argv_find(argv
, argc
, "view", &idx
)
9120 || argv_find(argv
, argc
, "vrf", &idx
))
9121 vrf
= argv
[++idx
]->arg
;
9122 if (argv_find(argv
, argc
, "ipv4", &idx
)
9123 || argv_find(argv
, argc
, "ipv6", &idx
)) {
9124 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
9125 if (argv_find(argv
, argc
, "unicast", &idx
)
9126 || argv_find(argv
, argc
, "multicast", &idx
))
9127 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
9130 bool uj
= use_json(argc
, argv
);
9132 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
9134 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
9138 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
))
9139 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
, afi
, safi
, uj
);
9141 return bgp_show(vty
, bgp
, afi
, safi
,
9142 bgp_show_type_lcommunity_all
, NULL
, uj
);
9145 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
9149 /* BGP route print out function without JSON */
9152 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
9153 <dampening <parameters>\
9158 |community <AA:NN|local-AS|no-advertise|no-export|graceful-shutdown\
9159 no-peer|blackhole|llgr-stale|no-llgr|accept-own|accept-own-nexthop\
9160 route-filter-v6|route-filter-v4|route-filter-translated-v6|\
9161 route-filter-translated-v4> [exact-match]\
9162 |community-list <(1-500)|WORD> [exact-match]\
9163 |A.B.C.D/M longer-prefixes\
9164 |X:X::X:X/M longer-prefixes\
9169 BGP_INSTANCE_HELP_STR
9171 BGP_SAFI_WITH_LABEL_HELP_STR
9172 "Display detailed information about dampening\n"
9173 "Display detail of configured dampening parameters\n"
9174 "Display routes matching the route-map\n"
9175 "A route-map to match on\n"
9176 "Display routes conforming to the prefix-list\n"
9177 "Prefix-list name\n"
9178 "Display routes conforming to the filter-list\n"
9179 "Regular expression access list name\n"
9180 "BGP RIB advertisement statistics\n"
9181 "Display routes matching the communities\n"
9183 "Do not send outside local AS (well-known community)\n"
9184 "Do not advertise to any peer (well-known community)\n"
9185 "Do not export to next AS (well-known community)\n"
9186 "Graceful shutdown (well-known community)\n"
9187 "Do not export to any peer (well-known community)\n"
9188 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
9189 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
9190 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
9191 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
9192 "Should accept VPN route with local nexthop (well-known community)\n"
9193 "RT VPNv6 route filtering (well-known community)\n"
9194 "RT VPNv4 route filtering (well-known community)\n"
9195 "RT translated VPNv6 route filtering (well-known community)\n"
9196 "RT translated VPNv4 route filtering (well-known community)\n"
9197 "Exact match of the communities\n"
9198 "Display routes matching the community-list\n"
9199 "community-list number\n"
9200 "community-list name\n"
9201 "Exact match of the communities\n"
9203 "Display route and more specific routes\n"
9205 "Display route and more specific routes\n")
9207 afi_t afi
= AFI_IP6
;
9208 safi_t safi
= SAFI_UNICAST
;
9209 int exact_match
= 0;
9210 struct bgp
*bgp
= NULL
;
9213 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9218 if (argv_find(argv
, argc
, "dampening", &idx
)) {
9219 if (argv_find(argv
, argc
, "parameters", &idx
))
9220 return bgp_show_dampening_parameters(vty
, afi
, safi
);
9223 if (argv_find(argv
, argc
, "prefix-list", &idx
))
9224 return bgp_show_prefix_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9225 safi
, bgp_show_type_prefix_list
);
9227 if (argv_find(argv
, argc
, "filter-list", &idx
))
9228 return bgp_show_filter_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9229 safi
, bgp_show_type_filter_list
);
9231 if (argv_find(argv
, argc
, "statistics", &idx
))
9232 return bgp_table_stats(vty
, bgp
, afi
, safi
);
9234 if (argv_find(argv
, argc
, "route-map", &idx
))
9235 return bgp_show_route_map(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9236 safi
, bgp_show_type_route_map
);
9238 if (argv_find(argv
, argc
, "community-list", &idx
)) {
9239 const char *clist_number_or_name
= argv
[++idx
]->arg
;
9240 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
9242 return bgp_show_community_list(vty
, bgp
, clist_number_or_name
,
9243 exact_match
, afi
, safi
);
9246 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
9247 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
9248 return bgp_show_prefix_longer(vty
, bgp
, argv
[idx
]->arg
, afi
,
9250 bgp_show_type_prefix_longer
);
9255 /* BGP route print out function with JSON */
9256 DEFUN (show_ip_bgp_json
,
9257 show_ip_bgp_json_cmd
,
9258 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
9261 |dampening <flap-statistics|dampened-paths>\
9262 |community [<AA:NN|local-AS|no-advertise|no-export|graceful-shutdown>] [exact-match]\
9267 BGP_INSTANCE_HELP_STR
9269 BGP_SAFI_WITH_LABEL_HELP_STR
9270 "Display only routes with non-natural netmasks\n"
9271 "Display detailed information about dampening\n"
9272 "Display flap statistics of routes\n"
9273 "Display paths suppressed due to dampening\n"
9274 "Display routes matching the communities\n"
9276 "Do not send outside local AS (well-known community)\n"
9277 "Do not advertise to any peer (well-known community)\n"
9278 "Do not export to next AS (well-known community)\n"
9279 "Graceful shutdown (well-known community)\n"
9280 "Exact match of the communities\n"
9283 afi_t afi
= AFI_IP6
;
9284 safi_t safi
= SAFI_UNICAST
;
9285 enum bgp_show_type sh_type
= bgp_show_type_normal
;
9286 struct bgp
*bgp
= NULL
;
9288 int idx_community_type
= 0;
9289 int exact_match
= 0;
9290 bool uj
= use_json(argc
, argv
);
9295 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9300 if (argv_find(argv
, argc
, "cidr-only", &idx
))
9301 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_cidr_only
,
9304 if (argv_find(argv
, argc
, "dampening", &idx
)) {
9305 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
9306 return bgp_show(vty
, bgp
, afi
, safi
,
9307 bgp_show_type_dampend_paths
, NULL
, uj
);
9308 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
9309 return bgp_show(vty
, bgp
, afi
, safi
,
9310 bgp_show_type_flap_statistics
, NULL
,
9314 if (argv_find(argv
, argc
, "community", &idx
)) {
9316 /* show a specific community */
9317 if (argv_find(argv
, argc
, "local-AS", &idx_community_type
) ||
9318 argv_find(argv
, argc
, "no-advertise",
9319 &idx_community_type
) ||
9320 argv_find(argv
, argc
, "no-export",
9321 &idx_community_type
) ||
9322 argv_find(argv
, argc
, "graceful-shutdown",
9323 &idx_community_type
) ||
9324 argv_find(argv
, argc
, "AA:NN", &idx_community_type
)) {
9325 if (argv_find(argv
, argc
, "exact-match", &idx
))
9328 return (bgp_show_community(vty
, bgp
,
9329 argv
[idx_community_type
]->arg
,
9330 exact_match
, afi
, safi
, uj
));
9333 /* show all communities */
9334 return (bgp_show(vty
, bgp
, afi
, safi
,
9335 bgp_show_type_community_all
, NULL
,
9340 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
, NULL
, uj
);
9343 DEFUN (show_ip_bgp_route
,
9344 show_ip_bgp_route_cmd
,
9345 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]"
9346 "<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [json]",
9350 BGP_INSTANCE_HELP_STR
9352 BGP_SAFI_WITH_LABEL_HELP_STR
9353 "Network in the BGP routing table to display\n"
9355 "Network in the BGP routing table to display\n"
9357 "Display only the bestpath\n"
9358 "Display only multipaths\n"
9361 int prefix_check
= 0;
9363 afi_t afi
= AFI_IP6
;
9364 safi_t safi
= SAFI_UNICAST
;
9365 char *prefix
= NULL
;
9366 struct bgp
*bgp
= NULL
;
9367 enum bgp_path_type path_type
;
9368 bool uj
= use_json(argc
, argv
);
9372 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9379 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
9383 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
9384 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
9385 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
9387 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
9388 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
9391 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
9392 && afi
!= AFI_IP6
) {
9394 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
9397 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
9400 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
9404 prefix
= argv
[idx
]->arg
;
9406 /* [<bestpath|multipath>] */
9407 if (argv_find(argv
, argc
, "bestpath", &idx
))
9408 path_type
= BGP_PATH_BESTPATH
;
9409 else if (argv_find(argv
, argc
, "multipath", &idx
))
9410 path_type
= BGP_PATH_MULTIPATH
;
9412 path_type
= BGP_PATH_ALL
;
9414 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
9418 DEFUN (show_ip_bgp_regexp
,
9419 show_ip_bgp_regexp_cmd
,
9420 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX...",
9424 BGP_INSTANCE_HELP_STR
9426 BGP_SAFI_WITH_LABEL_HELP_STR
9427 "Display routes matching the AS path regular expression\n"
9428 "A regular-expression to match the BGP AS paths\n")
9430 afi_t afi
= AFI_IP6
;
9431 safi_t safi
= SAFI_UNICAST
;
9432 struct bgp
*bgp
= NULL
;
9435 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9440 // get index of regex
9441 argv_find(argv
, argc
, "regexp", &idx
);
9444 char *regstr
= argv_concat(argv
, argc
, idx
);
9445 int rc
= bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
9446 bgp_show_type_regexp
);
9447 XFREE(MTYPE_TMP
, regstr
);
9451 DEFUN (show_ip_bgp_instance_all
,
9452 show_ip_bgp_instance_all_cmd
,
9453 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json]",
9457 BGP_INSTANCE_ALL_HELP_STR
9459 BGP_SAFI_WITH_LABEL_HELP_STR
9463 safi_t safi
= SAFI_UNICAST
;
9464 struct bgp
*bgp
= NULL
;
9466 bool uj
= use_json(argc
, argv
);
9471 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9476 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, uj
);
9480 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
9481 afi_t afi
, safi_t safi
, enum bgp_show_type type
)
9486 regex
= bgp_regcomp(regstr
);
9488 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
9492 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, 0);
9493 bgp_regex_free(regex
);
9497 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
9498 const char *prefix_list_str
, afi_t afi
,
9499 safi_t safi
, enum bgp_show_type type
)
9501 struct prefix_list
*plist
;
9503 plist
= prefix_list_lookup(afi
, prefix_list_str
);
9504 if (plist
== NULL
) {
9505 vty_out(vty
, "%% %s is not a valid prefix-list name\n",
9510 return bgp_show(vty
, bgp
, afi
, safi
, type
, plist
, 0);
9513 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
9514 const char *filter
, afi_t afi
, safi_t safi
,
9515 enum bgp_show_type type
)
9517 struct as_list
*as_list
;
9519 as_list
= as_list_lookup(filter
);
9520 if (as_list
== NULL
) {
9521 vty_out(vty
, "%% %s is not a valid AS-path access-list name\n",
9526 return bgp_show(vty
, bgp
, afi
, safi
, type
, as_list
, 0);
9529 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
9530 const char *rmap_str
, afi_t afi
, safi_t safi
,
9531 enum bgp_show_type type
)
9533 struct route_map
*rmap
;
9535 rmap
= route_map_lookup_by_name(rmap_str
);
9537 vty_out(vty
, "%% %s is not a valid route-map name\n", rmap_str
);
9541 return bgp_show(vty
, bgp
, afi
, safi
, type
, rmap
, 0);
9544 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
9545 const char *comstr
, int exact
, afi_t afi
,
9546 safi_t safi
, bool use_json
)
9548 struct community
*com
;
9551 com
= community_str2com(comstr
);
9553 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
9557 ret
= bgp_show(vty
, bgp
, afi
, safi
,
9558 (exact
? bgp_show_type_community_exact
9559 : bgp_show_type_community
),
9561 community_free(com
);
9566 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
9567 const char *com
, int exact
, afi_t afi
,
9570 struct community_list
*list
;
9572 list
= community_list_lookup(bgp_clist
, com
, COMMUNITY_LIST_MASTER
);
9574 vty_out(vty
, "%% %s is not a valid community-list name\n", com
);
9578 return bgp_show(vty
, bgp
, afi
, safi
,
9579 (exact
? bgp_show_type_community_list_exact
9580 : bgp_show_type_community_list
),
9584 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
9585 const char *prefix
, afi_t afi
, safi_t safi
,
9586 enum bgp_show_type type
)
9593 ret
= str2prefix(prefix
, p
);
9595 vty_out(vty
, "%% Malformed Prefix\n");
9599 ret
= bgp_show(vty
, bgp
, afi
, safi
, type
, p
, 0);
9604 static struct peer
*peer_lookup_in_view(struct vty
*vty
, struct bgp
*bgp
,
9605 const char *ip_str
, bool use_json
)
9611 /* Get peer sockunion. */
9612 ret
= str2sockunion(ip_str
, &su
);
9614 peer
= peer_lookup_by_conf_if(bgp
, ip_str
);
9616 peer
= peer_lookup_by_hostname(bgp
, ip_str
);
9620 json_object
*json_no
= NULL
;
9621 json_no
= json_object_new_object();
9622 json_object_string_add(
9624 "malformedAddressOrName",
9626 vty_out(vty
, "%s\n",
9627 json_object_to_json_string_ext(
9629 JSON_C_TO_STRING_PRETTY
));
9630 json_object_free(json_no
);
9633 "%% Malformed address or name: %s\n",
9641 /* Peer structure lookup. */
9642 peer
= peer_lookup(bgp
, &su
);
9645 json_object
*json_no
= NULL
;
9646 json_no
= json_object_new_object();
9647 json_object_string_add(json_no
, "warning",
9648 "No such neighbor in this view/vrf");
9649 vty_out(vty
, "%s\n",
9650 json_object_to_json_string_ext(
9651 json_no
, JSON_C_TO_STRING_PRETTY
));
9652 json_object_free(json_no
);
9654 vty_out(vty
, "No such neighbor in this view/vrf\n");
9662 BGP_STATS_MAXBITLEN
= 0,
9666 BGP_STATS_UNAGGREGATEABLE
,
9667 BGP_STATS_MAX_AGGREGATEABLE
,
9668 BGP_STATS_AGGREGATES
,
9670 BGP_STATS_ASPATH_COUNT
,
9671 BGP_STATS_ASPATH_MAXHOPS
,
9672 BGP_STATS_ASPATH_TOTHOPS
,
9673 BGP_STATS_ASPATH_MAXSIZE
,
9674 BGP_STATS_ASPATH_TOTSIZE
,
9675 BGP_STATS_ASN_HIGHEST
,
9679 static const char *table_stats_strs
[] = {
9680 [BGP_STATS_PREFIXES
] = "Total Prefixes",
9681 [BGP_STATS_TOTPLEN
] = "Average prefix length",
9682 [BGP_STATS_RIB
] = "Total Advertisements",
9683 [BGP_STATS_UNAGGREGATEABLE
] = "Unaggregateable prefixes",
9684 [BGP_STATS_MAX_AGGREGATEABLE
] =
9685 "Maximum aggregateable prefixes",
9686 [BGP_STATS_AGGREGATES
] = "BGP Aggregate advertisements",
9687 [BGP_STATS_SPACE
] = "Address space advertised",
9688 [BGP_STATS_ASPATH_COUNT
] = "Advertisements with paths",
9689 [BGP_STATS_ASPATH_MAXHOPS
] = "Longest AS-Path (hops)",
9690 [BGP_STATS_ASPATH_MAXSIZE
] = "Largest AS-Path (bytes)",
9691 [BGP_STATS_ASPATH_TOTHOPS
] = "Average AS-Path length (hops)",
9692 [BGP_STATS_ASPATH_TOTSIZE
] = "Average AS-Path size (bytes)",
9693 [BGP_STATS_ASN_HIGHEST
] = "Highest public ASN",
9694 [BGP_STATS_MAX
] = NULL
,
9697 struct bgp_table_stats
{
9698 struct bgp_table
*table
;
9699 unsigned long long counts
[BGP_STATS_MAX
];
9704 #define TALLY_SIGFIG 100000
9705 static unsigned long
9706 ravg_tally (unsigned long count
, unsigned long oldavg
, unsigned long newval
)
9708 unsigned long newtot
= (count
-1) * oldavg
+ (newval
* TALLY_SIGFIG
);
9709 unsigned long res
= (newtot
* TALLY_SIGFIG
) / count
;
9710 unsigned long ret
= newtot
/ count
;
9712 if ((res
% TALLY_SIGFIG
) > (TALLY_SIGFIG
/2))
9719 static int bgp_table_stats_walker(struct thread
*t
)
9721 struct bgp_node
*rn
;
9722 struct bgp_node
*top
;
9723 struct bgp_table_stats
*ts
= THREAD_ARG(t
);
9724 unsigned int space
= 0;
9726 if (!(top
= bgp_table_top(ts
->table
)))
9729 switch (top
->p
.family
) {
9731 space
= IPV4_MAX_BITLEN
;
9734 space
= IPV6_MAX_BITLEN
;
9738 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
9740 for (rn
= top
; rn
; rn
= bgp_route_next(rn
)) {
9741 struct bgp_info
*ri
;
9742 struct bgp_node
*prn
= bgp_node_parent_nolock(rn
);
9743 unsigned int rinum
= 0;
9751 ts
->counts
[BGP_STATS_PREFIXES
]++;
9752 ts
->counts
[BGP_STATS_TOTPLEN
] += rn
->p
.prefixlen
;
9755 ts
->counts
[BGP_STATS_AVGPLEN
]
9756 = ravg_tally (ts
->counts
[BGP_STATS_PREFIXES
],
9757 ts
->counts
[BGP_STATS_AVGPLEN
],
9761 /* check if the prefix is included by any other announcements */
9762 while (prn
&& !prn
->info
)
9763 prn
= bgp_node_parent_nolock(prn
);
9765 if (prn
== NULL
|| prn
== top
) {
9766 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
9767 /* announced address space */
9770 pow(2.0, space
- rn
->p
.prefixlen
);
9771 } else if (prn
->info
)
9772 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
9774 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
9776 ts
->counts
[BGP_STATS_RIB
]++;
9779 && (CHECK_FLAG(ri
->attr
->flag
,
9781 BGP_ATTR_ATOMIC_AGGREGATE
))))
9782 ts
->counts
[BGP_STATS_AGGREGATES
]++;
9785 if (ri
->attr
&& ri
->attr
->aspath
) {
9787 aspath_count_hops(ri
->attr
->aspath
);
9789 aspath_size(ri
->attr
->aspath
);
9790 as_t highest
= aspath_highest(ri
->attr
->aspath
);
9792 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
9794 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
9795 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] =
9798 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
9799 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] =
9802 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
9803 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
9805 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
]
9806 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
9807 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
],
9809 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
]
9810 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
9811 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
],
9814 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
9815 ts
->counts
[BGP_STATS_ASN_HIGHEST
] =
9823 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
9826 struct bgp_table_stats ts
;
9829 if (!bgp
->rib
[afi
][safi
]) {
9830 vty_out(vty
, "%% No RIB exist's for the AFI(%d)/SAFI(%d)\n",
9835 vty_out(vty
, "BGP %s RIB statistics\n", afi_safi_print(afi
, safi
));
9837 /* labeled-unicast routes live in the unicast table */
9838 if (safi
== SAFI_LABELED_UNICAST
)
9839 safi
= SAFI_UNICAST
;
9841 memset(&ts
, 0, sizeof(ts
));
9842 ts
.table
= bgp
->rib
[afi
][safi
];
9843 thread_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
9845 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
9846 if (!table_stats_strs
[i
])
9851 case BGP_STATS_ASPATH_AVGHOPS
:
9852 case BGP_STATS_ASPATH_AVGSIZE
:
9853 case BGP_STATS_AVGPLEN
:
9854 vty_out (vty
, "%-30s: ", table_stats_strs
[i
]);
9855 vty_out (vty
, "%12.2f",
9856 (float)ts
.counts
[i
] / (float)TALLY_SIGFIG
);
9859 case BGP_STATS_ASPATH_TOTHOPS
:
9860 case BGP_STATS_ASPATH_TOTSIZE
:
9861 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9862 vty_out(vty
, "%12.2f",
9864 ? (float)ts
.counts
[i
]
9866 [BGP_STATS_ASPATH_COUNT
]
9869 case BGP_STATS_TOTPLEN
:
9870 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9871 vty_out(vty
, "%12.2f",
9873 ? (float)ts
.counts
[i
]
9875 [BGP_STATS_PREFIXES
]
9878 case BGP_STATS_SPACE
:
9879 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9880 vty_out(vty
, "%12g\n", ts
.total_space
);
9882 if (afi
== AFI_IP6
) {
9883 vty_out(vty
, "%30s: ", "/32 equivalent ");
9884 vty_out(vty
, "%12g\n",
9885 ts
.total_space
* pow(2.0, -128 + 32));
9886 vty_out(vty
, "%30s: ", "/48 equivalent ");
9887 vty_out(vty
, "%12g\n",
9888 ts
.total_space
* pow(2.0, -128 + 48));
9890 vty_out(vty
, "%30s: ", "% announced ");
9891 vty_out(vty
, "%12.2f\n",
9892 ts
.total_space
* 100. * pow(2.0, -32));
9893 vty_out(vty
, "%30s: ", "/8 equivalent ");
9894 vty_out(vty
, "%12.2f\n",
9895 ts
.total_space
* pow(2.0, -32 + 8));
9896 vty_out(vty
, "%30s: ", "/24 equivalent ");
9897 vty_out(vty
, "%12.2f\n",
9898 ts
.total_space
* pow(2.0, -32 + 24));
9902 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9903 vty_out(vty
, "%12llu", ts
.counts
[i
]);
9920 PCOUNT_PFCNT
, /* the figure we display to users */
9924 static const char *pcount_strs
[] = {
9925 [PCOUNT_ADJ_IN
] = "Adj-in",
9926 [PCOUNT_DAMPED
] = "Damped",
9927 [PCOUNT_REMOVED
] = "Removed",
9928 [PCOUNT_HISTORY
] = "History",
9929 [PCOUNT_STALE
] = "Stale",
9930 [PCOUNT_VALID
] = "Valid",
9931 [PCOUNT_ALL
] = "All RIB",
9932 [PCOUNT_COUNTED
] = "PfxCt counted",
9933 [PCOUNT_PFCNT
] = "Useable",
9934 [PCOUNT_MAX
] = NULL
,
9937 struct peer_pcounts
{
9938 unsigned int count
[PCOUNT_MAX
];
9939 const struct peer
*peer
;
9940 const struct bgp_table
*table
;
9943 static int bgp_peer_count_walker(struct thread
*t
)
9945 struct bgp_node
*rn
;
9946 struct peer_pcounts
*pc
= THREAD_ARG(t
);
9947 const struct peer
*peer
= pc
->peer
;
9949 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
)) {
9950 struct bgp_adj_in
*ain
;
9951 struct bgp_info
*ri
;
9953 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
9954 if (ain
->peer
== peer
)
9955 pc
->count
[PCOUNT_ADJ_IN
]++;
9957 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
9958 if (ri
->peer
!= peer
)
9961 pc
->count
[PCOUNT_ALL
]++;
9963 if (CHECK_FLAG(ri
->flags
, BGP_INFO_DAMPED
))
9964 pc
->count
[PCOUNT_DAMPED
]++;
9965 if (CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
9966 pc
->count
[PCOUNT_HISTORY
]++;
9967 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
))
9968 pc
->count
[PCOUNT_REMOVED
]++;
9969 if (CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
))
9970 pc
->count
[PCOUNT_STALE
]++;
9971 if (CHECK_FLAG(ri
->flags
, BGP_INFO_VALID
))
9972 pc
->count
[PCOUNT_VALID
]++;
9973 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
9974 pc
->count
[PCOUNT_PFCNT
]++;
9976 if (CHECK_FLAG(ri
->flags
, BGP_INFO_COUNTED
)) {
9977 pc
->count
[PCOUNT_COUNTED
]++;
9978 if (CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
9981 "Attempting to count but flags say it is unusable");
9983 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
9986 "Not counted but flags say we should");
9993 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
9994 safi_t safi
, bool use_json
)
9996 struct peer_pcounts pcounts
= {.peer
= peer
};
9998 json_object
*json
= NULL
;
9999 json_object
*json_loop
= NULL
;
10002 json
= json_object_new_object();
10003 json_loop
= json_object_new_object();
10006 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
10007 || !peer
->bgp
->rib
[afi
][safi
]) {
10009 json_object_string_add(
10011 "No such neighbor or address family");
10012 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10013 json_object_free(json
);
10015 vty_out(vty
, "%% No such neighbor or address family\n");
10017 return CMD_WARNING
;
10020 memset(&pcounts
, 0, sizeof(pcounts
));
10021 pcounts
.peer
= peer
;
10022 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
10024 /* in-place call via thread subsystem so as to record execution time
10025 * stats for the thread-walk (i.e. ensure this can't be blamed on
10026 * on just vty_read()).
10028 thread_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
10031 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
10032 json_object_string_add(json
, "multiProtocol",
10033 afi_safi_print(afi
, safi
));
10034 json_object_int_add(json
, "pfxCounter",
10035 peer
->pcount
[afi
][safi
]);
10037 for (i
= 0; i
< PCOUNT_MAX
; i
++)
10038 json_object_int_add(json_loop
, pcount_strs
[i
],
10041 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
10043 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
10044 json_object_string_add(json
, "pfxctDriftFor",
10046 json_object_string_add(
10047 json
, "recommended",
10048 "Please report this bug, with the above command output");
10050 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
10051 json
, JSON_C_TO_STRING_PRETTY
));
10052 json_object_free(json
);
10056 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
10057 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
10058 peer
->hostname
, peer
->host
,
10059 afi_safi_print(afi
, safi
));
10061 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
10062 afi_safi_print(afi
, safi
));
10065 vty_out(vty
, "PfxCt: %ld\n", peer
->pcount
[afi
][safi
]);
10066 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
10068 for (i
= 0; i
< PCOUNT_MAX
; i
++)
10069 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
10072 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
10073 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
10075 "Please report this bug, with the above command output\n");
10079 return CMD_SUCCESS
;
10082 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
10083 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
10084 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_CMD_STR
"]] "
10085 "neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
10089 BGP_INSTANCE_HELP_STR
10092 "Detailed information on TCP and BGP neighbor connections\n"
10093 "Neighbor to display information about\n"
10094 "Neighbor to display information about\n"
10095 "Neighbor on BGP configured interface\n"
10096 "Display detailed prefix count information\n"
10099 afi_t afi
= AFI_IP6
;
10100 safi_t safi
= SAFI_UNICAST
;
10103 struct bgp
*bgp
= NULL
;
10104 bool uj
= use_json(argc
, argv
);
10109 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10112 return CMD_WARNING
;
10114 argv_find(argv
, argc
, "neighbors", &idx
);
10115 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
10117 return CMD_WARNING
;
10119 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_UNICAST
, uj
);
10122 #ifdef KEEP_OLD_VPN_COMMANDS
10123 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
10124 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
10125 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
10130 "Display information about all VPNv4 NLRIs\n"
10131 "Detailed information on TCP and BGP neighbor connections\n"
10132 "Neighbor to display information about\n"
10133 "Neighbor to display information about\n"
10134 "Neighbor on BGP configured interface\n"
10135 "Display detailed prefix count information\n"
10140 bool uj
= use_json(argc
, argv
);
10142 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
10144 return CMD_WARNING
;
10146 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
10149 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
10150 show_ip_bgp_vpn_all_route_prefix_cmd
,
10151 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
10156 "Display information about all VPNv4 NLRIs\n"
10157 "Network in the BGP routing table to display\n"
10158 "Network in the BGP routing table to display\n"
10162 char *network
= NULL
;
10163 struct bgp
*bgp
= bgp_get_default();
10165 vty_out(vty
, "Can't find default instance\n");
10166 return CMD_WARNING
;
10169 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
10170 network
= argv
[idx
]->arg
;
10171 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
10172 network
= argv
[idx
]->arg
;
10174 vty_out(vty
, "Unable to figure out Network\n");
10175 return CMD_WARNING
;
10178 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
10179 BGP_PATH_ALL
, use_json(argc
, argv
));
10181 #endif /* KEEP_OLD_VPN_COMMANDS */
10183 DEFUN (show_ip_bgp_l2vpn_evpn_all_route_prefix
,
10184 show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd
,
10185 "show [ip] bgp l2vpn evpn all <A.B.C.D|A.B.C.D/M> [json]",
10191 "Display information about all EVPN NLRIs\n"
10192 "Network in the BGP routing table to display\n"
10193 "Network in the BGP routing table to display\n"
10197 char *network
= NULL
;
10199 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
10200 network
= argv
[idx
]->arg
;
10201 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
10202 network
= argv
[idx
]->arg
;
10204 vty_out(vty
, "Unable to figure out Network\n");
10205 return CMD_WARNING
;
10207 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
, 0,
10208 BGP_PATH_ALL
, use_json(argc
, argv
));
10211 static void show_adj_route(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
10212 safi_t safi
, enum bgp_show_adj_route_type type
,
10213 const char *rmap_name
, bool use_json
,
10216 struct bgp_table
*table
;
10217 struct bgp_adj_in
*ain
;
10218 struct bgp_adj_out
*adj
;
10219 unsigned long output_count
;
10220 unsigned long filtered_count
;
10221 struct bgp_node
*rn
;
10227 struct update_subgroup
*subgrp
;
10228 json_object
*json_scode
= NULL
;
10229 json_object
*json_ocode
= NULL
;
10230 json_object
*json_ar
= NULL
;
10231 struct peer_af
*paf
;
10232 bool route_filtered
;
10235 json_scode
= json_object_new_object();
10236 json_ocode
= json_object_new_object();
10237 json_ar
= json_object_new_object();
10239 json_object_string_add(json_scode
, "suppressed", "s");
10240 json_object_string_add(json_scode
, "damped", "d");
10241 json_object_string_add(json_scode
, "history", "h");
10242 json_object_string_add(json_scode
, "valid", "*");
10243 json_object_string_add(json_scode
, "best", ">");
10244 json_object_string_add(json_scode
, "multipath", "=");
10245 json_object_string_add(json_scode
, "internal", "i");
10246 json_object_string_add(json_scode
, "ribFailure", "r");
10247 json_object_string_add(json_scode
, "stale", "S");
10248 json_object_string_add(json_scode
, "removed", "R");
10250 json_object_string_add(json_ocode
, "igp", "i");
10251 json_object_string_add(json_ocode
, "egp", "e");
10252 json_object_string_add(json_ocode
, "incomplete", "?");
10259 json_object_string_add(json
, "alert", "no BGP");
10260 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10261 json_object_free(json
);
10263 vty_out(vty
, "%% No bgp\n");
10267 table
= bgp
->rib
[afi
][safi
];
10269 output_count
= filtered_count
= 0;
10270 subgrp
= peer_subgroup(peer
, afi
, safi
);
10272 if (type
== bgp_show_adj_route_advertised
&& subgrp
10273 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
10275 json_object_int_add(json
, "bgpTableVersion",
10277 json_object_string_add(json
, "bgpLocalRouterId",
10278 inet_ntoa(bgp
->router_id
));
10279 json_object_object_add(json
, "bgpStatusCodes",
10281 json_object_object_add(json
, "bgpOriginCodes",
10283 json_object_string_add(
10284 json
, "bgpOriginatingDefaultNetwork",
10285 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
10287 vty_out(vty
, "BGP table version is %" PRIu64
10288 ", local router ID is %s, vrf id ",
10289 table
->version
, inet_ntoa(bgp
->router_id
));
10290 if (bgp
->vrf_id
== VRF_UNKNOWN
)
10291 vty_out(vty
, "%s", VRFID_NONE_STR
);
10293 vty_out(vty
, "%u", bgp
->vrf_id
);
10294 vty_out(vty
, "\n");
10295 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
10296 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
10297 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
10299 vty_out(vty
, "Originating default network %s\n\n",
10300 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
10305 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
10306 if (type
== bgp_show_adj_route_received
10307 || type
== bgp_show_adj_route_filtered
) {
10308 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
10309 if (ain
->peer
!= peer
|| !ain
->attr
)
10314 json_object_int_add(
10315 json
, "bgpTableVersion",
10317 json_object_string_add(
10319 "bgpLocalRouterId",
10322 json_object_object_add(
10323 json
, "bgpStatusCodes",
10325 json_object_object_add(
10326 json
, "bgpOriginCodes",
10330 "BGP table version is 0, local router ID is %s, vrf id ",
10333 if (bgp
->vrf_id
== VRF_UNKNOWN
)
10339 vty_out(vty
, "\n");
10341 BGP_SHOW_SCODE_HEADER
);
10343 BGP_SHOW_NCODE_HEADER
);
10345 BGP_SHOW_OCODE_HEADER
);
10351 vty_out(vty
, BGP_SHOW_HEADER
);
10355 bgp_attr_dup(&attr
, ain
->attr
);
10356 route_filtered
= false;
10358 /* Filter prefix using distribute list,
10359 * filter list or prefix list
10361 if ((bgp_input_filter(peer
, &rn
->p
, &attr
, afi
,
10362 safi
)) == FILTER_DENY
)
10363 route_filtered
= true;
10365 /* Filter prefix using route-map */
10366 ret
= bgp_input_modifier(peer
, &rn
->p
, &attr
,
10367 afi
, safi
, rmap_name
);
10369 if (type
== bgp_show_adj_route_filtered
&&
10370 !route_filtered
&& ret
!= RMAP_DENY
) {
10371 bgp_attr_undup(&attr
, ain
->attr
);
10375 if (type
== bgp_show_adj_route_received
&&
10376 (route_filtered
|| ret
== RMAP_DENY
))
10379 route_vty_out_tmp(vty
, &rn
->p
, &attr
, safi
,
10380 use_json
, json_ar
);
10381 bgp_attr_undup(&attr
, ain
->attr
);
10384 } else if (type
== bgp_show_adj_route_advertised
) {
10385 for (adj
= rn
->adj_out
; adj
; adj
= adj
->next
)
10386 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
10387 if (paf
->peer
!= peer
|| !adj
->attr
)
10392 json_object_int_add(
10396 json_object_string_add(
10398 "bgpLocalRouterId",
10401 json_object_object_add(
10405 json_object_object_add(
10411 "BGP table version is %" PRIu64
10412 ", local router ID is %s, vrf id ",
10425 vty_out(vty
, "\n");
10427 BGP_SHOW_SCODE_HEADER
);
10429 BGP_SHOW_NCODE_HEADER
);
10431 BGP_SHOW_OCODE_HEADER
);
10442 bgp_attr_dup(&attr
, adj
->attr
);
10443 ret
= bgp_output_modifier(
10444 peer
, &rn
->p
, &attr
, afi
, safi
,
10447 if (ret
!= RMAP_DENY
) {
10448 route_vty_out_tmp(vty
, &rn
->p
,
10457 bgp_attr_undup(&attr
, adj
->attr
);
10463 json_object_object_add(json
, "advertisedRoutes", json_ar
);
10464 json_object_int_add(json
, "totalPrefixCounter", output_count
);
10465 json_object_int_add(json
, "filteredPrefixCounter",
10468 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
10469 json
, JSON_C_TO_STRING_PRETTY
));
10470 json_object_free(json
);
10471 } else if (output_count
> 0) {
10472 if (filtered_count
> 0)
10474 "\nTotal number of prefixes %ld (%ld filtered)\n",
10475 output_count
, filtered_count
);
10477 vty_out(vty
, "\nTotal number of prefixes %ld\n",
10482 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
10483 safi_t safi
, enum bgp_show_adj_route_type type
,
10484 const char *rmap_name
, bool use_json
)
10486 json_object
*json
= NULL
;
10489 json
= json_object_new_object();
10491 /* labeled-unicast routes live in the unicast table */
10492 if (safi
== SAFI_LABELED_UNICAST
)
10493 safi
= SAFI_UNICAST
;
10495 if (!peer
|| !peer
->afc
[afi
][safi
]) {
10497 json_object_string_add(
10499 "No such neighbor or address family");
10500 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10501 json_object_free(json
);
10503 vty_out(vty
, "%% No such neighbor or address family\n");
10505 return CMD_WARNING
;
10508 if ((type
== bgp_show_adj_route_received
10509 || type
== bgp_show_adj_route_filtered
)
10510 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
10511 PEER_FLAG_SOFT_RECONFIG
)) {
10513 json_object_string_add(
10515 "Inbound soft reconfiguration not enabled");
10516 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10517 json_object_free(json
);
10520 "%% Inbound soft reconfiguration not enabled\n");
10522 return CMD_WARNING
;
10525 show_adj_route(vty
, peer
, afi
, safi
, type
, rmap_name
, use_json
, json
);
10527 return CMD_SUCCESS
;
10530 DEFUN (show_ip_bgp_instance_neighbor_advertised_route
,
10531 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
10532 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
10533 "neighbors <A.B.C.D|X:X::X:X|WORD> <advertised-routes|received-routes|filtered-routes> [route-map WORD] [json]",
10537 BGP_INSTANCE_HELP_STR
10539 BGP_SAFI_WITH_LABEL_HELP_STR
10540 "Detailed information on TCP and BGP neighbor connections\n"
10541 "Neighbor to display information about\n"
10542 "Neighbor to display information about\n"
10543 "Neighbor on BGP configured interface\n"
10544 "Display the routes advertised to a BGP neighbor\n"
10545 "Display the received routes from neighbor\n"
10546 "Display the filtered routes received from neighbor\n"
10547 "Route-map to modify the attributes\n"
10548 "Name of the route map\n"
10551 afi_t afi
= AFI_IP6
;
10552 safi_t safi
= SAFI_UNICAST
;
10553 char *rmap_name
= NULL
;
10554 char *peerstr
= NULL
;
10555 struct bgp
*bgp
= NULL
;
10557 enum bgp_show_adj_route_type type
= bgp_show_adj_route_advertised
;
10559 bool uj
= use_json(argc
, argv
);
10564 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10567 return CMD_WARNING
;
10569 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10570 argv_find(argv
, argc
, "neighbors", &idx
);
10571 peerstr
= argv
[++idx
]->arg
;
10573 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
10575 return CMD_WARNING
;
10577 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
10578 type
= bgp_show_adj_route_advertised
;
10579 else if (argv_find(argv
, argc
, "received-routes", &idx
))
10580 type
= bgp_show_adj_route_received
;
10581 else if (argv_find(argv
, argc
, "filtered-routes", &idx
))
10582 type
= bgp_show_adj_route_filtered
;
10584 if (argv_find(argv
, argc
, "route-map", &idx
))
10585 rmap_name
= argv
[++idx
]->arg
;
10587 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
, uj
);
10590 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
10591 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
10592 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
10598 "Address Family modifier\n"
10599 "Detailed information on TCP and BGP neighbor connections\n"
10600 "Neighbor to display information about\n"
10601 "Neighbor to display information about\n"
10602 "Neighbor on BGP configured interface\n"
10603 "Display information received from a BGP neighbor\n"
10604 "Display the prefixlist filter\n"
10607 afi_t afi
= AFI_IP6
;
10608 safi_t safi
= SAFI_UNICAST
;
10609 char *peerstr
= NULL
;
10612 union sockunion su
;
10618 /* show [ip] bgp */
10619 if (argv_find(argv
, argc
, "ip", &idx
))
10621 /* [<ipv4|ipv6> [unicast]] */
10622 if (argv_find(argv
, argc
, "ipv4", &idx
))
10624 if (argv_find(argv
, argc
, "ipv6", &idx
))
10626 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10627 argv_find(argv
, argc
, "neighbors", &idx
);
10628 peerstr
= argv
[++idx
]->arg
;
10630 bool uj
= use_json(argc
, argv
);
10632 ret
= str2sockunion(peerstr
, &su
);
10634 peer
= peer_lookup_by_conf_if(NULL
, peerstr
);
10637 vty_out(vty
, "{}\n");
10640 "%% Malformed address or name: %s\n",
10642 return CMD_WARNING
;
10645 peer
= peer_lookup(NULL
, &su
);
10648 vty_out(vty
, "{}\n");
10650 vty_out(vty
, "No peer\n");
10651 return CMD_WARNING
;
10655 sprintf(name
, "%s.%d.%d", peer
->host
, afi
, safi
);
10656 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
10659 vty_out(vty
, "Address Family: %s\n",
10660 afi_safi_print(afi
, safi
));
10661 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
10664 vty_out(vty
, "{}\n");
10666 vty_out(vty
, "No functional output\n");
10669 return CMD_SUCCESS
;
10672 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
10673 afi_t afi
, safi_t safi
,
10674 enum bgp_show_type type
, bool use_json
)
10676 /* labeled-unicast routes live in the unicast table */
10677 if (safi
== SAFI_LABELED_UNICAST
)
10678 safi
= SAFI_UNICAST
;
10680 if (!peer
|| !peer
->afc
[afi
][safi
]) {
10682 json_object
*json_no
= NULL
;
10683 json_no
= json_object_new_object();
10684 json_object_string_add(
10685 json_no
, "warning",
10686 "No such neighbor or address family");
10687 vty_out(vty
, "%s\n",
10688 json_object_to_json_string(json_no
));
10689 json_object_free(json_no
);
10691 vty_out(vty
, "%% No such neighbor or address family\n");
10692 return CMD_WARNING
;
10695 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, use_json
);
10698 DEFUN (show_ip_bgp_flowspec_routes_detailed
,
10699 show_ip_bgp_flowspec_routes_detailed_cmd
,
10700 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" flowspec] detail [json]",
10704 BGP_INSTANCE_HELP_STR
10707 "Detailed information on flowspec entries\n"
10710 afi_t afi
= AFI_IP
;
10711 safi_t safi
= SAFI_UNICAST
;
10712 struct bgp
*bgp
= NULL
;
10714 bool uj
= use_json(argc
, argv
);
10719 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10722 return CMD_WARNING
;
10724 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_detail
, NULL
, uj
);
10727 DEFUN (show_ip_bgp_neighbor_routes
,
10728 show_ip_bgp_neighbor_routes_cmd
,
10729 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
10730 "neighbors <A.B.C.D|X:X::X:X|WORD> <flap-statistics|dampened-routes|routes> [json]",
10734 BGP_INSTANCE_HELP_STR
10736 BGP_SAFI_WITH_LABEL_HELP_STR
10737 "Detailed information on TCP and BGP neighbor connections\n"
10738 "Neighbor to display information about\n"
10739 "Neighbor to display information about\n"
10740 "Neighbor on BGP configured interface\n"
10741 "Display flap statistics of the routes learned from neighbor\n"
10742 "Display the dampened routes received from neighbor\n"
10743 "Display routes learned from neighbor\n"
10746 char *peerstr
= NULL
;
10747 struct bgp
*bgp
= NULL
;
10748 afi_t afi
= AFI_IP6
;
10749 safi_t safi
= SAFI_UNICAST
;
10751 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
10753 bool uj
= use_json(argc
, argv
);
10758 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10761 return CMD_WARNING
;
10763 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10764 argv_find(argv
, argc
, "neighbors", &idx
);
10765 peerstr
= argv
[++idx
]->arg
;
10767 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
10769 return CMD_WARNING
;
10771 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
10772 sh_type
= bgp_show_type_flap_neighbor
;
10773 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
10774 sh_type
= bgp_show_type_damp_neighbor
;
10775 else if (argv_find(argv
, argc
, "routes", &idx
))
10776 sh_type
= bgp_show_type_neighbor
;
10778 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
10781 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
10783 struct bgp_distance
{
10784 /* Distance value for the IP source prefix. */
10787 /* Name of the access-list to be matched. */
10791 DEFUN (show_bgp_afi_vpn_rd_route
,
10792 show_bgp_afi_vpn_rd_route_cmd
,
10793 "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]",
10797 "Address Family modifier\n"
10798 "Display information for a route distinguisher\n"
10799 "Route Distinguisher\n"
10800 "Network in the BGP routing table to display\n"
10801 "Network in the BGP routing table to display\n"
10805 struct prefix_rd prd
;
10806 afi_t afi
= AFI_MAX
;
10809 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
10810 vty_out(vty
, "%% Malformed Address Family\n");
10811 return CMD_WARNING
;
10814 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
10816 vty_out(vty
, "%% Malformed Route Distinguisher\n");
10817 return CMD_WARNING
;
10820 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
10821 0, BGP_PATH_ALL
, use_json(argc
, argv
));
10824 static struct bgp_distance
*bgp_distance_new(void)
10826 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
10829 static void bgp_distance_free(struct bgp_distance
*bdistance
)
10831 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
10834 static int bgp_distance_set(struct vty
*vty
, const char *distance_str
,
10835 const char *ip_str
, const char *access_list_str
)
10842 struct bgp_node
*rn
;
10843 struct bgp_distance
*bdistance
;
10845 afi
= bgp_node_afi(vty
);
10846 safi
= bgp_node_safi(vty
);
10848 ret
= str2prefix(ip_str
, &p
);
10850 vty_out(vty
, "Malformed prefix\n");
10851 return CMD_WARNING_CONFIG_FAILED
;
10854 distance
= atoi(distance_str
);
10856 /* Get BGP distance node. */
10857 rn
= bgp_node_get(bgp_distance_table
[afi
][safi
], (struct prefix
*)&p
);
10858 bdistance
= bgp_distance_get_node(rn
);
10860 bgp_unlock_node(rn
);
10862 bdistance
= bgp_distance_new();
10863 bgp_distance_set_node_info(rn
, bdistance
);
10866 /* Set distance value. */
10867 bdistance
->distance
= distance
;
10869 /* Reset access-list configuration. */
10870 if (bdistance
->access_list
) {
10871 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
10872 bdistance
->access_list
= NULL
;
10874 if (access_list_str
)
10875 bdistance
->access_list
=
10876 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
10878 return CMD_SUCCESS
;
10881 static int bgp_distance_unset(struct vty
*vty
, const char *distance_str
,
10882 const char *ip_str
, const char *access_list_str
)
10889 struct bgp_node
*rn
;
10890 struct bgp_distance
*bdistance
;
10892 afi
= bgp_node_afi(vty
);
10893 safi
= bgp_node_safi(vty
);
10895 ret
= str2prefix(ip_str
, &p
);
10897 vty_out(vty
, "Malformed prefix\n");
10898 return CMD_WARNING_CONFIG_FAILED
;
10901 rn
= bgp_node_lookup(bgp_distance_table
[afi
][safi
],
10902 (struct prefix
*)&p
);
10904 vty_out(vty
, "Can't find specified prefix\n");
10905 return CMD_WARNING_CONFIG_FAILED
;
10908 bdistance
= bgp_distance_get_node(rn
);
10909 distance
= atoi(distance_str
);
10911 if (bdistance
->distance
!= distance
) {
10912 vty_out(vty
, "Distance does not match configured\n");
10913 return CMD_WARNING_CONFIG_FAILED
;
10916 if (bdistance
->access_list
)
10917 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
10918 bgp_distance_free(bdistance
);
10921 bgp_unlock_node(rn
);
10922 bgp_unlock_node(rn
);
10924 return CMD_SUCCESS
;
10927 /* Apply BGP information to distance method. */
10928 uint8_t bgp_distance_apply(struct prefix
*p
, struct bgp_info
*rinfo
, afi_t afi
,
10929 safi_t safi
, struct bgp
*bgp
)
10931 struct bgp_node
*rn
;
10934 struct bgp_distance
*bdistance
;
10935 struct access_list
*alist
;
10936 struct bgp_static
*bgp_static
;
10941 peer
= rinfo
->peer
;
10943 /* Check source address. */
10944 sockunion2hostprefix(&peer
->su
, &q
);
10945 rn
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
10947 bdistance
= bgp_distance_get_node(rn
);
10948 bgp_unlock_node(rn
);
10950 if (bdistance
->access_list
) {
10951 alist
= access_list_lookup(afi
, bdistance
->access_list
);
10953 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
10954 return bdistance
->distance
;
10956 return bdistance
->distance
;
10959 /* Backdoor check. */
10960 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
10962 bgp_static
= bgp_static_get_node_info(rn
);
10963 bgp_unlock_node(rn
);
10965 if (bgp_static
->backdoor
) {
10966 if (bgp
->distance_local
[afi
][safi
])
10967 return bgp
->distance_local
[afi
][safi
];
10969 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
10973 if (peer
->sort
== BGP_PEER_EBGP
) {
10974 if (bgp
->distance_ebgp
[afi
][safi
])
10975 return bgp
->distance_ebgp
[afi
][safi
];
10976 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
10978 if (bgp
->distance_ibgp
[afi
][safi
])
10979 return bgp
->distance_ibgp
[afi
][safi
];
10980 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
10984 DEFUN (bgp_distance
,
10986 "distance bgp (1-255) (1-255) (1-255)",
10987 "Define an administrative distance\n"
10989 "Distance for routes external to the AS\n"
10990 "Distance for routes internal to the AS\n"
10991 "Distance for local routes\n")
10993 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
10994 int idx_number
= 2;
10995 int idx_number_2
= 3;
10996 int idx_number_3
= 4;
11000 afi
= bgp_node_afi(vty
);
11001 safi
= bgp_node_safi(vty
);
11003 bgp
->distance_ebgp
[afi
][safi
] = atoi(argv
[idx_number
]->arg
);
11004 bgp
->distance_ibgp
[afi
][safi
] = atoi(argv
[idx_number_2
]->arg
);
11005 bgp
->distance_local
[afi
][safi
] = atoi(argv
[idx_number_3
]->arg
);
11006 return CMD_SUCCESS
;
11009 DEFUN (no_bgp_distance
,
11010 no_bgp_distance_cmd
,
11011 "no distance bgp [(1-255) (1-255) (1-255)]",
11013 "Define an administrative distance\n"
11015 "Distance for routes external to the AS\n"
11016 "Distance for routes internal to the AS\n"
11017 "Distance for local routes\n")
11019 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11023 afi
= bgp_node_afi(vty
);
11024 safi
= bgp_node_safi(vty
);
11026 bgp
->distance_ebgp
[afi
][safi
] = 0;
11027 bgp
->distance_ibgp
[afi
][safi
] = 0;
11028 bgp
->distance_local
[afi
][safi
] = 0;
11029 return CMD_SUCCESS
;
11033 DEFUN (bgp_distance_source
,
11034 bgp_distance_source_cmd
,
11035 "distance (1-255) A.B.C.D/M",
11036 "Define an administrative distance\n"
11037 "Administrative distance\n"
11038 "IP source prefix\n")
11040 int idx_number
= 1;
11041 int idx_ipv4_prefixlen
= 2;
11042 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
11043 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
11044 return CMD_SUCCESS
;
11047 DEFUN (no_bgp_distance_source
,
11048 no_bgp_distance_source_cmd
,
11049 "no distance (1-255) A.B.C.D/M",
11051 "Define an administrative distance\n"
11052 "Administrative distance\n"
11053 "IP source prefix\n")
11055 int idx_number
= 2;
11056 int idx_ipv4_prefixlen
= 3;
11057 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
11058 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
11059 return CMD_SUCCESS
;
11062 DEFUN (bgp_distance_source_access_list
,
11063 bgp_distance_source_access_list_cmd
,
11064 "distance (1-255) A.B.C.D/M WORD",
11065 "Define an administrative distance\n"
11066 "Administrative distance\n"
11067 "IP source prefix\n"
11068 "Access list name\n")
11070 int idx_number
= 1;
11071 int idx_ipv4_prefixlen
= 2;
11073 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
11074 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
11075 return CMD_SUCCESS
;
11078 DEFUN (no_bgp_distance_source_access_list
,
11079 no_bgp_distance_source_access_list_cmd
,
11080 "no distance (1-255) A.B.C.D/M WORD",
11082 "Define an administrative distance\n"
11083 "Administrative distance\n"
11084 "IP source prefix\n"
11085 "Access list name\n")
11087 int idx_number
= 2;
11088 int idx_ipv4_prefixlen
= 3;
11090 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
11091 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
11092 return CMD_SUCCESS
;
11095 DEFUN (ipv6_bgp_distance_source
,
11096 ipv6_bgp_distance_source_cmd
,
11097 "distance (1-255) X:X::X:X/M",
11098 "Define an administrative distance\n"
11099 "Administrative distance\n"
11100 "IP source prefix\n")
11102 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, NULL
);
11103 return CMD_SUCCESS
;
11106 DEFUN (no_ipv6_bgp_distance_source
,
11107 no_ipv6_bgp_distance_source_cmd
,
11108 "no distance (1-255) X:X::X:X/M",
11110 "Define an administrative distance\n"
11111 "Administrative distance\n"
11112 "IP source prefix\n")
11114 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, NULL
);
11115 return CMD_SUCCESS
;
11118 DEFUN (ipv6_bgp_distance_source_access_list
,
11119 ipv6_bgp_distance_source_access_list_cmd
,
11120 "distance (1-255) X:X::X:X/M WORD",
11121 "Define an administrative distance\n"
11122 "Administrative distance\n"
11123 "IP source prefix\n"
11124 "Access list name\n")
11126 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, argv
[3]->arg
);
11127 return CMD_SUCCESS
;
11130 DEFUN (no_ipv6_bgp_distance_source_access_list
,
11131 no_ipv6_bgp_distance_source_access_list_cmd
,
11132 "no distance (1-255) X:X::X:X/M WORD",
11134 "Define an administrative distance\n"
11135 "Administrative distance\n"
11136 "IP source prefix\n"
11137 "Access list name\n")
11139 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, argv
[4]->arg
);
11140 return CMD_SUCCESS
;
11143 DEFUN (bgp_damp_set
,
11145 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
11146 "BGP Specific commands\n"
11147 "Enable route-flap dampening\n"
11148 "Half-life time for the penalty\n"
11149 "Value to start reusing a route\n"
11150 "Value to start suppressing a route\n"
11151 "Maximum duration to suppress a stable route\n")
11153 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11154 int idx_half_life
= 2;
11156 int idx_suppress
= 4;
11157 int idx_max_suppress
= 5;
11158 int half
= DEFAULT_HALF_LIFE
* 60;
11159 int reuse
= DEFAULT_REUSE
;
11160 int suppress
= DEFAULT_SUPPRESS
;
11161 int max
= 4 * half
;
11164 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
11165 reuse
= atoi(argv
[idx_reuse
]->arg
);
11166 suppress
= atoi(argv
[idx_suppress
]->arg
);
11167 max
= atoi(argv
[idx_max_suppress
]->arg
) * 60;
11168 } else if (argc
== 3) {
11169 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
11173 if (suppress
< reuse
) {
11175 "Suppress value cannot be less than reuse value \n");
11179 return bgp_damp_enable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
), half
,
11180 reuse
, suppress
, max
);
11183 DEFUN (bgp_damp_unset
,
11184 bgp_damp_unset_cmd
,
11185 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
11187 "BGP Specific commands\n"
11188 "Enable route-flap dampening\n"
11189 "Half-life time for the penalty\n"
11190 "Value to start reusing a route\n"
11191 "Value to start suppressing a route\n"
11192 "Maximum duration to suppress a stable route\n")
11194 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11195 return bgp_damp_disable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
));
11198 /* Display specified route of BGP table. */
11199 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
11200 const char *ip_str
, afi_t afi
, safi_t safi
,
11201 struct prefix_rd
*prd
, int prefix_check
)
11204 struct prefix match
;
11205 struct bgp_node
*rn
;
11206 struct bgp_node
*rm
;
11207 struct bgp_info
*ri
;
11208 struct bgp_info
*ri_temp
;
11210 struct bgp_table
*table
;
11212 /* BGP structure lookup. */
11214 bgp
= bgp_lookup_by_name(view_name
);
11216 vty_out(vty
, "%% Can't find BGP instance %s\n",
11218 return CMD_WARNING
;
11221 bgp
= bgp_get_default();
11223 vty_out(vty
, "%% No BGP process is configured\n");
11224 return CMD_WARNING
;
11228 /* Check IP address argument. */
11229 ret
= str2prefix(ip_str
, &match
);
11231 vty_out(vty
, "%% address is malformed\n");
11232 return CMD_WARNING
;
11235 match
.family
= afi2family(afi
);
11237 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
11238 || (safi
== SAFI_EVPN
)) {
11239 for (rn
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); rn
;
11240 rn
= bgp_route_next(rn
)) {
11241 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
11243 if ((table
= rn
->info
) == NULL
)
11245 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
11249 || rm
->p
.prefixlen
== match
.prefixlen
) {
11252 if (ri
->extra
&& ri
->extra
->damp_info
) {
11253 ri_temp
= ri
->next
;
11254 bgp_damp_info_free(
11255 ri
->extra
->damp_info
,
11263 bgp_unlock_node(rm
);
11266 if ((rn
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
))
11269 || rn
->p
.prefixlen
== match
.prefixlen
) {
11272 if (ri
->extra
&& ri
->extra
->damp_info
) {
11273 ri_temp
= ri
->next
;
11274 bgp_damp_info_free(
11275 ri
->extra
->damp_info
,
11283 bgp_unlock_node(rn
);
11287 return CMD_SUCCESS
;
11290 DEFUN (clear_ip_bgp_dampening
,
11291 clear_ip_bgp_dampening_cmd
,
11292 "clear ip bgp dampening",
11296 "Clear route flap dampening information\n")
11298 bgp_damp_info_clean();
11299 return CMD_SUCCESS
;
11302 DEFUN (clear_ip_bgp_dampening_prefix
,
11303 clear_ip_bgp_dampening_prefix_cmd
,
11304 "clear ip bgp dampening A.B.C.D/M",
11308 "Clear route flap dampening information\n"
11311 int idx_ipv4_prefixlen
= 4;
11312 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
11313 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
11316 DEFUN (clear_ip_bgp_dampening_address
,
11317 clear_ip_bgp_dampening_address_cmd
,
11318 "clear ip bgp dampening A.B.C.D",
11322 "Clear route flap dampening information\n"
11323 "Network to clear damping information\n")
11326 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
11327 SAFI_UNICAST
, NULL
, 0);
11330 DEFUN (clear_ip_bgp_dampening_address_mask
,
11331 clear_ip_bgp_dampening_address_mask_cmd
,
11332 "clear ip bgp dampening A.B.C.D A.B.C.D",
11336 "Clear route flap dampening information\n"
11337 "Network to clear damping information\n"
11341 int idx_ipv4_2
= 5;
11343 char prefix_str
[BUFSIZ
];
11345 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
11348 vty_out(vty
, "%% Inconsistent address and mask\n");
11349 return CMD_WARNING
;
11352 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
11356 /* also used for encap safi */
11357 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
11358 afi_t afi
, safi_t safi
)
11360 struct bgp_node
*prn
;
11361 struct bgp_node
*rn
;
11362 struct bgp_table
*table
;
11364 struct prefix_rd
*prd
;
11365 struct bgp_static
*bgp_static
;
11366 mpls_label_t label
;
11367 char buf
[SU_ADDRSTRLEN
];
11368 char rdbuf
[RD_ADDRSTRLEN
];
11370 /* Network configuration. */
11371 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
11372 prn
= bgp_route_next(prn
)) {
11373 if ((table
= prn
->info
) == NULL
)
11376 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
11377 bgp_static
= bgp_static_get_node_info(rn
);
11378 if (bgp_static
== NULL
)
11382 prd
= (struct prefix_rd
*)&prn
->p
;
11384 /* "network" configuration display. */
11385 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
11386 label
= decode_label(&bgp_static
->label
);
11388 vty_out(vty
, " network %s/%d rd %s",
11389 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11391 p
->prefixlen
, rdbuf
);
11392 if (safi
== SAFI_MPLS_VPN
)
11393 vty_out(vty
, " label %u", label
);
11395 if (bgp_static
->rmap
.name
)
11396 vty_out(vty
, " route-map %s",
11397 bgp_static
->rmap
.name
);
11399 if (bgp_static
->backdoor
)
11400 vty_out(vty
, " backdoor");
11402 vty_out(vty
, "\n");
11407 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
11408 afi_t afi
, safi_t safi
)
11410 struct bgp_node
*prn
;
11411 struct bgp_node
*rn
;
11412 struct bgp_table
*table
;
11414 struct prefix_rd
*prd
;
11415 struct bgp_static
*bgp_static
;
11416 char buf
[PREFIX_STRLEN
* 2];
11417 char buf2
[SU_ADDRSTRLEN
];
11418 char rdbuf
[RD_ADDRSTRLEN
];
11420 /* Network configuration. */
11421 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
11422 prn
= bgp_route_next(prn
)) {
11423 if ((table
= prn
->info
) == NULL
)
11426 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
11427 bgp_static
= bgp_static_get_node_info(rn
);
11428 if (bgp_static
== NULL
)
11431 char *macrouter
= NULL
;
11434 if (bgp_static
->router_mac
)
11435 macrouter
= prefix_mac2str(
11436 bgp_static
->router_mac
, NULL
, 0);
11437 if (bgp_static
->eth_s_id
)
11438 esi
= esi2str(bgp_static
->eth_s_id
);
11440 prd
= (struct prefix_rd
*)&prn
->p
;
11442 /* "network" configuration display. */
11443 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
11444 if (p
->u
.prefix_evpn
.route_type
== 5) {
11445 char local_buf
[PREFIX_STRLEN
];
11446 uint8_t family
= is_evpn_prefix_ipaddr_v4((
11447 struct prefix_evpn
*)p
)
11451 &p
->u
.prefix_evpn
.prefix_addr
.ip
.ip
.addr
,
11452 local_buf
, PREFIX_STRLEN
);
11453 sprintf(buf
, "%s/%u", local_buf
,
11454 p
->u
.prefix_evpn
.prefix_addr
.ip_prefix_length
);
11456 prefix2str(p
, buf
, sizeof(buf
));
11459 if (bgp_static
->gatewayIp
.family
== AF_INET
11460 || bgp_static
->gatewayIp
.family
== AF_INET6
)
11461 inet_ntop(bgp_static
->gatewayIp
.family
,
11462 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
11465 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
11467 p
->u
.prefix_evpn
.prefix_addr
.eth_tag
,
11468 decode_label(&bgp_static
->label
), esi
, buf2
,
11472 XFREE(MTYPE_TMP
, macrouter
);
11474 XFREE(MTYPE_TMP
, esi
);
11479 /* Configuration of static route announcement and aggregate
11481 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11484 struct bgp_node
*rn
;
11486 struct bgp_static
*bgp_static
;
11487 struct bgp_aggregate
*bgp_aggregate
;
11488 char buf
[SU_ADDRSTRLEN
];
11490 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
11491 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
11495 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
11496 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
11500 /* Network configuration. */
11501 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
11502 rn
= bgp_route_next(rn
)) {
11503 bgp_static
= bgp_static_get_node_info(rn
);
11504 if (bgp_static
== NULL
)
11509 /* "network" configuration display. */
11510 if (bgp_option_check(BGP_OPT_CONFIG_CISCO
) && afi
== AFI_IP
) {
11511 uint32_t destination
;
11512 struct in_addr netmask
;
11514 destination
= ntohl(p
->u
.prefix4
.s_addr
);
11515 masklen2ip(p
->prefixlen
, &netmask
);
11516 vty_out(vty
, " network %s",
11517 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11520 if ((IN_CLASSC(destination
) && p
->prefixlen
== 24)
11521 || (IN_CLASSB(destination
) && p
->prefixlen
== 16)
11522 || (IN_CLASSA(destination
) && p
->prefixlen
== 8)
11523 || p
->u
.prefix4
.s_addr
== 0) {
11524 /* Natural mask is not display. */
11526 vty_out(vty
, " mask %s", inet_ntoa(netmask
));
11528 vty_out(vty
, " network %s/%d",
11529 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11534 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
11535 vty_out(vty
, " label-index %u",
11536 bgp_static
->label_index
);
11538 if (bgp_static
->rmap
.name
)
11539 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
11541 if (bgp_static
->backdoor
)
11542 vty_out(vty
, " backdoor");
11544 vty_out(vty
, "\n");
11547 /* Aggregate-address configuration. */
11548 for (rn
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); rn
;
11549 rn
= bgp_route_next(rn
)) {
11550 bgp_aggregate
= bgp_aggregate_get_node_info(rn
);
11551 if (bgp_aggregate
== NULL
)
11556 if (bgp_option_check(BGP_OPT_CONFIG_CISCO
) && afi
== AFI_IP
) {
11557 struct in_addr netmask
;
11559 masklen2ip(p
->prefixlen
, &netmask
);
11560 vty_out(vty
, " aggregate-address %s %s",
11561 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11563 inet_ntoa(netmask
));
11565 vty_out(vty
, " aggregate-address %s/%d",
11566 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11571 if (bgp_aggregate
->as_set
)
11572 vty_out(vty
, " as-set");
11574 if (bgp_aggregate
->summary_only
)
11575 vty_out(vty
, " summary-only");
11577 vty_out(vty
, "\n");
11581 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11584 struct bgp_node
*rn
;
11585 struct bgp_distance
*bdistance
;
11587 /* Distance configuration. */
11588 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
11589 && bgp
->distance_local
[afi
][safi
]
11590 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
11591 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
11592 || bgp
->distance_local
[afi
][safi
]
11593 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
11594 vty_out(vty
, " distance bgp %d %d %d\n",
11595 bgp
->distance_ebgp
[afi
][safi
],
11596 bgp
->distance_ibgp
[afi
][safi
],
11597 bgp
->distance_local
[afi
][safi
]);
11600 for (rn
= bgp_table_top(bgp_distance_table
[afi
][safi
]); rn
;
11601 rn
= bgp_route_next(rn
)) {
11602 bdistance
= bgp_distance_get_node(rn
);
11603 if (bdistance
!= NULL
) {
11604 char buf
[PREFIX_STRLEN
];
11606 vty_out(vty
, " distance %d %s %s\n",
11607 bdistance
->distance
,
11608 prefix2str(&rn
->p
, buf
, sizeof(buf
)),
11609 bdistance
->access_list
? bdistance
->access_list
11615 /* Allocate routing table structure and install commands. */
11616 void bgp_route_init(void)
11621 /* Init BGP distance table. */
11622 FOREACH_AFI_SAFI (afi
, safi
)
11623 bgp_distance_table
[afi
][safi
] = bgp_table_init(NULL
, afi
, safi
);
11625 /* IPv4 BGP commands. */
11626 install_element(BGP_NODE
, &bgp_table_map_cmd
);
11627 install_element(BGP_NODE
, &bgp_network_cmd
);
11628 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
11630 install_element(BGP_NODE
, &aggregate_address_cmd
);
11631 install_element(BGP_NODE
, &aggregate_address_mask_cmd
);
11632 install_element(BGP_NODE
, &no_aggregate_address_cmd
);
11633 install_element(BGP_NODE
, &no_aggregate_address_mask_cmd
);
11635 /* IPv4 unicast configuration. */
11636 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
11637 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
11638 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
11640 install_element(BGP_IPV4_NODE
, &aggregate_address_cmd
);
11641 install_element(BGP_IPV4_NODE
, &aggregate_address_mask_cmd
);
11642 install_element(BGP_IPV4_NODE
, &no_aggregate_address_cmd
);
11643 install_element(BGP_IPV4_NODE
, &no_aggregate_address_mask_cmd
);
11645 /* IPv4 multicast configuration. */
11646 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
11647 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
11648 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
11649 install_element(BGP_IPV4M_NODE
, &aggregate_address_cmd
);
11650 install_element(BGP_IPV4M_NODE
, &aggregate_address_mask_cmd
);
11651 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_cmd
);
11652 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_mask_cmd
);
11654 /* IPv4 labeled-unicast configuration. */
11655 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
11656 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
11657 install_element(VIEW_NODE
, &show_ip_bgp_json_cmd
);
11658 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
11659 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
11661 install_element(VIEW_NODE
,
11662 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
11663 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
11664 install_element(VIEW_NODE
,
11665 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
11666 #ifdef KEEP_OLD_VPN_COMMANDS
11667 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
11668 #endif /* KEEP_OLD_VPN_COMMANDS */
11669 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
11670 install_element(VIEW_NODE
,
11671 &show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd
);
11673 /* BGP dampening clear commands */
11674 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
11675 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
11677 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
11678 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
11681 install_element(ENABLE_NODE
,
11682 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
11683 #ifdef KEEP_OLD_VPN_COMMANDS
11684 install_element(ENABLE_NODE
,
11685 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
11686 #endif /* KEEP_OLD_VPN_COMMANDS */
11688 /* New config IPv6 BGP commands. */
11689 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
11690 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
11691 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
11693 install_element(BGP_IPV6_NODE
, &ipv6_aggregate_address_cmd
);
11694 install_element(BGP_IPV6_NODE
, &no_ipv6_aggregate_address_cmd
);
11696 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
11698 install_element(BGP_NODE
, &bgp_distance_cmd
);
11699 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
11700 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
11701 install_element(BGP_NODE
, &no_bgp_distance_source_cmd
);
11702 install_element(BGP_NODE
, &bgp_distance_source_access_list_cmd
);
11703 install_element(BGP_NODE
, &no_bgp_distance_source_access_list_cmd
);
11704 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
11705 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
11706 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
11707 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_cmd
);
11708 install_element(BGP_IPV4_NODE
, &bgp_distance_source_access_list_cmd
);
11709 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_access_list_cmd
);
11710 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
11711 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
11712 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
11713 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_source_cmd
);
11714 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_access_list_cmd
);
11715 install_element(BGP_IPV4M_NODE
,
11716 &no_bgp_distance_source_access_list_cmd
);
11717 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
11718 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
11719 install_element(BGP_IPV6_NODE
, &ipv6_bgp_distance_source_cmd
);
11720 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_distance_source_cmd
);
11721 install_element(BGP_IPV6_NODE
,
11722 &ipv6_bgp_distance_source_access_list_cmd
);
11723 install_element(BGP_IPV6_NODE
,
11724 &no_ipv6_bgp_distance_source_access_list_cmd
);
11725 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
11726 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
11727 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_distance_source_cmd
);
11728 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_distance_source_cmd
);
11729 install_element(BGP_IPV6M_NODE
,
11730 &ipv6_bgp_distance_source_access_list_cmd
);
11731 install_element(BGP_IPV6M_NODE
,
11732 &no_ipv6_bgp_distance_source_access_list_cmd
);
11734 install_element(BGP_NODE
, &bgp_damp_set_cmd
);
11735 install_element(BGP_NODE
, &bgp_damp_unset_cmd
);
11736 install_element(BGP_IPV4_NODE
, &bgp_damp_set_cmd
);
11737 install_element(BGP_IPV4_NODE
, &bgp_damp_unset_cmd
);
11739 /* IPv4 Multicast Mode */
11740 install_element(BGP_IPV4M_NODE
, &bgp_damp_set_cmd
);
11741 install_element(BGP_IPV4M_NODE
, &bgp_damp_unset_cmd
);
11743 /* Large Communities */
11744 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
11745 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
11747 /* show bgp ipv4 flowspec detailed */
11748 install_element(VIEW_NODE
, &show_ip_bgp_flowspec_routes_detailed_cmd
);
11752 void bgp_route_finish(void)
11757 FOREACH_AFI_SAFI (afi
, safi
) {
11758 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
11759 bgp_distance_table
[afi
][safi
] = NULL
;