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_and_null(&((*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
;
2780 if (afi
!= AFI_L2VPN
)
2783 memset(&temp
, 0, 16);
2784 info_eth_s_id
= (struct eth_segment_id
*)&temp
;
2785 info_gw_ip
= (union gw_addr
*)&temp
;
2786 if (eth_s_id
== NULL
&& gw_ip
== NULL
)
2789 info_eth_s_id
= &(info
->attr
->evpn_overlay
.eth_s_id
);
2790 info_gw_ip
= &(info
->attr
->evpn_overlay
.gw_ip
);
2793 info_gw_ip_remote
= (union gw_addr
*)&temp
;
2795 info_gw_ip_remote
= gw_ip
;
2796 if (eth_s_id
== NULL
)
2797 info_eth_s_id_remote
= (struct eth_segment_id
*)&temp
;
2799 info_eth_s_id_remote
= eth_s_id
;
2800 if (!memcmp(info_gw_ip
, info_gw_ip_remote
, sizeof(union gw_addr
)))
2802 return !memcmp(info_eth_s_id
, info_eth_s_id_remote
,
2803 sizeof(struct eth_segment_id
));
2806 /* Check if received nexthop is valid or not. */
2807 static int bgp_update_martian_nexthop(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
2812 /* Only validated for unicast and multicast currently. */
2813 /* Also valid for EVPN where the nexthop is an IP address. */
2814 if (safi
!= SAFI_UNICAST
&& safi
!= SAFI_MULTICAST
&& safi
!= SAFI_EVPN
)
2817 /* If NEXT_HOP is present, validate it. */
2818 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
2819 if (attr
->nexthop
.s_addr
== 0
2820 || IPV4_CLASS_DE(ntohl(attr
->nexthop
.s_addr
))
2821 || bgp_nexthop_self(bgp
, attr
->nexthop
))
2825 /* If MP_NEXTHOP is present, validate it. */
2826 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
2827 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
2828 * it is not an IPv6 link-local address.
2830 if (attr
->mp_nexthop_len
) {
2831 switch (attr
->mp_nexthop_len
) {
2832 case BGP_ATTR_NHLEN_IPV4
:
2833 case BGP_ATTR_NHLEN_VPNV4
:
2834 ret
= (attr
->mp_nexthop_global_in
.s_addr
== 0
2835 || IPV4_CLASS_DE(ntohl(
2836 attr
->mp_nexthop_global_in
.s_addr
))
2837 || bgp_nexthop_self(bgp
,
2838 attr
->mp_nexthop_global_in
));
2841 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
2842 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
2843 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
2844 ret
= (IN6_IS_ADDR_UNSPECIFIED(&attr
->mp_nexthop_global
)
2845 || IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
2846 || IN6_IS_ADDR_MULTICAST(
2847 &attr
->mp_nexthop_global
));
2859 int bgp_update(struct peer
*peer
, struct prefix
*p
, uint32_t addpath_id
,
2860 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
2861 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
2862 uint32_t num_labels
, int soft_reconfig
,
2863 struct bgp_route_evpn
*evpn
)
2866 int aspath_loop_count
= 0;
2867 struct bgp_node
*rn
;
2869 struct attr new_attr
;
2870 struct attr
*attr_new
;
2871 struct bgp_info
*ri
;
2872 struct bgp_info
*new;
2873 struct bgp_info_extra
*extra
;
2875 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
2877 int do_loop_check
= 1;
2878 int has_valid_label
= 0;
2880 int vnc_implicit_withdraw
= 0;
2884 memset(&new_attr
, 0, sizeof(struct attr
));
2885 new_attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
2886 new_attr
.label
= MPLS_INVALID_LABEL
;
2889 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
2890 /* TODO: Check to see if we can get rid of "is_valid_label" */
2891 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
2892 has_valid_label
= (num_labels
> 0) ? 1 : 0;
2894 has_valid_label
= bgp_is_valid_label(label
);
2896 /* When peer's soft reconfiguration enabled. Record input packet in
2899 && CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
2900 && peer
!= bgp
->peer_self
)
2901 bgp_adj_in_set(rn
, peer
, attr
, addpath_id
);
2903 /* Check previously received route. */
2904 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
2905 if (ri
->peer
== peer
&& ri
->type
== type
2906 && ri
->sub_type
== sub_type
2907 && ri
->addpath_rx_id
== addpath_id
)
2910 /* AS path local-as loop check. */
2911 if (peer
->change_local_as
) {
2912 if (peer
->allowas_in
[afi
][safi
])
2913 aspath_loop_count
= peer
->allowas_in
[afi
][safi
];
2914 else if (!CHECK_FLAG(peer
->flags
,
2915 PEER_FLAG_LOCAL_AS_NO_PREPEND
))
2916 aspath_loop_count
= 1;
2918 if (aspath_loop_check(attr
->aspath
, peer
->change_local_as
)
2919 > aspath_loop_count
) {
2920 reason
= "as-path contains our own AS;";
2925 /* If the peer is configured for "allowas-in origin" and the last ASN in
2927 * as-path is our ASN then we do not need to call aspath_loop_check
2929 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN_ORIGIN
))
2930 if (aspath_get_last_as(attr
->aspath
) == bgp
->as
)
2933 /* AS path loop check. */
2934 if (do_loop_check
) {
2935 if (aspath_loop_check(attr
->aspath
, bgp
->as
)
2936 > peer
->allowas_in
[afi
][safi
]
2937 || (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)
2938 && aspath_loop_check(attr
->aspath
, bgp
->confed_id
)
2939 > peer
->allowas_in
[afi
][safi
])) {
2940 reason
= "as-path contains our own AS;";
2945 /* Route reflector originator ID check. */
2946 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
2947 && IPV4_ADDR_SAME(&bgp
->router_id
, &attr
->originator_id
)) {
2948 reason
= "originator is us;";
2952 /* Route reflector cluster ID check. */
2953 if (bgp_cluster_filter(peer
, attr
)) {
2954 reason
= "reflected from the same cluster;";
2958 /* Apply incoming filter. */
2959 if (bgp_input_filter(peer
, p
, attr
, afi
, safi
) == FILTER_DENY
) {
2964 bgp_attr_dup(&new_attr
, attr
);
2966 /* Apply incoming route-map.
2967 * NB: new_attr may now contain newly allocated values from route-map
2969 * commands, so we need bgp_attr_flush in the error paths, until we
2971 * the attr (which takes over the memory references) */
2972 if (bgp_input_modifier(peer
, p
, &new_attr
, afi
, safi
, NULL
)
2974 reason
= "route-map;";
2975 bgp_attr_flush(&new_attr
);
2979 if (peer
->sort
== BGP_PEER_EBGP
) {
2981 /* If we receive the graceful-shutdown community from an eBGP
2982 * peer we must lower local-preference */
2983 if (new_attr
.community
2984 && community_include(new_attr
.community
, COMMUNITY_GSHUT
)) {
2985 new_attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
2986 new_attr
.local_pref
= BGP_GSHUT_LOCAL_PREF
;
2988 /* If graceful-shutdown is configured then add the GSHUT
2989 * community to all paths received from eBGP peers */
2990 } else if (bgp_flag_check(peer
->bgp
,
2991 BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
2992 bgp_attr_add_gshut_community(&new_attr
);
2996 /* next hop check. */
2997 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
)
2998 && bgp_update_martian_nexthop(bgp
, afi
, safi
, &new_attr
)) {
2999 reason
= "martian or self next-hop;";
3000 bgp_attr_flush(&new_attr
);
3004 attr_new
= bgp_attr_intern(&new_attr
);
3006 /* If the update is implicit withdraw. */
3008 ri
->uptime
= bgp_clock();
3009 same_attr
= attrhash_cmp(ri
->attr
, attr_new
);
3011 /* Same attribute comes in. */
3012 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)
3013 && attrhash_cmp(ri
->attr
, attr_new
)
3014 && (!has_valid_label
3015 || memcmp(&(bgp_info_extra_get(ri
))->label
, label
,
3016 num_labels
* sizeof(mpls_label_t
))
3018 && (overlay_index_equal(
3019 afi
, ri
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3020 evpn
== NULL
? NULL
: &evpn
->gw_ip
))) {
3021 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
3022 BGP_CONFIG_DAMPENING
)
3023 && peer
->sort
== BGP_PEER_EBGP
3024 && CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
)) {
3025 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3026 bgp_debug_rdpfxpath2str(
3027 afi
, safi
, prd
, p
, label
,
3028 num_labels
, addpath_id
? 1 : 0,
3029 addpath_id
, pfx_buf
,
3031 zlog_debug("%s rcvd %s", peer
->host
,
3035 if (bgp_damp_update(ri
, rn
, afi
, safi
)
3036 != BGP_DAMP_SUPPRESSED
) {
3037 bgp_aggregate_increment(bgp
, p
, ri
, afi
,
3039 bgp_process(bgp
, rn
, afi
, safi
);
3041 } else /* Duplicate - odd */
3043 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3044 if (!peer
->rcvd_attr_printed
) {
3046 "%s rcvd UPDATE w/ attr: %s",
3048 peer
->rcvd_attr_str
);
3049 peer
->rcvd_attr_printed
= 1;
3052 bgp_debug_rdpfxpath2str(
3053 afi
, safi
, prd
, p
, label
,
3054 num_labels
, addpath_id
? 1 : 0,
3055 addpath_id
, pfx_buf
,
3058 "%s rcvd %s...duplicate ignored",
3059 peer
->host
, pfx_buf
);
3062 /* graceful restart STALE flag unset. */
3063 if (CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
)) {
3064 bgp_info_unset_flag(rn
, ri
,
3066 bgp_process(bgp
, rn
, afi
, safi
);
3070 bgp_unlock_node(rn
);
3071 bgp_attr_unintern(&attr_new
);
3076 /* Withdraw/Announce before we fully processed the withdraw */
3077 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)) {
3078 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3079 bgp_debug_rdpfxpath2str(
3080 afi
, safi
, prd
, p
, label
, num_labels
,
3081 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3084 "%s rcvd %s, flapped quicker than processing",
3085 peer
->host
, pfx_buf
);
3088 bgp_info_restore(rn
, ri
);
3091 /* Received Logging. */
3092 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3093 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
3094 num_labels
, addpath_id
? 1 : 0,
3095 addpath_id
, pfx_buf
,
3097 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3100 /* graceful restart STALE flag unset. */
3101 if (CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
))
3102 bgp_info_unset_flag(rn
, ri
, BGP_INFO_STALE
);
3104 /* The attribute is changed. */
3105 bgp_info_set_flag(rn
, ri
, BGP_INFO_ATTR_CHANGED
);
3107 /* implicit withdraw, decrement aggregate and pcount here.
3108 * only if update is accepted, they'll increment below.
3110 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
3112 /* Update bgp route dampening information. */
3113 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3114 && peer
->sort
== BGP_PEER_EBGP
) {
3115 /* This is implicit withdraw so we should update
3118 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
3119 bgp_damp_withdraw(ri
, rn
, afi
, safi
, 1);
3122 if (safi
== SAFI_MPLS_VPN
) {
3123 struct bgp_node
*prn
= NULL
;
3124 struct bgp_table
*table
= NULL
;
3126 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3127 (struct prefix
*)prd
);
3129 table
= (struct bgp_table
*)(prn
->info
);
3131 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3132 bgp
, prd
, table
, p
, ri
);
3134 bgp_unlock_node(prn
);
3136 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3137 && (safi
== SAFI_UNICAST
)) {
3138 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
3140 * Implicit withdraw case.
3142 ++vnc_implicit_withdraw
;
3143 vnc_import_bgp_del_route(bgp
, p
, ri
);
3144 vnc_import_bgp_exterior_del_route(bgp
, p
, ri
);
3149 /* Special handling for EVPN update of an existing route. If the
3150 * extended community attribute has changed, we need to
3152 * the route using its existing extended community. It will be
3153 * subsequently processed for import with the new extended
3156 if (safi
== SAFI_EVPN
&& !same_attr
) {
3158 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))
3160 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
3163 cmp
= ecommunity_cmp(ri
->attr
->ecommunity
,
3164 attr_new
->ecommunity
);
3166 if (bgp_debug_update(peer
, p
, NULL
, 1))
3168 "Change in EXT-COMM, existing %s new %s",
3170 ri
->attr
->ecommunity
),
3172 attr_new
->ecommunity
));
3173 bgp_evpn_unimport_route(bgp
, afi
, safi
,
3179 /* Update to new attribute. */
3180 bgp_attr_unintern(&ri
->attr
);
3181 ri
->attr
= attr_new
;
3183 /* Update MPLS label */
3184 if (has_valid_label
) {
3185 extra
= bgp_info_extra_get(ri
);
3186 memcpy(&extra
->label
, label
,
3187 num_labels
* sizeof(mpls_label_t
));
3188 extra
->num_labels
= num_labels
;
3189 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3190 bgp_set_valid_label(&extra
->label
[0]);
3194 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3195 && (safi
== SAFI_UNICAST
)) {
3196 if (vnc_implicit_withdraw
) {
3198 * Add back the route with its new attributes
3200 * The route is still selected, until the route
3202 * queued by bgp_process actually runs. We have
3204 * update to the VNC side immediately to avoid
3206 * configuration changes (e.g., route-map
3208 * trigger re-importation of the entire RIB.
3210 vnc_import_bgp_add_route(bgp
, p
, ri
);
3211 vnc_import_bgp_exterior_add_route(bgp
, p
, ri
);
3215 /* Update Overlay Index */
3216 if (afi
== AFI_L2VPN
) {
3217 overlay_index_update(
3218 ri
->attr
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3219 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3222 /* Update bgp route dampening information. */
3223 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3224 && peer
->sort
== BGP_PEER_EBGP
) {
3225 /* Now we do normal update dampening. */
3226 ret
= bgp_damp_update(ri
, rn
, afi
, safi
);
3227 if (ret
== BGP_DAMP_SUPPRESSED
) {
3228 bgp_unlock_node(rn
);
3233 /* Nexthop reachability check - for unicast and
3234 * labeled-unicast.. */
3235 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3236 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
3237 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
3238 && !CHECK_FLAG(peer
->flags
,
3239 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3241 bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3246 struct bgp
*bgp_nexthop
= bgp
;
3248 if (ri
->extra
&& ri
->extra
->bgp_orig
)
3249 bgp_nexthop
= ri
->extra
->bgp_orig
;
3251 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
, afi
,
3252 ri
, NULL
, connected
)
3253 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3254 bgp_info_set_flag(rn
, ri
, BGP_INFO_VALID
);
3256 if (BGP_DEBUG(nht
, NHT
)) {
3257 char buf1
[INET6_ADDRSTRLEN
];
3259 (const void *)&attr_new
3261 buf1
, INET6_ADDRSTRLEN
);
3262 zlog_debug("%s(%s): NH unresolved",
3263 __FUNCTION__
, buf1
);
3265 bgp_info_unset_flag(rn
, ri
, BGP_INFO_VALID
);
3268 bgp_info_set_flag(rn
, ri
, BGP_INFO_VALID
);
3271 if (safi
== SAFI_MPLS_VPN
) {
3272 struct bgp_node
*prn
= NULL
;
3273 struct bgp_table
*table
= NULL
;
3275 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3276 (struct prefix
*)prd
);
3278 table
= (struct bgp_table
*)(prn
->info
);
3280 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3281 bgp
, prd
, table
, p
, ri
);
3283 bgp_unlock_node(prn
);
3287 /* If this is an EVPN route and some attribute has changed,
3289 * route for import. If the extended community has changed, we
3291 * have done the un-import earlier and the import would result
3293 * route getting injected into appropriate L2 VNIs. If it is
3295 * some other attribute change, the import will result in
3297 * the attributes for the route in the VNI(s).
3299 if (safi
== SAFI_EVPN
&& !same_attr
)
3300 bgp_evpn_import_route(bgp
, afi
, safi
, p
, ri
);
3302 /* Process change. */
3303 bgp_aggregate_increment(bgp
, p
, ri
, afi
, safi
);
3305 bgp_process(bgp
, rn
, afi
, safi
);
3306 bgp_unlock_node(rn
);
3308 if (SAFI_UNICAST
== safi
3309 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3310 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3312 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, ri
);
3314 if ((SAFI_MPLS_VPN
== safi
)
3315 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3317 vpn_leak_to_vrf_update(bgp
, ri
);
3321 if (SAFI_MPLS_VPN
== safi
) {
3322 mpls_label_t label_decoded
= decode_label(label
);
3324 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3325 type
, sub_type
, &label_decoded
);
3327 if (SAFI_ENCAP
== safi
) {
3328 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3329 type
, sub_type
, NULL
);
3334 } // End of implicit withdraw
3336 /* Received Logging. */
3337 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3338 if (!peer
->rcvd_attr_printed
) {
3339 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3340 peer
->rcvd_attr_str
);
3341 peer
->rcvd_attr_printed
= 1;
3344 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3345 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3347 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3350 /* Make new BGP info. */
3351 new = info_make(type
, sub_type
, 0, peer
, attr_new
, rn
);
3353 /* Update MPLS label */
3354 if (has_valid_label
) {
3355 extra
= bgp_info_extra_get(new);
3356 memcpy(&extra
->label
, label
, num_labels
* sizeof(mpls_label_t
));
3357 extra
->num_labels
= num_labels
;
3358 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3359 bgp_set_valid_label(&extra
->label
[0]);
3362 /* Update Overlay Index */
3363 if (afi
== AFI_L2VPN
) {
3364 overlay_index_update(new->attr
,
3365 evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3366 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3368 /* Nexthop reachability check. */
3369 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3370 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
3371 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
3372 && !CHECK_FLAG(peer
->flags
,
3373 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3374 && !bgp_flag_check(bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3379 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, new, NULL
, connected
)
3380 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3381 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
3383 if (BGP_DEBUG(nht
, NHT
)) {
3384 char buf1
[INET6_ADDRSTRLEN
];
3386 (const void *)&attr_new
->nexthop
,
3387 buf1
, INET6_ADDRSTRLEN
);
3388 zlog_debug("%s(%s): NH unresolved",
3389 __FUNCTION__
, buf1
);
3391 bgp_info_unset_flag(rn
, new, BGP_INFO_VALID
);
3394 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
3397 new->addpath_rx_id
= addpath_id
;
3399 /* Increment prefix */
3400 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
3402 /* Register new BGP information. */
3403 bgp_info_add(rn
, new);
3405 /* route_node_get lock */
3406 bgp_unlock_node(rn
);
3409 if (safi
== SAFI_MPLS_VPN
) {
3410 struct bgp_node
*prn
= NULL
;
3411 struct bgp_table
*table
= NULL
;
3413 prn
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
3415 table
= (struct bgp_table
*)(prn
->info
);
3417 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3418 bgp
, prd
, table
, p
, new);
3420 bgp_unlock_node(prn
);
3424 /* If maximum prefix count is configured and current prefix
3426 if (bgp_maximum_prefix_overflow(peer
, afi
, safi
, 0))
3429 /* If this is an EVPN route, process for import. */
3430 if (safi
== SAFI_EVPN
)
3431 bgp_evpn_import_route(bgp
, afi
, safi
, p
, new);
3433 /* Process change. */
3434 bgp_process(bgp
, rn
, afi
, safi
);
3436 if (SAFI_UNICAST
== safi
3437 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3438 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3439 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
3441 if ((SAFI_MPLS_VPN
== safi
)
3442 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3444 vpn_leak_to_vrf_update(bgp
, new);
3447 if (SAFI_MPLS_VPN
== safi
) {
3448 mpls_label_t label_decoded
= decode_label(label
);
3450 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3451 sub_type
, &label_decoded
);
3453 if (SAFI_ENCAP
== safi
) {
3454 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3461 /* This BGP update is filtered. Log the reason then update BGP
3464 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3465 if (!peer
->rcvd_attr_printed
) {
3466 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3467 peer
->rcvd_attr_str
);
3468 peer
->rcvd_attr_printed
= 1;
3471 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3472 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3474 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
3475 peer
->host
, pfx_buf
, reason
);
3479 /* If this is an EVPN route, un-import it as it is now filtered.
3481 if (safi
== SAFI_EVPN
)
3482 bgp_evpn_unimport_route(bgp
, afi
, safi
, p
, ri
);
3484 if (SAFI_UNICAST
== safi
3485 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3486 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3488 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, ri
);
3490 if ((SAFI_MPLS_VPN
== safi
)
3491 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3493 vpn_leak_to_vrf_withdraw(bgp
, ri
);
3496 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
3499 bgp_unlock_node(rn
);
3503 * Filtered update is treated as an implicit withdrawal (see
3505 * a few lines above)
3507 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3508 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3516 int bgp_withdraw(struct peer
*peer
, struct prefix
*p
, uint32_t addpath_id
,
3517 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
3518 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
3519 uint32_t num_labels
, struct bgp_route_evpn
*evpn
)
3522 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
3523 struct bgp_node
*rn
;
3524 struct bgp_info
*ri
;
3527 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3528 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3536 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
3538 /* If peer is soft reconfiguration enabled. Record input packet for
3539 * further calculation.
3541 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
3542 * routes that are filtered. This tanks out Quagga RS pretty badly due
3544 * the iteration over all RS clients.
3545 * Since we need to remove the entry from adj_in anyway, do that first
3547 * if there was no entry, we don't need to do anything more.
3549 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
3550 && peer
!= bgp
->peer_self
)
3551 if (!bgp_adj_in_unset(rn
, peer
, addpath_id
)) {
3552 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3553 bgp_debug_rdpfxpath2str(
3554 afi
, safi
, prd
, p
, label
, num_labels
,
3555 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3558 "%s withdrawing route %s not in adj-in",
3559 peer
->host
, pfx_buf
);
3561 bgp_unlock_node(rn
);
3565 /* Lookup withdrawn route. */
3566 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
3567 if (ri
->peer
== peer
&& ri
->type
== type
3568 && ri
->sub_type
== sub_type
3569 && ri
->addpath_rx_id
== addpath_id
)
3573 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3574 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3575 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3577 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer
->host
,
3581 /* Withdraw specified route from routing table. */
3582 if (ri
&& !CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
)) {
3583 bgp_rib_withdraw(rn
, ri
, peer
, afi
, safi
, prd
);
3584 if (SAFI_UNICAST
== safi
3585 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3586 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3587 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, ri
);
3589 if ((SAFI_MPLS_VPN
== safi
)
3590 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3592 vpn_leak_to_vrf_withdraw(bgp
, ri
);
3594 } else if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3595 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3596 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3598 zlog_debug("%s Can't find the route %s", peer
->host
, pfx_buf
);
3601 /* Unlock bgp_node_get() lock. */
3602 bgp_unlock_node(rn
);
3607 void bgp_default_originate(struct peer
*peer
, afi_t afi
, safi_t safi
,
3610 struct update_subgroup
*subgrp
;
3611 subgrp
= peer_subgroup(peer
, afi
, safi
);
3612 subgroup_default_originate(subgrp
, withdraw
);
3617 * bgp_stop_announce_route_timer
3619 void bgp_stop_announce_route_timer(struct peer_af
*paf
)
3621 if (!paf
->t_announce_route
)
3624 THREAD_TIMER_OFF(paf
->t_announce_route
);
3628 * bgp_announce_route_timer_expired
3630 * Callback that is invoked when the route announcement timer for a
3633 static int bgp_announce_route_timer_expired(struct thread
*t
)
3635 struct peer_af
*paf
;
3638 paf
= THREAD_ARG(t
);
3641 if (peer
->status
!= Established
)
3644 if (!peer
->afc_nego
[paf
->afi
][paf
->safi
])
3647 peer_af_announce_route(paf
, 1);
3652 * bgp_announce_route
3654 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
3656 void bgp_announce_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
3658 struct peer_af
*paf
;
3659 struct update_subgroup
*subgrp
;
3661 paf
= peer_af_find(peer
, afi
, safi
);
3664 subgrp
= PAF_SUBGRP(paf
);
3667 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
3668 * or a refresh has already been triggered.
3670 if (!subgrp
|| paf
->t_announce_route
)
3674 * Start a timer to stagger/delay the announce. This serves
3675 * two purposes - announcement can potentially be combined for
3676 * multiple peers and the announcement doesn't happen in the
3679 thread_add_timer_msec(bm
->master
, bgp_announce_route_timer_expired
, paf
,
3680 (subgrp
->peer_count
== 1)
3681 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
3682 : BGP_ANNOUNCE_ROUTE_DELAY_MS
,
3683 &paf
->t_announce_route
);
3687 * Announce routes from all AF tables to a peer.
3689 * This should ONLY be called when there is a need to refresh the
3690 * routes to the peer based on a policy change for this peer alone
3691 * or a route refresh request received from the peer.
3692 * The operation will result in splitting the peer from its existing
3693 * subgroups and putting it in new subgroups.
3695 void bgp_announce_route_all(struct peer
*peer
)
3700 FOREACH_AFI_SAFI (afi
, safi
)
3701 bgp_announce_route(peer
, afi
, safi
);
3704 static void bgp_soft_reconfig_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
3705 struct bgp_table
*table
,
3706 struct prefix_rd
*prd
)
3709 struct bgp_node
*rn
;
3710 struct bgp_adj_in
*ain
;
3713 table
= peer
->bgp
->rib
[afi
][safi
];
3715 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
3716 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
3717 if (ain
->peer
!= peer
)
3720 struct bgp_info
*ri
= rn
->info
;
3721 uint32_t num_labels
= 0;
3722 mpls_label_t
*label_pnt
= NULL
;
3724 if (ri
&& ri
->extra
)
3725 num_labels
= ri
->extra
->num_labels
;
3727 label_pnt
= &ri
->extra
->label
[0];
3729 ret
= bgp_update(peer
, &rn
->p
, ain
->addpath_rx_id
,
3730 ain
->attr
, afi
, safi
, ZEBRA_ROUTE_BGP
,
3731 BGP_ROUTE_NORMAL
, prd
, label_pnt
,
3732 num_labels
, 1, NULL
);
3735 bgp_unlock_node(rn
);
3741 void bgp_soft_reconfig_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
3743 struct bgp_node
*rn
;
3744 struct bgp_table
*table
;
3746 if (peer
->status
!= Established
)
3749 if ((safi
!= SAFI_MPLS_VPN
) && (safi
!= SAFI_ENCAP
)
3750 && (safi
!= SAFI_EVPN
))
3751 bgp_soft_reconfig_table(peer
, afi
, safi
, NULL
, NULL
);
3753 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
3754 rn
= bgp_route_next(rn
))
3755 if ((table
= rn
->info
) != NULL
) {
3756 struct prefix_rd prd
;
3757 prd
.family
= AF_UNSPEC
;
3759 memcpy(&prd
.val
, rn
->p
.u
.val
, 8);
3761 bgp_soft_reconfig_table(peer
, afi
, safi
, table
,
3767 struct bgp_clear_node_queue
{
3768 struct bgp_node
*rn
;
3771 static wq_item_status
bgp_clear_route_node(struct work_queue
*wq
, void *data
)
3773 struct bgp_clear_node_queue
*cnq
= data
;
3774 struct bgp_node
*rn
= cnq
->rn
;
3775 struct peer
*peer
= wq
->spec
.data
;
3776 struct bgp_info
*ri
;
3778 afi_t afi
= bgp_node_table(rn
)->afi
;
3779 safi_t safi
= bgp_node_table(rn
)->safi
;
3784 /* It is possible that we have multiple paths for a prefix from a peer
3785 * if that peer is using AddPath.
3787 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
3788 if (ri
->peer
!= peer
)
3791 /* graceful restart STALE flag set. */
3792 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_NSF_WAIT
)
3793 && peer
->nsf
[afi
][safi
]
3794 && !CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
)
3795 && !CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
3796 bgp_info_set_flag(rn
, ri
, BGP_INFO_STALE
);
3798 /* If this is an EVPN route, process for
3800 if (safi
== SAFI_EVPN
)
3801 bgp_evpn_unimport_route(bgp
, afi
, safi
,
3803 /* Handle withdraw for VRF route-leaking and L3VPN */
3804 if (SAFI_UNICAST
== safi
3805 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
||
3806 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3807 vpn_leak_from_vrf_withdraw(bgp_get_default(),
3810 if (SAFI_MPLS_VPN
== safi
&&
3811 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
3812 vpn_leak_to_vrf_withdraw(bgp
, ri
);
3815 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
3821 static void bgp_clear_node_queue_del(struct work_queue
*wq
, void *data
)
3823 struct bgp_clear_node_queue
*cnq
= data
;
3824 struct bgp_node
*rn
= cnq
->rn
;
3825 struct bgp_table
*table
= bgp_node_table(rn
);
3827 bgp_unlock_node(rn
);
3828 bgp_table_unlock(table
);
3829 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE
, cnq
);
3832 static void bgp_clear_node_complete(struct work_queue
*wq
)
3834 struct peer
*peer
= wq
->spec
.data
;
3836 /* Tickle FSM to start moving again */
3837 BGP_EVENT_ADD(peer
, Clearing_Completed
);
3839 peer_unlock(peer
); /* bgp_clear_route */
3842 static void bgp_clear_node_queue_init(struct peer
*peer
)
3844 char wname
[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
3846 snprintf(wname
, sizeof(wname
), "clear %s", peer
->host
);
3847 #undef CLEAR_QUEUE_NAME_LEN
3849 peer
->clear_node_queue
= work_queue_new(bm
->master
, wname
);
3850 peer
->clear_node_queue
->spec
.hold
= 10;
3851 peer
->clear_node_queue
->spec
.workfunc
= &bgp_clear_route_node
;
3852 peer
->clear_node_queue
->spec
.del_item_data
= &bgp_clear_node_queue_del
;
3853 peer
->clear_node_queue
->spec
.completion_func
= &bgp_clear_node_complete
;
3854 peer
->clear_node_queue
->spec
.max_retries
= 0;
3856 /* we only 'lock' this peer reference when the queue is actually active
3858 peer
->clear_node_queue
->spec
.data
= peer
;
3861 static void bgp_clear_route_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
3862 struct bgp_table
*table
)
3864 struct bgp_node
*rn
;
3865 int force
= bm
->process_main_queue
? 0 : 1;
3868 table
= peer
->bgp
->rib
[afi
][safi
];
3870 /* If still no table => afi/safi isn't configured at all or smth. */
3874 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
3875 struct bgp_info
*ri
, *next
;
3876 struct bgp_adj_in
*ain
;
3877 struct bgp_adj_in
*ain_next
;
3879 /* XXX:TODO: This is suboptimal, every non-empty route_node is
3880 * queued for every clearing peer, regardless of whether it is
3881 * relevant to the peer at hand.
3883 * Overview: There are 3 different indices which need to be
3884 * scrubbed, potentially, when a peer is removed:
3886 * 1 peer's routes visible via the RIB (ie accepted routes)
3887 * 2 peer's routes visible by the (optional) peer's adj-in index
3888 * 3 other routes visible by the peer's adj-out index
3890 * 3 there is no hurry in scrubbing, once the struct peer is
3891 * removed from bgp->peer, we could just GC such deleted peer's
3892 * adj-outs at our leisure.
3894 * 1 and 2 must be 'scrubbed' in some way, at least made
3895 * invisible via RIB index before peer session is allowed to be
3896 * brought back up. So one needs to know when such a 'search' is
3901 * - there'd be a single global queue or a single RIB walker
3902 * - rather than tracking which route_nodes still need to be
3903 * examined on a peer basis, we'd track which peers still
3906 * Given that our per-peer prefix-counts now should be reliable,
3907 * this may actually be achievable. It doesn't seem to be a huge
3908 * problem at this time,
3910 * It is possible that we have multiple paths for a prefix from
3912 * if that peer is using AddPath.
3916 ain_next
= ain
->next
;
3918 if (ain
->peer
== peer
) {
3919 bgp_adj_in_remove(rn
, ain
);
3920 bgp_unlock_node(rn
);
3926 for (ri
= rn
->info
; ri
; ri
= next
) {
3928 if (ri
->peer
!= peer
)
3932 bgp_info_reap(rn
, ri
);
3934 struct bgp_clear_node_queue
*cnq
;
3936 /* both unlocked in bgp_clear_node_queue_del */
3937 bgp_table_lock(bgp_node_table(rn
));
3940 MTYPE_BGP_CLEAR_NODE_QUEUE
,
3941 sizeof(struct bgp_clear_node_queue
));
3943 work_queue_add(peer
->clear_node_queue
, cnq
);
3951 void bgp_clear_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
3953 struct bgp_node
*rn
;
3954 struct bgp_table
*table
;
3956 if (peer
->clear_node_queue
== NULL
)
3957 bgp_clear_node_queue_init(peer
);
3959 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
3960 * Idle until it receives a Clearing_Completed event. This protects
3961 * against peers which flap faster than we can we clear, which could
3964 * a) race with routes from the new session being installed before
3965 * clear_route_node visits the node (to delete the route of that
3967 * b) resource exhaustion, clear_route_node likely leads to an entry
3968 * on the process_main queue. Fast-flapping could cause that queue
3972 /* lock peer in assumption that clear-node-queue will get nodes; if so,
3973 * the unlock will happen upon work-queue completion; other wise, the
3974 * unlock happens at the end of this function.
3976 if (!peer
->clear_node_queue
->thread
)
3979 if (safi
!= SAFI_MPLS_VPN
&& safi
!= SAFI_ENCAP
&& safi
!= SAFI_EVPN
)
3980 bgp_clear_route_table(peer
, afi
, safi
, NULL
);
3982 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
3983 rn
= bgp_route_next(rn
))
3984 if ((table
= rn
->info
) != NULL
)
3985 bgp_clear_route_table(peer
, afi
, safi
, table
);
3987 /* unlock if no nodes got added to the clear-node-queue. */
3988 if (!peer
->clear_node_queue
->thread
)
3992 void bgp_clear_route_all(struct peer
*peer
)
3997 FOREACH_AFI_SAFI (afi
, safi
)
3998 bgp_clear_route(peer
, afi
, safi
);
4001 rfapiProcessPeerDown(peer
);
4005 void bgp_clear_adj_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
4007 struct bgp_table
*table
;
4008 struct bgp_node
*rn
;
4009 struct bgp_adj_in
*ain
;
4010 struct bgp_adj_in
*ain_next
;
4012 table
= peer
->bgp
->rib
[afi
][safi
];
4014 /* It is possible that we have multiple paths for a prefix from a peer
4015 * if that peer is using AddPath.
4017 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
4021 ain_next
= ain
->next
;
4023 if (ain
->peer
== peer
) {
4024 bgp_adj_in_remove(rn
, ain
);
4025 bgp_unlock_node(rn
);
4033 void bgp_clear_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4035 struct bgp_node
*rn
;
4036 struct bgp_info
*ri
;
4037 struct bgp_table
*table
;
4039 if (safi
== SAFI_MPLS_VPN
) {
4040 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4041 rn
= bgp_route_next(rn
)) {
4042 struct bgp_node
*rm
;
4044 /* look for neighbor in tables */
4045 if ((table
= rn
->info
) == NULL
)
4048 for (rm
= bgp_table_top(table
); rm
;
4049 rm
= bgp_route_next(rm
))
4050 for (ri
= rm
->info
; ri
; ri
= ri
->next
) {
4051 if (ri
->peer
!= peer
)
4053 if (!CHECK_FLAG(ri
->flags
,
4057 bgp_rib_remove(rm
, ri
, peer
, afi
, safi
);
4062 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4063 rn
= bgp_route_next(rn
))
4064 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
4065 if (ri
->peer
!= peer
)
4067 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
))
4069 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
4075 static void bgp_cleanup_table(struct bgp
*bgp
, struct bgp_table
*table
,
4078 struct bgp_node
*rn
;
4079 struct bgp_info
*ri
;
4080 struct bgp_info
*next
;
4082 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
4083 for (ri
= rn
->info
; ri
; ri
= next
) {
4085 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)
4086 && ri
->type
== ZEBRA_ROUTE_BGP
4087 && (ri
->sub_type
== BGP_ROUTE_NORMAL
4088 || ri
->sub_type
== BGP_ROUTE_AGGREGATE
4089 || ri
->sub_type
== BGP_ROUTE_IMPORTED
)) {
4091 if (bgp_fibupd_safi(safi
))
4092 bgp_zebra_withdraw(&rn
->p
, ri
,
4094 bgp_info_reap(rn
, ri
);
4099 /* Delete all kernel routes. */
4100 void bgp_cleanup_routes(struct bgp
*bgp
)
4103 struct bgp_node
*rn
;
4105 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
4106 if (afi
== AFI_L2VPN
)
4108 bgp_cleanup_table(bgp
, bgp
->rib
[afi
][SAFI_UNICAST
],
4111 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
4113 if (afi
!= AFI_L2VPN
) {
4115 safi
= SAFI_MPLS_VPN
;
4116 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4117 rn
= bgp_route_next(rn
)) {
4119 bgp_cleanup_table(bgp
,
4120 (struct bgp_table
*)(rn
->info
),
4122 bgp_table_finish((struct bgp_table
**)&(
4125 bgp_unlock_node(rn
);
4129 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4130 rn
= bgp_route_next(rn
)) {
4132 bgp_cleanup_table(bgp
,
4133 (struct bgp_table
*)(rn
->info
),
4135 bgp_table_finish((struct bgp_table
**)&(
4138 bgp_unlock_node(rn
);
4143 for (rn
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); rn
;
4144 rn
= bgp_route_next(rn
)) {
4146 bgp_cleanup_table(bgp
,
4147 (struct bgp_table
*)(rn
->info
),
4149 bgp_table_finish((struct bgp_table
**)&(rn
->info
));
4151 bgp_unlock_node(rn
);
4156 void bgp_reset(void)
4159 bgp_zclient_reset();
4160 access_list_reset();
4161 prefix_list_reset();
4164 static int bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
4166 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
4167 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
4168 PEER_CAP_ADDPATH_AF_TX_RCV
));
4171 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
4173 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
4174 struct bgp_nlri
*packet
)
4183 int addpath_encoded
;
4184 uint32_t addpath_id
;
4187 lim
= pnt
+ packet
->length
;
4189 safi
= packet
->safi
;
4191 addpath_encoded
= bgp_addpath_encode_rx(peer
, afi
, safi
);
4193 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
4194 syntactic validity. If the field is syntactically incorrect,
4195 then the Error Subcode is set to Invalid Network Field. */
4196 for (; pnt
< lim
; pnt
+= psize
) {
4197 /* Clear prefix structure. */
4198 memset(&p
, 0, sizeof(struct prefix
));
4200 if (addpath_encoded
) {
4202 /* When packet overflow occurs return immediately. */
4203 if (pnt
+ BGP_ADDPATH_ID_LEN
> lim
)
4206 addpath_id
= ntohl(*((uint32_t *)pnt
));
4207 pnt
+= BGP_ADDPATH_ID_LEN
;
4210 /* Fetch prefix length. */
4211 p
.prefixlen
= *pnt
++;
4212 /* afi/safi validity already verified by caller,
4213 * bgp_update_receive */
4214 p
.family
= afi2family(afi
);
4216 /* Prefix length check. */
4217 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
4220 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
4221 peer
->host
, p
.prefixlen
, packet
->afi
);
4225 /* Packet size overflow check. */
4226 psize
= PSIZE(p
.prefixlen
);
4228 /* When packet overflow occur return immediately. */
4229 if (pnt
+ psize
> lim
) {
4232 "%s [Error] Update packet error (prefix length %d overflows packet)",
4233 peer
->host
, p
.prefixlen
);
4237 /* Defensive coding, double-check the psize fits in a struct
4239 if (psize
> (ssize_t
)sizeof(p
.u
)) {
4242 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
4243 peer
->host
, p
.prefixlen
, sizeof(p
.u
));
4247 /* Fetch prefix from NLRI packet. */
4248 memcpy(p
.u
.val
, pnt
, psize
);
4250 /* Check address. */
4251 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
4252 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
4253 /* From RFC4271 Section 6.3:
4255 * If a prefix in the NLRI field is semantically
4257 * (e.g., an unexpected multicast IP address),
4259 * be logged locally, and the prefix SHOULD be
4264 "%s: IPv4 unicast NLRI is multicast address %s, ignoring",
4265 peer
->host
, inet_ntoa(p
.u
.prefix4
));
4270 /* Check address. */
4271 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
4272 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4277 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
4279 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4284 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
4289 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
4291 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4298 /* Normal process. */
4300 ret
= bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
4301 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
4302 NULL
, NULL
, 0, 0, NULL
);
4304 ret
= bgp_withdraw(peer
, &p
, addpath_id
, attr
, afi
,
4305 safi
, ZEBRA_ROUTE_BGP
,
4306 BGP_ROUTE_NORMAL
, NULL
, NULL
, 0,
4309 /* Address family configuration mismatch or maximum-prefix count
4315 /* Packet length consistency check. */
4319 "%s [Error] Update packet error (prefix length mismatch with total length)",
4327 static struct bgp_static
*bgp_static_new(void)
4329 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
4332 static void bgp_static_free(struct bgp_static
*bgp_static
)
4334 if (bgp_static
->rmap
.name
)
4335 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
4336 if (bgp_static
->eth_s_id
)
4337 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
4338 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
4341 void bgp_static_update(struct bgp
*bgp
, struct prefix
*p
,
4342 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
4344 struct bgp_node
*rn
;
4345 struct bgp_info
*ri
;
4346 struct bgp_info
*new;
4347 struct bgp_info info
;
4349 struct attr
*attr_new
;
4352 int vnc_implicit_withdraw
= 0;
4359 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4361 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4363 attr
.nexthop
= bgp_static
->igpnexthop
;
4364 attr
.med
= bgp_static
->igpmetric
;
4365 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4367 if (bgp_static
->atomic
)
4368 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
4370 /* Store label index, if required. */
4371 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
4372 attr
.label_index
= bgp_static
->label_index
;
4373 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
4376 /* Apply route-map. */
4377 if (bgp_static
->rmap
.name
) {
4378 struct attr attr_tmp
= attr
;
4380 memset(&info
, 0, sizeof(struct bgp_info
));
4381 info
.peer
= bgp
->peer_self
;
4382 info
.attr
= &attr_tmp
;
4384 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4386 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
, &info
);
4388 bgp
->peer_self
->rmap_type
= 0;
4390 if (ret
== RMAP_DENYMATCH
) {
4391 /* Free uninterned attribute. */
4392 bgp_attr_flush(&attr_tmp
);
4394 /* Unintern original. */
4395 aspath_unintern(&attr
.aspath
);
4396 bgp_static_withdraw(bgp
, p
, afi
, safi
);
4400 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4401 bgp_attr_add_gshut_community(&attr_tmp
);
4403 attr_new
= bgp_attr_intern(&attr_tmp
);
4406 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4407 bgp_attr_add_gshut_community(&attr
);
4409 attr_new
= bgp_attr_intern(&attr
);
4412 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4413 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4414 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4418 if (attrhash_cmp(ri
->attr
, attr_new
)
4419 && !CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)
4420 && !bgp_flag_check(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
4421 bgp_unlock_node(rn
);
4422 bgp_attr_unintern(&attr_new
);
4423 aspath_unintern(&attr
.aspath
);
4426 /* The attribute is changed. */
4427 bgp_info_set_flag(rn
, ri
, BGP_INFO_ATTR_CHANGED
);
4429 /* Rewrite BGP route information. */
4430 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
))
4431 bgp_info_restore(rn
, ri
);
4433 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4435 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4436 && (safi
== SAFI_UNICAST
)) {
4437 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
4439 * Implicit withdraw case.
4440 * We have to do this before ri is
4443 ++vnc_implicit_withdraw
;
4444 vnc_import_bgp_del_route(bgp
, p
, ri
);
4445 vnc_import_bgp_exterior_del_route(
4450 bgp_attr_unintern(&ri
->attr
);
4451 ri
->attr
= attr_new
;
4452 ri
->uptime
= bgp_clock();
4454 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4455 && (safi
== SAFI_UNICAST
)) {
4456 if (vnc_implicit_withdraw
) {
4457 vnc_import_bgp_add_route(bgp
, p
, ri
);
4458 vnc_import_bgp_exterior_add_route(
4464 /* Nexthop reachability check. */
4465 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4466 && (safi
== SAFI_UNICAST
4467 || safi
== SAFI_LABELED_UNICAST
)) {
4469 struct bgp
*bgp_nexthop
= bgp
;
4471 if (ri
->extra
&& ri
->extra
->bgp_orig
)
4472 bgp_nexthop
= ri
->extra
->bgp_orig
;
4474 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
,
4476 bgp_info_set_flag(rn
, ri
,
4479 if (BGP_DEBUG(nht
, NHT
)) {
4480 char buf1
[INET6_ADDRSTRLEN
];
4481 inet_ntop(p
->family
,
4485 "%s(%s): Route not in table, not advertising",
4486 __FUNCTION__
, buf1
);
4488 bgp_info_unset_flag(rn
, ri
,
4492 /* Delete the NHT structure if any, if we're
4494 * enabling/disabling import check. We
4495 * deregister the route
4496 * from NHT to avoid overloading NHT and the
4497 * process interaction
4499 bgp_unlink_nexthop(ri
);
4500 bgp_info_set_flag(rn
, ri
, BGP_INFO_VALID
);
4502 /* Process change. */
4503 bgp_aggregate_increment(bgp
, p
, ri
, afi
, safi
);
4504 bgp_process(bgp
, rn
, afi
, safi
);
4506 if (SAFI_UNICAST
== safi
4507 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4509 == BGP_INSTANCE_TYPE_DEFAULT
)) {
4510 vpn_leak_from_vrf_update(bgp_get_default(), bgp
,
4514 bgp_unlock_node(rn
);
4515 aspath_unintern(&attr
.aspath
);
4520 /* Make new BGP info. */
4521 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
4523 /* Nexthop reachability check. */
4524 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4525 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
4526 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, new, NULL
, 0))
4527 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
4529 if (BGP_DEBUG(nht
, NHT
)) {
4530 char buf1
[INET6_ADDRSTRLEN
];
4531 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
4534 "%s(%s): Route not in table, not advertising",
4535 __FUNCTION__
, buf1
);
4537 bgp_info_unset_flag(rn
, new, BGP_INFO_VALID
);
4540 /* Delete the NHT structure if any, if we're toggling between
4541 * enabling/disabling import check. We deregister the route
4542 * from NHT to avoid overloading NHT and the process interaction
4544 bgp_unlink_nexthop(new);
4546 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
4549 /* Aggregate address increment. */
4550 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4552 /* Register new BGP information. */
4553 bgp_info_add(rn
, new);
4555 /* route_node_get lock */
4556 bgp_unlock_node(rn
);
4558 /* Process change. */
4559 bgp_process(bgp
, rn
, afi
, safi
);
4561 if (SAFI_UNICAST
== safi
4562 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4563 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4564 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
4567 /* Unintern original. */
4568 aspath_unintern(&attr
.aspath
);
4571 void bgp_static_withdraw(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
4574 struct bgp_node
*rn
;
4575 struct bgp_info
*ri
;
4577 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4579 /* Check selected route and self inserted route. */
4580 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4581 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4582 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4585 /* Withdraw static BGP route from routing table. */
4587 if (SAFI_UNICAST
== safi
4588 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4589 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4590 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, ri
);
4592 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4593 bgp_unlink_nexthop(ri
);
4594 bgp_info_delete(rn
, ri
);
4595 bgp_process(bgp
, rn
, afi
, safi
);
4598 /* Unlock bgp_node_lookup. */
4599 bgp_unlock_node(rn
);
4603 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
4605 static void bgp_static_withdraw_safi(struct bgp
*bgp
, struct prefix
*p
,
4606 afi_t afi
, safi_t safi
,
4607 struct prefix_rd
*prd
)
4609 struct bgp_node
*rn
;
4610 struct bgp_info
*ri
;
4612 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4614 /* Check selected route and self inserted route. */
4615 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4616 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4617 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4620 /* Withdraw static BGP route from routing table. */
4623 rfapiProcessWithdraw(
4624 ri
->peer
, NULL
, p
, prd
, ri
->attr
, afi
, safi
, ri
->type
,
4625 1); /* Kill, since it is an administrative change */
4627 if (SAFI_MPLS_VPN
== safi
4628 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4629 vpn_leak_to_vrf_withdraw(bgp
, ri
);
4631 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4632 bgp_info_delete(rn
, ri
);
4633 bgp_process(bgp
, rn
, afi
, safi
);
4636 /* Unlock bgp_node_lookup. */
4637 bgp_unlock_node(rn
);
4640 static void bgp_static_update_safi(struct bgp
*bgp
, struct prefix
*p
,
4641 struct bgp_static
*bgp_static
, afi_t afi
,
4644 struct bgp_node
*rn
;
4645 struct bgp_info
*new;
4646 struct attr
*attr_new
;
4647 struct attr attr
= {0};
4648 struct bgp_info
*ri
;
4650 mpls_label_t label
= 0;
4652 uint32_t num_labels
= 0;
4657 if (bgp_static
->label
!= MPLS_INVALID_LABEL
)
4659 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
4662 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4664 attr
.nexthop
= bgp_static
->igpnexthop
;
4665 attr
.med
= bgp_static
->igpmetric
;
4666 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4668 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
4669 || (safi
== SAFI_ENCAP
)) {
4670 if (afi
== AFI_IP
) {
4671 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
4672 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
4675 if (afi
== AFI_L2VPN
) {
4676 if (bgp_static
->gatewayIp
.family
== AF_INET
)
4678 bgp_static
->gatewayIp
.u
.prefix4
.s_addr
;
4679 else if (bgp_static
->gatewayIp
.family
== AF_INET6
)
4680 memcpy(&(add
.ipv6
), &(bgp_static
->gatewayIp
.u
.prefix6
),
4681 sizeof(struct in6_addr
));
4682 overlay_index_update(&attr
, bgp_static
->eth_s_id
, &add
);
4683 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
4684 struct bgp_encap_type_vxlan bet
;
4685 memset(&bet
, 0, sizeof(struct bgp_encap_type_vxlan
));
4686 bet
.vnid
= p
->u
.prefix_evpn
.prefix_addr
.eth_tag
;
4687 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
4689 if (bgp_static
->router_mac
) {
4690 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
4693 /* Apply route-map. */
4694 if (bgp_static
->rmap
.name
) {
4695 struct attr attr_tmp
= attr
;
4696 struct bgp_info info
;
4699 info
.peer
= bgp
->peer_self
;
4700 info
.attr
= &attr_tmp
;
4702 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4704 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
, &info
);
4706 bgp
->peer_self
->rmap_type
= 0;
4708 if (ret
== RMAP_DENYMATCH
) {
4709 /* Free uninterned attribute. */
4710 bgp_attr_flush(&attr_tmp
);
4712 /* Unintern original. */
4713 aspath_unintern(&attr
.aspath
);
4714 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
4719 attr_new
= bgp_attr_intern(&attr_tmp
);
4721 attr_new
= bgp_attr_intern(&attr
);
4724 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4725 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4726 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4730 memset(&add
, 0, sizeof(union gw_addr
));
4731 if (attrhash_cmp(ri
->attr
, attr_new
)
4732 && overlay_index_equal(afi
, ri
, bgp_static
->eth_s_id
, &add
)
4733 && !CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)) {
4734 bgp_unlock_node(rn
);
4735 bgp_attr_unintern(&attr_new
);
4736 aspath_unintern(&attr
.aspath
);
4739 /* The attribute is changed. */
4740 bgp_info_set_flag(rn
, ri
, BGP_INFO_ATTR_CHANGED
);
4742 /* Rewrite BGP route information. */
4743 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
))
4744 bgp_info_restore(rn
, ri
);
4746 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4747 bgp_attr_unintern(&ri
->attr
);
4748 ri
->attr
= attr_new
;
4749 ri
->uptime
= bgp_clock();
4752 label
= decode_label(&ri
->extra
->label
[0]);
4755 /* Process change. */
4756 bgp_aggregate_increment(bgp
, p
, ri
, afi
, safi
);
4757 bgp_process(bgp
, rn
, afi
, safi
);
4759 if (SAFI_MPLS_VPN
== safi
4760 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4761 vpn_leak_to_vrf_update(bgp
, ri
);
4764 rfapiProcessUpdate(ri
->peer
, NULL
, p
, &bgp_static
->prd
,
4765 ri
->attr
, afi
, safi
, ri
->type
,
4766 ri
->sub_type
, &label
);
4768 bgp_unlock_node(rn
);
4769 aspath_unintern(&attr
.aspath
);
4775 /* Make new BGP info. */
4776 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
4778 SET_FLAG(new->flags
, BGP_INFO_VALID
);
4779 new->extra
= bgp_info_extra_new();
4781 new->extra
->label
[0] = bgp_static
->label
;
4782 new->extra
->num_labels
= num_labels
;
4785 label
= decode_label(&bgp_static
->label
);
4788 /* Aggregate address increment. */
4789 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4791 /* Register new BGP information. */
4792 bgp_info_add(rn
, new);
4793 /* route_node_get lock */
4794 bgp_unlock_node(rn
);
4796 /* Process change. */
4797 bgp_process(bgp
, rn
, afi
, safi
);
4799 if (SAFI_MPLS_VPN
== safi
4800 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4801 vpn_leak_to_vrf_update(bgp
, new);
4804 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
4805 safi
, new->type
, new->sub_type
, &label
);
4808 /* Unintern original. */
4809 aspath_unintern(&attr
.aspath
);
4812 /* Configure static BGP network. When user don't run zebra, static
4813 route should be installed as valid. */
4814 static int bgp_static_set(struct vty
*vty
, const char *negate
,
4815 const char *ip_str
, afi_t afi
, safi_t safi
,
4816 const char *rmap
, int backdoor
, uint32_t label_index
)
4818 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
4821 struct bgp_static
*bgp_static
;
4822 struct bgp_node
*rn
;
4823 uint8_t need_update
= 0;
4825 /* Convert IP prefix string to struct prefix. */
4826 ret
= str2prefix(ip_str
, &p
);
4828 vty_out(vty
, "%% Malformed prefix\n");
4829 return CMD_WARNING_CONFIG_FAILED
;
4831 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4832 vty_out(vty
, "%% Malformed prefix (link-local address)\n");
4833 return CMD_WARNING_CONFIG_FAILED
;
4840 /* Set BGP static route configuration. */
4841 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
4844 vty_out(vty
, "%% Can't find static route specified\n");
4845 return CMD_WARNING_CONFIG_FAILED
;
4848 bgp_static
= bgp_static_get_node_info(rn
);
4850 if ((label_index
!= BGP_INVALID_LABEL_INDEX
)
4851 && (label_index
!= bgp_static
->label_index
)) {
4853 "%% label-index doesn't match static route\n");
4854 return CMD_WARNING_CONFIG_FAILED
;
4857 if ((rmap
&& bgp_static
->rmap
.name
)
4858 && strcmp(rmap
, bgp_static
->rmap
.name
)) {
4860 "%% route-map name doesn't match static route\n");
4861 return CMD_WARNING_CONFIG_FAILED
;
4864 /* Update BGP RIB. */
4865 if (!bgp_static
->backdoor
)
4866 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
4868 /* Clear configuration. */
4869 bgp_static_free(bgp_static
);
4870 bgp_static_set_node_info(rn
, NULL
);
4871 bgp_unlock_node(rn
);
4872 bgp_unlock_node(rn
);
4875 /* Set BGP static route configuration. */
4876 rn
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
4878 bgp_static
= bgp_static_get_node_info(rn
);
4880 /* Configuration change. */
4881 /* Label index cannot be changed. */
4882 if (bgp_static
->label_index
!= label_index
) {
4883 vty_out(vty
, "%% cannot change label-index\n");
4884 return CMD_WARNING_CONFIG_FAILED
;
4887 /* Check previous routes are installed into BGP. */
4888 if (bgp_static
->valid
4889 && bgp_static
->backdoor
!= backdoor
)
4892 bgp_static
->backdoor
= backdoor
;
4895 if (bgp_static
->rmap
.name
)
4896 XFREE(MTYPE_ROUTE_MAP_NAME
,
4897 bgp_static
->rmap
.name
);
4898 bgp_static
->rmap
.name
=
4899 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
4900 bgp_static
->rmap
.map
=
4901 route_map_lookup_by_name(rmap
);
4903 if (bgp_static
->rmap
.name
)
4904 XFREE(MTYPE_ROUTE_MAP_NAME
,
4905 bgp_static
->rmap
.name
);
4906 bgp_static
->rmap
.name
= NULL
;
4907 bgp_static
->rmap
.map
= NULL
;
4908 bgp_static
->valid
= 0;
4910 bgp_unlock_node(rn
);
4912 /* New configuration. */
4913 bgp_static
= bgp_static_new();
4914 bgp_static
->backdoor
= backdoor
;
4915 bgp_static
->valid
= 0;
4916 bgp_static
->igpmetric
= 0;
4917 bgp_static
->igpnexthop
.s_addr
= 0;
4918 bgp_static
->label_index
= label_index
;
4921 if (bgp_static
->rmap
.name
)
4922 XFREE(MTYPE_ROUTE_MAP_NAME
,
4923 bgp_static
->rmap
.name
);
4924 bgp_static
->rmap
.name
=
4925 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
4926 bgp_static
->rmap
.map
=
4927 route_map_lookup_by_name(rmap
);
4929 bgp_static_set_node_info(rn
, bgp_static
);
4932 bgp_static
->valid
= 1;
4934 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
4936 if (!bgp_static
->backdoor
)
4937 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
4943 void bgp_static_add(struct bgp
*bgp
)
4947 struct bgp_node
*rn
;
4948 struct bgp_node
*rm
;
4949 struct bgp_table
*table
;
4950 struct bgp_static
*bgp_static
;
4952 FOREACH_AFI_SAFI (afi
, safi
)
4953 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
4954 rn
= bgp_route_next(rn
)) {
4955 if (rn
->info
== NULL
)
4958 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
4959 || (safi
== SAFI_EVPN
)) {
4962 for (rm
= bgp_table_top(table
); rm
;
4963 rm
= bgp_route_next(rm
)) {
4965 bgp_static_get_node_info(rm
);
4966 bgp_static_update_safi(bgp
, &rm
->p
,
4971 bgp_static_update(bgp
, &rn
->p
,
4972 bgp_static_get_node_info(rn
),
4978 /* Called from bgp_delete(). Delete all static routes from the BGP
4980 void bgp_static_delete(struct bgp
*bgp
)
4984 struct bgp_node
*rn
;
4985 struct bgp_node
*rm
;
4986 struct bgp_table
*table
;
4987 struct bgp_static
*bgp_static
;
4989 FOREACH_AFI_SAFI (afi
, safi
)
4990 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
4991 rn
= bgp_route_next(rn
)) {
4992 if (rn
->info
== NULL
)
4995 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
4996 || (safi
== SAFI_EVPN
)) {
4999 for (rm
= bgp_table_top(table
); rm
;
5000 rm
= bgp_route_next(rm
)) {
5002 bgp_static_get_node_info(rm
);
5003 bgp_static_withdraw_safi(
5004 bgp
, &rm
->p
, AFI_IP
, safi
,
5005 (struct prefix_rd
*)&rn
->p
);
5006 bgp_static_free(bgp_static
);
5007 bgp_static_set_node_info(rn
, NULL
);
5008 bgp_unlock_node(rn
);
5011 bgp_static
= bgp_static_get_node_info(rn
);
5012 bgp_static_withdraw(bgp
, &rn
->p
, afi
, safi
);
5013 bgp_static_free(bgp_static
);
5014 bgp_static_set_node_info(rn
, NULL
);
5015 bgp_unlock_node(rn
);
5020 void bgp_static_redo_import_check(struct bgp
*bgp
)
5024 struct bgp_node
*rn
;
5025 struct bgp_node
*rm
;
5026 struct bgp_table
*table
;
5027 struct bgp_static
*bgp_static
;
5029 /* Use this flag to force reprocessing of the route */
5030 bgp_flag_set(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5031 FOREACH_AFI_SAFI (afi
, safi
) {
5032 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5033 rn
= bgp_route_next(rn
)) {
5034 if (rn
->info
== NULL
)
5037 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5038 || (safi
== SAFI_EVPN
)) {
5041 for (rm
= bgp_table_top(table
); rm
;
5042 rm
= bgp_route_next(rm
)) {
5044 bgp_static_get_node_info(rm
);
5045 bgp_static_update_safi(bgp
, &rm
->p
,
5050 bgp_static
= bgp_static_get_node_info(rn
);
5051 bgp_static_update(bgp
, &rn
->p
, bgp_static
, afi
,
5056 bgp_flag_unset(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5059 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
5062 struct bgp_table
*table
;
5063 struct bgp_node
*rn
;
5064 struct bgp_info
*ri
;
5066 table
= bgp
->rib
[afi
][safi
];
5067 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
5068 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
5069 if (ri
->peer
== bgp
->peer_self
5070 && ((ri
->type
== ZEBRA_ROUTE_BGP
5071 && ri
->sub_type
== BGP_ROUTE_STATIC
)
5072 || (ri
->type
!= ZEBRA_ROUTE_BGP
5074 == BGP_ROUTE_REDISTRIBUTE
))) {
5075 bgp_aggregate_decrement(bgp
, &rn
->p
, ri
, afi
,
5077 bgp_unlink_nexthop(ri
);
5078 bgp_info_delete(rn
, ri
);
5079 bgp_process(bgp
, rn
, afi
, safi
);
5086 * Purge all networks and redistributed routes from routing table.
5087 * Invoked upon the instance going down.
5089 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
5094 FOREACH_AFI_SAFI (afi
, safi
)
5095 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
5100 * Currently this is used to set static routes for VPN and ENCAP.
5101 * I think it can probably be factored with bgp_static_set.
5103 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5104 const char *ip_str
, const char *rd_str
,
5105 const char *label_str
, const char *rmap_str
,
5106 int evpn_type
, const char *esi
, const char *gwip
,
5107 const char *ethtag
, const char *routermac
)
5109 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5112 struct prefix_rd prd
;
5113 struct bgp_node
*prn
;
5114 struct bgp_node
*rn
;
5115 struct bgp_table
*table
;
5116 struct bgp_static
*bgp_static
;
5117 mpls_label_t label
= MPLS_INVALID_LABEL
;
5118 struct prefix gw_ip
;
5120 /* validate ip prefix */
5121 ret
= str2prefix(ip_str
, &p
);
5123 vty_out(vty
, "%% Malformed prefix\n");
5124 return CMD_WARNING_CONFIG_FAILED
;
5127 if ((afi
== AFI_L2VPN
)
5128 && (bgp_build_evpn_prefix(evpn_type
,
5129 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5130 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5131 return CMD_WARNING_CONFIG_FAILED
;
5134 ret
= str2prefix_rd(rd_str
, &prd
);
5136 vty_out(vty
, "%% Malformed rd\n");
5137 return CMD_WARNING_CONFIG_FAILED
;
5141 unsigned long label_val
;
5142 label_val
= strtoul(label_str
, NULL
, 10);
5143 encode_label(label_val
, &label
);
5146 if (safi
== SAFI_EVPN
) {
5147 if (esi
&& str2esi(esi
, NULL
) == 0) {
5148 vty_out(vty
, "%% Malformed ESI\n");
5149 return CMD_WARNING_CONFIG_FAILED
;
5151 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
5152 vty_out(vty
, "%% Malformed Router MAC\n");
5153 return CMD_WARNING_CONFIG_FAILED
;
5156 memset(&gw_ip
, 0, sizeof(struct prefix
));
5157 ret
= str2prefix(gwip
, &gw_ip
);
5159 vty_out(vty
, "%% Malformed GatewayIp\n");
5160 return CMD_WARNING_CONFIG_FAILED
;
5162 if ((gw_ip
.family
== AF_INET
5163 && is_evpn_prefix_ipaddr_v6(
5164 (struct prefix_evpn
*)&p
))
5165 || (gw_ip
.family
== AF_INET6
5166 && is_evpn_prefix_ipaddr_v4(
5167 (struct prefix_evpn
*)&p
))) {
5169 "%% GatewayIp family differs with IP prefix\n");
5170 return CMD_WARNING_CONFIG_FAILED
;
5174 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5175 if (prn
->info
== NULL
)
5176 prn
->info
= bgp_table_init(bgp
, afi
, safi
);
5178 bgp_unlock_node(prn
);
5181 rn
= bgp_node_get(table
, &p
);
5184 vty_out(vty
, "%% Same network configuration exists\n");
5185 bgp_unlock_node(rn
);
5187 /* New configuration. */
5188 bgp_static
= bgp_static_new();
5189 bgp_static
->backdoor
= 0;
5190 bgp_static
->valid
= 0;
5191 bgp_static
->igpmetric
= 0;
5192 bgp_static
->igpnexthop
.s_addr
= 0;
5193 bgp_static
->label
= label
;
5194 bgp_static
->prd
= prd
;
5197 if (bgp_static
->rmap
.name
)
5198 XFREE(MTYPE_ROUTE_MAP_NAME
,
5199 bgp_static
->rmap
.name
);
5200 bgp_static
->rmap
.name
=
5201 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
5202 bgp_static
->rmap
.map
=
5203 route_map_lookup_by_name(rmap_str
);
5206 if (safi
== SAFI_EVPN
) {
5208 bgp_static
->eth_s_id
=
5210 sizeof(struct eth_segment_id
));
5211 str2esi(esi
, bgp_static
->eth_s_id
);
5214 bgp_static
->router_mac
=
5215 XCALLOC(MTYPE_ATTR
, ETH_ALEN
+ 1);
5216 (void)prefix_str2mac(routermac
,
5217 bgp_static
->router_mac
);
5220 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
5222 bgp_static_set_node_info(rn
, bgp_static
);
5224 bgp_static
->valid
= 1;
5225 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
5231 /* Configure static BGP network. */
5232 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5233 const char *ip_str
, const char *rd_str
,
5234 const char *label_str
, int evpn_type
, const char *esi
,
5235 const char *gwip
, const char *ethtag
)
5237 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5240 struct prefix_rd prd
;
5241 struct bgp_node
*prn
;
5242 struct bgp_node
*rn
;
5243 struct bgp_table
*table
;
5244 struct bgp_static
*bgp_static
;
5245 mpls_label_t label
= MPLS_INVALID_LABEL
;
5247 /* Convert IP prefix string to struct prefix. */
5248 ret
= str2prefix(ip_str
, &p
);
5250 vty_out(vty
, "%% Malformed prefix\n");
5251 return CMD_WARNING_CONFIG_FAILED
;
5254 if ((afi
== AFI_L2VPN
)
5255 && (bgp_build_evpn_prefix(evpn_type
,
5256 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5257 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5258 return CMD_WARNING_CONFIG_FAILED
;
5260 ret
= str2prefix_rd(rd_str
, &prd
);
5262 vty_out(vty
, "%% Malformed rd\n");
5263 return CMD_WARNING_CONFIG_FAILED
;
5267 unsigned long label_val
;
5268 label_val
= strtoul(label_str
, NULL
, 10);
5269 encode_label(label_val
, &label
);
5272 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5273 if (prn
->info
== NULL
)
5274 prn
->info
= bgp_table_init(bgp
, afi
, safi
);
5276 bgp_unlock_node(prn
);
5279 rn
= bgp_node_lookup(table
, &p
);
5282 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
5284 bgp_static
= bgp_static_get_node_info(rn
);
5285 bgp_static_free(bgp_static
);
5286 bgp_static_set_node_info(rn
, NULL
);
5287 bgp_unlock_node(rn
);
5288 bgp_unlock_node(rn
);
5290 vty_out(vty
, "%% Can't find the route\n");
5295 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
5296 const char *rmap_name
)
5298 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5299 struct bgp_rmap
*rmap
;
5301 rmap
= &bgp
->table_map
[afi
][safi
];
5304 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5305 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
5306 rmap
->map
= route_map_lookup_by_name(rmap_name
);
5309 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5314 if (bgp_fibupd_safi(safi
))
5315 bgp_zebra_announce_table(bgp
, afi
, safi
);
5320 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
5321 const char *rmap_name
)
5323 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5324 struct bgp_rmap
*rmap
;
5326 rmap
= &bgp
->table_map
[afi
][safi
];
5328 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5332 if (bgp_fibupd_safi(safi
))
5333 bgp_zebra_announce_table(bgp
, afi
, safi
);
5338 void bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
5341 if (bgp
->table_map
[afi
][safi
].name
) {
5342 vty_out(vty
, " table-map %s\n",
5343 bgp
->table_map
[afi
][safi
].name
);
5347 DEFUN (bgp_table_map
,
5350 "BGP table to RIB route download filter\n"
5351 "Name of the route map\n")
5354 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5355 argv
[idx_word
]->arg
);
5357 DEFUN (no_bgp_table_map
,
5358 no_bgp_table_map_cmd
,
5359 "no table-map WORD",
5361 "BGP table to RIB route download filter\n"
5362 "Name of the route map\n")
5365 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5366 argv
[idx_word
]->arg
);
5372 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
5373 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
5374 backdoor$backdoor}]",
5376 "Specify a network to announce via BGP\n"
5381 "Route-map to modify the attributes\n"
5382 "Name of the route map\n"
5383 "Label index to associate with the prefix\n"
5384 "Label index value\n"
5385 "Specify a BGP backdoor route\n")
5387 char addr_prefix_str
[BUFSIZ
];
5392 ret
= netmask_str2prefix_str(address_str
, netmask_str
,
5395 vty_out(vty
, "%% Inconsistent address and mask\n");
5396 return CMD_WARNING_CONFIG_FAILED
;
5400 return bgp_static_set(
5401 vty
, no
, address_str
? addr_prefix_str
: prefix_str
, AFI_IP
,
5402 bgp_node_safi(vty
), map_name
, backdoor
? 1 : 0,
5403 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5406 DEFPY(ipv6_bgp_network
,
5407 ipv6_bgp_network_cmd
,
5408 "[no] network X:X::X:X/M$prefix \
5409 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
5411 "Specify a network to announce via BGP\n"
5413 "Route-map to modify the attributes\n"
5414 "Name of the route map\n"
5415 "Label index to associate with the prefix\n"
5416 "Label index value\n")
5418 return bgp_static_set(
5419 vty
, no
, prefix_str
, AFI_IP6
, bgp_node_safi(vty
), map_name
, 0,
5420 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5423 /* Aggreagete address:
5425 advertise-map Set condition to advertise attribute
5426 as-set Generate AS set path information
5427 attribute-map Set attributes of aggregate
5428 route-map Set parameters of aggregate
5429 summary-only Filter more specific routes from updates
5430 suppress-map Conditionally filter more specific routes from updates
5433 struct bgp_aggregate
{
5434 /* Summary-only flag. */
5435 uint8_t summary_only
;
5437 /* AS set generation. */
5440 /* Route-map for aggregated route. */
5441 struct route_map
*map
;
5443 /* Suppress-count. */
5444 unsigned long count
;
5446 /* SAFI configuration. */
5450 static struct bgp_aggregate
*bgp_aggregate_new(void)
5452 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
5455 static void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
5457 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
5460 static int bgp_aggregate_info_same(struct bgp_info
*ri
, uint8_t origin
,
5461 struct aspath
*aspath
,
5462 struct community
*comm
)
5464 static struct aspath
*ae
= NULL
;
5467 ae
= aspath_empty();
5472 if (origin
!= ri
->attr
->origin
)
5475 if (!aspath_cmp(ri
->attr
->aspath
, (aspath
) ? aspath
: ae
))
5478 if (!community_cmp(ri
->attr
->community
, comm
))
5481 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_VALID
))
5487 static void bgp_aggregate_install(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
5488 struct prefix
*p
, uint8_t origin
,
5489 struct aspath
*aspath
,
5490 struct community
*community
,
5491 uint8_t atomic_aggregate
,
5492 struct bgp_aggregate
*aggregate
)
5494 struct bgp_node
*rn
;
5495 struct bgp_table
*table
;
5496 struct bgp_info
*ri
, *new;
5498 table
= bgp
->rib
[afi
][safi
];
5500 rn
= bgp_node_get(table
, p
);
5502 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
5503 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
5504 && ri
->sub_type
== BGP_ROUTE_AGGREGATE
)
5507 if (aggregate
->count
> 0) {
5509 * If the aggregate information has not changed
5510 * no need to re-install it again.
5512 if (bgp_aggregate_info_same(rn
->info
, origin
, aspath
,
5514 bgp_unlock_node(rn
);
5517 aspath_free(aspath
);
5519 community_free(community
);
5525 * Mark the old as unusable
5528 bgp_info_delete(rn
, ri
);
5531 ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0, bgp
->peer_self
,
5532 bgp_attr_aggregate_intern(bgp
, origin
, aspath
,
5533 community
, aggregate
->as_set
,
5536 SET_FLAG(new->flags
, BGP_INFO_VALID
);
5538 bgp_info_add(rn
, new);
5539 bgp_process(bgp
, rn
, afi
, safi
);
5541 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
5542 if (ri
->peer
== bgp
->peer_self
5543 && ri
->type
== ZEBRA_ROUTE_BGP
5544 && ri
->sub_type
== BGP_ROUTE_AGGREGATE
)
5547 /* Withdraw static BGP route from routing table. */
5549 bgp_info_delete(rn
, ri
);
5550 bgp_process(bgp
, rn
, afi
, safi
);
5554 bgp_unlock_node(rn
);
5557 /* Update an aggregate as routes are added/removed from the BGP table */
5558 static void bgp_aggregate_route(struct bgp
*bgp
, struct prefix
*p
,
5559 struct bgp_info
*rinew
, afi_t afi
, safi_t safi
,
5560 struct bgp_info
*del
,
5561 struct bgp_aggregate
*aggregate
)
5563 struct bgp_table
*table
;
5564 struct bgp_node
*top
;
5565 struct bgp_node
*rn
;
5567 struct aspath
*aspath
= NULL
;
5568 struct aspath
*asmerge
= NULL
;
5569 struct community
*community
= NULL
;
5570 struct community
*commerge
= NULL
;
5571 struct bgp_info
*ri
;
5572 unsigned long match
= 0;
5573 uint8_t atomic_aggregate
= 0;
5575 /* ORIGIN attribute: If at least one route among routes that are
5576 aggregated has ORIGIN with the value INCOMPLETE, then the
5577 aggregated route must have the ORIGIN attribute with the value
5578 INCOMPLETE. Otherwise, if at least one route among routes that
5579 are aggregated has ORIGIN with the value EGP, then the aggregated
5580 route must have the origin attribute with the value EGP. In all
5581 other case the value of the ORIGIN attribute of the aggregated
5582 route is INTERNAL. */
5583 origin
= BGP_ORIGIN_IGP
;
5585 table
= bgp
->rib
[afi
][safi
];
5587 top
= bgp_node_get(table
, p
);
5588 for (rn
= bgp_node_get(table
, p
); rn
;
5589 rn
= bgp_route_next_until(rn
, top
)) {
5590 if (rn
->p
.prefixlen
<= p
->prefixlen
)
5595 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
5596 if (BGP_INFO_HOLDDOWN(ri
))
5599 if (del
&& ri
== del
)
5603 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
5604 atomic_aggregate
= 1;
5606 if (ri
->sub_type
== BGP_ROUTE_AGGREGATE
)
5610 * summary-only aggregate route suppress
5611 * aggregated route announcements.
5613 if (aggregate
->summary_only
) {
5614 (bgp_info_extra_get(ri
))->suppress
++;
5615 bgp_info_set_flag(rn
, ri
,
5616 BGP_INFO_ATTR_CHANGED
);
5623 * If at least one route among routes that are
5624 * aggregated has ORIGIN with the value INCOMPLETE,
5625 * then the aggregated route MUST have the ORIGIN
5626 * attribute with the value INCOMPLETE. Otherwise, if
5627 * at least one route among routes that are aggregated
5628 * has ORIGIN with the value EGP, then the aggregated
5629 * route MUST have the ORIGIN attribute with the value
5632 if (origin
< ri
->attr
->origin
)
5633 origin
= ri
->attr
->origin
;
5635 if (!aggregate
->as_set
)
5639 * as-set aggregate route generate origin, as path,
5640 * and community aggregation.
5643 asmerge
= aspath_aggregate(aspath
,
5645 aspath_free(aspath
);
5648 aspath
= aspath_dup(ri
->attr
->aspath
);
5650 if (!ri
->attr
->community
)
5654 commerge
= community_merge(community
,
5655 ri
->attr
->community
);
5656 community
= community_uniq_sort(commerge
);
5657 community_free(commerge
);
5659 community
= community_dup(ri
->attr
->community
);
5662 bgp_process(bgp
, rn
, afi
, safi
);
5664 bgp_unlock_node(top
);
5669 if (aggregate
->summary_only
)
5670 (bgp_info_extra_get(rinew
))->suppress
++;
5672 if (origin
< rinew
->attr
->origin
)
5673 origin
= rinew
->attr
->origin
;
5675 if (aggregate
->as_set
) {
5677 asmerge
= aspath_aggregate(aspath
,
5678 rinew
->attr
->aspath
);
5679 aspath_free(aspath
);
5682 aspath
= aspath_dup(rinew
->attr
->aspath
);
5684 if (rinew
->attr
->community
) {
5686 commerge
= community_merge(
5688 rinew
->attr
->community
);
5690 community_uniq_sort(commerge
);
5691 community_free(commerge
);
5693 community
= community_dup(
5694 rinew
->attr
->community
);
5699 bgp_aggregate_install(bgp
, afi
, safi
, p
, origin
, aspath
, community
,
5700 atomic_aggregate
, aggregate
);
5702 if (aggregate
->count
== 0) {
5704 aspath_free(aspath
);
5706 community_free(community
);
5710 static void bgp_aggregate_delete(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
5711 safi_t safi
, struct bgp_aggregate
*aggregate
)
5713 struct bgp_table
*table
;
5714 struct bgp_node
*top
;
5715 struct bgp_node
*rn
;
5716 struct bgp_info
*ri
;
5717 unsigned long match
;
5719 table
= bgp
->rib
[afi
][safi
];
5721 /* If routes exists below this node, generate aggregate routes. */
5722 top
= bgp_node_get(table
, p
);
5723 for (rn
= bgp_node_get(table
, p
); rn
;
5724 rn
= bgp_route_next_until(rn
, top
)) {
5725 if (rn
->p
.prefixlen
<= p
->prefixlen
)
5729 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
5730 if (BGP_INFO_HOLDDOWN(ri
))
5733 if (ri
->sub_type
== BGP_ROUTE_AGGREGATE
)
5736 if (aggregate
->summary_only
&& ri
->extra
) {
5737 ri
->extra
->suppress
--;
5739 if (ri
->extra
->suppress
== 0) {
5741 rn
, ri
, BGP_INFO_ATTR_CHANGED
);
5748 /* If this node was suppressed, process the change. */
5750 bgp_process(bgp
, rn
, afi
, safi
);
5752 bgp_unlock_node(top
);
5755 void bgp_aggregate_increment(struct bgp
*bgp
, struct prefix
*p
,
5756 struct bgp_info
*ri
, afi_t afi
, safi_t safi
)
5758 struct bgp_node
*child
;
5759 struct bgp_node
*rn
;
5760 struct bgp_aggregate
*aggregate
;
5761 struct bgp_table
*table
;
5763 table
= bgp
->aggregate
[afi
][safi
];
5765 /* No aggregates configured. */
5766 if (bgp_table_top_nolock(table
) == NULL
)
5769 if (p
->prefixlen
== 0)
5772 if (BGP_INFO_HOLDDOWN(ri
))
5775 child
= bgp_node_get(table
, p
);
5777 /* Aggregate address configuration check. */
5778 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
)) {
5779 aggregate
= bgp_aggregate_get_node_info(rn
);
5780 if (aggregate
!= NULL
&& rn
->p
.prefixlen
< p
->prefixlen
) {
5781 bgp_aggregate_delete(bgp
, &rn
->p
, afi
, safi
, aggregate
);
5782 bgp_aggregate_route(bgp
, &rn
->p
, ri
, afi
, safi
, NULL
,
5786 bgp_unlock_node(child
);
5789 void bgp_aggregate_decrement(struct bgp
*bgp
, struct prefix
*p
,
5790 struct bgp_info
*del
, afi_t afi
, safi_t safi
)
5792 struct bgp_node
*child
;
5793 struct bgp_node
*rn
;
5794 struct bgp_aggregate
*aggregate
;
5795 struct bgp_table
*table
;
5797 table
= bgp
->aggregate
[afi
][safi
];
5799 /* No aggregates configured. */
5800 if (bgp_table_top_nolock(table
) == NULL
)
5803 if (p
->prefixlen
== 0)
5806 child
= bgp_node_get(table
, p
);
5808 /* Aggregate address configuration check. */
5809 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
)) {
5810 aggregate
= bgp_aggregate_get_node_info(rn
);
5811 if (aggregate
!= NULL
&& rn
->p
.prefixlen
< p
->prefixlen
) {
5812 bgp_aggregate_delete(bgp
, &rn
->p
, afi
, safi
, aggregate
);
5813 bgp_aggregate_route(bgp
, &rn
->p
, NULL
, afi
, safi
, del
,
5817 bgp_unlock_node(child
);
5820 /* Aggregate route attribute. */
5821 #define AGGREGATE_SUMMARY_ONLY 1
5822 #define AGGREGATE_AS_SET 1
5824 static int bgp_aggregate_unset(struct vty
*vty
, const char *prefix_str
,
5825 afi_t afi
, safi_t safi
)
5827 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5830 struct bgp_node
*rn
;
5831 struct bgp_aggregate
*aggregate
;
5833 /* Convert string to prefix structure. */
5834 ret
= str2prefix(prefix_str
, &p
);
5836 vty_out(vty
, "Malformed prefix\n");
5837 return CMD_WARNING_CONFIG_FAILED
;
5841 /* Old configuration check. */
5842 rn
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], &p
);
5845 "%% There is no aggregate-address configuration.\n");
5846 return CMD_WARNING_CONFIG_FAILED
;
5849 aggregate
= bgp_aggregate_get_node_info(rn
);
5850 bgp_aggregate_delete(bgp
, &p
, afi
, safi
, aggregate
);
5851 bgp_aggregate_install(bgp
, afi
, safi
, &p
, 0, NULL
, NULL
, 0, aggregate
);
5853 /* Unlock aggregate address configuration. */
5854 bgp_aggregate_set_node_info(rn
, NULL
);
5855 bgp_aggregate_free(aggregate
);
5856 bgp_unlock_node(rn
);
5857 bgp_unlock_node(rn
);
5862 static int bgp_aggregate_set(struct vty
*vty
, const char *prefix_str
, afi_t afi
,
5863 safi_t safi
, uint8_t summary_only
, uint8_t as_set
)
5865 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5868 struct bgp_node
*rn
;
5869 struct bgp_aggregate
*aggregate
;
5871 /* Convert string to prefix structure. */
5872 ret
= str2prefix(prefix_str
, &p
);
5874 vty_out(vty
, "Malformed prefix\n");
5875 return CMD_WARNING_CONFIG_FAILED
;
5879 if ((afi
== AFI_IP
&& p
.prefixlen
== IPV4_MAX_BITLEN
) ||
5880 (afi
== AFI_IP6
&& p
.prefixlen
== IPV6_MAX_BITLEN
)) {
5881 vty_out(vty
, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
5883 return CMD_WARNING_CONFIG_FAILED
;
5886 /* Old configuration check. */
5887 rn
= bgp_node_get(bgp
->aggregate
[afi
][safi
], &p
);
5890 vty_out(vty
, "There is already same aggregate network.\n");
5891 /* try to remove the old entry */
5892 ret
= bgp_aggregate_unset(vty
, prefix_str
, afi
, safi
);
5894 vty_out(vty
, "Error deleting aggregate.\n");
5895 bgp_unlock_node(rn
);
5896 return CMD_WARNING_CONFIG_FAILED
;
5900 /* Make aggregate address structure. */
5901 aggregate
= bgp_aggregate_new();
5902 aggregate
->summary_only
= summary_only
;
5903 aggregate
->as_set
= as_set
;
5904 aggregate
->safi
= safi
;
5905 bgp_aggregate_set_node_info(rn
, aggregate
);
5907 /* Aggregate address insert into BGP routing table. */
5908 bgp_aggregate_route(bgp
, &p
, NULL
, afi
, safi
, NULL
, aggregate
);
5913 DEFUN (aggregate_address
,
5914 aggregate_address_cmd
,
5915 "aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
5916 "Configure BGP aggregate entries\n"
5917 "Aggregate prefix\n"
5918 "Generate AS set path information\n"
5919 "Filter more specific routes from updates\n"
5920 "Filter more specific routes from updates\n"
5921 "Generate AS set path information\n")
5924 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
5925 char *prefix
= argv
[idx
]->arg
;
5927 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
5929 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
5930 ? AGGREGATE_SUMMARY_ONLY
5933 return bgp_aggregate_set(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
),
5934 summary_only
, as_set
);
5937 DEFUN (aggregate_address_mask
,
5938 aggregate_address_mask_cmd
,
5939 "aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
5940 "Configure BGP aggregate entries\n"
5941 "Aggregate address\n"
5943 "Generate AS set path information\n"
5944 "Filter more specific routes from updates\n"
5945 "Filter more specific routes from updates\n"
5946 "Generate AS set path information\n")
5949 argv_find(argv
, argc
, "A.B.C.D", &idx
);
5950 char *prefix
= argv
[idx
]->arg
;
5951 char *mask
= argv
[idx
+ 1]->arg
;
5953 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
5955 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
5956 ? AGGREGATE_SUMMARY_ONLY
5959 char prefix_str
[BUFSIZ
];
5960 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
5963 vty_out(vty
, "%% Inconsistent address and mask\n");
5964 return CMD_WARNING_CONFIG_FAILED
;
5967 return bgp_aggregate_set(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
),
5968 summary_only
, as_set
);
5971 DEFUN (no_aggregate_address
,
5972 no_aggregate_address_cmd
,
5973 "no aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
5975 "Configure BGP aggregate entries\n"
5976 "Aggregate prefix\n"
5977 "Generate AS set path information\n"
5978 "Filter more specific routes from updates\n"
5979 "Filter more specific routes from updates\n"
5980 "Generate AS set path information\n")
5983 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
5984 char *prefix
= argv
[idx
]->arg
;
5985 return bgp_aggregate_unset(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
));
5988 DEFUN (no_aggregate_address_mask
,
5989 no_aggregate_address_mask_cmd
,
5990 "no aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
5992 "Configure BGP aggregate entries\n"
5993 "Aggregate address\n"
5995 "Generate AS set path information\n"
5996 "Filter more specific routes from updates\n"
5997 "Filter more specific routes from updates\n"
5998 "Generate AS set path information\n")
6001 argv_find(argv
, argc
, "A.B.C.D", &idx
);
6002 char *prefix
= argv
[idx
]->arg
;
6003 char *mask
= argv
[idx
+ 1]->arg
;
6005 char prefix_str
[BUFSIZ
];
6006 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
6009 vty_out(vty
, "%% Inconsistent address and mask\n");
6010 return CMD_WARNING_CONFIG_FAILED
;
6013 return bgp_aggregate_unset(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
));
6016 DEFUN (ipv6_aggregate_address
,
6017 ipv6_aggregate_address_cmd
,
6018 "aggregate-address X:X::X:X/M [summary-only]",
6019 "Configure BGP aggregate entries\n"
6020 "Aggregate prefix\n"
6021 "Filter more specific routes from updates\n")
6024 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6025 char *prefix
= argv
[idx
]->arg
;
6026 int sum_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6027 ? AGGREGATE_SUMMARY_ONLY
6029 return bgp_aggregate_set(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
, sum_only
,
6033 DEFUN (no_ipv6_aggregate_address
,
6034 no_ipv6_aggregate_address_cmd
,
6035 "no aggregate-address X:X::X:X/M [summary-only]",
6037 "Configure BGP aggregate entries\n"
6038 "Aggregate prefix\n"
6039 "Filter more specific routes from updates\n")
6042 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6043 char *prefix
= argv
[idx
]->arg
;
6044 return bgp_aggregate_unset(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
);
6047 /* Redistribute route treatment. */
6048 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
6049 const union g_addr
*nexthop
, ifindex_t ifindex
,
6050 enum nexthop_types_t nhtype
, uint32_t metric
,
6051 uint8_t type
, unsigned short instance
,
6054 struct bgp_info
*new;
6055 struct bgp_info
*bi
;
6056 struct bgp_info info
;
6057 struct bgp_node
*bn
;
6059 struct attr
*new_attr
;
6062 struct bgp_redist
*red
;
6064 /* Make default attribute. */
6065 bgp_attr_default_set(&attr
, BGP_ORIGIN_INCOMPLETE
);
6068 case NEXTHOP_TYPE_IFINDEX
:
6070 case NEXTHOP_TYPE_IPV4
:
6071 case NEXTHOP_TYPE_IPV4_IFINDEX
:
6072 attr
.nexthop
= nexthop
->ipv4
;
6074 case NEXTHOP_TYPE_IPV6
:
6075 case NEXTHOP_TYPE_IPV6_IFINDEX
:
6076 attr
.mp_nexthop_global
= nexthop
->ipv6
;
6077 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6079 case NEXTHOP_TYPE_BLACKHOLE
:
6080 switch (p
->family
) {
6082 attr
.nexthop
.s_addr
= INADDR_ANY
;
6085 memset(&attr
.mp_nexthop_global
, 0,
6086 sizeof(attr
.mp_nexthop_global
));
6087 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6092 attr
.nh_ifindex
= ifindex
;
6095 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6098 afi
= family2afi(p
->family
);
6100 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6102 struct attr attr_new
;
6104 /* Copy attribute for modification. */
6105 bgp_attr_dup(&attr_new
, &attr
);
6107 if (red
->redist_metric_flag
)
6108 attr_new
.med
= red
->redist_metric
;
6110 /* Apply route-map. */
6111 if (red
->rmap
.name
) {
6112 memset(&info
, 0, sizeof(struct bgp_info
));
6113 info
.peer
= bgp
->peer_self
;
6114 info
.attr
= &attr_new
;
6116 SET_FLAG(bgp
->peer_self
->rmap_type
,
6117 PEER_RMAP_TYPE_REDISTRIBUTE
);
6119 ret
= route_map_apply(red
->rmap
.map
, p
, RMAP_BGP
,
6122 bgp
->peer_self
->rmap_type
= 0;
6124 if (ret
== RMAP_DENYMATCH
) {
6125 /* Free uninterned attribute. */
6126 bgp_attr_flush(&attr_new
);
6128 /* Unintern original. */
6129 aspath_unintern(&attr
.aspath
);
6130 bgp_redistribute_delete(bgp
, p
, type
, instance
);
6135 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
6136 bgp_attr_add_gshut_community(&attr_new
);
6138 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6139 SAFI_UNICAST
, p
, NULL
);
6141 new_attr
= bgp_attr_intern(&attr_new
);
6143 for (bi
= bn
->info
; bi
; bi
= bi
->next
)
6144 if (bi
->peer
== bgp
->peer_self
6145 && bi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
6149 /* Ensure the (source route) type is updated. */
6151 if (attrhash_cmp(bi
->attr
, new_attr
)
6152 && !CHECK_FLAG(bi
->flags
, BGP_INFO_REMOVED
)) {
6153 bgp_attr_unintern(&new_attr
);
6154 aspath_unintern(&attr
.aspath
);
6155 bgp_unlock_node(bn
);
6158 /* The attribute is changed. */
6159 bgp_info_set_flag(bn
, bi
,
6160 BGP_INFO_ATTR_CHANGED
);
6162 /* Rewrite BGP route information. */
6163 if (CHECK_FLAG(bi
->flags
, BGP_INFO_REMOVED
))
6164 bgp_info_restore(bn
, bi
);
6166 bgp_aggregate_decrement(bgp
, p
, bi
, afi
,
6168 bgp_attr_unintern(&bi
->attr
);
6169 bi
->attr
= new_attr
;
6170 bi
->uptime
= bgp_clock();
6172 /* Process change. */
6173 bgp_aggregate_increment(bgp
, p
, bi
, afi
,
6175 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6176 bgp_unlock_node(bn
);
6177 aspath_unintern(&attr
.aspath
);
6179 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6181 == BGP_INSTANCE_TYPE_DEFAULT
)) {
6183 vpn_leak_from_vrf_update(
6184 bgp_get_default(), bgp
, bi
);
6190 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
6191 bgp
->peer_self
, new_attr
, bn
);
6192 SET_FLAG(new->flags
, BGP_INFO_VALID
);
6194 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
6195 bgp_info_add(bn
, new);
6196 bgp_unlock_node(bn
);
6197 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6199 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6200 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6202 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
6206 /* Unintern original. */
6207 aspath_unintern(&attr
.aspath
);
6210 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, uint8_t type
,
6211 unsigned short instance
)
6214 struct bgp_node
*rn
;
6215 struct bgp_info
*ri
;
6216 struct bgp_redist
*red
;
6218 afi
= family2afi(p
->family
);
6220 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6222 rn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6223 SAFI_UNICAST
, p
, NULL
);
6225 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
6226 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== type
)
6230 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6231 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6233 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6236 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, SAFI_UNICAST
);
6237 bgp_info_delete(rn
, ri
);
6238 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6240 bgp_unlock_node(rn
);
6244 /* Withdraw specified route type's route. */
6245 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
6246 unsigned short instance
)
6248 struct bgp_node
*rn
;
6249 struct bgp_info
*ri
;
6250 struct bgp_table
*table
;
6252 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
6254 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
6255 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
6256 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== type
6257 && ri
->instance
== instance
)
6261 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6262 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6264 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6267 bgp_aggregate_decrement(bgp
, &rn
->p
, ri
, afi
,
6269 bgp_info_delete(rn
, ri
);
6270 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6275 /* Static function to display route. */
6276 static void route_vty_out_route(struct prefix
*p
, struct vty
*vty
,
6282 if (p
->family
== AF_INET
) {
6286 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
6289 json_object_string_add(json
, "prefix",
6290 inet_ntop(p
->family
,
6293 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
6295 } else if (p
->family
== AF_ETHERNET
) {
6296 prefix2str(p
, buf
, PREFIX_STRLEN
);
6297 len
= vty_out(vty
, "%s", buf
);
6298 } else if (p
->family
== AF_EVPN
) {
6302 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf
,
6305 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
6306 } else if (p
->family
== AF_FLOWSPEC
) {
6307 route_vty_out_flowspec(vty
, p
, NULL
,
6309 NLRI_STRING_FORMAT_JSON_SIMPLE
:
6310 NLRI_STRING_FORMAT_MIN
, json
);
6315 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
6322 vty_out(vty
, "\n%*s", 20, " ");
6324 vty_out(vty
, "%*s", len
, " ");
6328 enum bgp_display_type
{
6332 /* Print the short form route status for a bgp_info */
6333 static void route_vty_short_status_out(struct vty
*vty
, struct bgp_info
*binfo
,
6334 json_object
*json_path
)
6338 /* Route status display. */
6339 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_REMOVED
))
6340 json_object_boolean_true_add(json_path
, "removed");
6342 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_STALE
))
6343 json_object_boolean_true_add(json_path
, "stale");
6345 if (binfo
->extra
&& binfo
->extra
->suppress
)
6346 json_object_boolean_true_add(json_path
, "suppressed");
6348 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)
6349 && !CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6350 json_object_boolean_true_add(json_path
, "valid");
6353 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6354 json_object_boolean_true_add(json_path
, "history");
6356 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
))
6357 json_object_boolean_true_add(json_path
, "damped");
6359 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
))
6360 json_object_boolean_true_add(json_path
, "bestpath");
6362 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_MULTIPATH
))
6363 json_object_boolean_true_add(json_path
, "multipath");
6365 /* Internal route. */
6366 if ((binfo
->peer
->as
)
6367 && (binfo
->peer
->as
== binfo
->peer
->local_as
))
6368 json_object_string_add(json_path
, "pathFrom",
6371 json_object_string_add(json_path
, "pathFrom",
6377 /* Route status display. */
6378 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_REMOVED
))
6380 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_STALE
))
6382 else if (binfo
->extra
&& binfo
->extra
->suppress
)
6384 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)
6385 && !CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6391 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6393 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
))
6395 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
))
6397 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_MULTIPATH
))
6402 /* Internal route. */
6403 if (binfo
->peer
&& (binfo
->peer
->as
)
6404 && (binfo
->peer
->as
== binfo
->peer
->local_as
))
6410 /* called from terminal list command */
6411 void route_vty_out(struct vty
*vty
, struct prefix
*p
, struct bgp_info
*binfo
,
6412 int display
, safi_t safi
, json_object
*json_paths
)
6415 json_object
*json_path
= NULL
;
6416 json_object
*json_nexthops
= NULL
;
6417 json_object
*json_nexthop_global
= NULL
;
6418 json_object
*json_nexthop_ll
= NULL
;
6419 char vrf_id_str
[VRF_NAMSIZ
] = {0};
6420 bool nexthop_self
= CHECK_FLAG(binfo
->flags
, BGP_INFO_ANNC_NH_SELF
)
6423 bool nexthop_othervrf
= false;
6424 vrf_id_t nexthop_vrfid
= VRF_DEFAULT
;
6425 const char *nexthop_vrfname
= "Default";
6428 json_path
= json_object_new_object();
6430 /* short status lead text */
6431 route_vty_short_status_out(vty
, binfo
, json_path
);
6434 /* print prefix and mask */
6436 route_vty_out_route(p
, vty
, json_path
);
6438 vty_out(vty
, "%*s", 17, " ");
6440 route_vty_out_route(p
, vty
, json_path
);
6443 /* Print attribute */
6447 json_object_array_add(json_paths
, json_path
);
6455 * If vrf id of nexthop is different from that of prefix,
6456 * set up printable string to append
6458 if (binfo
->extra
&& binfo
->extra
->bgp_orig
) {
6459 const char *self
= "";
6464 nexthop_othervrf
= true;
6465 nexthop_vrfid
= binfo
->extra
->bgp_orig
->vrf_id
;
6467 if (binfo
->extra
->bgp_orig
->vrf_id
== VRF_UNKNOWN
)
6468 snprintf(vrf_id_str
, sizeof(vrf_id_str
),
6469 "@%s%s", VRFID_NONE_STR
, self
);
6471 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "@%u%s",
6472 binfo
->extra
->bgp_orig
->vrf_id
, self
);
6474 if (binfo
->extra
->bgp_orig
->inst_type
!=
6475 BGP_INSTANCE_TYPE_DEFAULT
)
6477 nexthop_vrfname
= binfo
->extra
->bgp_orig
->name
;
6479 const char *self
= "";
6484 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "%s", self
);
6488 * For ENCAP and EVPN routes, nexthop address family is not
6489 * neccessarily the same as the prefix address family.
6490 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
6491 * EVPN routes are also exchanged with a MP nexthop. Currently,
6493 * is only IPv4, the value will be present in either
6495 * attr->mp_nexthop_global_in
6497 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
6500 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
6504 sprintf(nexthop
, "%s",
6505 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
6509 sprintf(nexthop
, "%s",
6510 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
6514 sprintf(nexthop
, "?");
6519 json_nexthop_global
= json_object_new_object();
6521 json_object_string_add(json_nexthop_global
, "afi",
6522 (af
== AF_INET
) ? "ip" : "ipv6");
6523 json_object_string_add(json_nexthop_global
,
6524 (af
== AF_INET
) ? "ip" : "ipv6",
6526 json_object_boolean_true_add(json_nexthop_global
,
6529 vty_out(vty
, "%s%s", nexthop
, vrf_id_str
);
6530 } else if (safi
== SAFI_EVPN
) {
6532 json_nexthop_global
= json_object_new_object();
6534 json_object_string_add(json_nexthop_global
, "ip",
6535 inet_ntoa(attr
->nexthop
));
6536 json_object_string_add(json_nexthop_global
, "afi",
6538 json_object_boolean_true_add(json_nexthop_global
,
6541 vty_out(vty
, "%-16s%s", inet_ntoa(attr
->nexthop
),
6543 } else if (safi
== SAFI_FLOWSPEC
) {
6544 if (attr
->nexthop
.s_addr
!= 0) {
6546 json_nexthop_global
= json_object_new_object();
6547 json_object_string_add(
6548 json_nexthop_global
, "ip",
6549 inet_ntoa(attr
->nexthop
));
6550 json_object_string_add(json_nexthop_global
,
6552 json_object_boolean_true_add(json_nexthop_global
,
6555 vty_out(vty
, "%-16s", inet_ntoa(attr
->nexthop
));
6558 } else if (p
->family
== AF_INET
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6560 json_nexthop_global
= json_object_new_object();
6562 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_EVPN
))
6563 json_object_string_add(
6564 json_nexthop_global
, "ip",
6565 inet_ntoa(attr
->mp_nexthop_global_in
));
6567 json_object_string_add(
6568 json_nexthop_global
, "ip",
6569 inet_ntoa(attr
->nexthop
));
6571 json_object_string_add(json_nexthop_global
, "afi",
6573 json_object_boolean_true_add(json_nexthop_global
,
6578 snprintf(buf
, sizeof(buf
), "%s%s",
6579 inet_ntoa(attr
->nexthop
), vrf_id_str
);
6580 vty_out(vty
, "%-16s", buf
);
6585 else if (p
->family
== AF_INET6
|| BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6590 json_nexthop_global
= json_object_new_object();
6591 json_object_string_add(
6592 json_nexthop_global
, "ip",
6593 inet_ntop(AF_INET6
, &attr
->mp_nexthop_global
,
6595 json_object_string_add(json_nexthop_global
, "afi",
6597 json_object_string_add(json_nexthop_global
, "scope",
6600 /* We display both LL & GL if both have been
6602 if ((attr
->mp_nexthop_len
== 32)
6603 || (binfo
->peer
->conf_if
)) {
6604 json_nexthop_ll
= json_object_new_object();
6605 json_object_string_add(
6606 json_nexthop_ll
, "ip",
6608 &attr
->mp_nexthop_local
, buf
,
6610 json_object_string_add(json_nexthop_ll
, "afi",
6612 json_object_string_add(json_nexthop_ll
, "scope",
6615 if ((IPV6_ADDR_CMP(&attr
->mp_nexthop_global
,
6616 &attr
->mp_nexthop_local
)
6618 && !attr
->mp_nexthop_prefer_global
)
6619 json_object_boolean_true_add(
6620 json_nexthop_ll
, "used");
6622 json_object_boolean_true_add(
6623 json_nexthop_global
, "used");
6625 json_object_boolean_true_add(
6626 json_nexthop_global
, "used");
6628 /* Display LL if LL/Global both in table unless
6629 * prefer-global is set */
6630 if (((attr
->mp_nexthop_len
== 32)
6631 && !attr
->mp_nexthop_prefer_global
)
6632 || (binfo
->peer
->conf_if
)) {
6633 if (binfo
->peer
->conf_if
) {
6634 len
= vty_out(vty
, "%s",
6635 binfo
->peer
->conf_if
);
6636 len
= 16 - len
; /* len of IPv6
6642 vty_out(vty
, "\n%*s", 36, " ");
6644 vty_out(vty
, "%*s", len
, " ");
6650 &attr
->mp_nexthop_local
,
6656 vty_out(vty
, "\n%*s", 36, " ");
6658 vty_out(vty
, "%*s", len
, " ");
6664 &attr
->mp_nexthop_global
, buf
,
6670 vty_out(vty
, "\n%*s", 36, " ");
6672 vty_out(vty
, "%*s", len
, " ");
6678 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
6680 json_object_int_add(json_path
, "med", attr
->med
);
6682 vty_out(vty
, "%10u", attr
->med
);
6683 else if (!json_paths
)
6687 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
6689 json_object_int_add(json_path
, "localpref",
6692 vty_out(vty
, "%7u", attr
->local_pref
);
6693 else if (!json_paths
)
6697 json_object_int_add(json_path
, "weight", attr
->weight
);
6699 vty_out(vty
, "%7u ", attr
->weight
);
6703 json_object_string_add(
6704 json_path
, "peerId",
6705 sockunion2str(&binfo
->peer
->su
, buf
, SU_ADDRSTRLEN
));
6711 json_object_string_add(json_path
, "aspath",
6714 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
6719 json_object_string_add(json_path
, "origin",
6720 bgp_origin_long_str
[attr
->origin
]);
6722 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
6726 json_object_boolean_true_add(json_path
,
6727 "announceNexthopSelf");
6728 if (nexthop_othervrf
) {
6729 json_object_string_add(json_path
, "nhVrfName",
6732 json_object_int_add(json_path
, "nhVrfId",
6733 ((nexthop_vrfid
== VRF_UNKNOWN
)
6735 : (int)nexthop_vrfid
));
6740 if (json_nexthop_global
|| json_nexthop_ll
) {
6741 json_nexthops
= json_object_new_array();
6743 if (json_nexthop_global
)
6744 json_object_array_add(json_nexthops
,
6745 json_nexthop_global
);
6747 if (json_nexthop_ll
)
6748 json_object_array_add(json_nexthops
,
6751 json_object_object_add(json_path
, "nexthops",
6755 json_object_array_add(json_paths
, json_path
);
6759 /* prints an additional line, indented, with VNC info, if
6761 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
6762 rfapi_vty_out_vncinfo(vty
, p
, binfo
, safi
);
6767 /* called from terminal list command */
6768 void route_vty_out_tmp(struct vty
*vty
, struct prefix
*p
, struct attr
*attr
,
6769 safi_t safi
, bool use_json
, json_object
*json_ar
)
6771 json_object
*json_status
= NULL
;
6772 json_object
*json_net
= NULL
;
6774 /* Route status display. */
6776 json_status
= json_object_new_object();
6777 json_net
= json_object_new_object();
6784 /* print prefix and mask */
6786 json_object_string_add(
6787 json_net
, "addrPrefix",
6788 inet_ntop(p
->family
, &p
->u
.prefix
, buff
, BUFSIZ
));
6790 route_vty_out_route(p
, vty
, NULL
);
6792 /* Print attribute */
6795 if (p
->family
== AF_INET
6796 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6797 || safi
== SAFI_EVPN
6798 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6799 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6800 || safi
== SAFI_EVPN
)
6801 json_object_string_add(
6802 json_net
, "nextHop",
6804 attr
->mp_nexthop_global_in
));
6806 json_object_string_add(
6807 json_net
, "nextHop",
6808 inet_ntoa(attr
->nexthop
));
6809 } else if (p
->family
== AF_INET6
6810 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6813 json_object_string_add(
6814 json_net
, "netHopGloabal",
6816 &attr
->mp_nexthop_global
, buf
,
6821 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
6822 json_object_int_add(json_net
, "metric",
6825 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
6826 json_object_int_add(json_net
, "localPref",
6829 json_object_int_add(json_net
, "weight", attr
->weight
);
6833 json_object_string_add(json_net
, "asPath",
6837 json_object_string_add(json_net
, "bgpOriginCode",
6838 bgp_origin_str
[attr
->origin
]);
6840 if (p
->family
== AF_INET
6841 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6842 || safi
== SAFI_EVPN
6843 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6844 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6845 || safi
== SAFI_EVPN
)
6846 vty_out(vty
, "%-16s",
6848 attr
->mp_nexthop_global_in
));
6850 vty_out(vty
, "%-16s",
6851 inet_ntoa(attr
->nexthop
));
6852 } else if (p
->family
== AF_INET6
6853 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6860 &attr
->mp_nexthop_global
, buf
,
6864 vty_out(vty
, "\n%*s", 36, " ");
6866 vty_out(vty
, "%*s", len
, " ");
6869 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
6870 vty_out(vty
, "%10u", attr
->med
);
6874 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
6875 vty_out(vty
, "%7u", attr
->local_pref
);
6879 vty_out(vty
, "%7u ", attr
->weight
);
6883 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
6886 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
6890 json_object_boolean_true_add(json_status
, "*");
6891 json_object_boolean_true_add(json_status
, ">");
6892 json_object_object_add(json_net
, "appliedStatusSymbols",
6894 char buf_cut
[BUFSIZ
];
6895 json_object_object_add(
6897 inet_ntop(p
->family
, &p
->u
.prefix
, buf_cut
, BUFSIZ
),
6903 void route_vty_out_tag(struct vty
*vty
, struct prefix
*p
,
6904 struct bgp_info
*binfo
, int display
, safi_t safi
,
6907 json_object
*json_out
= NULL
;
6909 mpls_label_t label
= MPLS_INVALID_LABEL
;
6915 json_out
= json_object_new_object();
6917 /* short status lead text */
6918 route_vty_short_status_out(vty
, binfo
, json_out
);
6920 /* print prefix and mask */
6923 route_vty_out_route(p
, vty
, NULL
);
6925 vty_out(vty
, "%*s", 17, " ");
6928 /* Print attribute */
6931 if (((p
->family
== AF_INET
)
6932 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
6933 || (safi
== SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
6934 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6935 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6936 || safi
== SAFI_EVPN
) {
6938 json_object_string_add(
6939 json_out
, "mpNexthopGlobalIn",
6941 attr
->mp_nexthop_global_in
));
6943 vty_out(vty
, "%-16s",
6945 attr
->mp_nexthop_global_in
));
6948 json_object_string_add(
6949 json_out
, "nexthop",
6950 inet_ntoa(attr
->nexthop
));
6952 vty_out(vty
, "%-16s",
6953 inet_ntoa(attr
->nexthop
));
6955 } else if (((p
->family
== AF_INET6
)
6956 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
6957 || (safi
== SAFI_EVPN
6958 && BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
6959 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6963 if (attr
->mp_nexthop_len
6964 == BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
6966 json_object_string_add(
6967 json_out
, "mpNexthopGlobalIn",
6970 &attr
->mp_nexthop_global
,
6971 buf_a
, sizeof(buf_a
)));
6976 &attr
->mp_nexthop_global
,
6977 buf_a
, sizeof(buf_a
)));
6978 } else if (attr
->mp_nexthop_len
6979 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
6982 &attr
->mp_nexthop_global
,
6983 buf_a
, sizeof(buf_a
));
6985 &attr
->mp_nexthop_local
,
6986 buf_b
, sizeof(buf_b
));
6987 sprintf(buf_c
, "%s(%s)", buf_a
, buf_b
);
6988 json_object_string_add(
6990 "mpNexthopGlobalLocal", buf_c
);
6992 vty_out(vty
, "%s(%s)",
6995 &attr
->mp_nexthop_global
,
6996 buf_a
, sizeof(buf_a
)),
6999 &attr
->mp_nexthop_local
,
7000 buf_b
, sizeof(buf_b
)));
7005 label
= decode_label(&binfo
->extra
->label
[0]);
7007 if (bgp_is_valid_label(&label
)) {
7009 json_object_int_add(json_out
, "notag", label
);
7010 json_object_array_add(json
, json_out
);
7012 vty_out(vty
, "notag/%d", label
);
7018 void route_vty_out_overlay(struct vty
*vty
, struct prefix
*p
,
7019 struct bgp_info
*binfo
, int display
,
7020 json_object
*json_paths
)
7024 json_object
*json_path
= NULL
;
7027 json_path
= json_object_new_object();
7032 /* short status lead text */
7033 route_vty_short_status_out(vty
, binfo
, json_path
);
7035 /* print prefix and mask */
7037 route_vty_out_route(p
, vty
, NULL
);
7039 vty_out(vty
, "%*s", 17, " ");
7041 /* Print attribute */
7045 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
7049 vty_out(vty
, "%-16s",
7050 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
7054 vty_out(vty
, "%s(%s)",
7055 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
7057 inet_ntop(af
, &attr
->mp_nexthop_local
, buf1
,
7064 char *str
= esi2str(&(attr
->evpn_overlay
.eth_s_id
));
7066 vty_out(vty
, "%s", str
);
7067 XFREE(MTYPE_TMP
, str
);
7069 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn
*)p
)) {
7071 inet_ntoa(attr
->evpn_overlay
.gw_ip
.ipv4
));
7072 } else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn
*)p
)) {
7075 &(attr
->evpn_overlay
.gw_ip
.ipv6
), buf
,
7078 if (attr
->ecommunity
) {
7080 struct ecommunity_val
*routermac
= ecommunity_lookup(
7081 attr
->ecommunity
, ECOMMUNITY_ENCODE_EVPN
,
7082 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
7084 mac
= ecom_mac2str((char *)routermac
->val
);
7086 vty_out(vty
, "/%s", (char *)mac
);
7087 XFREE(MTYPE_TMP
, mac
);
7095 /* dampening route */
7096 static void damp_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7097 struct bgp_info
*binfo
, int display
, safi_t safi
,
7098 bool use_json
, json_object
*json
)
7102 char timebuf
[BGP_UPTIME_LEN
];
7104 /* short status lead text */
7105 route_vty_short_status_out(vty
, binfo
, json
);
7107 /* print prefix and mask */
7110 route_vty_out_route(p
, vty
, NULL
);
7112 vty_out(vty
, "%*s", 17, " ");
7115 len
= vty_out(vty
, "%s", binfo
->peer
->host
);
7119 vty_out(vty
, "\n%*s", 34, " ");
7122 json_object_int_add(json
, "peerHost", len
);
7124 vty_out(vty
, "%*s", len
, " ");
7128 bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
, BGP_UPTIME_LEN
,
7131 vty_out(vty
, "%s ", bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
,
7135 /* Print attribute */
7141 json_object_string_add(json
, "asPath",
7144 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7149 json_object_string_add(json
, "origin",
7150 bgp_origin_str
[attr
->origin
]);
7152 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7159 static void flap_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7160 struct bgp_info
*binfo
, int display
, safi_t safi
,
7161 bool use_json
, json_object
*json
)
7164 struct bgp_damp_info
*bdi
;
7165 char timebuf
[BGP_UPTIME_LEN
];
7171 bdi
= binfo
->extra
->damp_info
;
7173 /* short status lead text */
7174 route_vty_short_status_out(vty
, binfo
, json
);
7176 /* print prefix and mask */
7179 route_vty_out_route(p
, vty
, NULL
);
7181 vty_out(vty
, "%*s", 17, " ");
7184 len
= vty_out(vty
, "%s", binfo
->peer
->host
);
7188 vty_out(vty
, "\n%*s", 33, " ");
7191 json_object_int_add(json
, "peerHost", len
);
7193 vty_out(vty
, "%*s", len
, " ");
7196 len
= vty_out(vty
, "%d", bdi
->flap
);
7203 json_object_int_add(json
, "bdiFlap", len
);
7205 vty_out(vty
, "%*s", len
, " ");
7209 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
7212 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
7213 BGP_UPTIME_LEN
, 0, NULL
));
7215 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
)
7216 && !CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
)) {
7218 bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
,
7219 BGP_UPTIME_LEN
, use_json
, json
);
7222 bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
,
7227 vty_out(vty
, "%*s ", 8, " ");
7230 /* Print attribute */
7236 json_object_string_add(json
, "asPath",
7239 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7244 json_object_string_add(json
, "origin",
7245 bgp_origin_str
[attr
->origin
]);
7247 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7253 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
7254 int *first
, const char *header
,
7255 json_object
*json_adv_to
)
7257 char buf1
[INET6_ADDRSTRLEN
];
7258 json_object
*json_peer
= NULL
;
7261 /* 'advertised-to' is a dictionary of peers we have advertised
7263 * prefix too. The key is the peer's IP or swpX, the value is
7265 * hostname if we know it and "" if not.
7267 json_peer
= json_object_new_object();
7270 json_object_string_add(json_peer
, "hostname",
7274 json_object_object_add(json_adv_to
, peer
->conf_if
,
7277 json_object_object_add(
7279 sockunion2str(&peer
->su
, buf1
, SU_ADDRSTRLEN
),
7283 vty_out(vty
, "%s", header
);
7288 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
7290 vty_out(vty
, " %s(%s)", peer
->hostname
,
7293 vty_out(vty
, " %s(%s)", peer
->hostname
,
7294 sockunion2str(&peer
->su
, buf1
,
7298 vty_out(vty
, " %s", peer
->conf_if
);
7301 sockunion2str(&peer
->su
, buf1
,
7307 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
, struct prefix
*p
,
7308 struct bgp_info
*binfo
, afi_t afi
, safi_t safi
,
7309 json_object
*json_paths
)
7311 char buf
[INET6_ADDRSTRLEN
];
7313 char buf2
[EVPN_ROUTE_STRLEN
];
7315 int sockunion_vty_out(struct vty
*, union sockunion
*);
7317 json_object
*json_bestpath
= NULL
;
7318 json_object
*json_cluster_list
= NULL
;
7319 json_object
*json_cluster_list_list
= NULL
;
7320 json_object
*json_ext_community
= NULL
;
7321 json_object
*json_last_update
= NULL
;
7322 json_object
*json_pmsi
= NULL
;
7323 json_object
*json_nexthop_global
= NULL
;
7324 json_object
*json_nexthop_ll
= NULL
;
7325 json_object
*json_nexthops
= NULL
;
7326 json_object
*json_path
= NULL
;
7327 json_object
*json_peer
= NULL
;
7328 json_object
*json_string
= NULL
;
7329 json_object
*json_adv_to
= NULL
;
7331 struct listnode
*node
, *nnode
;
7333 int addpath_capable
;
7335 unsigned int first_as
;
7336 bool nexthop_self
= CHECK_FLAG(binfo
->flags
, BGP_INFO_ANNC_NH_SELF
)
7341 json_path
= json_object_new_object();
7342 json_peer
= json_object_new_object();
7343 json_nexthop_global
= json_object_new_object();
7346 if (!json_paths
&& safi
== SAFI_EVPN
) {
7349 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf2
, sizeof(buf2
));
7350 vty_out(vty
, " Route %s", buf2
);
7352 if (binfo
->extra
&& binfo
->extra
->num_labels
) {
7353 bgp_evpn_label2str(binfo
->extra
->label
,
7354 binfo
->extra
->num_labels
, tag_buf
,
7356 vty_out(vty
, " VNI %s", tag_buf
);
7359 if (binfo
->extra
&& binfo
->extra
->parent
) {
7360 struct bgp_info
*parent_ri
;
7361 struct bgp_node
*rn
, *prn
;
7363 parent_ri
= (struct bgp_info
*)binfo
->extra
->parent
;
7364 rn
= parent_ri
->net
;
7365 if (rn
&& rn
->prn
) {
7367 vty_out(vty
, " Imported from %s:%s\n",
7369 (struct prefix_rd
*)&prn
->p
,
7370 buf1
, sizeof(buf1
)),
7379 /* Line1 display AS-path, Aggregator */
7382 if (!attr
->aspath
->json
)
7383 aspath_str_update(attr
->aspath
, true);
7384 json_object_lock(attr
->aspath
->json
);
7385 json_object_object_add(json_path
, "aspath",
7386 attr
->aspath
->json
);
7388 if (attr
->aspath
->segments
)
7389 aspath_print_vty(vty
, " %s",
7392 vty_out(vty
, " Local");
7396 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_REMOVED
)) {
7398 json_object_boolean_true_add(json_path
,
7401 vty_out(vty
, ", (removed)");
7404 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_STALE
)) {
7406 json_object_boolean_true_add(json_path
,
7409 vty_out(vty
, ", (stale)");
7412 if (CHECK_FLAG(attr
->flag
,
7413 ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
7415 json_object_int_add(json_path
, "aggregatorAs",
7416 attr
->aggregator_as
);
7417 json_object_string_add(
7418 json_path
, "aggregatorId",
7419 inet_ntoa(attr
->aggregator_addr
));
7421 vty_out(vty
, ", (aggregated by %u %s)",
7422 attr
->aggregator_as
,
7423 inet_ntoa(attr
->aggregator_addr
));
7427 if (CHECK_FLAG(binfo
->peer
->af_flags
[afi
][safi
],
7428 PEER_FLAG_REFLECTOR_CLIENT
)) {
7430 json_object_boolean_true_add(
7431 json_path
, "rxedFromRrClient");
7433 vty_out(vty
, ", (Received from a RR-client)");
7436 if (CHECK_FLAG(binfo
->peer
->af_flags
[afi
][safi
],
7437 PEER_FLAG_RSERVER_CLIENT
)) {
7439 json_object_boolean_true_add(
7440 json_path
, "rxedFromRsClient");
7442 vty_out(vty
, ", (Received from a RS-client)");
7445 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
)) {
7447 json_object_boolean_true_add(
7448 json_path
, "dampeningHistoryEntry");
7450 vty_out(vty
, ", (history entry)");
7451 } else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
)) {
7453 json_object_boolean_true_add(
7454 json_path
, "dampeningSuppressed");
7456 vty_out(vty
, ", (suppressed due to dampening)");
7462 /* Line2 display Next-hop, Neighbor, Router-id */
7463 /* Display the nexthop */
7464 if ((p
->family
== AF_INET
|| p
->family
== AF_ETHERNET
7465 || p
->family
== AF_EVPN
)
7466 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7467 || safi
== SAFI_EVPN
7468 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7469 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7470 || safi
== SAFI_EVPN
) {
7472 json_object_string_add(
7473 json_nexthop_global
, "ip",
7475 attr
->mp_nexthop_global_in
));
7479 attr
->mp_nexthop_global_in
));
7482 json_object_string_add(
7483 json_nexthop_global
, "ip",
7484 inet_ntoa(attr
->nexthop
));
7487 inet_ntoa(attr
->nexthop
));
7491 json_object_string_add(json_nexthop_global
,
7495 json_object_string_add(
7496 json_nexthop_global
, "ip",
7498 &attr
->mp_nexthop_global
, buf
,
7500 json_object_string_add(json_nexthop_global
,
7502 json_object_string_add(json_nexthop_global
,
7507 &attr
->mp_nexthop_global
, buf
,
7512 /* Display the IGP cost or 'inaccessible' */
7513 if (!CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)) {
7515 json_object_boolean_false_add(
7516 json_nexthop_global
, "accessible");
7518 vty_out(vty
, " (inaccessible)");
7520 if (binfo
->extra
&& binfo
->extra
->igpmetric
) {
7522 json_object_int_add(
7523 json_nexthop_global
, "metric",
7524 binfo
->extra
->igpmetric
);
7526 vty_out(vty
, " (metric %u)",
7527 binfo
->extra
->igpmetric
);
7530 /* IGP cost is 0, display this only for json */
7533 json_object_int_add(json_nexthop_global
,
7538 json_object_boolean_true_add(
7539 json_nexthop_global
, "accessible");
7542 /* Display peer "from" output */
7543 /* This path was originated locally */
7544 if (binfo
->peer
== bgp
->peer_self
) {
7546 if (safi
== SAFI_EVPN
7547 || (p
->family
== AF_INET
7548 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7550 json_object_string_add(
7551 json_peer
, "peerId", "0.0.0.0");
7553 vty_out(vty
, " from 0.0.0.0 ");
7556 json_object_string_add(json_peer
,
7559 vty_out(vty
, " from :: ");
7563 json_object_string_add(
7564 json_peer
, "routerId",
7565 inet_ntoa(bgp
->router_id
));
7567 vty_out(vty
, "(%s)", inet_ntoa(bgp
->router_id
));
7570 /* We RXed this path from one of our peers */
7574 json_object_string_add(
7575 json_peer
, "peerId",
7576 sockunion2str(&binfo
->peer
->su
, buf
,
7578 json_object_string_add(
7579 json_peer
, "routerId",
7581 &binfo
->peer
->remote_id
, buf1
,
7584 if (binfo
->peer
->hostname
)
7585 json_object_string_add(
7586 json_peer
, "hostname",
7587 binfo
->peer
->hostname
);
7589 if (binfo
->peer
->domainname
)
7590 json_object_string_add(
7591 json_peer
, "domainname",
7592 binfo
->peer
->domainname
);
7594 if (binfo
->peer
->conf_if
)
7595 json_object_string_add(
7596 json_peer
, "interface",
7597 binfo
->peer
->conf_if
);
7599 if (binfo
->peer
->conf_if
) {
7600 if (binfo
->peer
->hostname
7603 BGP_FLAG_SHOW_HOSTNAME
))
7604 vty_out(vty
, " from %s(%s)",
7605 binfo
->peer
->hostname
,
7606 binfo
->peer
->conf_if
);
7608 vty_out(vty
, " from %s",
7609 binfo
->peer
->conf_if
);
7611 if (binfo
->peer
->hostname
7614 BGP_FLAG_SHOW_HOSTNAME
))
7615 vty_out(vty
, " from %s(%s)",
7616 binfo
->peer
->hostname
,
7619 vty_out(vty
, " from %s",
7628 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
7629 vty_out(vty
, " (%s)",
7630 inet_ntoa(attr
->originator_id
));
7632 vty_out(vty
, " (%s)",
7635 &binfo
->peer
->remote_id
,
7636 buf1
, sizeof(buf1
)));
7641 * Note when vrfid of nexthop is different from that of prefix
7643 if (binfo
->extra
&& binfo
->extra
->bgp_orig
) {
7644 vrf_id_t nexthop_vrfid
= binfo
->extra
->bgp_orig
->vrf_id
;
7649 if (binfo
->extra
->bgp_orig
->inst_type
==
7650 BGP_INSTANCE_TYPE_DEFAULT
)
7654 vn
= binfo
->extra
->bgp_orig
->name
;
7656 json_object_string_add(json_path
, "nhVrfName",
7659 if (nexthop_vrfid
== VRF_UNKNOWN
) {
7660 json_object_int_add(json_path
,
7663 json_object_int_add(json_path
,
7664 "nhVrfId", (int)nexthop_vrfid
);
7667 if (nexthop_vrfid
== VRF_UNKNOWN
)
7668 vty_out(vty
, " vrf ?");
7670 vty_out(vty
, " vrf %u", nexthop_vrfid
);
7676 json_object_boolean_true_add(json_path
,
7677 "announceNexthopSelf");
7679 vty_out(vty
, " announce-nh-self");
7686 /* display the link-local nexthop */
7687 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
7689 json_nexthop_ll
= json_object_new_object();
7690 json_object_string_add(
7691 json_nexthop_ll
, "ip",
7693 &attr
->mp_nexthop_local
, buf
,
7695 json_object_string_add(json_nexthop_ll
, "afi",
7697 json_object_string_add(json_nexthop_ll
, "scope",
7700 json_object_boolean_true_add(json_nexthop_ll
,
7703 if (!attr
->mp_nexthop_prefer_global
)
7704 json_object_boolean_true_add(
7705 json_nexthop_ll
, "used");
7707 json_object_boolean_true_add(
7708 json_nexthop_global
, "used");
7710 vty_out(vty
, " (%s) %s\n",
7712 &attr
->mp_nexthop_local
, buf
,
7714 attr
->mp_nexthop_prefer_global
7719 /* If we do not have a link-local nexthop then we must flag the
7723 json_object_boolean_true_add(
7724 json_nexthop_global
, "used");
7727 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
7728 * Int/Ext/Local, Atomic, best */
7730 json_object_string_add(
7731 json_path
, "origin",
7732 bgp_origin_long_str
[attr
->origin
]);
7734 vty_out(vty
, " Origin %s",
7735 bgp_origin_long_str
[attr
->origin
]);
7737 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
7739 json_object_int_add(json_path
, "med",
7742 vty_out(vty
, ", metric %u", attr
->med
);
7745 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
7747 json_object_int_add(json_path
, "localpref",
7750 vty_out(vty
, ", localpref %u",
7754 if (attr
->weight
!= 0) {
7756 json_object_int_add(json_path
, "weight",
7759 vty_out(vty
, ", weight %u", attr
->weight
);
7762 if (attr
->tag
!= 0) {
7764 json_object_int_add(json_path
, "tag",
7767 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
,
7771 if (!CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)) {
7773 json_object_boolean_false_add(json_path
,
7776 vty_out(vty
, ", invalid");
7777 } else if (!CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
)) {
7779 json_object_boolean_true_add(json_path
,
7782 vty_out(vty
, ", valid");
7785 if (binfo
->peer
!= bgp
->peer_self
) {
7786 if (binfo
->peer
->as
== binfo
->peer
->local_as
) {
7787 if (CHECK_FLAG(bgp
->config
,
7788 BGP_CONFIG_CONFEDERATION
)) {
7790 json_object_string_add(
7795 ", confed-internal");
7798 json_object_string_add(
7802 vty_out(vty
, ", internal");
7805 if (bgp_confederation_peers_check(
7806 bgp
, binfo
->peer
->as
)) {
7808 json_object_string_add(
7813 ", confed-external");
7816 json_object_string_add(
7820 vty_out(vty
, ", external");
7823 } else if (binfo
->sub_type
== BGP_ROUTE_AGGREGATE
) {
7825 json_object_boolean_true_add(json_path
,
7827 json_object_boolean_true_add(json_path
,
7830 vty_out(vty
, ", aggregated, local");
7832 } else if (binfo
->type
!= ZEBRA_ROUTE_BGP
) {
7834 json_object_boolean_true_add(json_path
,
7837 vty_out(vty
, ", sourced");
7840 json_object_boolean_true_add(json_path
,
7842 json_object_boolean_true_add(json_path
,
7845 vty_out(vty
, ", sourced, local");
7849 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
7851 json_object_boolean_true_add(json_path
,
7854 vty_out(vty
, ", atomic-aggregate");
7857 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_MULTIPATH
)
7858 || (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
)
7859 && bgp_info_mpath_count(binfo
))) {
7861 json_object_boolean_true_add(json_path
,
7864 vty_out(vty
, ", multipath");
7867 // Mark the bestpath(s)
7868 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DMED_SELECTED
)) {
7869 first_as
= aspath_get_first_as(attr
->aspath
);
7874 json_object_new_object();
7875 json_object_int_add(json_bestpath
,
7876 "bestpathFromAs", first_as
);
7879 vty_out(vty
, ", bestpath-from-AS %u",
7883 ", bestpath-from-AS Local");
7887 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
)) {
7891 json_object_new_object();
7892 json_object_boolean_true_add(json_bestpath
,
7895 vty_out(vty
, ", best");
7899 json_object_object_add(json_path
, "bestpath",
7905 /* Line 4 display Community */
7906 if (attr
->community
) {
7908 if (!attr
->community
->json
)
7909 community_str(attr
->community
, true);
7910 json_object_lock(attr
->community
->json
);
7911 json_object_object_add(json_path
, "community",
7912 attr
->community
->json
);
7914 vty_out(vty
, " Community: %s\n",
7915 attr
->community
->str
);
7919 /* Line 5 display Extended-community */
7920 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
7922 json_ext_community
= json_object_new_object();
7923 json_object_string_add(json_ext_community
,
7925 attr
->ecommunity
->str
);
7926 json_object_object_add(json_path
,
7927 "extendedCommunity",
7928 json_ext_community
);
7930 vty_out(vty
, " Extended Community: %s\n",
7931 attr
->ecommunity
->str
);
7935 /* Line 6 display Large community */
7936 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
7938 if (!attr
->lcommunity
->json
)
7939 lcommunity_str(attr
->lcommunity
, true);
7940 json_object_lock(attr
->lcommunity
->json
);
7941 json_object_object_add(json_path
,
7943 attr
->lcommunity
->json
);
7945 vty_out(vty
, " Large Community: %s\n",
7946 attr
->lcommunity
->str
);
7950 /* Line 7 display Originator, Cluster-id */
7951 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
7952 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
7954 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
7956 json_object_string_add(
7957 json_path
, "originatorId",
7958 inet_ntoa(attr
->originator_id
));
7960 vty_out(vty
, " Originator: %s",
7961 inet_ntoa(attr
->originator_id
));
7964 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
7969 json_object_new_object();
7970 json_cluster_list_list
=
7971 json_object_new_array();
7974 i
< attr
->cluster
->length
/ 4;
7976 json_string
= json_object_new_string(
7980 json_object_array_add(
7981 json_cluster_list_list
,
7985 /* struct cluster_list does not have
7987 * aspath and community do. Add this
7990 json_object_string_add(json_cluster_list,
7991 "string", attr->cluster->str);
7993 json_object_object_add(
7994 json_cluster_list
, "list",
7995 json_cluster_list_list
);
7996 json_object_object_add(
7997 json_path
, "clusterList",
8000 vty_out(vty
, ", Cluster list: ");
8003 i
< attr
->cluster
->length
/ 4;
8017 if (binfo
->extra
&& binfo
->extra
->damp_info
)
8018 bgp_damp_info_vty(vty
, binfo
, json_path
);
8021 if (binfo
->extra
&& bgp_is_valid_label(&binfo
->extra
->label
[0])
8022 && safi
!= SAFI_EVPN
) {
8023 mpls_label_t label
=
8024 label_pton(&binfo
->extra
->label
[0]);
8026 json_object_int_add(json_path
, "remoteLabel",
8029 vty_out(vty
, " Remote label: %d\n", label
);
8033 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
8035 json_object_int_add(json_path
, "labelIndex",
8038 vty_out(vty
, " Label Index: %d\n",
8042 /* Line 8 display Addpath IDs */
8043 if (binfo
->addpath_rx_id
|| binfo
->addpath_tx_id
) {
8045 json_object_int_add(json_path
, "addpathRxId",
8046 binfo
->addpath_rx_id
);
8047 json_object_int_add(json_path
, "addpathTxId",
8048 binfo
->addpath_tx_id
);
8050 vty_out(vty
, " AddPath ID: RX %u, TX %u\n",
8051 binfo
->addpath_rx_id
,
8052 binfo
->addpath_tx_id
);
8056 /* If we used addpath to TX a non-bestpath we need to display
8057 * "Advertised to" on a path-by-path basis */
8058 if (bgp
->addpath_tx_used
[afi
][safi
]) {
8061 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
8063 bgp_addpath_encode_tx(peer
, afi
, safi
);
8064 has_adj
= bgp_adj_out_lookup(
8065 peer
, binfo
->net
, binfo
->addpath_tx_id
);
8067 if ((addpath_capable
&& has_adj
)
8068 || (!addpath_capable
&& has_adj
8069 && CHECK_FLAG(binfo
->flags
,
8070 BGP_INFO_SELECTED
))) {
8071 if (json_path
&& !json_adv_to
)
8073 json_object_new_object();
8075 route_vty_out_advertised_to(
8084 json_object_object_add(json_path
,
8095 /* Line 9 display Uptime */
8096 tbuf
= time(NULL
) - (bgp_clock() - binfo
->uptime
);
8098 json_last_update
= json_object_new_object();
8099 json_object_int_add(json_last_update
, "epoch", tbuf
);
8100 json_object_string_add(json_last_update
, "string",
8102 json_object_object_add(json_path
, "lastUpdate",
8105 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
8107 /* Line 10 display PMSI tunnel attribute, if present */
8108 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
8109 const char *str
= lookup_msg(bgp_pmsi_tnltype_str
,
8110 attr
->pmsi_tnl_type
,
8111 PMSI_TNLTYPE_STR_DEFAULT
);
8114 json_pmsi
= json_object_new_object();
8115 json_object_string_add(json_pmsi
,
8117 json_object_object_add(json_path
, "pmsi",
8120 vty_out(vty
, " PMSI Tunnel Type: %s\n",
8126 /* We've constructed the json object for this path, add it to the json
8130 if (json_nexthop_global
|| json_nexthop_ll
) {
8131 json_nexthops
= json_object_new_array();
8133 if (json_nexthop_global
)
8134 json_object_array_add(json_nexthops
,
8135 json_nexthop_global
);
8137 if (json_nexthop_ll
)
8138 json_object_array_add(json_nexthops
,
8141 json_object_object_add(json_path
, "nexthops",
8145 json_object_object_add(json_path
, "peer", json_peer
);
8146 json_object_array_add(json_paths
, json_path
);
8151 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
8152 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
8153 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
8155 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
8156 const char *prefix_list_str
, afi_t afi
,
8157 safi_t safi
, enum bgp_show_type type
);
8158 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
8159 const char *filter
, afi_t afi
, safi_t safi
,
8160 enum bgp_show_type type
);
8161 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
8162 const char *rmap_str
, afi_t afi
, safi_t safi
,
8163 enum bgp_show_type type
);
8164 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
8165 const char *com
, int exact
, afi_t afi
,
8167 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
8168 const char *prefix
, afi_t afi
, safi_t safi
,
8169 enum bgp_show_type type
);
8170 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
8171 afi_t afi
, safi_t safi
, enum bgp_show_type type
);
8172 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
8173 const char *comstr
, int exact
, afi_t afi
,
8174 safi_t safi
, bool use_json
);
8177 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
8178 struct bgp_table
*table
, enum bgp_show_type type
,
8179 void *output_arg
, bool use_json
, char *rd
,
8180 int is_last
, unsigned long *output_cum
,
8181 unsigned long *total_cum
,
8182 unsigned long *json_header_depth
)
8184 struct bgp_info
*ri
;
8185 struct bgp_node
*rn
;
8188 unsigned long output_count
= 0;
8189 unsigned long total_count
= 0;
8193 json_object
*json_paths
= NULL
;
8196 if (output_cum
&& *output_cum
!= 0)
8199 if (use_json
&& !*json_header_depth
) {
8201 "{\n \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
8202 ",\n \"routerId\": \"%s\",\n \"routes\": { ",
8203 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
8204 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
? "Default"
8206 table
->version
, inet_ntoa(bgp
->router_id
));
8207 *json_header_depth
= 2;
8209 vty_out(vty
, " \"routeDistinguishers\" : {");
8210 ++*json_header_depth
;
8214 if (use_json
&& rd
) {
8215 vty_out(vty
, " \"%s\" : { ", rd
);
8218 /* Start processing of routes. */
8219 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
8220 if (rn
->info
== NULL
)
8225 json_paths
= json_object_new_array();
8229 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
8231 if (type
== bgp_show_type_flap_statistics
8232 || type
== bgp_show_type_flap_neighbor
8233 || type
== bgp_show_type_dampend_paths
8234 || type
== bgp_show_type_damp_neighbor
) {
8235 if (!(ri
->extra
&& ri
->extra
->damp_info
))
8238 if (type
== bgp_show_type_regexp
) {
8239 regex_t
*regex
= output_arg
;
8241 if (bgp_regexec(regex
, ri
->attr
->aspath
)
8245 if (type
== bgp_show_type_prefix_list
) {
8246 struct prefix_list
*plist
= output_arg
;
8248 if (prefix_list_apply(plist
, &rn
->p
)
8252 if (type
== bgp_show_type_filter_list
) {
8253 struct as_list
*as_list
= output_arg
;
8255 if (as_list_apply(as_list
, ri
->attr
->aspath
)
8256 != AS_FILTER_PERMIT
)
8259 if (type
== bgp_show_type_route_map
) {
8260 struct route_map
*rmap
= output_arg
;
8261 struct bgp_info binfo
;
8262 struct attr dummy_attr
;
8265 bgp_attr_dup(&dummy_attr
, ri
->attr
);
8267 binfo
.peer
= ri
->peer
;
8268 binfo
.attr
= &dummy_attr
;
8270 ret
= route_map_apply(rmap
, &rn
->p
, RMAP_BGP
,
8272 if (ret
== RMAP_DENYMATCH
)
8275 if (type
== bgp_show_type_neighbor
8276 || type
== bgp_show_type_flap_neighbor
8277 || type
== bgp_show_type_damp_neighbor
) {
8278 union sockunion
*su
= output_arg
;
8280 if (ri
->peer
== NULL
8281 || ri
->peer
->su_remote
== NULL
8282 || !sockunion_same(ri
->peer
->su_remote
, su
))
8285 if (type
== bgp_show_type_cidr_only
) {
8286 uint32_t destination
;
8288 destination
= ntohl(rn
->p
.u
.prefix4
.s_addr
);
8289 if (IN_CLASSC(destination
)
8290 && rn
->p
.prefixlen
== 24)
8292 if (IN_CLASSB(destination
)
8293 && rn
->p
.prefixlen
== 16)
8295 if (IN_CLASSA(destination
)
8296 && rn
->p
.prefixlen
== 8)
8299 if (type
== bgp_show_type_prefix_longer
) {
8301 if (!prefix_match(p
, &rn
->p
))
8304 if (type
== bgp_show_type_community_all
) {
8305 if (!ri
->attr
->community
)
8308 if (type
== bgp_show_type_community
) {
8309 struct community
*com
= output_arg
;
8311 if (!ri
->attr
->community
8312 || !community_match(ri
->attr
->community
,
8316 if (type
== bgp_show_type_community_exact
) {
8317 struct community
*com
= output_arg
;
8319 if (!ri
->attr
->community
8320 || !community_cmp(ri
->attr
->community
, com
))
8323 if (type
== bgp_show_type_community_list
) {
8324 struct community_list
*list
= output_arg
;
8326 if (!community_list_match(ri
->attr
->community
,
8330 if (type
== bgp_show_type_community_list_exact
) {
8331 struct community_list
*list
= output_arg
;
8333 if (!community_list_exact_match(
8334 ri
->attr
->community
, list
))
8337 if (type
== bgp_show_type_lcommunity
) {
8338 struct lcommunity
*lcom
= output_arg
;
8340 if (!ri
->attr
->lcommunity
8341 || !lcommunity_match(ri
->attr
->lcommunity
,
8345 if (type
== bgp_show_type_lcommunity_list
) {
8346 struct community_list
*list
= output_arg
;
8348 if (!lcommunity_list_match(ri
->attr
->lcommunity
,
8352 if (type
== bgp_show_type_lcommunity_all
) {
8353 if (!ri
->attr
->lcommunity
)
8356 if (type
== bgp_show_type_dampend_paths
8357 || type
== bgp_show_type_damp_neighbor
) {
8358 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_DAMPED
)
8359 || CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
8363 if (!use_json
&& header
) {
8364 vty_out(vty
, "BGP table version is %" PRIu64
8365 ", local router ID is %s, vrf id ",
8367 inet_ntoa(bgp
->router_id
));
8368 if (bgp
->vrf_id
== VRF_UNKNOWN
)
8369 vty_out(vty
, "%s", VRFID_NONE_STR
);
8371 vty_out(vty
, "%u", bgp
->vrf_id
);
8373 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
8374 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
8375 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
8376 if (type
== bgp_show_type_dampend_paths
8377 || type
== bgp_show_type_damp_neighbor
)
8378 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
8379 else if (type
== bgp_show_type_flap_statistics
8380 || type
== bgp_show_type_flap_neighbor
)
8381 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
8383 vty_out(vty
, BGP_SHOW_HEADER
);
8386 if (rd
!= NULL
&& !display
&& !output_count
) {
8389 "Route Distinguisher: %s\n",
8392 if (type
== bgp_show_type_dampend_paths
8393 || type
== bgp_show_type_damp_neighbor
)
8394 damp_route_vty_out(vty
, &rn
->p
, ri
, display
,
8395 safi
, use_json
, json_paths
);
8396 else if (type
== bgp_show_type_flap_statistics
8397 || type
== bgp_show_type_flap_neighbor
)
8398 flap_route_vty_out(vty
, &rn
->p
, ri
, display
,
8399 safi
, use_json
, json_paths
);
8401 route_vty_out(vty
, &rn
->p
, ri
, display
, safi
,
8412 sprintf(buf2
, "%s/%d",
8413 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
8416 vty_out(vty
, "\"%s\": ", buf2
);
8418 vty_out(vty
, ",\"%s\": ", buf2
);
8421 json_object_to_json_string(json_paths
));
8422 json_object_free(json_paths
);
8429 output_count
+= *output_cum
;
8430 *output_cum
= output_count
;
8433 total_count
+= *total_cum
;
8434 *total_cum
= total_count
;
8438 vty_out(vty
, " }%s ", (is_last
? "" : ","));
8442 for (i
= 0; i
< *json_header_depth
; ++i
)
8443 vty_out(vty
, " } ");
8447 /* No route is displayed */
8448 if (output_count
== 0) {
8449 if (type
== bgp_show_type_normal
)
8451 "No BGP prefixes displayed, %ld exist\n",
8455 "\nDisplayed %ld routes and %ld total paths\n",
8456 output_count
, total_count
);
8463 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
8464 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
8465 enum bgp_show_type type
, void *output_arg
, bool use_json
)
8467 struct bgp_node
*rn
, *next
;
8468 unsigned long output_cum
= 0;
8469 unsigned long total_cum
= 0;
8470 unsigned long json_header_depth
= 0;
8473 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
8475 for (rn
= bgp_table_top(table
); rn
; rn
= next
) {
8476 next
= bgp_route_next(rn
);
8477 if (prd_match
&& memcmp(rn
->p
.u
.val
, prd_match
->val
, 8) != 0)
8479 if (rn
->info
!= NULL
) {
8480 struct prefix_rd prd
;
8481 char rd
[RD_ADDRSTRLEN
];
8483 memcpy(&prd
, &(rn
->p
), sizeof(struct prefix_rd
));
8484 prefix_rd2str(&prd
, rd
, sizeof(rd
));
8485 bgp_show_table(vty
, bgp
, safi
, rn
->info
, type
,
8486 output_arg
, use_json
, rd
, next
== NULL
,
8487 &output_cum
, &total_cum
,
8488 &json_header_depth
);
8494 if (output_cum
== 0)
8495 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
8499 "\nDisplayed %ld routes and %ld total paths\n",
8500 output_cum
, total_cum
);
8504 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
8505 enum bgp_show_type type
, void *output_arg
, bool use_json
)
8507 struct bgp_table
*table
;
8508 unsigned long json_header_depth
= 0;
8511 bgp
= bgp_get_default();
8516 vty_out(vty
, "No BGP process is configured\n");
8518 vty_out(vty
, "{}\n");
8522 table
= bgp
->rib
[afi
][safi
];
8523 /* use MPLS and ENCAP specific shows until they are merged */
8524 if (safi
== SAFI_MPLS_VPN
) {
8525 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
8526 output_arg
, use_json
);
8529 if (safi
== SAFI_FLOWSPEC
&& type
== bgp_show_type_detail
) {
8530 return bgp_show_table_flowspec(vty
, bgp
, afi
, table
, type
,
8531 output_arg
, use_json
,
8534 /* labeled-unicast routes live in the unicast table */
8535 else if (safi
== SAFI_LABELED_UNICAST
)
8536 safi
= SAFI_UNICAST
;
8538 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, use_json
,
8539 NULL
, 1, NULL
, NULL
, &json_header_depth
);
8542 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
8543 safi_t safi
, bool use_json
)
8545 struct listnode
*node
, *nnode
;
8548 bool route_output
= false;
8551 vty_out(vty
, "{\n");
8553 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
8554 route_output
= true;
8557 vty_out(vty
, ",\n");
8561 vty_out(vty
, "\"%s\":",
8562 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
8566 vty_out(vty
, "\nInstance %s:\n",
8567 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
8571 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
8576 vty_out(vty
, "}\n");
8577 else if (!route_output
)
8578 vty_out(vty
, "%% BGP instance not found\n");
8581 /* Header of detailed BGP route information */
8582 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
8583 struct bgp_node
*rn
, struct prefix_rd
*prd
,
8584 afi_t afi
, safi_t safi
, json_object
*json
)
8586 struct bgp_info
*ri
;
8589 struct listnode
*node
, *nnode
;
8590 char buf1
[RD_ADDRSTRLEN
];
8591 char buf2
[INET6_ADDRSTRLEN
];
8592 char buf3
[EVPN_ROUTE_STRLEN
];
8593 char prefix_str
[BUFSIZ
];
8598 int route_filter_translated_v4
= 0;
8599 int route_filter_v4
= 0;
8600 int route_filter_translated_v6
= 0;
8601 int route_filter_v6
= 0;
8604 int accept_own_nexthop
= 0;
8607 int no_advertise
= 0;
8611 int has_valid_label
= 0;
8612 mpls_label_t label
= 0;
8613 json_object
*json_adv_to
= NULL
;
8616 has_valid_label
= bgp_is_valid_label(&rn
->local_label
);
8618 if (has_valid_label
)
8619 label
= label_pton(&rn
->local_label
);
8622 if (has_valid_label
)
8623 json_object_int_add(json
, "localLabel", label
);
8625 json_object_string_add(
8627 prefix2str(p
, prefix_str
, sizeof(prefix_str
)));
8629 if (safi
== SAFI_EVPN
)
8630 vty_out(vty
, "BGP routing table entry for %s%s%s\n",
8631 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
))
8634 bgp_evpn_route2str((struct prefix_evpn
*)p
,
8635 buf3
, sizeof(buf3
)));
8637 vty_out(vty
, "BGP routing table entry for %s%s%s/%d\n",
8638 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
8639 ? prefix_rd2str(prd
, buf1
,
8642 safi
== SAFI_MPLS_VPN
? ":" : "",
8643 inet_ntop(p
->family
, &p
->u
.prefix
, buf2
,
8647 if (has_valid_label
)
8648 vty_out(vty
, "Local label: %d\n", label
);
8649 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
8650 vty_out(vty
, "not allocated\n");
8653 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
8655 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
8657 if (ri
->extra
&& ri
->extra
->suppress
)
8659 if (ri
->attr
->community
!= NULL
) {
8660 if (community_include(ri
->attr
->community
,
8661 COMMUNITY_NO_ADVERTISE
))
8663 if (community_include(ri
->attr
->community
,
8664 COMMUNITY_NO_EXPORT
))
8666 if (community_include(ri
->attr
->community
,
8667 COMMUNITY_LOCAL_AS
))
8674 vty_out(vty
, "Paths: (%d available", count
);
8676 vty_out(vty
, ", best #%d", best
);
8677 if (safi
== SAFI_UNICAST
)
8678 vty_out(vty
, ", table %s",
8680 == BGP_INSTANCE_TYPE_DEFAULT
)
8681 ? "Default-IP-Routing-Table"
8684 vty_out(vty
, ", no best path");
8688 ", accept own local route exported and imported in different VRF");
8689 else if (route_filter_translated_v4
)
8691 ", mark translated RTs for VPNv4 route filtering");
8692 else if (route_filter_v4
)
8694 ", attach RT as-is for VPNv4 route filtering");
8695 else if (route_filter_translated_v6
)
8697 ", mark translated RTs for VPNv6 route filtering");
8698 else if (route_filter_v6
)
8700 ", attach RT as-is for VPNv6 route filtering");
8701 else if (llgr_stale
)
8703 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
8706 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
8707 else if (accept_own_nexthop
)
8709 ", accept local nexthop");
8711 vty_out(vty
, ", inform peer to blackhole prefix");
8713 vty_out(vty
, ", not advertised to EBGP peer");
8714 else if (no_advertise
)
8715 vty_out(vty
, ", not advertised to any peer");
8717 vty_out(vty
, ", not advertised outside local AS");
8720 ", inform EBGP peer not to advertise to their EBGP peers");
8724 ", Advertisements suppressed by an aggregate.");
8725 vty_out(vty
, ")\n");
8728 /* If we are not using addpath then we can display Advertised to and
8730 * show what peers we advertised the bestpath to. If we are using
8732 * though then we must display Advertised to on a path-by-path basis. */
8733 if (!bgp
->addpath_tx_used
[afi
][safi
]) {
8734 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
8735 if (bgp_adj_out_lookup(peer
, rn
, 0)) {
8736 if (json
&& !json_adv_to
)
8737 json_adv_to
= json_object_new_object();
8739 route_vty_out_advertised_to(
8741 " Advertised to non peer-group peers:\n ",
8748 json_object_object_add(json
, "advertisedTo",
8753 vty_out(vty
, " Not advertised to any peer");
8759 /* Display specified route of BGP table. */
8760 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
8761 struct bgp_table
*rib
, const char *ip_str
,
8762 afi_t afi
, safi_t safi
,
8763 struct prefix_rd
*prd
, int prefix_check
,
8764 enum bgp_path_type pathtype
, bool use_json
)
8769 struct prefix match
;
8770 struct bgp_node
*rn
;
8771 struct bgp_node
*rm
;
8772 struct bgp_info
*ri
;
8773 struct bgp_table
*table
;
8774 json_object
*json
= NULL
;
8775 json_object
*json_paths
= NULL
;
8777 /* Check IP address argument. */
8778 ret
= str2prefix(ip_str
, &match
);
8780 vty_out(vty
, "address is malformed\n");
8784 match
.family
= afi2family(afi
);
8787 json
= json_object_new_object();
8788 json_paths
= json_object_new_array();
8791 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
8792 for (rn
= bgp_table_top(rib
); rn
; rn
= bgp_route_next(rn
)) {
8793 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
8796 if ((table
= rn
->info
) == NULL
)
8801 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
8805 && rm
->p
.prefixlen
!= match
.prefixlen
) {
8806 bgp_unlock_node(rm
);
8810 for (ri
= rm
->info
; ri
; ri
= ri
->next
) {
8812 route_vty_out_detail_header(
8814 (struct prefix_rd
*)&rn
->p
,
8815 AFI_IP
, safi
, json
);
8820 if (pathtype
== BGP_PATH_ALL
8821 || (pathtype
== BGP_PATH_BESTPATH
8822 && CHECK_FLAG(ri
->flags
,
8824 || (pathtype
== BGP_PATH_MULTIPATH
8825 && (CHECK_FLAG(ri
->flags
,
8827 || CHECK_FLAG(ri
->flags
,
8828 BGP_INFO_SELECTED
))))
8829 route_vty_out_detail(vty
, bgp
, &rm
->p
,
8834 bgp_unlock_node(rm
);
8836 } else if (safi
== SAFI_FLOWSPEC
) {
8837 display
= bgp_flowspec_display_match_per_ip(afi
, rib
,
8838 &match
, prefix_check
,
8845 if ((rn
= bgp_node_match(rib
, &match
)) != NULL
) {
8847 || rn
->p
.prefixlen
== match
.prefixlen
) {
8848 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
8850 route_vty_out_detail_header(
8851 vty
, bgp
, rn
, NULL
, afi
,
8857 if (pathtype
== BGP_PATH_ALL
8858 || (pathtype
== BGP_PATH_BESTPATH
8862 || (pathtype
== BGP_PATH_MULTIPATH
8868 BGP_INFO_SELECTED
))))
8869 route_vty_out_detail(
8870 vty
, bgp
, &rn
->p
, ri
,
8871 afi
, safi
, json_paths
);
8875 bgp_unlock_node(rn
);
8881 json_object_object_add(json
, "paths", json_paths
);
8883 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
8884 json
, JSON_C_TO_STRING_PRETTY
));
8885 json_object_free(json
);
8888 vty_out(vty
, "%% Network not in table\n");
8896 /* Display specified route of Main RIB */
8897 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
8898 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
8899 int prefix_check
, enum bgp_path_type pathtype
,
8903 bgp
= bgp_get_default();
8906 vty_out(vty
, "No BGP process is configured\n");
8908 vty_out(vty
, "{}\n");
8913 /* labeled-unicast routes live in the unicast table */
8914 if (safi
== SAFI_LABELED_UNICAST
)
8915 safi
= SAFI_UNICAST
;
8917 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
8918 afi
, safi
, prd
, prefix_check
, pathtype
,
8922 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
8923 struct cmd_token
**argv
, afi_t afi
, safi_t safi
,
8926 struct lcommunity
*lcom
;
8932 b
= buffer_new(1024);
8933 for (i
= 0; i
< argc
; i
++) {
8935 buffer_putc(b
, ' ');
8937 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
8939 buffer_putstr(b
, argv
[i
]->arg
);
8943 buffer_putc(b
, '\0');
8945 str
= buffer_getstr(b
);
8948 lcom
= lcommunity_str2com(str
);
8949 XFREE(MTYPE_TMP
, str
);
8951 vty_out(vty
, "%% Large-community malformed\n");
8955 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_lcommunity
, lcom
,
8959 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
8960 const char *lcom
, afi_t afi
, safi_t safi
,
8963 struct community_list
*list
;
8965 list
= community_list_lookup(bgp_clist
, lcom
,
8966 LARGE_COMMUNITY_LIST_MASTER
);
8968 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
8973 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_lcommunity_list
,
8977 DEFUN (show_ip_bgp_large_community_list
,
8978 show_ip_bgp_large_community_list_cmd
,
8979 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community-list <(1-500)|WORD> [json]",
8983 BGP_INSTANCE_HELP_STR
8985 BGP_SAFI_WITH_LABEL_HELP_STR
8986 "Display routes matching the large-community-list\n"
8987 "large-community-list number\n"
8988 "large-community-list name\n"
8992 afi_t afi
= AFI_IP6
;
8993 safi_t safi
= SAFI_UNICAST
;
8996 if (argv_find(argv
, argc
, "ip", &idx
))
8998 if (argv_find(argv
, argc
, "view", &idx
)
8999 || argv_find(argv
, argc
, "vrf", &idx
))
9000 vrf
= argv
[++idx
]->arg
;
9001 if (argv_find(argv
, argc
, "ipv4", &idx
)
9002 || argv_find(argv
, argc
, "ipv6", &idx
)) {
9003 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
9004 if (argv_find(argv
, argc
, "unicast", &idx
)
9005 || argv_find(argv
, argc
, "multicast", &idx
))
9006 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
9009 bool uj
= use_json(argc
, argv
);
9011 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
9013 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
9017 argv_find(argv
, argc
, "large-community-list", &idx
);
9018 return bgp_show_lcommunity_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
, safi
,
9021 DEFUN (show_ip_bgp_large_community
,
9022 show_ip_bgp_large_community_cmd
,
9023 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [AA:BB:CC] [json]",
9027 BGP_INSTANCE_HELP_STR
9029 BGP_SAFI_WITH_LABEL_HELP_STR
9030 "Display routes matching the large-communities\n"
9031 "List of large-community numbers\n"
9035 afi_t afi
= AFI_IP6
;
9036 safi_t safi
= SAFI_UNICAST
;
9039 if (argv_find(argv
, argc
, "ip", &idx
))
9041 if (argv_find(argv
, argc
, "view", &idx
)
9042 || argv_find(argv
, argc
, "vrf", &idx
))
9043 vrf
= argv
[++idx
]->arg
;
9044 if (argv_find(argv
, argc
, "ipv4", &idx
)
9045 || argv_find(argv
, argc
, "ipv6", &idx
)) {
9046 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
9047 if (argv_find(argv
, argc
, "unicast", &idx
)
9048 || argv_find(argv
, argc
, "multicast", &idx
))
9049 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
9052 bool uj
= use_json(argc
, argv
);
9054 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
9056 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
9060 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
))
9061 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
, afi
, safi
, uj
);
9063 return bgp_show(vty
, bgp
, afi
, safi
,
9064 bgp_show_type_lcommunity_all
, NULL
, uj
);
9067 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
9071 /* BGP route print out function without JSON */
9074 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
9075 <dampening <parameters>\
9080 |community <AA:NN|local-AS|no-advertise|no-export|graceful-shutdown\
9081 no-peer|blackhole|llgr-stale|no-llgr|accept-own|accept-own-nexthop\
9082 route-filter-v6|route-filter-v4|route-filter-translated-v6|\
9083 route-filter-translated-v4> [exact-match]\
9084 |community-list <(1-500)|WORD> [exact-match]\
9085 |A.B.C.D/M longer-prefixes\
9086 |X:X::X:X/M longer-prefixes\
9091 BGP_INSTANCE_HELP_STR
9093 BGP_SAFI_WITH_LABEL_HELP_STR
9094 "Display detailed information about dampening\n"
9095 "Display detail of configured dampening parameters\n"
9096 "Display routes matching the route-map\n"
9097 "A route-map to match on\n"
9098 "Display routes conforming to the prefix-list\n"
9099 "Prefix-list name\n"
9100 "Display routes conforming to the filter-list\n"
9101 "Regular expression access list name\n"
9102 "BGP RIB advertisement statistics\n"
9103 "Display routes matching the communities\n"
9105 "Do not send outside local AS (well-known community)\n"
9106 "Do not advertise to any peer (well-known community)\n"
9107 "Do not export to next AS (well-known community)\n"
9108 "Graceful shutdown (well-known community)\n"
9109 "Do not export to any peer (well-known community)\n"
9110 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
9111 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
9112 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
9113 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
9114 "Should accept VPN route with local nexthop (well-known community)\n"
9115 "RT VPNv6 route filtering (well-known community)\n"
9116 "RT VPNv4 route filtering (well-known community)\n"
9117 "RT translated VPNv6 route filtering (well-known community)\n"
9118 "RT translated VPNv4 route filtering (well-known community)\n"
9119 "Exact match of the communities\n"
9120 "Display routes matching the community-list\n"
9121 "community-list number\n"
9122 "community-list name\n"
9123 "Exact match of the communities\n"
9125 "Display route and more specific routes\n"
9127 "Display route and more specific routes\n")
9129 afi_t afi
= AFI_IP6
;
9130 safi_t safi
= SAFI_UNICAST
;
9131 int exact_match
= 0;
9132 struct bgp
*bgp
= NULL
;
9135 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9140 if (argv_find(argv
, argc
, "dampening", &idx
)) {
9141 if (argv_find(argv
, argc
, "parameters", &idx
))
9142 return bgp_show_dampening_parameters(vty
, afi
, safi
);
9145 if (argv_find(argv
, argc
, "prefix-list", &idx
))
9146 return bgp_show_prefix_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9147 safi
, bgp_show_type_prefix_list
);
9149 if (argv_find(argv
, argc
, "filter-list", &idx
))
9150 return bgp_show_filter_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9151 safi
, bgp_show_type_filter_list
);
9153 if (argv_find(argv
, argc
, "statistics", &idx
))
9154 return bgp_table_stats(vty
, bgp
, afi
, safi
);
9156 if (argv_find(argv
, argc
, "route-map", &idx
))
9157 return bgp_show_route_map(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9158 safi
, bgp_show_type_route_map
);
9160 if (argv_find(argv
, argc
, "community-list", &idx
)) {
9161 const char *clist_number_or_name
= argv
[++idx
]->arg
;
9162 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
9164 return bgp_show_community_list(vty
, bgp
, clist_number_or_name
,
9165 exact_match
, afi
, safi
);
9168 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
9169 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
9170 return bgp_show_prefix_longer(vty
, bgp
, argv
[idx
]->arg
, afi
,
9172 bgp_show_type_prefix_longer
);
9177 /* BGP route print out function with JSON */
9178 DEFUN (show_ip_bgp_json
,
9179 show_ip_bgp_json_cmd
,
9180 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
9183 |dampening <flap-statistics|dampened-paths>\
9184 |community [<AA:NN|local-AS|no-advertise|no-export|graceful-shutdown>] [exact-match]\
9189 BGP_INSTANCE_HELP_STR
9191 BGP_SAFI_WITH_LABEL_HELP_STR
9192 "Display only routes with non-natural netmasks\n"
9193 "Display detailed information about dampening\n"
9194 "Display flap statistics of routes\n"
9195 "Display paths suppressed due to dampening\n"
9196 "Display routes matching the communities\n"
9198 "Do not send outside local AS (well-known community)\n"
9199 "Do not advertise to any peer (well-known community)\n"
9200 "Do not export to next AS (well-known community)\n"
9201 "Graceful shutdown (well-known community)\n"
9202 "Exact match of the communities\n"
9205 afi_t afi
= AFI_IP6
;
9206 safi_t safi
= SAFI_UNICAST
;
9207 enum bgp_show_type sh_type
= bgp_show_type_normal
;
9208 struct bgp
*bgp
= NULL
;
9210 int idx_community_type
= 0;
9211 int exact_match
= 0;
9212 bool uj
= use_json(argc
, argv
);
9217 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9222 if (argv_find(argv
, argc
, "cidr-only", &idx
))
9223 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_cidr_only
,
9226 if (argv_find(argv
, argc
, "dampening", &idx
)) {
9227 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
9228 return bgp_show(vty
, bgp
, afi
, safi
,
9229 bgp_show_type_dampend_paths
, NULL
, uj
);
9230 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
9231 return bgp_show(vty
, bgp
, afi
, safi
,
9232 bgp_show_type_flap_statistics
, NULL
,
9236 if (argv_find(argv
, argc
, "community", &idx
)) {
9238 /* show a specific community */
9239 if (argv_find(argv
, argc
, "local-AS", &idx_community_type
) ||
9240 argv_find(argv
, argc
, "no-advertise",
9241 &idx_community_type
) ||
9242 argv_find(argv
, argc
, "no-export",
9243 &idx_community_type
) ||
9244 argv_find(argv
, argc
, "graceful-shutdown",
9245 &idx_community_type
) ||
9246 argv_find(argv
, argc
, "AA:NN", &idx_community_type
)) {
9247 if (argv_find(argv
, argc
, "exact-match", &idx
))
9250 return (bgp_show_community(vty
, bgp
,
9251 argv
[idx_community_type
]->arg
,
9252 exact_match
, afi
, safi
, uj
));
9255 /* show all communities */
9256 return (bgp_show(vty
, bgp
, afi
, safi
,
9257 bgp_show_type_community_all
, NULL
,
9262 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
, NULL
, uj
);
9265 DEFUN (show_ip_bgp_route
,
9266 show_ip_bgp_route_cmd
,
9267 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]"
9268 "<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [json]",
9272 BGP_INSTANCE_HELP_STR
9274 BGP_SAFI_WITH_LABEL_HELP_STR
9275 "Network in the BGP routing table to display\n"
9277 "Network in the BGP routing table to display\n"
9279 "Display only the bestpath\n"
9280 "Display only multipaths\n"
9283 int prefix_check
= 0;
9285 afi_t afi
= AFI_IP6
;
9286 safi_t safi
= SAFI_UNICAST
;
9287 char *prefix
= NULL
;
9288 struct bgp
*bgp
= NULL
;
9289 enum bgp_path_type path_type
;
9290 bool uj
= use_json(argc
, argv
);
9294 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9301 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
9305 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
9306 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
9307 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
9309 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
9310 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
9313 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
9314 && afi
!= AFI_IP6
) {
9316 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
9319 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
9322 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
9326 prefix
= argv
[idx
]->arg
;
9328 /* [<bestpath|multipath>] */
9329 if (argv_find(argv
, argc
, "bestpath", &idx
))
9330 path_type
= BGP_PATH_BESTPATH
;
9331 else if (argv_find(argv
, argc
, "multipath", &idx
))
9332 path_type
= BGP_PATH_MULTIPATH
;
9334 path_type
= BGP_PATH_ALL
;
9336 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
9340 DEFUN (show_ip_bgp_regexp
,
9341 show_ip_bgp_regexp_cmd
,
9342 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX...",
9346 BGP_INSTANCE_HELP_STR
9348 BGP_SAFI_WITH_LABEL_HELP_STR
9349 "Display routes matching the AS path regular expression\n"
9350 "A regular-expression to match the BGP AS paths\n")
9352 afi_t afi
= AFI_IP6
;
9353 safi_t safi
= SAFI_UNICAST
;
9354 struct bgp
*bgp
= NULL
;
9357 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9362 // get index of regex
9363 argv_find(argv
, argc
, "regexp", &idx
);
9366 char *regstr
= argv_concat(argv
, argc
, idx
);
9367 int rc
= bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
9368 bgp_show_type_regexp
);
9369 XFREE(MTYPE_TMP
, regstr
);
9373 DEFUN (show_ip_bgp_instance_all
,
9374 show_ip_bgp_instance_all_cmd
,
9375 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json]",
9379 BGP_INSTANCE_ALL_HELP_STR
9381 BGP_SAFI_WITH_LABEL_HELP_STR
9385 safi_t safi
= SAFI_UNICAST
;
9386 struct bgp
*bgp
= NULL
;
9388 bool uj
= use_json(argc
, argv
);
9393 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9398 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, uj
);
9402 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
9403 afi_t afi
, safi_t safi
, enum bgp_show_type type
)
9408 regex
= bgp_regcomp(regstr
);
9410 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
9414 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, 0);
9415 bgp_regex_free(regex
);
9419 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
9420 const char *prefix_list_str
, afi_t afi
,
9421 safi_t safi
, enum bgp_show_type type
)
9423 struct prefix_list
*plist
;
9425 plist
= prefix_list_lookup(afi
, prefix_list_str
);
9426 if (plist
== NULL
) {
9427 vty_out(vty
, "%% %s is not a valid prefix-list name\n",
9432 return bgp_show(vty
, bgp
, afi
, safi
, type
, plist
, 0);
9435 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
9436 const char *filter
, afi_t afi
, safi_t safi
,
9437 enum bgp_show_type type
)
9439 struct as_list
*as_list
;
9441 as_list
= as_list_lookup(filter
);
9442 if (as_list
== NULL
) {
9443 vty_out(vty
, "%% %s is not a valid AS-path access-list name\n",
9448 return bgp_show(vty
, bgp
, afi
, safi
, type
, as_list
, 0);
9451 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
9452 const char *rmap_str
, afi_t afi
, safi_t safi
,
9453 enum bgp_show_type type
)
9455 struct route_map
*rmap
;
9457 rmap
= route_map_lookup_by_name(rmap_str
);
9459 vty_out(vty
, "%% %s is not a valid route-map name\n", rmap_str
);
9463 return bgp_show(vty
, bgp
, afi
, safi
, type
, rmap
, 0);
9466 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
9467 const char *comstr
, int exact
, afi_t afi
,
9468 safi_t safi
, bool use_json
)
9470 struct community
*com
;
9473 com
= community_str2com(comstr
);
9475 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
9479 ret
= bgp_show(vty
, bgp
, afi
, safi
,
9480 (exact
? bgp_show_type_community_exact
9481 : bgp_show_type_community
),
9483 community_free(com
);
9488 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
9489 const char *com
, int exact
, afi_t afi
,
9492 struct community_list
*list
;
9494 list
= community_list_lookup(bgp_clist
, com
, COMMUNITY_LIST_MASTER
);
9496 vty_out(vty
, "%% %s is not a valid community-list name\n", com
);
9500 return bgp_show(vty
, bgp
, afi
, safi
,
9501 (exact
? bgp_show_type_community_list_exact
9502 : bgp_show_type_community_list
),
9506 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
9507 const char *prefix
, afi_t afi
, safi_t safi
,
9508 enum bgp_show_type type
)
9515 ret
= str2prefix(prefix
, p
);
9517 vty_out(vty
, "%% Malformed Prefix\n");
9521 ret
= bgp_show(vty
, bgp
, afi
, safi
, type
, p
, 0);
9526 static struct peer
*peer_lookup_in_view(struct vty
*vty
, struct bgp
*bgp
,
9527 const char *ip_str
, bool use_json
)
9533 /* Get peer sockunion. */
9534 ret
= str2sockunion(ip_str
, &su
);
9536 peer
= peer_lookup_by_conf_if(bgp
, ip_str
);
9538 peer
= peer_lookup_by_hostname(bgp
, ip_str
);
9542 json_object
*json_no
= NULL
;
9543 json_no
= json_object_new_object();
9544 json_object_string_add(
9546 "malformedAddressOrName",
9548 vty_out(vty
, "%s\n",
9549 json_object_to_json_string_ext(
9551 JSON_C_TO_STRING_PRETTY
));
9552 json_object_free(json_no
);
9555 "%% Malformed address or name: %s\n",
9563 /* Peer structure lookup. */
9564 peer
= peer_lookup(bgp
, &su
);
9567 json_object
*json_no
= NULL
;
9568 json_no
= json_object_new_object();
9569 json_object_string_add(json_no
, "warning",
9570 "No such neighbor in this view/vrf");
9571 vty_out(vty
, "%s\n",
9572 json_object_to_json_string_ext(
9573 json_no
, JSON_C_TO_STRING_PRETTY
));
9574 json_object_free(json_no
);
9576 vty_out(vty
, "No such neighbor in this view/vrf\n");
9584 BGP_STATS_MAXBITLEN
= 0,
9588 BGP_STATS_UNAGGREGATEABLE
,
9589 BGP_STATS_MAX_AGGREGATEABLE
,
9590 BGP_STATS_AGGREGATES
,
9592 BGP_STATS_ASPATH_COUNT
,
9593 BGP_STATS_ASPATH_MAXHOPS
,
9594 BGP_STATS_ASPATH_TOTHOPS
,
9595 BGP_STATS_ASPATH_MAXSIZE
,
9596 BGP_STATS_ASPATH_TOTSIZE
,
9597 BGP_STATS_ASN_HIGHEST
,
9601 static const char *table_stats_strs
[] = {
9602 [BGP_STATS_PREFIXES
] = "Total Prefixes",
9603 [BGP_STATS_TOTPLEN
] = "Average prefix length",
9604 [BGP_STATS_RIB
] = "Total Advertisements",
9605 [BGP_STATS_UNAGGREGATEABLE
] = "Unaggregateable prefixes",
9606 [BGP_STATS_MAX_AGGREGATEABLE
] =
9607 "Maximum aggregateable prefixes",
9608 [BGP_STATS_AGGREGATES
] = "BGP Aggregate advertisements",
9609 [BGP_STATS_SPACE
] = "Address space advertised",
9610 [BGP_STATS_ASPATH_COUNT
] = "Advertisements with paths",
9611 [BGP_STATS_ASPATH_MAXHOPS
] = "Longest AS-Path (hops)",
9612 [BGP_STATS_ASPATH_MAXSIZE
] = "Largest AS-Path (bytes)",
9613 [BGP_STATS_ASPATH_TOTHOPS
] = "Average AS-Path length (hops)",
9614 [BGP_STATS_ASPATH_TOTSIZE
] = "Average AS-Path size (bytes)",
9615 [BGP_STATS_ASN_HIGHEST
] = "Highest public ASN",
9616 [BGP_STATS_MAX
] = NULL
,
9619 struct bgp_table_stats
{
9620 struct bgp_table
*table
;
9621 unsigned long long counts
[BGP_STATS_MAX
];
9626 #define TALLY_SIGFIG 100000
9627 static unsigned long
9628 ravg_tally (unsigned long count
, unsigned long oldavg
, unsigned long newval
)
9630 unsigned long newtot
= (count
-1) * oldavg
+ (newval
* TALLY_SIGFIG
);
9631 unsigned long res
= (newtot
* TALLY_SIGFIG
) / count
;
9632 unsigned long ret
= newtot
/ count
;
9634 if ((res
% TALLY_SIGFIG
) > (TALLY_SIGFIG
/2))
9641 static int bgp_table_stats_walker(struct thread
*t
)
9643 struct bgp_node
*rn
;
9644 struct bgp_node
*top
;
9645 struct bgp_table_stats
*ts
= THREAD_ARG(t
);
9646 unsigned int space
= 0;
9648 if (!(top
= bgp_table_top(ts
->table
)))
9651 switch (top
->p
.family
) {
9653 space
= IPV4_MAX_BITLEN
;
9656 space
= IPV6_MAX_BITLEN
;
9660 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
9662 for (rn
= top
; rn
; rn
= bgp_route_next(rn
)) {
9663 struct bgp_info
*ri
;
9664 struct bgp_node
*prn
= bgp_node_parent_nolock(rn
);
9665 unsigned int rinum
= 0;
9673 ts
->counts
[BGP_STATS_PREFIXES
]++;
9674 ts
->counts
[BGP_STATS_TOTPLEN
] += rn
->p
.prefixlen
;
9677 ts
->counts
[BGP_STATS_AVGPLEN
]
9678 = ravg_tally (ts
->counts
[BGP_STATS_PREFIXES
],
9679 ts
->counts
[BGP_STATS_AVGPLEN
],
9683 /* check if the prefix is included by any other announcements */
9684 while (prn
&& !prn
->info
)
9685 prn
= bgp_node_parent_nolock(prn
);
9687 if (prn
== NULL
|| prn
== top
) {
9688 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
9689 /* announced address space */
9692 pow(2.0, space
- rn
->p
.prefixlen
);
9693 } else if (prn
->info
)
9694 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
9696 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
9698 ts
->counts
[BGP_STATS_RIB
]++;
9701 && (CHECK_FLAG(ri
->attr
->flag
,
9703 BGP_ATTR_ATOMIC_AGGREGATE
))))
9704 ts
->counts
[BGP_STATS_AGGREGATES
]++;
9707 if (ri
->attr
&& ri
->attr
->aspath
) {
9709 aspath_count_hops(ri
->attr
->aspath
);
9711 aspath_size(ri
->attr
->aspath
);
9712 as_t highest
= aspath_highest(ri
->attr
->aspath
);
9714 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
9716 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
9717 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] =
9720 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
9721 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] =
9724 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
9725 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
9727 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
]
9728 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
9729 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
],
9731 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
]
9732 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
9733 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
],
9736 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
9737 ts
->counts
[BGP_STATS_ASN_HIGHEST
] =
9745 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
9748 struct bgp_table_stats ts
;
9751 if (!bgp
->rib
[afi
][safi
]) {
9752 vty_out(vty
, "%% No RIB exist's for the AFI(%d)/SAFI(%d)\n",
9757 vty_out(vty
, "BGP %s RIB statistics\n", afi_safi_print(afi
, safi
));
9759 /* labeled-unicast routes live in the unicast table */
9760 if (safi
== SAFI_LABELED_UNICAST
)
9761 safi
= SAFI_UNICAST
;
9763 memset(&ts
, 0, sizeof(ts
));
9764 ts
.table
= bgp
->rib
[afi
][safi
];
9765 thread_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
9767 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
9768 if (!table_stats_strs
[i
])
9773 case BGP_STATS_ASPATH_AVGHOPS
:
9774 case BGP_STATS_ASPATH_AVGSIZE
:
9775 case BGP_STATS_AVGPLEN
:
9776 vty_out (vty
, "%-30s: ", table_stats_strs
[i
]);
9777 vty_out (vty
, "%12.2f",
9778 (float)ts
.counts
[i
] / (float)TALLY_SIGFIG
);
9781 case BGP_STATS_ASPATH_TOTHOPS
:
9782 case BGP_STATS_ASPATH_TOTSIZE
:
9783 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9784 vty_out(vty
, "%12.2f",
9786 ? (float)ts
.counts
[i
]
9788 [BGP_STATS_ASPATH_COUNT
]
9791 case BGP_STATS_TOTPLEN
:
9792 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9793 vty_out(vty
, "%12.2f",
9795 ? (float)ts
.counts
[i
]
9797 [BGP_STATS_PREFIXES
]
9800 case BGP_STATS_SPACE
:
9801 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9802 vty_out(vty
, "%12g\n", ts
.total_space
);
9804 if (afi
== AFI_IP6
) {
9805 vty_out(vty
, "%30s: ", "/32 equivalent ");
9806 vty_out(vty
, "%12g\n",
9807 ts
.total_space
* pow(2.0, -128 + 32));
9808 vty_out(vty
, "%30s: ", "/48 equivalent ");
9809 vty_out(vty
, "%12g\n",
9810 ts
.total_space
* pow(2.0, -128 + 48));
9812 vty_out(vty
, "%30s: ", "% announced ");
9813 vty_out(vty
, "%12.2f\n",
9814 ts
.total_space
* 100. * pow(2.0, -32));
9815 vty_out(vty
, "%30s: ", "/8 equivalent ");
9816 vty_out(vty
, "%12.2f\n",
9817 ts
.total_space
* pow(2.0, -32 + 8));
9818 vty_out(vty
, "%30s: ", "/24 equivalent ");
9819 vty_out(vty
, "%12.2f\n",
9820 ts
.total_space
* pow(2.0, -32 + 24));
9824 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9825 vty_out(vty
, "%12llu", ts
.counts
[i
]);
9842 PCOUNT_PFCNT
, /* the figure we display to users */
9846 static const char *pcount_strs
[] = {
9847 [PCOUNT_ADJ_IN
] = "Adj-in",
9848 [PCOUNT_DAMPED
] = "Damped",
9849 [PCOUNT_REMOVED
] = "Removed",
9850 [PCOUNT_HISTORY
] = "History",
9851 [PCOUNT_STALE
] = "Stale",
9852 [PCOUNT_VALID
] = "Valid",
9853 [PCOUNT_ALL
] = "All RIB",
9854 [PCOUNT_COUNTED
] = "PfxCt counted",
9855 [PCOUNT_PFCNT
] = "Useable",
9856 [PCOUNT_MAX
] = NULL
,
9859 struct peer_pcounts
{
9860 unsigned int count
[PCOUNT_MAX
];
9861 const struct peer
*peer
;
9862 const struct bgp_table
*table
;
9865 static int bgp_peer_count_walker(struct thread
*t
)
9867 struct bgp_node
*rn
;
9868 struct peer_pcounts
*pc
= THREAD_ARG(t
);
9869 const struct peer
*peer
= pc
->peer
;
9871 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
)) {
9872 struct bgp_adj_in
*ain
;
9873 struct bgp_info
*ri
;
9875 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
9876 if (ain
->peer
== peer
)
9877 pc
->count
[PCOUNT_ADJ_IN
]++;
9879 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
9880 if (ri
->peer
!= peer
)
9883 pc
->count
[PCOUNT_ALL
]++;
9885 if (CHECK_FLAG(ri
->flags
, BGP_INFO_DAMPED
))
9886 pc
->count
[PCOUNT_DAMPED
]++;
9887 if (CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
9888 pc
->count
[PCOUNT_HISTORY
]++;
9889 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
))
9890 pc
->count
[PCOUNT_REMOVED
]++;
9891 if (CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
))
9892 pc
->count
[PCOUNT_STALE
]++;
9893 if (CHECK_FLAG(ri
->flags
, BGP_INFO_VALID
))
9894 pc
->count
[PCOUNT_VALID
]++;
9895 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
9896 pc
->count
[PCOUNT_PFCNT
]++;
9898 if (CHECK_FLAG(ri
->flags
, BGP_INFO_COUNTED
)) {
9899 pc
->count
[PCOUNT_COUNTED
]++;
9900 if (CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
9903 "Attempting to count but flags say it is unusable");
9905 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
9908 "Not counted but flags say we should");
9915 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
9916 safi_t safi
, bool use_json
)
9918 struct peer_pcounts pcounts
= {.peer
= peer
};
9920 json_object
*json
= NULL
;
9921 json_object
*json_loop
= NULL
;
9924 json
= json_object_new_object();
9925 json_loop
= json_object_new_object();
9928 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
9929 || !peer
->bgp
->rib
[afi
][safi
]) {
9931 json_object_string_add(
9933 "No such neighbor or address family");
9934 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
9935 json_object_free(json
);
9937 vty_out(vty
, "%% No such neighbor or address family\n");
9942 memset(&pcounts
, 0, sizeof(pcounts
));
9943 pcounts
.peer
= peer
;
9944 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
9946 /* in-place call via thread subsystem so as to record execution time
9947 * stats for the thread-walk (i.e. ensure this can't be blamed on
9948 * on just vty_read()).
9950 thread_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
9953 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
9954 json_object_string_add(json
, "multiProtocol",
9955 afi_safi_print(afi
, safi
));
9956 json_object_int_add(json
, "pfxCounter",
9957 peer
->pcount
[afi
][safi
]);
9959 for (i
= 0; i
< PCOUNT_MAX
; i
++)
9960 json_object_int_add(json_loop
, pcount_strs
[i
],
9963 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
9965 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
9966 json_object_string_add(json
, "pfxctDriftFor",
9968 json_object_string_add(
9969 json
, "recommended",
9970 "Please report this bug, with the above command output");
9972 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
9973 json
, JSON_C_TO_STRING_PRETTY
));
9974 json_object_free(json
);
9978 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
9979 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
9980 peer
->hostname
, peer
->host
,
9981 afi_safi_print(afi
, safi
));
9983 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
9984 afi_safi_print(afi
, safi
));
9987 vty_out(vty
, "PfxCt: %ld\n", peer
->pcount
[afi
][safi
]);
9988 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
9990 for (i
= 0; i
< PCOUNT_MAX
; i
++)
9991 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
9994 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
9995 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
9997 "Please report this bug, with the above command output\n");
10001 return CMD_SUCCESS
;
10004 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
10005 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
10006 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_CMD_STR
"]] "
10007 "neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
10011 BGP_INSTANCE_HELP_STR
10014 "Detailed information on TCP and BGP neighbor connections\n"
10015 "Neighbor to display information about\n"
10016 "Neighbor to display information about\n"
10017 "Neighbor on BGP configured interface\n"
10018 "Display detailed prefix count information\n"
10021 afi_t afi
= AFI_IP6
;
10022 safi_t safi
= SAFI_UNICAST
;
10025 struct bgp
*bgp
= NULL
;
10026 bool uj
= use_json(argc
, argv
);
10031 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10034 return CMD_WARNING
;
10036 argv_find(argv
, argc
, "neighbors", &idx
);
10037 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
10039 return CMD_WARNING
;
10041 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_UNICAST
, uj
);
10044 #ifdef KEEP_OLD_VPN_COMMANDS
10045 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
10046 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
10047 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
10052 "Display information about all VPNv4 NLRIs\n"
10053 "Detailed information on TCP and BGP neighbor connections\n"
10054 "Neighbor to display information about\n"
10055 "Neighbor to display information about\n"
10056 "Neighbor on BGP configured interface\n"
10057 "Display detailed prefix count information\n"
10062 bool uj
= use_json(argc
, argv
);
10064 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
10066 return CMD_WARNING
;
10068 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
10071 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
10072 show_ip_bgp_vpn_all_route_prefix_cmd
,
10073 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
10078 "Display information about all VPNv4 NLRIs\n"
10079 "Network in the BGP routing table to display\n"
10080 "Network in the BGP routing table to display\n"
10084 char *network
= NULL
;
10085 struct bgp
*bgp
= bgp_get_default();
10087 vty_out(vty
, "Can't find default instance\n");
10088 return CMD_WARNING
;
10091 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
10092 network
= argv
[idx
]->arg
;
10093 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
10094 network
= argv
[idx
]->arg
;
10096 vty_out(vty
, "Unable to figure out Network\n");
10097 return CMD_WARNING
;
10100 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
10101 BGP_PATH_ALL
, use_json(argc
, argv
));
10103 #endif /* KEEP_OLD_VPN_COMMANDS */
10105 DEFUN (show_ip_bgp_l2vpn_evpn_all_route_prefix
,
10106 show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd
,
10107 "show [ip] bgp l2vpn evpn all <A.B.C.D|A.B.C.D/M> [json]",
10113 "Display information about all EVPN NLRIs\n"
10114 "Network in the BGP routing table to display\n"
10115 "Network in the BGP routing table to display\n"
10119 char *network
= NULL
;
10121 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
10122 network
= argv
[idx
]->arg
;
10123 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
10124 network
= argv
[idx
]->arg
;
10126 vty_out(vty
, "Unable to figure out Network\n");
10127 return CMD_WARNING
;
10129 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
, 0,
10130 BGP_PATH_ALL
, use_json(argc
, argv
));
10133 static void show_adj_route(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
10134 safi_t safi
, enum bgp_show_adj_route_type type
,
10135 const char *rmap_name
, bool use_json
,
10138 struct bgp_table
*table
;
10139 struct bgp_adj_in
*ain
;
10140 struct bgp_adj_out
*adj
;
10141 unsigned long output_count
;
10142 unsigned long filtered_count
;
10143 struct bgp_node
*rn
;
10149 struct update_subgroup
*subgrp
;
10150 json_object
*json_scode
= NULL
;
10151 json_object
*json_ocode
= NULL
;
10152 json_object
*json_ar
= NULL
;
10153 struct peer_af
*paf
;
10154 bool route_filtered
;
10157 json_scode
= json_object_new_object();
10158 json_ocode
= json_object_new_object();
10159 json_ar
= json_object_new_object();
10161 json_object_string_add(json_scode
, "suppressed", "s");
10162 json_object_string_add(json_scode
, "damped", "d");
10163 json_object_string_add(json_scode
, "history", "h");
10164 json_object_string_add(json_scode
, "valid", "*");
10165 json_object_string_add(json_scode
, "best", ">");
10166 json_object_string_add(json_scode
, "multipath", "=");
10167 json_object_string_add(json_scode
, "internal", "i");
10168 json_object_string_add(json_scode
, "ribFailure", "r");
10169 json_object_string_add(json_scode
, "stale", "S");
10170 json_object_string_add(json_scode
, "removed", "R");
10172 json_object_string_add(json_ocode
, "igp", "i");
10173 json_object_string_add(json_ocode
, "egp", "e");
10174 json_object_string_add(json_ocode
, "incomplete", "?");
10181 json_object_string_add(json
, "alert", "no BGP");
10182 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10183 json_object_free(json
);
10185 vty_out(vty
, "%% No bgp\n");
10189 table
= bgp
->rib
[afi
][safi
];
10191 output_count
= filtered_count
= 0;
10192 subgrp
= peer_subgroup(peer
, afi
, safi
);
10194 if (type
== bgp_show_adj_route_advertised
&& subgrp
10195 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
10197 json_object_int_add(json
, "bgpTableVersion",
10199 json_object_string_add(json
, "bgpLocalRouterId",
10200 inet_ntoa(bgp
->router_id
));
10201 json_object_object_add(json
, "bgpStatusCodes",
10203 json_object_object_add(json
, "bgpOriginCodes",
10205 json_object_string_add(
10206 json
, "bgpOriginatingDefaultNetwork",
10207 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
10209 vty_out(vty
, "BGP table version is %" PRIu64
10210 ", local router ID is %s, vrf id ",
10211 table
->version
, inet_ntoa(bgp
->router_id
));
10212 if (bgp
->vrf_id
== VRF_UNKNOWN
)
10213 vty_out(vty
, "%s", VRFID_NONE_STR
);
10215 vty_out(vty
, "%u", bgp
->vrf_id
);
10216 vty_out(vty
, "\n");
10217 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
10218 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
10219 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
10221 vty_out(vty
, "Originating default network %s\n\n",
10222 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
10227 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
10228 if (type
== bgp_show_adj_route_received
10229 || type
== bgp_show_adj_route_filtered
) {
10230 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
10231 if (ain
->peer
!= peer
|| !ain
->attr
)
10236 json_object_int_add(
10237 json
, "bgpTableVersion",
10239 json_object_string_add(
10241 "bgpLocalRouterId",
10244 json_object_object_add(
10245 json
, "bgpStatusCodes",
10247 json_object_object_add(
10248 json
, "bgpOriginCodes",
10252 "BGP table version is 0, local router ID is %s, vrf id ",
10255 if (bgp
->vrf_id
== VRF_UNKNOWN
)
10261 vty_out(vty
, "\n");
10263 BGP_SHOW_SCODE_HEADER
);
10265 BGP_SHOW_NCODE_HEADER
);
10267 BGP_SHOW_OCODE_HEADER
);
10273 vty_out(vty
, BGP_SHOW_HEADER
);
10277 bgp_attr_dup(&attr
, ain
->attr
);
10278 route_filtered
= false;
10280 /* Filter prefix using distribute list,
10281 * filter list or prefix list
10283 if ((bgp_input_filter(peer
, &rn
->p
, &attr
, afi
,
10284 safi
)) == FILTER_DENY
)
10285 route_filtered
= true;
10287 /* Filter prefix using route-map */
10288 ret
= bgp_input_modifier(peer
, &rn
->p
, &attr
,
10289 afi
, safi
, rmap_name
);
10291 if (type
== bgp_show_adj_route_filtered
&&
10292 !route_filtered
&& ret
!= RMAP_DENY
) {
10293 bgp_attr_undup(&attr
, ain
->attr
);
10297 if (type
== bgp_show_adj_route_received
&&
10298 (route_filtered
|| ret
== RMAP_DENY
))
10301 route_vty_out_tmp(vty
, &rn
->p
, &attr
, safi
,
10302 use_json
, json_ar
);
10303 bgp_attr_undup(&attr
, ain
->attr
);
10306 } else if (type
== bgp_show_adj_route_advertised
) {
10307 for (adj
= rn
->adj_out
; adj
; adj
= adj
->next
)
10308 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
10309 if (paf
->peer
!= peer
|| !adj
->attr
)
10314 json_object_int_add(
10318 json_object_string_add(
10320 "bgpLocalRouterId",
10323 json_object_object_add(
10327 json_object_object_add(
10333 "BGP table version is %" PRIu64
10334 ", local router ID is %s, vrf id ",
10347 vty_out(vty
, "\n");
10349 BGP_SHOW_SCODE_HEADER
);
10351 BGP_SHOW_NCODE_HEADER
);
10353 BGP_SHOW_OCODE_HEADER
);
10364 bgp_attr_dup(&attr
, adj
->attr
);
10365 ret
= bgp_output_modifier(
10366 peer
, &rn
->p
, &attr
, afi
, safi
,
10369 if (ret
!= RMAP_DENY
) {
10370 route_vty_out_tmp(vty
, &rn
->p
,
10379 bgp_attr_undup(&attr
, adj
->attr
);
10385 json_object_object_add(json
, "advertisedRoutes", json_ar
);
10386 json_object_int_add(json
, "totalPrefixCounter", output_count
);
10387 json_object_int_add(json
, "filteredPrefixCounter",
10390 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
10391 json
, JSON_C_TO_STRING_PRETTY
));
10392 json_object_free(json
);
10393 } else if (output_count
> 0) {
10394 if (filtered_count
> 0)
10396 "\nTotal number of prefixes %ld (%ld filtered)\n",
10397 output_count
, filtered_count
);
10399 vty_out(vty
, "\nTotal number of prefixes %ld\n",
10404 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
10405 safi_t safi
, enum bgp_show_adj_route_type type
,
10406 const char *rmap_name
, bool use_json
)
10408 json_object
*json
= NULL
;
10411 json
= json_object_new_object();
10413 /* labeled-unicast routes live in the unicast table */
10414 if (safi
== SAFI_LABELED_UNICAST
)
10415 safi
= SAFI_UNICAST
;
10417 if (!peer
|| !peer
->afc
[afi
][safi
]) {
10419 json_object_string_add(
10421 "No such neighbor or address family");
10422 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10423 json_object_free(json
);
10425 vty_out(vty
, "%% No such neighbor or address family\n");
10427 return CMD_WARNING
;
10430 if ((type
== bgp_show_adj_route_received
10431 || type
== bgp_show_adj_route_filtered
)
10432 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
10433 PEER_FLAG_SOFT_RECONFIG
)) {
10435 json_object_string_add(
10437 "Inbound soft reconfiguration not enabled");
10438 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10439 json_object_free(json
);
10442 "%% Inbound soft reconfiguration not enabled\n");
10444 return CMD_WARNING
;
10447 show_adj_route(vty
, peer
, afi
, safi
, type
, rmap_name
, use_json
, json
);
10449 return CMD_SUCCESS
;
10452 DEFUN (show_ip_bgp_instance_neighbor_advertised_route
,
10453 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
10454 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
10455 "neighbors <A.B.C.D|X:X::X:X|WORD> <advertised-routes|received-routes|filtered-routes> [route-map WORD] [json]",
10459 BGP_INSTANCE_HELP_STR
10461 BGP_SAFI_WITH_LABEL_HELP_STR
10462 "Detailed information on TCP and BGP neighbor connections\n"
10463 "Neighbor to display information about\n"
10464 "Neighbor to display information about\n"
10465 "Neighbor on BGP configured interface\n"
10466 "Display the routes advertised to a BGP neighbor\n"
10467 "Display the received routes from neighbor\n"
10468 "Display the filtered routes received from neighbor\n"
10469 "Route-map to modify the attributes\n"
10470 "Name of the route map\n"
10473 afi_t afi
= AFI_IP6
;
10474 safi_t safi
= SAFI_UNICAST
;
10475 char *rmap_name
= NULL
;
10476 char *peerstr
= NULL
;
10477 struct bgp
*bgp
= NULL
;
10479 enum bgp_show_adj_route_type type
= bgp_show_adj_route_advertised
;
10481 bool uj
= use_json(argc
, argv
);
10486 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10489 return CMD_WARNING
;
10491 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10492 argv_find(argv
, argc
, "neighbors", &idx
);
10493 peerstr
= argv
[++idx
]->arg
;
10495 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
10497 return CMD_WARNING
;
10499 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
10500 type
= bgp_show_adj_route_advertised
;
10501 else if (argv_find(argv
, argc
, "received-routes", &idx
))
10502 type
= bgp_show_adj_route_received
;
10503 else if (argv_find(argv
, argc
, "filtered-routes", &idx
))
10504 type
= bgp_show_adj_route_filtered
;
10506 if (argv_find(argv
, argc
, "route-map", &idx
))
10507 rmap_name
= argv
[++idx
]->arg
;
10509 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
, uj
);
10512 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
10513 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
10514 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
10520 "Address Family modifier\n"
10521 "Detailed information on TCP and BGP neighbor connections\n"
10522 "Neighbor to display information about\n"
10523 "Neighbor to display information about\n"
10524 "Neighbor on BGP configured interface\n"
10525 "Display information received from a BGP neighbor\n"
10526 "Display the prefixlist filter\n"
10529 afi_t afi
= AFI_IP6
;
10530 safi_t safi
= SAFI_UNICAST
;
10531 char *peerstr
= NULL
;
10534 union sockunion su
;
10540 /* show [ip] bgp */
10541 if (argv_find(argv
, argc
, "ip", &idx
))
10543 /* [<ipv4|ipv6> [unicast]] */
10544 if (argv_find(argv
, argc
, "ipv4", &idx
))
10546 if (argv_find(argv
, argc
, "ipv6", &idx
))
10548 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10549 argv_find(argv
, argc
, "neighbors", &idx
);
10550 peerstr
= argv
[++idx
]->arg
;
10552 bool uj
= use_json(argc
, argv
);
10554 ret
= str2sockunion(peerstr
, &su
);
10556 peer
= peer_lookup_by_conf_if(NULL
, peerstr
);
10559 vty_out(vty
, "{}\n");
10562 "%% Malformed address or name: %s\n",
10564 return CMD_WARNING
;
10567 peer
= peer_lookup(NULL
, &su
);
10570 vty_out(vty
, "{}\n");
10572 vty_out(vty
, "No peer\n");
10573 return CMD_WARNING
;
10577 sprintf(name
, "%s.%d.%d", peer
->host
, afi
, safi
);
10578 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
10581 vty_out(vty
, "Address Family: %s\n",
10582 afi_safi_print(afi
, safi
));
10583 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
10586 vty_out(vty
, "{}\n");
10588 vty_out(vty
, "No functional output\n");
10591 return CMD_SUCCESS
;
10594 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
10595 afi_t afi
, safi_t safi
,
10596 enum bgp_show_type type
, bool use_json
)
10598 /* labeled-unicast routes live in the unicast table */
10599 if (safi
== SAFI_LABELED_UNICAST
)
10600 safi
= SAFI_UNICAST
;
10602 if (!peer
|| !peer
->afc
[afi
][safi
]) {
10604 json_object
*json_no
= NULL
;
10605 json_no
= json_object_new_object();
10606 json_object_string_add(
10607 json_no
, "warning",
10608 "No such neighbor or address family");
10609 vty_out(vty
, "%s\n",
10610 json_object_to_json_string(json_no
));
10611 json_object_free(json_no
);
10613 vty_out(vty
, "%% No such neighbor or address family\n");
10614 return CMD_WARNING
;
10617 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, use_json
);
10620 DEFUN (show_ip_bgp_flowspec_routes_detailed
,
10621 show_ip_bgp_flowspec_routes_detailed_cmd
,
10622 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" flowspec] detail [json]",
10626 BGP_INSTANCE_HELP_STR
10629 "Detailed information on flowspec entries\n"
10632 afi_t afi
= AFI_IP
;
10633 safi_t safi
= SAFI_UNICAST
;
10634 struct bgp
*bgp
= NULL
;
10636 bool uj
= use_json(argc
, argv
);
10641 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10644 return CMD_WARNING
;
10646 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_detail
, NULL
, uj
);
10649 DEFUN (show_ip_bgp_neighbor_routes
,
10650 show_ip_bgp_neighbor_routes_cmd
,
10651 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
10652 "neighbors <A.B.C.D|X:X::X:X|WORD> <flap-statistics|dampened-routes|routes> [json]",
10656 BGP_INSTANCE_HELP_STR
10658 BGP_SAFI_WITH_LABEL_HELP_STR
10659 "Detailed information on TCP and BGP neighbor connections\n"
10660 "Neighbor to display information about\n"
10661 "Neighbor to display information about\n"
10662 "Neighbor on BGP configured interface\n"
10663 "Display flap statistics of the routes learned from neighbor\n"
10664 "Display the dampened routes received from neighbor\n"
10665 "Display routes learned from neighbor\n"
10668 char *peerstr
= NULL
;
10669 struct bgp
*bgp
= NULL
;
10670 afi_t afi
= AFI_IP6
;
10671 safi_t safi
= SAFI_UNICAST
;
10673 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
10675 bool uj
= use_json(argc
, argv
);
10680 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10683 return CMD_WARNING
;
10685 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10686 argv_find(argv
, argc
, "neighbors", &idx
);
10687 peerstr
= argv
[++idx
]->arg
;
10689 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
10691 return CMD_WARNING
;
10693 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
10694 sh_type
= bgp_show_type_flap_neighbor
;
10695 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
10696 sh_type
= bgp_show_type_damp_neighbor
;
10697 else if (argv_find(argv
, argc
, "routes", &idx
))
10698 sh_type
= bgp_show_type_neighbor
;
10700 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
10703 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
10705 struct bgp_distance
{
10706 /* Distance value for the IP source prefix. */
10709 /* Name of the access-list to be matched. */
10713 DEFUN (show_bgp_afi_vpn_rd_route
,
10714 show_bgp_afi_vpn_rd_route_cmd
,
10715 "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]",
10719 "Address Family modifier\n"
10720 "Display information for a route distinguisher\n"
10721 "Route Distinguisher\n"
10722 "Network in the BGP routing table to display\n"
10723 "Network in the BGP routing table to display\n"
10727 struct prefix_rd prd
;
10728 afi_t afi
= AFI_MAX
;
10731 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
10732 vty_out(vty
, "%% Malformed Address Family\n");
10733 return CMD_WARNING
;
10736 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
10738 vty_out(vty
, "%% Malformed Route Distinguisher\n");
10739 return CMD_WARNING
;
10742 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
10743 0, BGP_PATH_ALL
, use_json(argc
, argv
));
10746 static struct bgp_distance
*bgp_distance_new(void)
10748 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
10751 static void bgp_distance_free(struct bgp_distance
*bdistance
)
10753 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
10756 static int bgp_distance_set(struct vty
*vty
, const char *distance_str
,
10757 const char *ip_str
, const char *access_list_str
)
10764 struct bgp_node
*rn
;
10765 struct bgp_distance
*bdistance
;
10767 afi
= bgp_node_afi(vty
);
10768 safi
= bgp_node_safi(vty
);
10770 ret
= str2prefix(ip_str
, &p
);
10772 vty_out(vty
, "Malformed prefix\n");
10773 return CMD_WARNING_CONFIG_FAILED
;
10776 distance
= atoi(distance_str
);
10778 /* Get BGP distance node. */
10779 rn
= bgp_node_get(bgp_distance_table
[afi
][safi
], (struct prefix
*)&p
);
10780 bdistance
= bgp_distance_get_node(rn
);
10782 bgp_unlock_node(rn
);
10784 bdistance
= bgp_distance_new();
10785 bgp_distance_set_node_info(rn
, bdistance
);
10788 /* Set distance value. */
10789 bdistance
->distance
= distance
;
10791 /* Reset access-list configuration. */
10792 if (bdistance
->access_list
) {
10793 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
10794 bdistance
->access_list
= NULL
;
10796 if (access_list_str
)
10797 bdistance
->access_list
=
10798 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
10800 return CMD_SUCCESS
;
10803 static int bgp_distance_unset(struct vty
*vty
, const char *distance_str
,
10804 const char *ip_str
, const char *access_list_str
)
10811 struct bgp_node
*rn
;
10812 struct bgp_distance
*bdistance
;
10814 afi
= bgp_node_afi(vty
);
10815 safi
= bgp_node_safi(vty
);
10817 ret
= str2prefix(ip_str
, &p
);
10819 vty_out(vty
, "Malformed prefix\n");
10820 return CMD_WARNING_CONFIG_FAILED
;
10823 rn
= bgp_node_lookup(bgp_distance_table
[afi
][safi
],
10824 (struct prefix
*)&p
);
10826 vty_out(vty
, "Can't find specified prefix\n");
10827 return CMD_WARNING_CONFIG_FAILED
;
10830 bdistance
= bgp_distance_get_node(rn
);
10831 distance
= atoi(distance_str
);
10833 if (bdistance
->distance
!= distance
) {
10834 vty_out(vty
, "Distance does not match configured\n");
10835 return CMD_WARNING_CONFIG_FAILED
;
10838 if (bdistance
->access_list
)
10839 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
10840 bgp_distance_free(bdistance
);
10843 bgp_unlock_node(rn
);
10844 bgp_unlock_node(rn
);
10846 return CMD_SUCCESS
;
10849 /* Apply BGP information to distance method. */
10850 uint8_t bgp_distance_apply(struct prefix
*p
, struct bgp_info
*rinfo
, afi_t afi
,
10851 safi_t safi
, struct bgp
*bgp
)
10853 struct bgp_node
*rn
;
10856 struct bgp_distance
*bdistance
;
10857 struct access_list
*alist
;
10858 struct bgp_static
*bgp_static
;
10863 peer
= rinfo
->peer
;
10865 /* Check source address. */
10866 sockunion2hostprefix(&peer
->su
, &q
);
10867 rn
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
10869 bdistance
= bgp_distance_get_node(rn
);
10870 bgp_unlock_node(rn
);
10872 if (bdistance
->access_list
) {
10873 alist
= access_list_lookup(afi
, bdistance
->access_list
);
10875 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
10876 return bdistance
->distance
;
10878 return bdistance
->distance
;
10881 /* Backdoor check. */
10882 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
10884 bgp_static
= bgp_static_get_node_info(rn
);
10885 bgp_unlock_node(rn
);
10887 if (bgp_static
->backdoor
) {
10888 if (bgp
->distance_local
[afi
][safi
])
10889 return bgp
->distance_local
[afi
][safi
];
10891 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
10895 if (peer
->sort
== BGP_PEER_EBGP
) {
10896 if (bgp
->distance_ebgp
[afi
][safi
])
10897 return bgp
->distance_ebgp
[afi
][safi
];
10898 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
10900 if (bgp
->distance_ibgp
[afi
][safi
])
10901 return bgp
->distance_ibgp
[afi
][safi
];
10902 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
10906 DEFUN (bgp_distance
,
10908 "distance bgp (1-255) (1-255) (1-255)",
10909 "Define an administrative distance\n"
10911 "Distance for routes external to the AS\n"
10912 "Distance for routes internal to the AS\n"
10913 "Distance for local routes\n")
10915 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
10916 int idx_number
= 2;
10917 int idx_number_2
= 3;
10918 int idx_number_3
= 4;
10922 afi
= bgp_node_afi(vty
);
10923 safi
= bgp_node_safi(vty
);
10925 bgp
->distance_ebgp
[afi
][safi
] = atoi(argv
[idx_number
]->arg
);
10926 bgp
->distance_ibgp
[afi
][safi
] = atoi(argv
[idx_number_2
]->arg
);
10927 bgp
->distance_local
[afi
][safi
] = atoi(argv
[idx_number_3
]->arg
);
10928 return CMD_SUCCESS
;
10931 DEFUN (no_bgp_distance
,
10932 no_bgp_distance_cmd
,
10933 "no distance bgp [(1-255) (1-255) (1-255)]",
10935 "Define an administrative distance\n"
10937 "Distance for routes external to the AS\n"
10938 "Distance for routes internal to the AS\n"
10939 "Distance for local routes\n")
10941 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
10945 afi
= bgp_node_afi(vty
);
10946 safi
= bgp_node_safi(vty
);
10948 bgp
->distance_ebgp
[afi
][safi
] = 0;
10949 bgp
->distance_ibgp
[afi
][safi
] = 0;
10950 bgp
->distance_local
[afi
][safi
] = 0;
10951 return CMD_SUCCESS
;
10955 DEFUN (bgp_distance_source
,
10956 bgp_distance_source_cmd
,
10957 "distance (1-255) A.B.C.D/M",
10958 "Define an administrative distance\n"
10959 "Administrative distance\n"
10960 "IP source prefix\n")
10962 int idx_number
= 1;
10963 int idx_ipv4_prefixlen
= 2;
10964 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
10965 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
10966 return CMD_SUCCESS
;
10969 DEFUN (no_bgp_distance_source
,
10970 no_bgp_distance_source_cmd
,
10971 "no distance (1-255) A.B.C.D/M",
10973 "Define an administrative distance\n"
10974 "Administrative distance\n"
10975 "IP source prefix\n")
10977 int idx_number
= 2;
10978 int idx_ipv4_prefixlen
= 3;
10979 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
10980 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
10981 return CMD_SUCCESS
;
10984 DEFUN (bgp_distance_source_access_list
,
10985 bgp_distance_source_access_list_cmd
,
10986 "distance (1-255) A.B.C.D/M WORD",
10987 "Define an administrative distance\n"
10988 "Administrative distance\n"
10989 "IP source prefix\n"
10990 "Access list name\n")
10992 int idx_number
= 1;
10993 int idx_ipv4_prefixlen
= 2;
10995 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
10996 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
10997 return CMD_SUCCESS
;
11000 DEFUN (no_bgp_distance_source_access_list
,
11001 no_bgp_distance_source_access_list_cmd
,
11002 "no distance (1-255) A.B.C.D/M WORD",
11004 "Define an administrative distance\n"
11005 "Administrative distance\n"
11006 "IP source prefix\n"
11007 "Access list name\n")
11009 int idx_number
= 2;
11010 int idx_ipv4_prefixlen
= 3;
11012 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
11013 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
11014 return CMD_SUCCESS
;
11017 DEFUN (ipv6_bgp_distance_source
,
11018 ipv6_bgp_distance_source_cmd
,
11019 "distance (1-255) X:X::X:X/M",
11020 "Define an administrative distance\n"
11021 "Administrative distance\n"
11022 "IP source prefix\n")
11024 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, NULL
);
11025 return CMD_SUCCESS
;
11028 DEFUN (no_ipv6_bgp_distance_source
,
11029 no_ipv6_bgp_distance_source_cmd
,
11030 "no distance (1-255) X:X::X:X/M",
11032 "Define an administrative distance\n"
11033 "Administrative distance\n"
11034 "IP source prefix\n")
11036 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, NULL
);
11037 return CMD_SUCCESS
;
11040 DEFUN (ipv6_bgp_distance_source_access_list
,
11041 ipv6_bgp_distance_source_access_list_cmd
,
11042 "distance (1-255) X:X::X:X/M WORD",
11043 "Define an administrative distance\n"
11044 "Administrative distance\n"
11045 "IP source prefix\n"
11046 "Access list name\n")
11048 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, argv
[3]->arg
);
11049 return CMD_SUCCESS
;
11052 DEFUN (no_ipv6_bgp_distance_source_access_list
,
11053 no_ipv6_bgp_distance_source_access_list_cmd
,
11054 "no distance (1-255) X:X::X:X/M WORD",
11056 "Define an administrative distance\n"
11057 "Administrative distance\n"
11058 "IP source prefix\n"
11059 "Access list name\n")
11061 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, argv
[4]->arg
);
11062 return CMD_SUCCESS
;
11065 DEFUN (bgp_damp_set
,
11067 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
11068 "BGP Specific commands\n"
11069 "Enable route-flap dampening\n"
11070 "Half-life time for the penalty\n"
11071 "Value to start reusing a route\n"
11072 "Value to start suppressing a route\n"
11073 "Maximum duration to suppress a stable route\n")
11075 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11076 int idx_half_life
= 2;
11078 int idx_suppress
= 4;
11079 int idx_max_suppress
= 5;
11080 int half
= DEFAULT_HALF_LIFE
* 60;
11081 int reuse
= DEFAULT_REUSE
;
11082 int suppress
= DEFAULT_SUPPRESS
;
11083 int max
= 4 * half
;
11086 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
11087 reuse
= atoi(argv
[idx_reuse
]->arg
);
11088 suppress
= atoi(argv
[idx_suppress
]->arg
);
11089 max
= atoi(argv
[idx_max_suppress
]->arg
) * 60;
11090 } else if (argc
== 3) {
11091 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
11095 if (suppress
< reuse
) {
11097 "Suppress value cannot be less than reuse value \n");
11101 return bgp_damp_enable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
), half
,
11102 reuse
, suppress
, max
);
11105 DEFUN (bgp_damp_unset
,
11106 bgp_damp_unset_cmd
,
11107 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
11109 "BGP Specific commands\n"
11110 "Enable route-flap dampening\n"
11111 "Half-life time for the penalty\n"
11112 "Value to start reusing a route\n"
11113 "Value to start suppressing a route\n"
11114 "Maximum duration to suppress a stable route\n")
11116 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11117 return bgp_damp_disable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
));
11120 /* Display specified route of BGP table. */
11121 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
11122 const char *ip_str
, afi_t afi
, safi_t safi
,
11123 struct prefix_rd
*prd
, int prefix_check
)
11126 struct prefix match
;
11127 struct bgp_node
*rn
;
11128 struct bgp_node
*rm
;
11129 struct bgp_info
*ri
;
11130 struct bgp_info
*ri_temp
;
11132 struct bgp_table
*table
;
11134 /* BGP structure lookup. */
11136 bgp
= bgp_lookup_by_name(view_name
);
11138 vty_out(vty
, "%% Can't find BGP instance %s\n",
11140 return CMD_WARNING
;
11143 bgp
= bgp_get_default();
11145 vty_out(vty
, "%% No BGP process is configured\n");
11146 return CMD_WARNING
;
11150 /* Check IP address argument. */
11151 ret
= str2prefix(ip_str
, &match
);
11153 vty_out(vty
, "%% address is malformed\n");
11154 return CMD_WARNING
;
11157 match
.family
= afi2family(afi
);
11159 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
11160 || (safi
== SAFI_EVPN
)) {
11161 for (rn
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); rn
;
11162 rn
= bgp_route_next(rn
)) {
11163 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
11165 if ((table
= rn
->info
) == NULL
)
11167 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
11171 || rm
->p
.prefixlen
== match
.prefixlen
) {
11174 if (ri
->extra
&& ri
->extra
->damp_info
) {
11175 ri_temp
= ri
->next
;
11176 bgp_damp_info_free(
11177 ri
->extra
->damp_info
,
11185 bgp_unlock_node(rm
);
11188 if ((rn
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
))
11191 || rn
->p
.prefixlen
== match
.prefixlen
) {
11194 if (ri
->extra
&& ri
->extra
->damp_info
) {
11195 ri_temp
= ri
->next
;
11196 bgp_damp_info_free(
11197 ri
->extra
->damp_info
,
11205 bgp_unlock_node(rn
);
11209 return CMD_SUCCESS
;
11212 DEFUN (clear_ip_bgp_dampening
,
11213 clear_ip_bgp_dampening_cmd
,
11214 "clear ip bgp dampening",
11218 "Clear route flap dampening information\n")
11220 bgp_damp_info_clean();
11221 return CMD_SUCCESS
;
11224 DEFUN (clear_ip_bgp_dampening_prefix
,
11225 clear_ip_bgp_dampening_prefix_cmd
,
11226 "clear ip bgp dampening A.B.C.D/M",
11230 "Clear route flap dampening information\n"
11233 int idx_ipv4_prefixlen
= 4;
11234 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
11235 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
11238 DEFUN (clear_ip_bgp_dampening_address
,
11239 clear_ip_bgp_dampening_address_cmd
,
11240 "clear ip bgp dampening A.B.C.D",
11244 "Clear route flap dampening information\n"
11245 "Network to clear damping information\n")
11248 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
11249 SAFI_UNICAST
, NULL
, 0);
11252 DEFUN (clear_ip_bgp_dampening_address_mask
,
11253 clear_ip_bgp_dampening_address_mask_cmd
,
11254 "clear ip bgp dampening A.B.C.D A.B.C.D",
11258 "Clear route flap dampening information\n"
11259 "Network to clear damping information\n"
11263 int idx_ipv4_2
= 5;
11265 char prefix_str
[BUFSIZ
];
11267 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
11270 vty_out(vty
, "%% Inconsistent address and mask\n");
11271 return CMD_WARNING
;
11274 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
11278 /* also used for encap safi */
11279 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
11280 afi_t afi
, safi_t safi
)
11282 struct bgp_node
*prn
;
11283 struct bgp_node
*rn
;
11284 struct bgp_table
*table
;
11286 struct prefix_rd
*prd
;
11287 struct bgp_static
*bgp_static
;
11288 mpls_label_t label
;
11289 char buf
[SU_ADDRSTRLEN
];
11290 char rdbuf
[RD_ADDRSTRLEN
];
11292 /* Network configuration. */
11293 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
11294 prn
= bgp_route_next(prn
)) {
11295 if ((table
= prn
->info
) == NULL
)
11298 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
11299 bgp_static
= bgp_static_get_node_info(rn
);
11300 if (bgp_static
== NULL
)
11304 prd
= (struct prefix_rd
*)&prn
->p
;
11306 /* "network" configuration display. */
11307 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
11308 label
= decode_label(&bgp_static
->label
);
11310 vty_out(vty
, " network %s/%d rd %s",
11311 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11313 p
->prefixlen
, rdbuf
);
11314 if (safi
== SAFI_MPLS_VPN
)
11315 vty_out(vty
, " label %u", label
);
11317 if (bgp_static
->rmap
.name
)
11318 vty_out(vty
, " route-map %s",
11319 bgp_static
->rmap
.name
);
11321 if (bgp_static
->backdoor
)
11322 vty_out(vty
, " backdoor");
11324 vty_out(vty
, "\n");
11329 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
11330 afi_t afi
, safi_t safi
)
11332 struct bgp_node
*prn
;
11333 struct bgp_node
*rn
;
11334 struct bgp_table
*table
;
11336 struct prefix_rd
*prd
;
11337 struct bgp_static
*bgp_static
;
11338 char buf
[PREFIX_STRLEN
* 2];
11339 char buf2
[SU_ADDRSTRLEN
];
11340 char rdbuf
[RD_ADDRSTRLEN
];
11342 /* Network configuration. */
11343 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
11344 prn
= bgp_route_next(prn
)) {
11345 if ((table
= prn
->info
) == NULL
)
11348 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
11349 bgp_static
= bgp_static_get_node_info(rn
);
11350 if (bgp_static
== NULL
)
11353 char *macrouter
= NULL
;
11356 if (bgp_static
->router_mac
)
11357 macrouter
= prefix_mac2str(
11358 bgp_static
->router_mac
, NULL
, 0);
11359 if (bgp_static
->eth_s_id
)
11360 esi
= esi2str(bgp_static
->eth_s_id
);
11362 prd
= (struct prefix_rd
*)&prn
->p
;
11364 /* "network" configuration display. */
11365 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
11366 if (p
->u
.prefix_evpn
.route_type
== 5) {
11367 char local_buf
[PREFIX_STRLEN
];
11368 uint8_t family
= is_evpn_prefix_ipaddr_v4((
11369 struct prefix_evpn
*)p
)
11373 &p
->u
.prefix_evpn
.prefix_addr
.ip
.ip
.addr
,
11374 local_buf
, PREFIX_STRLEN
);
11375 sprintf(buf
, "%s/%u", local_buf
,
11376 p
->u
.prefix_evpn
.prefix_addr
.ip_prefix_length
);
11378 prefix2str(p
, buf
, sizeof(buf
));
11381 if (bgp_static
->gatewayIp
.family
== AF_INET
11382 || bgp_static
->gatewayIp
.family
== AF_INET6
)
11383 inet_ntop(bgp_static
->gatewayIp
.family
,
11384 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
11387 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
11389 p
->u
.prefix_evpn
.prefix_addr
.eth_tag
,
11390 decode_label(&bgp_static
->label
), esi
, buf2
,
11394 XFREE(MTYPE_TMP
, macrouter
);
11396 XFREE(MTYPE_TMP
, esi
);
11401 /* Configuration of static route announcement and aggregate
11403 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11406 struct bgp_node
*rn
;
11408 struct bgp_static
*bgp_static
;
11409 struct bgp_aggregate
*bgp_aggregate
;
11410 char buf
[SU_ADDRSTRLEN
];
11412 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
11413 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
11417 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
11418 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
11422 /* Network configuration. */
11423 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
11424 rn
= bgp_route_next(rn
)) {
11425 bgp_static
= bgp_static_get_node_info(rn
);
11426 if (bgp_static
== NULL
)
11431 /* "network" configuration display. */
11432 if (bgp_option_check(BGP_OPT_CONFIG_CISCO
) && afi
== AFI_IP
) {
11433 uint32_t destination
;
11434 struct in_addr netmask
;
11436 destination
= ntohl(p
->u
.prefix4
.s_addr
);
11437 masklen2ip(p
->prefixlen
, &netmask
);
11438 vty_out(vty
, " network %s",
11439 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11442 if ((IN_CLASSC(destination
) && p
->prefixlen
== 24)
11443 || (IN_CLASSB(destination
) && p
->prefixlen
== 16)
11444 || (IN_CLASSA(destination
) && p
->prefixlen
== 8)
11445 || p
->u
.prefix4
.s_addr
== 0) {
11446 /* Natural mask is not display. */
11448 vty_out(vty
, " mask %s", inet_ntoa(netmask
));
11450 vty_out(vty
, " network %s/%d",
11451 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11456 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
11457 vty_out(vty
, " label-index %u",
11458 bgp_static
->label_index
);
11460 if (bgp_static
->rmap
.name
)
11461 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
11463 if (bgp_static
->backdoor
)
11464 vty_out(vty
, " backdoor");
11466 vty_out(vty
, "\n");
11469 /* Aggregate-address configuration. */
11470 for (rn
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); rn
;
11471 rn
= bgp_route_next(rn
)) {
11472 bgp_aggregate
= bgp_aggregate_get_node_info(rn
);
11473 if (bgp_aggregate
== NULL
)
11478 if (bgp_option_check(BGP_OPT_CONFIG_CISCO
) && afi
== AFI_IP
) {
11479 struct in_addr netmask
;
11481 masklen2ip(p
->prefixlen
, &netmask
);
11482 vty_out(vty
, " aggregate-address %s %s",
11483 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11485 inet_ntoa(netmask
));
11487 vty_out(vty
, " aggregate-address %s/%d",
11488 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11493 if (bgp_aggregate
->as_set
)
11494 vty_out(vty
, " as-set");
11496 if (bgp_aggregate
->summary_only
)
11497 vty_out(vty
, " summary-only");
11499 vty_out(vty
, "\n");
11503 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11506 struct bgp_node
*rn
;
11507 struct bgp_distance
*bdistance
;
11509 /* Distance configuration. */
11510 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
11511 && bgp
->distance_local
[afi
][safi
]
11512 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
11513 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
11514 || bgp
->distance_local
[afi
][safi
]
11515 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
11516 vty_out(vty
, " distance bgp %d %d %d\n",
11517 bgp
->distance_ebgp
[afi
][safi
],
11518 bgp
->distance_ibgp
[afi
][safi
],
11519 bgp
->distance_local
[afi
][safi
]);
11522 for (rn
= bgp_table_top(bgp_distance_table
[afi
][safi
]); rn
;
11523 rn
= bgp_route_next(rn
)) {
11524 bdistance
= bgp_distance_get_node(rn
);
11525 if (bdistance
!= NULL
) {
11526 char buf
[PREFIX_STRLEN
];
11528 vty_out(vty
, " distance %d %s %s\n",
11529 bdistance
->distance
,
11530 prefix2str(&rn
->p
, buf
, sizeof(buf
)),
11531 bdistance
->access_list
? bdistance
->access_list
11537 /* Allocate routing table structure and install commands. */
11538 void bgp_route_init(void)
11543 /* Init BGP distance table. */
11544 FOREACH_AFI_SAFI (afi
, safi
)
11545 bgp_distance_table
[afi
][safi
] = bgp_table_init(NULL
, afi
, safi
);
11547 /* IPv4 BGP commands. */
11548 install_element(BGP_NODE
, &bgp_table_map_cmd
);
11549 install_element(BGP_NODE
, &bgp_network_cmd
);
11550 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
11552 install_element(BGP_NODE
, &aggregate_address_cmd
);
11553 install_element(BGP_NODE
, &aggregate_address_mask_cmd
);
11554 install_element(BGP_NODE
, &no_aggregate_address_cmd
);
11555 install_element(BGP_NODE
, &no_aggregate_address_mask_cmd
);
11557 /* IPv4 unicast configuration. */
11558 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
11559 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
11560 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
11562 install_element(BGP_IPV4_NODE
, &aggregate_address_cmd
);
11563 install_element(BGP_IPV4_NODE
, &aggregate_address_mask_cmd
);
11564 install_element(BGP_IPV4_NODE
, &no_aggregate_address_cmd
);
11565 install_element(BGP_IPV4_NODE
, &no_aggregate_address_mask_cmd
);
11567 /* IPv4 multicast configuration. */
11568 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
11569 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
11570 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
11571 install_element(BGP_IPV4M_NODE
, &aggregate_address_cmd
);
11572 install_element(BGP_IPV4M_NODE
, &aggregate_address_mask_cmd
);
11573 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_cmd
);
11574 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_mask_cmd
);
11576 /* IPv4 labeled-unicast configuration. */
11577 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
11578 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
11579 install_element(VIEW_NODE
, &show_ip_bgp_json_cmd
);
11580 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
11581 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
11583 install_element(VIEW_NODE
,
11584 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
11585 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
11586 install_element(VIEW_NODE
,
11587 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
11588 #ifdef KEEP_OLD_VPN_COMMANDS
11589 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
11590 #endif /* KEEP_OLD_VPN_COMMANDS */
11591 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
11592 install_element(VIEW_NODE
,
11593 &show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd
);
11595 /* BGP dampening clear commands */
11596 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
11597 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
11599 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
11600 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
11603 install_element(ENABLE_NODE
,
11604 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
11605 #ifdef KEEP_OLD_VPN_COMMANDS
11606 install_element(ENABLE_NODE
,
11607 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
11608 #endif /* KEEP_OLD_VPN_COMMANDS */
11610 /* New config IPv6 BGP commands. */
11611 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
11612 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
11613 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
11615 install_element(BGP_IPV6_NODE
, &ipv6_aggregate_address_cmd
);
11616 install_element(BGP_IPV6_NODE
, &no_ipv6_aggregate_address_cmd
);
11618 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
11620 install_element(BGP_NODE
, &bgp_distance_cmd
);
11621 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
11622 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
11623 install_element(BGP_NODE
, &no_bgp_distance_source_cmd
);
11624 install_element(BGP_NODE
, &bgp_distance_source_access_list_cmd
);
11625 install_element(BGP_NODE
, &no_bgp_distance_source_access_list_cmd
);
11626 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
11627 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
11628 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
11629 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_cmd
);
11630 install_element(BGP_IPV4_NODE
, &bgp_distance_source_access_list_cmd
);
11631 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_access_list_cmd
);
11632 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
11633 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
11634 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
11635 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_source_cmd
);
11636 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_access_list_cmd
);
11637 install_element(BGP_IPV4M_NODE
,
11638 &no_bgp_distance_source_access_list_cmd
);
11639 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
11640 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
11641 install_element(BGP_IPV6_NODE
, &ipv6_bgp_distance_source_cmd
);
11642 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_distance_source_cmd
);
11643 install_element(BGP_IPV6_NODE
,
11644 &ipv6_bgp_distance_source_access_list_cmd
);
11645 install_element(BGP_IPV6_NODE
,
11646 &no_ipv6_bgp_distance_source_access_list_cmd
);
11647 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
11648 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
11649 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_distance_source_cmd
);
11650 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_distance_source_cmd
);
11651 install_element(BGP_IPV6M_NODE
,
11652 &ipv6_bgp_distance_source_access_list_cmd
);
11653 install_element(BGP_IPV6M_NODE
,
11654 &no_ipv6_bgp_distance_source_access_list_cmd
);
11656 install_element(BGP_NODE
, &bgp_damp_set_cmd
);
11657 install_element(BGP_NODE
, &bgp_damp_unset_cmd
);
11658 install_element(BGP_IPV4_NODE
, &bgp_damp_set_cmd
);
11659 install_element(BGP_IPV4_NODE
, &bgp_damp_unset_cmd
);
11661 /* IPv4 Multicast Mode */
11662 install_element(BGP_IPV4M_NODE
, &bgp_damp_set_cmd
);
11663 install_element(BGP_IPV4M_NODE
, &bgp_damp_unset_cmd
);
11665 /* Large Communities */
11666 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
11667 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
11669 /* show bgp ipv4 flowspec detailed */
11670 install_element(VIEW_NODE
, &show_ip_bgp_flowspec_routes_detailed_cmd
);
11674 void bgp_route_finish(void)
11679 FOREACH_AFI_SAFI (afi
, safi
) {
11680 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
11681 bgp_distance_table
[afi
][safi
] = NULL
;