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(LIB_ERR_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
;
4043 struct bgp_info
*ri
;
4045 /* look for neighbor in tables */
4046 if ((table
= rn
->info
) == NULL
)
4049 for (rm
= bgp_table_top(table
); rm
;
4050 rm
= bgp_route_next(rm
))
4051 for (ri
= rm
->info
; ri
; ri
= ri
->next
) {
4052 if (ri
->peer
!= peer
)
4054 if (!CHECK_FLAG(ri
->flags
,
4058 bgp_rib_remove(rm
, ri
, peer
, afi
, safi
);
4063 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4064 rn
= bgp_route_next(rn
))
4065 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
4066 if (ri
->peer
!= peer
)
4068 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
))
4070 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
4076 static void bgp_cleanup_table(struct bgp
*bgp
, struct bgp_table
*table
,
4079 struct bgp_node
*rn
;
4080 struct bgp_info
*ri
;
4081 struct bgp_info
*next
;
4083 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
4084 for (ri
= rn
->info
; ri
; ri
= next
) {
4086 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)
4087 && ri
->type
== ZEBRA_ROUTE_BGP
4088 && (ri
->sub_type
== BGP_ROUTE_NORMAL
4089 || ri
->sub_type
== BGP_ROUTE_AGGREGATE
4090 || ri
->sub_type
== BGP_ROUTE_IMPORTED
)) {
4092 if (bgp_fibupd_safi(safi
))
4093 bgp_zebra_withdraw(&rn
->p
, ri
,
4095 bgp_info_reap(rn
, ri
);
4100 /* Delete all kernel routes. */
4101 void bgp_cleanup_routes(struct bgp
*bgp
)
4104 struct bgp_node
*rn
;
4106 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
4107 if (afi
== AFI_L2VPN
)
4109 bgp_cleanup_table(bgp
, bgp
->rib
[afi
][SAFI_UNICAST
],
4112 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
4114 if (afi
!= AFI_L2VPN
) {
4116 safi
= SAFI_MPLS_VPN
;
4117 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4118 rn
= bgp_route_next(rn
)) {
4120 bgp_cleanup_table(bgp
,
4121 (struct bgp_table
*)(rn
->info
),
4123 bgp_table_finish((struct bgp_table
**)&(
4126 bgp_unlock_node(rn
);
4130 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4131 rn
= bgp_route_next(rn
)) {
4133 bgp_cleanup_table(bgp
,
4134 (struct bgp_table
*)(rn
->info
),
4136 bgp_table_finish((struct bgp_table
**)&(
4139 bgp_unlock_node(rn
);
4144 for (rn
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); rn
;
4145 rn
= bgp_route_next(rn
)) {
4147 bgp_cleanup_table(bgp
,
4148 (struct bgp_table
*)(rn
->info
),
4150 bgp_table_finish((struct bgp_table
**)&(rn
->info
));
4152 bgp_unlock_node(rn
);
4157 void bgp_reset(void)
4160 bgp_zclient_reset();
4161 access_list_reset();
4162 prefix_list_reset();
4165 static int bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
4167 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
4168 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
4169 PEER_CAP_ADDPATH_AF_TX_RCV
));
4172 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
4174 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
4175 struct bgp_nlri
*packet
)
4184 int addpath_encoded
;
4185 uint32_t addpath_id
;
4188 lim
= pnt
+ packet
->length
;
4190 safi
= packet
->safi
;
4192 addpath_encoded
= bgp_addpath_encode_rx(peer
, afi
, safi
);
4194 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
4195 syntactic validity. If the field is syntactically incorrect,
4196 then the Error Subcode is set to Invalid Network Field. */
4197 for (; pnt
< lim
; pnt
+= psize
) {
4198 /* Clear prefix structure. */
4199 memset(&p
, 0, sizeof(struct prefix
));
4201 if (addpath_encoded
) {
4203 /* When packet overflow occurs return immediately. */
4204 if (pnt
+ BGP_ADDPATH_ID_LEN
> lim
)
4207 addpath_id
= ntohl(*((uint32_t *)pnt
));
4208 pnt
+= BGP_ADDPATH_ID_LEN
;
4211 /* Fetch prefix length. */
4212 p
.prefixlen
= *pnt
++;
4213 /* afi/safi validity already verified by caller,
4214 * bgp_update_receive */
4215 p
.family
= afi2family(afi
);
4217 /* Prefix length check. */
4218 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
4221 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
4222 peer
->host
, p
.prefixlen
, packet
->afi
);
4226 /* Packet size overflow check. */
4227 psize
= PSIZE(p
.prefixlen
);
4229 /* When packet overflow occur return immediately. */
4230 if (pnt
+ psize
> lim
) {
4233 "%s [Error] Update packet error (prefix length %d overflows packet)",
4234 peer
->host
, p
.prefixlen
);
4238 /* Defensive coding, double-check the psize fits in a struct
4240 if (psize
> (ssize_t
)sizeof(p
.u
)) {
4243 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
4244 peer
->host
, p
.prefixlen
, sizeof(p
.u
));
4248 /* Fetch prefix from NLRI packet. */
4249 memcpy(p
.u
.val
, pnt
, psize
);
4251 /* Check address. */
4252 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
4253 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
4254 /* From RFC4271 Section 6.3:
4256 * If a prefix in the NLRI field is semantically
4258 * (e.g., an unexpected multicast IP address),
4260 * be logged locally, and the prefix SHOULD be
4265 "%s: IPv4 unicast NLRI is multicast address %s, ignoring",
4266 peer
->host
, inet_ntoa(p
.u
.prefix4
));
4271 /* Check address. */
4272 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
4273 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4278 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
4280 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4285 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
4290 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
4292 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4299 /* Normal process. */
4301 ret
= bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
4302 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
4303 NULL
, NULL
, 0, 0, NULL
);
4305 ret
= bgp_withdraw(peer
, &p
, addpath_id
, attr
, afi
,
4306 safi
, ZEBRA_ROUTE_BGP
,
4307 BGP_ROUTE_NORMAL
, NULL
, NULL
, 0,
4310 /* Address family configuration mismatch or maximum-prefix count
4316 /* Packet length consistency check. */
4320 "%s [Error] Update packet error (prefix length mismatch with total length)",
4328 static struct bgp_static
*bgp_static_new(void)
4330 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
4333 static void bgp_static_free(struct bgp_static
*bgp_static
)
4335 if (bgp_static
->rmap
.name
)
4336 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
4337 if (bgp_static
->eth_s_id
)
4338 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
4339 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
4342 void bgp_static_update(struct bgp
*bgp
, struct prefix
*p
,
4343 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
4345 struct bgp_node
*rn
;
4346 struct bgp_info
*ri
;
4347 struct bgp_info
*new;
4348 struct bgp_info info
;
4350 struct attr
*attr_new
;
4353 int vnc_implicit_withdraw
= 0;
4360 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4362 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4364 attr
.nexthop
= bgp_static
->igpnexthop
;
4365 attr
.med
= bgp_static
->igpmetric
;
4366 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4368 if (bgp_static
->atomic
)
4369 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
4371 /* Store label index, if required. */
4372 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
4373 attr
.label_index
= bgp_static
->label_index
;
4374 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
4377 /* Apply route-map. */
4378 if (bgp_static
->rmap
.name
) {
4379 struct attr attr_tmp
= attr
;
4381 memset(&info
, 0, sizeof(struct bgp_info
));
4382 info
.peer
= bgp
->peer_self
;
4383 info
.attr
= &attr_tmp
;
4385 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4387 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
, &info
);
4389 bgp
->peer_self
->rmap_type
= 0;
4391 if (ret
== RMAP_DENYMATCH
) {
4392 /* Free uninterned attribute. */
4393 bgp_attr_flush(&attr_tmp
);
4395 /* Unintern original. */
4396 aspath_unintern(&attr
.aspath
);
4397 bgp_static_withdraw(bgp
, p
, afi
, safi
);
4401 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4402 bgp_attr_add_gshut_community(&attr_tmp
);
4404 attr_new
= bgp_attr_intern(&attr_tmp
);
4407 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4408 bgp_attr_add_gshut_community(&attr
);
4410 attr_new
= bgp_attr_intern(&attr
);
4413 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4414 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4415 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4419 if (attrhash_cmp(ri
->attr
, attr_new
)
4420 && !CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)
4421 && !bgp_flag_check(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
4422 bgp_unlock_node(rn
);
4423 bgp_attr_unintern(&attr_new
);
4424 aspath_unintern(&attr
.aspath
);
4427 /* The attribute is changed. */
4428 bgp_info_set_flag(rn
, ri
, BGP_INFO_ATTR_CHANGED
);
4430 /* Rewrite BGP route information. */
4431 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
))
4432 bgp_info_restore(rn
, ri
);
4434 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4436 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4437 && (safi
== SAFI_UNICAST
)) {
4438 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
4440 * Implicit withdraw case.
4441 * We have to do this before ri is
4444 ++vnc_implicit_withdraw
;
4445 vnc_import_bgp_del_route(bgp
, p
, ri
);
4446 vnc_import_bgp_exterior_del_route(
4451 bgp_attr_unintern(&ri
->attr
);
4452 ri
->attr
= attr_new
;
4453 ri
->uptime
= bgp_clock();
4455 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4456 && (safi
== SAFI_UNICAST
)) {
4457 if (vnc_implicit_withdraw
) {
4458 vnc_import_bgp_add_route(bgp
, p
, ri
);
4459 vnc_import_bgp_exterior_add_route(
4465 /* Nexthop reachability check. */
4466 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4467 && (safi
== SAFI_UNICAST
4468 || safi
== SAFI_LABELED_UNICAST
)) {
4470 struct bgp
*bgp_nexthop
= bgp
;
4472 if (ri
->extra
&& ri
->extra
->bgp_orig
)
4473 bgp_nexthop
= ri
->extra
->bgp_orig
;
4475 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
,
4477 bgp_info_set_flag(rn
, ri
,
4480 if (BGP_DEBUG(nht
, NHT
)) {
4481 char buf1
[INET6_ADDRSTRLEN
];
4482 inet_ntop(p
->family
,
4486 "%s(%s): Route not in table, not advertising",
4487 __FUNCTION__
, buf1
);
4489 bgp_info_unset_flag(rn
, ri
,
4493 /* Delete the NHT structure if any, if we're
4495 * enabling/disabling import check. We
4496 * deregister the route
4497 * from NHT to avoid overloading NHT and the
4498 * process interaction
4500 bgp_unlink_nexthop(ri
);
4501 bgp_info_set_flag(rn
, ri
, BGP_INFO_VALID
);
4503 /* Process change. */
4504 bgp_aggregate_increment(bgp
, p
, ri
, afi
, safi
);
4505 bgp_process(bgp
, rn
, afi
, safi
);
4507 if (SAFI_UNICAST
== safi
4508 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4510 == BGP_INSTANCE_TYPE_DEFAULT
)) {
4511 vpn_leak_from_vrf_update(bgp_get_default(), bgp
,
4515 bgp_unlock_node(rn
);
4516 aspath_unintern(&attr
.aspath
);
4521 /* Make new BGP info. */
4522 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
4524 /* Nexthop reachability check. */
4525 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4526 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
4527 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, new, NULL
, 0))
4528 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
4530 if (BGP_DEBUG(nht
, NHT
)) {
4531 char buf1
[INET6_ADDRSTRLEN
];
4532 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
4535 "%s(%s): Route not in table, not advertising",
4536 __FUNCTION__
, buf1
);
4538 bgp_info_unset_flag(rn
, new, BGP_INFO_VALID
);
4541 /* Delete the NHT structure if any, if we're toggling between
4542 * enabling/disabling import check. We deregister the route
4543 * from NHT to avoid overloading NHT and the process interaction
4545 bgp_unlink_nexthop(new);
4547 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
4550 /* Aggregate address increment. */
4551 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4553 /* Register new BGP information. */
4554 bgp_info_add(rn
, new);
4556 /* route_node_get lock */
4557 bgp_unlock_node(rn
);
4559 /* Process change. */
4560 bgp_process(bgp
, rn
, afi
, safi
);
4562 if (SAFI_UNICAST
== safi
4563 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4564 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4565 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
4568 /* Unintern original. */
4569 aspath_unintern(&attr
.aspath
);
4572 void bgp_static_withdraw(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
4575 struct bgp_node
*rn
;
4576 struct bgp_info
*ri
;
4578 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4580 /* Check selected route and self inserted route. */
4581 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4582 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4583 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4586 /* Withdraw static BGP route from routing table. */
4588 if (SAFI_UNICAST
== safi
4589 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4590 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4591 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, ri
);
4593 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4594 bgp_unlink_nexthop(ri
);
4595 bgp_info_delete(rn
, ri
);
4596 bgp_process(bgp
, rn
, afi
, safi
);
4599 /* Unlock bgp_node_lookup. */
4600 bgp_unlock_node(rn
);
4604 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
4606 static void bgp_static_withdraw_safi(struct bgp
*bgp
, struct prefix
*p
,
4607 afi_t afi
, safi_t safi
,
4608 struct prefix_rd
*prd
)
4610 struct bgp_node
*rn
;
4611 struct bgp_info
*ri
;
4613 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4615 /* Check selected route and self inserted route. */
4616 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4617 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4618 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4621 /* Withdraw static BGP route from routing table. */
4624 rfapiProcessWithdraw(
4625 ri
->peer
, NULL
, p
, prd
, ri
->attr
, afi
, safi
, ri
->type
,
4626 1); /* Kill, since it is an administrative change */
4628 if (SAFI_MPLS_VPN
== safi
4629 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4630 vpn_leak_to_vrf_withdraw(bgp
, ri
);
4632 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4633 bgp_info_delete(rn
, ri
);
4634 bgp_process(bgp
, rn
, afi
, safi
);
4637 /* Unlock bgp_node_lookup. */
4638 bgp_unlock_node(rn
);
4641 static void bgp_static_update_safi(struct bgp
*bgp
, struct prefix
*p
,
4642 struct bgp_static
*bgp_static
, afi_t afi
,
4645 struct bgp_node
*rn
;
4646 struct bgp_info
*new;
4647 struct attr
*attr_new
;
4648 struct attr attr
= {0};
4649 struct bgp_info
*ri
;
4651 mpls_label_t label
= 0;
4653 uint32_t num_labels
= 0;
4658 if (bgp_static
->label
!= MPLS_INVALID_LABEL
)
4660 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
4663 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4665 attr
.nexthop
= bgp_static
->igpnexthop
;
4666 attr
.med
= bgp_static
->igpmetric
;
4667 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4669 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
4670 || (safi
== SAFI_ENCAP
)) {
4671 if (afi
== AFI_IP
) {
4672 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
4673 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
4676 if (afi
== AFI_L2VPN
) {
4677 if (bgp_static
->gatewayIp
.family
== AF_INET
)
4679 bgp_static
->gatewayIp
.u
.prefix4
.s_addr
;
4680 else if (bgp_static
->gatewayIp
.family
== AF_INET6
)
4681 memcpy(&(add
.ipv6
), &(bgp_static
->gatewayIp
.u
.prefix6
),
4682 sizeof(struct in6_addr
));
4683 overlay_index_update(&attr
, bgp_static
->eth_s_id
, &add
);
4684 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
4685 struct bgp_encap_type_vxlan bet
;
4686 memset(&bet
, 0, sizeof(struct bgp_encap_type_vxlan
));
4687 bet
.vnid
= p
->u
.prefix_evpn
.prefix_addr
.eth_tag
;
4688 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
4690 if (bgp_static
->router_mac
) {
4691 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
4694 /* Apply route-map. */
4695 if (bgp_static
->rmap
.name
) {
4696 struct attr attr_tmp
= attr
;
4697 struct bgp_info info
;
4700 info
.peer
= bgp
->peer_self
;
4701 info
.attr
= &attr_tmp
;
4703 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4705 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
, &info
);
4707 bgp
->peer_self
->rmap_type
= 0;
4709 if (ret
== RMAP_DENYMATCH
) {
4710 /* Free uninterned attribute. */
4711 bgp_attr_flush(&attr_tmp
);
4713 /* Unintern original. */
4714 aspath_unintern(&attr
.aspath
);
4715 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
4720 attr_new
= bgp_attr_intern(&attr_tmp
);
4722 attr_new
= bgp_attr_intern(&attr
);
4725 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4726 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4727 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4732 memset(&add
, 0, sizeof(union gw_addr
));
4733 if (attrhash_cmp(ri
->attr
, attr_new
)
4734 && overlay_index_equal(afi
, ri
, bgp_static
->eth_s_id
, &add
)
4735 && !CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)) {
4736 bgp_unlock_node(rn
);
4737 bgp_attr_unintern(&attr_new
);
4738 aspath_unintern(&attr
.aspath
);
4741 /* The attribute is changed. */
4742 bgp_info_set_flag(rn
, ri
, BGP_INFO_ATTR_CHANGED
);
4744 /* Rewrite BGP route information. */
4745 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
))
4746 bgp_info_restore(rn
, ri
);
4748 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4749 bgp_attr_unintern(&ri
->attr
);
4750 ri
->attr
= attr_new
;
4751 ri
->uptime
= bgp_clock();
4754 label
= decode_label(&ri
->extra
->label
[0]);
4757 /* Process change. */
4758 bgp_aggregate_increment(bgp
, p
, ri
, afi
, safi
);
4759 bgp_process(bgp
, rn
, afi
, safi
);
4761 if (SAFI_MPLS_VPN
== safi
4762 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4763 vpn_leak_to_vrf_update(bgp
, ri
);
4766 rfapiProcessUpdate(ri
->peer
, NULL
, p
, &bgp_static
->prd
,
4767 ri
->attr
, afi
, safi
, ri
->type
,
4768 ri
->sub_type
, &label
);
4770 bgp_unlock_node(rn
);
4771 aspath_unintern(&attr
.aspath
);
4777 /* Make new BGP info. */
4778 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
4780 SET_FLAG(new->flags
, BGP_INFO_VALID
);
4781 new->extra
= bgp_info_extra_new();
4783 new->extra
->label
[0] = bgp_static
->label
;
4784 new->extra
->num_labels
= num_labels
;
4787 label
= decode_label(&bgp_static
->label
);
4790 /* Aggregate address increment. */
4791 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4793 /* Register new BGP information. */
4794 bgp_info_add(rn
, new);
4795 /* route_node_get lock */
4796 bgp_unlock_node(rn
);
4798 /* Process change. */
4799 bgp_process(bgp
, rn
, afi
, safi
);
4801 if (SAFI_MPLS_VPN
== safi
4802 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4803 vpn_leak_to_vrf_update(bgp
, new);
4806 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
4807 safi
, new->type
, new->sub_type
, &label
);
4810 /* Unintern original. */
4811 aspath_unintern(&attr
.aspath
);
4814 /* Configure static BGP network. When user don't run zebra, static
4815 route should be installed as valid. */
4816 static int bgp_static_set(struct vty
*vty
, const char *negate
,
4817 const char *ip_str
, afi_t afi
, safi_t safi
,
4818 const char *rmap
, int backdoor
, uint32_t label_index
)
4820 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
4823 struct bgp_static
*bgp_static
;
4824 struct bgp_node
*rn
;
4825 uint8_t need_update
= 0;
4827 /* Convert IP prefix string to struct prefix. */
4828 ret
= str2prefix(ip_str
, &p
);
4830 vty_out(vty
, "%% Malformed prefix\n");
4831 return CMD_WARNING_CONFIG_FAILED
;
4833 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4834 vty_out(vty
, "%% Malformed prefix (link-local address)\n");
4835 return CMD_WARNING_CONFIG_FAILED
;
4842 /* Set BGP static route configuration. */
4843 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
4846 vty_out(vty
, "%% Can't find static route specified\n");
4847 return CMD_WARNING_CONFIG_FAILED
;
4850 bgp_static
= rn
->info
;
4852 if ((label_index
!= BGP_INVALID_LABEL_INDEX
)
4853 && (label_index
!= bgp_static
->label_index
)) {
4855 "%% label-index doesn't match static route\n");
4856 return CMD_WARNING_CONFIG_FAILED
;
4859 if ((rmap
&& bgp_static
->rmap
.name
)
4860 && strcmp(rmap
, bgp_static
->rmap
.name
)) {
4862 "%% route-map name doesn't match static route\n");
4863 return CMD_WARNING_CONFIG_FAILED
;
4866 /* Update BGP RIB. */
4867 if (!bgp_static
->backdoor
)
4868 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
4870 /* Clear configuration. */
4871 bgp_static_free(bgp_static
);
4873 bgp_unlock_node(rn
);
4874 bgp_unlock_node(rn
);
4877 /* Set BGP static route configuration. */
4878 rn
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
4881 /* Configuration change. */
4882 bgp_static
= rn
->info
;
4884 /* Label index cannot be changed. */
4885 if (bgp_static
->label_index
!= label_index
) {
4886 vty_out(vty
, "%% cannot change label-index\n");
4887 return CMD_WARNING_CONFIG_FAILED
;
4890 /* Check previous routes are installed into BGP. */
4891 if (bgp_static
->valid
4892 && bgp_static
->backdoor
!= backdoor
)
4895 bgp_static
->backdoor
= backdoor
;
4898 if (bgp_static
->rmap
.name
)
4899 XFREE(MTYPE_ROUTE_MAP_NAME
,
4900 bgp_static
->rmap
.name
);
4901 bgp_static
->rmap
.name
=
4902 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
4903 bgp_static
->rmap
.map
=
4904 route_map_lookup_by_name(rmap
);
4906 if (bgp_static
->rmap
.name
)
4907 XFREE(MTYPE_ROUTE_MAP_NAME
,
4908 bgp_static
->rmap
.name
);
4909 bgp_static
->rmap
.name
= NULL
;
4910 bgp_static
->rmap
.map
= NULL
;
4911 bgp_static
->valid
= 0;
4913 bgp_unlock_node(rn
);
4915 /* New configuration. */
4916 bgp_static
= bgp_static_new();
4917 bgp_static
->backdoor
= backdoor
;
4918 bgp_static
->valid
= 0;
4919 bgp_static
->igpmetric
= 0;
4920 bgp_static
->igpnexthop
.s_addr
= 0;
4921 bgp_static
->label_index
= label_index
;
4924 if (bgp_static
->rmap
.name
)
4925 XFREE(MTYPE_ROUTE_MAP_NAME
,
4926 bgp_static
->rmap
.name
);
4927 bgp_static
->rmap
.name
=
4928 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
4929 bgp_static
->rmap
.map
=
4930 route_map_lookup_by_name(rmap
);
4932 rn
->info
= bgp_static
;
4935 bgp_static
->valid
= 1;
4937 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
4939 if (!bgp_static
->backdoor
)
4940 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
4946 void bgp_static_add(struct bgp
*bgp
)
4950 struct bgp_node
*rn
;
4951 struct bgp_node
*rm
;
4952 struct bgp_table
*table
;
4953 struct bgp_static
*bgp_static
;
4955 FOREACH_AFI_SAFI (afi
, safi
)
4956 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
4957 rn
= bgp_route_next(rn
)) {
4958 if (rn
->info
== NULL
)
4961 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
4962 || (safi
== SAFI_EVPN
)) {
4965 for (rm
= bgp_table_top(table
); rm
;
4966 rm
= bgp_route_next(rm
)) {
4967 bgp_static
= rm
->info
;
4968 bgp_static_update_safi(bgp
, &rm
->p
,
4973 bgp_static_update(bgp
, &rn
->p
, rn
->info
, afi
,
4979 /* Called from bgp_delete(). Delete all static routes from the BGP
4981 void bgp_static_delete(struct bgp
*bgp
)
4985 struct bgp_node
*rn
;
4986 struct bgp_node
*rm
;
4987 struct bgp_table
*table
;
4988 struct bgp_static
*bgp_static
;
4990 FOREACH_AFI_SAFI (afi
, safi
)
4991 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
4992 rn
= bgp_route_next(rn
)) {
4993 if (rn
->info
== NULL
)
4996 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
4997 || (safi
== SAFI_EVPN
)) {
5000 for (rm
= bgp_table_top(table
); rm
;
5001 rm
= bgp_route_next(rm
)) {
5002 bgp_static
= rm
->info
;
5003 bgp_static_withdraw_safi(
5004 bgp
, &rm
->p
, AFI_IP
, safi
,
5005 (struct prefix_rd
*)&rn
->p
);
5006 bgp_static_free(bgp_static
);
5008 bgp_unlock_node(rn
);
5011 bgp_static
= rn
->info
;
5012 bgp_static_withdraw(bgp
, &rn
->p
, afi
, safi
);
5013 bgp_static_free(bgp_static
);
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
)) {
5043 bgp_static
= rm
->info
;
5044 bgp_static_update_safi(bgp
, &rm
->p
,
5049 bgp_static
= rn
->info
;
5050 bgp_static_update(bgp
, &rn
->p
, bgp_static
, afi
,
5055 bgp_flag_unset(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5058 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
5061 struct bgp_table
*table
;
5062 struct bgp_node
*rn
;
5063 struct bgp_info
*ri
;
5065 table
= bgp
->rib
[afi
][safi
];
5066 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
5067 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
5068 if (ri
->peer
== bgp
->peer_self
5069 && ((ri
->type
== ZEBRA_ROUTE_BGP
5070 && ri
->sub_type
== BGP_ROUTE_STATIC
)
5071 || (ri
->type
!= ZEBRA_ROUTE_BGP
5073 == BGP_ROUTE_REDISTRIBUTE
))) {
5074 bgp_aggregate_decrement(bgp
, &rn
->p
, ri
, afi
,
5076 bgp_unlink_nexthop(ri
);
5077 bgp_info_delete(rn
, ri
);
5078 bgp_process(bgp
, rn
, afi
, safi
);
5085 * Purge all networks and redistributed routes from routing table.
5086 * Invoked upon the instance going down.
5088 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
5093 FOREACH_AFI_SAFI (afi
, safi
)
5094 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
5099 * Currently this is used to set static routes for VPN and ENCAP.
5100 * I think it can probably be factored with bgp_static_set.
5102 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5103 const char *ip_str
, const char *rd_str
,
5104 const char *label_str
, const char *rmap_str
,
5105 int evpn_type
, const char *esi
, const char *gwip
,
5106 const char *ethtag
, const char *routermac
)
5108 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5111 struct prefix_rd prd
;
5112 struct bgp_node
*prn
;
5113 struct bgp_node
*rn
;
5114 struct bgp_table
*table
;
5115 struct bgp_static
*bgp_static
;
5116 mpls_label_t label
= MPLS_INVALID_LABEL
;
5117 struct prefix gw_ip
;
5119 /* validate ip prefix */
5120 ret
= str2prefix(ip_str
, &p
);
5122 vty_out(vty
, "%% Malformed prefix\n");
5123 return CMD_WARNING_CONFIG_FAILED
;
5126 if ((afi
== AFI_L2VPN
)
5127 && (bgp_build_evpn_prefix(evpn_type
,
5128 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5129 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5130 return CMD_WARNING_CONFIG_FAILED
;
5133 ret
= str2prefix_rd(rd_str
, &prd
);
5135 vty_out(vty
, "%% Malformed rd\n");
5136 return CMD_WARNING_CONFIG_FAILED
;
5140 unsigned long label_val
;
5141 label_val
= strtoul(label_str
, NULL
, 10);
5142 encode_label(label_val
, &label
);
5145 if (safi
== SAFI_EVPN
) {
5146 if (esi
&& str2esi(esi
, NULL
) == 0) {
5147 vty_out(vty
, "%% Malformed ESI\n");
5148 return CMD_WARNING_CONFIG_FAILED
;
5150 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
5151 vty_out(vty
, "%% Malformed Router MAC\n");
5152 return CMD_WARNING_CONFIG_FAILED
;
5155 memset(&gw_ip
, 0, sizeof(struct prefix
));
5156 ret
= str2prefix(gwip
, &gw_ip
);
5158 vty_out(vty
, "%% Malformed GatewayIp\n");
5159 return CMD_WARNING_CONFIG_FAILED
;
5161 if ((gw_ip
.family
== AF_INET
5162 && is_evpn_prefix_ipaddr_v6(
5163 (struct prefix_evpn
*)&p
))
5164 || (gw_ip
.family
== AF_INET6
5165 && is_evpn_prefix_ipaddr_v4(
5166 (struct prefix_evpn
*)&p
))) {
5168 "%% GatewayIp family differs with IP prefix\n");
5169 return CMD_WARNING_CONFIG_FAILED
;
5173 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5174 if (prn
->info
== NULL
)
5175 prn
->info
= bgp_table_init(bgp
, afi
, safi
);
5177 bgp_unlock_node(prn
);
5180 rn
= bgp_node_get(table
, &p
);
5183 vty_out(vty
, "%% Same network configuration exists\n");
5184 bgp_unlock_node(rn
);
5186 /* New configuration. */
5187 bgp_static
= bgp_static_new();
5188 bgp_static
->backdoor
= 0;
5189 bgp_static
->valid
= 0;
5190 bgp_static
->igpmetric
= 0;
5191 bgp_static
->igpnexthop
.s_addr
= 0;
5192 bgp_static
->label
= label
;
5193 bgp_static
->prd
= prd
;
5196 if (bgp_static
->rmap
.name
)
5197 XFREE(MTYPE_ROUTE_MAP_NAME
,
5198 bgp_static
->rmap
.name
);
5199 bgp_static
->rmap
.name
=
5200 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
5201 bgp_static
->rmap
.map
=
5202 route_map_lookup_by_name(rmap_str
);
5205 if (safi
== SAFI_EVPN
) {
5207 bgp_static
->eth_s_id
=
5209 sizeof(struct eth_segment_id
));
5210 str2esi(esi
, bgp_static
->eth_s_id
);
5213 bgp_static
->router_mac
=
5214 XCALLOC(MTYPE_ATTR
, ETH_ALEN
+ 1);
5215 (void)prefix_str2mac(routermac
,
5216 bgp_static
->router_mac
);
5219 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
5221 rn
->info
= bgp_static
;
5223 bgp_static
->valid
= 1;
5224 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
5230 /* Configure static BGP network. */
5231 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5232 const char *ip_str
, const char *rd_str
,
5233 const char *label_str
, int evpn_type
, const char *esi
,
5234 const char *gwip
, const char *ethtag
)
5236 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5239 struct prefix_rd prd
;
5240 struct bgp_node
*prn
;
5241 struct bgp_node
*rn
;
5242 struct bgp_table
*table
;
5243 struct bgp_static
*bgp_static
;
5244 mpls_label_t label
= MPLS_INVALID_LABEL
;
5246 /* Convert IP prefix string to struct prefix. */
5247 ret
= str2prefix(ip_str
, &p
);
5249 vty_out(vty
, "%% Malformed prefix\n");
5250 return CMD_WARNING_CONFIG_FAILED
;
5253 if ((afi
== AFI_L2VPN
)
5254 && (bgp_build_evpn_prefix(evpn_type
,
5255 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5256 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5257 return CMD_WARNING_CONFIG_FAILED
;
5259 ret
= str2prefix_rd(rd_str
, &prd
);
5261 vty_out(vty
, "%% Malformed rd\n");
5262 return CMD_WARNING_CONFIG_FAILED
;
5266 unsigned long label_val
;
5267 label_val
= strtoul(label_str
, NULL
, 10);
5268 encode_label(label_val
, &label
);
5271 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5272 if (prn
->info
== NULL
)
5273 prn
->info
= bgp_table_init(bgp
, afi
, safi
);
5275 bgp_unlock_node(prn
);
5278 rn
= bgp_node_lookup(table
, &p
);
5281 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
5283 bgp_static
= rn
->info
;
5284 bgp_static_free(bgp_static
);
5286 bgp_unlock_node(rn
);
5287 bgp_unlock_node(rn
);
5289 vty_out(vty
, "%% Can't find the route\n");
5294 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
5295 const char *rmap_name
)
5297 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5298 struct bgp_rmap
*rmap
;
5300 rmap
= &bgp
->table_map
[afi
][safi
];
5303 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5304 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
5305 rmap
->map
= route_map_lookup_by_name(rmap_name
);
5308 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5313 if (bgp_fibupd_safi(safi
))
5314 bgp_zebra_announce_table(bgp
, afi
, safi
);
5319 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
5320 const char *rmap_name
)
5322 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5323 struct bgp_rmap
*rmap
;
5325 rmap
= &bgp
->table_map
[afi
][safi
];
5327 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5331 if (bgp_fibupd_safi(safi
))
5332 bgp_zebra_announce_table(bgp
, afi
, safi
);
5337 void bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
5340 if (bgp
->table_map
[afi
][safi
].name
) {
5341 vty_out(vty
, " table-map %s\n",
5342 bgp
->table_map
[afi
][safi
].name
);
5346 DEFUN (bgp_table_map
,
5349 "BGP table to RIB route download filter\n"
5350 "Name of the route map\n")
5353 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5354 argv
[idx_word
]->arg
);
5356 DEFUN (no_bgp_table_map
,
5357 no_bgp_table_map_cmd
,
5358 "no table-map WORD",
5360 "BGP table to RIB route download filter\n"
5361 "Name of the route map\n")
5364 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5365 argv
[idx_word
]->arg
);
5371 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
5372 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
5373 backdoor$backdoor}]",
5375 "Specify a network to announce via BGP\n"
5380 "Route-map to modify the attributes\n"
5381 "Name of the route map\n"
5382 "Label index to associate with the prefix\n"
5383 "Label index value\n"
5384 "Specify a BGP backdoor route\n")
5386 char addr_prefix_str
[BUFSIZ
];
5391 ret
= netmask_str2prefix_str(address_str
, netmask_str
,
5394 vty_out(vty
, "%% Inconsistent address and mask\n");
5395 return CMD_WARNING_CONFIG_FAILED
;
5399 return bgp_static_set(
5400 vty
, no
, address_str
? addr_prefix_str
: prefix_str
, AFI_IP
,
5401 bgp_node_safi(vty
), map_name
, backdoor
? 1 : 0,
5402 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5405 DEFPY(ipv6_bgp_network
,
5406 ipv6_bgp_network_cmd
,
5407 "[no] network X:X::X:X/M$prefix \
5408 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
5410 "Specify a network to announce via BGP\n"
5412 "Route-map to modify the attributes\n"
5413 "Name of the route map\n"
5414 "Label index to associate with the prefix\n"
5415 "Label index value\n")
5417 return bgp_static_set(
5418 vty
, no
, prefix_str
, AFI_IP6
, bgp_node_safi(vty
), map_name
, 0,
5419 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5422 /* Aggreagete address:
5424 advertise-map Set condition to advertise attribute
5425 as-set Generate AS set path information
5426 attribute-map Set attributes of aggregate
5427 route-map Set parameters of aggregate
5428 summary-only Filter more specific routes from updates
5429 suppress-map Conditionally filter more specific routes from updates
5432 struct bgp_aggregate
{
5433 /* Summary-only flag. */
5434 uint8_t summary_only
;
5436 /* AS set generation. */
5439 /* Route-map for aggregated route. */
5440 struct route_map
*map
;
5442 /* Suppress-count. */
5443 unsigned long count
;
5445 /* SAFI configuration. */
5449 static struct bgp_aggregate
*bgp_aggregate_new(void)
5451 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
5454 static void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
5456 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
5459 static int bgp_aggregate_info_same(struct bgp_info
*ri
, struct aspath
*aspath
,
5460 struct community
*comm
)
5462 static struct aspath
*ae
= NULL
;
5465 ae
= aspath_empty();
5470 if (!aspath_cmp(ri
->attr
->aspath
, (aspath
) ? aspath
: ae
))
5473 if (!community_cmp(ri
->attr
->community
, comm
))
5479 static void bgp_aggregate_install(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
5480 struct prefix
*p
, uint8_t origin
,
5481 struct aspath
*aspath
,
5482 struct community
*community
,
5483 uint8_t atomic_aggregate
,
5484 struct bgp_aggregate
*aggregate
)
5486 struct bgp_node
*rn
;
5487 struct bgp_table
*table
;
5488 struct bgp_info
*ri
, *new;
5490 table
= bgp
->rib
[afi
][safi
];
5492 rn
= bgp_node_get(table
, p
);
5494 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
5495 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
5496 && ri
->sub_type
== BGP_ROUTE_AGGREGATE
)
5499 if (aggregate
->count
> 0) {
5501 * If the aggregate information has not changed
5502 * no need to re-install it again.
5504 if (bgp_aggregate_info_same(rn
->info
, aspath
, community
)) {
5505 bgp_unlock_node(rn
);
5508 aspath_free(aspath
);
5510 community_free(community
);
5516 * Mark the old as unusable
5519 bgp_info_delete(rn
, ri
);
5522 ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0, bgp
->peer_self
,
5523 bgp_attr_aggregate_intern(bgp
, origin
, aspath
,
5524 community
, aggregate
->as_set
,
5527 SET_FLAG(new->flags
, BGP_INFO_VALID
);
5529 bgp_info_add(rn
, new);
5530 bgp_process(bgp
, rn
, afi
, safi
);
5532 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
5533 if (ri
->peer
== bgp
->peer_self
5534 && ri
->type
== ZEBRA_ROUTE_BGP
5535 && ri
->sub_type
== BGP_ROUTE_AGGREGATE
)
5538 /* Withdraw static BGP route from routing table. */
5540 bgp_info_delete(rn
, ri
);
5541 bgp_process(bgp
, rn
, afi
, safi
);
5545 bgp_unlock_node(rn
);
5548 /* Update an aggregate as routes are added/removed from the BGP table */
5549 static void bgp_aggregate_route(struct bgp
*bgp
, struct prefix
*p
,
5550 struct bgp_info
*rinew
, afi_t afi
, safi_t safi
,
5551 struct bgp_info
*del
,
5552 struct bgp_aggregate
*aggregate
)
5554 struct bgp_table
*table
;
5555 struct bgp_node
*top
;
5556 struct bgp_node
*rn
;
5558 struct aspath
*aspath
= NULL
;
5559 struct aspath
*asmerge
= NULL
;
5560 struct community
*community
= NULL
;
5561 struct community
*commerge
= NULL
;
5562 struct bgp_info
*ri
;
5563 unsigned long match
= 0;
5564 uint8_t atomic_aggregate
= 0;
5566 /* ORIGIN attribute: If at least one route among routes that are
5567 aggregated has ORIGIN with the value INCOMPLETE, then the
5568 aggregated route must have the ORIGIN attribute with the value
5569 INCOMPLETE. Otherwise, if at least one route among routes that
5570 are aggregated has ORIGIN with the value EGP, then the aggregated
5571 route must have the origin attribute with the value EGP. In all
5572 other case the value of the ORIGIN attribute of the aggregated
5573 route is INTERNAL. */
5574 origin
= BGP_ORIGIN_IGP
;
5576 table
= bgp
->rib
[afi
][safi
];
5578 top
= bgp_node_get(table
, p
);
5579 for (rn
= bgp_node_get(table
, p
); rn
;
5580 rn
= bgp_route_next_until(rn
, top
)) {
5581 if (rn
->p
.prefixlen
<= p
->prefixlen
)
5586 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
5587 if (BGP_INFO_HOLDDOWN(ri
))
5590 if (del
&& ri
== del
)
5594 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
5595 atomic_aggregate
= 1;
5597 if (ri
->sub_type
== BGP_ROUTE_AGGREGATE
)
5601 * summary-only aggregate route suppress
5602 * aggregated route announcements.
5604 if (aggregate
->summary_only
) {
5605 (bgp_info_extra_get(ri
))->suppress
++;
5606 bgp_info_set_flag(rn
, ri
,
5607 BGP_INFO_ATTR_CHANGED
);
5614 * If at least one route among routes that are
5615 * aggregated has ORIGIN with the value INCOMPLETE,
5616 * then the aggregated route MUST have the ORIGIN
5617 * attribute with the value INCOMPLETE. Otherwise, if
5618 * at least one route among routes that are aggregated
5619 * has ORIGIN with the value EGP, then the aggregated
5620 * route MUST have the ORIGIN attribute with the value
5623 if (origin
< ri
->attr
->origin
)
5624 origin
= ri
->attr
->origin
;
5626 if (!aggregate
->as_set
)
5630 * as-set aggregate route generate origin, as path,
5631 * and community aggregation.
5634 asmerge
= aspath_aggregate(aspath
,
5636 aspath_free(aspath
);
5639 aspath
= aspath_dup(ri
->attr
->aspath
);
5641 if (!ri
->attr
->community
)
5645 commerge
= community_merge(community
,
5646 ri
->attr
->community
);
5647 community
= community_uniq_sort(commerge
);
5648 community_free(commerge
);
5650 community
= community_dup(ri
->attr
->community
);
5653 bgp_process(bgp
, rn
, afi
, safi
);
5655 bgp_unlock_node(top
);
5660 if (aggregate
->summary_only
)
5661 (bgp_info_extra_get(rinew
))->suppress
++;
5663 if (origin
< rinew
->attr
->origin
)
5664 origin
= rinew
->attr
->origin
;
5666 if (aggregate
->as_set
) {
5668 asmerge
= aspath_aggregate(aspath
,
5669 rinew
->attr
->aspath
);
5670 aspath_free(aspath
);
5673 aspath
= aspath_dup(rinew
->attr
->aspath
);
5675 if (rinew
->attr
->community
) {
5677 commerge
= community_merge(
5679 rinew
->attr
->community
);
5681 community_uniq_sort(commerge
);
5682 community_free(commerge
);
5684 community
= community_dup(
5685 rinew
->attr
->community
);
5690 bgp_aggregate_install(bgp
, afi
, safi
, p
, origin
, aspath
, community
,
5691 atomic_aggregate
, aggregate
);
5693 if (aggregate
->count
== 0) {
5695 aspath_free(aspath
);
5697 community_free(community
);
5701 static void bgp_aggregate_delete(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
5702 safi_t safi
, struct bgp_aggregate
*aggregate
)
5704 struct bgp_table
*table
;
5705 struct bgp_node
*top
;
5706 struct bgp_node
*rn
;
5707 struct bgp_info
*ri
;
5708 unsigned long match
;
5710 table
= bgp
->rib
[afi
][safi
];
5712 /* If routes exists below this node, generate aggregate routes. */
5713 top
= bgp_node_get(table
, p
);
5714 for (rn
= bgp_node_get(table
, p
); rn
;
5715 rn
= bgp_route_next_until(rn
, top
)) {
5716 if (rn
->p
.prefixlen
<= p
->prefixlen
)
5720 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
5721 if (BGP_INFO_HOLDDOWN(ri
))
5724 if (ri
->sub_type
== BGP_ROUTE_AGGREGATE
)
5727 if (aggregate
->summary_only
&& ri
->extra
) {
5728 ri
->extra
->suppress
--;
5730 if (ri
->extra
->suppress
== 0) {
5732 rn
, ri
, BGP_INFO_ATTR_CHANGED
);
5739 /* If this node was suppressed, process the change. */
5741 bgp_process(bgp
, rn
, afi
, safi
);
5743 bgp_unlock_node(top
);
5746 void bgp_aggregate_increment(struct bgp
*bgp
, struct prefix
*p
,
5747 struct bgp_info
*ri
, afi_t afi
, safi_t safi
)
5749 struct bgp_node
*child
;
5750 struct bgp_node
*rn
;
5751 struct bgp_aggregate
*aggregate
;
5752 struct bgp_table
*table
;
5754 table
= bgp
->aggregate
[afi
][safi
];
5756 /* No aggregates configured. */
5757 if (bgp_table_top_nolock(table
) == NULL
)
5760 if (p
->prefixlen
== 0)
5763 if (BGP_INFO_HOLDDOWN(ri
))
5766 child
= bgp_node_get(table
, p
);
5768 /* Aggregate address configuration check. */
5769 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
))
5770 if ((aggregate
= rn
->info
) != NULL
5771 && rn
->p
.prefixlen
< p
->prefixlen
) {
5772 bgp_aggregate_delete(bgp
, &rn
->p
, afi
, safi
, aggregate
);
5773 bgp_aggregate_route(bgp
, &rn
->p
, ri
, afi
, safi
, NULL
,
5776 bgp_unlock_node(child
);
5779 void bgp_aggregate_decrement(struct bgp
*bgp
, struct prefix
*p
,
5780 struct bgp_info
*del
, afi_t afi
, safi_t safi
)
5782 struct bgp_node
*child
;
5783 struct bgp_node
*rn
;
5784 struct bgp_aggregate
*aggregate
;
5785 struct bgp_table
*table
;
5787 table
= bgp
->aggregate
[afi
][safi
];
5789 /* No aggregates configured. */
5790 if (bgp_table_top_nolock(table
) == NULL
)
5793 if (p
->prefixlen
== 0)
5796 child
= bgp_node_get(table
, p
);
5798 /* Aggregate address configuration check. */
5799 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
))
5800 if ((aggregate
= rn
->info
) != NULL
5801 && rn
->p
.prefixlen
< p
->prefixlen
) {
5802 bgp_aggregate_delete(bgp
, &rn
->p
, afi
, safi
, aggregate
);
5803 bgp_aggregate_route(bgp
, &rn
->p
, NULL
, afi
, safi
, del
,
5806 bgp_unlock_node(child
);
5809 /* Aggregate route attribute. */
5810 #define AGGREGATE_SUMMARY_ONLY 1
5811 #define AGGREGATE_AS_SET 1
5813 static int bgp_aggregate_unset(struct vty
*vty
, const char *prefix_str
,
5814 afi_t afi
, safi_t safi
)
5816 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5819 struct bgp_node
*rn
;
5820 struct bgp_aggregate
*aggregate
;
5822 /* Convert string to prefix structure. */
5823 ret
= str2prefix(prefix_str
, &p
);
5825 vty_out(vty
, "Malformed prefix\n");
5826 return CMD_WARNING_CONFIG_FAILED
;
5830 /* Old configuration check. */
5831 rn
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], &p
);
5834 "%% There is no aggregate-address configuration.\n");
5835 return CMD_WARNING_CONFIG_FAILED
;
5838 aggregate
= rn
->info
;
5839 bgp_aggregate_delete(bgp
, &p
, afi
, safi
, aggregate
);
5840 bgp_aggregate_install(bgp
, afi
, safi
, &p
, 0, NULL
, NULL
, 0, aggregate
);
5842 /* Unlock aggregate address configuration. */
5844 bgp_aggregate_free(aggregate
);
5845 bgp_unlock_node(rn
);
5846 bgp_unlock_node(rn
);
5851 static int bgp_aggregate_set(struct vty
*vty
, const char *prefix_str
, afi_t afi
,
5852 safi_t safi
, uint8_t summary_only
, uint8_t as_set
)
5854 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5857 struct bgp_node
*rn
;
5858 struct bgp_aggregate
*aggregate
;
5860 /* Convert string to prefix structure. */
5861 ret
= str2prefix(prefix_str
, &p
);
5863 vty_out(vty
, "Malformed prefix\n");
5864 return CMD_WARNING_CONFIG_FAILED
;
5868 if ((afi
== AFI_IP
&& p
.prefixlen
== IPV4_MAX_BITLEN
) ||
5869 (afi
== AFI_IP6
&& p
.prefixlen
== IPV6_MAX_BITLEN
)) {
5870 vty_out(vty
, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
5872 return CMD_WARNING_CONFIG_FAILED
;
5875 /* Old configuration check. */
5876 rn
= bgp_node_get(bgp
->aggregate
[afi
][safi
], &p
);
5879 vty_out(vty
, "There is already same aggregate network.\n");
5880 /* try to remove the old entry */
5881 ret
= bgp_aggregate_unset(vty
, prefix_str
, afi
, safi
);
5883 vty_out(vty
, "Error deleting aggregate.\n");
5884 bgp_unlock_node(rn
);
5885 return CMD_WARNING_CONFIG_FAILED
;
5889 /* Make aggregate address structure. */
5890 aggregate
= bgp_aggregate_new();
5891 aggregate
->summary_only
= summary_only
;
5892 aggregate
->as_set
= as_set
;
5893 aggregate
->safi
= safi
;
5894 rn
->info
= aggregate
;
5896 /* Aggregate address insert into BGP routing table. */
5897 bgp_aggregate_route(bgp
, &p
, NULL
, afi
, safi
, NULL
, aggregate
);
5902 DEFUN (aggregate_address
,
5903 aggregate_address_cmd
,
5904 "aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
5905 "Configure BGP aggregate entries\n"
5906 "Aggregate prefix\n"
5907 "Generate AS set path information\n"
5908 "Filter more specific routes from updates\n"
5909 "Filter more specific routes from updates\n"
5910 "Generate AS set path information\n")
5913 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
5914 char *prefix
= argv
[idx
]->arg
;
5916 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
5918 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
5919 ? AGGREGATE_SUMMARY_ONLY
5922 return bgp_aggregate_set(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
),
5923 summary_only
, as_set
);
5926 DEFUN (aggregate_address_mask
,
5927 aggregate_address_mask_cmd
,
5928 "aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
5929 "Configure BGP aggregate entries\n"
5930 "Aggregate address\n"
5932 "Generate AS set path information\n"
5933 "Filter more specific routes from updates\n"
5934 "Filter more specific routes from updates\n"
5935 "Generate AS set path information\n")
5938 argv_find(argv
, argc
, "A.B.C.D", &idx
);
5939 char *prefix
= argv
[idx
]->arg
;
5940 char *mask
= argv
[idx
+ 1]->arg
;
5942 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
5944 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
5945 ? AGGREGATE_SUMMARY_ONLY
5948 char prefix_str
[BUFSIZ
];
5949 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
5952 vty_out(vty
, "%% Inconsistent address and mask\n");
5953 return CMD_WARNING_CONFIG_FAILED
;
5956 return bgp_aggregate_set(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
),
5957 summary_only
, as_set
);
5960 DEFUN (no_aggregate_address
,
5961 no_aggregate_address_cmd
,
5962 "no aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
5964 "Configure BGP aggregate entries\n"
5965 "Aggregate prefix\n"
5966 "Generate AS set path information\n"
5967 "Filter more specific routes from updates\n"
5968 "Filter more specific routes from updates\n"
5969 "Generate AS set path information\n")
5972 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
5973 char *prefix
= argv
[idx
]->arg
;
5974 return bgp_aggregate_unset(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
));
5977 DEFUN (no_aggregate_address_mask
,
5978 no_aggregate_address_mask_cmd
,
5979 "no aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
5981 "Configure BGP aggregate entries\n"
5982 "Aggregate address\n"
5984 "Generate AS set path information\n"
5985 "Filter more specific routes from updates\n"
5986 "Filter more specific routes from updates\n"
5987 "Generate AS set path information\n")
5990 argv_find(argv
, argc
, "A.B.C.D", &idx
);
5991 char *prefix
= argv
[idx
]->arg
;
5992 char *mask
= argv
[idx
+ 1]->arg
;
5994 char prefix_str
[BUFSIZ
];
5995 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
5998 vty_out(vty
, "%% Inconsistent address and mask\n");
5999 return CMD_WARNING_CONFIG_FAILED
;
6002 return bgp_aggregate_unset(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
));
6005 DEFUN (ipv6_aggregate_address
,
6006 ipv6_aggregate_address_cmd
,
6007 "aggregate-address X:X::X:X/M [summary-only]",
6008 "Configure BGP aggregate entries\n"
6009 "Aggregate prefix\n"
6010 "Filter more specific routes from updates\n")
6013 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6014 char *prefix
= argv
[idx
]->arg
;
6015 int sum_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6016 ? AGGREGATE_SUMMARY_ONLY
6018 return bgp_aggregate_set(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
, sum_only
,
6022 DEFUN (no_ipv6_aggregate_address
,
6023 no_ipv6_aggregate_address_cmd
,
6024 "no aggregate-address X:X::X:X/M [summary-only]",
6026 "Configure BGP aggregate entries\n"
6027 "Aggregate prefix\n"
6028 "Filter more specific routes from updates\n")
6031 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6032 char *prefix
= argv
[idx
]->arg
;
6033 return bgp_aggregate_unset(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
);
6036 /* Redistribute route treatment. */
6037 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
6038 const union g_addr
*nexthop
, ifindex_t ifindex
,
6039 enum nexthop_types_t nhtype
, uint32_t metric
,
6040 uint8_t type
, unsigned short instance
,
6043 struct bgp_info
*new;
6044 struct bgp_info
*bi
;
6045 struct bgp_info info
;
6046 struct bgp_node
*bn
;
6048 struct attr
*new_attr
;
6051 struct bgp_redist
*red
;
6053 /* Make default attribute. */
6054 bgp_attr_default_set(&attr
, BGP_ORIGIN_INCOMPLETE
);
6057 case NEXTHOP_TYPE_IFINDEX
:
6059 case NEXTHOP_TYPE_IPV4
:
6060 case NEXTHOP_TYPE_IPV4_IFINDEX
:
6061 attr
.nexthop
= nexthop
->ipv4
;
6063 case NEXTHOP_TYPE_IPV6
:
6064 case NEXTHOP_TYPE_IPV6_IFINDEX
:
6065 attr
.mp_nexthop_global
= nexthop
->ipv6
;
6066 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6068 case NEXTHOP_TYPE_BLACKHOLE
:
6069 switch (p
->family
) {
6071 attr
.nexthop
.s_addr
= INADDR_ANY
;
6074 memset(&attr
.mp_nexthop_global
, 0,
6075 sizeof(attr
.mp_nexthop_global
));
6076 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6081 attr
.nh_ifindex
= ifindex
;
6084 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6087 afi
= family2afi(p
->family
);
6089 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6091 struct attr attr_new
;
6093 /* Copy attribute for modification. */
6094 bgp_attr_dup(&attr_new
, &attr
);
6096 if (red
->redist_metric_flag
)
6097 attr_new
.med
= red
->redist_metric
;
6099 /* Apply route-map. */
6100 if (red
->rmap
.name
) {
6101 memset(&info
, 0, sizeof(struct bgp_info
));
6102 info
.peer
= bgp
->peer_self
;
6103 info
.attr
= &attr_new
;
6105 SET_FLAG(bgp
->peer_self
->rmap_type
,
6106 PEER_RMAP_TYPE_REDISTRIBUTE
);
6108 ret
= route_map_apply(red
->rmap
.map
, p
, RMAP_BGP
,
6111 bgp
->peer_self
->rmap_type
= 0;
6113 if (ret
== RMAP_DENYMATCH
) {
6114 /* Free uninterned attribute. */
6115 bgp_attr_flush(&attr_new
);
6117 /* Unintern original. */
6118 aspath_unintern(&attr
.aspath
);
6119 bgp_redistribute_delete(bgp
, p
, type
, instance
);
6124 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
6125 bgp_attr_add_gshut_community(&attr_new
);
6127 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6128 SAFI_UNICAST
, p
, NULL
);
6130 new_attr
= bgp_attr_intern(&attr_new
);
6132 for (bi
= bn
->info
; bi
; bi
= bi
->next
)
6133 if (bi
->peer
== bgp
->peer_self
6134 && bi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
6138 /* Ensure the (source route) type is updated. */
6140 if (attrhash_cmp(bi
->attr
, new_attr
)
6141 && !CHECK_FLAG(bi
->flags
, BGP_INFO_REMOVED
)) {
6142 bgp_attr_unintern(&new_attr
);
6143 aspath_unintern(&attr
.aspath
);
6144 bgp_unlock_node(bn
);
6147 /* The attribute is changed. */
6148 bgp_info_set_flag(bn
, bi
,
6149 BGP_INFO_ATTR_CHANGED
);
6151 /* Rewrite BGP route information. */
6152 if (CHECK_FLAG(bi
->flags
, BGP_INFO_REMOVED
))
6153 bgp_info_restore(bn
, bi
);
6155 bgp_aggregate_decrement(bgp
, p
, bi
, afi
,
6157 bgp_attr_unintern(&bi
->attr
);
6158 bi
->attr
= new_attr
;
6159 bi
->uptime
= bgp_clock();
6161 /* Process change. */
6162 bgp_aggregate_increment(bgp
, p
, bi
, afi
,
6164 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6165 bgp_unlock_node(bn
);
6166 aspath_unintern(&attr
.aspath
);
6168 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6170 == BGP_INSTANCE_TYPE_DEFAULT
)) {
6172 vpn_leak_from_vrf_update(
6173 bgp_get_default(), bgp
, bi
);
6179 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
6180 bgp
->peer_self
, new_attr
, bn
);
6181 SET_FLAG(new->flags
, BGP_INFO_VALID
);
6183 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
6184 bgp_info_add(bn
, new);
6185 bgp_unlock_node(bn
);
6186 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6188 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6189 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6191 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
6195 /* Unintern original. */
6196 aspath_unintern(&attr
.aspath
);
6199 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, uint8_t type
,
6200 unsigned short instance
)
6203 struct bgp_node
*rn
;
6204 struct bgp_info
*ri
;
6205 struct bgp_redist
*red
;
6207 afi
= family2afi(p
->family
);
6209 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6211 rn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6212 SAFI_UNICAST
, p
, NULL
);
6214 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
6215 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== type
)
6219 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6220 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6222 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6225 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, SAFI_UNICAST
);
6226 bgp_info_delete(rn
, ri
);
6227 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6229 bgp_unlock_node(rn
);
6233 /* Withdraw specified route type's route. */
6234 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
6235 unsigned short instance
)
6237 struct bgp_node
*rn
;
6238 struct bgp_info
*ri
;
6239 struct bgp_table
*table
;
6241 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
6243 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
6244 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
6245 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== type
6246 && ri
->instance
== instance
)
6250 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6251 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6253 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6256 bgp_aggregate_decrement(bgp
, &rn
->p
, ri
, afi
,
6258 bgp_info_delete(rn
, ri
);
6259 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6264 /* Static function to display route. */
6265 static void route_vty_out_route(struct prefix
*p
, struct vty
*vty
,
6271 if (p
->family
== AF_INET
) {
6275 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
6278 json_object_string_add(json
, "prefix",
6279 inet_ntop(p
->family
,
6282 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
6284 } else if (p
->family
== AF_ETHERNET
) {
6285 prefix2str(p
, buf
, PREFIX_STRLEN
);
6286 len
= vty_out(vty
, "%s", buf
);
6287 } else if (p
->family
== AF_EVPN
) {
6291 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf
,
6294 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
6295 } else if (p
->family
== AF_FLOWSPEC
) {
6296 route_vty_out_flowspec(vty
, p
, NULL
,
6298 NLRI_STRING_FORMAT_JSON_SIMPLE
:
6299 NLRI_STRING_FORMAT_MIN
, json
);
6304 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
6311 vty_out(vty
, "\n%*s", 20, " ");
6313 vty_out(vty
, "%*s", len
, " ");
6317 enum bgp_display_type
{
6321 /* Print the short form route status for a bgp_info */
6322 static void route_vty_short_status_out(struct vty
*vty
, struct bgp_info
*binfo
,
6323 json_object
*json_path
)
6327 /* Route status display. */
6328 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_REMOVED
))
6329 json_object_boolean_true_add(json_path
, "removed");
6331 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_STALE
))
6332 json_object_boolean_true_add(json_path
, "stale");
6334 if (binfo
->extra
&& binfo
->extra
->suppress
)
6335 json_object_boolean_true_add(json_path
, "suppressed");
6337 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)
6338 && !CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6339 json_object_boolean_true_add(json_path
, "valid");
6342 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6343 json_object_boolean_true_add(json_path
, "history");
6345 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
))
6346 json_object_boolean_true_add(json_path
, "damped");
6348 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
))
6349 json_object_boolean_true_add(json_path
, "bestpath");
6351 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_MULTIPATH
))
6352 json_object_boolean_true_add(json_path
, "multipath");
6354 /* Internal route. */
6355 if ((binfo
->peer
->as
)
6356 && (binfo
->peer
->as
== binfo
->peer
->local_as
))
6357 json_object_string_add(json_path
, "pathFrom",
6360 json_object_string_add(json_path
, "pathFrom",
6366 /* Route status display. */
6367 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_REMOVED
))
6369 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_STALE
))
6371 else if (binfo
->extra
&& binfo
->extra
->suppress
)
6373 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)
6374 && !CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6380 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6382 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
))
6384 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
))
6386 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_MULTIPATH
))
6391 /* Internal route. */
6392 if (binfo
->peer
&& (binfo
->peer
->as
)
6393 && (binfo
->peer
->as
== binfo
->peer
->local_as
))
6399 /* called from terminal list command */
6400 void route_vty_out(struct vty
*vty
, struct prefix
*p
, struct bgp_info
*binfo
,
6401 int display
, safi_t safi
, json_object
*json_paths
)
6404 json_object
*json_path
= NULL
;
6405 json_object
*json_nexthops
= NULL
;
6406 json_object
*json_nexthop_global
= NULL
;
6407 json_object
*json_nexthop_ll
= NULL
;
6408 char vrf_id_str
[VRF_NAMSIZ
] = {0};
6409 bool nexthop_self
= CHECK_FLAG(binfo
->flags
, BGP_INFO_ANNC_NH_SELF
)
6412 bool nexthop_othervrf
= false;
6413 vrf_id_t nexthop_vrfid
= VRF_DEFAULT
;
6414 const char *nexthop_vrfname
= "Default";
6417 json_path
= json_object_new_object();
6419 /* short status lead text */
6420 route_vty_short_status_out(vty
, binfo
, json_path
);
6423 /* print prefix and mask */
6425 route_vty_out_route(p
, vty
, json_path
);
6427 vty_out(vty
, "%*s", 17, " ");
6429 route_vty_out_route(p
, vty
, json_path
);
6432 /* Print attribute */
6436 json_object_array_add(json_paths
, json_path
);
6444 * If vrf id of nexthop is different from that of prefix,
6445 * set up printable string to append
6447 if (binfo
->extra
&& binfo
->extra
->bgp_orig
) {
6448 const char *self
= "";
6453 nexthop_othervrf
= true;
6454 nexthop_vrfid
= binfo
->extra
->bgp_orig
->vrf_id
;
6456 if (binfo
->extra
->bgp_orig
->vrf_id
== VRF_UNKNOWN
)
6457 snprintf(vrf_id_str
, sizeof(vrf_id_str
),
6458 "@%s%s", VRFID_NONE_STR
, self
);
6460 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "@%u%s",
6461 binfo
->extra
->bgp_orig
->vrf_id
, self
);
6463 if (binfo
->extra
->bgp_orig
->inst_type
!=
6464 BGP_INSTANCE_TYPE_DEFAULT
)
6466 nexthop_vrfname
= binfo
->extra
->bgp_orig
->name
;
6468 const char *self
= "";
6473 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "%s", self
);
6477 * For ENCAP and EVPN routes, nexthop address family is not
6478 * neccessarily the same as the prefix address family.
6479 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
6480 * EVPN routes are also exchanged with a MP nexthop. Currently,
6482 * is only IPv4, the value will be present in either
6484 * attr->mp_nexthop_global_in
6486 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
6489 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
6493 sprintf(nexthop
, "%s",
6494 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
6498 sprintf(nexthop
, "%s",
6499 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
6503 sprintf(nexthop
, "?");
6508 json_nexthop_global
= json_object_new_object();
6510 json_object_string_add(json_nexthop_global
, "afi",
6511 (af
== AF_INET
) ? "ip" : "ipv6");
6512 json_object_string_add(json_nexthop_global
,
6513 (af
== AF_INET
) ? "ip" : "ipv6",
6515 json_object_boolean_true_add(json_nexthop_global
,
6518 vty_out(vty
, "%s%s", nexthop
, vrf_id_str
);
6519 } else if (safi
== SAFI_EVPN
) {
6521 json_nexthop_global
= json_object_new_object();
6523 json_object_string_add(json_nexthop_global
, "ip",
6524 inet_ntoa(attr
->nexthop
));
6525 json_object_string_add(json_nexthop_global
, "afi",
6527 json_object_boolean_true_add(json_nexthop_global
,
6530 vty_out(vty
, "%-16s%s", inet_ntoa(attr
->nexthop
),
6532 } else if (safi
== SAFI_FLOWSPEC
) {
6533 if (attr
->nexthop
.s_addr
!= 0) {
6535 json_nexthop_global
= json_object_new_object();
6536 json_object_string_add(
6537 json_nexthop_global
, "ip",
6538 inet_ntoa(attr
->nexthop
));
6539 json_object_string_add(json_nexthop_global
,
6541 json_object_boolean_true_add(json_nexthop_global
,
6544 vty_out(vty
, "%-16s", inet_ntoa(attr
->nexthop
));
6547 } else if (p
->family
== AF_INET
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6549 json_nexthop_global
= json_object_new_object();
6551 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_EVPN
))
6552 json_object_string_add(
6553 json_nexthop_global
, "ip",
6554 inet_ntoa(attr
->mp_nexthop_global_in
));
6556 json_object_string_add(
6557 json_nexthop_global
, "ip",
6558 inet_ntoa(attr
->nexthop
));
6560 json_object_string_add(json_nexthop_global
, "afi",
6562 json_object_boolean_true_add(json_nexthop_global
,
6567 snprintf(buf
, sizeof(buf
), "%s%s",
6568 inet_ntoa(attr
->nexthop
), vrf_id_str
);
6569 vty_out(vty
, "%-16s", buf
);
6574 else if (p
->family
== AF_INET6
|| BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6579 json_nexthop_global
= json_object_new_object();
6580 json_object_string_add(
6581 json_nexthop_global
, "ip",
6582 inet_ntop(AF_INET6
, &attr
->mp_nexthop_global
,
6584 json_object_string_add(json_nexthop_global
, "afi",
6586 json_object_string_add(json_nexthop_global
, "scope",
6589 /* We display both LL & GL if both have been
6591 if ((attr
->mp_nexthop_len
== 32)
6592 || (binfo
->peer
->conf_if
)) {
6593 json_nexthop_ll
= json_object_new_object();
6594 json_object_string_add(
6595 json_nexthop_ll
, "ip",
6597 &attr
->mp_nexthop_local
, buf
,
6599 json_object_string_add(json_nexthop_ll
, "afi",
6601 json_object_string_add(json_nexthop_ll
, "scope",
6604 if ((IPV6_ADDR_CMP(&attr
->mp_nexthop_global
,
6605 &attr
->mp_nexthop_local
)
6607 && !attr
->mp_nexthop_prefer_global
)
6608 json_object_boolean_true_add(
6609 json_nexthop_ll
, "used");
6611 json_object_boolean_true_add(
6612 json_nexthop_global
, "used");
6614 json_object_boolean_true_add(
6615 json_nexthop_global
, "used");
6617 /* Display LL if LL/Global both in table unless
6618 * prefer-global is set */
6619 if (((attr
->mp_nexthop_len
== 32)
6620 && !attr
->mp_nexthop_prefer_global
)
6621 || (binfo
->peer
->conf_if
)) {
6622 if (binfo
->peer
->conf_if
) {
6623 len
= vty_out(vty
, "%s",
6624 binfo
->peer
->conf_if
);
6625 len
= 16 - len
; /* len of IPv6
6631 vty_out(vty
, "\n%*s", 36, " ");
6633 vty_out(vty
, "%*s", len
, " ");
6639 &attr
->mp_nexthop_local
,
6645 vty_out(vty
, "\n%*s", 36, " ");
6647 vty_out(vty
, "%*s", len
, " ");
6653 &attr
->mp_nexthop_global
, buf
,
6659 vty_out(vty
, "\n%*s", 36, " ");
6661 vty_out(vty
, "%*s", len
, " ");
6667 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
6669 json_object_int_add(json_path
, "med", attr
->med
);
6671 vty_out(vty
, "%10u", attr
->med
);
6672 else if (!json_paths
)
6676 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
6678 json_object_int_add(json_path
, "localpref",
6681 vty_out(vty
, "%7u", attr
->local_pref
);
6682 else if (!json_paths
)
6686 json_object_int_add(json_path
, "weight", attr
->weight
);
6688 vty_out(vty
, "%7u ", attr
->weight
);
6692 json_object_string_add(
6693 json_path
, "peerId",
6694 sockunion2str(&binfo
->peer
->su
, buf
, SU_ADDRSTRLEN
));
6700 json_object_string_add(json_path
, "aspath",
6703 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
6708 json_object_string_add(json_path
, "origin",
6709 bgp_origin_long_str
[attr
->origin
]);
6711 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
6715 json_object_boolean_true_add(json_path
,
6716 "announceNexthopSelf");
6717 if (nexthop_othervrf
) {
6718 json_object_string_add(json_path
, "nhVrfName",
6721 json_object_int_add(json_path
, "nhVrfId",
6722 ((nexthop_vrfid
== VRF_UNKNOWN
)
6724 : (int)nexthop_vrfid
));
6729 if (json_nexthop_global
|| json_nexthop_ll
) {
6730 json_nexthops
= json_object_new_array();
6732 if (json_nexthop_global
)
6733 json_object_array_add(json_nexthops
,
6734 json_nexthop_global
);
6736 if (json_nexthop_ll
)
6737 json_object_array_add(json_nexthops
,
6740 json_object_object_add(json_path
, "nexthops",
6744 json_object_array_add(json_paths
, json_path
);
6748 /* prints an additional line, indented, with VNC info, if
6750 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
6751 rfapi_vty_out_vncinfo(vty
, p
, binfo
, safi
);
6756 /* called from terminal list command */
6757 void route_vty_out_tmp(struct vty
*vty
, struct prefix
*p
, struct attr
*attr
,
6758 safi_t safi
, uint8_t use_json
, json_object
*json_ar
)
6760 json_object
*json_status
= NULL
;
6761 json_object
*json_net
= NULL
;
6763 /* Route status display. */
6765 json_status
= json_object_new_object();
6766 json_net
= json_object_new_object();
6773 /* print prefix and mask */
6775 json_object_string_add(
6776 json_net
, "addrPrefix",
6777 inet_ntop(p
->family
, &p
->u
.prefix
, buff
, BUFSIZ
));
6779 route_vty_out_route(p
, vty
, NULL
);
6781 /* Print attribute */
6784 if (p
->family
== AF_INET
6785 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6786 || safi
== SAFI_EVPN
6787 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6788 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6789 || safi
== SAFI_EVPN
)
6790 json_object_string_add(
6791 json_net
, "nextHop",
6793 attr
->mp_nexthop_global_in
));
6795 json_object_string_add(
6796 json_net
, "nextHop",
6797 inet_ntoa(attr
->nexthop
));
6798 } else if (p
->family
== AF_INET6
6799 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6802 json_object_string_add(
6803 json_net
, "netHopGloabal",
6805 &attr
->mp_nexthop_global
, buf
,
6810 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
6811 json_object_int_add(json_net
, "metric",
6814 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
6815 json_object_int_add(json_net
, "localPref",
6818 json_object_int_add(json_net
, "weight", attr
->weight
);
6822 json_object_string_add(json_net
, "asPath",
6826 json_object_string_add(json_net
, "bgpOriginCode",
6827 bgp_origin_str
[attr
->origin
]);
6829 if (p
->family
== AF_INET
6830 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6831 || safi
== SAFI_EVPN
6832 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6833 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6834 || safi
== SAFI_EVPN
)
6835 vty_out(vty
, "%-16s",
6837 attr
->mp_nexthop_global_in
));
6839 vty_out(vty
, "%-16s",
6840 inet_ntoa(attr
->nexthop
));
6841 } else if (p
->family
== AF_INET6
6842 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6849 &attr
->mp_nexthop_global
, buf
,
6853 vty_out(vty
, "\n%*s", 36, " ");
6855 vty_out(vty
, "%*s", len
, " ");
6858 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
6859 vty_out(vty
, "%10u", attr
->med
);
6863 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
6864 vty_out(vty
, "%7u", attr
->local_pref
);
6868 vty_out(vty
, "%7u ", attr
->weight
);
6872 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
6875 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
6879 json_object_boolean_true_add(json_status
, "*");
6880 json_object_boolean_true_add(json_status
, ">");
6881 json_object_object_add(json_net
, "appliedStatusSymbols",
6883 char buf_cut
[BUFSIZ
];
6884 json_object_object_add(
6886 inet_ntop(p
->family
, &p
->u
.prefix
, buf_cut
, BUFSIZ
),
6892 void route_vty_out_tag(struct vty
*vty
, struct prefix
*p
,
6893 struct bgp_info
*binfo
, int display
, safi_t safi
,
6896 json_object
*json_out
= NULL
;
6898 mpls_label_t label
= MPLS_INVALID_LABEL
;
6904 json_out
= json_object_new_object();
6906 /* short status lead text */
6907 route_vty_short_status_out(vty
, binfo
, json_out
);
6909 /* print prefix and mask */
6912 route_vty_out_route(p
, vty
, NULL
);
6914 vty_out(vty
, "%*s", 17, " ");
6917 /* Print attribute */
6920 if (((p
->family
== AF_INET
)
6921 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
6922 || (safi
== SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
6923 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6924 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6925 || safi
== SAFI_EVPN
) {
6927 json_object_string_add(
6928 json_out
, "mpNexthopGlobalIn",
6930 attr
->mp_nexthop_global_in
));
6932 vty_out(vty
, "%-16s",
6934 attr
->mp_nexthop_global_in
));
6937 json_object_string_add(
6938 json_out
, "nexthop",
6939 inet_ntoa(attr
->nexthop
));
6941 vty_out(vty
, "%-16s",
6942 inet_ntoa(attr
->nexthop
));
6944 } else if (((p
->family
== AF_INET6
)
6945 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
6946 || (safi
== SAFI_EVPN
6947 && BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
6948 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6952 if (attr
->mp_nexthop_len
6953 == BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
6955 json_object_string_add(
6956 json_out
, "mpNexthopGlobalIn",
6959 &attr
->mp_nexthop_global
,
6960 buf_a
, sizeof(buf_a
)));
6965 &attr
->mp_nexthop_global
,
6966 buf_a
, sizeof(buf_a
)));
6967 } else if (attr
->mp_nexthop_len
6968 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
6971 &attr
->mp_nexthop_global
,
6972 buf_a
, sizeof(buf_a
));
6974 &attr
->mp_nexthop_local
,
6975 buf_b
, sizeof(buf_b
));
6976 sprintf(buf_c
, "%s(%s)", buf_a
, buf_b
);
6977 json_object_string_add(
6979 "mpNexthopGlobalLocal", buf_c
);
6981 vty_out(vty
, "%s(%s)",
6984 &attr
->mp_nexthop_global
,
6985 buf_a
, sizeof(buf_a
)),
6988 &attr
->mp_nexthop_local
,
6989 buf_b
, sizeof(buf_b
)));
6994 label
= decode_label(&binfo
->extra
->label
[0]);
6996 if (bgp_is_valid_label(&label
)) {
6998 json_object_int_add(json_out
, "notag", label
);
6999 json_object_array_add(json
, json_out
);
7001 vty_out(vty
, "notag/%d", label
);
7007 void route_vty_out_overlay(struct vty
*vty
, struct prefix
*p
,
7008 struct bgp_info
*binfo
, int display
,
7009 json_object
*json_paths
)
7013 json_object
*json_path
= NULL
;
7016 json_path
= json_object_new_object();
7021 /* short status lead text */
7022 route_vty_short_status_out(vty
, binfo
, json_path
);
7024 /* print prefix and mask */
7026 route_vty_out_route(p
, vty
, NULL
);
7028 vty_out(vty
, "%*s", 17, " ");
7030 /* Print attribute */
7034 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
7038 vty_out(vty
, "%-16s",
7039 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
7043 vty_out(vty
, "%s(%s)",
7044 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
7046 inet_ntop(af
, &attr
->mp_nexthop_local
, buf1
,
7053 char *str
= esi2str(&(attr
->evpn_overlay
.eth_s_id
));
7055 vty_out(vty
, "%s", str
);
7056 XFREE(MTYPE_TMP
, str
);
7058 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn
*)p
)) {
7060 inet_ntoa(attr
->evpn_overlay
.gw_ip
.ipv4
));
7061 } else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn
*)p
)) {
7064 &(attr
->evpn_overlay
.gw_ip
.ipv6
), buf
,
7067 if (attr
->ecommunity
) {
7069 struct ecommunity_val
*routermac
= ecommunity_lookup(
7070 attr
->ecommunity
, ECOMMUNITY_ENCODE_EVPN
,
7071 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
7073 mac
= ecom_mac2str((char *)routermac
->val
);
7075 vty_out(vty
, "/%s", (char *)mac
);
7076 XFREE(MTYPE_TMP
, mac
);
7084 /* dampening route */
7085 static void damp_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7086 struct bgp_info
*binfo
, int display
, safi_t safi
,
7087 uint8_t use_json
, json_object
*json
)
7091 char timebuf
[BGP_UPTIME_LEN
];
7093 /* short status lead text */
7094 route_vty_short_status_out(vty
, binfo
, json
);
7096 /* print prefix and mask */
7099 route_vty_out_route(p
, vty
, NULL
);
7101 vty_out(vty
, "%*s", 17, " ");
7104 len
= vty_out(vty
, "%s", binfo
->peer
->host
);
7108 vty_out(vty
, "\n%*s", 34, " ");
7111 json_object_int_add(json
, "peerHost", len
);
7113 vty_out(vty
, "%*s", len
, " ");
7117 bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
, BGP_UPTIME_LEN
,
7120 vty_out(vty
, "%s ", bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
,
7124 /* Print attribute */
7130 json_object_string_add(json
, "asPath",
7133 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7138 json_object_string_add(json
, "origin",
7139 bgp_origin_str
[attr
->origin
]);
7141 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7148 static void flap_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7149 struct bgp_info
*binfo
, int display
, safi_t safi
,
7150 uint8_t use_json
, json_object
*json
)
7153 struct bgp_damp_info
*bdi
;
7154 char timebuf
[BGP_UPTIME_LEN
];
7160 bdi
= binfo
->extra
->damp_info
;
7162 /* short status lead text */
7163 route_vty_short_status_out(vty
, binfo
, json
);
7165 /* print prefix and mask */
7168 route_vty_out_route(p
, vty
, NULL
);
7170 vty_out(vty
, "%*s", 17, " ");
7173 len
= vty_out(vty
, "%s", binfo
->peer
->host
);
7177 vty_out(vty
, "\n%*s", 33, " ");
7180 json_object_int_add(json
, "peerHost", len
);
7182 vty_out(vty
, "%*s", len
, " ");
7185 len
= vty_out(vty
, "%d", bdi
->flap
);
7192 json_object_int_add(json
, "bdiFlap", len
);
7194 vty_out(vty
, "%*s", len
, " ");
7198 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
7201 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
7202 BGP_UPTIME_LEN
, 0, NULL
));
7204 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
)
7205 && !CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
)) {
7207 bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
,
7208 BGP_UPTIME_LEN
, use_json
, json
);
7211 bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
,
7216 vty_out(vty
, "%*s ", 8, " ");
7219 /* Print attribute */
7225 json_object_string_add(json
, "asPath",
7228 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7233 json_object_string_add(json
, "origin",
7234 bgp_origin_str
[attr
->origin
]);
7236 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7242 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
7243 int *first
, const char *header
,
7244 json_object
*json_adv_to
)
7246 char buf1
[INET6_ADDRSTRLEN
];
7247 json_object
*json_peer
= NULL
;
7250 /* 'advertised-to' is a dictionary of peers we have advertised
7252 * prefix too. The key is the peer's IP or swpX, the value is
7254 * hostname if we know it and "" if not.
7256 json_peer
= json_object_new_object();
7259 json_object_string_add(json_peer
, "hostname",
7263 json_object_object_add(json_adv_to
, peer
->conf_if
,
7266 json_object_object_add(
7268 sockunion2str(&peer
->su
, buf1
, SU_ADDRSTRLEN
),
7272 vty_out(vty
, "%s", header
);
7277 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
7279 vty_out(vty
, " %s(%s)", peer
->hostname
,
7282 vty_out(vty
, " %s(%s)", peer
->hostname
,
7283 sockunion2str(&peer
->su
, buf1
,
7287 vty_out(vty
, " %s", peer
->conf_if
);
7290 sockunion2str(&peer
->su
, buf1
,
7296 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
, struct prefix
*p
,
7297 struct bgp_info
*binfo
, afi_t afi
, safi_t safi
,
7298 json_object
*json_paths
)
7300 char buf
[INET6_ADDRSTRLEN
];
7302 char buf2
[EVPN_ROUTE_STRLEN
];
7304 int sockunion_vty_out(struct vty
*, union sockunion
*);
7306 json_object
*json_bestpath
= NULL
;
7307 json_object
*json_cluster_list
= NULL
;
7308 json_object
*json_cluster_list_list
= NULL
;
7309 json_object
*json_ext_community
= NULL
;
7310 json_object
*json_last_update
= NULL
;
7311 json_object
*json_pmsi
= NULL
;
7312 json_object
*json_nexthop_global
= NULL
;
7313 json_object
*json_nexthop_ll
= NULL
;
7314 json_object
*json_nexthops
= NULL
;
7315 json_object
*json_path
= NULL
;
7316 json_object
*json_peer
= NULL
;
7317 json_object
*json_string
= NULL
;
7318 json_object
*json_adv_to
= NULL
;
7320 struct listnode
*node
, *nnode
;
7322 int addpath_capable
;
7324 unsigned int first_as
;
7325 bool nexthop_self
= CHECK_FLAG(binfo
->flags
, BGP_INFO_ANNC_NH_SELF
)
7330 json_path
= json_object_new_object();
7331 json_peer
= json_object_new_object();
7332 json_nexthop_global
= json_object_new_object();
7335 if (!json_paths
&& safi
== SAFI_EVPN
) {
7338 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf2
, sizeof(buf2
));
7339 vty_out(vty
, " Route %s", buf2
);
7341 if (binfo
->extra
&& binfo
->extra
->num_labels
) {
7342 bgp_evpn_label2str(binfo
->extra
->label
,
7343 binfo
->extra
->num_labels
, tag_buf
,
7345 vty_out(vty
, " VNI %s", tag_buf
);
7348 if (binfo
->extra
&& binfo
->extra
->parent
) {
7349 struct bgp_info
*parent_ri
;
7350 struct bgp_node
*rn
, *prn
;
7352 parent_ri
= (struct bgp_info
*)binfo
->extra
->parent
;
7353 rn
= parent_ri
->net
;
7354 if (rn
&& rn
->prn
) {
7356 vty_out(vty
, " Imported from %s:%s\n",
7358 (struct prefix_rd
*)&prn
->p
,
7359 buf1
, sizeof(buf1
)),
7368 /* Line1 display AS-path, Aggregator */
7371 if (!attr
->aspath
->json
)
7372 aspath_str_update(attr
->aspath
, true);
7373 json_object_lock(attr
->aspath
->json
);
7374 json_object_object_add(json_path
, "aspath",
7375 attr
->aspath
->json
);
7377 if (attr
->aspath
->segments
)
7378 aspath_print_vty(vty
, " %s",
7381 vty_out(vty
, " Local");
7385 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_REMOVED
)) {
7387 json_object_boolean_true_add(json_path
,
7390 vty_out(vty
, ", (removed)");
7393 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_STALE
)) {
7395 json_object_boolean_true_add(json_path
,
7398 vty_out(vty
, ", (stale)");
7401 if (CHECK_FLAG(attr
->flag
,
7402 ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
7404 json_object_int_add(json_path
, "aggregatorAs",
7405 attr
->aggregator_as
);
7406 json_object_string_add(
7407 json_path
, "aggregatorId",
7408 inet_ntoa(attr
->aggregator_addr
));
7410 vty_out(vty
, ", (aggregated by %u %s)",
7411 attr
->aggregator_as
,
7412 inet_ntoa(attr
->aggregator_addr
));
7416 if (CHECK_FLAG(binfo
->peer
->af_flags
[afi
][safi
],
7417 PEER_FLAG_REFLECTOR_CLIENT
)) {
7419 json_object_boolean_true_add(
7420 json_path
, "rxedFromRrClient");
7422 vty_out(vty
, ", (Received from a RR-client)");
7425 if (CHECK_FLAG(binfo
->peer
->af_flags
[afi
][safi
],
7426 PEER_FLAG_RSERVER_CLIENT
)) {
7428 json_object_boolean_true_add(
7429 json_path
, "rxedFromRsClient");
7431 vty_out(vty
, ", (Received from a RS-client)");
7434 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
)) {
7436 json_object_boolean_true_add(
7437 json_path
, "dampeningHistoryEntry");
7439 vty_out(vty
, ", (history entry)");
7440 } else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
)) {
7442 json_object_boolean_true_add(
7443 json_path
, "dampeningSuppressed");
7445 vty_out(vty
, ", (suppressed due to dampening)");
7451 /* Line2 display Next-hop, Neighbor, Router-id */
7452 /* Display the nexthop */
7453 if ((p
->family
== AF_INET
|| p
->family
== AF_ETHERNET
7454 || p
->family
== AF_EVPN
)
7455 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7456 || safi
== SAFI_EVPN
7457 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7458 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7459 || safi
== SAFI_EVPN
) {
7461 json_object_string_add(
7462 json_nexthop_global
, "ip",
7464 attr
->mp_nexthop_global_in
));
7468 attr
->mp_nexthop_global_in
));
7471 json_object_string_add(
7472 json_nexthop_global
, "ip",
7473 inet_ntoa(attr
->nexthop
));
7476 inet_ntoa(attr
->nexthop
));
7480 json_object_string_add(json_nexthop_global
,
7484 json_object_string_add(
7485 json_nexthop_global
, "ip",
7487 &attr
->mp_nexthop_global
, buf
,
7489 json_object_string_add(json_nexthop_global
,
7491 json_object_string_add(json_nexthop_global
,
7496 &attr
->mp_nexthop_global
, buf
,
7501 /* Display the IGP cost or 'inaccessible' */
7502 if (!CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)) {
7504 json_object_boolean_false_add(
7505 json_nexthop_global
, "accessible");
7507 vty_out(vty
, " (inaccessible)");
7509 if (binfo
->extra
&& binfo
->extra
->igpmetric
) {
7511 json_object_int_add(
7512 json_nexthop_global
, "metric",
7513 binfo
->extra
->igpmetric
);
7515 vty_out(vty
, " (metric %u)",
7516 binfo
->extra
->igpmetric
);
7519 /* IGP cost is 0, display this only for json */
7522 json_object_int_add(json_nexthop_global
,
7527 json_object_boolean_true_add(
7528 json_nexthop_global
, "accessible");
7531 /* Display peer "from" output */
7532 /* This path was originated locally */
7533 if (binfo
->peer
== bgp
->peer_self
) {
7535 if (safi
== SAFI_EVPN
7536 || (p
->family
== AF_INET
7537 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7539 json_object_string_add(
7540 json_peer
, "peerId", "0.0.0.0");
7542 vty_out(vty
, " from 0.0.0.0 ");
7545 json_object_string_add(json_peer
,
7548 vty_out(vty
, " from :: ");
7552 json_object_string_add(
7553 json_peer
, "routerId",
7554 inet_ntoa(bgp
->router_id
));
7556 vty_out(vty
, "(%s)", inet_ntoa(bgp
->router_id
));
7559 /* We RXed this path from one of our peers */
7563 json_object_string_add(
7564 json_peer
, "peerId",
7565 sockunion2str(&binfo
->peer
->su
, buf
,
7567 json_object_string_add(
7568 json_peer
, "routerId",
7570 &binfo
->peer
->remote_id
, buf1
,
7573 if (binfo
->peer
->hostname
)
7574 json_object_string_add(
7575 json_peer
, "hostname",
7576 binfo
->peer
->hostname
);
7578 if (binfo
->peer
->domainname
)
7579 json_object_string_add(
7580 json_peer
, "domainname",
7581 binfo
->peer
->domainname
);
7583 if (binfo
->peer
->conf_if
)
7584 json_object_string_add(
7585 json_peer
, "interface",
7586 binfo
->peer
->conf_if
);
7588 if (binfo
->peer
->conf_if
) {
7589 if (binfo
->peer
->hostname
7592 BGP_FLAG_SHOW_HOSTNAME
))
7593 vty_out(vty
, " from %s(%s)",
7594 binfo
->peer
->hostname
,
7595 binfo
->peer
->conf_if
);
7597 vty_out(vty
, " from %s",
7598 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
,
7608 vty_out(vty
, " from %s",
7617 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
7618 vty_out(vty
, " (%s)",
7619 inet_ntoa(attr
->originator_id
));
7621 vty_out(vty
, " (%s)",
7624 &binfo
->peer
->remote_id
,
7625 buf1
, sizeof(buf1
)));
7630 * Note when vrfid of nexthop is different from that of prefix
7632 if (binfo
->extra
&& binfo
->extra
->bgp_orig
) {
7633 vrf_id_t nexthop_vrfid
= binfo
->extra
->bgp_orig
->vrf_id
;
7638 if (binfo
->extra
->bgp_orig
->inst_type
==
7639 BGP_INSTANCE_TYPE_DEFAULT
)
7643 vn
= binfo
->extra
->bgp_orig
->name
;
7645 json_object_string_add(json_path
, "nhVrfName",
7648 if (nexthop_vrfid
== VRF_UNKNOWN
) {
7649 json_object_int_add(json_path
,
7652 json_object_int_add(json_path
,
7653 "nhVrfId", (int)nexthop_vrfid
);
7656 if (nexthop_vrfid
== VRF_UNKNOWN
)
7657 vty_out(vty
, " vrf ?");
7659 vty_out(vty
, " vrf %u", nexthop_vrfid
);
7665 json_object_boolean_true_add(json_path
,
7666 "announceNexthopSelf");
7668 vty_out(vty
, " announce-nh-self");
7675 /* display the link-local nexthop */
7676 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
7678 json_nexthop_ll
= json_object_new_object();
7679 json_object_string_add(
7680 json_nexthop_ll
, "ip",
7682 &attr
->mp_nexthop_local
, buf
,
7684 json_object_string_add(json_nexthop_ll
, "afi",
7686 json_object_string_add(json_nexthop_ll
, "scope",
7689 json_object_boolean_true_add(json_nexthop_ll
,
7692 if (!attr
->mp_nexthop_prefer_global
)
7693 json_object_boolean_true_add(
7694 json_nexthop_ll
, "used");
7696 json_object_boolean_true_add(
7697 json_nexthop_global
, "used");
7699 vty_out(vty
, " (%s) %s\n",
7701 &attr
->mp_nexthop_local
, buf
,
7703 attr
->mp_nexthop_prefer_global
7708 /* If we do not have a link-local nexthop then we must flag the
7712 json_object_boolean_true_add(
7713 json_nexthop_global
, "used");
7716 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
7717 * Int/Ext/Local, Atomic, best */
7719 json_object_string_add(
7720 json_path
, "origin",
7721 bgp_origin_long_str
[attr
->origin
]);
7723 vty_out(vty
, " Origin %s",
7724 bgp_origin_long_str
[attr
->origin
]);
7726 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
7728 json_object_int_add(json_path
, "med",
7731 vty_out(vty
, ", metric %u", attr
->med
);
7734 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
7736 json_object_int_add(json_path
, "localpref",
7739 vty_out(vty
, ", localpref %u",
7743 if (attr
->weight
!= 0) {
7745 json_object_int_add(json_path
, "weight",
7748 vty_out(vty
, ", weight %u", attr
->weight
);
7751 if (attr
->tag
!= 0) {
7753 json_object_int_add(json_path
, "tag",
7756 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
,
7760 if (!CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)) {
7762 json_object_boolean_false_add(json_path
,
7765 vty_out(vty
, ", invalid");
7766 } else if (!CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
)) {
7768 json_object_boolean_true_add(json_path
,
7771 vty_out(vty
, ", valid");
7774 if (binfo
->peer
!= bgp
->peer_self
) {
7775 if (binfo
->peer
->as
== binfo
->peer
->local_as
) {
7776 if (CHECK_FLAG(bgp
->config
,
7777 BGP_CONFIG_CONFEDERATION
)) {
7779 json_object_string_add(
7784 ", confed-internal");
7787 json_object_string_add(
7791 vty_out(vty
, ", internal");
7794 if (bgp_confederation_peers_check(
7795 bgp
, binfo
->peer
->as
)) {
7797 json_object_string_add(
7802 ", confed-external");
7805 json_object_string_add(
7809 vty_out(vty
, ", external");
7812 } else if (binfo
->sub_type
== BGP_ROUTE_AGGREGATE
) {
7814 json_object_boolean_true_add(json_path
,
7816 json_object_boolean_true_add(json_path
,
7819 vty_out(vty
, ", aggregated, local");
7821 } else if (binfo
->type
!= ZEBRA_ROUTE_BGP
) {
7823 json_object_boolean_true_add(json_path
,
7826 vty_out(vty
, ", sourced");
7829 json_object_boolean_true_add(json_path
,
7831 json_object_boolean_true_add(json_path
,
7834 vty_out(vty
, ", sourced, local");
7838 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
7840 json_object_boolean_true_add(json_path
,
7843 vty_out(vty
, ", atomic-aggregate");
7846 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_MULTIPATH
)
7847 || (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
)
7848 && bgp_info_mpath_count(binfo
))) {
7850 json_object_boolean_true_add(json_path
,
7853 vty_out(vty
, ", multipath");
7856 // Mark the bestpath(s)
7857 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DMED_SELECTED
)) {
7858 first_as
= aspath_get_first_as(attr
->aspath
);
7863 json_object_new_object();
7864 json_object_int_add(json_bestpath
,
7865 "bestpathFromAs", first_as
);
7868 vty_out(vty
, ", bestpath-from-AS %u",
7872 ", bestpath-from-AS Local");
7876 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
)) {
7880 json_object_new_object();
7881 json_object_boolean_true_add(json_bestpath
,
7884 vty_out(vty
, ", best");
7888 json_object_object_add(json_path
, "bestpath",
7894 /* Line 4 display Community */
7895 if (attr
->community
) {
7897 if (!attr
->community
->json
)
7898 community_str(attr
->community
, true);
7899 json_object_lock(attr
->community
->json
);
7900 json_object_object_add(json_path
, "community",
7901 attr
->community
->json
);
7903 vty_out(vty
, " Community: %s\n",
7904 attr
->community
->str
);
7908 /* Line 5 display Extended-community */
7909 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
7911 json_ext_community
= json_object_new_object();
7912 json_object_string_add(json_ext_community
,
7914 attr
->ecommunity
->str
);
7915 json_object_object_add(json_path
,
7916 "extendedCommunity",
7917 json_ext_community
);
7919 vty_out(vty
, " Extended Community: %s\n",
7920 attr
->ecommunity
->str
);
7924 /* Line 6 display Large community */
7925 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
7927 if (!attr
->lcommunity
->json
)
7928 lcommunity_str(attr
->lcommunity
, true);
7929 json_object_lock(attr
->lcommunity
->json
);
7930 json_object_object_add(json_path
,
7932 attr
->lcommunity
->json
);
7934 vty_out(vty
, " Large Community: %s\n",
7935 attr
->lcommunity
->str
);
7939 /* Line 7 display Originator, Cluster-id */
7940 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
7941 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
7943 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
7945 json_object_string_add(
7946 json_path
, "originatorId",
7947 inet_ntoa(attr
->originator_id
));
7949 vty_out(vty
, " Originator: %s",
7950 inet_ntoa(attr
->originator_id
));
7953 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
7958 json_object_new_object();
7959 json_cluster_list_list
=
7960 json_object_new_array();
7963 i
< attr
->cluster
->length
/ 4;
7965 json_string
= json_object_new_string(
7969 json_object_array_add(
7970 json_cluster_list_list
,
7974 /* struct cluster_list does not have
7976 * aspath and community do. Add this
7979 json_object_string_add(json_cluster_list,
7980 "string", attr->cluster->str);
7982 json_object_object_add(
7983 json_cluster_list
, "list",
7984 json_cluster_list_list
);
7985 json_object_object_add(
7986 json_path
, "clusterList",
7989 vty_out(vty
, ", Cluster list: ");
7992 i
< attr
->cluster
->length
/ 4;
8006 if (binfo
->extra
&& binfo
->extra
->damp_info
)
8007 bgp_damp_info_vty(vty
, binfo
, json_path
);
8010 if (binfo
->extra
&& bgp_is_valid_label(&binfo
->extra
->label
[0])
8011 && safi
!= SAFI_EVPN
) {
8012 mpls_label_t label
=
8013 label_pton(&binfo
->extra
->label
[0]);
8015 json_object_int_add(json_path
, "remoteLabel",
8018 vty_out(vty
, " Remote label: %d\n", label
);
8022 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
8024 json_object_int_add(json_path
, "labelIndex",
8027 vty_out(vty
, " Label Index: %d\n",
8031 /* Line 8 display Addpath IDs */
8032 if (binfo
->addpath_rx_id
|| binfo
->addpath_tx_id
) {
8034 json_object_int_add(json_path
, "addpathRxId",
8035 binfo
->addpath_rx_id
);
8036 json_object_int_add(json_path
, "addpathTxId",
8037 binfo
->addpath_tx_id
);
8039 vty_out(vty
, " AddPath ID: RX %u, TX %u\n",
8040 binfo
->addpath_rx_id
,
8041 binfo
->addpath_tx_id
);
8045 /* If we used addpath to TX a non-bestpath we need to display
8046 * "Advertised to" on a path-by-path basis */
8047 if (bgp
->addpath_tx_used
[afi
][safi
]) {
8050 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
8052 bgp_addpath_encode_tx(peer
, afi
, safi
);
8053 has_adj
= bgp_adj_out_lookup(
8054 peer
, binfo
->net
, binfo
->addpath_tx_id
);
8056 if ((addpath_capable
&& has_adj
)
8057 || (!addpath_capable
&& has_adj
8058 && CHECK_FLAG(binfo
->flags
,
8059 BGP_INFO_SELECTED
))) {
8060 if (json_path
&& !json_adv_to
)
8062 json_object_new_object();
8064 route_vty_out_advertised_to(
8073 json_object_object_add(json_path
,
8084 /* Line 9 display Uptime */
8085 tbuf
= time(NULL
) - (bgp_clock() - binfo
->uptime
);
8087 json_last_update
= json_object_new_object();
8088 json_object_int_add(json_last_update
, "epoch", tbuf
);
8089 json_object_string_add(json_last_update
, "string",
8091 json_object_object_add(json_path
, "lastUpdate",
8094 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
8096 /* Line 10 display PMSI tunnel attribute, if present */
8097 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
8098 const char *str
= lookup_msg(bgp_pmsi_tnltype_str
,
8099 attr
->pmsi_tnl_type
,
8100 PMSI_TNLTYPE_STR_DEFAULT
);
8103 json_pmsi
= json_object_new_object();
8104 json_object_string_add(json_pmsi
,
8106 json_object_object_add(json_path
, "pmsi",
8109 vty_out(vty
, " PMSI Tunnel Type: %s\n",
8115 /* We've constructed the json object for this path, add it to the json
8119 if (json_nexthop_global
|| json_nexthop_ll
) {
8120 json_nexthops
= json_object_new_array();
8122 if (json_nexthop_global
)
8123 json_object_array_add(json_nexthops
,
8124 json_nexthop_global
);
8126 if (json_nexthop_ll
)
8127 json_object_array_add(json_nexthops
,
8130 json_object_object_add(json_path
, "nexthops",
8134 json_object_object_add(json_path
, "peer", json_peer
);
8135 json_object_array_add(json_paths
, json_path
);
8140 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
8141 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
8142 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
8144 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
8145 const char *prefix_list_str
, afi_t afi
,
8146 safi_t safi
, enum bgp_show_type type
);
8147 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
8148 const char *filter
, afi_t afi
, safi_t safi
,
8149 enum bgp_show_type type
);
8150 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
8151 const char *rmap_str
, afi_t afi
, safi_t safi
,
8152 enum bgp_show_type type
);
8153 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
8154 const char *com
, int exact
, afi_t afi
,
8156 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
8157 const char *prefix
, afi_t afi
, safi_t safi
,
8158 enum bgp_show_type type
);
8159 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
8160 afi_t afi
, safi_t safi
, enum bgp_show_type type
);
8161 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
8162 const char *comstr
, int exact
, afi_t afi
,
8163 safi_t safi
, uint8_t use_json
);
8166 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
8167 struct bgp_table
*table
, enum bgp_show_type type
,
8168 void *output_arg
, uint8_t use_json
, char *rd
,
8169 int is_last
, unsigned long *output_cum
,
8170 unsigned long *total_cum
,
8171 unsigned long *json_header_depth
)
8173 struct bgp_info
*ri
;
8174 struct bgp_node
*rn
;
8177 unsigned long output_count
= 0;
8178 unsigned long total_count
= 0;
8182 json_object
*json_paths
= NULL
;
8185 if (output_cum
&& *output_cum
!= 0)
8188 if (use_json
&& !*json_header_depth
) {
8190 "{\n \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
8191 ",\n \"routerId\": \"%s\",\n \"routes\": { ",
8192 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
8193 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
? "Default"
8195 table
->version
, inet_ntoa(bgp
->router_id
));
8196 *json_header_depth
= 2;
8198 vty_out(vty
, " \"routeDistinguishers\" : {");
8199 ++*json_header_depth
;
8203 if (use_json
&& rd
) {
8204 vty_out(vty
, " \"%s\" : { ", rd
);
8207 /* Start processing of routes. */
8208 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
8209 if (rn
->info
== NULL
)
8214 json_paths
= json_object_new_array();
8218 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
8220 if (type
== bgp_show_type_flap_statistics
8221 || type
== bgp_show_type_flap_neighbor
8222 || type
== bgp_show_type_dampend_paths
8223 || type
== bgp_show_type_damp_neighbor
) {
8224 if (!(ri
->extra
&& ri
->extra
->damp_info
))
8227 if (type
== bgp_show_type_regexp
) {
8228 regex_t
*regex
= output_arg
;
8230 if (bgp_regexec(regex
, ri
->attr
->aspath
)
8234 if (type
== bgp_show_type_prefix_list
) {
8235 struct prefix_list
*plist
= output_arg
;
8237 if (prefix_list_apply(plist
, &rn
->p
)
8241 if (type
== bgp_show_type_filter_list
) {
8242 struct as_list
*as_list
= output_arg
;
8244 if (as_list_apply(as_list
, ri
->attr
->aspath
)
8245 != AS_FILTER_PERMIT
)
8248 if (type
== bgp_show_type_route_map
) {
8249 struct route_map
*rmap
= output_arg
;
8250 struct bgp_info binfo
;
8251 struct attr dummy_attr
;
8254 bgp_attr_dup(&dummy_attr
, ri
->attr
);
8256 binfo
.peer
= ri
->peer
;
8257 binfo
.attr
= &dummy_attr
;
8259 ret
= route_map_apply(rmap
, &rn
->p
, RMAP_BGP
,
8261 if (ret
== RMAP_DENYMATCH
)
8264 if (type
== bgp_show_type_neighbor
8265 || type
== bgp_show_type_flap_neighbor
8266 || type
== bgp_show_type_damp_neighbor
) {
8267 union sockunion
*su
= output_arg
;
8269 if (ri
->peer
== NULL
8270 || ri
->peer
->su_remote
== NULL
8271 || !sockunion_same(ri
->peer
->su_remote
, su
))
8274 if (type
== bgp_show_type_cidr_only
) {
8275 uint32_t destination
;
8277 destination
= ntohl(rn
->p
.u
.prefix4
.s_addr
);
8278 if (IN_CLASSC(destination
)
8279 && rn
->p
.prefixlen
== 24)
8281 if (IN_CLASSB(destination
)
8282 && rn
->p
.prefixlen
== 16)
8284 if (IN_CLASSA(destination
)
8285 && rn
->p
.prefixlen
== 8)
8288 if (type
== bgp_show_type_prefix_longer
) {
8289 struct prefix
*p
= output_arg
;
8291 if (!prefix_match(p
, &rn
->p
))
8294 if (type
== bgp_show_type_community_all
) {
8295 if (!ri
->attr
->community
)
8298 if (type
== bgp_show_type_community
) {
8299 struct community
*com
= output_arg
;
8301 if (!ri
->attr
->community
8302 || !community_match(ri
->attr
->community
,
8306 if (type
== bgp_show_type_community_exact
) {
8307 struct community
*com
= output_arg
;
8309 if (!ri
->attr
->community
8310 || !community_cmp(ri
->attr
->community
, com
))
8313 if (type
== bgp_show_type_community_list
) {
8314 struct community_list
*list
= output_arg
;
8316 if (!community_list_match(ri
->attr
->community
,
8320 if (type
== bgp_show_type_community_list_exact
) {
8321 struct community_list
*list
= output_arg
;
8323 if (!community_list_exact_match(
8324 ri
->attr
->community
, list
))
8327 if (type
== bgp_show_type_lcommunity
) {
8328 struct lcommunity
*lcom
= output_arg
;
8330 if (!ri
->attr
->lcommunity
8331 || !lcommunity_match(ri
->attr
->lcommunity
,
8335 if (type
== bgp_show_type_lcommunity_list
) {
8336 struct community_list
*list
= output_arg
;
8338 if (!lcommunity_list_match(ri
->attr
->lcommunity
,
8342 if (type
== bgp_show_type_lcommunity_all
) {
8343 if (!ri
->attr
->lcommunity
)
8346 if (type
== bgp_show_type_dampend_paths
8347 || type
== bgp_show_type_damp_neighbor
) {
8348 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_DAMPED
)
8349 || CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
8353 if (!use_json
&& header
) {
8354 vty_out(vty
, "BGP table version is %" PRIu64
8355 ", local router ID is %s, vrf id ",
8357 inet_ntoa(bgp
->router_id
));
8358 if (bgp
->vrf_id
== VRF_UNKNOWN
)
8359 vty_out(vty
, "%s", VRFID_NONE_STR
);
8361 vty_out(vty
, "%u", bgp
->vrf_id
);
8363 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
8364 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
8365 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
8366 if (type
== bgp_show_type_dampend_paths
8367 || type
== bgp_show_type_damp_neighbor
)
8368 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
8369 else if (type
== bgp_show_type_flap_statistics
8370 || type
== bgp_show_type_flap_neighbor
)
8371 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
8373 vty_out(vty
, BGP_SHOW_HEADER
);
8376 if (rd
!= NULL
&& !display
&& !output_count
) {
8379 "Route Distinguisher: %s\n",
8382 if (type
== bgp_show_type_dampend_paths
8383 || type
== bgp_show_type_damp_neighbor
)
8384 damp_route_vty_out(vty
, &rn
->p
, ri
, display
,
8385 safi
, use_json
, json_paths
);
8386 else if (type
== bgp_show_type_flap_statistics
8387 || type
== bgp_show_type_flap_neighbor
)
8388 flap_route_vty_out(vty
, &rn
->p
, ri
, display
,
8389 safi
, use_json
, json_paths
);
8391 route_vty_out(vty
, &rn
->p
, ri
, display
, safi
,
8402 sprintf(buf2
, "%s/%d",
8403 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
8406 vty_out(vty
, "\"%s\": ", buf2
);
8408 vty_out(vty
, ",\"%s\": ", buf2
);
8411 json_object_to_json_string(json_paths
));
8412 json_object_free(json_paths
);
8419 output_count
+= *output_cum
;
8420 *output_cum
= output_count
;
8423 total_count
+= *total_cum
;
8424 *total_cum
= total_count
;
8428 vty_out(vty
, " }%s ", (is_last
? "" : ","));
8432 for (i
= 0; i
< *json_header_depth
; ++i
)
8433 vty_out(vty
, " } ");
8437 /* No route is displayed */
8438 if (output_count
== 0) {
8439 if (type
== bgp_show_type_normal
)
8441 "No BGP prefixes displayed, %ld exist\n",
8445 "\nDisplayed %ld routes and %ld total paths\n",
8446 output_count
, total_count
);
8453 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
8454 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
8455 enum bgp_show_type type
, void *output_arg
,
8458 struct bgp_node
*rn
, *next
;
8459 unsigned long output_cum
= 0;
8460 unsigned long total_cum
= 0;
8461 unsigned long json_header_depth
= 0;
8464 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
8466 for (rn
= bgp_table_top(table
); rn
; rn
= next
) {
8467 next
= bgp_route_next(rn
);
8468 if (prd_match
&& memcmp(rn
->p
.u
.val
, prd_match
->val
, 8) != 0)
8470 if (rn
->info
!= NULL
) {
8471 struct prefix_rd prd
;
8472 char rd
[RD_ADDRSTRLEN
];
8474 memcpy(&prd
, &(rn
->p
), sizeof(struct prefix_rd
));
8475 prefix_rd2str(&prd
, rd
, sizeof(rd
));
8476 bgp_show_table(vty
, bgp
, safi
, rn
->info
, type
,
8477 output_arg
, use_json
, rd
, next
== NULL
,
8478 &output_cum
, &total_cum
,
8479 &json_header_depth
);
8485 if (output_cum
== 0)
8486 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
8490 "\nDisplayed %ld routes and %ld total paths\n",
8491 output_cum
, total_cum
);
8495 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
8496 enum bgp_show_type type
, void *output_arg
, uint8_t use_json
)
8498 struct bgp_table
*table
;
8499 unsigned long json_header_depth
= 0;
8502 bgp
= bgp_get_default();
8507 vty_out(vty
, "No BGP process is configured\n");
8509 vty_out(vty
, "{}\n");
8513 table
= bgp
->rib
[afi
][safi
];
8514 /* use MPLS and ENCAP specific shows until they are merged */
8515 if (safi
== SAFI_MPLS_VPN
) {
8516 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
8517 output_arg
, use_json
);
8520 if (safi
== SAFI_FLOWSPEC
&& type
== bgp_show_type_detail
) {
8521 return bgp_show_table_flowspec(vty
, bgp
, afi
, table
, type
,
8522 output_arg
, use_json
,
8525 /* labeled-unicast routes live in the unicast table */
8526 else if (safi
== SAFI_LABELED_UNICAST
)
8527 safi
= SAFI_UNICAST
;
8529 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, use_json
,
8530 NULL
, 1, NULL
, NULL
, &json_header_depth
);
8533 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
8534 safi_t safi
, uint8_t use_json
)
8536 struct listnode
*node
, *nnode
;
8541 vty_out(vty
, "{\n");
8543 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
8546 vty_out(vty
, ",\n");
8550 vty_out(vty
, "\"%s\":",
8551 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
8555 vty_out(vty
, "\nInstance %s:\n",
8556 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
8560 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
8565 vty_out(vty
, "}\n");
8568 /* Header of detailed BGP route information */
8569 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
8570 struct bgp_node
*rn
, struct prefix_rd
*prd
,
8571 afi_t afi
, safi_t safi
, json_object
*json
)
8573 struct bgp_info
*ri
;
8576 struct listnode
*node
, *nnode
;
8577 char buf1
[RD_ADDRSTRLEN
];
8578 char buf2
[INET6_ADDRSTRLEN
];
8579 char buf3
[EVPN_ROUTE_STRLEN
];
8580 char prefix_str
[BUFSIZ
];
8585 int no_advertise
= 0;
8588 int has_valid_label
= 0;
8589 mpls_label_t label
= 0;
8590 json_object
*json_adv_to
= NULL
;
8593 has_valid_label
= bgp_is_valid_label(&rn
->local_label
);
8595 if (has_valid_label
)
8596 label
= label_pton(&rn
->local_label
);
8599 if (has_valid_label
)
8600 json_object_int_add(json
, "localLabel", label
);
8602 json_object_string_add(
8604 prefix2str(p
, prefix_str
, sizeof(prefix_str
)));
8606 if (safi
== SAFI_EVPN
)
8607 vty_out(vty
, "BGP routing table entry for %s%s%s\n",
8608 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
))
8611 bgp_evpn_route2str((struct prefix_evpn
*)p
,
8612 buf3
, sizeof(buf3
)));
8614 vty_out(vty
, "BGP routing table entry for %s%s%s/%d\n",
8615 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
8616 ? prefix_rd2str(prd
, buf1
,
8619 safi
== SAFI_MPLS_VPN
? ":" : "",
8620 inet_ntop(p
->family
, &p
->u
.prefix
, buf2
,
8624 if (has_valid_label
)
8625 vty_out(vty
, "Local label: %d\n", label
);
8626 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
8627 vty_out(vty
, "not allocated\n");
8630 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
8632 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
8634 if (ri
->extra
&& ri
->extra
->suppress
)
8636 if (ri
->attr
->community
!= NULL
) {
8637 if (community_include(ri
->attr
->community
,
8638 COMMUNITY_NO_ADVERTISE
))
8640 if (community_include(ri
->attr
->community
,
8641 COMMUNITY_NO_EXPORT
))
8643 if (community_include(ri
->attr
->community
,
8644 COMMUNITY_LOCAL_AS
))
8651 vty_out(vty
, "Paths: (%d available", count
);
8653 vty_out(vty
, ", best #%d", best
);
8654 if (safi
== SAFI_UNICAST
)
8655 vty_out(vty
, ", table %s",
8657 == BGP_INSTANCE_TYPE_DEFAULT
)
8658 ? "Default-IP-Routing-Table"
8661 vty_out(vty
, ", no best path");
8664 vty_out(vty
, ", not advertised to any peer");
8666 vty_out(vty
, ", not advertised to EBGP peer");
8668 vty_out(vty
, ", not advertised outside local AS");
8672 ", Advertisements suppressed by an aggregate.");
8673 vty_out(vty
, ")\n");
8676 /* If we are not using addpath then we can display Advertised to and
8678 * show what peers we advertised the bestpath to. If we are using
8680 * though then we must display Advertised to on a path-by-path basis. */
8681 if (!bgp
->addpath_tx_used
[afi
][safi
]) {
8682 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
8683 if (bgp_adj_out_lookup(peer
, rn
, 0)) {
8684 if (json
&& !json_adv_to
)
8685 json_adv_to
= json_object_new_object();
8687 route_vty_out_advertised_to(
8689 " Advertised to non peer-group peers:\n ",
8696 json_object_object_add(json
, "advertisedTo",
8701 vty_out(vty
, " Not advertised to any peer");
8707 /* Display specified route of BGP table. */
8708 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
8709 struct bgp_table
*rib
, const char *ip_str
,
8710 afi_t afi
, safi_t safi
,
8711 struct prefix_rd
*prd
, int prefix_check
,
8712 enum bgp_path_type pathtype
,
8718 struct prefix match
;
8719 struct bgp_node
*rn
;
8720 struct bgp_node
*rm
;
8721 struct bgp_info
*ri
;
8722 struct bgp_table
*table
;
8723 json_object
*json
= NULL
;
8724 json_object
*json_paths
= NULL
;
8726 /* Check IP address argument. */
8727 ret
= str2prefix(ip_str
, &match
);
8729 vty_out(vty
, "address is malformed\n");
8733 match
.family
= afi2family(afi
);
8736 json
= json_object_new_object();
8737 json_paths
= json_object_new_array();
8740 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
8741 for (rn
= bgp_table_top(rib
); rn
; rn
= bgp_route_next(rn
)) {
8742 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
8745 if ((table
= rn
->info
) == NULL
)
8750 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
8754 && rm
->p
.prefixlen
!= match
.prefixlen
) {
8755 bgp_unlock_node(rm
);
8759 for (ri
= rm
->info
; ri
; ri
= ri
->next
) {
8761 route_vty_out_detail_header(
8763 (struct prefix_rd
*)&rn
->p
,
8764 AFI_IP
, safi
, json
);
8769 if (pathtype
== BGP_PATH_ALL
8770 || (pathtype
== BGP_PATH_BESTPATH
8771 && CHECK_FLAG(ri
->flags
,
8773 || (pathtype
== BGP_PATH_MULTIPATH
8774 && (CHECK_FLAG(ri
->flags
,
8776 || CHECK_FLAG(ri
->flags
,
8777 BGP_INFO_SELECTED
))))
8778 route_vty_out_detail(vty
, bgp
, &rm
->p
,
8783 bgp_unlock_node(rm
);
8785 } else if (safi
== SAFI_FLOWSPEC
) {
8786 display
= bgp_flowspec_display_match_per_ip(afi
, rib
,
8787 &match
, prefix_check
,
8794 if ((rn
= bgp_node_match(rib
, &match
)) != NULL
) {
8796 || rn
->p
.prefixlen
== match
.prefixlen
) {
8797 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
8799 route_vty_out_detail_header(
8800 vty
, bgp
, rn
, NULL
, afi
,
8806 if (pathtype
== BGP_PATH_ALL
8807 || (pathtype
== BGP_PATH_BESTPATH
8811 || (pathtype
== BGP_PATH_MULTIPATH
8817 BGP_INFO_SELECTED
))))
8818 route_vty_out_detail(
8819 vty
, bgp
, &rn
->p
, ri
,
8820 afi
, safi
, json_paths
);
8824 bgp_unlock_node(rn
);
8830 json_object_object_add(json
, "paths", json_paths
);
8832 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
8833 json
, JSON_C_TO_STRING_PRETTY
));
8834 json_object_free(json
);
8837 vty_out(vty
, "%% Network not in table\n");
8845 /* Display specified route of Main RIB */
8846 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
8847 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
8848 int prefix_check
, enum bgp_path_type pathtype
,
8852 bgp
= bgp_get_default();
8855 vty_out(vty
, "No BGP process is configured\n");
8857 vty_out(vty
, "{}\n");
8862 /* labeled-unicast routes live in the unicast table */
8863 if (safi
== SAFI_LABELED_UNICAST
)
8864 safi
= SAFI_UNICAST
;
8866 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
8867 afi
, safi
, prd
, prefix_check
, pathtype
,
8871 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
8872 struct cmd_token
**argv
, afi_t afi
, safi_t safi
,
8875 struct lcommunity
*lcom
;
8881 b
= buffer_new(1024);
8882 for (i
= 0; i
< argc
; i
++) {
8884 buffer_putc(b
, ' ');
8886 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
8888 buffer_putstr(b
, argv
[i
]->arg
);
8892 buffer_putc(b
, '\0');
8894 str
= buffer_getstr(b
);
8897 lcom
= lcommunity_str2com(str
);
8898 XFREE(MTYPE_TMP
, str
);
8900 vty_out(vty
, "%% Large-community malformed\n");
8904 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_lcommunity
, lcom
,
8908 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
8909 const char *lcom
, afi_t afi
, safi_t safi
,
8912 struct community_list
*list
;
8914 list
= community_list_lookup(bgp_clist
, lcom
,
8915 LARGE_COMMUNITY_LIST_MASTER
);
8917 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
8922 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_lcommunity_list
,
8926 DEFUN (show_ip_bgp_large_community_list
,
8927 show_ip_bgp_large_community_list_cmd
,
8928 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community-list <(1-500)|WORD> [json]",
8932 BGP_INSTANCE_HELP_STR
8934 BGP_SAFI_WITH_LABEL_HELP_STR
8935 "Display routes matching the large-community-list\n"
8936 "large-community-list number\n"
8937 "large-community-list name\n"
8941 afi_t afi
= AFI_IP6
;
8942 safi_t safi
= SAFI_UNICAST
;
8945 if (argv_find(argv
, argc
, "ip", &idx
))
8947 if (argv_find(argv
, argc
, "view", &idx
)
8948 || argv_find(argv
, argc
, "vrf", &idx
))
8949 vrf
= argv
[++idx
]->arg
;
8950 if (argv_find(argv
, argc
, "ipv4", &idx
)
8951 || argv_find(argv
, argc
, "ipv6", &idx
)) {
8952 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
8953 if (argv_find(argv
, argc
, "unicast", &idx
)
8954 || argv_find(argv
, argc
, "multicast", &idx
))
8955 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
8958 int uj
= use_json(argc
, argv
);
8960 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
8962 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
8966 argv_find(argv
, argc
, "large-community-list", &idx
);
8967 return bgp_show_lcommunity_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
, safi
,
8970 DEFUN (show_ip_bgp_large_community
,
8971 show_ip_bgp_large_community_cmd
,
8972 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [AA:BB:CC] [json]",
8976 BGP_INSTANCE_HELP_STR
8978 BGP_SAFI_WITH_LABEL_HELP_STR
8979 "Display routes matching the large-communities\n"
8980 "List of large-community numbers\n"
8984 afi_t afi
= AFI_IP6
;
8985 safi_t safi
= SAFI_UNICAST
;
8988 if (argv_find(argv
, argc
, "ip", &idx
))
8990 if (argv_find(argv
, argc
, "view", &idx
)
8991 || argv_find(argv
, argc
, "vrf", &idx
))
8992 vrf
= argv
[++idx
]->arg
;
8993 if (argv_find(argv
, argc
, "ipv4", &idx
)
8994 || argv_find(argv
, argc
, "ipv6", &idx
)) {
8995 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
8996 if (argv_find(argv
, argc
, "unicast", &idx
)
8997 || argv_find(argv
, argc
, "multicast", &idx
))
8998 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
9001 int uj
= use_json(argc
, argv
);
9003 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
9005 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
9009 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
))
9010 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
, afi
, safi
, uj
);
9012 return bgp_show(vty
, bgp
, afi
, safi
,
9013 bgp_show_type_lcommunity_all
, NULL
, uj
);
9016 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
9020 /* BGP route print out function without JSON */
9023 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
9024 <dampening <parameters>\
9029 |community-list <(1-500)|WORD> [exact-match]\
9030 |A.B.C.D/M longer-prefixes\
9031 |X:X::X:X/M longer-prefixes\
9036 BGP_INSTANCE_HELP_STR
9038 BGP_SAFI_WITH_LABEL_HELP_STR
9039 "Display detailed information about dampening\n"
9040 "Display detail of configured dampening parameters\n"
9041 "Display routes matching the route-map\n"
9042 "A route-map to match on\n"
9043 "Display routes conforming to the prefix-list\n"
9044 "Prefix-list name\n"
9045 "Display routes conforming to the filter-list\n"
9046 "Regular expression access list name\n"
9047 "BGP RIB advertisement statistics\n"
9048 "Display routes matching the community-list\n"
9049 "community-list number\n"
9050 "community-list name\n"
9051 "Exact match of the communities\n"
9053 "Display route and more specific routes\n"
9055 "Display route and more specific routes\n")
9057 afi_t afi
= AFI_IP6
;
9058 safi_t safi
= SAFI_UNICAST
;
9059 int exact_match
= 0;
9060 struct bgp
*bgp
= NULL
;
9063 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9068 if (argv_find(argv
, argc
, "dampening", &idx
)) {
9069 if (argv_find(argv
, argc
, "parameters", &idx
))
9070 return bgp_show_dampening_parameters(vty
, afi
, safi
);
9073 if (argv_find(argv
, argc
, "prefix-list", &idx
))
9074 return bgp_show_prefix_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9075 safi
, bgp_show_type_prefix_list
);
9077 if (argv_find(argv
, argc
, "filter-list", &idx
))
9078 return bgp_show_filter_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9079 safi
, bgp_show_type_filter_list
);
9081 if (argv_find(argv
, argc
, "statistics", &idx
))
9082 return bgp_table_stats(vty
, bgp
, afi
, safi
);
9084 if (argv_find(argv
, argc
, "route-map", &idx
))
9085 return bgp_show_route_map(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9086 safi
, bgp_show_type_route_map
);
9088 if (argv_find(argv
, argc
, "community-list", &idx
)) {
9089 const char *clist_number_or_name
= argv
[++idx
]->arg
;
9090 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
9092 return bgp_show_community_list(vty
, bgp
, clist_number_or_name
,
9093 exact_match
, afi
, safi
);
9096 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
9097 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
9098 return bgp_show_prefix_longer(vty
, bgp
, argv
[idx
]->arg
, afi
,
9100 bgp_show_type_prefix_longer
);
9105 /* BGP route print out function with JSON */
9106 DEFUN (show_ip_bgp_json
,
9107 show_ip_bgp_json_cmd
,
9108 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
9111 |dampening <flap-statistics|dampened-paths>\
9112 |community [<AA:NN|local-AS|no-advertise|no-export|graceful-shutdown>] [exact-match]\
9117 BGP_INSTANCE_HELP_STR
9119 BGP_SAFI_WITH_LABEL_HELP_STR
9120 "Display only routes with non-natural netmasks\n"
9121 "Display detailed information about dampening\n"
9122 "Display flap statistics of routes\n"
9123 "Display paths suppressed due to dampening\n"
9124 "Display routes matching the communities\n"
9126 "Do not send outside local AS (well-known community)\n"
9127 "Do not advertise to any peer (well-known community)\n"
9128 "Do not export to next AS (well-known community)\n"
9129 "Graceful shutdown (well-known community)\n"
9130 "Exact match of the communities\n"
9133 afi_t afi
= AFI_IP6
;
9134 safi_t safi
= SAFI_UNICAST
;
9135 enum bgp_show_type sh_type
= bgp_show_type_normal
;
9136 struct bgp
*bgp
= NULL
;
9138 int idx_community_type
= 0;
9139 int exact_match
= 0;
9141 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9146 int uj
= use_json(argc
, argv
);
9150 if (argv_find(argv
, argc
, "cidr-only", &idx
))
9151 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_cidr_only
,
9154 if (argv_find(argv
, argc
, "dampening", &idx
)) {
9155 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
9156 return bgp_show(vty
, bgp
, afi
, safi
,
9157 bgp_show_type_dampend_paths
, NULL
, uj
);
9158 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
9159 return bgp_show(vty
, bgp
, afi
, safi
,
9160 bgp_show_type_flap_statistics
, NULL
,
9164 if (argv_find(argv
, argc
, "community", &idx
)) {
9166 /* show a specific community */
9167 if (argv_find(argv
, argc
, "local-AS", &idx_community_type
) ||
9168 argv_find(argv
, argc
, "no-advertise",
9169 &idx_community_type
) ||
9170 argv_find(argv
, argc
, "no-export",
9171 &idx_community_type
) ||
9172 argv_find(argv
, argc
, "graceful-shutdown",
9173 &idx_community_type
) ||
9174 argv_find(argv
, argc
, "AA:NN", &idx_community_type
)) {
9175 if (argv_find(argv
, argc
, "exact-match", &idx
))
9178 return (bgp_show_community(vty
, bgp
,
9179 argv
[idx_community_type
]->arg
,
9180 exact_match
, afi
, safi
, uj
));
9183 /* show all communities */
9184 return (bgp_show(vty
, bgp
, afi
, safi
,
9185 bgp_show_type_community_all
, NULL
,
9190 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
, NULL
, uj
);
9193 DEFUN (show_ip_bgp_route
,
9194 show_ip_bgp_route_cmd
,
9195 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]"
9196 "<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [json]",
9200 BGP_INSTANCE_HELP_STR
9202 BGP_SAFI_WITH_LABEL_HELP_STR
9203 "Network in the BGP routing table to display\n"
9205 "Network in the BGP routing table to display\n"
9207 "Display only the bestpath\n"
9208 "Display only multipaths\n"
9211 int prefix_check
= 0;
9213 afi_t afi
= AFI_IP6
;
9214 safi_t safi
= SAFI_UNICAST
;
9215 char *prefix
= NULL
;
9216 struct bgp
*bgp
= NULL
;
9217 enum bgp_path_type path_type
;
9218 uint8_t uj
= use_json(argc
, argv
);
9222 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9229 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
9233 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
9234 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
9235 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
9237 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
9238 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
9241 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
9242 && afi
!= AFI_IP6
) {
9244 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
9247 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
9250 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
9254 prefix
= argv
[idx
]->arg
;
9256 /* [<bestpath|multipath>] */
9257 if (argv_find(argv
, argc
, "bestpath", &idx
))
9258 path_type
= BGP_PATH_BESTPATH
;
9259 else if (argv_find(argv
, argc
, "multipath", &idx
))
9260 path_type
= BGP_PATH_MULTIPATH
;
9262 path_type
= BGP_PATH_ALL
;
9264 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
9268 DEFUN (show_ip_bgp_regexp
,
9269 show_ip_bgp_regexp_cmd
,
9270 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX...",
9274 BGP_INSTANCE_HELP_STR
9276 BGP_SAFI_WITH_LABEL_HELP_STR
9277 "Display routes matching the AS path regular expression\n"
9278 "A regular-expression to match the BGP AS paths\n")
9280 afi_t afi
= AFI_IP6
;
9281 safi_t safi
= SAFI_UNICAST
;
9282 struct bgp
*bgp
= NULL
;
9285 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9290 // get index of regex
9291 argv_find(argv
, argc
, "regexp", &idx
);
9294 char *regstr
= argv_concat(argv
, argc
, idx
);
9295 int rc
= bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
9296 bgp_show_type_regexp
);
9297 XFREE(MTYPE_TMP
, regstr
);
9301 DEFUN (show_ip_bgp_instance_all
,
9302 show_ip_bgp_instance_all_cmd
,
9303 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json]",
9307 BGP_INSTANCE_ALL_HELP_STR
9309 BGP_SAFI_WITH_LABEL_HELP_STR
9313 safi_t safi
= SAFI_UNICAST
;
9314 struct bgp
*bgp
= NULL
;
9317 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9322 int uj
= use_json(argc
, argv
);
9326 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, uj
);
9330 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
9331 afi_t afi
, safi_t safi
, enum bgp_show_type type
)
9336 regex
= bgp_regcomp(regstr
);
9338 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
9342 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, 0);
9343 bgp_regex_free(regex
);
9347 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
9348 const char *prefix_list_str
, afi_t afi
,
9349 safi_t safi
, enum bgp_show_type type
)
9351 struct prefix_list
*plist
;
9353 plist
= prefix_list_lookup(afi
, prefix_list_str
);
9354 if (plist
== NULL
) {
9355 vty_out(vty
, "%% %s is not a valid prefix-list name\n",
9360 return bgp_show(vty
, bgp
, afi
, safi
, type
, plist
, 0);
9363 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
9364 const char *filter
, afi_t afi
, safi_t safi
,
9365 enum bgp_show_type type
)
9367 struct as_list
*as_list
;
9369 as_list
= as_list_lookup(filter
);
9370 if (as_list
== NULL
) {
9371 vty_out(vty
, "%% %s is not a valid AS-path access-list name\n",
9376 return bgp_show(vty
, bgp
, afi
, safi
, type
, as_list
, 0);
9379 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
9380 const char *rmap_str
, afi_t afi
, safi_t safi
,
9381 enum bgp_show_type type
)
9383 struct route_map
*rmap
;
9385 rmap
= route_map_lookup_by_name(rmap_str
);
9387 vty_out(vty
, "%% %s is not a valid route-map name\n", rmap_str
);
9391 return bgp_show(vty
, bgp
, afi
, safi
, type
, rmap
, 0);
9394 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
9395 const char *comstr
, int exact
, afi_t afi
,
9396 safi_t safi
, uint8_t use_json
)
9398 struct community
*com
;
9401 com
= community_str2com(comstr
);
9403 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
9407 ret
= bgp_show(vty
, bgp
, afi
, safi
,
9408 (exact
? bgp_show_type_community_exact
9409 : bgp_show_type_community
),
9411 community_free(com
);
9416 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
9417 const char *com
, int exact
, afi_t afi
,
9420 struct community_list
*list
;
9422 list
= community_list_lookup(bgp_clist
, com
, COMMUNITY_LIST_MASTER
);
9424 vty_out(vty
, "%% %s is not a valid community-list name\n", com
);
9428 return bgp_show(vty
, bgp
, afi
, safi
,
9429 (exact
? bgp_show_type_community_list_exact
9430 : bgp_show_type_community_list
),
9434 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
9435 const char *prefix
, afi_t afi
, safi_t safi
,
9436 enum bgp_show_type type
)
9443 ret
= str2prefix(prefix
, p
);
9445 vty_out(vty
, "%% Malformed Prefix\n");
9449 ret
= bgp_show(vty
, bgp
, afi
, safi
, type
, p
, 0);
9454 static struct peer
*peer_lookup_in_view(struct vty
*vty
, struct bgp
*bgp
,
9455 const char *ip_str
, uint8_t use_json
)
9461 /* Get peer sockunion. */
9462 ret
= str2sockunion(ip_str
, &su
);
9464 peer
= peer_lookup_by_conf_if(bgp
, ip_str
);
9466 peer
= peer_lookup_by_hostname(bgp
, ip_str
);
9470 json_object
*json_no
= NULL
;
9471 json_no
= json_object_new_object();
9472 json_object_string_add(
9474 "malformedAddressOrName",
9476 vty_out(vty
, "%s\n",
9477 json_object_to_json_string_ext(
9479 JSON_C_TO_STRING_PRETTY
));
9480 json_object_free(json_no
);
9483 "%% Malformed address or name: %s\n",
9491 /* Peer structure lookup. */
9492 peer
= peer_lookup(bgp
, &su
);
9495 json_object
*json_no
= NULL
;
9496 json_no
= json_object_new_object();
9497 json_object_string_add(json_no
, "warning",
9498 "No such neighbor in this view/vrf");
9499 vty_out(vty
, "%s\n",
9500 json_object_to_json_string_ext(
9501 json_no
, JSON_C_TO_STRING_PRETTY
));
9502 json_object_free(json_no
);
9504 vty_out(vty
, "No such neighbor in this view/vrf\n");
9512 BGP_STATS_MAXBITLEN
= 0,
9516 BGP_STATS_UNAGGREGATEABLE
,
9517 BGP_STATS_MAX_AGGREGATEABLE
,
9518 BGP_STATS_AGGREGATES
,
9520 BGP_STATS_ASPATH_COUNT
,
9521 BGP_STATS_ASPATH_MAXHOPS
,
9522 BGP_STATS_ASPATH_TOTHOPS
,
9523 BGP_STATS_ASPATH_MAXSIZE
,
9524 BGP_STATS_ASPATH_TOTSIZE
,
9525 BGP_STATS_ASN_HIGHEST
,
9529 static const char *table_stats_strs
[] = {
9530 [BGP_STATS_PREFIXES
] = "Total Prefixes",
9531 [BGP_STATS_TOTPLEN
] = "Average prefix length",
9532 [BGP_STATS_RIB
] = "Total Advertisements",
9533 [BGP_STATS_UNAGGREGATEABLE
] = "Unaggregateable prefixes",
9534 [BGP_STATS_MAX_AGGREGATEABLE
] =
9535 "Maximum aggregateable prefixes",
9536 [BGP_STATS_AGGREGATES
] = "BGP Aggregate advertisements",
9537 [BGP_STATS_SPACE
] = "Address space advertised",
9538 [BGP_STATS_ASPATH_COUNT
] = "Advertisements with paths",
9539 [BGP_STATS_ASPATH_MAXHOPS
] = "Longest AS-Path (hops)",
9540 [BGP_STATS_ASPATH_MAXSIZE
] = "Largest AS-Path (bytes)",
9541 [BGP_STATS_ASPATH_TOTHOPS
] = "Average AS-Path length (hops)",
9542 [BGP_STATS_ASPATH_TOTSIZE
] = "Average AS-Path size (bytes)",
9543 [BGP_STATS_ASN_HIGHEST
] = "Highest public ASN",
9544 [BGP_STATS_MAX
] = NULL
,
9547 struct bgp_table_stats
{
9548 struct bgp_table
*table
;
9549 unsigned long long counts
[BGP_STATS_MAX
];
9554 #define TALLY_SIGFIG 100000
9555 static unsigned long
9556 ravg_tally (unsigned long count
, unsigned long oldavg
, unsigned long newval
)
9558 unsigned long newtot
= (count
-1) * oldavg
+ (newval
* TALLY_SIGFIG
);
9559 unsigned long res
= (newtot
* TALLY_SIGFIG
) / count
;
9560 unsigned long ret
= newtot
/ count
;
9562 if ((res
% TALLY_SIGFIG
) > (TALLY_SIGFIG
/2))
9569 static int bgp_table_stats_walker(struct thread
*t
)
9571 struct bgp_node
*rn
;
9572 struct bgp_node
*top
;
9573 struct bgp_table_stats
*ts
= THREAD_ARG(t
);
9574 unsigned int space
= 0;
9576 if (!(top
= bgp_table_top(ts
->table
)))
9579 switch (top
->p
.family
) {
9581 space
= IPV4_MAX_BITLEN
;
9584 space
= IPV6_MAX_BITLEN
;
9588 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
9590 for (rn
= top
; rn
; rn
= bgp_route_next(rn
)) {
9591 struct bgp_info
*ri
;
9592 struct bgp_node
*prn
= bgp_node_parent_nolock(rn
);
9593 unsigned int rinum
= 0;
9601 ts
->counts
[BGP_STATS_PREFIXES
]++;
9602 ts
->counts
[BGP_STATS_TOTPLEN
] += rn
->p
.prefixlen
;
9605 ts
->counts
[BGP_STATS_AVGPLEN
]
9606 = ravg_tally (ts
->counts
[BGP_STATS_PREFIXES
],
9607 ts
->counts
[BGP_STATS_AVGPLEN
],
9611 /* check if the prefix is included by any other announcements */
9612 while (prn
&& !prn
->info
)
9613 prn
= bgp_node_parent_nolock(prn
);
9615 if (prn
== NULL
|| prn
== top
) {
9616 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
9617 /* announced address space */
9620 pow(2.0, space
- rn
->p
.prefixlen
);
9621 } else if (prn
->info
)
9622 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
9624 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
9626 ts
->counts
[BGP_STATS_RIB
]++;
9629 && (CHECK_FLAG(ri
->attr
->flag
,
9631 BGP_ATTR_ATOMIC_AGGREGATE
))))
9632 ts
->counts
[BGP_STATS_AGGREGATES
]++;
9635 if (ri
->attr
&& ri
->attr
->aspath
) {
9637 aspath_count_hops(ri
->attr
->aspath
);
9639 aspath_size(ri
->attr
->aspath
);
9640 as_t highest
= aspath_highest(ri
->attr
->aspath
);
9642 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
9644 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
9645 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] =
9648 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
9649 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] =
9652 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
9653 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
9655 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
]
9656 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
9657 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
],
9659 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
]
9660 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
9661 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
],
9664 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
9665 ts
->counts
[BGP_STATS_ASN_HIGHEST
] =
9673 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
9676 struct bgp_table_stats ts
;
9679 if (!bgp
->rib
[afi
][safi
]) {
9680 vty_out(vty
, "%% No RIB exist's for the AFI(%d)/SAFI(%d)\n",
9685 vty_out(vty
, "BGP %s RIB statistics\n", afi_safi_print(afi
, safi
));
9687 /* labeled-unicast routes live in the unicast table */
9688 if (safi
== SAFI_LABELED_UNICAST
)
9689 safi
= SAFI_UNICAST
;
9691 memset(&ts
, 0, sizeof(ts
));
9692 ts
.table
= bgp
->rib
[afi
][safi
];
9693 thread_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
9695 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
9696 if (!table_stats_strs
[i
])
9701 case BGP_STATS_ASPATH_AVGHOPS
:
9702 case BGP_STATS_ASPATH_AVGSIZE
:
9703 case BGP_STATS_AVGPLEN
:
9704 vty_out (vty
, "%-30s: ", table_stats_strs
[i
]);
9705 vty_out (vty
, "%12.2f",
9706 (float)ts
.counts
[i
] / (float)TALLY_SIGFIG
);
9709 case BGP_STATS_ASPATH_TOTHOPS
:
9710 case BGP_STATS_ASPATH_TOTSIZE
:
9711 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9712 vty_out(vty
, "%12.2f",
9714 ? (float)ts
.counts
[i
]
9716 [BGP_STATS_ASPATH_COUNT
]
9719 case BGP_STATS_TOTPLEN
:
9720 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9721 vty_out(vty
, "%12.2f",
9723 ? (float)ts
.counts
[i
]
9725 [BGP_STATS_PREFIXES
]
9728 case BGP_STATS_SPACE
:
9729 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9730 vty_out(vty
, "%12g\n", ts
.total_space
);
9732 if (afi
== AFI_IP6
) {
9733 vty_out(vty
, "%30s: ", "/32 equivalent ");
9734 vty_out(vty
, "%12g\n",
9735 ts
.total_space
* pow(2.0, -128 + 32));
9736 vty_out(vty
, "%30s: ", "/48 equivalent ");
9737 vty_out(vty
, "%12g\n",
9738 ts
.total_space
* pow(2.0, -128 + 48));
9740 vty_out(vty
, "%30s: ", "% announced ");
9741 vty_out(vty
, "%12.2f\n",
9742 ts
.total_space
* 100. * pow(2.0, -32));
9743 vty_out(vty
, "%30s: ", "/8 equivalent ");
9744 vty_out(vty
, "%12.2f\n",
9745 ts
.total_space
* pow(2.0, -32 + 8));
9746 vty_out(vty
, "%30s: ", "/24 equivalent ");
9747 vty_out(vty
, "%12.2f\n",
9748 ts
.total_space
* pow(2.0, -32 + 24));
9752 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9753 vty_out(vty
, "%12llu", ts
.counts
[i
]);
9770 PCOUNT_PFCNT
, /* the figure we display to users */
9774 static const char *pcount_strs
[] = {
9775 [PCOUNT_ADJ_IN
] = "Adj-in",
9776 [PCOUNT_DAMPED
] = "Damped",
9777 [PCOUNT_REMOVED
] = "Removed",
9778 [PCOUNT_HISTORY
] = "History",
9779 [PCOUNT_STALE
] = "Stale",
9780 [PCOUNT_VALID
] = "Valid",
9781 [PCOUNT_ALL
] = "All RIB",
9782 [PCOUNT_COUNTED
] = "PfxCt counted",
9783 [PCOUNT_PFCNT
] = "Useable",
9784 [PCOUNT_MAX
] = NULL
,
9787 struct peer_pcounts
{
9788 unsigned int count
[PCOUNT_MAX
];
9789 const struct peer
*peer
;
9790 const struct bgp_table
*table
;
9793 static int bgp_peer_count_walker(struct thread
*t
)
9795 struct bgp_node
*rn
;
9796 struct peer_pcounts
*pc
= THREAD_ARG(t
);
9797 const struct peer
*peer
= pc
->peer
;
9799 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
)) {
9800 struct bgp_adj_in
*ain
;
9801 struct bgp_info
*ri
;
9803 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
9804 if (ain
->peer
== peer
)
9805 pc
->count
[PCOUNT_ADJ_IN
]++;
9807 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
9808 if (ri
->peer
!= peer
)
9811 pc
->count
[PCOUNT_ALL
]++;
9813 if (CHECK_FLAG(ri
->flags
, BGP_INFO_DAMPED
))
9814 pc
->count
[PCOUNT_DAMPED
]++;
9815 if (CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
9816 pc
->count
[PCOUNT_HISTORY
]++;
9817 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
))
9818 pc
->count
[PCOUNT_REMOVED
]++;
9819 if (CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
))
9820 pc
->count
[PCOUNT_STALE
]++;
9821 if (CHECK_FLAG(ri
->flags
, BGP_INFO_VALID
))
9822 pc
->count
[PCOUNT_VALID
]++;
9823 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
9824 pc
->count
[PCOUNT_PFCNT
]++;
9826 if (CHECK_FLAG(ri
->flags
, BGP_INFO_COUNTED
)) {
9827 pc
->count
[PCOUNT_COUNTED
]++;
9828 if (CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
9829 flog_err(LIB_ERR_DEVELOPMENT
,
9830 "Attempting to count but flags say it is unusable");
9832 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
9833 flog_err(LIB_ERR_DEVELOPMENT
,
9834 "Not counted but flags say we should");
9841 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
9842 safi_t safi
, uint8_t use_json
)
9844 struct peer_pcounts pcounts
= {.peer
= peer
};
9846 json_object
*json
= NULL
;
9847 json_object
*json_loop
= NULL
;
9850 json
= json_object_new_object();
9851 json_loop
= json_object_new_object();
9854 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
9855 || !peer
->bgp
->rib
[afi
][safi
]) {
9857 json_object_string_add(
9859 "No such neighbor or address family");
9860 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
9861 json_object_free(json
);
9863 vty_out(vty
, "%% No such neighbor or address family\n");
9868 memset(&pcounts
, 0, sizeof(pcounts
));
9869 pcounts
.peer
= peer
;
9870 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
9872 /* in-place call via thread subsystem so as to record execution time
9873 * stats for the thread-walk (i.e. ensure this can't be blamed on
9874 * on just vty_read()).
9876 thread_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
9879 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
9880 json_object_string_add(json
, "multiProtocol",
9881 afi_safi_print(afi
, safi
));
9882 json_object_int_add(json
, "pfxCounter",
9883 peer
->pcount
[afi
][safi
]);
9885 for (i
= 0; i
< PCOUNT_MAX
; i
++)
9886 json_object_int_add(json_loop
, pcount_strs
[i
],
9889 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
9891 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
9892 json_object_string_add(json
, "pfxctDriftFor",
9894 json_object_string_add(
9895 json
, "recommended",
9896 "Please report this bug, with the above command output");
9898 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
9899 json
, JSON_C_TO_STRING_PRETTY
));
9900 json_object_free(json
);
9904 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
9905 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
9906 peer
->hostname
, peer
->host
,
9907 afi_safi_print(afi
, safi
));
9909 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
9910 afi_safi_print(afi
, safi
));
9913 vty_out(vty
, "PfxCt: %ld\n", peer
->pcount
[afi
][safi
]);
9914 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
9916 for (i
= 0; i
< PCOUNT_MAX
; i
++)
9917 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
9920 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
9921 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
9923 "Please report this bug, with the above command output\n");
9930 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
9931 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
9932 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_CMD_STR
"]] "
9933 "neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
9937 BGP_INSTANCE_HELP_STR
9940 "Detailed information on TCP and BGP neighbor connections\n"
9941 "Neighbor to display information about\n"
9942 "Neighbor to display information about\n"
9943 "Neighbor on BGP configured interface\n"
9944 "Display detailed prefix count information\n"
9947 afi_t afi
= AFI_IP6
;
9948 safi_t safi
= SAFI_UNICAST
;
9951 struct bgp
*bgp
= NULL
;
9953 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9958 int uj
= use_json(argc
, argv
);
9962 argv_find(argv
, argc
, "neighbors", &idx
);
9963 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
9967 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_UNICAST
, uj
);
9970 #ifdef KEEP_OLD_VPN_COMMANDS
9971 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
9972 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
9973 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
9978 "Display information about all VPNv4 NLRIs\n"
9979 "Detailed information on TCP and BGP neighbor connections\n"
9980 "Neighbor to display information about\n"
9981 "Neighbor to display information about\n"
9982 "Neighbor on BGP configured interface\n"
9983 "Display detailed prefix count information\n"
9988 uint8_t uj
= use_json(argc
, argv
);
9990 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
9994 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
9997 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
9998 show_ip_bgp_vpn_all_route_prefix_cmd
,
9999 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
10004 "Display information about all VPNv4 NLRIs\n"
10005 "Network in the BGP routing table to display\n"
10006 "Network in the BGP routing table to display\n"
10010 char *network
= NULL
;
10011 struct bgp
*bgp
= bgp_get_default();
10013 vty_out(vty
, "Can't find default instance\n");
10014 return CMD_WARNING
;
10017 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
10018 network
= argv
[idx
]->arg
;
10019 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
10020 network
= argv
[idx
]->arg
;
10022 vty_out(vty
, "Unable to figure out Network\n");
10023 return CMD_WARNING
;
10026 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
10027 BGP_PATH_ALL
, use_json(argc
, argv
));
10029 #endif /* KEEP_OLD_VPN_COMMANDS */
10031 DEFUN (show_ip_bgp_l2vpn_evpn_all_route_prefix
,
10032 show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd
,
10033 "show [ip] bgp l2vpn evpn all <A.B.C.D|A.B.C.D/M> [json]",
10039 "Display information about all EVPN NLRIs\n"
10040 "Network in the BGP routing table to display\n"
10041 "Network in the BGP routing table to display\n"
10045 char *network
= NULL
;
10047 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
10048 network
= argv
[idx
]->arg
;
10049 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
10050 network
= argv
[idx
]->arg
;
10052 vty_out(vty
, "Unable to figure out Network\n");
10053 return CMD_WARNING
;
10055 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
, 0,
10056 BGP_PATH_ALL
, use_json(argc
, argv
));
10059 static void show_adj_route(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
10060 safi_t safi
, enum bgp_show_adj_route_type type
,
10061 const char *rmap_name
, uint8_t use_json
,
10064 struct bgp_table
*table
;
10065 struct bgp_adj_in
*ain
;
10066 struct bgp_adj_out
*adj
;
10067 unsigned long output_count
;
10068 unsigned long filtered_count
;
10069 struct bgp_node
*rn
;
10075 struct update_subgroup
*subgrp
;
10076 json_object
*json_scode
= NULL
;
10077 json_object
*json_ocode
= NULL
;
10078 json_object
*json_ar
= NULL
;
10079 struct peer_af
*paf
;
10080 bool route_filtered
;
10083 json_scode
= json_object_new_object();
10084 json_ocode
= json_object_new_object();
10085 json_ar
= json_object_new_object();
10087 json_object_string_add(json_scode
, "suppressed", "s");
10088 json_object_string_add(json_scode
, "damped", "d");
10089 json_object_string_add(json_scode
, "history", "h");
10090 json_object_string_add(json_scode
, "valid", "*");
10091 json_object_string_add(json_scode
, "best", ">");
10092 json_object_string_add(json_scode
, "multipath", "=");
10093 json_object_string_add(json_scode
, "internal", "i");
10094 json_object_string_add(json_scode
, "ribFailure", "r");
10095 json_object_string_add(json_scode
, "stale", "S");
10096 json_object_string_add(json_scode
, "removed", "R");
10098 json_object_string_add(json_ocode
, "igp", "i");
10099 json_object_string_add(json_ocode
, "egp", "e");
10100 json_object_string_add(json_ocode
, "incomplete", "?");
10107 json_object_string_add(json
, "alert", "no BGP");
10108 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10109 json_object_free(json
);
10111 vty_out(vty
, "%% No bgp\n");
10115 table
= bgp
->rib
[afi
][safi
];
10117 output_count
= filtered_count
= 0;
10118 subgrp
= peer_subgroup(peer
, afi
, safi
);
10120 if (type
== bgp_show_adj_route_advertised
&& subgrp
10121 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
10123 json_object_int_add(json
, "bgpTableVersion",
10125 json_object_string_add(json
, "bgpLocalRouterId",
10126 inet_ntoa(bgp
->router_id
));
10127 json_object_object_add(json
, "bgpStatusCodes",
10129 json_object_object_add(json
, "bgpOriginCodes",
10131 json_object_string_add(
10132 json
, "bgpOriginatingDefaultNetwork",
10133 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
10135 vty_out(vty
, "BGP table version is %" PRIu64
10136 ", local router ID is %s, vrf id ",
10137 table
->version
, inet_ntoa(bgp
->router_id
));
10138 if (bgp
->vrf_id
== VRF_UNKNOWN
)
10139 vty_out(vty
, "%s", VRFID_NONE_STR
);
10141 vty_out(vty
, "%u", bgp
->vrf_id
);
10142 vty_out(vty
, "\n");
10143 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
10144 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
10145 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
10147 vty_out(vty
, "Originating default network %s\n\n",
10148 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
10153 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
10154 if (type
== bgp_show_adj_route_received
10155 || type
== bgp_show_adj_route_filtered
) {
10156 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
10157 if (ain
->peer
!= peer
|| !ain
->attr
)
10162 json_object_int_add(
10163 json
, "bgpTableVersion",
10165 json_object_string_add(
10167 "bgpLocalRouterId",
10170 json_object_object_add(
10171 json
, "bgpStatusCodes",
10173 json_object_object_add(
10174 json
, "bgpOriginCodes",
10178 "BGP table version is 0, local router ID is %s, vrf id ",
10181 if (bgp
->vrf_id
== VRF_UNKNOWN
)
10187 vty_out(vty
, "\n");
10189 BGP_SHOW_SCODE_HEADER
);
10191 BGP_SHOW_NCODE_HEADER
);
10193 BGP_SHOW_OCODE_HEADER
);
10199 vty_out(vty
, BGP_SHOW_HEADER
);
10203 bgp_attr_dup(&attr
, ain
->attr
);
10204 route_filtered
= false;
10206 /* Filter prefix using distribute list,
10207 * filter list or prefix list
10209 if ((bgp_input_filter(peer
, &rn
->p
, &attr
, afi
,
10210 safi
)) == FILTER_DENY
)
10211 route_filtered
= true;
10213 /* Filter prefix using route-map */
10214 ret
= bgp_input_modifier(peer
, &rn
->p
, &attr
,
10215 afi
, safi
, rmap_name
);
10217 if (type
== bgp_show_adj_route_filtered
&&
10218 !route_filtered
&& ret
!= RMAP_DENY
) {
10219 bgp_attr_undup(&attr
, ain
->attr
);
10223 if (type
== bgp_show_adj_route_received
&&
10224 (route_filtered
|| ret
== RMAP_DENY
))
10227 route_vty_out_tmp(vty
, &rn
->p
, &attr
, safi
,
10228 use_json
, json_ar
);
10229 bgp_attr_undup(&attr
, ain
->attr
);
10232 } else if (type
== bgp_show_adj_route_advertised
) {
10233 for (adj
= rn
->adj_out
; adj
; adj
= adj
->next
)
10234 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
10235 if (paf
->peer
!= peer
|| !adj
->attr
)
10240 json_object_int_add(
10244 json_object_string_add(
10246 "bgpLocalRouterId",
10249 json_object_object_add(
10253 json_object_object_add(
10259 "BGP table version is %" PRIu64
10260 ", local router ID is %s, vrf id ",
10273 vty_out(vty
, "\n");
10275 BGP_SHOW_SCODE_HEADER
);
10277 BGP_SHOW_NCODE_HEADER
);
10279 BGP_SHOW_OCODE_HEADER
);
10290 bgp_attr_dup(&attr
, adj
->attr
);
10291 ret
= bgp_output_modifier(
10292 peer
, &rn
->p
, &attr
, afi
, safi
,
10295 if (ret
!= RMAP_DENY
) {
10296 route_vty_out_tmp(vty
, &rn
->p
,
10305 bgp_attr_undup(&attr
, adj
->attr
);
10311 json_object_object_add(json
, "advertisedRoutes", json_ar
);
10312 json_object_int_add(json
, "totalPrefixCounter", output_count
);
10313 json_object_int_add(json
, "filteredPrefixCounter",
10316 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
10317 json
, JSON_C_TO_STRING_PRETTY
));
10318 json_object_free(json
);
10319 } else if (output_count
> 0) {
10320 if (filtered_count
> 0)
10322 "\nTotal number of prefixes %ld (%ld filtered)\n",
10323 output_count
, filtered_count
);
10325 vty_out(vty
, "\nTotal number of prefixes %ld\n",
10330 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
10331 safi_t safi
, enum bgp_show_adj_route_type type
,
10332 const char *rmap_name
, uint8_t use_json
)
10334 json_object
*json
= NULL
;
10337 json
= json_object_new_object();
10339 /* labeled-unicast routes live in the unicast table */
10340 if (safi
== SAFI_LABELED_UNICAST
)
10341 safi
= SAFI_UNICAST
;
10343 if (!peer
|| !peer
->afc
[afi
][safi
]) {
10345 json_object_string_add(
10347 "No such neighbor or address family");
10348 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10349 json_object_free(json
);
10351 vty_out(vty
, "%% No such neighbor or address family\n");
10353 return CMD_WARNING
;
10356 if ((type
== bgp_show_adj_route_received
10357 || type
== bgp_show_adj_route_filtered
)
10358 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
10359 PEER_FLAG_SOFT_RECONFIG
)) {
10361 json_object_string_add(
10363 "Inbound soft reconfiguration not enabled");
10364 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10365 json_object_free(json
);
10368 "%% Inbound soft reconfiguration not enabled\n");
10370 return CMD_WARNING
;
10373 show_adj_route(vty
, peer
, afi
, safi
, type
, rmap_name
, use_json
, json
);
10375 return CMD_SUCCESS
;
10378 DEFUN (show_ip_bgp_instance_neighbor_advertised_route
,
10379 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
10380 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
10381 "neighbors <A.B.C.D|X:X::X:X|WORD> <advertised-routes|received-routes|filtered-routes> [route-map WORD] [json]",
10385 BGP_INSTANCE_HELP_STR
10387 BGP_SAFI_WITH_LABEL_HELP_STR
10388 "Detailed information on TCP and BGP neighbor connections\n"
10389 "Neighbor to display information about\n"
10390 "Neighbor to display information about\n"
10391 "Neighbor on BGP configured interface\n"
10392 "Display the routes advertised to a BGP neighbor\n"
10393 "Display the received routes from neighbor\n"
10394 "Display the filtered routes received from neighbor\n"
10395 "Route-map to modify the attributes\n"
10396 "Name of the route map\n"
10399 afi_t afi
= AFI_IP6
;
10400 safi_t safi
= SAFI_UNICAST
;
10401 char *rmap_name
= NULL
;
10402 char *peerstr
= NULL
;
10403 struct bgp
*bgp
= NULL
;
10405 enum bgp_show_adj_route_type type
= bgp_show_adj_route_advertised
;
10408 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10411 return CMD_WARNING
;
10413 int uj
= use_json(argc
, argv
);
10418 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10419 argv_find(argv
, argc
, "neighbors", &idx
);
10420 peerstr
= argv
[++idx
]->arg
;
10422 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
10424 return CMD_WARNING
;
10426 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
10427 type
= bgp_show_adj_route_advertised
;
10428 else if (argv_find(argv
, argc
, "received-routes", &idx
))
10429 type
= bgp_show_adj_route_received
;
10430 else if (argv_find(argv
, argc
, "filtered-routes", &idx
))
10431 type
= bgp_show_adj_route_filtered
;
10433 if (argv_find(argv
, argc
, "route-map", &idx
))
10434 rmap_name
= argv
[++idx
]->arg
;
10436 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
, uj
);
10439 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
10440 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
10441 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
10447 "Address Family modifier\n"
10448 "Detailed information on TCP and BGP neighbor connections\n"
10449 "Neighbor to display information about\n"
10450 "Neighbor to display information about\n"
10451 "Neighbor on BGP configured interface\n"
10452 "Display information received from a BGP neighbor\n"
10453 "Display the prefixlist filter\n"
10456 afi_t afi
= AFI_IP6
;
10457 safi_t safi
= SAFI_UNICAST
;
10458 char *peerstr
= NULL
;
10461 union sockunion su
;
10467 /* show [ip] bgp */
10468 if (argv_find(argv
, argc
, "ip", &idx
))
10470 /* [<ipv4|ipv6> [unicast]] */
10471 if (argv_find(argv
, argc
, "ipv4", &idx
))
10473 if (argv_find(argv
, argc
, "ipv6", &idx
))
10475 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10476 argv_find(argv
, argc
, "neighbors", &idx
);
10477 peerstr
= argv
[++idx
]->arg
;
10479 uint8_t uj
= use_json(argc
, argv
);
10481 ret
= str2sockunion(peerstr
, &su
);
10483 peer
= peer_lookup_by_conf_if(NULL
, peerstr
);
10486 vty_out(vty
, "{}\n");
10489 "%% Malformed address or name: %s\n",
10491 return CMD_WARNING
;
10494 peer
= peer_lookup(NULL
, &su
);
10497 vty_out(vty
, "{}\n");
10499 vty_out(vty
, "No peer\n");
10500 return CMD_WARNING
;
10504 sprintf(name
, "%s.%d.%d", peer
->host
, afi
, safi
);
10505 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
10508 vty_out(vty
, "Address Family: %s\n",
10509 afi_safi_print(afi
, safi
));
10510 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
10513 vty_out(vty
, "{}\n");
10515 vty_out(vty
, "No functional output\n");
10518 return CMD_SUCCESS
;
10521 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
10522 afi_t afi
, safi_t safi
,
10523 enum bgp_show_type type
, uint8_t use_json
)
10525 /* labeled-unicast routes live in the unicast table */
10526 if (safi
== SAFI_LABELED_UNICAST
)
10527 safi
= SAFI_UNICAST
;
10529 if (!peer
|| !peer
->afc
[afi
][safi
]) {
10531 json_object
*json_no
= NULL
;
10532 json_no
= json_object_new_object();
10533 json_object_string_add(
10534 json_no
, "warning",
10535 "No such neighbor or address family");
10536 vty_out(vty
, "%s\n",
10537 json_object_to_json_string(json_no
));
10538 json_object_free(json_no
);
10540 vty_out(vty
, "%% No such neighbor or address family\n");
10541 return CMD_WARNING
;
10544 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, use_json
);
10547 DEFUN (show_ip_bgp_flowspec_routes_detailed
,
10548 show_ip_bgp_flowspec_routes_detailed_cmd
,
10549 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" flowspec] detail [json]",
10553 BGP_INSTANCE_HELP_STR
10556 "Detailed information on flowspec entries\n"
10559 afi_t afi
= AFI_IP
;
10560 safi_t safi
= SAFI_UNICAST
;
10561 struct bgp
*bgp
= NULL
;
10564 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10567 return CMD_WARNING
;
10569 return bgp_show(vty
, bgp
, afi
, safi
,
10570 bgp_show_type_detail
, NULL
, use_json(argc
, argv
));
10573 DEFUN (show_ip_bgp_neighbor_routes
,
10574 show_ip_bgp_neighbor_routes_cmd
,
10575 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
10576 "neighbors <A.B.C.D|X:X::X:X|WORD> <flap-statistics|dampened-routes|routes> [json]",
10580 BGP_INSTANCE_HELP_STR
10582 BGP_SAFI_WITH_LABEL_HELP_STR
10583 "Detailed information on TCP and BGP neighbor connections\n"
10584 "Neighbor to display information about\n"
10585 "Neighbor to display information about\n"
10586 "Neighbor on BGP configured interface\n"
10587 "Display flap statistics of the routes learned from neighbor\n"
10588 "Display the dampened routes received from neighbor\n"
10589 "Display routes learned from neighbor\n"
10592 char *peerstr
= NULL
;
10593 struct bgp
*bgp
= NULL
;
10594 afi_t afi
= AFI_IP6
;
10595 safi_t safi
= SAFI_UNICAST
;
10597 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
10601 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10604 return CMD_WARNING
;
10606 int uj
= use_json(argc
, argv
);
10610 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10611 argv_find(argv
, argc
, "neighbors", &idx
);
10612 peerstr
= argv
[++idx
]->arg
;
10614 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
10616 return CMD_WARNING
;
10618 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
10619 sh_type
= bgp_show_type_flap_neighbor
;
10620 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
10621 sh_type
= bgp_show_type_damp_neighbor
;
10622 else if (argv_find(argv
, argc
, "routes", &idx
))
10623 sh_type
= bgp_show_type_neighbor
;
10625 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
10628 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
10630 struct bgp_distance
{
10631 /* Distance value for the IP source prefix. */
10634 /* Name of the access-list to be matched. */
10638 DEFUN (show_bgp_afi_vpn_rd_route
,
10639 show_bgp_afi_vpn_rd_route_cmd
,
10640 "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]",
10644 "Address Family modifier\n"
10645 "Display information for a route distinguisher\n"
10646 "Route Distinguisher\n"
10647 "Network in the BGP routing table to display\n"
10648 "Network in the BGP routing table to display\n"
10652 struct prefix_rd prd
;
10653 afi_t afi
= AFI_MAX
;
10656 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
10657 vty_out(vty
, "%% Malformed Address Family\n");
10658 return CMD_WARNING
;
10661 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
10663 vty_out(vty
, "%% Malformed Route Distinguisher\n");
10664 return CMD_WARNING
;
10667 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
10668 0, BGP_PATH_ALL
, use_json(argc
, argv
));
10671 static struct bgp_distance
*bgp_distance_new(void)
10673 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
10676 static void bgp_distance_free(struct bgp_distance
*bdistance
)
10678 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
10681 static int bgp_distance_set(struct vty
*vty
, const char *distance_str
,
10682 const char *ip_str
, const char *access_list_str
)
10689 struct bgp_node
*rn
;
10690 struct bgp_distance
*bdistance
;
10692 afi
= bgp_node_afi(vty
);
10693 safi
= bgp_node_safi(vty
);
10695 ret
= str2prefix(ip_str
, &p
);
10697 vty_out(vty
, "Malformed prefix\n");
10698 return CMD_WARNING_CONFIG_FAILED
;
10701 distance
= atoi(distance_str
);
10703 /* Get BGP distance node. */
10704 rn
= bgp_node_get(bgp_distance_table
[afi
][safi
], (struct prefix
*)&p
);
10706 bdistance
= rn
->info
;
10707 bgp_unlock_node(rn
);
10709 bdistance
= bgp_distance_new();
10710 rn
->info
= bdistance
;
10713 /* Set distance value. */
10714 bdistance
->distance
= distance
;
10716 /* Reset access-list configuration. */
10717 if (bdistance
->access_list
) {
10718 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
10719 bdistance
->access_list
= NULL
;
10721 if (access_list_str
)
10722 bdistance
->access_list
=
10723 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
10725 return CMD_SUCCESS
;
10728 static int bgp_distance_unset(struct vty
*vty
, const char *distance_str
,
10729 const char *ip_str
, const char *access_list_str
)
10736 struct bgp_node
*rn
;
10737 struct bgp_distance
*bdistance
;
10739 afi
= bgp_node_afi(vty
);
10740 safi
= bgp_node_safi(vty
);
10742 ret
= str2prefix(ip_str
, &p
);
10744 vty_out(vty
, "Malformed prefix\n");
10745 return CMD_WARNING_CONFIG_FAILED
;
10748 rn
= bgp_node_lookup(bgp_distance_table
[afi
][safi
],
10749 (struct prefix
*)&p
);
10751 vty_out(vty
, "Can't find specified prefix\n");
10752 return CMD_WARNING_CONFIG_FAILED
;
10755 bdistance
= rn
->info
;
10756 distance
= atoi(distance_str
);
10758 if (bdistance
->distance
!= distance
) {
10759 vty_out(vty
, "Distance does not match configured\n");
10760 return CMD_WARNING_CONFIG_FAILED
;
10763 if (bdistance
->access_list
)
10764 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
10765 bgp_distance_free(bdistance
);
10768 bgp_unlock_node(rn
);
10769 bgp_unlock_node(rn
);
10771 return CMD_SUCCESS
;
10774 /* Apply BGP information to distance method. */
10775 uint8_t bgp_distance_apply(struct prefix
*p
, struct bgp_info
*rinfo
, afi_t afi
,
10776 safi_t safi
, struct bgp
*bgp
)
10778 struct bgp_node
*rn
;
10781 struct bgp_distance
*bdistance
;
10782 struct access_list
*alist
;
10783 struct bgp_static
*bgp_static
;
10788 peer
= rinfo
->peer
;
10790 /* Check source address. */
10791 sockunion2hostprefix(&peer
->su
, &q
);
10792 rn
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
10794 bdistance
= rn
->info
;
10795 bgp_unlock_node(rn
);
10797 if (bdistance
->access_list
) {
10798 alist
= access_list_lookup(afi
, bdistance
->access_list
);
10800 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
10801 return bdistance
->distance
;
10803 return bdistance
->distance
;
10806 /* Backdoor check. */
10807 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
10809 bgp_static
= rn
->info
;
10810 bgp_unlock_node(rn
);
10812 if (bgp_static
->backdoor
) {
10813 if (bgp
->distance_local
[afi
][safi
])
10814 return bgp
->distance_local
[afi
][safi
];
10816 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
10820 if (peer
->sort
== BGP_PEER_EBGP
) {
10821 if (bgp
->distance_ebgp
[afi
][safi
])
10822 return bgp
->distance_ebgp
[afi
][safi
];
10823 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
10825 if (bgp
->distance_ibgp
[afi
][safi
])
10826 return bgp
->distance_ibgp
[afi
][safi
];
10827 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
10831 DEFUN (bgp_distance
,
10833 "distance bgp (1-255) (1-255) (1-255)",
10834 "Define an administrative distance\n"
10836 "Distance for routes external to the AS\n"
10837 "Distance for routes internal to the AS\n"
10838 "Distance for local routes\n")
10840 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
10841 int idx_number
= 2;
10842 int idx_number_2
= 3;
10843 int idx_number_3
= 4;
10847 afi
= bgp_node_afi(vty
);
10848 safi
= bgp_node_safi(vty
);
10850 bgp
->distance_ebgp
[afi
][safi
] = atoi(argv
[idx_number
]->arg
);
10851 bgp
->distance_ibgp
[afi
][safi
] = atoi(argv
[idx_number_2
]->arg
);
10852 bgp
->distance_local
[afi
][safi
] = atoi(argv
[idx_number_3
]->arg
);
10853 return CMD_SUCCESS
;
10856 DEFUN (no_bgp_distance
,
10857 no_bgp_distance_cmd
,
10858 "no distance bgp [(1-255) (1-255) (1-255)]",
10860 "Define an administrative distance\n"
10862 "Distance for routes external to the AS\n"
10863 "Distance for routes internal to the AS\n"
10864 "Distance for local routes\n")
10866 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
10870 afi
= bgp_node_afi(vty
);
10871 safi
= bgp_node_safi(vty
);
10873 bgp
->distance_ebgp
[afi
][safi
] = 0;
10874 bgp
->distance_ibgp
[afi
][safi
] = 0;
10875 bgp
->distance_local
[afi
][safi
] = 0;
10876 return CMD_SUCCESS
;
10880 DEFUN (bgp_distance_source
,
10881 bgp_distance_source_cmd
,
10882 "distance (1-255) A.B.C.D/M",
10883 "Define an administrative distance\n"
10884 "Administrative distance\n"
10885 "IP source prefix\n")
10887 int idx_number
= 1;
10888 int idx_ipv4_prefixlen
= 2;
10889 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
10890 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
10891 return CMD_SUCCESS
;
10894 DEFUN (no_bgp_distance_source
,
10895 no_bgp_distance_source_cmd
,
10896 "no distance (1-255) A.B.C.D/M",
10898 "Define an administrative distance\n"
10899 "Administrative distance\n"
10900 "IP source prefix\n")
10902 int idx_number
= 2;
10903 int idx_ipv4_prefixlen
= 3;
10904 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
10905 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
10906 return CMD_SUCCESS
;
10909 DEFUN (bgp_distance_source_access_list
,
10910 bgp_distance_source_access_list_cmd
,
10911 "distance (1-255) A.B.C.D/M WORD",
10912 "Define an administrative distance\n"
10913 "Administrative distance\n"
10914 "IP source prefix\n"
10915 "Access list name\n")
10917 int idx_number
= 1;
10918 int idx_ipv4_prefixlen
= 2;
10920 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
10921 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
10922 return CMD_SUCCESS
;
10925 DEFUN (no_bgp_distance_source_access_list
,
10926 no_bgp_distance_source_access_list_cmd
,
10927 "no distance (1-255) A.B.C.D/M WORD",
10929 "Define an administrative distance\n"
10930 "Administrative distance\n"
10931 "IP source prefix\n"
10932 "Access list name\n")
10934 int idx_number
= 2;
10935 int idx_ipv4_prefixlen
= 3;
10937 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
10938 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
10939 return CMD_SUCCESS
;
10942 DEFUN (ipv6_bgp_distance_source
,
10943 ipv6_bgp_distance_source_cmd
,
10944 "distance (1-255) X:X::X:X/M",
10945 "Define an administrative distance\n"
10946 "Administrative distance\n"
10947 "IP source prefix\n")
10949 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, NULL
);
10950 return CMD_SUCCESS
;
10953 DEFUN (no_ipv6_bgp_distance_source
,
10954 no_ipv6_bgp_distance_source_cmd
,
10955 "no distance (1-255) X:X::X:X/M",
10957 "Define an administrative distance\n"
10958 "Administrative distance\n"
10959 "IP source prefix\n")
10961 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, NULL
);
10962 return CMD_SUCCESS
;
10965 DEFUN (ipv6_bgp_distance_source_access_list
,
10966 ipv6_bgp_distance_source_access_list_cmd
,
10967 "distance (1-255) X:X::X:X/M WORD",
10968 "Define an administrative distance\n"
10969 "Administrative distance\n"
10970 "IP source prefix\n"
10971 "Access list name\n")
10973 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, argv
[3]->arg
);
10974 return CMD_SUCCESS
;
10977 DEFUN (no_ipv6_bgp_distance_source_access_list
,
10978 no_ipv6_bgp_distance_source_access_list_cmd
,
10979 "no distance (1-255) X:X::X:X/M WORD",
10981 "Define an administrative distance\n"
10982 "Administrative distance\n"
10983 "IP source prefix\n"
10984 "Access list name\n")
10986 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, argv
[4]->arg
);
10987 return CMD_SUCCESS
;
10990 DEFUN (bgp_damp_set
,
10992 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
10993 "BGP Specific commands\n"
10994 "Enable route-flap dampening\n"
10995 "Half-life time for the penalty\n"
10996 "Value to start reusing a route\n"
10997 "Value to start suppressing a route\n"
10998 "Maximum duration to suppress a stable route\n")
11000 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11001 int idx_half_life
= 2;
11003 int idx_suppress
= 4;
11004 int idx_max_suppress
= 5;
11005 int half
= DEFAULT_HALF_LIFE
* 60;
11006 int reuse
= DEFAULT_REUSE
;
11007 int suppress
= DEFAULT_SUPPRESS
;
11008 int max
= 4 * half
;
11011 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
11012 reuse
= atoi(argv
[idx_reuse
]->arg
);
11013 suppress
= atoi(argv
[idx_suppress
]->arg
);
11014 max
= atoi(argv
[idx_max_suppress
]->arg
) * 60;
11015 } else if (argc
== 3) {
11016 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
11020 if (suppress
< reuse
) {
11022 "Suppress value cannot be less than reuse value \n");
11026 return bgp_damp_enable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
), half
,
11027 reuse
, suppress
, max
);
11030 DEFUN (bgp_damp_unset
,
11031 bgp_damp_unset_cmd
,
11032 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
11034 "BGP Specific commands\n"
11035 "Enable route-flap dampening\n"
11036 "Half-life time for the penalty\n"
11037 "Value to start reusing a route\n"
11038 "Value to start suppressing a route\n"
11039 "Maximum duration to suppress a stable route\n")
11041 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11042 return bgp_damp_disable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
));
11045 /* Display specified route of BGP table. */
11046 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
11047 const char *ip_str
, afi_t afi
, safi_t safi
,
11048 struct prefix_rd
*prd
, int prefix_check
)
11051 struct prefix match
;
11052 struct bgp_node
*rn
;
11053 struct bgp_node
*rm
;
11054 struct bgp_info
*ri
;
11055 struct bgp_info
*ri_temp
;
11057 struct bgp_table
*table
;
11059 /* BGP structure lookup. */
11061 bgp
= bgp_lookup_by_name(view_name
);
11063 vty_out(vty
, "%% Can't find BGP instance %s\n",
11065 return CMD_WARNING
;
11068 bgp
= bgp_get_default();
11070 vty_out(vty
, "%% No BGP process is configured\n");
11071 return CMD_WARNING
;
11075 /* Check IP address argument. */
11076 ret
= str2prefix(ip_str
, &match
);
11078 vty_out(vty
, "%% address is malformed\n");
11079 return CMD_WARNING
;
11082 match
.family
= afi2family(afi
);
11084 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
11085 || (safi
== SAFI_EVPN
)) {
11086 for (rn
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); rn
;
11087 rn
= bgp_route_next(rn
)) {
11088 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
11090 if ((table
= rn
->info
) == NULL
)
11092 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
11096 || rm
->p
.prefixlen
== match
.prefixlen
) {
11099 if (ri
->extra
&& ri
->extra
->damp_info
) {
11100 ri_temp
= ri
->next
;
11101 bgp_damp_info_free(
11102 ri
->extra
->damp_info
,
11110 bgp_unlock_node(rm
);
11113 if ((rn
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
))
11116 || rn
->p
.prefixlen
== match
.prefixlen
) {
11119 if (ri
->extra
&& ri
->extra
->damp_info
) {
11120 ri_temp
= ri
->next
;
11121 bgp_damp_info_free(
11122 ri
->extra
->damp_info
,
11130 bgp_unlock_node(rn
);
11134 return CMD_SUCCESS
;
11137 DEFUN (clear_ip_bgp_dampening
,
11138 clear_ip_bgp_dampening_cmd
,
11139 "clear ip bgp dampening",
11143 "Clear route flap dampening information\n")
11145 bgp_damp_info_clean();
11146 return CMD_SUCCESS
;
11149 DEFUN (clear_ip_bgp_dampening_prefix
,
11150 clear_ip_bgp_dampening_prefix_cmd
,
11151 "clear ip bgp dampening A.B.C.D/M",
11155 "Clear route flap dampening information\n"
11158 int idx_ipv4_prefixlen
= 4;
11159 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
11160 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
11163 DEFUN (clear_ip_bgp_dampening_address
,
11164 clear_ip_bgp_dampening_address_cmd
,
11165 "clear ip bgp dampening A.B.C.D",
11169 "Clear route flap dampening information\n"
11170 "Network to clear damping information\n")
11173 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
11174 SAFI_UNICAST
, NULL
, 0);
11177 DEFUN (clear_ip_bgp_dampening_address_mask
,
11178 clear_ip_bgp_dampening_address_mask_cmd
,
11179 "clear ip bgp dampening A.B.C.D A.B.C.D",
11183 "Clear route flap dampening information\n"
11184 "Network to clear damping information\n"
11188 int idx_ipv4_2
= 5;
11190 char prefix_str
[BUFSIZ
];
11192 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
11195 vty_out(vty
, "%% Inconsistent address and mask\n");
11196 return CMD_WARNING
;
11199 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
11203 /* also used for encap safi */
11204 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
11205 afi_t afi
, safi_t safi
)
11207 struct bgp_node
*prn
;
11208 struct bgp_node
*rn
;
11209 struct bgp_table
*table
;
11211 struct prefix_rd
*prd
;
11212 struct bgp_static
*bgp_static
;
11213 mpls_label_t label
;
11214 char buf
[SU_ADDRSTRLEN
];
11215 char rdbuf
[RD_ADDRSTRLEN
];
11217 /* Network configuration. */
11218 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
11219 prn
= bgp_route_next(prn
)) {
11220 if ((table
= prn
->info
) == NULL
)
11223 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
11224 if ((bgp_static
= rn
->info
) == NULL
)
11228 prd
= (struct prefix_rd
*)&prn
->p
;
11230 /* "network" configuration display. */
11231 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
11232 label
= decode_label(&bgp_static
->label
);
11234 vty_out(vty
, " network %s/%d rd %s",
11235 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11237 p
->prefixlen
, rdbuf
);
11238 if (safi
== SAFI_MPLS_VPN
)
11239 vty_out(vty
, " label %u", label
);
11241 if (bgp_static
->rmap
.name
)
11242 vty_out(vty
, " route-map %s",
11243 bgp_static
->rmap
.name
);
11245 if (bgp_static
->backdoor
)
11246 vty_out(vty
, " backdoor");
11248 vty_out(vty
, "\n");
11253 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
11254 afi_t afi
, safi_t safi
)
11256 struct bgp_node
*prn
;
11257 struct bgp_node
*rn
;
11258 struct bgp_table
*table
;
11260 struct prefix_rd
*prd
;
11261 struct bgp_static
*bgp_static
;
11262 char buf
[PREFIX_STRLEN
* 2];
11263 char buf2
[SU_ADDRSTRLEN
];
11264 char rdbuf
[RD_ADDRSTRLEN
];
11266 /* Network configuration. */
11267 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
11268 prn
= bgp_route_next(prn
)) {
11269 if ((table
= prn
->info
) == NULL
)
11272 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
11273 if ((bgp_static
= rn
->info
) == NULL
)
11276 char *macrouter
= NULL
;
11279 if (bgp_static
->router_mac
)
11280 macrouter
= prefix_mac2str(
11281 bgp_static
->router_mac
, NULL
, 0);
11282 if (bgp_static
->eth_s_id
)
11283 esi
= esi2str(bgp_static
->eth_s_id
);
11285 prd
= (struct prefix_rd
*)&prn
->p
;
11287 /* "network" configuration display. */
11288 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
11289 if (p
->u
.prefix_evpn
.route_type
== 5) {
11290 char local_buf
[PREFIX_STRLEN
];
11291 uint8_t family
= is_evpn_prefix_ipaddr_v4((
11292 struct prefix_evpn
*)p
)
11296 &p
->u
.prefix_evpn
.prefix_addr
.ip
.ip
.addr
,
11297 local_buf
, PREFIX_STRLEN
);
11298 sprintf(buf
, "%s/%u", local_buf
,
11299 p
->u
.prefix_evpn
.prefix_addr
.ip_prefix_length
);
11301 prefix2str(p
, buf
, sizeof(buf
));
11304 if (bgp_static
->gatewayIp
.family
== AF_INET
11305 || bgp_static
->gatewayIp
.family
== AF_INET6
)
11306 inet_ntop(bgp_static
->gatewayIp
.family
,
11307 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
11310 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
11312 p
->u
.prefix_evpn
.prefix_addr
.eth_tag
,
11313 decode_label(&bgp_static
->label
), esi
, buf2
,
11317 XFREE(MTYPE_TMP
, macrouter
);
11319 XFREE(MTYPE_TMP
, esi
);
11324 /* Configuration of static route announcement and aggregate
11326 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11329 struct bgp_node
*rn
;
11331 struct bgp_static
*bgp_static
;
11332 struct bgp_aggregate
*bgp_aggregate
;
11333 char buf
[SU_ADDRSTRLEN
];
11335 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
11336 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
11340 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
11341 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
11345 /* Network configuration. */
11346 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
11347 rn
= bgp_route_next(rn
)) {
11348 if ((bgp_static
= rn
->info
) == NULL
)
11353 /* "network" configuration display. */
11354 if (bgp_option_check(BGP_OPT_CONFIG_CISCO
) && afi
== AFI_IP
) {
11355 uint32_t destination
;
11356 struct in_addr netmask
;
11358 destination
= ntohl(p
->u
.prefix4
.s_addr
);
11359 masklen2ip(p
->prefixlen
, &netmask
);
11360 vty_out(vty
, " network %s",
11361 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11364 if ((IN_CLASSC(destination
) && p
->prefixlen
== 24)
11365 || (IN_CLASSB(destination
) && p
->prefixlen
== 16)
11366 || (IN_CLASSA(destination
) && p
->prefixlen
== 8)
11367 || p
->u
.prefix4
.s_addr
== 0) {
11368 /* Natural mask is not display. */
11370 vty_out(vty
, " mask %s", inet_ntoa(netmask
));
11372 vty_out(vty
, " network %s/%d",
11373 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11378 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
11379 vty_out(vty
, " label-index %u",
11380 bgp_static
->label_index
);
11382 if (bgp_static
->rmap
.name
)
11383 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
11385 if (bgp_static
->backdoor
)
11386 vty_out(vty
, " backdoor");
11388 vty_out(vty
, "\n");
11391 /* Aggregate-address configuration. */
11392 for (rn
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); rn
;
11393 rn
= bgp_route_next(rn
)) {
11394 if ((bgp_aggregate
= rn
->info
) == NULL
)
11399 if (bgp_option_check(BGP_OPT_CONFIG_CISCO
) && afi
== AFI_IP
) {
11400 struct in_addr netmask
;
11402 masklen2ip(p
->prefixlen
, &netmask
);
11403 vty_out(vty
, " aggregate-address %s %s",
11404 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11406 inet_ntoa(netmask
));
11408 vty_out(vty
, " aggregate-address %s/%d",
11409 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11414 if (bgp_aggregate
->as_set
)
11415 vty_out(vty
, " as-set");
11417 if (bgp_aggregate
->summary_only
)
11418 vty_out(vty
, " summary-only");
11420 vty_out(vty
, "\n");
11424 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11427 struct bgp_node
*rn
;
11428 struct bgp_distance
*bdistance
;
11430 /* Distance configuration. */
11431 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
11432 && bgp
->distance_local
[afi
][safi
]
11433 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
11434 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
11435 || bgp
->distance_local
[afi
][safi
]
11436 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
11437 vty_out(vty
, " distance bgp %d %d %d\n",
11438 bgp
->distance_ebgp
[afi
][safi
],
11439 bgp
->distance_ibgp
[afi
][safi
],
11440 bgp
->distance_local
[afi
][safi
]);
11443 for (rn
= bgp_table_top(bgp_distance_table
[afi
][safi
]); rn
;
11444 rn
= bgp_route_next(rn
))
11445 if ((bdistance
= rn
->info
) != NULL
) {
11446 char buf
[PREFIX_STRLEN
];
11448 vty_out(vty
, " distance %d %s %s\n",
11449 bdistance
->distance
,
11450 prefix2str(&rn
->p
, buf
, sizeof(buf
)),
11451 bdistance
->access_list
? bdistance
->access_list
11456 /* Allocate routing table structure and install commands. */
11457 void bgp_route_init(void)
11462 /* Init BGP distance table. */
11463 FOREACH_AFI_SAFI (afi
, safi
)
11464 bgp_distance_table
[afi
][safi
] = bgp_table_init(NULL
, afi
, safi
);
11466 /* IPv4 BGP commands. */
11467 install_element(BGP_NODE
, &bgp_table_map_cmd
);
11468 install_element(BGP_NODE
, &bgp_network_cmd
);
11469 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
11471 install_element(BGP_NODE
, &aggregate_address_cmd
);
11472 install_element(BGP_NODE
, &aggregate_address_mask_cmd
);
11473 install_element(BGP_NODE
, &no_aggregate_address_cmd
);
11474 install_element(BGP_NODE
, &no_aggregate_address_mask_cmd
);
11476 /* IPv4 unicast configuration. */
11477 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
11478 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
11479 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
11481 install_element(BGP_IPV4_NODE
, &aggregate_address_cmd
);
11482 install_element(BGP_IPV4_NODE
, &aggregate_address_mask_cmd
);
11483 install_element(BGP_IPV4_NODE
, &no_aggregate_address_cmd
);
11484 install_element(BGP_IPV4_NODE
, &no_aggregate_address_mask_cmd
);
11486 /* IPv4 multicast configuration. */
11487 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
11488 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
11489 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
11490 install_element(BGP_IPV4M_NODE
, &aggregate_address_cmd
);
11491 install_element(BGP_IPV4M_NODE
, &aggregate_address_mask_cmd
);
11492 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_cmd
);
11493 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_mask_cmd
);
11495 /* IPv4 labeled-unicast configuration. */
11496 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
11497 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
11498 install_element(VIEW_NODE
, &show_ip_bgp_json_cmd
);
11499 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
11500 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
11502 install_element(VIEW_NODE
,
11503 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
11504 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
11505 install_element(VIEW_NODE
,
11506 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
11507 #ifdef KEEP_OLD_VPN_COMMANDS
11508 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
11509 #endif /* KEEP_OLD_VPN_COMMANDS */
11510 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
11511 install_element(VIEW_NODE
,
11512 &show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd
);
11514 /* BGP dampening clear commands */
11515 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
11516 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
11518 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
11519 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
11522 install_element(ENABLE_NODE
,
11523 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
11524 #ifdef KEEP_OLD_VPN_COMMANDS
11525 install_element(ENABLE_NODE
,
11526 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
11527 #endif /* KEEP_OLD_VPN_COMMANDS */
11529 /* New config IPv6 BGP commands. */
11530 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
11531 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
11532 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
11534 install_element(BGP_IPV6_NODE
, &ipv6_aggregate_address_cmd
);
11535 install_element(BGP_IPV6_NODE
, &no_ipv6_aggregate_address_cmd
);
11537 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
11539 install_element(BGP_NODE
, &bgp_distance_cmd
);
11540 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
11541 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
11542 install_element(BGP_NODE
, &no_bgp_distance_source_cmd
);
11543 install_element(BGP_NODE
, &bgp_distance_source_access_list_cmd
);
11544 install_element(BGP_NODE
, &no_bgp_distance_source_access_list_cmd
);
11545 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
11546 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
11547 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
11548 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_cmd
);
11549 install_element(BGP_IPV4_NODE
, &bgp_distance_source_access_list_cmd
);
11550 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_access_list_cmd
);
11551 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
11552 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
11553 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
11554 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_source_cmd
);
11555 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_access_list_cmd
);
11556 install_element(BGP_IPV4M_NODE
,
11557 &no_bgp_distance_source_access_list_cmd
);
11558 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
11559 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
11560 install_element(BGP_IPV6_NODE
, &ipv6_bgp_distance_source_cmd
);
11561 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_distance_source_cmd
);
11562 install_element(BGP_IPV6_NODE
,
11563 &ipv6_bgp_distance_source_access_list_cmd
);
11564 install_element(BGP_IPV6_NODE
,
11565 &no_ipv6_bgp_distance_source_access_list_cmd
);
11566 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
11567 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
11568 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_distance_source_cmd
);
11569 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_distance_source_cmd
);
11570 install_element(BGP_IPV6M_NODE
,
11571 &ipv6_bgp_distance_source_access_list_cmd
);
11572 install_element(BGP_IPV6M_NODE
,
11573 &no_ipv6_bgp_distance_source_access_list_cmd
);
11575 install_element(BGP_NODE
, &bgp_damp_set_cmd
);
11576 install_element(BGP_NODE
, &bgp_damp_unset_cmd
);
11577 install_element(BGP_IPV4_NODE
, &bgp_damp_set_cmd
);
11578 install_element(BGP_IPV4_NODE
, &bgp_damp_unset_cmd
);
11580 /* IPv4 Multicast Mode */
11581 install_element(BGP_IPV4M_NODE
, &bgp_damp_set_cmd
);
11582 install_element(BGP_IPV4M_NODE
, &bgp_damp_unset_cmd
);
11584 /* Large Communities */
11585 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
11586 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
11588 /* show bgp ipv4 flowspec detailed */
11589 install_element(VIEW_NODE
, &show_ip_bgp_flowspec_routes_detailed_cmd
);
11593 void bgp_route_finish(void)
11598 FOREACH_AFI_SAFI (afi
, safi
) {
11599 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
11600 bgp_distance_table
[afi
][safi
] = NULL
;