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"
42 #include "bgpd/bgpd.h"
43 #include "bgpd/bgp_table.h"
44 #include "bgpd/bgp_route.h"
45 #include "bgpd/bgp_attr.h"
46 #include "bgpd/bgp_debug.h"
47 #include "bgpd/bgp_aspath.h"
48 #include "bgpd/bgp_regex.h"
49 #include "bgpd/bgp_community.h"
50 #include "bgpd/bgp_ecommunity.h"
51 #include "bgpd/bgp_lcommunity.h"
52 #include "bgpd/bgp_clist.h"
53 #include "bgpd/bgp_packet.h"
54 #include "bgpd/bgp_filter.h"
55 #include "bgpd/bgp_fsm.h"
56 #include "bgpd/bgp_mplsvpn.h"
57 #include "bgpd/bgp_nexthop.h"
58 #include "bgpd/bgp_damp.h"
59 #include "bgpd/bgp_advertise.h"
60 #include "bgpd/bgp_zebra.h"
61 #include "bgpd/bgp_vty.h"
62 #include "bgpd/bgp_mpath.h"
63 #include "bgpd/bgp_nht.h"
64 #include "bgpd/bgp_updgrp.h"
65 #include "bgpd/bgp_label.h"
68 #include "bgpd/rfapi/rfapi_backend.h"
69 #include "bgpd/rfapi/vnc_import_bgp.h"
70 #include "bgpd/rfapi/vnc_export_bgp.h"
72 #include "bgpd/bgp_encap_types.h"
73 #include "bgpd/bgp_encap_tlv.h"
74 #include "bgpd/bgp_evpn.h"
75 #include "bgpd/bgp_evpn_vty.h"
76 #include "bgpd/bgp_flowspec.h"
77 #include "bgpd/bgp_flowspec_util.h"
79 #ifndef VTYSH_EXTRACT_PL
80 #include "bgpd/bgp_route_clippy.c"
83 /* Extern from bgp_dump.c */
84 extern const char *bgp_origin_str
[];
85 extern const char *bgp_origin_long_str
[];
88 #define PMSI_TNLTYPE_STR_NO_INFO "No info"
89 #define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
90 static const struct message bgp_pmsi_tnltype_str
[] = {
91 {PMSI_TNLTYPE_NO_INFO
, PMSI_TNLTYPE_STR_NO_INFO
},
92 {PMSI_TNLTYPE_RSVP_TE_P2MP
, "RSVP-TE P2MP"},
93 {PMSI_TNLTYPE_MLDP_P2MP
, "mLDP P2MP"},
94 {PMSI_TNLTYPE_PIM_SSM
, "PIM-SSM"},
95 {PMSI_TNLTYPE_PIM_SM
, "PIM-SM"},
96 {PMSI_TNLTYPE_PIM_BIDIR
, "PIM-BIDIR"},
97 {PMSI_TNLTYPE_INGR_REPL
, "Ingress Replication"},
98 {PMSI_TNLTYPE_MLDP_MP2MP
, "mLDP MP2MP"},
102 #define VRFID_NONE_STR "-"
104 struct bgp_node
*bgp_afi_node_get(struct bgp_table
*table
, afi_t afi
,
105 safi_t safi
, struct prefix
*p
,
106 struct prefix_rd
*prd
)
109 struct bgp_node
*prn
= NULL
;
115 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
116 || (safi
== SAFI_EVPN
)) {
117 prn
= bgp_node_get(table
, (struct prefix
*)prd
);
119 if (prn
->info
== NULL
)
120 prn
->info
= bgp_table_init(table
->bgp
, afi
, safi
);
122 bgp_unlock_node(prn
);
126 rn
= bgp_node_get(table
, p
);
128 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
129 || (safi
== SAFI_EVPN
))
135 struct bgp_node
*bgp_afi_node_lookup(struct bgp_table
*table
, afi_t afi
,
136 safi_t safi
, struct prefix
*p
,
137 struct prefix_rd
*prd
)
140 struct bgp_node
*prn
= NULL
;
145 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
146 || (safi
== SAFI_EVPN
)) {
147 prn
= bgp_node_lookup(table
, (struct prefix
*)prd
);
151 if (prn
->info
== NULL
) {
152 bgp_unlock_node(prn
);
159 rn
= bgp_node_lookup(table
, p
);
164 /* Allocate bgp_info_extra */
165 static struct bgp_info_extra
*bgp_info_extra_new(void)
167 struct bgp_info_extra
*new;
168 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA
, sizeof(struct bgp_info_extra
));
169 new->label
[0] = MPLS_INVALID_LABEL
;
174 static void bgp_info_extra_free(struct bgp_info_extra
**extra
)
176 if (extra
&& *extra
) {
177 if ((*extra
)->damp_info
)
178 bgp_damp_info_free((*extra
)->damp_info
, 0);
180 (*extra
)->damp_info
= NULL
;
182 XFREE(MTYPE_BGP_ROUTE_EXTRA
, *extra
);
188 /* Get bgp_info extra information for the given bgp_info, lazy allocated
191 struct bgp_info_extra
*bgp_info_extra_get(struct bgp_info
*ri
)
194 ri
->extra
= bgp_info_extra_new();
198 /* Allocate new bgp info structure. */
199 struct bgp_info
*bgp_info_new(void)
201 return XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_info
));
204 /* Free bgp route information. */
205 static void bgp_info_free(struct bgp_info
*binfo
)
208 bgp_attr_unintern(&binfo
->attr
);
210 bgp_unlink_nexthop(binfo
);
211 bgp_info_extra_free(&binfo
->extra
);
212 bgp_info_mpath_free(&binfo
->mpath
);
214 peer_unlock(binfo
->peer
); /* bgp_info peer reference */
216 XFREE(MTYPE_BGP_ROUTE
, binfo
);
219 struct bgp_info
*bgp_info_lock(struct bgp_info
*binfo
)
225 struct bgp_info
*bgp_info_unlock(struct bgp_info
*binfo
)
227 assert(binfo
&& binfo
->lock
> 0);
230 if (binfo
->lock
== 0) {
232 zlog_debug ("%s: unlocked and freeing", __func__
);
233 zlog_backtrace (LOG_DEBUG
);
235 bgp_info_free(binfo
);
240 if (binfo
->lock
== 1)
242 zlog_debug ("%s: unlocked to 1", __func__
);
243 zlog_backtrace (LOG_DEBUG
);
250 void bgp_info_add(struct bgp_node
*rn
, struct bgp_info
*ri
)
252 struct bgp_info
*top
;
264 peer_lock(ri
->peer
); /* bgp_info peer reference */
267 /* Do the actual removal of info from RIB, for use by bgp_process
268 completion callback *only* */
269 void bgp_info_reap(struct bgp_node
*rn
, struct bgp_info
*ri
)
272 ri
->next
->prev
= ri
->prev
;
274 ri
->prev
->next
= ri
->next
;
278 bgp_info_mpath_dequeue(ri
);
283 void bgp_info_delete(struct bgp_node
*rn
, struct bgp_info
*ri
)
285 bgp_info_set_flag(rn
, ri
, BGP_INFO_REMOVED
);
286 /* set of previous already took care of pcount */
287 UNSET_FLAG(ri
->flags
, BGP_INFO_VALID
);
290 /* undo the effects of a previous call to bgp_info_delete; typically
291 called when a route is deleted and then quickly re-added before the
292 deletion has been processed */
293 void bgp_info_restore(struct bgp_node
*rn
, struct bgp_info
*ri
)
295 bgp_info_unset_flag(rn
, ri
, BGP_INFO_REMOVED
);
296 /* unset of previous already took care of pcount */
297 SET_FLAG(ri
->flags
, BGP_INFO_VALID
);
300 /* Adjust pcount as required */
301 static void bgp_pcount_adjust(struct bgp_node
*rn
, struct bgp_info
*ri
)
303 struct bgp_table
*table
;
305 assert(rn
&& bgp_node_table(rn
));
306 assert(ri
&& ri
->peer
&& ri
->peer
->bgp
);
308 table
= bgp_node_table(rn
);
310 if (ri
->peer
== ri
->peer
->bgp
->peer_self
)
313 if (!BGP_INFO_COUNTABLE(ri
)
314 && CHECK_FLAG(ri
->flags
, BGP_INFO_COUNTED
)) {
316 UNSET_FLAG(ri
->flags
, BGP_INFO_COUNTED
);
318 /* slight hack, but more robust against errors. */
319 if (ri
->peer
->pcount
[table
->afi
][table
->safi
])
320 ri
->peer
->pcount
[table
->afi
][table
->safi
]--;
323 "%s: Asked to decrement 0 prefix count for peer %s",
324 __func__
, ri
->peer
->host
);
325 zlog_backtrace(LOG_WARNING
);
326 zlog_warn("%s: Please report to Quagga bugzilla",
329 } else if (BGP_INFO_COUNTABLE(ri
)
330 && !CHECK_FLAG(ri
->flags
, BGP_INFO_COUNTED
)) {
331 SET_FLAG(ri
->flags
, BGP_INFO_COUNTED
);
332 ri
->peer
->pcount
[table
->afi
][table
->safi
]++;
336 static int bgp_label_index_differs(struct bgp_info
*ri1
, struct bgp_info
*ri2
)
338 return (!(ri1
->attr
->label_index
== ri2
->attr
->label_index
));
341 /* Set/unset bgp_info flags, adjusting any other state as needed.
342 * This is here primarily to keep prefix-count in check.
344 void bgp_info_set_flag(struct bgp_node
*rn
, struct bgp_info
*ri
, uint32_t flag
)
346 SET_FLAG(ri
->flags
, flag
);
348 /* early bath if we know it's not a flag that changes countability state
350 if (!CHECK_FLAG(flag
,
351 BGP_INFO_VALID
| BGP_INFO_HISTORY
| BGP_INFO_REMOVED
))
354 bgp_pcount_adjust(rn
, ri
);
357 void bgp_info_unset_flag(struct bgp_node
*rn
, struct bgp_info
*ri
,
360 UNSET_FLAG(ri
->flags
, flag
);
362 /* early bath if we know it's not a flag that changes countability state
364 if (!CHECK_FLAG(flag
,
365 BGP_INFO_VALID
| BGP_INFO_HISTORY
| BGP_INFO_REMOVED
))
368 bgp_pcount_adjust(rn
, ri
);
371 /* Get MED value. If MED value is missing and "bgp bestpath
372 missing-as-worst" is specified, treat it as the worst value. */
373 static uint32_t bgp_med_value(struct attr
*attr
, struct bgp
*bgp
)
375 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
378 if (bgp_flag_check(bgp
, BGP_FLAG_MED_MISSING_AS_WORST
))
385 void bgp_info_path_with_addpath_rx_str(struct bgp_info
*ri
, char *buf
)
387 if (ri
->addpath_rx_id
)
388 sprintf(buf
, "path %s (addpath rxid %d)", ri
->peer
->host
,
391 sprintf(buf
, "path %s", ri
->peer
->host
);
394 /* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
396 static int bgp_info_cmp(struct bgp
*bgp
, struct bgp_info
*new,
397 struct bgp_info
*exist
, int *paths_eq
,
398 struct bgp_maxpaths_cfg
*mpath_cfg
, int debug
,
399 char *pfx_buf
, afi_t afi
, safi_t safi
)
401 struct attr
*newattr
, *existattr
;
402 bgp_peer_sort_t new_sort
;
403 bgp_peer_sort_t exist_sort
;
409 uint32_t exist_weight
;
410 uint32_t newm
, existm
;
411 struct in_addr new_id
;
412 struct in_addr exist_id
;
415 int internal_as_route
;
418 char new_buf
[PATH_ADDPATH_STR_BUFFER
];
419 char exist_buf
[PATH_ADDPATH_STR_BUFFER
];
421 uint32_t exist_mm_seq
;
428 zlog_debug("%s: new is NULL", pfx_buf
);
433 bgp_info_path_with_addpath_rx_str(new, new_buf
);
437 zlog_debug("%s: %s is the initial bestpath", pfx_buf
,
443 bgp_info_path_with_addpath_rx_str(exist
, exist_buf
);
444 zlog_debug("%s: Comparing %s flags 0x%x with %s flags 0x%x",
445 pfx_buf
, new_buf
, new->flags
, exist_buf
,
450 existattr
= exist
->attr
;
452 /* For EVPN routes, we cannot just go by local vs remote, we have to
453 * look at the MAC mobility sequence number, if present.
455 if (safi
== SAFI_EVPN
) {
456 /* This is an error condition described in RFC 7432 Section
458 * states that in this scenario "the PE MUST alert the operator"
460 * does not state what other action to take. In order to provide
462 * consistency in this scenario we are going to prefer the path
466 if (newattr
->sticky
!= existattr
->sticky
) {
468 prefix2str(&new->net
->p
, pfx_buf
,
470 * PREFIX2STR_BUFFER
);
471 bgp_info_path_with_addpath_rx_str(new, new_buf
);
472 bgp_info_path_with_addpath_rx_str(exist
,
476 if (newattr
->sticky
&& !existattr
->sticky
) {
478 "%s: %s wins over %s due to sticky MAC flag",
479 pfx_buf
, new_buf
, exist_buf
);
483 if (!newattr
->sticky
&& existattr
->sticky
) {
485 "%s: %s loses to %s due to sticky MAC flag",
486 pfx_buf
, new_buf
, exist_buf
);
491 new_mm_seq
= mac_mobility_seqnum(newattr
);
492 exist_mm_seq
= mac_mobility_seqnum(existattr
);
494 if (new_mm_seq
> exist_mm_seq
) {
497 "%s: %s wins over %s due to MM seq %u > %u",
498 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
503 if (new_mm_seq
< exist_mm_seq
) {
506 "%s: %s loses to %s due to MM seq %u < %u",
507 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
513 /* 1. Weight check. */
514 new_weight
= newattr
->weight
;
515 exist_weight
= existattr
->weight
;
517 if (new_weight
> exist_weight
) {
519 zlog_debug("%s: %s wins over %s due to weight %d > %d",
520 pfx_buf
, new_buf
, exist_buf
, new_weight
,
525 if (new_weight
< exist_weight
) {
527 zlog_debug("%s: %s loses to %s due to weight %d < %d",
528 pfx_buf
, new_buf
, exist_buf
, new_weight
,
533 /* 2. Local preference check. */
534 new_pref
= exist_pref
= bgp
->default_local_pref
;
536 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
537 new_pref
= newattr
->local_pref
;
538 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
539 exist_pref
= existattr
->local_pref
;
541 if (new_pref
> exist_pref
) {
544 "%s: %s wins over %s due to localpref %d > %d",
545 pfx_buf
, new_buf
, exist_buf
, new_pref
,
550 if (new_pref
< exist_pref
) {
553 "%s: %s loses to %s due to localpref %d < %d",
554 pfx_buf
, new_buf
, exist_buf
, new_pref
,
559 /* 3. Local route check. We prefer:
561 * - BGP_ROUTE_AGGREGATE
562 * - BGP_ROUTE_REDISTRIBUTE
564 if (!(new->sub_type
== BGP_ROUTE_NORMAL
||
565 new->sub_type
== BGP_ROUTE_IMPORTED
)) {
568 "%s: %s wins over %s due to preferred BGP_ROUTE type",
569 pfx_buf
, new_buf
, exist_buf
);
573 if (!(exist
->sub_type
== BGP_ROUTE_NORMAL
||
574 exist
->sub_type
== BGP_ROUTE_IMPORTED
)) {
577 "%s: %s loses to %s due to preferred BGP_ROUTE type",
578 pfx_buf
, new_buf
, exist_buf
);
582 /* 4. AS path length check. */
583 if (!bgp_flag_check(bgp
, BGP_FLAG_ASPATH_IGNORE
)) {
584 int exist_hops
= aspath_count_hops(existattr
->aspath
);
585 int exist_confeds
= aspath_count_confeds(existattr
->aspath
);
587 if (bgp_flag_check(bgp
, BGP_FLAG_ASPATH_CONFED
)) {
590 aspath_hops
= aspath_count_hops(newattr
->aspath
);
591 aspath_hops
+= aspath_count_confeds(newattr
->aspath
);
593 if (aspath_hops
< (exist_hops
+ exist_confeds
)) {
596 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
597 pfx_buf
, new_buf
, exist_buf
,
599 (exist_hops
+ exist_confeds
));
603 if (aspath_hops
> (exist_hops
+ exist_confeds
)) {
606 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
607 pfx_buf
, new_buf
, exist_buf
,
609 (exist_hops
+ exist_confeds
));
613 int newhops
= aspath_count_hops(newattr
->aspath
);
615 if (newhops
< exist_hops
) {
618 "%s: %s wins over %s due to aspath hopcount %d < %d",
619 pfx_buf
, new_buf
, exist_buf
,
620 newhops
, exist_hops
);
624 if (newhops
> exist_hops
) {
627 "%s: %s loses to %s due to aspath hopcount %d > %d",
628 pfx_buf
, new_buf
, exist_buf
,
629 newhops
, exist_hops
);
635 /* 5. Origin check. */
636 if (newattr
->origin
< existattr
->origin
) {
638 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
639 pfx_buf
, new_buf
, exist_buf
,
640 bgp_origin_long_str
[newattr
->origin
],
641 bgp_origin_long_str
[existattr
->origin
]);
645 if (newattr
->origin
> existattr
->origin
) {
647 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
648 pfx_buf
, new_buf
, exist_buf
,
649 bgp_origin_long_str
[newattr
->origin
],
650 bgp_origin_long_str
[existattr
->origin
]);
655 internal_as_route
= (aspath_count_hops(newattr
->aspath
) == 0
656 && aspath_count_hops(existattr
->aspath
) == 0);
657 confed_as_route
= (aspath_count_confeds(newattr
->aspath
) > 0
658 && aspath_count_confeds(existattr
->aspath
) > 0
659 && aspath_count_hops(newattr
->aspath
) == 0
660 && aspath_count_hops(existattr
->aspath
) == 0);
662 if (bgp_flag_check(bgp
, BGP_FLAG_ALWAYS_COMPARE_MED
)
663 || (bgp_flag_check(bgp
, BGP_FLAG_MED_CONFED
) && confed_as_route
)
664 || aspath_cmp_left(newattr
->aspath
, existattr
->aspath
)
665 || aspath_cmp_left_confed(newattr
->aspath
, existattr
->aspath
)
666 || internal_as_route
) {
667 new_med
= bgp_med_value(new->attr
, bgp
);
668 exist_med
= bgp_med_value(exist
->attr
, bgp
);
670 if (new_med
< exist_med
) {
673 "%s: %s wins over %s due to MED %d < %d",
674 pfx_buf
, new_buf
, exist_buf
, new_med
,
679 if (new_med
> exist_med
) {
682 "%s: %s loses to %s due to MED %d > %d",
683 pfx_buf
, new_buf
, exist_buf
, new_med
,
689 /* 7. Peer type check. */
690 new_sort
= new->peer
->sort
;
691 exist_sort
= exist
->peer
->sort
;
693 if (new_sort
== BGP_PEER_EBGP
694 && (exist_sort
== BGP_PEER_IBGP
|| exist_sort
== BGP_PEER_CONFED
)) {
697 "%s: %s wins over %s due to eBGP peer > iBGP peer",
698 pfx_buf
, new_buf
, exist_buf
);
702 if (exist_sort
== BGP_PEER_EBGP
703 && (new_sort
== BGP_PEER_IBGP
|| new_sort
== BGP_PEER_CONFED
)) {
706 "%s: %s loses to %s due to iBGP peer < eBGP peer",
707 pfx_buf
, new_buf
, exist_buf
);
711 /* 8. IGP metric check. */
715 newm
= new->extra
->igpmetric
;
717 existm
= exist
->extra
->igpmetric
;
722 "%s: %s wins over %s due to IGP metric %d < %d",
723 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
730 "%s: %s loses to %s due to IGP metric %d > %d",
731 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
735 /* 9. Same IGP metric. Compare the cluster list length as
736 representative of IGP hops metric. Rewrite the metric value
737 pair (newm, existm) with the cluster list length. Prefer the
738 path with smaller cluster list length. */
739 if (newm
== existm
) {
740 if (peer_sort(new->peer
) == BGP_PEER_IBGP
741 && peer_sort(exist
->peer
) == BGP_PEER_IBGP
742 && (mpath_cfg
== NULL
744 mpath_cfg
->ibgp_flags
,
745 BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN
))) {
746 newm
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
747 existm
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
752 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
753 pfx_buf
, new_buf
, exist_buf
,
761 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
762 pfx_buf
, new_buf
, exist_buf
,
769 /* 10. confed-external vs. confed-internal */
770 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
771 if (new_sort
== BGP_PEER_CONFED
772 && exist_sort
== BGP_PEER_IBGP
) {
775 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
776 pfx_buf
, new_buf
, exist_buf
);
780 if (exist_sort
== BGP_PEER_CONFED
781 && new_sort
== BGP_PEER_IBGP
) {
784 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
785 pfx_buf
, new_buf
, exist_buf
);
790 /* 11. Maximum path check. */
791 if (newm
== existm
) {
792 /* If one path has a label but the other does not, do not treat
793 * them as equals for multipath
795 if ((new->extra
&&bgp_is_valid_label(&new->extra
->label
[0]))
797 && bgp_is_valid_label(&exist
->extra
->label
[0]))) {
800 "%s: %s and %s cannot be multipath, one has a label while the other does not",
801 pfx_buf
, new_buf
, exist_buf
);
802 } else if (bgp_flag_check(bgp
,
803 BGP_FLAG_ASPATH_MULTIPATH_RELAX
)) {
806 * For the two paths, all comparison steps till IGP
808 * have succeeded - including AS_PATH hop count. Since
810 * bestpath as-path multipath-relax' knob is on, we
812 * an exact match of AS_PATH. Thus, mark the paths are
814 * That will trigger both these paths to get into the
822 "%s: %s and %s are equal via multipath-relax",
823 pfx_buf
, new_buf
, exist_buf
);
824 } else if (new->peer
->sort
== BGP_PEER_IBGP
) {
825 if (aspath_cmp(new->attr
->aspath
,
826 exist
->attr
->aspath
)) {
831 "%s: %s and %s are equal via matching aspaths",
832 pfx_buf
, new_buf
, exist_buf
);
834 } else if (new->peer
->as
== exist
->peer
->as
) {
839 "%s: %s and %s are equal via same remote-as",
840 pfx_buf
, new_buf
, exist_buf
);
844 * TODO: If unequal cost ibgp multipath is enabled we can
845 * mark the paths as equal here instead of returning
850 "%s: %s wins over %s after IGP metric comparison",
851 pfx_buf
, new_buf
, exist_buf
);
854 "%s: %s loses to %s after IGP metric comparison",
855 pfx_buf
, new_buf
, exist_buf
);
860 /* 12. If both paths are external, prefer the path that was received
861 first (the oldest one). This step minimizes route-flap, since a
862 newer path won't displace an older one, even if it was the
863 preferred route based on the additional decision criteria below. */
864 if (!bgp_flag_check(bgp
, BGP_FLAG_COMPARE_ROUTER_ID
)
865 && new_sort
== BGP_PEER_EBGP
&& exist_sort
== BGP_PEER_EBGP
) {
866 if (CHECK_FLAG(new->flags
, BGP_INFO_SELECTED
)) {
869 "%s: %s wins over %s due to oldest external",
870 pfx_buf
, new_buf
, exist_buf
);
874 if (CHECK_FLAG(exist
->flags
, BGP_INFO_SELECTED
)) {
877 "%s: %s loses to %s due to oldest external",
878 pfx_buf
, new_buf
, exist_buf
);
883 /* 13. Router-ID comparision. */
884 /* If one of the paths is "stale", the corresponding peer router-id will
885 * be 0 and would always win over the other path. If originator id is
886 * used for the comparision, it will decide which path is better.
888 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
889 new_id
.s_addr
= newattr
->originator_id
.s_addr
;
891 new_id
.s_addr
= new->peer
->remote_id
.s_addr
;
892 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
893 exist_id
.s_addr
= existattr
->originator_id
.s_addr
;
895 exist_id
.s_addr
= exist
->peer
->remote_id
.s_addr
;
897 if (ntohl(new_id
.s_addr
) < ntohl(exist_id
.s_addr
)) {
900 "%s: %s wins over %s due to Router-ID comparison",
901 pfx_buf
, new_buf
, exist_buf
);
905 if (ntohl(new_id
.s_addr
) > ntohl(exist_id
.s_addr
)) {
908 "%s: %s loses to %s due to Router-ID comparison",
909 pfx_buf
, new_buf
, exist_buf
);
913 /* 14. Cluster length comparision. */
914 new_cluster
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
915 exist_cluster
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
917 if (new_cluster
< exist_cluster
) {
920 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
921 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
926 if (new_cluster
> exist_cluster
) {
929 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
930 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
935 /* 15. Neighbor address comparision. */
936 /* Do this only if neither path is "stale" as stale paths do not have
937 * valid peer information (as the connection may or may not be up).
939 if (CHECK_FLAG(exist
->flags
, BGP_INFO_STALE
)) {
942 "%s: %s wins over %s due to latter path being STALE",
943 pfx_buf
, new_buf
, exist_buf
);
947 if (CHECK_FLAG(new->flags
, BGP_INFO_STALE
)) {
950 "%s: %s loses to %s due to former path being STALE",
951 pfx_buf
, new_buf
, exist_buf
);
955 /* locally configured routes to advertise do not have su_remote */
956 if (new->peer
->su_remote
== NULL
)
958 if (exist
->peer
->su_remote
== NULL
)
961 ret
= sockunion_cmp(new->peer
->su_remote
, exist
->peer
->su_remote
);
966 "%s: %s loses to %s due to Neighor IP comparison",
967 pfx_buf
, new_buf
, exist_buf
);
974 "%s: %s wins over %s due to Neighor IP comparison",
975 pfx_buf
, new_buf
, exist_buf
);
980 zlog_debug("%s: %s wins over %s due to nothing left to compare",
981 pfx_buf
, new_buf
, exist_buf
);
986 /* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
987 * is preferred, or 0 if they are the same (usually will only occur if
988 * multipath is enabled
989 * This version is compatible with */
990 int bgp_info_cmp_compatible(struct bgp
*bgp
, struct bgp_info
*new,
991 struct bgp_info
*exist
, char *pfx_buf
, afi_t afi
,
996 ret
= bgp_info_cmp(bgp
, new, exist
, &paths_eq
, NULL
, 0, pfx_buf
, afi
,
1010 static enum filter_type
bgp_input_filter(struct peer
*peer
, struct prefix
*p
,
1011 struct attr
*attr
, afi_t afi
,
1014 struct bgp_filter
*filter
;
1016 filter
= &peer
->filter
[afi
][safi
];
1018 #define FILTER_EXIST_WARN(F, f, filter) \
1019 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
1020 zlog_warn("%s: Could not find configured input %s-list %s!", \
1021 peer->host, #f, F##_IN_NAME(filter));
1023 if (DISTRIBUTE_IN_NAME(filter
)) {
1024 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1026 if (access_list_apply(DISTRIBUTE_IN(filter
), p
) == FILTER_DENY
)
1030 if (PREFIX_LIST_IN_NAME(filter
)) {
1031 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1033 if (prefix_list_apply(PREFIX_LIST_IN(filter
), p
) == PREFIX_DENY
)
1037 if (FILTER_LIST_IN_NAME(filter
)) {
1038 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1040 if (as_list_apply(FILTER_LIST_IN(filter
), attr
->aspath
)
1045 return FILTER_PERMIT
;
1046 #undef FILTER_EXIST_WARN
1049 static enum filter_type
bgp_output_filter(struct peer
*peer
, struct prefix
*p
,
1050 struct attr
*attr
, afi_t afi
,
1053 struct bgp_filter
*filter
;
1055 filter
= &peer
->filter
[afi
][safi
];
1057 #define FILTER_EXIST_WARN(F, f, filter) \
1058 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
1059 zlog_warn("%s: Could not find configured output %s-list %s!", \
1060 peer->host, #f, F##_OUT_NAME(filter));
1062 if (DISTRIBUTE_OUT_NAME(filter
)) {
1063 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1065 if (access_list_apply(DISTRIBUTE_OUT(filter
), p
) == FILTER_DENY
)
1069 if (PREFIX_LIST_OUT_NAME(filter
)) {
1070 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1072 if (prefix_list_apply(PREFIX_LIST_OUT(filter
), p
)
1077 if (FILTER_LIST_OUT_NAME(filter
)) {
1078 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1080 if (as_list_apply(FILTER_LIST_OUT(filter
), attr
->aspath
)
1085 return FILTER_PERMIT
;
1086 #undef FILTER_EXIST_WARN
1089 /* If community attribute includes no_export then return 1. */
1090 static int bgp_community_filter(struct peer
*peer
, struct attr
*attr
)
1092 if (attr
->community
) {
1093 /* NO_ADVERTISE check. */
1094 if (community_include(attr
->community
, COMMUNITY_NO_ADVERTISE
))
1097 /* NO_EXPORT check. */
1098 if (peer
->sort
== BGP_PEER_EBGP
1099 && community_include(attr
->community
, COMMUNITY_NO_EXPORT
))
1102 /* NO_EXPORT_SUBCONFED check. */
1103 if (peer
->sort
== BGP_PEER_EBGP
1104 || peer
->sort
== BGP_PEER_CONFED
)
1105 if (community_include(attr
->community
,
1106 COMMUNITY_NO_EXPORT_SUBCONFED
))
1112 /* Route reflection loop check. */
1113 static int bgp_cluster_filter(struct peer
*peer
, struct attr
*attr
)
1115 struct in_addr cluster_id
;
1117 if (attr
->cluster
) {
1118 if (peer
->bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
1119 cluster_id
= peer
->bgp
->cluster_id
;
1121 cluster_id
= peer
->bgp
->router_id
;
1123 if (cluster_loop_check(attr
->cluster
, cluster_id
))
1129 static int bgp_input_modifier(struct peer
*peer
, struct prefix
*p
,
1130 struct attr
*attr
, afi_t afi
, safi_t safi
,
1131 const char *rmap_name
)
1133 struct bgp_filter
*filter
;
1134 struct bgp_info info
;
1135 route_map_result_t ret
;
1136 struct route_map
*rmap
= NULL
;
1138 filter
= &peer
->filter
[afi
][safi
];
1140 /* Apply default weight value. */
1141 if (peer
->weight
[afi
][safi
])
1142 attr
->weight
= peer
->weight
[afi
][safi
];
1145 rmap
= route_map_lookup_by_name(rmap_name
);
1150 if (ROUTE_MAP_IN_NAME(filter
)) {
1151 rmap
= ROUTE_MAP_IN(filter
);
1158 /* Route map apply. */
1160 /* Duplicate current value to new strucutre for modification. */
1164 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_IN
);
1166 /* Apply BGP route map to the attribute. */
1167 ret
= route_map_apply(rmap
, p
, RMAP_BGP
, &info
);
1169 peer
->rmap_type
= 0;
1171 if (ret
== RMAP_DENYMATCH
) {
1172 /* Free newly generated AS path and community by
1174 bgp_attr_flush(attr
);
1181 static int bgp_output_modifier(struct peer
*peer
, struct prefix
*p
,
1182 struct attr
*attr
, afi_t afi
, safi_t safi
,
1183 const char *rmap_name
)
1185 struct bgp_info info
;
1186 route_map_result_t ret
;
1187 struct route_map
*rmap
= NULL
;
1191 * So if we get to this point and have no rmap_name
1192 * we want to just show the output as it currently
1198 /* Apply default weight value. */
1199 if (peer
->weight
[afi
][safi
])
1200 attr
->weight
= peer
->weight
[afi
][safi
];
1202 rmap
= route_map_lookup_by_name(rmap_name
);
1205 * If we have a route map name and we do not find
1206 * the routemap that means we have an implicit
1212 /* Route map apply. */
1213 /* Duplicate current value to new strucutre for modification. */
1217 rmap_type
= peer
->rmap_type
;
1218 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1220 /* Apply BGP route map to the attribute. */
1221 ret
= route_map_apply(rmap
, p
, RMAP_BGP
, &info
);
1223 peer
->rmap_type
= rmap_type
;
1225 if (ret
== RMAP_DENYMATCH
)
1227 * caller has multiple error paths with bgp_attr_flush()
1234 /* If this is an EBGP peer with remove-private-AS */
1235 static void bgp_peer_remove_private_as(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1236 struct peer
*peer
, struct attr
*attr
)
1238 if (peer
->sort
== BGP_PEER_EBGP
1239 && (peer_af_flag_check(peer
, afi
, safi
,
1240 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1241 || peer_af_flag_check(peer
, afi
, safi
,
1242 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
)
1243 || peer_af_flag_check(peer
, afi
, safi
,
1244 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)
1245 || peer_af_flag_check(peer
, afi
, safi
,
1246 PEER_FLAG_REMOVE_PRIVATE_AS
))) {
1247 // Take action on the entire aspath
1248 if (peer_af_flag_check(peer
, afi
, safi
,
1249 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1250 || peer_af_flag_check(peer
, afi
, safi
,
1251 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)) {
1252 if (peer_af_flag_check(
1254 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
))
1255 attr
->aspath
= aspath_replace_private_asns(
1256 attr
->aspath
, bgp
->as
);
1258 // The entire aspath consists of private ASNs so create
1260 else if (aspath_private_as_check(attr
->aspath
))
1261 attr
->aspath
= aspath_empty_get();
1263 // There are some public and some private ASNs, remove
1266 attr
->aspath
= aspath_remove_private_asns(
1270 // 'all' was not specified so the entire aspath must be private
1272 // for us to do anything
1273 else if (aspath_private_as_check(attr
->aspath
)) {
1274 if (peer_af_flag_check(
1276 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
))
1277 attr
->aspath
= aspath_replace_private_asns(
1278 attr
->aspath
, bgp
->as
);
1280 attr
->aspath
= aspath_empty_get();
1285 /* If this is an EBGP peer with as-override */
1286 static void bgp_peer_as_override(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1287 struct peer
*peer
, struct attr
*attr
)
1289 if (peer
->sort
== BGP_PEER_EBGP
1290 && peer_af_flag_check(peer
, afi
, safi
, PEER_FLAG_AS_OVERRIDE
)) {
1291 if (aspath_single_asn_check(attr
->aspath
, peer
->as
))
1292 attr
->aspath
= aspath_replace_specific_asn(
1293 attr
->aspath
, peer
->as
, bgp
->as
);
1297 void bgp_attr_add_gshut_community(struct attr
*attr
)
1299 struct community
*old
;
1300 struct community
*new;
1301 struct community
*merge
;
1302 struct community
*gshut
;
1304 old
= attr
->community
;
1305 gshut
= community_str2com("graceful-shutdown");
1308 merge
= community_merge(community_dup(old
), gshut
);
1310 if (old
->refcnt
== 0)
1311 community_free(old
);
1313 new = community_uniq_sort(merge
);
1314 community_free(merge
);
1316 new = community_dup(gshut
);
1319 community_free(gshut
);
1320 attr
->community
= new;
1321 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
1323 /* When we add the graceful-shutdown community we must also
1324 * lower the local-preference */
1325 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1326 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1330 static void subgroup_announce_reset_nhop(uint8_t family
, struct attr
*attr
)
1332 if (family
== AF_INET
) {
1333 attr
->nexthop
.s_addr
= 0;
1334 attr
->mp_nexthop_global_in
.s_addr
= 0;
1336 if (family
== AF_INET6
)
1337 memset(&attr
->mp_nexthop_global
, 0, IPV6_MAX_BYTELEN
);
1340 int subgroup_announce_check(struct bgp_node
*rn
, struct bgp_info
*ri
,
1341 struct update_subgroup
*subgrp
, struct prefix
*p
,
1344 struct bgp_filter
*filter
;
1347 struct peer
*onlypeer
;
1349 struct attr
*riattr
;
1350 char buf
[PREFIX_STRLEN
];
1356 int samepeer_safe
= 0; /* for synthetic mplsvpns routes */
1358 if (DISABLE_BGP_ANNOUNCE
)
1361 afi
= SUBGRP_AFI(subgrp
);
1362 safi
= SUBGRP_SAFI(subgrp
);
1363 peer
= SUBGRP_PEER(subgrp
);
1365 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_LONESOUL
))
1366 onlypeer
= SUBGRP_PFIRST(subgrp
)->peer
;
1369 filter
= &peer
->filter
[afi
][safi
];
1370 bgp
= SUBGRP_INST(subgrp
);
1371 riattr
= bgp_info_mpath_count(ri
) ? bgp_info_mpath_attr(ri
) : ri
->attr
;
1374 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
)) && (safi
== SAFI_MPLS_VPN
)
1375 && ((ri
->type
== ZEBRA_ROUTE_BGP_DIRECT
)
1376 || (ri
->type
== ZEBRA_ROUTE_BGP_DIRECT_EXT
))) {
1379 * direct and direct_ext type routes originate internally even
1380 * though they can have peer pointers that reference other
1383 prefix2str(p
, buf
, PREFIX_STRLEN
);
1384 zlog_debug("%s: pfx %s bgp_direct->vpn route peer safe",
1390 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
))
1391 && ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_UNICAST
))
1392 && (ri
->type
== ZEBRA_ROUTE_BGP
)
1393 && (ri
->sub_type
== BGP_ROUTE_IMPORTED
)) {
1395 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1400 /* With addpath we may be asked to TX all kinds of paths so make sure
1402 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_VALID
)
1403 || CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
)
1404 || CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)) {
1408 /* If this is not the bestpath then check to see if there is an enabled
1410 * feature that requires us to advertise it */
1411 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
1412 if (!bgp_addpath_tx_path(peer
, afi
, safi
, ri
)) {
1417 /* Aggregate-address suppress check. */
1418 if (ri
->extra
&& ri
->extra
->suppress
)
1419 if (!UNSUPPRESS_MAP_NAME(filter
)) {
1424 * If we are doing VRF 2 VRF leaking via the import
1425 * statement, we want to prevent the route going
1426 * off box as that the RT and RD created are localy
1427 * significant and globaly useless.
1429 if (safi
== SAFI_MPLS_VPN
&& ri
->extra
&& ri
->extra
->num_labels
1430 && ri
->extra
->label
[0] == BGP_PREVENT_VRF_2_VRF_LEAK
)
1433 /* If it's labeled safi, make sure the route has a valid label. */
1434 if (safi
== SAFI_LABELED_UNICAST
) {
1435 mpls_label_t label
= bgp_adv_label(rn
, ri
, peer
, afi
, safi
);
1436 if (!bgp_is_valid_label(&label
)) {
1437 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1438 zlog_debug("u%" PRIu64
":s%" PRIu64
1439 " %s/%d is filtered - no label (%p)",
1440 subgrp
->update_group
->id
, subgrp
->id
,
1441 inet_ntop(p
->family
, &p
->u
.prefix
,
1442 buf
, SU_ADDRSTRLEN
),
1443 p
->prefixlen
, &label
);
1448 /* Do not send back route to sender. */
1449 if (onlypeer
&& from
== onlypeer
) {
1453 /* Do not send the default route in the BGP table if the neighbor is
1454 * configured for default-originate */
1455 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1456 PEER_FLAG_DEFAULT_ORIGINATE
)) {
1457 if (p
->family
== AF_INET
&& p
->u
.prefix4
.s_addr
== INADDR_ANY
)
1459 else if (p
->family
== AF_INET6
&& p
->prefixlen
== 0)
1463 /* Transparency check. */
1464 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
)
1465 && CHECK_FLAG(from
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
))
1470 /* If community is not disabled check the no-export and local. */
1471 if (!transparent
&& bgp_community_filter(peer
, riattr
)) {
1472 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1474 "subgrpannouncecheck: community filter check fail");
1478 /* If the attribute has originator-id and it is same as remote
1480 if (onlypeer
&& riattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
1481 && (IPV4_ADDR_SAME(&onlypeer
->remote_id
, &riattr
->originator_id
))) {
1482 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1484 "%s [Update:SEND] %s originator-id is same as "
1487 prefix2str(p
, buf
, sizeof(buf
)));
1491 /* ORF prefix-list filter check */
1492 if (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_RM_ADV
)
1493 && (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_SM_RCV
)
1494 || CHECK_FLAG(peer
->af_cap
[afi
][safi
],
1495 PEER_CAP_ORF_PREFIX_SM_OLD_RCV
)))
1496 if (peer
->orf_plist
[afi
][safi
]) {
1497 if (prefix_list_apply(peer
->orf_plist
[afi
][safi
], p
)
1499 if (bgp_debug_update(NULL
, p
,
1500 subgrp
->update_group
, 0))
1502 "%s [Update:SEND] %s is filtered via ORF",
1510 /* Output filter check. */
1511 if (bgp_output_filter(peer
, p
, riattr
, afi
, safi
) == FILTER_DENY
) {
1512 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1513 zlog_debug("%s [Update:SEND] %s is filtered",
1514 peer
->host
, prefix2str(p
, buf
, sizeof(buf
)));
1518 #ifdef BGP_SEND_ASPATH_CHECK
1519 /* AS path loop check. */
1520 if (onlypeer
&& aspath_loop_check(riattr
->aspath
, onlypeer
->as
)) {
1521 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1523 "%s [Update:SEND] suppress announcement to peer AS %u "
1524 "that is part of AS path.",
1525 onlypeer
->host
, onlypeer
->as
);
1528 #endif /* BGP_SEND_ASPATH_CHECK */
1530 /* If we're a CONFED we need to loop check the CONFED ID too */
1531 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
1532 if (aspath_loop_check(riattr
->aspath
, bgp
->confed_id
)) {
1533 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1535 "%s [Update:SEND] suppress announcement to peer AS %u"
1537 peer
->host
, bgp
->confed_id
);
1542 /* Route-Reflect check. */
1543 if (from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1548 /* IBGP reflection check. */
1549 if (reflect
&& !samepeer_safe
) {
1550 /* A route from a Client peer. */
1551 if (CHECK_FLAG(from
->af_flags
[afi
][safi
],
1552 PEER_FLAG_REFLECTOR_CLIENT
)) {
1553 /* Reflect to all the Non-Client peers and also to the
1554 Client peers other than the originator. Originator
1556 is already done. So there is noting to do. */
1557 /* no bgp client-to-client reflection check. */
1558 if (bgp_flag_check(bgp
, BGP_FLAG_NO_CLIENT_TO_CLIENT
))
1559 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1560 PEER_FLAG_REFLECTOR_CLIENT
))
1563 /* A route from a Non-client peer. Reflect to all other
1565 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1566 PEER_FLAG_REFLECTOR_CLIENT
))
1571 /* For modify attribute, copy it to temporary structure. */
1572 bgp_attr_dup(attr
, riattr
);
1574 /* If local-preference is not set. */
1575 if ((peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
)
1576 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))) {
1577 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1578 attr
->local_pref
= bgp
->default_local_pref
;
1581 /* If originator-id is not set and the route is to be reflected,
1582 set the originator id */
1584 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)))) {
1585 IPV4_ADDR_COPY(&(attr
->originator_id
), &(from
->remote_id
));
1586 SET_FLAG(attr
->flag
, BGP_ATTR_ORIGINATOR_ID
);
1589 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
1591 if (peer
->sort
== BGP_PEER_EBGP
1592 && attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
1593 if (from
!= bgp
->peer_self
&& !transparent
1594 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1595 PEER_FLAG_MED_UNCHANGED
))
1597 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
));
1600 /* Since the nexthop attribute can vary per peer, it is not explicitly
1602 * in announce check, only certain flags and length (or number of
1604 * -- for IPv6/MP_REACH) are set here in order to guide the update
1606 * code in setting the nexthop(s) on a per peer basis in
1608 * Typically, the source nexthop in the attribute is preserved but in
1610 * scenarios where we know it will always be overwritten, we reset the
1611 * nexthop to "0" in an attempt to achieve better Update packing. An
1612 * example of this is when a prefix from each of 2 IBGP peers needs to
1614 * announced to an EBGP peer (and they have the same attributes barring
1618 SET_FLAG(attr
->rmap_change_flags
, BATTR_REFLECTED
);
1620 #define NEXTHOP_IS_V6 \
1621 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
1622 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
1623 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
1624 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
1626 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
1628 * the peer (group) is configured to receive link-local nexthop
1630 * and it is available in the prefix OR we're not reflecting the route
1632 * the peer (group) to whom we're going to announce is on a shared
1634 * and this is either a self-originated route or the peer is EBGP.
1636 if (NEXTHOP_IS_V6
) {
1637 attr
->mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
1638 if ((CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1639 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)
1640 && IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
))
1641 || (!reflect
&& peer
->shared_network
1642 && (from
== bgp
->peer_self
1643 || peer
->sort
== BGP_PEER_EBGP
))) {
1644 attr
->mp_nexthop_len
=
1645 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
;
1648 /* Clear off link-local nexthop in source, whenever it is not
1650 * ensure more prefixes share the same attribute for
1653 if (!(CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1654 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)))
1655 memset(&attr
->mp_nexthop_local
, 0, IPV6_MAX_BYTELEN
);
1658 bgp_peer_remove_private_as(bgp
, afi
, safi
, peer
, attr
);
1659 bgp_peer_as_override(bgp
, afi
, safi
, peer
, attr
);
1661 /* Route map & unsuppress-map apply. */
1662 if (ROUTE_MAP_OUT_NAME(filter
) || (ri
->extra
&& ri
->extra
->suppress
)) {
1663 struct bgp_info info
;
1664 struct bgp_info_extra dummy_info_extra
;
1665 struct attr dummy_attr
;
1671 memcpy(&dummy_info_extra
, ri
->extra
,
1672 sizeof(struct bgp_info_extra
));
1673 info
.extra
= &dummy_info_extra
;
1676 /* don't confuse inbound and outbound setting */
1677 RESET_FLAG(attr
->rmap_change_flags
);
1680 * The route reflector is not allowed to modify the attributes
1681 * of the reflected IBGP routes unless explicitly allowed.
1683 if ((from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1684 && !bgp_flag_check(bgp
,
1685 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY
)) {
1686 bgp_attr_dup(&dummy_attr
, attr
);
1687 info
.attr
= &dummy_attr
;
1690 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1692 if (ri
->extra
&& ri
->extra
->suppress
)
1693 ret
= route_map_apply(UNSUPPRESS_MAP(filter
), p
,
1696 ret
= route_map_apply(ROUTE_MAP_OUT(filter
), p
,
1699 peer
->rmap_type
= 0;
1701 if (ret
== RMAP_DENYMATCH
) {
1702 bgp_attr_flush(attr
);
1707 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
1708 if (peer
->sort
== BGP_PEER_IBGP
1709 || peer
->sort
== BGP_PEER_CONFED
) {
1710 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1711 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1713 bgp_attr_add_gshut_community(attr
);
1717 /* After route-map has been applied, we check to see if the nexthop to
1718 * be carried in the attribute (that is used for the announcement) can
1719 * be cleared off or not. We do this in all cases where we would be
1720 * setting the nexthop to "ourselves". For IPv6, we only need to
1722 * the global nexthop here; the link-local nexthop would have been
1724 * already, and if not, it is required by the update formation code.
1725 * Also see earlier comments in this function.
1728 * If route-map has performed some operation on the nexthop or the peer
1729 * configuration says to pass it unchanged, we cannot reset the nexthop
1730 * here, so only attempt to do it if these aren't true. Note that the
1731 * route-map handler itself might have cleared the nexthop, if for
1733 * it is configured as 'peer-address'.
1735 if (!bgp_rmap_nhop_changed(attr
->rmap_change_flags
,
1736 riattr
->rmap_change_flags
)
1738 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1739 PEER_FLAG_NEXTHOP_UNCHANGED
)) {
1740 /* We can reset the nexthop, if setting (or forcing) it to
1742 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1743 PEER_FLAG_NEXTHOP_SELF
)
1744 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1745 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
1747 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1748 PEER_FLAG_FORCE_NEXTHOP_SELF
))
1749 subgroup_announce_reset_nhop(
1750 (peer_cap_enhe(peer
, afi
, safi
)
1754 } else if (peer
->sort
== BGP_PEER_EBGP
) {
1755 /* Can also reset the nexthop if announcing to EBGP, but
1757 * no peer in the subgroup is on a shared subnet.
1758 * Note: 3rd party nexthop currently implemented for
1761 if (!bgp_subgrp_multiaccess_check_v4(riattr
->nexthop
,
1763 subgroup_announce_reset_nhop(
1764 (peer_cap_enhe(peer
, afi
, safi
)
1768 } else if (CHECK_FLAG(ri
->flags
, BGP_INFO_ANNC_NH_SELF
)) {
1770 * This flag is used for leaked vpn-vrf routes
1772 int family
= p
->family
;
1774 if (peer_cap_enhe(peer
, afi
, safi
))
1777 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1779 "%s: BGP_INFO_ANNC_NH_SELF, family=%s",
1780 __func__
, family2str(family
));
1781 subgroup_announce_reset_nhop(family
, attr
);
1784 /* If IPv6/MP and nexthop does not have any override and happens
1786 * be a link-local address, reset it so that we don't pass along
1788 * source's link-local IPv6 address to recipients who may not be
1790 * the same interface.
1792 if (p
->family
== AF_INET6
|| peer_cap_enhe(peer
, afi
, safi
)) {
1793 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
))
1794 subgroup_announce_reset_nhop(AF_INET6
, attr
);
1801 void bgp_best_selection(struct bgp
*bgp
, struct bgp_node
*rn
,
1802 struct bgp_maxpaths_cfg
*mpath_cfg
,
1803 struct bgp_info_pair
*result
, afi_t afi
, safi_t safi
)
1805 struct bgp_info
*new_select
;
1806 struct bgp_info
*old_select
;
1807 struct bgp_info
*ri
;
1808 struct bgp_info
*ri1
;
1809 struct bgp_info
*ri2
;
1810 struct bgp_info
*nextri
= NULL
;
1811 int paths_eq
, do_mpath
, debug
;
1812 struct list mp_list
;
1813 char pfx_buf
[PREFIX2STR_BUFFER
];
1814 char path_buf
[PATH_ADDPATH_STR_BUFFER
];
1816 bgp_mp_list_init(&mp_list
);
1818 (mpath_cfg
->maxpaths_ebgp
> 1 || mpath_cfg
->maxpaths_ibgp
> 1);
1820 debug
= bgp_debug_bestpath(&rn
->p
);
1823 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
1825 /* bgp deterministic-med */
1827 if (bgp_flag_check(bgp
, BGP_FLAG_DETERMINISTIC_MED
)) {
1829 /* Clear BGP_INFO_DMED_SELECTED for all paths */
1830 for (ri1
= rn
->info
; ri1
; ri1
= ri1
->next
)
1831 bgp_info_unset_flag(rn
, ri1
, BGP_INFO_DMED_SELECTED
);
1833 for (ri1
= rn
->info
; ri1
; ri1
= ri1
->next
) {
1834 if (CHECK_FLAG(ri1
->flags
, BGP_INFO_DMED_CHECK
))
1836 if (BGP_INFO_HOLDDOWN(ri1
))
1838 if (ri1
->peer
&& ri1
->peer
!= bgp
->peer_self
)
1839 if (ri1
->peer
->status
!= Established
)
1844 for (ri2
= ri1
->next
; ri2
; ri2
= ri2
->next
) {
1845 if (CHECK_FLAG(ri2
->flags
,
1846 BGP_INFO_DMED_CHECK
))
1848 if (BGP_INFO_HOLDDOWN(ri2
))
1851 && ri2
->peer
!= bgp
->peer_self
1854 PEER_STATUS_NSF_WAIT
))
1855 if (ri2
->peer
->status
1859 if (aspath_cmp_left(ri1
->attr
->aspath
,
1861 || aspath_cmp_left_confed(
1863 ri2
->attr
->aspath
)) {
1864 if (bgp_info_cmp(bgp
, ri2
,
1870 bgp_info_unset_flag(
1872 BGP_INFO_DMED_SELECTED
);
1878 BGP_INFO_DMED_CHECK
);
1882 bgp_info_set_flag(rn
, new_select
, BGP_INFO_DMED_CHECK
);
1883 bgp_info_set_flag(rn
, new_select
,
1884 BGP_INFO_DMED_SELECTED
);
1887 bgp_info_path_with_addpath_rx_str(new_select
,
1889 zlog_debug("%s: %s is the bestpath from AS %u",
1891 aspath_get_first_as(
1892 new_select
->attr
->aspath
));
1897 /* Check old selected route and new selected route. */
1900 for (ri
= rn
->info
; (ri
!= NULL
) && (nextri
= ri
->next
, 1);
1902 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
))
1905 if (BGP_INFO_HOLDDOWN(ri
)) {
1906 /* reap REMOVED routes, if needs be
1907 * selected route must stay for a while longer though
1909 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)
1910 && (ri
!= old_select
))
1911 bgp_info_reap(rn
, ri
);
1914 zlog_debug("%s: ri %p in holddown", __func__
,
1920 if (ri
->peer
&& ri
->peer
!= bgp
->peer_self
1921 && !CHECK_FLAG(ri
->peer
->sflags
, PEER_STATUS_NSF_WAIT
))
1922 if (ri
->peer
->status
!= Established
) {
1926 "%s: ri %p non self peer %s not estab state",
1927 __func__
, ri
, ri
->peer
->host
);
1932 if (bgp_flag_check(bgp
, BGP_FLAG_DETERMINISTIC_MED
)
1933 && (!CHECK_FLAG(ri
->flags
, BGP_INFO_DMED_SELECTED
))) {
1934 bgp_info_unset_flag(rn
, ri
, BGP_INFO_DMED_CHECK
);
1936 zlog_debug("%s: ri %p dmed", __func__
, ri
);
1940 bgp_info_unset_flag(rn
, ri
, BGP_INFO_DMED_CHECK
);
1942 if (bgp_info_cmp(bgp
, ri
, new_select
, &paths_eq
, mpath_cfg
,
1943 debug
, pfx_buf
, afi
, safi
)) {
1948 /* Now that we know which path is the bestpath see if any of the other
1950 * qualify as multipaths
1954 bgp_info_path_with_addpath_rx_str(new_select
, path_buf
);
1956 sprintf(path_buf
, "NONE");
1958 "%s: After path selection, newbest is %s oldbest was %s",
1960 old_select
? old_select
->peer
->host
: "NONE");
1963 if (do_mpath
&& new_select
) {
1964 for (ri
= rn
->info
; (ri
!= NULL
) && (nextri
= ri
->next
, 1);
1968 bgp_info_path_with_addpath_rx_str(ri
, path_buf
);
1970 if (ri
== new_select
) {
1973 "%s: %s is the bestpath, add to the multipath list",
1975 bgp_mp_list_add(&mp_list
, ri
);
1979 if (BGP_INFO_HOLDDOWN(ri
))
1982 if (ri
->peer
&& ri
->peer
!= bgp
->peer_self
1983 && !CHECK_FLAG(ri
->peer
->sflags
,
1984 PEER_STATUS_NSF_WAIT
))
1985 if (ri
->peer
->status
!= Established
)
1988 if (!bgp_info_nexthop_cmp(ri
, new_select
)) {
1991 "%s: %s has the same nexthop as the bestpath, skip it",
1996 bgp_info_cmp(bgp
, ri
, new_select
, &paths_eq
, mpath_cfg
,
1997 debug
, pfx_buf
, afi
, safi
);
2002 "%s: %s is equivalent to the bestpath, add to the multipath list",
2004 bgp_mp_list_add(&mp_list
, ri
);
2009 bgp_info_mpath_update(rn
, new_select
, old_select
, &mp_list
, mpath_cfg
);
2010 bgp_info_mpath_aggregate_update(new_select
, old_select
);
2011 bgp_mp_list_clear(&mp_list
);
2013 result
->old
= old_select
;
2014 result
->new = new_select
;
2020 * A new route/change in bestpath of an existing route. Evaluate the path
2021 * for advertisement to the subgroup.
2023 int subgroup_process_announce_selected(struct update_subgroup
*subgrp
,
2024 struct bgp_info
*selected
,
2025 struct bgp_node
*rn
,
2026 uint32_t addpath_tx_id
)
2029 struct peer
*onlypeer
;
2035 afi
= SUBGRP_AFI(subgrp
);
2036 safi
= SUBGRP_SAFI(subgrp
);
2037 onlypeer
= ((SUBGRP_PCOUNT(subgrp
) == 1) ? (SUBGRP_PFIRST(subgrp
))->peer
2040 if (BGP_DEBUG(update
, UPDATE_OUT
)) {
2041 char buf_prefix
[PREFIX_STRLEN
];
2042 prefix2str(p
, buf_prefix
, sizeof(buf_prefix
));
2043 zlog_debug("%s: p=%s, selected=%p", __func__
, buf_prefix
,
2047 /* First update is deferred until ORF or ROUTE-REFRESH is received */
2048 if (onlypeer
&& CHECK_FLAG(onlypeer
->af_sflags
[afi
][safi
],
2049 PEER_STATUS_ORF_WAIT_REFRESH
))
2052 memset(&attr
, 0, sizeof(struct attr
));
2053 /* It's initialized in bgp_announce_check() */
2055 /* Announcement to the subgroup. If the route is filtered withdraw it.
2058 if (subgroup_announce_check(rn
, selected
, subgrp
, p
, &attr
))
2059 bgp_adj_out_set_subgroup(rn
, subgrp
, &attr
, selected
);
2061 bgp_adj_out_unset_subgroup(rn
, subgrp
, 1,
2062 selected
->addpath_tx_id
);
2065 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2067 bgp_adj_out_unset_subgroup(rn
, subgrp
, 1, addpath_tx_id
);
2074 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2075 * This is called at the end of route processing.
2077 void bgp_zebra_clear_route_change_flags(struct bgp_node
*rn
)
2079 struct bgp_info
*ri
;
2081 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
2082 if (BGP_INFO_HOLDDOWN(ri
))
2084 UNSET_FLAG(ri
->flags
, BGP_INFO_IGP_CHANGED
);
2085 UNSET_FLAG(ri
->flags
, BGP_INFO_ATTR_CHANGED
);
2090 * Has the route changed from the RIB's perspective? This is invoked only
2091 * if the route selection returns the same best route as earlier - to
2092 * determine if we need to update zebra or not.
2094 int bgp_zebra_has_route_changed(struct bgp_node
*rn
, struct bgp_info
*selected
)
2096 struct bgp_info
*mpinfo
;
2098 /* If this is multipath, check all selected paths for any nexthop change
2100 * attribute change. Some attribute changes (e.g., community) aren't of
2101 * relevance to the RIB, but we'll update zebra to ensure we handle the
2102 * case of BGP nexthop change. This is the behavior when the best path
2104 * an attribute change anyway.
2106 if (CHECK_FLAG(selected
->flags
, BGP_INFO_IGP_CHANGED
)
2107 || CHECK_FLAG(selected
->flags
, BGP_INFO_MULTIPATH_CHG
))
2110 /* If this is multipath, check all selected paths for any nexthop change
2112 for (mpinfo
= bgp_info_mpath_first(selected
); mpinfo
;
2113 mpinfo
= bgp_info_mpath_next(mpinfo
)) {
2114 if (CHECK_FLAG(mpinfo
->flags
, BGP_INFO_IGP_CHANGED
)
2115 || CHECK_FLAG(mpinfo
->flags
, BGP_INFO_ATTR_CHANGED
))
2119 /* Nothing has changed from the RIB's perspective. */
2123 struct bgp_process_queue
{
2125 STAILQ_HEAD(, bgp_node
) pqueue
;
2126 #define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2128 unsigned int queued
;
2132 * old_select = The old best path
2133 * new_select = the new best path
2135 * if (!old_select && new_select)
2136 * We are sending new information on.
2138 * if (old_select && new_select) {
2139 * if (new_select != old_select)
2140 * We have a new best path send a change
2142 * We've received a update with new attributes that needs
2146 * if (old_select && !new_select)
2147 * We have no eligible route that we can announce or the rn
2150 static void bgp_process_main_one(struct bgp
*bgp
, struct bgp_node
*rn
,
2151 afi_t afi
, safi_t safi
)
2153 struct prefix
*p
= &rn
->p
;
2154 struct bgp_info
*new_select
;
2155 struct bgp_info
*old_select
;
2156 struct bgp_info_pair old_and_new
;
2157 char pfx_buf
[PREFIX2STR_BUFFER
];
2160 /* Is it end of initial update? (after startup) */
2162 quagga_timestamp(3, bgp
->update_delay_zebra_resume_time
,
2163 sizeof(bgp
->update_delay_zebra_resume_time
));
2165 bgp
->main_zebra_update_hold
= 0;
2166 FOREACH_AFI_SAFI (afi
, safi
) {
2167 if (bgp_fibupd_safi(safi
))
2168 bgp_zebra_announce_table(bgp
, afi
, safi
);
2170 bgp
->main_peers_update_hold
= 0;
2172 bgp_start_routeadv(bgp
);
2176 debug
= bgp_debug_bestpath(&rn
->p
);
2178 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
2179 zlog_debug("%s: p=%s afi=%s, safi=%s start", __func__
, pfx_buf
,
2180 afi2str(afi
), safi2str(safi
));
2183 /* Best path selection. */
2184 bgp_best_selection(bgp
, rn
, &bgp
->maxpaths
[afi
][safi
], &old_and_new
,
2186 old_select
= old_and_new
.old
;
2187 new_select
= old_and_new
.new;
2189 /* Do we need to allocate or free labels?
2190 * Right now, since we only deal with per-prefix labels, it is not
2191 * necessary to do this upon changes to best path except if the label
2194 if (bgp
->allocate_mpls_labels
[afi
][safi
]) {
2197 || bgp_label_index_differs(new_select
, old_select
)
2198 || new_select
->sub_type
!= old_select
->sub_type
) {
2199 if (new_select
->sub_type
== BGP_ROUTE_STATIC
2200 && new_select
->attr
->flag
2202 BGP_ATTR_PREFIX_SID
)
2203 && new_select
->attr
->label_index
2204 != BGP_INVALID_LABEL_INDEX
) {
2207 BGP_NODE_REGISTERED_FOR_LABEL
))
2208 bgp_unregister_for_label(rn
);
2209 label_ntop(MPLS_LABEL_IMPLICIT_NULL
, 1,
2211 bgp_set_valid_label(&rn
->local_label
);
2213 bgp_register_for_label(rn
, new_select
);
2215 } else if (CHECK_FLAG(rn
->flags
,
2216 BGP_NODE_REGISTERED_FOR_LABEL
)) {
2217 bgp_unregister_for_label(rn
);
2219 } else if (CHECK_FLAG(rn
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
)) {
2220 bgp_unregister_for_label(rn
);
2224 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
2226 "%s: p=%s afi=%s, safi=%s, old_select=%p, new_select=%p",
2227 __func__
, pfx_buf
, afi2str(afi
), safi2str(safi
),
2228 old_select
, new_select
);
2231 /* If best route remains the same and this is not due to user-initiated
2232 * clear, see exactly what needs to be done.
2235 if (old_select
&& old_select
== new_select
2236 && !CHECK_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
)
2237 && !CHECK_FLAG(old_select
->flags
, BGP_INFO_ATTR_CHANGED
)
2238 && !bgp
->addpath_tx_used
[afi
][safi
]) {
2239 if (bgp_zebra_has_route_changed(rn
, old_select
)) {
2241 vnc_import_bgp_add_route(bgp
, p
, old_select
);
2242 vnc_import_bgp_exterior_add_route(bgp
, p
, old_select
);
2244 if (bgp_fibupd_safi(safi
)
2245 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2247 if (new_select
->type
== ZEBRA_ROUTE_BGP
2248 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2249 || new_select
->sub_type
2250 == BGP_ROUTE_IMPORTED
))
2252 bgp_zebra_announce(rn
, p
, old_select
,
2256 UNSET_FLAG(old_select
->flags
, BGP_INFO_MULTIPATH_CHG
);
2257 bgp_zebra_clear_route_change_flags(rn
);
2259 /* If there is a change of interest to peers, reannounce the
2261 if (CHECK_FLAG(old_select
->flags
, BGP_INFO_ATTR_CHANGED
)
2262 || CHECK_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
)) {
2263 group_announce_route(bgp
, afi
, safi
, rn
, new_select
);
2265 /* unicast routes must also be annouced to
2266 * labeled-unicast update-groups */
2267 if (safi
== SAFI_UNICAST
)
2268 group_announce_route(bgp
, afi
,
2269 SAFI_LABELED_UNICAST
, rn
,
2272 UNSET_FLAG(old_select
->flags
, BGP_INFO_ATTR_CHANGED
);
2273 UNSET_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
);
2276 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2280 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2282 UNSET_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
);
2284 /* bestpath has changed; bump version */
2285 if (old_select
|| new_select
) {
2286 bgp_bump_version(rn
);
2288 if (!bgp
->t_rmap_def_originate_eval
) {
2292 update_group_refresh_default_originate_route_map
,
2293 bgp
, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER
,
2294 &bgp
->t_rmap_def_originate_eval
);
2299 bgp_info_unset_flag(rn
, old_select
, BGP_INFO_SELECTED
);
2302 zlog_debug("%s: setting SELECTED flag", __func__
);
2303 bgp_info_set_flag(rn
, new_select
, BGP_INFO_SELECTED
);
2304 bgp_info_unset_flag(rn
, new_select
, BGP_INFO_ATTR_CHANGED
);
2305 UNSET_FLAG(new_select
->flags
, BGP_INFO_MULTIPATH_CHG
);
2309 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2310 if (old_select
!= new_select
) {
2312 vnc_import_bgp_exterior_del_route(bgp
, p
,
2314 vnc_import_bgp_del_route(bgp
, p
, old_select
);
2317 vnc_import_bgp_exterior_add_route(bgp
, p
,
2319 vnc_import_bgp_add_route(bgp
, p
, new_select
);
2325 group_announce_route(bgp
, afi
, safi
, rn
, new_select
);
2327 /* unicast routes must also be annouced to labeled-unicast update-groups
2329 if (safi
== SAFI_UNICAST
)
2330 group_announce_route(bgp
, afi
, SAFI_LABELED_UNICAST
, rn
,
2334 if (bgp_fibupd_safi(safi
) && (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VIEW
)
2335 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2336 if (new_select
&& new_select
->type
== ZEBRA_ROUTE_BGP
2337 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2338 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
2339 || new_select
->sub_type
== BGP_ROUTE_IMPORTED
))
2341 bgp_zebra_announce(rn
, p
, new_select
, bgp
, afi
, safi
);
2343 /* Withdraw the route from the kernel. */
2344 if (old_select
&& old_select
->type
== ZEBRA_ROUTE_BGP
2345 && (old_select
->sub_type
== BGP_ROUTE_NORMAL
2346 || old_select
->sub_type
== BGP_ROUTE_AGGREGATE
2347 || old_select
->sub_type
== BGP_ROUTE_IMPORTED
))
2349 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2353 /* advertise/withdraw type-5 routes */
2354 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2355 if (advertise_type5_routes(bgp
, afi
) && new_select
&&
2356 (!new_select
->extra
|| !new_select
->extra
->parent
))
2357 bgp_evpn_advertise_type5_route(bgp
, &rn
->p
,
2360 else if (advertise_type5_routes(bgp
, afi
) && old_select
&&
2361 (!old_select
->extra
|| !old_select
->extra
->parent
))
2362 bgp_evpn_withdraw_type5_route(bgp
, &rn
->p
, afi
, safi
);
2365 /* Clear any route change flags. */
2366 bgp_zebra_clear_route_change_flags(rn
);
2368 /* Reap old select bgp_info, if it has been removed */
2369 if (old_select
&& CHECK_FLAG(old_select
->flags
, BGP_INFO_REMOVED
))
2370 bgp_info_reap(rn
, old_select
);
2372 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2376 static wq_item_status
bgp_process_wq(struct work_queue
*wq
, void *data
)
2378 struct bgp_process_queue
*pqnode
= data
;
2379 struct bgp
*bgp
= pqnode
->bgp
;
2380 struct bgp_table
*table
;
2381 struct bgp_node
*rn
;
2384 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)) {
2385 bgp_process_main_one(bgp
, NULL
, 0, 0);
2386 /* should always have dedicated wq call */
2387 assert(STAILQ_FIRST(&pqnode
->pqueue
) == NULL
);
2391 while (!STAILQ_EMPTY(&pqnode
->pqueue
)) {
2392 rn
= STAILQ_FIRST(&pqnode
->pqueue
);
2393 STAILQ_REMOVE_HEAD(&pqnode
->pqueue
, pq
);
2394 STAILQ_NEXT(rn
, pq
) = NULL
; /* complete unlink */
2395 table
= bgp_node_table(rn
);
2396 /* note, new RNs may be added as part of processing */
2397 bgp_process_main_one(bgp
, rn
, table
->afi
, table
->safi
);
2399 bgp_unlock_node(rn
);
2400 bgp_table_unlock(table
);
2406 static void bgp_processq_del(struct work_queue
*wq
, void *data
)
2408 struct bgp_process_queue
*pqnode
= data
;
2410 bgp_unlock(pqnode
->bgp
);
2412 XFREE(MTYPE_BGP_PROCESS_QUEUE
, pqnode
);
2415 void bgp_process_queue_init(void)
2417 if (!bm
->process_main_queue
) {
2418 bm
->process_main_queue
=
2419 work_queue_new(bm
->master
, "process_main_queue");
2421 if (!bm
->process_main_queue
) {
2422 zlog_err("%s: Failed to allocate work queue", __func__
);
2427 bm
->process_main_queue
->spec
.workfunc
= &bgp_process_wq
;
2428 bm
->process_main_queue
->spec
.del_item_data
= &bgp_processq_del
;
2429 bm
->process_main_queue
->spec
.max_retries
= 0;
2430 bm
->process_main_queue
->spec
.hold
= 50;
2431 /* Use a higher yield value of 50ms for main queue processing */
2432 bm
->process_main_queue
->spec
.yield
= 50 * 1000L;
2435 static struct bgp_process_queue
*bgp_processq_alloc(struct bgp
*bgp
)
2437 struct bgp_process_queue
*pqnode
;
2439 pqnode
= XCALLOC(MTYPE_BGP_PROCESS_QUEUE
,
2440 sizeof(struct bgp_process_queue
));
2442 /* unlocked in bgp_processq_del */
2443 pqnode
->bgp
= bgp_lock(bgp
);
2444 STAILQ_INIT(&pqnode
->pqueue
);
2449 void bgp_process(struct bgp
*bgp
, struct bgp_node
*rn
, afi_t afi
, safi_t safi
)
2451 #define ARBITRARY_PROCESS_QLEN 10000
2452 struct work_queue
*wq
= bm
->process_main_queue
;
2453 struct bgp_process_queue
*pqnode
;
2454 int pqnode_reuse
= 0;
2456 /* already scheduled for processing? */
2457 if (CHECK_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
2463 /* Add route nodes to an existing work queue item until reaching the
2464 limit only if is from the same BGP view and it's not an EOIU marker
2466 if (work_queue_item_count(wq
)) {
2467 struct work_queue_item
*item
= work_queue_last_item(wq
);
2468 pqnode
= item
->data
;
2470 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)
2471 || pqnode
->bgp
!= bgp
2472 || pqnode
->queued
>= ARBITRARY_PROCESS_QLEN
)
2473 pqnode
= bgp_processq_alloc(bgp
);
2477 pqnode
= bgp_processq_alloc(bgp
);
2478 /* all unlocked in bgp_process_wq */
2479 bgp_table_lock(bgp_node_table(rn
));
2481 SET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2484 /* can't be enqueued twice */
2485 assert(STAILQ_NEXT(rn
, pq
) == NULL
);
2486 STAILQ_INSERT_TAIL(&pqnode
->pqueue
, rn
, pq
);
2490 work_queue_add(wq
, pqnode
);
2495 void bgp_add_eoiu_mark(struct bgp
*bgp
)
2497 struct bgp_process_queue
*pqnode
;
2499 if (bm
->process_main_queue
== NULL
)
2502 pqnode
= bgp_processq_alloc(bgp
);
2504 SET_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
);
2505 work_queue_add(bm
->process_main_queue
, pqnode
);
2508 static int bgp_maximum_prefix_restart_timer(struct thread
*thread
)
2512 peer
= THREAD_ARG(thread
);
2513 peer
->t_pmax_restart
= NULL
;
2515 if (bgp_debug_neighbor_events(peer
))
2517 "%s Maximum-prefix restart timer expired, restore peering",
2520 peer_clear(peer
, NULL
);
2525 int bgp_maximum_prefix_overflow(struct peer
*peer
, afi_t afi
, safi_t safi
,
2529 iana_safi_t pkt_safi
;
2531 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX
))
2534 if (peer
->pcount
[afi
][safi
] > peer
->pmax
[afi
][safi
]) {
2535 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2536 PEER_STATUS_PREFIX_LIMIT
)
2541 "%%MAXPFXEXCEED: No. of %s prefix received from %s %ld exceed, "
2543 afi_safi_print(afi
, safi
), peer
->host
,
2544 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2545 SET_FLAG(peer
->af_sflags
[afi
][safi
], PEER_STATUS_PREFIX_LIMIT
);
2547 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2548 PEER_FLAG_MAX_PREFIX_WARNING
))
2551 /* Convert AFI, SAFI to values for packet. */
2552 pkt_afi
= afi_int2iana(afi
);
2553 pkt_safi
= safi_int2iana(safi
);
2557 ndata
[0] = (pkt_afi
>> 8);
2559 ndata
[2] = pkt_safi
;
2560 ndata
[3] = (peer
->pmax
[afi
][safi
] >> 24);
2561 ndata
[4] = (peer
->pmax
[afi
][safi
] >> 16);
2562 ndata
[5] = (peer
->pmax
[afi
][safi
] >> 8);
2563 ndata
[6] = (peer
->pmax
[afi
][safi
]);
2565 SET_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
);
2566 bgp_notify_send_with_data(peer
, BGP_NOTIFY_CEASE
,
2567 BGP_NOTIFY_CEASE_MAX_PREFIX
,
2571 /* Dynamic peers will just close their connection. */
2572 if (peer_dynamic_neighbor(peer
))
2575 /* restart timer start */
2576 if (peer
->pmax_restart
[afi
][safi
]) {
2577 peer
->v_pmax_restart
=
2578 peer
->pmax_restart
[afi
][safi
] * 60;
2580 if (bgp_debug_neighbor_events(peer
))
2582 "%s Maximum-prefix restart timer started for %d secs",
2583 peer
->host
, peer
->v_pmax_restart
);
2585 BGP_TIMER_ON(peer
->t_pmax_restart
,
2586 bgp_maximum_prefix_restart_timer
,
2587 peer
->v_pmax_restart
);
2592 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
2593 PEER_STATUS_PREFIX_LIMIT
);
2595 if (peer
->pcount
[afi
][safi
]
2596 > (peer
->pmax
[afi
][safi
] * peer
->pmax_threshold
[afi
][safi
] / 100)) {
2597 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2598 PEER_STATUS_PREFIX_THRESHOLD
)
2603 "%%MAXPFX: No. of %s prefix received from %s reaches %ld, max %ld",
2604 afi_safi_print(afi
, safi
), peer
->host
,
2605 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2606 SET_FLAG(peer
->af_sflags
[afi
][safi
],
2607 PEER_STATUS_PREFIX_THRESHOLD
);
2609 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
2610 PEER_STATUS_PREFIX_THRESHOLD
);
2614 /* Unconditionally remove the route from the RIB, without taking
2615 * damping into consideration (eg, because the session went down)
2617 void bgp_rib_remove(struct bgp_node
*rn
, struct bgp_info
*ri
, struct peer
*peer
,
2618 afi_t afi
, safi_t safi
)
2620 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, ri
, afi
, safi
);
2622 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
2623 bgp_info_delete(rn
, ri
); /* keep historical info */
2625 bgp_process(peer
->bgp
, rn
, afi
, safi
);
2628 static void bgp_rib_withdraw(struct bgp_node
*rn
, struct bgp_info
*ri
,
2629 struct peer
*peer
, afi_t afi
, safi_t safi
,
2630 struct prefix_rd
*prd
)
2632 int status
= BGP_DAMP_NONE
;
2634 /* apply dampening, if result is suppressed, we'll be retaining
2635 * the bgp_info in the RIB for historical reference.
2637 if (CHECK_FLAG(peer
->bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
2638 && peer
->sort
== BGP_PEER_EBGP
)
2639 if ((status
= bgp_damp_withdraw(ri
, rn
, afi
, safi
, 0))
2640 == BGP_DAMP_SUPPRESSED
) {
2641 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, ri
, afi
,
2647 if (safi
== SAFI_MPLS_VPN
) {
2648 struct bgp_node
*prn
= NULL
;
2649 struct bgp_table
*table
= NULL
;
2651 prn
= bgp_node_get(peer
->bgp
->rib
[afi
][safi
],
2652 (struct prefix
*)prd
);
2654 table
= (struct bgp_table
*)(prn
->info
);
2656 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
2657 peer
->bgp
, prd
, table
, &rn
->p
, ri
);
2659 bgp_unlock_node(prn
);
2661 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2662 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
2664 vnc_import_bgp_del_route(peer
->bgp
, &rn
->p
, ri
);
2665 vnc_import_bgp_exterior_del_route(peer
->bgp
, &rn
->p
,
2671 /* If this is an EVPN route, process for un-import. */
2672 if (safi
== SAFI_EVPN
)
2673 bgp_evpn_unimport_route(peer
->bgp
, afi
, safi
, &rn
->p
, ri
);
2675 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
2678 struct bgp_info
*info_make(int type
, int sub_type
, unsigned short instance
,
2679 struct peer
*peer
, struct attr
*attr
,
2680 struct bgp_node
*rn
)
2682 struct bgp_info
*new;
2684 /* Make new BGP info. */
2685 new = XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_info
));
2687 new->instance
= instance
;
2688 new->sub_type
= sub_type
;
2691 new->uptime
= bgp_clock();
2693 new->addpath_tx_id
= ++peer
->bgp
->addpath_tx_id
;
2697 static void overlay_index_update(struct attr
*attr
,
2698 struct eth_segment_id
*eth_s_id
,
2699 union gw_addr
*gw_ip
)
2704 if (eth_s_id
== NULL
) {
2705 memset(&(attr
->evpn_overlay
.eth_s_id
), 0,
2706 sizeof(struct eth_segment_id
));
2708 memcpy(&(attr
->evpn_overlay
.eth_s_id
), eth_s_id
,
2709 sizeof(struct eth_segment_id
));
2711 if (gw_ip
== NULL
) {
2712 memset(&(attr
->evpn_overlay
.gw_ip
), 0, sizeof(union gw_addr
));
2714 memcpy(&(attr
->evpn_overlay
.gw_ip
), gw_ip
,
2715 sizeof(union gw_addr
));
2719 static bool overlay_index_equal(afi_t afi
, struct bgp_info
*info
,
2720 struct eth_segment_id
*eth_s_id
,
2721 union gw_addr
*gw_ip
)
2723 struct eth_segment_id
*info_eth_s_id
, *info_eth_s_id_remote
;
2724 union gw_addr
*info_gw_ip
, *info_gw_ip_remote
;
2727 if (afi
!= AFI_L2VPN
)
2730 memset(&temp
, 0, 16);
2731 info_eth_s_id
= (struct eth_segment_id
*)&temp
;
2732 info_gw_ip
= (union gw_addr
*)&temp
;
2733 if (eth_s_id
== NULL
&& gw_ip
== NULL
)
2736 info_eth_s_id
= &(info
->attr
->evpn_overlay
.eth_s_id
);
2737 info_gw_ip
= &(info
->attr
->evpn_overlay
.gw_ip
);
2740 info_gw_ip_remote
= (union gw_addr
*)&temp
;
2742 info_gw_ip_remote
= gw_ip
;
2743 if (eth_s_id
== NULL
)
2744 info_eth_s_id_remote
= (struct eth_segment_id
*)&temp
;
2746 info_eth_s_id_remote
= eth_s_id
;
2747 if (!memcmp(info_gw_ip
, info_gw_ip_remote
, sizeof(union gw_addr
)))
2749 return !memcmp(info_eth_s_id
, info_eth_s_id_remote
,
2750 sizeof(struct eth_segment_id
));
2753 /* Check if received nexthop is valid or not. */
2754 static int bgp_update_martian_nexthop(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
2759 /* Only validated for unicast and multicast currently. */
2760 /* Also valid for EVPN where the nexthop is an IP address. */
2761 if (safi
!= SAFI_UNICAST
&& safi
!= SAFI_MULTICAST
&& safi
!= SAFI_EVPN
)
2764 /* If NEXT_HOP is present, validate it. */
2765 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
2766 if (attr
->nexthop
.s_addr
== 0
2767 || IPV4_CLASS_DE(ntohl(attr
->nexthop
.s_addr
))
2768 || bgp_nexthop_self(bgp
, attr
->nexthop
))
2772 /* If MP_NEXTHOP is present, validate it. */
2773 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
2774 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
2775 * it is not an IPv6 link-local address.
2777 if (attr
->mp_nexthop_len
) {
2778 switch (attr
->mp_nexthop_len
) {
2779 case BGP_ATTR_NHLEN_IPV4
:
2780 case BGP_ATTR_NHLEN_VPNV4
:
2781 ret
= (attr
->mp_nexthop_global_in
.s_addr
== 0
2782 || IPV4_CLASS_DE(ntohl(
2783 attr
->mp_nexthop_global_in
.s_addr
))
2784 || bgp_nexthop_self(bgp
,
2785 attr
->mp_nexthop_global_in
));
2788 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
2789 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
2790 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
2791 ret
= (IN6_IS_ADDR_UNSPECIFIED(&attr
->mp_nexthop_global
)
2792 || IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
2793 || IN6_IS_ADDR_MULTICAST(
2794 &attr
->mp_nexthop_global
));
2806 int bgp_update(struct peer
*peer
, struct prefix
*p
, uint32_t addpath_id
,
2807 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
2808 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
2809 uint32_t num_labels
, int soft_reconfig
,
2810 struct bgp_route_evpn
*evpn
)
2813 int aspath_loop_count
= 0;
2814 struct bgp_node
*rn
;
2816 struct attr new_attr
;
2817 struct attr
*attr_new
;
2818 struct bgp_info
*ri
;
2819 struct bgp_info
*new;
2820 struct bgp_info_extra
*extra
;
2822 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
2824 int do_loop_check
= 1;
2825 int has_valid_label
= 0;
2827 int vnc_implicit_withdraw
= 0;
2831 memset(&new_attr
, 0, sizeof(struct attr
));
2832 new_attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
2833 new_attr
.label
= MPLS_INVALID_LABEL
;
2836 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
2837 /* TODO: Check to see if we can get rid of "is_valid_label" */
2838 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
2839 has_valid_label
= (num_labels
> 0) ? 1 : 0;
2841 has_valid_label
= bgp_is_valid_label(label
);
2843 /* When peer's soft reconfiguration enabled. Record input packet in
2846 && CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
2847 && peer
!= bgp
->peer_self
)
2848 bgp_adj_in_set(rn
, peer
, attr
, addpath_id
);
2850 /* Check previously received route. */
2851 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
2852 if (ri
->peer
== peer
&& ri
->type
== type
2853 && ri
->sub_type
== sub_type
2854 && ri
->addpath_rx_id
== addpath_id
)
2857 /* AS path local-as loop check. */
2858 if (peer
->change_local_as
) {
2859 if (peer
->allowas_in
[afi
][safi
])
2860 aspath_loop_count
= peer
->allowas_in
[afi
][safi
];
2861 else if (!CHECK_FLAG(peer
->flags
,
2862 PEER_FLAG_LOCAL_AS_NO_PREPEND
))
2863 aspath_loop_count
= 1;
2865 if (aspath_loop_check(attr
->aspath
, peer
->change_local_as
)
2866 > aspath_loop_count
) {
2867 reason
= "as-path contains our own AS;";
2872 /* If the peer is configured for "allowas-in origin" and the last ASN in
2874 * as-path is our ASN then we do not need to call aspath_loop_check
2876 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN_ORIGIN
))
2877 if (aspath_get_last_as(attr
->aspath
) == bgp
->as
)
2880 /* AS path loop check. */
2881 if (do_loop_check
) {
2882 if (aspath_loop_check(attr
->aspath
, bgp
->as
)
2883 > peer
->allowas_in
[afi
][safi
]
2884 || (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)
2885 && aspath_loop_check(attr
->aspath
, bgp
->confed_id
)
2886 > peer
->allowas_in
[afi
][safi
])) {
2887 reason
= "as-path contains our own AS;";
2892 /* Route reflector originator ID check. */
2893 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
2894 && IPV4_ADDR_SAME(&bgp
->router_id
, &attr
->originator_id
)) {
2895 reason
= "originator is us;";
2899 /* Route reflector cluster ID check. */
2900 if (bgp_cluster_filter(peer
, attr
)) {
2901 reason
= "reflected from the same cluster;";
2905 /* Apply incoming filter. */
2906 if (bgp_input_filter(peer
, p
, attr
, afi
, safi
) == FILTER_DENY
) {
2911 bgp_attr_dup(&new_attr
, attr
);
2913 /* Apply incoming route-map.
2914 * NB: new_attr may now contain newly allocated values from route-map
2916 * commands, so we need bgp_attr_flush in the error paths, until we
2918 * the attr (which takes over the memory references) */
2919 if (bgp_input_modifier(peer
, p
, &new_attr
, afi
, safi
, NULL
)
2921 reason
= "route-map;";
2922 bgp_attr_flush(&new_attr
);
2926 if (peer
->sort
== BGP_PEER_EBGP
) {
2928 /* If we receive the graceful-shutdown community from an eBGP
2929 * peer we must lower local-preference */
2930 if (new_attr
.community
2931 && community_include(new_attr
.community
, COMMUNITY_GSHUT
)) {
2932 new_attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
2933 new_attr
.local_pref
= BGP_GSHUT_LOCAL_PREF
;
2935 /* If graceful-shutdown is configured then add the GSHUT
2936 * community to all paths received from eBGP peers */
2937 } else if (bgp_flag_check(peer
->bgp
,
2938 BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
2939 bgp_attr_add_gshut_community(&new_attr
);
2943 /* next hop check. */
2944 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
)
2945 && bgp_update_martian_nexthop(bgp
, afi
, safi
, &new_attr
)) {
2946 reason
= "martian or self next-hop;";
2947 bgp_attr_flush(&new_attr
);
2951 attr_new
= bgp_attr_intern(&new_attr
);
2953 /* If the update is implicit withdraw. */
2955 ri
->uptime
= bgp_clock();
2956 same_attr
= attrhash_cmp(ri
->attr
, attr_new
);
2958 /* Same attribute comes in. */
2959 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)
2960 && attrhash_cmp(ri
->attr
, attr_new
)
2961 && (!has_valid_label
2962 || memcmp(&(bgp_info_extra_get(ri
))->label
, label
,
2963 num_labels
* sizeof(mpls_label_t
))
2965 && (overlay_index_equal(
2966 afi
, ri
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
2967 evpn
== NULL
? NULL
: &evpn
->gw_ip
))) {
2968 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
2969 BGP_CONFIG_DAMPENING
)
2970 && peer
->sort
== BGP_PEER_EBGP
2971 && CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
)) {
2972 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
2973 bgp_debug_rdpfxpath2str(
2974 afi
, safi
, prd
, p
, label
,
2975 num_labels
, addpath_id
? 1 : 0,
2976 addpath_id
, pfx_buf
,
2978 zlog_debug("%s rcvd %s", peer
->host
,
2982 if (bgp_damp_update(ri
, rn
, afi
, safi
)
2983 != BGP_DAMP_SUPPRESSED
) {
2984 bgp_aggregate_increment(bgp
, p
, ri
, afi
,
2986 bgp_process(bgp
, rn
, afi
, safi
);
2988 } else /* Duplicate - odd */
2990 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
2991 if (!peer
->rcvd_attr_printed
) {
2993 "%s rcvd UPDATE w/ attr: %s",
2995 peer
->rcvd_attr_str
);
2996 peer
->rcvd_attr_printed
= 1;
2999 bgp_debug_rdpfxpath2str(
3000 afi
, safi
, prd
, p
, label
,
3001 num_labels
, addpath_id
? 1 : 0,
3002 addpath_id
, pfx_buf
,
3005 "%s rcvd %s...duplicate ignored",
3006 peer
->host
, pfx_buf
);
3009 /* graceful restart STALE flag unset. */
3010 if (CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
)) {
3011 bgp_info_unset_flag(rn
, ri
,
3013 bgp_process(bgp
, rn
, afi
, safi
);
3017 bgp_unlock_node(rn
);
3018 bgp_attr_unintern(&attr_new
);
3023 /* Withdraw/Announce before we fully processed the withdraw */
3024 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)) {
3025 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3026 bgp_debug_rdpfxpath2str(
3027 afi
, safi
, prd
, p
, label
, num_labels
,
3028 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3031 "%s rcvd %s, flapped quicker than processing",
3032 peer
->host
, pfx_buf
);
3035 bgp_info_restore(rn
, ri
);
3038 /* Received Logging. */
3039 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3040 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
3041 num_labels
, addpath_id
? 1 : 0,
3042 addpath_id
, pfx_buf
,
3044 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3047 /* graceful restart STALE flag unset. */
3048 if (CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
))
3049 bgp_info_unset_flag(rn
, ri
, BGP_INFO_STALE
);
3051 /* The attribute is changed. */
3052 bgp_info_set_flag(rn
, ri
, BGP_INFO_ATTR_CHANGED
);
3054 /* implicit withdraw, decrement aggregate and pcount here.
3055 * only if update is accepted, they'll increment below.
3057 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
3059 /* Update bgp route dampening information. */
3060 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3061 && peer
->sort
== BGP_PEER_EBGP
) {
3062 /* This is implicit withdraw so we should update
3065 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
3066 bgp_damp_withdraw(ri
, rn
, afi
, safi
, 1);
3069 if (safi
== SAFI_MPLS_VPN
) {
3070 struct bgp_node
*prn
= NULL
;
3071 struct bgp_table
*table
= NULL
;
3073 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3074 (struct prefix
*)prd
);
3076 table
= (struct bgp_table
*)(prn
->info
);
3078 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3079 bgp
, prd
, table
, p
, ri
);
3081 bgp_unlock_node(prn
);
3083 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3084 && (safi
== SAFI_UNICAST
)) {
3085 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
3087 * Implicit withdraw case.
3089 ++vnc_implicit_withdraw
;
3090 vnc_import_bgp_del_route(bgp
, p
, ri
);
3091 vnc_import_bgp_exterior_del_route(bgp
, p
, ri
);
3096 /* Special handling for EVPN update of an existing route. If the
3097 * extended community attribute has changed, we need to
3099 * the route using its existing extended community. It will be
3100 * subsequently processed for import with the new extended
3103 if (safi
== SAFI_EVPN
&& !same_attr
) {
3105 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))
3107 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
3110 cmp
= ecommunity_cmp(ri
->attr
->ecommunity
,
3111 attr_new
->ecommunity
);
3113 if (bgp_debug_update(peer
, p
, NULL
, 1))
3115 "Change in EXT-COMM, existing %s new %s",
3117 ri
->attr
->ecommunity
),
3119 attr_new
->ecommunity
));
3120 bgp_evpn_unimport_route(bgp
, afi
, safi
,
3126 /* Update to new attribute. */
3127 bgp_attr_unintern(&ri
->attr
);
3128 ri
->attr
= attr_new
;
3130 /* Update MPLS label */
3131 if (has_valid_label
) {
3132 extra
= bgp_info_extra_get(ri
);
3133 memcpy(&extra
->label
, label
,
3134 num_labels
* sizeof(mpls_label_t
));
3135 extra
->num_labels
= num_labels
;
3136 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3137 bgp_set_valid_label(&extra
->label
[0]);
3141 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3142 && (safi
== SAFI_UNICAST
)) {
3143 if (vnc_implicit_withdraw
) {
3145 * Add back the route with its new attributes
3147 * The route is still selected, until the route
3149 * queued by bgp_process actually runs. We have
3151 * update to the VNC side immediately to avoid
3153 * configuration changes (e.g., route-map
3155 * trigger re-importation of the entire RIB.
3157 vnc_import_bgp_add_route(bgp
, p
, ri
);
3158 vnc_import_bgp_exterior_add_route(bgp
, p
, ri
);
3162 /* Update Overlay Index */
3163 if (afi
== AFI_L2VPN
) {
3164 overlay_index_update(
3165 ri
->attr
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3166 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3169 /* Update bgp route dampening information. */
3170 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3171 && peer
->sort
== BGP_PEER_EBGP
) {
3172 /* Now we do normal update dampening. */
3173 ret
= bgp_damp_update(ri
, rn
, afi
, safi
);
3174 if (ret
== BGP_DAMP_SUPPRESSED
) {
3175 bgp_unlock_node(rn
);
3180 /* Nexthop reachability check - for unicast and
3181 * labeled-unicast.. */
3182 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3183 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
3184 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
3185 && !CHECK_FLAG(peer
->flags
,
3186 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3188 bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3193 struct bgp
*bgp_nexthop
= bgp
;
3195 if (ri
->extra
&& ri
->extra
->bgp_orig
)
3196 bgp_nexthop
= ri
->extra
->bgp_orig
;
3198 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
, afi
,
3199 ri
, NULL
, connected
)
3200 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3201 bgp_info_set_flag(rn
, ri
, BGP_INFO_VALID
);
3203 if (BGP_DEBUG(nht
, NHT
)) {
3204 char buf1
[INET6_ADDRSTRLEN
];
3206 (const void *)&attr_new
3208 buf1
, INET6_ADDRSTRLEN
);
3209 zlog_debug("%s(%s): NH unresolved",
3210 __FUNCTION__
, buf1
);
3212 bgp_info_unset_flag(rn
, ri
, BGP_INFO_VALID
);
3215 bgp_info_set_flag(rn
, ri
, BGP_INFO_VALID
);
3218 if (safi
== SAFI_MPLS_VPN
) {
3219 struct bgp_node
*prn
= NULL
;
3220 struct bgp_table
*table
= NULL
;
3222 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3223 (struct prefix
*)prd
);
3225 table
= (struct bgp_table
*)(prn
->info
);
3227 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3228 bgp
, prd
, table
, p
, ri
);
3230 bgp_unlock_node(prn
);
3234 /* If this is an EVPN route and some attribute has changed,
3236 * route for import. If the extended community has changed, we
3238 * have done the un-import earlier and the import would result
3240 * route getting injected into appropriate L2 VNIs. If it is
3242 * some other attribute change, the import will result in
3244 * the attributes for the route in the VNI(s).
3246 if (safi
== SAFI_EVPN
&& !same_attr
)
3247 bgp_evpn_import_route(bgp
, afi
, safi
, p
, ri
);
3249 /* Process change. */
3250 bgp_aggregate_increment(bgp
, p
, ri
, afi
, safi
);
3252 bgp_process(bgp
, rn
, afi
, safi
);
3253 bgp_unlock_node(rn
);
3255 if (SAFI_UNICAST
== safi
3256 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3257 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3259 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, ri
);
3261 if ((SAFI_MPLS_VPN
== safi
)
3262 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3264 vpn_leak_to_vrf_update(bgp
, ri
);
3268 if (SAFI_MPLS_VPN
== safi
) {
3269 mpls_label_t label_decoded
= decode_label(label
);
3271 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3272 type
, sub_type
, &label_decoded
);
3274 if (SAFI_ENCAP
== safi
) {
3275 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3276 type
, sub_type
, NULL
);
3281 } // End of implicit withdraw
3283 /* Received Logging. */
3284 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3285 if (!peer
->rcvd_attr_printed
) {
3286 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3287 peer
->rcvd_attr_str
);
3288 peer
->rcvd_attr_printed
= 1;
3291 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3292 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3294 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3297 /* Make new BGP info. */
3298 new = info_make(type
, sub_type
, 0, peer
, attr_new
, rn
);
3300 /* Update MPLS label */
3301 if (has_valid_label
) {
3302 extra
= bgp_info_extra_get(new);
3303 memcpy(&extra
->label
, label
, num_labels
* sizeof(mpls_label_t
));
3304 extra
->num_labels
= num_labels
;
3305 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3306 bgp_set_valid_label(&extra
->label
[0]);
3309 /* Update Overlay Index */
3310 if (afi
== AFI_L2VPN
) {
3311 overlay_index_update(new->attr
,
3312 evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3313 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3315 /* Nexthop reachability check. */
3316 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3317 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
3318 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
3319 && !CHECK_FLAG(peer
->flags
,
3320 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3321 && !bgp_flag_check(bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3326 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, new, NULL
, connected
)
3327 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3328 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
3330 if (BGP_DEBUG(nht
, NHT
)) {
3331 char buf1
[INET6_ADDRSTRLEN
];
3333 (const void *)&attr_new
->nexthop
,
3334 buf1
, INET6_ADDRSTRLEN
);
3335 zlog_debug("%s(%s): NH unresolved",
3336 __FUNCTION__
, buf1
);
3338 bgp_info_unset_flag(rn
, new, BGP_INFO_VALID
);
3341 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
3344 new->addpath_rx_id
= addpath_id
;
3346 /* Increment prefix */
3347 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
3349 /* Register new BGP information. */
3350 bgp_info_add(rn
, new);
3352 /* route_node_get lock */
3353 bgp_unlock_node(rn
);
3356 if (safi
== SAFI_MPLS_VPN
) {
3357 struct bgp_node
*prn
= NULL
;
3358 struct bgp_table
*table
= NULL
;
3360 prn
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
3362 table
= (struct bgp_table
*)(prn
->info
);
3364 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3365 bgp
, prd
, table
, p
, new);
3367 bgp_unlock_node(prn
);
3371 /* If maximum prefix count is configured and current prefix
3373 if (bgp_maximum_prefix_overflow(peer
, afi
, safi
, 0))
3376 /* If this is an EVPN route, process for import. */
3377 if (safi
== SAFI_EVPN
)
3378 bgp_evpn_import_route(bgp
, afi
, safi
, p
, new);
3380 /* Process change. */
3381 bgp_process(bgp
, rn
, afi
, safi
);
3383 if (SAFI_UNICAST
== safi
3384 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3385 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3386 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
3388 if ((SAFI_MPLS_VPN
== safi
)
3389 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3391 vpn_leak_to_vrf_update(bgp
, new);
3394 if (SAFI_MPLS_VPN
== safi
) {
3395 mpls_label_t label_decoded
= decode_label(label
);
3397 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3398 sub_type
, &label_decoded
);
3400 if (SAFI_ENCAP
== safi
) {
3401 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3408 /* This BGP update is filtered. Log the reason then update BGP
3411 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3412 if (!peer
->rcvd_attr_printed
) {
3413 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3414 peer
->rcvd_attr_str
);
3415 peer
->rcvd_attr_printed
= 1;
3418 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3419 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3421 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
3422 peer
->host
, pfx_buf
, reason
);
3426 /* If this is an EVPN route, un-import it as it is now filtered.
3428 if (safi
== SAFI_EVPN
)
3429 bgp_evpn_unimport_route(bgp
, afi
, safi
, p
, ri
);
3431 if (SAFI_UNICAST
== safi
3432 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3433 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3435 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, ri
);
3437 if ((SAFI_MPLS_VPN
== safi
)
3438 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3440 vpn_leak_to_vrf_withdraw(bgp
, ri
);
3443 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
3446 bgp_unlock_node(rn
);
3450 * Filtered update is treated as an implicit withdrawal (see
3452 * a few lines above)
3454 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3455 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3463 int bgp_withdraw(struct peer
*peer
, struct prefix
*p
, uint32_t addpath_id
,
3464 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
3465 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
3466 uint32_t num_labels
, struct bgp_route_evpn
*evpn
)
3469 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
3470 struct bgp_node
*rn
;
3471 struct bgp_info
*ri
;
3474 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3475 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3483 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
3485 /* If peer is soft reconfiguration enabled. Record input packet for
3486 * further calculation.
3488 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
3489 * routes that are filtered. This tanks out Quagga RS pretty badly due
3491 * the iteration over all RS clients.
3492 * Since we need to remove the entry from adj_in anyway, do that first
3494 * if there was no entry, we don't need to do anything more.
3496 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
3497 && peer
!= bgp
->peer_self
)
3498 if (!bgp_adj_in_unset(rn
, peer
, addpath_id
)) {
3499 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3500 bgp_debug_rdpfxpath2str(
3501 afi
, safi
, prd
, p
, label
, num_labels
,
3502 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3505 "%s withdrawing route %s not in adj-in",
3506 peer
->host
, pfx_buf
);
3508 bgp_unlock_node(rn
);
3512 /* Lookup withdrawn route. */
3513 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
3514 if (ri
->peer
== peer
&& ri
->type
== type
3515 && ri
->sub_type
== sub_type
3516 && ri
->addpath_rx_id
== addpath_id
)
3520 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3521 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3522 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3524 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer
->host
,
3528 /* Withdraw specified route from routing table. */
3529 if (ri
&& !CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
)) {
3530 bgp_rib_withdraw(rn
, ri
, peer
, afi
, safi
, prd
);
3531 if (SAFI_UNICAST
== safi
3532 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3533 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3534 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, ri
);
3536 if ((SAFI_MPLS_VPN
== safi
)
3537 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3539 vpn_leak_to_vrf_withdraw(bgp
, ri
);
3541 } else if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3542 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3543 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3545 zlog_debug("%s Can't find the route %s", peer
->host
, pfx_buf
);
3548 /* Unlock bgp_node_get() lock. */
3549 bgp_unlock_node(rn
);
3554 void bgp_default_originate(struct peer
*peer
, afi_t afi
, safi_t safi
,
3557 struct update_subgroup
*subgrp
;
3558 subgrp
= peer_subgroup(peer
, afi
, safi
);
3559 subgroup_default_originate(subgrp
, withdraw
);
3564 * bgp_stop_announce_route_timer
3566 void bgp_stop_announce_route_timer(struct peer_af
*paf
)
3568 if (!paf
->t_announce_route
)
3571 THREAD_TIMER_OFF(paf
->t_announce_route
);
3575 * bgp_announce_route_timer_expired
3577 * Callback that is invoked when the route announcement timer for a
3580 static int bgp_announce_route_timer_expired(struct thread
*t
)
3582 struct peer_af
*paf
;
3585 paf
= THREAD_ARG(t
);
3588 if (peer
->status
!= Established
)
3591 if (!peer
->afc_nego
[paf
->afi
][paf
->safi
])
3594 peer_af_announce_route(paf
, 1);
3599 * bgp_announce_route
3601 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
3603 void bgp_announce_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
3605 struct peer_af
*paf
;
3606 struct update_subgroup
*subgrp
;
3608 paf
= peer_af_find(peer
, afi
, safi
);
3611 subgrp
= PAF_SUBGRP(paf
);
3614 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
3615 * or a refresh has already been triggered.
3617 if (!subgrp
|| paf
->t_announce_route
)
3621 * Start a timer to stagger/delay the announce. This serves
3622 * two purposes - announcement can potentially be combined for
3623 * multiple peers and the announcement doesn't happen in the
3626 thread_add_timer_msec(bm
->master
, bgp_announce_route_timer_expired
, paf
,
3627 (subgrp
->peer_count
== 1)
3628 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
3629 : BGP_ANNOUNCE_ROUTE_DELAY_MS
,
3630 &paf
->t_announce_route
);
3634 * Announce routes from all AF tables to a peer.
3636 * This should ONLY be called when there is a need to refresh the
3637 * routes to the peer based on a policy change for this peer alone
3638 * or a route refresh request received from the peer.
3639 * The operation will result in splitting the peer from its existing
3640 * subgroups and putting it in new subgroups.
3642 void bgp_announce_route_all(struct peer
*peer
)
3647 FOREACH_AFI_SAFI (afi
, safi
)
3648 bgp_announce_route(peer
, afi
, safi
);
3651 static void bgp_soft_reconfig_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
3652 struct bgp_table
*table
,
3653 struct prefix_rd
*prd
)
3656 struct bgp_node
*rn
;
3657 struct bgp_adj_in
*ain
;
3660 table
= peer
->bgp
->rib
[afi
][safi
];
3662 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
3663 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
3664 if (ain
->peer
!= peer
)
3667 struct bgp_info
*ri
= rn
->info
;
3668 uint32_t num_labels
= 0;
3669 mpls_label_t
*label_pnt
= NULL
;
3671 if (ri
&& ri
->extra
)
3672 num_labels
= ri
->extra
->num_labels
;
3674 label_pnt
= &ri
->extra
->label
[0];
3676 ret
= bgp_update(peer
, &rn
->p
, ain
->addpath_rx_id
,
3677 ain
->attr
, afi
, safi
, ZEBRA_ROUTE_BGP
,
3678 BGP_ROUTE_NORMAL
, prd
, label_pnt
,
3679 num_labels
, 1, NULL
);
3682 bgp_unlock_node(rn
);
3688 void bgp_soft_reconfig_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
3690 struct bgp_node
*rn
;
3691 struct bgp_table
*table
;
3693 if (peer
->status
!= Established
)
3696 if ((safi
!= SAFI_MPLS_VPN
) && (safi
!= SAFI_ENCAP
)
3697 && (safi
!= SAFI_EVPN
))
3698 bgp_soft_reconfig_table(peer
, afi
, safi
, NULL
, NULL
);
3700 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
3701 rn
= bgp_route_next(rn
))
3702 if ((table
= rn
->info
) != NULL
) {
3703 struct prefix_rd prd
;
3704 prd
.family
= AF_UNSPEC
;
3706 memcpy(&prd
.val
, rn
->p
.u
.val
, 8);
3708 bgp_soft_reconfig_table(peer
, afi
, safi
, table
,
3714 struct bgp_clear_node_queue
{
3715 struct bgp_node
*rn
;
3718 static wq_item_status
bgp_clear_route_node(struct work_queue
*wq
, void *data
)
3720 struct bgp_clear_node_queue
*cnq
= data
;
3721 struct bgp_node
*rn
= cnq
->rn
;
3722 struct peer
*peer
= wq
->spec
.data
;
3723 struct bgp_info
*ri
;
3725 afi_t afi
= bgp_node_table(rn
)->afi
;
3726 safi_t safi
= bgp_node_table(rn
)->safi
;
3731 /* It is possible that we have multiple paths for a prefix from a peer
3732 * if that peer is using AddPath.
3734 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
3735 if (ri
->peer
!= peer
)
3738 /* graceful restart STALE flag set. */
3739 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_NSF_WAIT
)
3740 && peer
->nsf
[afi
][safi
]
3741 && !CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
)
3742 && !CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
3743 bgp_info_set_flag(rn
, ri
, BGP_INFO_STALE
);
3745 /* If this is an EVPN route, process for
3747 if (safi
== SAFI_EVPN
)
3748 bgp_evpn_unimport_route(bgp
, afi
, safi
,
3750 /* Handle withdraw for VRF route-leaking and L3VPN */
3751 if (SAFI_UNICAST
== safi
3752 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
||
3753 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3754 vpn_leak_from_vrf_withdraw(bgp_get_default(),
3757 if (SAFI_MPLS_VPN
== safi
&&
3758 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
3759 vpn_leak_to_vrf_withdraw(bgp
, ri
);
3762 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
3768 static void bgp_clear_node_queue_del(struct work_queue
*wq
, void *data
)
3770 struct bgp_clear_node_queue
*cnq
= data
;
3771 struct bgp_node
*rn
= cnq
->rn
;
3772 struct bgp_table
*table
= bgp_node_table(rn
);
3774 bgp_unlock_node(rn
);
3775 bgp_table_unlock(table
);
3776 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE
, cnq
);
3779 static void bgp_clear_node_complete(struct work_queue
*wq
)
3781 struct peer
*peer
= wq
->spec
.data
;
3783 /* Tickle FSM to start moving again */
3784 BGP_EVENT_ADD(peer
, Clearing_Completed
);
3786 peer_unlock(peer
); /* bgp_clear_route */
3789 static void bgp_clear_node_queue_init(struct peer
*peer
)
3791 char wname
[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
3793 snprintf(wname
, sizeof(wname
), "clear %s", peer
->host
);
3794 #undef CLEAR_QUEUE_NAME_LEN
3796 if ((peer
->clear_node_queue
= work_queue_new(bm
->master
, wname
))
3798 zlog_err("%s: Failed to allocate work queue", __func__
);
3801 peer
->clear_node_queue
->spec
.hold
= 10;
3802 peer
->clear_node_queue
->spec
.workfunc
= &bgp_clear_route_node
;
3803 peer
->clear_node_queue
->spec
.del_item_data
= &bgp_clear_node_queue_del
;
3804 peer
->clear_node_queue
->spec
.completion_func
= &bgp_clear_node_complete
;
3805 peer
->clear_node_queue
->spec
.max_retries
= 0;
3807 /* we only 'lock' this peer reference when the queue is actually active
3809 peer
->clear_node_queue
->spec
.data
= peer
;
3812 static void bgp_clear_route_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
3813 struct bgp_table
*table
)
3815 struct bgp_node
*rn
;
3816 int force
= bm
->process_main_queue
? 0 : 1;
3819 table
= peer
->bgp
->rib
[afi
][safi
];
3821 /* If still no table => afi/safi isn't configured at all or smth. */
3825 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
3826 struct bgp_info
*ri
, *next
;
3827 struct bgp_adj_in
*ain
;
3828 struct bgp_adj_in
*ain_next
;
3830 /* XXX:TODO: This is suboptimal, every non-empty route_node is
3831 * queued for every clearing peer, regardless of whether it is
3832 * relevant to the peer at hand.
3834 * Overview: There are 3 different indices which need to be
3835 * scrubbed, potentially, when a peer is removed:
3837 * 1 peer's routes visible via the RIB (ie accepted routes)
3838 * 2 peer's routes visible by the (optional) peer's adj-in index
3839 * 3 other routes visible by the peer's adj-out index
3841 * 3 there is no hurry in scrubbing, once the struct peer is
3842 * removed from bgp->peer, we could just GC such deleted peer's
3843 * adj-outs at our leisure.
3845 * 1 and 2 must be 'scrubbed' in some way, at least made
3846 * invisible via RIB index before peer session is allowed to be
3847 * brought back up. So one needs to know when such a 'search' is
3852 * - there'd be a single global queue or a single RIB walker
3853 * - rather than tracking which route_nodes still need to be
3854 * examined on a peer basis, we'd track which peers still
3857 * Given that our per-peer prefix-counts now should be reliable,
3858 * this may actually be achievable. It doesn't seem to be a huge
3859 * problem at this time,
3861 * It is possible that we have multiple paths for a prefix from
3863 * if that peer is using AddPath.
3867 ain_next
= ain
->next
;
3869 if (ain
->peer
== peer
) {
3870 bgp_adj_in_remove(rn
, ain
);
3871 bgp_unlock_node(rn
);
3877 for (ri
= rn
->info
; ri
; ri
= next
) {
3879 if (ri
->peer
!= peer
)
3883 bgp_info_reap(rn
, ri
);
3885 struct bgp_clear_node_queue
*cnq
;
3887 /* both unlocked in bgp_clear_node_queue_del */
3888 bgp_table_lock(bgp_node_table(rn
));
3891 MTYPE_BGP_CLEAR_NODE_QUEUE
,
3892 sizeof(struct bgp_clear_node_queue
));
3894 work_queue_add(peer
->clear_node_queue
, cnq
);
3902 void bgp_clear_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
3904 struct bgp_node
*rn
;
3905 struct bgp_table
*table
;
3907 if (peer
->clear_node_queue
== NULL
)
3908 bgp_clear_node_queue_init(peer
);
3910 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
3911 * Idle until it receives a Clearing_Completed event. This protects
3912 * against peers which flap faster than we can we clear, which could
3915 * a) race with routes from the new session being installed before
3916 * clear_route_node visits the node (to delete the route of that
3918 * b) resource exhaustion, clear_route_node likely leads to an entry
3919 * on the process_main queue. Fast-flapping could cause that queue
3923 /* lock peer in assumption that clear-node-queue will get nodes; if so,
3924 * the unlock will happen upon work-queue completion; other wise, the
3925 * unlock happens at the end of this function.
3927 if (!peer
->clear_node_queue
->thread
)
3930 if (safi
!= SAFI_MPLS_VPN
&& safi
!= SAFI_ENCAP
&& safi
!= SAFI_EVPN
)
3931 bgp_clear_route_table(peer
, afi
, safi
, NULL
);
3933 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
3934 rn
= bgp_route_next(rn
))
3935 if ((table
= rn
->info
) != NULL
)
3936 bgp_clear_route_table(peer
, afi
, safi
, table
);
3938 /* unlock if no nodes got added to the clear-node-queue. */
3939 if (!peer
->clear_node_queue
->thread
)
3943 void bgp_clear_route_all(struct peer
*peer
)
3948 FOREACH_AFI_SAFI (afi
, safi
)
3949 bgp_clear_route(peer
, afi
, safi
);
3952 rfapiProcessPeerDown(peer
);
3956 void bgp_clear_adj_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
3958 struct bgp_table
*table
;
3959 struct bgp_node
*rn
;
3960 struct bgp_adj_in
*ain
;
3961 struct bgp_adj_in
*ain_next
;
3963 table
= peer
->bgp
->rib
[afi
][safi
];
3965 /* It is possible that we have multiple paths for a prefix from a peer
3966 * if that peer is using AddPath.
3968 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
3972 ain_next
= ain
->next
;
3974 if (ain
->peer
== peer
) {
3975 bgp_adj_in_remove(rn
, ain
);
3976 bgp_unlock_node(rn
);
3984 void bgp_clear_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
3986 struct bgp_node
*rn
;
3987 struct bgp_info
*ri
;
3988 struct bgp_table
*table
;
3990 if (safi
== SAFI_MPLS_VPN
) {
3991 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
3992 rn
= bgp_route_next(rn
)) {
3993 struct bgp_node
*rm
;
3994 struct bgp_info
*ri
;
3996 /* look for neighbor in tables */
3997 if ((table
= rn
->info
) == NULL
)
4000 for (rm
= bgp_table_top(table
); rm
;
4001 rm
= bgp_route_next(rm
))
4002 for (ri
= rm
->info
; ri
; ri
= ri
->next
) {
4003 if (ri
->peer
!= peer
)
4005 if (!CHECK_FLAG(ri
->flags
,
4009 bgp_rib_remove(rm
, ri
, peer
, afi
, safi
);
4014 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4015 rn
= bgp_route_next(rn
))
4016 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
4017 if (ri
->peer
!= peer
)
4019 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
))
4021 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
4027 static void bgp_cleanup_table(struct bgp
*bgp
, struct bgp_table
*table
,
4030 struct bgp_node
*rn
;
4031 struct bgp_info
*ri
;
4032 struct bgp_info
*next
;
4034 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
4035 for (ri
= rn
->info
; ri
; ri
= next
) {
4037 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)
4038 && ri
->type
== ZEBRA_ROUTE_BGP
4039 && (ri
->sub_type
== BGP_ROUTE_NORMAL
4040 || ri
->sub_type
== BGP_ROUTE_AGGREGATE
4041 || ri
->sub_type
== BGP_ROUTE_IMPORTED
)) {
4043 if (bgp_fibupd_safi(safi
))
4044 bgp_zebra_withdraw(&rn
->p
, ri
,
4046 bgp_info_reap(rn
, ri
);
4051 /* Delete all kernel routes. */
4052 void bgp_cleanup_routes(struct bgp
*bgp
)
4055 struct bgp_node
*rn
;
4057 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
4058 if (afi
== AFI_L2VPN
)
4060 bgp_cleanup_table(bgp
, bgp
->rib
[afi
][SAFI_UNICAST
],
4063 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
4065 if (afi
!= AFI_L2VPN
) {
4067 safi
= SAFI_MPLS_VPN
;
4068 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4069 rn
= bgp_route_next(rn
)) {
4071 bgp_cleanup_table(bgp
,
4072 (struct bgp_table
*)(rn
->info
),
4074 bgp_table_finish((struct bgp_table
**)&(
4077 bgp_unlock_node(rn
);
4081 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4082 rn
= bgp_route_next(rn
)) {
4084 bgp_cleanup_table(bgp
,
4085 (struct bgp_table
*)(rn
->info
),
4087 bgp_table_finish((struct bgp_table
**)&(
4090 bgp_unlock_node(rn
);
4095 for (rn
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); rn
;
4096 rn
= bgp_route_next(rn
)) {
4098 bgp_cleanup_table(bgp
,
4099 (struct bgp_table
*)(rn
->info
),
4101 bgp_table_finish((struct bgp_table
**)&(rn
->info
));
4103 bgp_unlock_node(rn
);
4108 void bgp_reset(void)
4111 bgp_zclient_reset();
4112 access_list_reset();
4113 prefix_list_reset();
4116 static int bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
4118 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
4119 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
4120 PEER_CAP_ADDPATH_AF_TX_RCV
));
4123 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
4125 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
4126 struct bgp_nlri
*packet
)
4135 int addpath_encoded
;
4136 uint32_t addpath_id
;
4139 lim
= pnt
+ packet
->length
;
4141 safi
= packet
->safi
;
4143 addpath_encoded
= bgp_addpath_encode_rx(peer
, afi
, safi
);
4145 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
4146 syntactic validity. If the field is syntactically incorrect,
4147 then the Error Subcode is set to Invalid Network Field. */
4148 for (; pnt
< lim
; pnt
+= psize
) {
4149 /* Clear prefix structure. */
4150 memset(&p
, 0, sizeof(struct prefix
));
4152 if (addpath_encoded
) {
4154 /* When packet overflow occurs return immediately. */
4155 if (pnt
+ BGP_ADDPATH_ID_LEN
> lim
)
4158 addpath_id
= ntohl(*((uint32_t *)pnt
));
4159 pnt
+= BGP_ADDPATH_ID_LEN
;
4162 /* Fetch prefix length. */
4163 p
.prefixlen
= *pnt
++;
4164 /* afi/safi validity already verified by caller,
4165 * bgp_update_receive */
4166 p
.family
= afi2family(afi
);
4168 /* Prefix length check. */
4169 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
4171 "%s [Error] Update packet error (wrong perfix length %d for afi %u)",
4172 peer
->host
, p
.prefixlen
, packet
->afi
);
4176 /* Packet size overflow check. */
4177 psize
= PSIZE(p
.prefixlen
);
4179 /* When packet overflow occur return immediately. */
4180 if (pnt
+ psize
> lim
) {
4182 "%s [Error] Update packet error (prefix length %d overflows packet)",
4183 peer
->host
, p
.prefixlen
);
4187 /* Defensive coding, double-check the psize fits in a struct
4189 if (psize
> (ssize_t
)sizeof(p
.u
)) {
4191 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
4192 peer
->host
, p
.prefixlen
, sizeof(p
.u
));
4196 /* Fetch prefix from NLRI packet. */
4197 memcpy(&p
.u
.prefix
, pnt
, psize
);
4199 /* Check address. */
4200 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
4201 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
4202 /* From RFC4271 Section 6.3:
4204 * If a prefix in the NLRI field is semantically
4206 * (e.g., an unexpected multicast IP address),
4208 * be logged locally, and the prefix SHOULD be
4212 "%s: IPv4 unicast NLRI is multicast address %s, ignoring",
4213 peer
->host
, inet_ntoa(p
.u
.prefix4
));
4218 /* Check address. */
4219 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
4220 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4224 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
4226 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4231 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
4235 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
4237 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4244 /* Normal process. */
4246 ret
= bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
4247 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
4248 NULL
, NULL
, 0, 0, NULL
);
4250 ret
= bgp_withdraw(peer
, &p
, addpath_id
, attr
, afi
,
4251 safi
, ZEBRA_ROUTE_BGP
,
4252 BGP_ROUTE_NORMAL
, NULL
, NULL
, 0,
4255 /* Address family configuration mismatch or maximum-prefix count
4261 /* Packet length consistency check. */
4264 "%s [Error] Update packet error (prefix length mismatch with total length)",
4272 static struct bgp_static
*bgp_static_new(void)
4274 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
4277 static void bgp_static_free(struct bgp_static
*bgp_static
)
4279 if (bgp_static
->rmap
.name
)
4280 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
4281 if (bgp_static
->eth_s_id
)
4282 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
4283 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
4286 void bgp_static_update(struct bgp
*bgp
, struct prefix
*p
,
4287 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
4289 struct bgp_node
*rn
;
4290 struct bgp_info
*ri
;
4291 struct bgp_info
*new;
4292 struct bgp_info info
;
4294 struct attr
*attr_new
;
4297 int vnc_implicit_withdraw
= 0;
4304 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4306 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4308 attr
.nexthop
= bgp_static
->igpnexthop
;
4309 attr
.med
= bgp_static
->igpmetric
;
4310 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4312 if (bgp_static
->atomic
)
4313 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
4315 /* Store label index, if required. */
4316 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
4317 attr
.label_index
= bgp_static
->label_index
;
4318 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
4321 /* Apply route-map. */
4322 if (bgp_static
->rmap
.name
) {
4323 struct attr attr_tmp
= attr
;
4324 info
.peer
= bgp
->peer_self
;
4325 info
.attr
= &attr_tmp
;
4327 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4329 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
, &info
);
4331 bgp
->peer_self
->rmap_type
= 0;
4333 if (ret
== RMAP_DENYMATCH
) {
4334 /* Free uninterned attribute. */
4335 bgp_attr_flush(&attr_tmp
);
4337 /* Unintern original. */
4338 aspath_unintern(&attr
.aspath
);
4339 bgp_static_withdraw(bgp
, p
, afi
, safi
);
4343 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4344 bgp_attr_add_gshut_community(&attr_tmp
);
4346 attr_new
= bgp_attr_intern(&attr_tmp
);
4349 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4350 bgp_attr_add_gshut_community(&attr
);
4352 attr_new
= bgp_attr_intern(&attr
);
4355 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4356 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4357 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4361 if (attrhash_cmp(ri
->attr
, attr_new
)
4362 && !CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)
4363 && !bgp_flag_check(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
4364 bgp_unlock_node(rn
);
4365 bgp_attr_unintern(&attr_new
);
4366 aspath_unintern(&attr
.aspath
);
4369 /* The attribute is changed. */
4370 bgp_info_set_flag(rn
, ri
, BGP_INFO_ATTR_CHANGED
);
4372 /* Rewrite BGP route information. */
4373 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
))
4374 bgp_info_restore(rn
, ri
);
4376 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4378 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4379 && (safi
== SAFI_UNICAST
)) {
4380 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
4382 * Implicit withdraw case.
4383 * We have to do this before ri is
4386 ++vnc_implicit_withdraw
;
4387 vnc_import_bgp_del_route(bgp
, p
, ri
);
4388 vnc_import_bgp_exterior_del_route(
4393 bgp_attr_unintern(&ri
->attr
);
4394 ri
->attr
= attr_new
;
4395 ri
->uptime
= bgp_clock();
4397 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4398 && (safi
== SAFI_UNICAST
)) {
4399 if (vnc_implicit_withdraw
) {
4400 vnc_import_bgp_add_route(bgp
, p
, ri
);
4401 vnc_import_bgp_exterior_add_route(
4407 /* Nexthop reachability check. */
4408 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4409 && (safi
== SAFI_UNICAST
4410 || safi
== SAFI_LABELED_UNICAST
)) {
4412 struct bgp
*bgp_nexthop
= bgp
;
4414 if (ri
->extra
&& ri
->extra
->bgp_orig
)
4415 bgp_nexthop
= ri
->extra
->bgp_orig
;
4417 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
,
4419 bgp_info_set_flag(rn
, ri
,
4422 if (BGP_DEBUG(nht
, NHT
)) {
4423 char buf1
[INET6_ADDRSTRLEN
];
4424 inet_ntop(p
->family
,
4428 "%s(%s): Route not in table, not advertising",
4429 __FUNCTION__
, buf1
);
4431 bgp_info_unset_flag(rn
, ri
,
4435 /* Delete the NHT structure if any, if we're
4437 * enabling/disabling import check. We
4438 * deregister the route
4439 * from NHT to avoid overloading NHT and the
4440 * process interaction
4442 bgp_unlink_nexthop(ri
);
4443 bgp_info_set_flag(rn
, ri
, BGP_INFO_VALID
);
4445 /* Process change. */
4446 bgp_aggregate_increment(bgp
, p
, ri
, afi
, safi
);
4447 bgp_process(bgp
, rn
, afi
, safi
);
4449 if (SAFI_UNICAST
== safi
4450 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4452 == BGP_INSTANCE_TYPE_DEFAULT
)) {
4453 vpn_leak_from_vrf_update(bgp_get_default(), bgp
,
4457 bgp_unlock_node(rn
);
4458 aspath_unintern(&attr
.aspath
);
4463 /* Make new BGP info. */
4464 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
4466 /* Nexthop reachability check. */
4467 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4468 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
4469 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, new, NULL
, 0))
4470 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
4472 if (BGP_DEBUG(nht
, NHT
)) {
4473 char buf1
[INET6_ADDRSTRLEN
];
4474 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
4477 "%s(%s): Route not in table, not advertising",
4478 __FUNCTION__
, buf1
);
4480 bgp_info_unset_flag(rn
, new, BGP_INFO_VALID
);
4483 /* Delete the NHT structure if any, if we're toggling between
4484 * enabling/disabling import check. We deregister the route
4485 * from NHT to avoid overloading NHT and the process interaction
4487 bgp_unlink_nexthop(new);
4489 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
4492 /* Aggregate address increment. */
4493 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4495 /* Register new BGP information. */
4496 bgp_info_add(rn
, new);
4498 /* route_node_get lock */
4499 bgp_unlock_node(rn
);
4501 /* Process change. */
4502 bgp_process(bgp
, rn
, afi
, safi
);
4504 if (SAFI_UNICAST
== safi
4505 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4506 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4507 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
4510 /* Unintern original. */
4511 aspath_unintern(&attr
.aspath
);
4514 void bgp_static_withdraw(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
4517 struct bgp_node
*rn
;
4518 struct bgp_info
*ri
;
4520 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4522 /* Check selected route and self inserted route. */
4523 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4524 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4525 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4528 /* Withdraw static BGP route from routing table. */
4530 if (SAFI_UNICAST
== safi
4531 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4532 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4533 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, ri
);
4535 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4536 bgp_unlink_nexthop(ri
);
4537 bgp_info_delete(rn
, ri
);
4538 bgp_process(bgp
, rn
, afi
, safi
);
4541 /* Unlock bgp_node_lookup. */
4542 bgp_unlock_node(rn
);
4546 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
4548 static void bgp_static_withdraw_safi(struct bgp
*bgp
, struct prefix
*p
,
4549 afi_t afi
, safi_t safi
,
4550 struct prefix_rd
*prd
)
4552 struct bgp_node
*rn
;
4553 struct bgp_info
*ri
;
4555 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4557 /* Check selected route and self inserted route. */
4558 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4559 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4560 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4563 /* Withdraw static BGP route from routing table. */
4566 rfapiProcessWithdraw(
4567 ri
->peer
, NULL
, p
, prd
, ri
->attr
, afi
, safi
, ri
->type
,
4568 1); /* Kill, since it is an administrative change */
4570 if (SAFI_MPLS_VPN
== safi
4571 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4572 vpn_leak_to_vrf_withdraw(bgp
, ri
);
4574 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4575 bgp_info_delete(rn
, ri
);
4576 bgp_process(bgp
, rn
, afi
, safi
);
4579 /* Unlock bgp_node_lookup. */
4580 bgp_unlock_node(rn
);
4583 static void bgp_static_update_safi(struct bgp
*bgp
, struct prefix
*p
,
4584 struct bgp_static
*bgp_static
, afi_t afi
,
4587 struct bgp_node
*rn
;
4588 struct bgp_info
*new;
4589 struct attr
*attr_new
;
4590 struct attr attr
= {0};
4591 struct bgp_info
*ri
;
4593 mpls_label_t label
= 0;
4595 uint32_t num_labels
= 0;
4600 if (bgp_static
->label
!= MPLS_INVALID_LABEL
)
4602 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
4605 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4607 attr
.nexthop
= bgp_static
->igpnexthop
;
4608 attr
.med
= bgp_static
->igpmetric
;
4609 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4611 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
4612 || (safi
== SAFI_ENCAP
)) {
4613 if (afi
== AFI_IP
) {
4614 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
4615 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
4618 if (afi
== AFI_L2VPN
) {
4619 if (bgp_static
->gatewayIp
.family
== AF_INET
)
4621 bgp_static
->gatewayIp
.u
.prefix4
.s_addr
;
4622 else if (bgp_static
->gatewayIp
.family
== AF_INET6
)
4623 memcpy(&(add
.ipv6
), &(bgp_static
->gatewayIp
.u
.prefix6
),
4624 sizeof(struct in6_addr
));
4625 overlay_index_update(&attr
, bgp_static
->eth_s_id
, &add
);
4626 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
4627 struct bgp_encap_type_vxlan bet
;
4628 memset(&bet
, 0, sizeof(struct bgp_encap_type_vxlan
));
4629 bet
.vnid
= p
->u
.prefix_evpn
.eth_tag
;
4630 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
4632 if (bgp_static
->router_mac
) {
4633 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
4636 /* Apply route-map. */
4637 if (bgp_static
->rmap
.name
) {
4638 struct attr attr_tmp
= attr
;
4639 struct bgp_info info
;
4642 info
.peer
= bgp
->peer_self
;
4643 info
.attr
= &attr_tmp
;
4645 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4647 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
, &info
);
4649 bgp
->peer_self
->rmap_type
= 0;
4651 if (ret
== RMAP_DENYMATCH
) {
4652 /* Free uninterned attribute. */
4653 bgp_attr_flush(&attr_tmp
);
4655 /* Unintern original. */
4656 aspath_unintern(&attr
.aspath
);
4657 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
4662 attr_new
= bgp_attr_intern(&attr_tmp
);
4664 attr_new
= bgp_attr_intern(&attr
);
4667 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4668 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4669 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4674 memset(&add
, 0, sizeof(union gw_addr
));
4675 if (attrhash_cmp(ri
->attr
, attr_new
)
4676 && overlay_index_equal(afi
, ri
, bgp_static
->eth_s_id
, &add
)
4677 && !CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)) {
4678 bgp_unlock_node(rn
);
4679 bgp_attr_unintern(&attr_new
);
4680 aspath_unintern(&attr
.aspath
);
4683 /* The attribute is changed. */
4684 bgp_info_set_flag(rn
, ri
, BGP_INFO_ATTR_CHANGED
);
4686 /* Rewrite BGP route information. */
4687 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
))
4688 bgp_info_restore(rn
, ri
);
4690 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4691 bgp_attr_unintern(&ri
->attr
);
4692 ri
->attr
= attr_new
;
4693 ri
->uptime
= bgp_clock();
4696 label
= decode_label(&ri
->extra
->label
[0]);
4699 /* Process change. */
4700 bgp_aggregate_increment(bgp
, p
, ri
, afi
, safi
);
4701 bgp_process(bgp
, rn
, afi
, safi
);
4703 if (SAFI_MPLS_VPN
== safi
4704 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4705 vpn_leak_to_vrf_update(bgp
, ri
);
4708 rfapiProcessUpdate(ri
->peer
, NULL
, p
, &bgp_static
->prd
,
4709 ri
->attr
, afi
, safi
, ri
->type
,
4710 ri
->sub_type
, &label
);
4712 bgp_unlock_node(rn
);
4713 aspath_unintern(&attr
.aspath
);
4719 /* Make new BGP info. */
4720 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
4722 SET_FLAG(new->flags
, BGP_INFO_VALID
);
4723 new->extra
= bgp_info_extra_new();
4725 new->extra
->label
[0] = bgp_static
->label
;
4726 new->extra
->num_labels
= num_labels
;
4729 label
= decode_label(&bgp_static
->label
);
4732 /* Aggregate address increment. */
4733 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4735 /* Register new BGP information. */
4736 bgp_info_add(rn
, new);
4737 /* route_node_get lock */
4738 bgp_unlock_node(rn
);
4740 /* Process change. */
4741 bgp_process(bgp
, rn
, afi
, safi
);
4743 if (SAFI_MPLS_VPN
== safi
4744 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4745 vpn_leak_to_vrf_update(bgp
, new);
4748 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
4749 safi
, new->type
, new->sub_type
, &label
);
4752 /* Unintern original. */
4753 aspath_unintern(&attr
.aspath
);
4756 /* Configure static BGP network. When user don't run zebra, static
4757 route should be installed as valid. */
4758 static int bgp_static_set(struct vty
*vty
, const char *negate
,
4759 const char *ip_str
, afi_t afi
, safi_t safi
,
4760 const char *rmap
, int backdoor
, uint32_t label_index
)
4762 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
4765 struct bgp_static
*bgp_static
;
4766 struct bgp_node
*rn
;
4767 uint8_t need_update
= 0;
4769 /* Convert IP prefix string to struct prefix. */
4770 ret
= str2prefix(ip_str
, &p
);
4772 vty_out(vty
, "%% Malformed prefix\n");
4773 return CMD_WARNING_CONFIG_FAILED
;
4775 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4776 vty_out(vty
, "%% Malformed prefix (link-local address)\n");
4777 return CMD_WARNING_CONFIG_FAILED
;
4784 /* Set BGP static route configuration. */
4785 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
4788 vty_out(vty
, "%% Can't find static route specified\n");
4789 return CMD_WARNING_CONFIG_FAILED
;
4792 bgp_static
= rn
->info
;
4794 if ((label_index
!= BGP_INVALID_LABEL_INDEX
)
4795 && (label_index
!= bgp_static
->label_index
)) {
4797 "%% label-index doesn't match static route\n");
4798 return CMD_WARNING_CONFIG_FAILED
;
4801 if ((rmap
&& bgp_static
->rmap
.name
)
4802 && strcmp(rmap
, bgp_static
->rmap
.name
)) {
4804 "%% route-map name doesn't match static route\n");
4805 return CMD_WARNING_CONFIG_FAILED
;
4808 /* Update BGP RIB. */
4809 if (!bgp_static
->backdoor
)
4810 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
4812 /* Clear configuration. */
4813 bgp_static_free(bgp_static
);
4815 bgp_unlock_node(rn
);
4816 bgp_unlock_node(rn
);
4819 /* Set BGP static route configuration. */
4820 rn
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
4823 /* Configuration change. */
4824 bgp_static
= rn
->info
;
4826 /* Label index cannot be changed. */
4827 if (bgp_static
->label_index
!= label_index
) {
4828 vty_out(vty
, "%% cannot change label-index\n");
4829 return CMD_WARNING_CONFIG_FAILED
;
4832 /* Check previous routes are installed into BGP. */
4833 if (bgp_static
->valid
4834 && bgp_static
->backdoor
!= backdoor
)
4837 bgp_static
->backdoor
= backdoor
;
4840 if (bgp_static
->rmap
.name
)
4841 XFREE(MTYPE_ROUTE_MAP_NAME
,
4842 bgp_static
->rmap
.name
);
4843 bgp_static
->rmap
.name
=
4844 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
4845 bgp_static
->rmap
.map
=
4846 route_map_lookup_by_name(rmap
);
4848 if (bgp_static
->rmap
.name
)
4849 XFREE(MTYPE_ROUTE_MAP_NAME
,
4850 bgp_static
->rmap
.name
);
4851 bgp_static
->rmap
.name
= NULL
;
4852 bgp_static
->rmap
.map
= NULL
;
4853 bgp_static
->valid
= 0;
4855 bgp_unlock_node(rn
);
4857 /* New configuration. */
4858 bgp_static
= bgp_static_new();
4859 bgp_static
->backdoor
= backdoor
;
4860 bgp_static
->valid
= 0;
4861 bgp_static
->igpmetric
= 0;
4862 bgp_static
->igpnexthop
.s_addr
= 0;
4863 bgp_static
->label_index
= label_index
;
4866 if (bgp_static
->rmap
.name
)
4867 XFREE(MTYPE_ROUTE_MAP_NAME
,
4868 bgp_static
->rmap
.name
);
4869 bgp_static
->rmap
.name
=
4870 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
4871 bgp_static
->rmap
.map
=
4872 route_map_lookup_by_name(rmap
);
4874 rn
->info
= bgp_static
;
4877 bgp_static
->valid
= 1;
4879 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
4881 if (!bgp_static
->backdoor
)
4882 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
4888 void bgp_static_add(struct bgp
*bgp
)
4892 struct bgp_node
*rn
;
4893 struct bgp_node
*rm
;
4894 struct bgp_table
*table
;
4895 struct bgp_static
*bgp_static
;
4897 FOREACH_AFI_SAFI (afi
, safi
)
4898 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
4899 rn
= bgp_route_next(rn
)) {
4900 if (rn
->info
== NULL
)
4903 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
4904 || (safi
== SAFI_EVPN
)) {
4907 for (rm
= bgp_table_top(table
); rm
;
4908 rm
= bgp_route_next(rm
)) {
4909 bgp_static
= rm
->info
;
4910 bgp_static_update_safi(bgp
, &rm
->p
,
4915 bgp_static_update(bgp
, &rn
->p
, rn
->info
, afi
,
4921 /* Called from bgp_delete(). Delete all static routes from the BGP
4923 void bgp_static_delete(struct bgp
*bgp
)
4927 struct bgp_node
*rn
;
4928 struct bgp_node
*rm
;
4929 struct bgp_table
*table
;
4930 struct bgp_static
*bgp_static
;
4932 FOREACH_AFI_SAFI (afi
, safi
)
4933 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
4934 rn
= bgp_route_next(rn
)) {
4935 if (rn
->info
== NULL
)
4938 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
4939 || (safi
== SAFI_EVPN
)) {
4942 for (rm
= bgp_table_top(table
); rm
;
4943 rm
= bgp_route_next(rm
)) {
4944 bgp_static
= rm
->info
;
4945 bgp_static_withdraw_safi(
4946 bgp
, &rm
->p
, AFI_IP
, safi
,
4947 (struct prefix_rd
*)&rn
->p
);
4948 bgp_static_free(bgp_static
);
4950 bgp_unlock_node(rn
);
4953 bgp_static
= rn
->info
;
4954 bgp_static_withdraw(bgp
, &rn
->p
, afi
, safi
);
4955 bgp_static_free(bgp_static
);
4957 bgp_unlock_node(rn
);
4962 void bgp_static_redo_import_check(struct bgp
*bgp
)
4966 struct bgp_node
*rn
;
4967 struct bgp_node
*rm
;
4968 struct bgp_table
*table
;
4969 struct bgp_static
*bgp_static
;
4971 /* Use this flag to force reprocessing of the route */
4972 bgp_flag_set(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
4973 FOREACH_AFI_SAFI (afi
, safi
) {
4974 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
4975 rn
= bgp_route_next(rn
)) {
4976 if (rn
->info
== NULL
)
4979 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
4980 || (safi
== SAFI_EVPN
)) {
4983 for (rm
= bgp_table_top(table
); rm
;
4984 rm
= bgp_route_next(rm
)) {
4985 bgp_static
= rm
->info
;
4986 bgp_static_update_safi(bgp
, &rm
->p
,
4991 bgp_static
= rn
->info
;
4992 bgp_static_update(bgp
, &rn
->p
, bgp_static
, afi
,
4997 bgp_flag_unset(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5000 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
5003 struct bgp_table
*table
;
5004 struct bgp_node
*rn
;
5005 struct bgp_info
*ri
;
5007 table
= bgp
->rib
[afi
][safi
];
5008 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
5009 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
5010 if (ri
->peer
== bgp
->peer_self
5011 && ((ri
->type
== ZEBRA_ROUTE_BGP
5012 && ri
->sub_type
== BGP_ROUTE_STATIC
)
5013 || (ri
->type
!= ZEBRA_ROUTE_BGP
5015 == BGP_ROUTE_REDISTRIBUTE
))) {
5016 bgp_aggregate_decrement(bgp
, &rn
->p
, ri
, afi
,
5018 bgp_unlink_nexthop(ri
);
5019 bgp_info_delete(rn
, ri
);
5020 bgp_process(bgp
, rn
, afi
, safi
);
5027 * Purge all networks and redistributed routes from routing table.
5028 * Invoked upon the instance going down.
5030 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
5035 FOREACH_AFI_SAFI (afi
, safi
)
5036 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
5041 * Currently this is used to set static routes for VPN and ENCAP.
5042 * I think it can probably be factored with bgp_static_set.
5044 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5045 const char *ip_str
, const char *rd_str
,
5046 const char *label_str
, const char *rmap_str
,
5047 int evpn_type
, const char *esi
, const char *gwip
,
5048 const char *ethtag
, const char *routermac
)
5050 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5053 struct prefix_rd prd
;
5054 struct bgp_node
*prn
;
5055 struct bgp_node
*rn
;
5056 struct bgp_table
*table
;
5057 struct bgp_static
*bgp_static
;
5058 mpls_label_t label
= MPLS_INVALID_LABEL
;
5059 struct prefix gw_ip
;
5061 /* validate ip prefix */
5062 ret
= str2prefix(ip_str
, &p
);
5064 vty_out(vty
, "%% Malformed prefix\n");
5065 return CMD_WARNING_CONFIG_FAILED
;
5068 if ((afi
== AFI_L2VPN
)
5069 && (bgp_build_evpn_prefix(evpn_type
,
5070 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5071 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5072 return CMD_WARNING_CONFIG_FAILED
;
5075 ret
= str2prefix_rd(rd_str
, &prd
);
5077 vty_out(vty
, "%% Malformed rd\n");
5078 return CMD_WARNING_CONFIG_FAILED
;
5082 unsigned long label_val
;
5083 label_val
= strtoul(label_str
, NULL
, 10);
5084 encode_label(label_val
, &label
);
5087 if (safi
== SAFI_EVPN
) {
5088 if (esi
&& str2esi(esi
, NULL
) == 0) {
5089 vty_out(vty
, "%% Malformed ESI\n");
5090 return CMD_WARNING_CONFIG_FAILED
;
5092 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
5093 vty_out(vty
, "%% Malformed Router MAC\n");
5094 return CMD_WARNING_CONFIG_FAILED
;
5097 memset(&gw_ip
, 0, sizeof(struct prefix
));
5098 ret
= str2prefix(gwip
, &gw_ip
);
5100 vty_out(vty
, "%% Malformed GatewayIp\n");
5101 return CMD_WARNING_CONFIG_FAILED
;
5103 if ((gw_ip
.family
== AF_INET
5104 && IS_EVPN_PREFIX_IPADDR_V6(
5105 (struct prefix_evpn
*)&p
))
5106 || (gw_ip
.family
== AF_INET6
5107 && IS_EVPN_PREFIX_IPADDR_V4(
5108 (struct prefix_evpn
*)&p
))) {
5110 "%% GatewayIp family differs with IP prefix\n");
5111 return CMD_WARNING_CONFIG_FAILED
;
5115 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5116 if (prn
->info
== NULL
)
5117 prn
->info
= bgp_table_init(bgp
, afi
, safi
);
5119 bgp_unlock_node(prn
);
5122 rn
= bgp_node_get(table
, &p
);
5125 vty_out(vty
, "%% Same network configuration exists\n");
5126 bgp_unlock_node(rn
);
5128 /* New configuration. */
5129 bgp_static
= bgp_static_new();
5130 bgp_static
->backdoor
= 0;
5131 bgp_static
->valid
= 0;
5132 bgp_static
->igpmetric
= 0;
5133 bgp_static
->igpnexthop
.s_addr
= 0;
5134 bgp_static
->label
= label
;
5135 bgp_static
->prd
= prd
;
5138 if (bgp_static
->rmap
.name
)
5139 XFREE(MTYPE_ROUTE_MAP_NAME
,
5140 bgp_static
->rmap
.name
);
5141 bgp_static
->rmap
.name
=
5142 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
5143 bgp_static
->rmap
.map
=
5144 route_map_lookup_by_name(rmap_str
);
5147 if (safi
== SAFI_EVPN
) {
5149 bgp_static
->eth_s_id
=
5151 sizeof(struct eth_segment_id
));
5152 str2esi(esi
, bgp_static
->eth_s_id
);
5155 bgp_static
->router_mac
=
5156 XCALLOC(MTYPE_ATTR
, ETH_ALEN
+ 1);
5157 prefix_str2mac(routermac
,
5158 bgp_static
->router_mac
);
5161 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
5163 rn
->info
= bgp_static
;
5165 bgp_static
->valid
= 1;
5166 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
5172 /* Configure static BGP network. */
5173 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5174 const char *ip_str
, const char *rd_str
,
5175 const char *label_str
, int evpn_type
, const char *esi
,
5176 const char *gwip
, const char *ethtag
)
5178 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5181 struct prefix_rd prd
;
5182 struct bgp_node
*prn
;
5183 struct bgp_node
*rn
;
5184 struct bgp_table
*table
;
5185 struct bgp_static
*bgp_static
;
5186 mpls_label_t label
= MPLS_INVALID_LABEL
;
5188 /* Convert IP prefix string to struct prefix. */
5189 ret
= str2prefix(ip_str
, &p
);
5191 vty_out(vty
, "%% Malformed prefix\n");
5192 return CMD_WARNING_CONFIG_FAILED
;
5195 if ((afi
== AFI_L2VPN
)
5196 && (bgp_build_evpn_prefix(evpn_type
,
5197 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5198 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5199 return CMD_WARNING_CONFIG_FAILED
;
5201 ret
= str2prefix_rd(rd_str
, &prd
);
5203 vty_out(vty
, "%% Malformed rd\n");
5204 return CMD_WARNING_CONFIG_FAILED
;
5208 unsigned long label_val
;
5209 label_val
= strtoul(label_str
, NULL
, 10);
5210 encode_label(label_val
, &label
);
5213 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5214 if (prn
->info
== NULL
)
5215 prn
->info
= bgp_table_init(bgp
, afi
, safi
);
5217 bgp_unlock_node(prn
);
5220 rn
= bgp_node_lookup(table
, &p
);
5223 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
5225 bgp_static
= rn
->info
;
5226 bgp_static_free(bgp_static
);
5228 bgp_unlock_node(rn
);
5229 bgp_unlock_node(rn
);
5231 vty_out(vty
, "%% Can't find the route\n");
5236 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
5237 const char *rmap_name
)
5239 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5240 struct bgp_rmap
*rmap
;
5242 rmap
= &bgp
->table_map
[afi
][safi
];
5245 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5246 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
5247 rmap
->map
= route_map_lookup_by_name(rmap_name
);
5250 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5255 if (bgp_fibupd_safi(safi
))
5256 bgp_zebra_announce_table(bgp
, afi
, safi
);
5261 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
5262 const char *rmap_name
)
5264 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5265 struct bgp_rmap
*rmap
;
5267 rmap
= &bgp
->table_map
[afi
][safi
];
5269 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5273 if (bgp_fibupd_safi(safi
))
5274 bgp_zebra_announce_table(bgp
, afi
, safi
);
5279 void bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
5282 if (bgp
->table_map
[afi
][safi
].name
) {
5283 vty_out(vty
, " table-map %s\n",
5284 bgp
->table_map
[afi
][safi
].name
);
5288 DEFUN (bgp_table_map
,
5291 "BGP table to RIB route download filter\n"
5292 "Name of the route map\n")
5295 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5296 argv
[idx_word
]->arg
);
5298 DEFUN (no_bgp_table_map
,
5299 no_bgp_table_map_cmd
,
5300 "no table-map WORD",
5302 "BGP table to RIB route download filter\n"
5303 "Name of the route map\n")
5306 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5307 argv
[idx_word
]->arg
);
5313 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
5314 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
5315 backdoor$backdoor}]",
5317 "Specify a network to announce via BGP\n"
5322 "Route-map to modify the attributes\n"
5323 "Name of the route map\n"
5324 "Label index to associate with the prefix\n"
5325 "Label index value\n"
5326 "Specify a BGP backdoor route\n")
5328 char addr_prefix_str
[BUFSIZ
];
5333 ret
= netmask_str2prefix_str(address_str
, netmask_str
,
5336 vty_out(vty
, "%% Inconsistent address and mask\n");
5337 return CMD_WARNING_CONFIG_FAILED
;
5341 return bgp_static_set(
5342 vty
, no
, address_str
? addr_prefix_str
: prefix_str
, AFI_IP
,
5343 bgp_node_safi(vty
), map_name
, backdoor
? 1 : 0,
5344 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5347 DEFPY(ipv6_bgp_network
,
5348 ipv6_bgp_network_cmd
,
5349 "[no] network X:X::X:X/M$prefix \
5350 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
5352 "Specify a network to announce via BGP\n"
5354 "Route-map to modify the attributes\n"
5355 "Name of the route map\n"
5356 "Label index to associate with the prefix\n"
5357 "Label index value\n")
5359 return bgp_static_set(
5360 vty
, no
, prefix_str
, AFI_IP6
, bgp_node_safi(vty
), map_name
, 0,
5361 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5364 /* Aggreagete address:
5366 advertise-map Set condition to advertise attribute
5367 as-set Generate AS set path information
5368 attribute-map Set attributes of aggregate
5369 route-map Set parameters of aggregate
5370 summary-only Filter more specific routes from updates
5371 suppress-map Conditionally filter more specific routes from updates
5374 struct bgp_aggregate
{
5375 /* Summary-only flag. */
5376 uint8_t summary_only
;
5378 /* AS set generation. */
5381 /* Route-map for aggregated route. */
5382 struct route_map
*map
;
5384 /* Suppress-count. */
5385 unsigned long count
;
5387 /* SAFI configuration. */
5391 static struct bgp_aggregate
*bgp_aggregate_new(void)
5393 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
5396 static void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
5398 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
5401 /* Update an aggregate as routes are added/removed from the BGP table */
5402 static void bgp_aggregate_route(struct bgp
*bgp
, struct prefix
*p
,
5403 struct bgp_info
*rinew
, afi_t afi
, safi_t safi
,
5404 struct bgp_info
*del
,
5405 struct bgp_aggregate
*aggregate
)
5407 struct bgp_table
*table
;
5408 struct bgp_node
*top
;
5409 struct bgp_node
*rn
;
5411 struct aspath
*aspath
= NULL
;
5412 struct aspath
*asmerge
= NULL
;
5413 struct community
*community
= NULL
;
5414 struct community
*commerge
= NULL
;
5415 #if defined(AGGREGATE_NEXTHOP_CHECK)
5416 struct in_addr nexthop
;
5419 struct bgp_info
*ri
;
5420 struct bgp_info
*new;
5422 unsigned long match
= 0;
5423 uint8_t atomic_aggregate
= 0;
5425 /* Record adding route's nexthop and med. */
5427 #if defined(AGGREGATE_NEXTHOP_CHECK)
5428 nexthop
= rinew
->attr
->nexthop
;
5429 med
= rinew
->attr
->med
;
5433 /* ORIGIN attribute: If at least one route among routes that are
5434 aggregated has ORIGIN with the value INCOMPLETE, then the
5435 aggregated route must have the ORIGIN attribute with the value
5436 INCOMPLETE. Otherwise, if at least one route among routes that
5437 are aggregated has ORIGIN with the value EGP, then the aggregated
5438 route must have the origin attribute with the value EGP. In all
5439 other case the value of the ORIGIN attribute of the aggregated
5440 route is INTERNAL. */
5441 origin
= BGP_ORIGIN_IGP
;
5443 table
= bgp
->rib
[afi
][safi
];
5445 top
= bgp_node_get(table
, p
);
5446 for (rn
= bgp_node_get(table
, p
); rn
;
5447 rn
= bgp_route_next_until(rn
, top
))
5448 if (rn
->p
.prefixlen
> p
->prefixlen
) {
5451 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
5452 if (BGP_INFO_HOLDDOWN(ri
))
5455 if (del
&& ri
== del
)
5458 if (!rinew
&& first
) {
5459 #if defined(AGGREGATE_NEXTHOP_CHECK)
5460 nexthop
= ri
->attr
->nexthop
;
5461 med
= ri
->attr
->med
;
5466 #ifdef AGGREGATE_NEXTHOP_CHECK
5467 if (!IPV4_ADDR_SAME(&ri
->attr
->nexthop
,
5469 || ri
->attr
->med
!= med
) {
5471 aspath_free(aspath
);
5473 community_free(community
);
5474 bgp_unlock_node(rn
);
5475 bgp_unlock_node(top
);
5478 #endif /* AGGREGATE_NEXTHOP_CHECK */
5481 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
5482 atomic_aggregate
= 1;
5484 if (ri
->sub_type
!= BGP_ROUTE_AGGREGATE
) {
5485 if (aggregate
->summary_only
) {
5486 (bgp_info_extra_get(ri
))
5490 BGP_INFO_ATTR_CHANGED
);
5496 if (origin
< ri
->attr
->origin
)
5497 origin
= ri
->attr
->origin
;
5499 if (aggregate
->as_set
) {
5501 asmerge
= aspath_aggregate(
5504 aspath_free(aspath
);
5507 aspath
= aspath_dup(
5510 if (ri
->attr
->community
) {
5512 commerge
= community_merge(
5514 ri
->attr
->community
);
5515 community
= community_uniq_sort(
5520 community
= community_dup(
5521 ri
->attr
->community
);
5527 bgp_process(bgp
, rn
, afi
, safi
);
5529 bgp_unlock_node(top
);
5534 if (aggregate
->summary_only
)
5535 (bgp_info_extra_get(rinew
))->suppress
++;
5537 if (origin
< rinew
->attr
->origin
)
5538 origin
= rinew
->attr
->origin
;
5540 if (aggregate
->as_set
) {
5542 asmerge
= aspath_aggregate(aspath
,
5543 rinew
->attr
->aspath
);
5544 aspath_free(aspath
);
5547 aspath
= aspath_dup(rinew
->attr
->aspath
);
5549 if (rinew
->attr
->community
) {
5551 commerge
= community_merge(
5553 rinew
->attr
->community
);
5555 community_uniq_sort(commerge
);
5556 community_free(commerge
);
5558 community
= community_dup(
5559 rinew
->attr
->community
);
5564 if (aggregate
->count
> 0) {
5565 rn
= bgp_node_get(table
, p
);
5567 ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0, bgp
->peer_self
,
5568 bgp_attr_aggregate_intern(bgp
, origin
, aspath
,
5569 community
, aggregate
->as_set
,
5572 SET_FLAG(new->flags
, BGP_INFO_VALID
);
5574 bgp_info_add(rn
, new);
5575 bgp_unlock_node(rn
);
5576 bgp_process(bgp
, rn
, afi
, safi
);
5579 aspath_free(aspath
);
5581 community_free(community
);
5585 void bgp_aggregate_delete(struct bgp
*, struct prefix
*, afi_t
, safi_t
,
5586 struct bgp_aggregate
*);
5588 void bgp_aggregate_increment(struct bgp
*bgp
, struct prefix
*p
,
5589 struct bgp_info
*ri
, afi_t afi
, safi_t safi
)
5591 struct bgp_node
*child
;
5592 struct bgp_node
*rn
;
5593 struct bgp_aggregate
*aggregate
;
5594 struct bgp_table
*table
;
5596 /* MPLS-VPN aggregation is not yet supported. */
5597 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5598 || (safi
== SAFI_EVPN
)
5599 || (safi
== SAFI_FLOWSPEC
))
5602 table
= bgp
->aggregate
[afi
][safi
];
5604 /* No aggregates configured. */
5605 if (bgp_table_top_nolock(table
) == NULL
)
5608 if (p
->prefixlen
== 0)
5611 if (BGP_INFO_HOLDDOWN(ri
))
5614 child
= bgp_node_get(table
, p
);
5616 /* Aggregate address configuration check. */
5617 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
))
5618 if ((aggregate
= rn
->info
) != NULL
5619 && rn
->p
.prefixlen
< p
->prefixlen
) {
5620 bgp_aggregate_delete(bgp
, &rn
->p
, afi
, safi
, aggregate
);
5621 bgp_aggregate_route(bgp
, &rn
->p
, ri
, afi
, safi
, NULL
,
5624 bgp_unlock_node(child
);
5627 void bgp_aggregate_decrement(struct bgp
*bgp
, struct prefix
*p
,
5628 struct bgp_info
*del
, afi_t afi
, safi_t safi
)
5630 struct bgp_node
*child
;
5631 struct bgp_node
*rn
;
5632 struct bgp_aggregate
*aggregate
;
5633 struct bgp_table
*table
;
5635 /* MPLS-VPN aggregation is not yet supported. */
5636 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5637 || (safi
== SAFI_EVPN
)
5638 || (safi
== SAFI_FLOWSPEC
))
5641 table
= bgp
->aggregate
[afi
][safi
];
5643 /* No aggregates configured. */
5644 if (bgp_table_top_nolock(table
) == NULL
)
5647 if (p
->prefixlen
== 0)
5650 child
= bgp_node_get(table
, p
);
5652 /* Aggregate address configuration check. */
5653 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
))
5654 if ((aggregate
= rn
->info
) != NULL
5655 && rn
->p
.prefixlen
< p
->prefixlen
) {
5656 bgp_aggregate_delete(bgp
, &rn
->p
, afi
, safi
, aggregate
);
5657 bgp_aggregate_route(bgp
, &rn
->p
, NULL
, afi
, safi
, del
,
5660 bgp_unlock_node(child
);
5663 /* Called via bgp_aggregate_set when the user configures aggregate-address */
5664 static void bgp_aggregate_add(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
5665 safi_t safi
, struct bgp_aggregate
*aggregate
)
5667 struct bgp_table
*table
;
5668 struct bgp_node
*top
;
5669 struct bgp_node
*rn
;
5670 struct bgp_info
*new;
5671 struct bgp_info
*ri
;
5672 unsigned long match
;
5673 uint8_t origin
= BGP_ORIGIN_IGP
;
5674 struct aspath
*aspath
= NULL
;
5675 struct aspath
*asmerge
= NULL
;
5676 struct community
*community
= NULL
;
5677 struct community
*commerge
= NULL
;
5678 uint8_t atomic_aggregate
= 0;
5680 table
= bgp
->rib
[afi
][safi
];
5683 if (afi
== AFI_IP
&& p
->prefixlen
== IPV4_MAX_BITLEN
)
5685 if (afi
== AFI_IP6
&& p
->prefixlen
== IPV6_MAX_BITLEN
)
5688 /* If routes exists below this node, generate aggregate routes. */
5689 top
= bgp_node_get(table
, p
);
5690 for (rn
= bgp_node_get(table
, p
); rn
;
5691 rn
= bgp_route_next_until(rn
, top
)) {
5692 if (rn
->p
.prefixlen
<= p
->prefixlen
)
5697 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
5698 if (BGP_INFO_HOLDDOWN(ri
))
5702 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
5703 atomic_aggregate
= 1;
5705 if (ri
->sub_type
== BGP_ROUTE_AGGREGATE
)
5708 /* summary-only aggregate route suppress
5709 * aggregated route announcement. */
5710 if (aggregate
->summary_only
) {
5711 (bgp_info_extra_get(ri
))->suppress
++;
5712 bgp_info_set_flag(rn
, ri
,
5713 BGP_INFO_ATTR_CHANGED
);
5717 /* If at least one route among routes that are
5718 * aggregated has ORIGIN with the value INCOMPLETE,
5719 * then the aggregated route MUST have the ORIGIN
5720 * attribute with the value INCOMPLETE. Otherwise, if
5721 * at least one route among routes that are aggregated
5722 * has ORIGIN with the value EGP, then the aggregated
5723 * route MUST have the ORIGIN attribute with the value
5726 if (origin
< ri
->attr
->origin
)
5727 origin
= ri
->attr
->origin
;
5729 /* as-set aggregate route generate origin, as path,
5730 * community aggregation. */
5731 if (aggregate
->as_set
) {
5733 asmerge
= aspath_aggregate(
5734 aspath
, ri
->attr
->aspath
);
5735 aspath_free(aspath
);
5738 aspath
= aspath_dup(ri
->attr
->aspath
);
5740 if (ri
->attr
->community
) {
5742 commerge
= community_merge(
5744 ri
->attr
->community
);
5745 community
= community_uniq_sort(
5747 community_free(commerge
);
5749 community
= community_dup(
5750 ri
->attr
->community
);
5756 /* If this node is suppressed, process the change. */
5758 bgp_process(bgp
, rn
, afi
, safi
);
5760 bgp_unlock_node(top
);
5762 /* Add aggregate route to BGP table. */
5763 if (aggregate
->count
) {
5764 rn
= bgp_node_get(table
, p
);
5766 ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0, bgp
->peer_self
,
5767 bgp_attr_aggregate_intern(bgp
, origin
, aspath
,
5768 community
, aggregate
->as_set
,
5771 SET_FLAG(new->flags
, BGP_INFO_VALID
);
5773 bgp_info_add(rn
, new);
5774 bgp_unlock_node(rn
);
5776 /* Process change. */
5777 bgp_process(bgp
, rn
, afi
, safi
);
5780 aspath_free(aspath
);
5782 community_free(community
);
5786 void bgp_aggregate_delete(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
5787 safi_t safi
, struct bgp_aggregate
*aggregate
)
5789 struct bgp_table
*table
;
5790 struct bgp_node
*top
;
5791 struct bgp_node
*rn
;
5792 struct bgp_info
*ri
;
5793 unsigned long match
;
5795 table
= bgp
->rib
[afi
][safi
];
5797 if (afi
== AFI_IP
&& p
->prefixlen
== IPV4_MAX_BITLEN
)
5799 if (afi
== AFI_IP6
&& p
->prefixlen
== IPV6_MAX_BITLEN
)
5802 /* If routes exists below this node, generate aggregate routes. */
5803 top
= bgp_node_get(table
, p
);
5804 for (rn
= bgp_node_get(table
, p
); rn
;
5805 rn
= bgp_route_next_until(rn
, top
)) {
5806 if (rn
->p
.prefixlen
<= p
->prefixlen
)
5810 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
5811 if (BGP_INFO_HOLDDOWN(ri
))
5814 if (ri
->sub_type
== BGP_ROUTE_AGGREGATE
)
5817 if (aggregate
->summary_only
&& ri
->extra
) {
5818 ri
->extra
->suppress
--;
5820 if (ri
->extra
->suppress
== 0) {
5822 rn
, ri
, BGP_INFO_ATTR_CHANGED
);
5829 /* If this node was suppressed, process the change. */
5831 bgp_process(bgp
, rn
, afi
, safi
);
5833 bgp_unlock_node(top
);
5835 /* Delete aggregate route from BGP table. */
5836 rn
= bgp_node_get(table
, p
);
5838 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
5839 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
5840 && ri
->sub_type
== BGP_ROUTE_AGGREGATE
)
5843 /* Withdraw static BGP route from routing table. */
5845 bgp_info_delete(rn
, ri
);
5846 bgp_process(bgp
, rn
, afi
, safi
);
5849 /* Unlock bgp_node_lookup. */
5850 bgp_unlock_node(rn
);
5853 /* Aggregate route attribute. */
5854 #define AGGREGATE_SUMMARY_ONLY 1
5855 #define AGGREGATE_AS_SET 1
5857 static int bgp_aggregate_unset(struct vty
*vty
, const char *prefix_str
,
5858 afi_t afi
, safi_t safi
)
5860 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5863 struct bgp_node
*rn
;
5864 struct bgp_aggregate
*aggregate
;
5866 if (safi
== SAFI_FLOWSPEC
)
5867 return CMD_WARNING_CONFIG_FAILED
;
5869 /* Convert string to prefix structure. */
5870 ret
= str2prefix(prefix_str
, &p
);
5872 vty_out(vty
, "Malformed prefix\n");
5873 return CMD_WARNING_CONFIG_FAILED
;
5877 /* Old configuration check. */
5878 rn
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], &p
);
5881 "%% There is no aggregate-address configuration.\n");
5882 return CMD_WARNING_CONFIG_FAILED
;
5885 aggregate
= rn
->info
;
5886 if (aggregate
->safi
== SAFI_UNICAST
)
5887 bgp_aggregate_delete(bgp
, &p
, afi
, SAFI_UNICAST
, aggregate
);
5888 if (aggregate
->safi
== SAFI_LABELED_UNICAST
)
5889 bgp_aggregate_delete(bgp
, &p
, afi
, SAFI_LABELED_UNICAST
,
5891 if (aggregate
->safi
== SAFI_MULTICAST
)
5892 bgp_aggregate_delete(bgp
, &p
, afi
, SAFI_MULTICAST
, aggregate
);
5894 /* Unlock aggregate address configuration. */
5896 bgp_aggregate_free(aggregate
);
5897 bgp_unlock_node(rn
);
5898 bgp_unlock_node(rn
);
5903 static int bgp_aggregate_set(struct vty
*vty
, const char *prefix_str
, afi_t afi
,
5904 safi_t safi
, uint8_t summary_only
, uint8_t as_set
)
5906 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5909 struct bgp_node
*rn
;
5910 struct bgp_aggregate
*aggregate
;
5912 if (safi
== SAFI_FLOWSPEC
)
5913 return CMD_WARNING_CONFIG_FAILED
;
5915 /* Convert string to prefix structure. */
5916 ret
= str2prefix(prefix_str
, &p
);
5918 vty_out(vty
, "Malformed prefix\n");
5919 return CMD_WARNING_CONFIG_FAILED
;
5923 /* Old configuration check. */
5924 rn
= bgp_node_get(bgp
->aggregate
[afi
][safi
], &p
);
5927 vty_out(vty
, "There is already same aggregate network.\n");
5928 /* try to remove the old entry */
5929 ret
= bgp_aggregate_unset(vty
, prefix_str
, afi
, safi
);
5931 vty_out(vty
, "Error deleting aggregate.\n");
5932 bgp_unlock_node(rn
);
5933 return CMD_WARNING_CONFIG_FAILED
;
5937 /* Make aggregate address structure. */
5938 aggregate
= bgp_aggregate_new();
5939 aggregate
->summary_only
= summary_only
;
5940 aggregate
->as_set
= as_set
;
5941 aggregate
->safi
= safi
;
5942 rn
->info
= aggregate
;
5944 /* Aggregate address insert into BGP routing table. */
5945 if (safi
== SAFI_UNICAST
)
5946 bgp_aggregate_add(bgp
, &p
, afi
, SAFI_UNICAST
, aggregate
);
5947 if (safi
== SAFI_LABELED_UNICAST
)
5948 bgp_aggregate_add(bgp
, &p
, afi
, SAFI_LABELED_UNICAST
,
5950 if (safi
== SAFI_MULTICAST
)
5951 bgp_aggregate_add(bgp
, &p
, afi
, SAFI_MULTICAST
, aggregate
);
5956 DEFUN (aggregate_address
,
5957 aggregate_address_cmd
,
5958 "aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
5959 "Configure BGP aggregate entries\n"
5960 "Aggregate prefix\n"
5961 "Generate AS set path information\n"
5962 "Filter more specific routes from updates\n"
5963 "Filter more specific routes from updates\n"
5964 "Generate AS set path information\n")
5967 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
5968 char *prefix
= argv
[idx
]->arg
;
5970 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
5972 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
5973 ? AGGREGATE_SUMMARY_ONLY
5976 return bgp_aggregate_set(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
),
5977 summary_only
, as_set
);
5980 DEFUN (aggregate_address_mask
,
5981 aggregate_address_mask_cmd
,
5982 "aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
5983 "Configure BGP aggregate entries\n"
5984 "Aggregate address\n"
5986 "Generate AS set path information\n"
5987 "Filter more specific routes from updates\n"
5988 "Filter more specific routes from updates\n"
5989 "Generate AS set path information\n")
5992 argv_find(argv
, argc
, "A.B.C.D", &idx
);
5993 char *prefix
= argv
[idx
]->arg
;
5994 char *mask
= argv
[idx
+ 1]->arg
;
5996 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
5998 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
5999 ? AGGREGATE_SUMMARY_ONLY
6002 char prefix_str
[BUFSIZ
];
6003 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
6006 vty_out(vty
, "%% Inconsistent address and mask\n");
6007 return CMD_WARNING_CONFIG_FAILED
;
6010 return bgp_aggregate_set(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
),
6011 summary_only
, as_set
);
6014 DEFUN (no_aggregate_address
,
6015 no_aggregate_address_cmd
,
6016 "no aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
6018 "Configure BGP aggregate entries\n"
6019 "Aggregate prefix\n"
6020 "Generate AS set path information\n"
6021 "Filter more specific routes from updates\n"
6022 "Filter more specific routes from updates\n"
6023 "Generate AS set path information\n")
6026 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
6027 char *prefix
= argv
[idx
]->arg
;
6028 return bgp_aggregate_unset(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
));
6031 DEFUN (no_aggregate_address_mask
,
6032 no_aggregate_address_mask_cmd
,
6033 "no aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
6035 "Configure BGP aggregate entries\n"
6036 "Aggregate address\n"
6038 "Generate AS set path information\n"
6039 "Filter more specific routes from updates\n"
6040 "Filter more specific routes from updates\n"
6041 "Generate AS set path information\n")
6044 argv_find(argv
, argc
, "A.B.C.D", &idx
);
6045 char *prefix
= argv
[idx
]->arg
;
6046 char *mask
= argv
[idx
+ 1]->arg
;
6048 char prefix_str
[BUFSIZ
];
6049 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
6052 vty_out(vty
, "%% Inconsistent address and mask\n");
6053 return CMD_WARNING_CONFIG_FAILED
;
6056 return bgp_aggregate_unset(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
));
6059 DEFUN (ipv6_aggregate_address
,
6060 ipv6_aggregate_address_cmd
,
6061 "aggregate-address X:X::X:X/M [summary-only]",
6062 "Configure BGP aggregate entries\n"
6063 "Aggregate prefix\n"
6064 "Filter more specific routes from updates\n")
6067 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6068 char *prefix
= argv
[idx
]->arg
;
6069 int sum_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6070 ? AGGREGATE_SUMMARY_ONLY
6072 return bgp_aggregate_set(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
, sum_only
,
6076 DEFUN (no_ipv6_aggregate_address
,
6077 no_ipv6_aggregate_address_cmd
,
6078 "no aggregate-address X:X::X:X/M [summary-only]",
6080 "Configure BGP aggregate entries\n"
6081 "Aggregate prefix\n"
6082 "Filter more specific routes from updates\n")
6085 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6086 char *prefix
= argv
[idx
]->arg
;
6087 return bgp_aggregate_unset(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
);
6090 /* Redistribute route treatment. */
6091 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
6092 const union g_addr
*nexthop
, ifindex_t ifindex
,
6093 enum nexthop_types_t nhtype
, uint32_t metric
,
6094 uint8_t type
, unsigned short instance
,
6097 struct bgp_info
*new;
6098 struct bgp_info
*bi
;
6099 struct bgp_info info
;
6100 struct bgp_node
*bn
;
6102 struct attr
*new_attr
;
6105 struct bgp_redist
*red
;
6107 /* Make default attribute. */
6108 bgp_attr_default_set(&attr
, BGP_ORIGIN_INCOMPLETE
);
6111 case NEXTHOP_TYPE_IFINDEX
:
6113 case NEXTHOP_TYPE_IPV4
:
6114 case NEXTHOP_TYPE_IPV4_IFINDEX
:
6115 attr
.nexthop
= nexthop
->ipv4
;
6117 case NEXTHOP_TYPE_IPV6
:
6118 case NEXTHOP_TYPE_IPV6_IFINDEX
:
6119 attr
.mp_nexthop_global
= nexthop
->ipv6
;
6120 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6122 case NEXTHOP_TYPE_BLACKHOLE
:
6123 switch (p
->family
) {
6125 attr
.nexthop
.s_addr
= INADDR_ANY
;
6128 memset(&attr
.mp_nexthop_global
, 0,
6129 sizeof(attr
.mp_nexthop_global
));
6130 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6135 attr
.nh_ifindex
= ifindex
;
6138 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6141 afi
= family2afi(p
->family
);
6143 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6145 struct attr attr_new
;
6147 /* Copy attribute for modification. */
6148 bgp_attr_dup(&attr_new
, &attr
);
6150 if (red
->redist_metric_flag
)
6151 attr_new
.med
= red
->redist_metric
;
6153 /* Apply route-map. */
6154 if (red
->rmap
.name
) {
6155 info
.peer
= bgp
->peer_self
;
6156 info
.attr
= &attr_new
;
6158 SET_FLAG(bgp
->peer_self
->rmap_type
,
6159 PEER_RMAP_TYPE_REDISTRIBUTE
);
6161 ret
= route_map_apply(red
->rmap
.map
, p
, RMAP_BGP
,
6164 bgp
->peer_self
->rmap_type
= 0;
6166 if (ret
== RMAP_DENYMATCH
) {
6167 /* Free uninterned attribute. */
6168 bgp_attr_flush(&attr_new
);
6170 /* Unintern original. */
6171 aspath_unintern(&attr
.aspath
);
6172 bgp_redistribute_delete(bgp
, p
, type
, instance
);
6177 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
6178 bgp_attr_add_gshut_community(&attr_new
);
6180 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6181 SAFI_UNICAST
, p
, NULL
);
6183 new_attr
= bgp_attr_intern(&attr_new
);
6185 for (bi
= bn
->info
; bi
; bi
= bi
->next
)
6186 if (bi
->peer
== bgp
->peer_self
6187 && bi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
6191 /* Ensure the (source route) type is updated. */
6193 if (attrhash_cmp(bi
->attr
, new_attr
)
6194 && !CHECK_FLAG(bi
->flags
, BGP_INFO_REMOVED
)) {
6195 bgp_attr_unintern(&new_attr
);
6196 aspath_unintern(&attr
.aspath
);
6197 bgp_unlock_node(bn
);
6200 /* The attribute is changed. */
6201 bgp_info_set_flag(bn
, bi
,
6202 BGP_INFO_ATTR_CHANGED
);
6204 /* Rewrite BGP route information. */
6205 if (CHECK_FLAG(bi
->flags
, BGP_INFO_REMOVED
))
6206 bgp_info_restore(bn
, bi
);
6208 bgp_aggregate_decrement(bgp
, p
, bi
, afi
,
6210 bgp_attr_unintern(&bi
->attr
);
6211 bi
->attr
= new_attr
;
6212 bi
->uptime
= bgp_clock();
6214 /* Process change. */
6215 bgp_aggregate_increment(bgp
, p
, bi
, afi
,
6217 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6218 bgp_unlock_node(bn
);
6219 aspath_unintern(&attr
.aspath
);
6221 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6223 == BGP_INSTANCE_TYPE_DEFAULT
)) {
6225 vpn_leak_from_vrf_update(
6226 bgp_get_default(), bgp
, bi
);
6232 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
6233 bgp
->peer_self
, new_attr
, bn
);
6234 SET_FLAG(new->flags
, BGP_INFO_VALID
);
6236 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
6237 bgp_info_add(bn
, new);
6238 bgp_unlock_node(bn
);
6239 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6241 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6242 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6244 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
6248 /* Unintern original. */
6249 aspath_unintern(&attr
.aspath
);
6252 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, uint8_t type
,
6253 unsigned short instance
)
6256 struct bgp_node
*rn
;
6257 struct bgp_info
*ri
;
6258 struct bgp_redist
*red
;
6260 afi
= family2afi(p
->family
);
6262 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6264 rn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6265 SAFI_UNICAST
, p
, NULL
);
6267 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
6268 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== type
)
6272 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6273 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6275 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6278 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, SAFI_UNICAST
);
6279 bgp_info_delete(rn
, ri
);
6280 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6282 bgp_unlock_node(rn
);
6286 /* Withdraw specified route type's route. */
6287 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
6288 unsigned short instance
)
6290 struct bgp_node
*rn
;
6291 struct bgp_info
*ri
;
6292 struct bgp_table
*table
;
6294 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
6296 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
6297 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
6298 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== type
6299 && ri
->instance
== instance
)
6303 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6304 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6306 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6309 bgp_aggregate_decrement(bgp
, &rn
->p
, ri
, afi
,
6311 bgp_info_delete(rn
, ri
);
6312 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6317 /* Static function to display route. */
6318 static void route_vty_out_route(struct prefix
*p
, struct vty
*vty
,
6322 uint32_t destination
;
6325 if (p
->family
== AF_INET
) {
6327 len
= vty_out(vty
, "%s",
6328 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
6330 destination
= ntohl(p
->u
.prefix4
.s_addr
);
6332 if ((IN_CLASSC(destination
) && p
->prefixlen
== 24)
6333 || (IN_CLASSB(destination
) && p
->prefixlen
== 16)
6334 || (IN_CLASSA(destination
) && p
->prefixlen
== 8)
6335 || p
->u
.prefix4
.s_addr
== 0) {
6336 /* When mask is natural,
6337 mask is not displayed. */
6339 len
+= vty_out(vty
, "/%d", p
->prefixlen
);
6341 json_object_string_add(json
, "prefix",
6342 inet_ntop(p
->family
,
6345 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
6347 } else if (p
->family
== AF_ETHERNET
) {
6348 prefix2str(p
, buf
, PREFIX_STRLEN
);
6349 len
= vty_out(vty
, "%s", buf
);
6350 } else if (p
->family
== AF_EVPN
) {
6351 #if defined(HAVE_CUMULUS)
6355 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf
,
6358 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
6360 prefix2str(p
, buf
, PREFIX_STRLEN
);
6361 len
= vty_out(vty
, "%s", buf
);
6363 } else if (p
->family
== AF_FLOWSPEC
) {
6364 route_vty_out_flowspec(vty
, p
, NULL
,
6366 NLRI_STRING_FORMAT_JSON_SIMPLE
:
6367 NLRI_STRING_FORMAT_MIN
, json
);
6372 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
6379 vty_out(vty
, "\n%*s", 20, " ");
6381 vty_out(vty
, "%*s", len
, " ");
6385 enum bgp_display_type
{
6389 /* Print the short form route status for a bgp_info */
6390 static void route_vty_short_status_out(struct vty
*vty
, struct bgp_info
*binfo
,
6391 json_object
*json_path
)
6395 /* Route status display. */
6396 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_REMOVED
))
6397 json_object_boolean_true_add(json_path
, "removed");
6399 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_STALE
))
6400 json_object_boolean_true_add(json_path
, "stale");
6402 if (binfo
->extra
&& binfo
->extra
->suppress
)
6403 json_object_boolean_true_add(json_path
, "suppressed");
6405 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)
6406 && !CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6407 json_object_boolean_true_add(json_path
, "valid");
6410 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6411 json_object_boolean_true_add(json_path
, "history");
6413 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
))
6414 json_object_boolean_true_add(json_path
, "damped");
6416 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
))
6417 json_object_boolean_true_add(json_path
, "bestpath");
6419 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_MULTIPATH
))
6420 json_object_boolean_true_add(json_path
, "multipath");
6422 /* Internal route. */
6423 if ((binfo
->peer
->as
)
6424 && (binfo
->peer
->as
== binfo
->peer
->local_as
))
6425 json_object_string_add(json_path
, "pathFrom",
6428 json_object_string_add(json_path
, "pathFrom",
6434 /* Route status display. */
6435 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_REMOVED
))
6437 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_STALE
))
6439 else if (binfo
->extra
&& binfo
->extra
->suppress
)
6441 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)
6442 && !CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6448 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6450 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
))
6452 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
))
6454 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_MULTIPATH
))
6459 /* Internal route. */
6460 if (binfo
->peer
&& (binfo
->peer
->as
)
6461 && (binfo
->peer
->as
== binfo
->peer
->local_as
))
6467 /* called from terminal list command */
6468 void route_vty_out(struct vty
*vty
, struct prefix
*p
, struct bgp_info
*binfo
,
6469 int display
, safi_t safi
, json_object
*json_paths
)
6472 json_object
*json_path
= NULL
;
6473 json_object
*json_nexthops
= NULL
;
6474 json_object
*json_nexthop_global
= NULL
;
6475 json_object
*json_nexthop_ll
= NULL
;
6476 char vrf_id_str
[VRF_NAMSIZ
] = {0};
6477 bool nexthop_self
= CHECK_FLAG(binfo
->flags
, BGP_INFO_ANNC_NH_SELF
)
6480 bool nexthop_othervrf
= false;
6481 vrf_id_t nexthop_vrfid
;
6482 const char *nexthop_vrfname
= "Default";
6485 json_path
= json_object_new_object();
6487 /* short status lead text */
6488 route_vty_short_status_out(vty
, binfo
, json_path
);
6491 /* print prefix and mask */
6493 route_vty_out_route(p
, vty
, json_path
);
6495 vty_out(vty
, "%*s", 17, " ");
6497 route_vty_out_route(p
, vty
, json_path
);
6500 /* Print attribute */
6504 json_object_array_add(json_paths
, json_path
);
6512 * If vrf id of nexthop is different from that of prefix,
6513 * set up printable string to append
6515 if (binfo
->extra
&& binfo
->extra
->bgp_orig
) {
6516 const char *self
= "";
6521 nexthop_othervrf
= true;
6522 nexthop_vrfid
= binfo
->extra
->bgp_orig
->vrf_id
;
6524 if (binfo
->extra
->bgp_orig
->vrf_id
== VRF_UNKNOWN
)
6525 snprintf(vrf_id_str
, sizeof(vrf_id_str
),
6526 "@%s%s", VRFID_NONE_STR
, self
);
6528 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "@%u%s",
6529 binfo
->extra
->bgp_orig
->vrf_id
, self
);
6531 if (binfo
->extra
->bgp_orig
->inst_type
!=
6532 BGP_INSTANCE_TYPE_DEFAULT
)
6534 nexthop_vrfname
= binfo
->extra
->bgp_orig
->name
;
6536 const char *self
= "";
6541 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "%s", self
);
6545 * For ENCAP and EVPN routes, nexthop address family is not
6546 * neccessarily the same as the prefix address family.
6547 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
6548 * EVPN routes are also exchanged with a MP nexthop. Currently,
6550 * is only IPv4, the value will be present in either
6552 * attr->mp_nexthop_global_in
6554 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
6557 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
6561 sprintf(nexthop
, "%s",
6562 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
6566 sprintf(nexthop
, "%s",
6567 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
6571 sprintf(nexthop
, "?");
6576 json_nexthop_global
= json_object_new_object();
6578 json_object_string_add(json_nexthop_global
, "afi",
6579 (af
== AF_INET
) ? "ip" : "ipv6");
6580 json_object_string_add(json_nexthop_global
,
6581 (af
== AF_INET
) ? "ip" : "ipv6",
6583 json_object_boolean_true_add(json_nexthop_global
,
6586 vty_out(vty
, "%s%s", nexthop
, vrf_id_str
);
6587 } else if (safi
== SAFI_EVPN
) {
6589 json_nexthop_global
= json_object_new_object();
6591 json_object_string_add(json_nexthop_global
, "ip",
6592 inet_ntoa(attr
->nexthop
));
6593 json_object_string_add(json_nexthop_global
, "afi",
6595 json_object_boolean_true_add(json_nexthop_global
,
6598 vty_out(vty
, "%-16s%s", inet_ntoa(attr
->nexthop
),
6600 } else if (safi
== SAFI_FLOWSPEC
) {
6601 if (attr
->nexthop
.s_addr
!= 0) {
6603 json_nexthop_global
= json_object_new_object();
6604 json_object_string_add(
6605 json_nexthop_global
, "ip",
6606 inet_ntoa(attr
->nexthop
));
6607 json_object_string_add(json_nexthop_global
,
6609 json_object_boolean_true_add(json_nexthop_global
,
6612 vty_out(vty
, "%-16s", inet_ntoa(attr
->nexthop
));
6615 } else if (p
->family
== AF_INET
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6617 json_nexthop_global
= json_object_new_object();
6619 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_EVPN
))
6620 json_object_string_add(
6621 json_nexthop_global
, "ip",
6622 inet_ntoa(attr
->mp_nexthop_global_in
));
6624 json_object_string_add(
6625 json_nexthop_global
, "ip",
6626 inet_ntoa(attr
->nexthop
));
6628 json_object_string_add(json_nexthop_global
, "afi",
6630 json_object_boolean_true_add(json_nexthop_global
,
6635 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_EVPN
))
6636 snprintf(buf
, sizeof(buf
), "%s%s",
6637 inet_ntoa(attr
->mp_nexthop_global_in
),
6640 snprintf(buf
, sizeof(buf
), "%s%s",
6641 inet_ntoa(attr
->nexthop
),
6643 vty_out(vty
, "%-16s", buf
);
6648 else if (p
->family
== AF_INET6
|| BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6653 json_nexthop_global
= json_object_new_object();
6654 json_object_string_add(
6655 json_nexthop_global
, "ip",
6656 inet_ntop(AF_INET6
, &attr
->mp_nexthop_global
,
6658 json_object_string_add(json_nexthop_global
, "afi",
6660 json_object_string_add(json_nexthop_global
, "scope",
6663 /* We display both LL & GL if both have been
6665 if ((attr
->mp_nexthop_len
== 32)
6666 || (binfo
->peer
->conf_if
)) {
6667 json_nexthop_ll
= json_object_new_object();
6668 json_object_string_add(
6669 json_nexthop_ll
, "ip",
6671 &attr
->mp_nexthop_local
, buf
,
6673 json_object_string_add(json_nexthop_ll
, "afi",
6675 json_object_string_add(json_nexthop_ll
, "scope",
6678 if ((IPV6_ADDR_CMP(&attr
->mp_nexthop_global
,
6679 &attr
->mp_nexthop_local
)
6681 && !attr
->mp_nexthop_prefer_global
)
6682 json_object_boolean_true_add(
6683 json_nexthop_ll
, "used");
6685 json_object_boolean_true_add(
6686 json_nexthop_global
, "used");
6688 json_object_boolean_true_add(
6689 json_nexthop_global
, "used");
6691 /* Display LL if LL/Global both in table unless
6692 * prefer-global is set */
6693 if (((attr
->mp_nexthop_len
== 32)
6694 && !attr
->mp_nexthop_prefer_global
)
6695 || (binfo
->peer
->conf_if
)) {
6696 if (binfo
->peer
->conf_if
) {
6697 len
= vty_out(vty
, "%s",
6698 binfo
->peer
->conf_if
);
6699 len
= 16 - len
; /* len of IPv6
6705 vty_out(vty
, "\n%*s", 36, " ");
6707 vty_out(vty
, "%*s", len
, " ");
6713 &attr
->mp_nexthop_local
,
6719 vty_out(vty
, "\n%*s", 36, " ");
6721 vty_out(vty
, "%*s", len
, " ");
6727 &attr
->mp_nexthop_global
, buf
,
6733 vty_out(vty
, "\n%*s", 36, " ");
6735 vty_out(vty
, "%*s", len
, " ");
6741 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
6743 json_object_int_add(json_path
, "med", attr
->med
);
6745 vty_out(vty
, "%10u", attr
->med
);
6746 else if (!json_paths
)
6750 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
6752 json_object_int_add(json_path
, "localpref",
6755 vty_out(vty
, "%7u", attr
->local_pref
);
6756 else if (!json_paths
)
6760 json_object_int_add(json_path
, "weight", attr
->weight
);
6762 vty_out(vty
, "%7u ", attr
->weight
);
6766 json_object_string_add(
6767 json_path
, "peerId",
6768 sockunion2str(&binfo
->peer
->su
, buf
, SU_ADDRSTRLEN
));
6774 json_object_string_add(json_path
, "aspath",
6777 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
6782 json_object_string_add(json_path
, "origin",
6783 bgp_origin_long_str
[attr
->origin
]);
6785 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
6789 json_object_boolean_true_add(json_path
,
6790 "announceNexthopSelf");
6791 if (nexthop_othervrf
) {
6792 json_object_string_add(json_path
, "nhVrfName",
6795 json_object_int_add(json_path
, "nhVrfId",
6796 ((nexthop_vrfid
== VRF_UNKNOWN
)
6798 : (int)nexthop_vrfid
));
6803 if (json_nexthop_global
|| json_nexthop_ll
) {
6804 json_nexthops
= json_object_new_array();
6806 if (json_nexthop_global
)
6807 json_object_array_add(json_nexthops
,
6808 json_nexthop_global
);
6810 if (json_nexthop_ll
)
6811 json_object_array_add(json_nexthops
,
6814 json_object_object_add(json_path
, "nexthops",
6818 json_object_array_add(json_paths
, json_path
);
6822 /* prints an additional line, indented, with VNC info, if
6824 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
6825 rfapi_vty_out_vncinfo(vty
, p
, binfo
, safi
);
6830 /* called from terminal list command */
6831 void route_vty_out_tmp(struct vty
*vty
, struct prefix
*p
, struct attr
*attr
,
6832 safi_t safi
, uint8_t use_json
, json_object
*json_ar
)
6834 json_object
*json_status
= NULL
;
6835 json_object
*json_net
= NULL
;
6837 /* Route status display. */
6839 json_status
= json_object_new_object();
6840 json_net
= json_object_new_object();
6847 /* print prefix and mask */
6849 json_object_string_add(
6850 json_net
, "addrPrefix",
6851 inet_ntop(p
->family
, &p
->u
.prefix
, buff
, BUFSIZ
));
6853 route_vty_out_route(p
, vty
, NULL
);
6855 /* Print attribute */
6858 if (p
->family
== AF_INET
6859 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6860 || safi
== SAFI_EVPN
6861 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6862 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6863 || safi
== SAFI_EVPN
)
6864 json_object_string_add(
6865 json_net
, "nextHop",
6867 attr
->mp_nexthop_global_in
));
6869 json_object_string_add(
6870 json_net
, "nextHop",
6871 inet_ntoa(attr
->nexthop
));
6872 } else if (p
->family
== AF_INET6
6873 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6876 json_object_string_add(
6877 json_net
, "netHopGloabal",
6879 &attr
->mp_nexthop_global
, buf
,
6884 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
6885 json_object_int_add(json_net
, "metric",
6888 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
6889 json_object_int_add(json_net
, "localPref",
6892 json_object_int_add(json_net
, "weight", attr
->weight
);
6896 json_object_string_add(json_net
, "asPath",
6900 json_object_string_add(json_net
, "bgpOriginCode",
6901 bgp_origin_str
[attr
->origin
]);
6903 if (p
->family
== AF_INET
6904 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6905 || safi
== SAFI_EVPN
6906 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6907 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6908 || safi
== SAFI_EVPN
)
6909 vty_out(vty
, "%-16s",
6911 attr
->mp_nexthop_global_in
));
6913 vty_out(vty
, "%-16s",
6914 inet_ntoa(attr
->nexthop
));
6915 } else if (p
->family
== AF_INET6
6916 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6923 &attr
->mp_nexthop_global
, buf
,
6927 vty_out(vty
, "\n%*s", 36, " ");
6929 vty_out(vty
, "%*s", len
, " ");
6932 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
6933 vty_out(vty
, "%10u", attr
->med
);
6937 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
6938 vty_out(vty
, "%7u", attr
->local_pref
);
6942 vty_out(vty
, "%7u ", attr
->weight
);
6946 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
6949 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
6953 json_object_boolean_true_add(json_status
, "*");
6954 json_object_boolean_true_add(json_status
, ">");
6955 json_object_object_add(json_net
, "appliedStatusSymbols",
6957 char buf_cut
[BUFSIZ
];
6958 json_object_object_add(
6960 inet_ntop(p
->family
, &p
->u
.prefix
, buf_cut
, BUFSIZ
),
6966 void route_vty_out_tag(struct vty
*vty
, struct prefix
*p
,
6967 struct bgp_info
*binfo
, int display
, safi_t safi
,
6970 json_object
*json_out
= NULL
;
6972 mpls_label_t label
= MPLS_INVALID_LABEL
;
6978 json_out
= json_object_new_object();
6980 /* short status lead text */
6981 route_vty_short_status_out(vty
, binfo
, json_out
);
6983 /* print prefix and mask */
6986 route_vty_out_route(p
, vty
, NULL
);
6988 vty_out(vty
, "%*s", 17, " ");
6991 /* Print attribute */
6994 if (((p
->family
== AF_INET
)
6995 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
6996 || (safi
== SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
6997 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6998 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6999 || safi
== SAFI_EVPN
) {
7001 json_object_string_add(
7002 json_out
, "mpNexthopGlobalIn",
7004 attr
->mp_nexthop_global_in
));
7006 vty_out(vty
, "%-16s",
7008 attr
->mp_nexthop_global_in
));
7011 json_object_string_add(
7012 json_out
, "nexthop",
7013 inet_ntoa(attr
->nexthop
));
7015 vty_out(vty
, "%-16s",
7016 inet_ntoa(attr
->nexthop
));
7018 } else if (((p
->family
== AF_INET6
)
7019 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
7020 || (safi
== SAFI_EVPN
7021 && BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
7022 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7026 if (attr
->mp_nexthop_len
7027 == BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
7029 json_object_string_add(
7030 json_out
, "mpNexthopGlobalIn",
7033 &attr
->mp_nexthop_global
,
7039 &attr
->mp_nexthop_global
,
7041 } else if (attr
->mp_nexthop_len
7042 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
7045 &attr
->mp_nexthop_global
,
7048 &attr
->mp_nexthop_local
,
7050 sprintf(buf_c
, "%s(%s)", buf_a
, buf_b
);
7051 json_object_string_add(
7053 "mpNexthopGlobalLocal", buf_c
);
7055 vty_out(vty
, "%s(%s)",
7058 &attr
->mp_nexthop_global
,
7062 &attr
->mp_nexthop_local
,
7068 label
= decode_label(&binfo
->extra
->label
[0]);
7070 if (bgp_is_valid_label(&label
)) {
7072 json_object_int_add(json_out
, "notag", label
);
7073 json_object_array_add(json
, json_out
);
7075 vty_out(vty
, "notag/%d", label
);
7081 void route_vty_out_overlay(struct vty
*vty
, struct prefix
*p
,
7082 struct bgp_info
*binfo
, int display
,
7083 json_object
*json_paths
)
7087 json_object
*json_path
= NULL
;
7090 json_path
= json_object_new_object();
7095 /* short status lead text */
7096 route_vty_short_status_out(vty
, binfo
, json_path
);
7098 /* print prefix and mask */
7100 route_vty_out_route(p
, vty
, NULL
);
7102 vty_out(vty
, "%*s", 17, " ");
7104 /* Print attribute */
7108 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
7112 vty_out(vty
, "%-16s",
7113 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
7117 vty_out(vty
, "%s(%s)",
7118 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
7120 inet_ntop(af
, &attr
->mp_nexthop_local
, buf1
,
7127 char *str
= esi2str(&(attr
->evpn_overlay
.eth_s_id
));
7129 vty_out(vty
, "%s", str
);
7130 XFREE(MTYPE_TMP
, str
);
7132 if (IS_EVPN_PREFIX_IPADDR_V4((struct prefix_evpn
*)p
)) {
7134 inet_ntoa(attr
->evpn_overlay
.gw_ip
.ipv4
));
7135 } else if (IS_EVPN_PREFIX_IPADDR_V6((struct prefix_evpn
*)p
)) {
7138 &(attr
->evpn_overlay
.gw_ip
.ipv6
), buf
,
7141 if (attr
->ecommunity
) {
7143 struct ecommunity_val
*routermac
= ecommunity_lookup(
7144 attr
->ecommunity
, ECOMMUNITY_ENCODE_EVPN
,
7145 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
7147 mac
= ecom_mac2str((char *)routermac
->val
);
7149 vty_out(vty
, "/%s", (char *)mac
);
7150 XFREE(MTYPE_TMP
, mac
);
7158 /* dampening route */
7159 static void damp_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7160 struct bgp_info
*binfo
, int display
, safi_t safi
,
7161 uint8_t use_json
, json_object
*json
)
7165 char timebuf
[BGP_UPTIME_LEN
];
7167 /* short status lead text */
7168 route_vty_short_status_out(vty
, binfo
, json
);
7170 /* print prefix and mask */
7173 route_vty_out_route(p
, vty
, NULL
);
7175 vty_out(vty
, "%*s", 17, " ");
7178 len
= vty_out(vty
, "%s", binfo
->peer
->host
);
7182 vty_out(vty
, "\n%*s", 34, " ");
7185 json_object_int_add(json
, "peerHost", len
);
7187 vty_out(vty
, "%*s", len
, " ");
7191 bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
, BGP_UPTIME_LEN
,
7194 vty_out(vty
, "%s ", bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
,
7198 /* Print attribute */
7204 json_object_string_add(json
, "asPath",
7207 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7212 json_object_string_add(json
, "origin",
7213 bgp_origin_str
[attr
->origin
]);
7215 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7222 static void flap_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7223 struct bgp_info
*binfo
, int display
, safi_t safi
,
7224 uint8_t use_json
, json_object
*json
)
7227 struct bgp_damp_info
*bdi
;
7228 char timebuf
[BGP_UPTIME_LEN
];
7234 bdi
= binfo
->extra
->damp_info
;
7236 /* short status lead text */
7237 route_vty_short_status_out(vty
, binfo
, json
);
7239 /* print prefix and mask */
7242 route_vty_out_route(p
, vty
, NULL
);
7244 vty_out(vty
, "%*s", 17, " ");
7247 len
= vty_out(vty
, "%s", binfo
->peer
->host
);
7251 vty_out(vty
, "\n%*s", 33, " ");
7254 json_object_int_add(json
, "peerHost", len
);
7256 vty_out(vty
, "%*s", len
, " ");
7259 len
= vty_out(vty
, "%d", bdi
->flap
);
7266 json_object_int_add(json
, "bdiFlap", len
);
7268 vty_out(vty
, "%*s", len
, " ");
7272 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
7275 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
7276 BGP_UPTIME_LEN
, 0, NULL
));
7278 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
)
7279 && !CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
)) {
7281 bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
,
7282 BGP_UPTIME_LEN
, use_json
, json
);
7285 bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
,
7290 vty_out(vty
, "%*s ", 8, " ");
7293 /* Print attribute */
7299 json_object_string_add(json
, "asPath",
7302 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7307 json_object_string_add(json
, "origin",
7308 bgp_origin_str
[attr
->origin
]);
7310 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7316 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
7317 int *first
, const char *header
,
7318 json_object
*json_adv_to
)
7320 char buf1
[INET6_ADDRSTRLEN
];
7321 json_object
*json_peer
= NULL
;
7324 /* 'advertised-to' is a dictionary of peers we have advertised
7326 * prefix too. The key is the peer's IP or swpX, the value is
7328 * hostname if we know it and "" if not.
7330 json_peer
= json_object_new_object();
7333 json_object_string_add(json_peer
, "hostname",
7337 json_object_object_add(json_adv_to
, peer
->conf_if
,
7340 json_object_object_add(
7342 sockunion2str(&peer
->su
, buf1
, SU_ADDRSTRLEN
),
7346 vty_out(vty
, "%s", header
);
7351 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
7353 vty_out(vty
, " %s(%s)", peer
->hostname
,
7356 vty_out(vty
, " %s(%s)", peer
->hostname
,
7357 sockunion2str(&peer
->su
, buf1
,
7361 vty_out(vty
, " %s", peer
->conf_if
);
7364 sockunion2str(&peer
->su
, buf1
,
7370 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
, struct prefix
*p
,
7371 struct bgp_info
*binfo
, afi_t afi
, safi_t safi
,
7372 json_object
*json_paths
)
7374 char buf
[INET6_ADDRSTRLEN
];
7376 #if defined(HAVE_CUMULUS)
7377 char buf2
[EVPN_ROUTE_STRLEN
];
7380 int sockunion_vty_out(struct vty
*, union sockunion
*);
7382 json_object
*json_bestpath
= NULL
;
7383 json_object
*json_cluster_list
= NULL
;
7384 json_object
*json_cluster_list_list
= NULL
;
7385 json_object
*json_ext_community
= NULL
;
7386 json_object
*json_lcommunity
= NULL
;
7387 json_object
*json_last_update
= NULL
;
7388 json_object
*json_pmsi
= NULL
;
7389 json_object
*json_nexthop_global
= NULL
;
7390 json_object
*json_nexthop_ll
= NULL
;
7391 json_object
*json_nexthops
= NULL
;
7392 json_object
*json_path
= NULL
;
7393 json_object
*json_peer
= NULL
;
7394 json_object
*json_string
= NULL
;
7395 json_object
*json_adv_to
= NULL
;
7397 struct listnode
*node
, *nnode
;
7399 int addpath_capable
;
7401 unsigned int first_as
;
7402 bool nexthop_self
= CHECK_FLAG(binfo
->flags
, BGP_INFO_ANNC_NH_SELF
)
7407 json_path
= json_object_new_object();
7408 json_peer
= json_object_new_object();
7409 json_nexthop_global
= json_object_new_object();
7412 #if defined(HAVE_CUMULUS)
7413 if (!json_paths
&& safi
== SAFI_EVPN
) {
7416 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf2
, sizeof(buf2
));
7417 vty_out(vty
, " Route %s", buf2
);
7419 if (binfo
->extra
&& binfo
->extra
->num_labels
) {
7420 bgp_evpn_label2str(binfo
->extra
->label
,
7421 binfo
->extra
->num_labels
, tag_buf
,
7423 vty_out(vty
, " VNI %s", tag_buf
);
7426 if (binfo
->extra
&& binfo
->extra
->parent
) {
7427 struct bgp_info
*parent_ri
;
7428 struct bgp_node
*rn
, *prn
;
7430 parent_ri
= (struct bgp_info
*)binfo
->extra
->parent
;
7431 rn
= parent_ri
->net
;
7432 if (rn
&& rn
->prn
) {
7434 vty_out(vty
, " Imported from %s:%s\n",
7436 (struct prefix_rd
*)&prn
->p
,
7437 buf1
, sizeof(buf1
)),
7447 /* Line1 display AS-path, Aggregator */
7450 if (!attr
->aspath
->json
)
7451 aspath_str_update(attr
->aspath
, true);
7452 json_object_lock(attr
->aspath
->json
);
7453 json_object_object_add(json_path
, "aspath",
7454 attr
->aspath
->json
);
7456 if (attr
->aspath
->segments
)
7457 aspath_print_vty(vty
, " %s",
7460 vty_out(vty
, " Local");
7464 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_REMOVED
)) {
7466 json_object_boolean_true_add(json_path
,
7469 vty_out(vty
, ", (removed)");
7472 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_STALE
)) {
7474 json_object_boolean_true_add(json_path
,
7477 vty_out(vty
, ", (stale)");
7480 if (CHECK_FLAG(attr
->flag
,
7481 ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
7483 json_object_int_add(json_path
, "aggregatorAs",
7484 attr
->aggregator_as
);
7485 json_object_string_add(
7486 json_path
, "aggregatorId",
7487 inet_ntoa(attr
->aggregator_addr
));
7489 vty_out(vty
, ", (aggregated by %u %s)",
7490 attr
->aggregator_as
,
7491 inet_ntoa(attr
->aggregator_addr
));
7495 if (CHECK_FLAG(binfo
->peer
->af_flags
[afi
][safi
],
7496 PEER_FLAG_REFLECTOR_CLIENT
)) {
7498 json_object_boolean_true_add(
7499 json_path
, "rxedFromRrClient");
7501 vty_out(vty
, ", (Received from a RR-client)");
7504 if (CHECK_FLAG(binfo
->peer
->af_flags
[afi
][safi
],
7505 PEER_FLAG_RSERVER_CLIENT
)) {
7507 json_object_boolean_true_add(
7508 json_path
, "rxedFromRsClient");
7510 vty_out(vty
, ", (Received from a RS-client)");
7513 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
)) {
7515 json_object_boolean_true_add(
7516 json_path
, "dampeningHistoryEntry");
7518 vty_out(vty
, ", (history entry)");
7519 } else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
)) {
7521 json_object_boolean_true_add(
7522 json_path
, "dampeningSuppressed");
7524 vty_out(vty
, ", (suppressed due to dampening)");
7530 /* Line2 display Next-hop, Neighbor, Router-id */
7531 /* Display the nexthop */
7532 if ((p
->family
== AF_INET
|| p
->family
== AF_ETHERNET
7533 || p
->family
== AF_EVPN
)
7534 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7535 || safi
== SAFI_EVPN
7536 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7537 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7538 || safi
== SAFI_EVPN
) {
7540 json_object_string_add(
7541 json_nexthop_global
, "ip",
7543 attr
->mp_nexthop_global_in
));
7547 attr
->mp_nexthop_global_in
));
7550 json_object_string_add(
7551 json_nexthop_global
, "ip",
7552 inet_ntoa(attr
->nexthop
));
7555 inet_ntoa(attr
->nexthop
));
7559 json_object_string_add(json_nexthop_global
,
7563 json_object_string_add(
7564 json_nexthop_global
, "ip",
7566 &attr
->mp_nexthop_global
, buf
,
7568 json_object_string_add(json_nexthop_global
,
7570 json_object_string_add(json_nexthop_global
,
7575 &attr
->mp_nexthop_global
, buf
,
7580 /* Display the IGP cost or 'inaccessible' */
7581 if (!CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)) {
7583 json_object_boolean_false_add(
7584 json_nexthop_global
, "accessible");
7586 vty_out(vty
, " (inaccessible)");
7588 if (binfo
->extra
&& binfo
->extra
->igpmetric
) {
7590 json_object_int_add(
7591 json_nexthop_global
, "metric",
7592 binfo
->extra
->igpmetric
);
7594 vty_out(vty
, " (metric %u)",
7595 binfo
->extra
->igpmetric
);
7598 /* IGP cost is 0, display this only for json */
7601 json_object_int_add(json_nexthop_global
,
7606 json_object_boolean_true_add(
7607 json_nexthop_global
, "accessible");
7610 /* Display peer "from" output */
7611 /* This path was originated locally */
7612 if (binfo
->peer
== bgp
->peer_self
) {
7614 if (safi
== SAFI_EVPN
7615 || (p
->family
== AF_INET
7616 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7618 json_object_string_add(
7619 json_peer
, "peerId", "0.0.0.0");
7621 vty_out(vty
, " from 0.0.0.0 ");
7624 json_object_string_add(json_peer
,
7627 vty_out(vty
, " from :: ");
7631 json_object_string_add(
7632 json_peer
, "routerId",
7633 inet_ntoa(bgp
->router_id
));
7635 vty_out(vty
, "(%s)", inet_ntoa(bgp
->router_id
));
7638 /* We RXed this path from one of our peers */
7642 json_object_string_add(
7643 json_peer
, "peerId",
7644 sockunion2str(&binfo
->peer
->su
, buf
,
7646 json_object_string_add(
7647 json_peer
, "routerId",
7649 &binfo
->peer
->remote_id
, buf1
,
7652 if (binfo
->peer
->hostname
)
7653 json_object_string_add(
7654 json_peer
, "hostname",
7655 binfo
->peer
->hostname
);
7657 if (binfo
->peer
->domainname
)
7658 json_object_string_add(
7659 json_peer
, "domainname",
7660 binfo
->peer
->domainname
);
7662 if (binfo
->peer
->conf_if
)
7663 json_object_string_add(
7664 json_peer
, "interface",
7665 binfo
->peer
->conf_if
);
7667 if (binfo
->peer
->conf_if
) {
7668 if (binfo
->peer
->hostname
7671 BGP_FLAG_SHOW_HOSTNAME
))
7672 vty_out(vty
, " from %s(%s)",
7673 binfo
->peer
->hostname
,
7674 binfo
->peer
->conf_if
);
7676 vty_out(vty
, " from %s",
7677 binfo
->peer
->conf_if
);
7679 if (binfo
->peer
->hostname
7682 BGP_FLAG_SHOW_HOSTNAME
))
7683 vty_out(vty
, " from %s(%s)",
7684 binfo
->peer
->hostname
,
7687 vty_out(vty
, " from %s",
7696 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
7697 vty_out(vty
, " (%s)",
7698 inet_ntoa(attr
->originator_id
));
7700 vty_out(vty
, " (%s)",
7703 &binfo
->peer
->remote_id
,
7704 buf1
, sizeof(buf1
)));
7709 * Note when vrfid of nexthop is different from that of prefix
7711 if (binfo
->extra
&& binfo
->extra
->bgp_orig
) {
7712 vrf_id_t nexthop_vrfid
= binfo
->extra
->bgp_orig
->vrf_id
;
7717 if (binfo
->extra
->bgp_orig
->inst_type
==
7718 BGP_INSTANCE_TYPE_DEFAULT
)
7722 vn
= binfo
->extra
->bgp_orig
->name
;
7724 json_object_string_add(json_path
, "nhVrfName",
7727 if (nexthop_vrfid
== VRF_UNKNOWN
) {
7728 json_object_int_add(json_path
,
7731 json_object_int_add(json_path
,
7732 "nhVrfId", (int)nexthop_vrfid
);
7735 if (nexthop_vrfid
== VRF_UNKNOWN
)
7736 vty_out(vty
, " vrf ?");
7738 vty_out(vty
, " vrf %u", nexthop_vrfid
);
7744 json_object_boolean_true_add(json_path
,
7745 "announceNexthopSelf");
7747 vty_out(vty
, " announce-nh-self");
7754 /* display the link-local nexthop */
7755 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
7757 json_nexthop_ll
= json_object_new_object();
7758 json_object_string_add(
7759 json_nexthop_ll
, "ip",
7761 &attr
->mp_nexthop_local
, buf
,
7763 json_object_string_add(json_nexthop_ll
, "afi",
7765 json_object_string_add(json_nexthop_ll
, "scope",
7768 json_object_boolean_true_add(json_nexthop_ll
,
7771 if (!attr
->mp_nexthop_prefer_global
)
7772 json_object_boolean_true_add(
7773 json_nexthop_ll
, "used");
7775 json_object_boolean_true_add(
7776 json_nexthop_global
, "used");
7778 vty_out(vty
, " (%s) %s\n",
7780 &attr
->mp_nexthop_local
, buf
,
7782 attr
->mp_nexthop_prefer_global
7787 /* If we do not have a link-local nexthop then we must flag the
7791 json_object_boolean_true_add(
7792 json_nexthop_global
, "used");
7795 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
7796 * Int/Ext/Local, Atomic, best */
7798 json_object_string_add(
7799 json_path
, "origin",
7800 bgp_origin_long_str
[attr
->origin
]);
7802 vty_out(vty
, " Origin %s",
7803 bgp_origin_long_str
[attr
->origin
]);
7805 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
7807 json_object_int_add(json_path
, "med",
7810 vty_out(vty
, ", metric %u", attr
->med
);
7813 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
7815 json_object_int_add(json_path
, "localpref",
7818 vty_out(vty
, ", localpref %u",
7822 json_object_int_add(json_path
, "localpref",
7823 bgp
->default_local_pref
);
7825 vty_out(vty
, ", localpref %u",
7826 bgp
->default_local_pref
);
7829 if (attr
->weight
!= 0) {
7831 json_object_int_add(json_path
, "weight",
7834 vty_out(vty
, ", weight %u", attr
->weight
);
7837 if (attr
->tag
!= 0) {
7839 json_object_int_add(json_path
, "tag",
7842 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
,
7846 if (!CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)) {
7848 json_object_boolean_false_add(json_path
,
7851 vty_out(vty
, ", invalid");
7852 } else if (!CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
)) {
7854 json_object_boolean_true_add(json_path
,
7857 vty_out(vty
, ", valid");
7860 if (binfo
->peer
!= bgp
->peer_self
) {
7861 if (binfo
->peer
->as
== binfo
->peer
->local_as
) {
7862 if (CHECK_FLAG(bgp
->config
,
7863 BGP_CONFIG_CONFEDERATION
)) {
7865 json_object_string_add(
7870 ", confed-internal");
7873 json_object_string_add(
7877 vty_out(vty
, ", internal");
7880 if (bgp_confederation_peers_check(
7881 bgp
, binfo
->peer
->as
)) {
7883 json_object_string_add(
7888 ", confed-external");
7891 json_object_string_add(
7895 vty_out(vty
, ", external");
7898 } else if (binfo
->sub_type
== BGP_ROUTE_AGGREGATE
) {
7900 json_object_boolean_true_add(json_path
,
7902 json_object_boolean_true_add(json_path
,
7905 vty_out(vty
, ", aggregated, local");
7907 } else if (binfo
->type
!= ZEBRA_ROUTE_BGP
) {
7909 json_object_boolean_true_add(json_path
,
7912 vty_out(vty
, ", sourced");
7915 json_object_boolean_true_add(json_path
,
7917 json_object_boolean_true_add(json_path
,
7920 vty_out(vty
, ", sourced, local");
7924 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
7926 json_object_boolean_true_add(json_path
,
7929 vty_out(vty
, ", atomic-aggregate");
7932 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_MULTIPATH
)
7933 || (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
)
7934 && bgp_info_mpath_count(binfo
))) {
7936 json_object_boolean_true_add(json_path
,
7939 vty_out(vty
, ", multipath");
7942 // Mark the bestpath(s)
7943 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DMED_SELECTED
)) {
7944 first_as
= aspath_get_first_as(attr
->aspath
);
7949 json_object_new_object();
7950 json_object_int_add(json_bestpath
,
7951 "bestpathFromAs", first_as
);
7954 vty_out(vty
, ", bestpath-from-AS %u",
7958 ", bestpath-from-AS Local");
7962 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
)) {
7966 json_object_new_object();
7967 json_object_boolean_true_add(json_bestpath
,
7970 vty_out(vty
, ", best");
7974 json_object_object_add(json_path
, "bestpath",
7980 /* Line 4 display Community */
7981 if (attr
->community
) {
7983 if (!attr
->community
->json
)
7984 community_str(attr
->community
, true);
7985 json_object_lock(attr
->community
->json
);
7986 json_object_object_add(json_path
, "community",
7987 attr
->community
->json
);
7989 vty_out(vty
, " Community: %s\n",
7990 attr
->community
->str
);
7994 /* Line 5 display Extended-community */
7995 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
7997 json_ext_community
= json_object_new_object();
7998 json_object_string_add(json_ext_community
,
8000 attr
->ecommunity
->str
);
8001 json_object_object_add(json_path
,
8002 "extendedCommunity",
8003 json_ext_community
);
8005 vty_out(vty
, " Extended Community: %s\n",
8006 attr
->ecommunity
->str
);
8010 /* Line 6 display Large community */
8011 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
8013 json_lcommunity
= json_object_new_object();
8014 json_object_string_add(json_lcommunity
,
8016 attr
->lcommunity
->str
);
8017 json_object_object_add(json_path
,
8021 vty_out(vty
, " Large Community: %s\n",
8022 attr
->lcommunity
->str
);
8026 /* Line 7 display Originator, Cluster-id */
8027 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
8028 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
8030 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
8032 json_object_string_add(
8033 json_path
, "originatorId",
8034 inet_ntoa(attr
->originator_id
));
8036 vty_out(vty
, " Originator: %s",
8037 inet_ntoa(attr
->originator_id
));
8040 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
8045 json_object_new_object();
8046 json_cluster_list_list
=
8047 json_object_new_array();
8050 i
< attr
->cluster
->length
/ 4;
8052 json_string
= json_object_new_string(
8056 json_object_array_add(
8057 json_cluster_list_list
,
8061 /* struct cluster_list does not have
8063 * aspath and community do. Add this
8066 json_object_string_add(json_cluster_list,
8067 "string", attr->cluster->str);
8069 json_object_object_add(
8070 json_cluster_list
, "list",
8071 json_cluster_list_list
);
8072 json_object_object_add(
8073 json_path
, "clusterList",
8076 vty_out(vty
, ", Cluster list: ");
8079 i
< attr
->cluster
->length
/ 4;
8093 if (binfo
->extra
&& binfo
->extra
->damp_info
)
8094 bgp_damp_info_vty(vty
, binfo
, json_path
);
8097 #if defined(HAVE_CUMULUS)
8098 if (binfo
->extra
&& bgp_is_valid_label(&binfo
->extra
->label
[0])
8099 && safi
!= SAFI_EVPN
)
8101 if (binfo
->extra
&& bgp_is_valid_label(&binfo
->extra
->label
[0]))
8104 mpls_label_t label
=
8105 label_pton(&binfo
->extra
->label
[0]);
8107 json_object_int_add(json_path
, "remoteLabel",
8110 vty_out(vty
, " Remote label: %d\n", label
);
8114 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
8116 json_object_int_add(json_path
, "labelIndex",
8119 vty_out(vty
, " Label Index: %d\n",
8123 /* Line 8 display Addpath IDs */
8124 if (binfo
->addpath_rx_id
|| binfo
->addpath_tx_id
) {
8126 json_object_int_add(json_path
, "addpathRxId",
8127 binfo
->addpath_rx_id
);
8128 json_object_int_add(json_path
, "addpathTxId",
8129 binfo
->addpath_tx_id
);
8131 vty_out(vty
, " AddPath ID: RX %u, TX %u\n",
8132 binfo
->addpath_rx_id
,
8133 binfo
->addpath_tx_id
);
8137 /* If we used addpath to TX a non-bestpath we need to display
8138 * "Advertised to" on a path-by-path basis */
8139 if (bgp
->addpath_tx_used
[afi
][safi
]) {
8142 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
8144 bgp_addpath_encode_tx(peer
, afi
, safi
);
8145 has_adj
= bgp_adj_out_lookup(
8146 peer
, binfo
->net
, binfo
->addpath_tx_id
);
8148 if ((addpath_capable
&& has_adj
)
8149 || (!addpath_capable
&& has_adj
8150 && CHECK_FLAG(binfo
->flags
,
8151 BGP_INFO_SELECTED
))) {
8152 if (json_path
&& !json_adv_to
)
8154 json_object_new_object();
8156 route_vty_out_advertised_to(
8165 json_object_object_add(json_path
,
8176 /* Line 9 display Uptime */
8177 tbuf
= time(NULL
) - (bgp_clock() - binfo
->uptime
);
8179 json_last_update
= json_object_new_object();
8180 json_object_int_add(json_last_update
, "epoch", tbuf
);
8181 json_object_string_add(json_last_update
, "string",
8183 json_object_object_add(json_path
, "lastUpdate",
8186 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
8188 /* Line 10 display PMSI tunnel attribute, if present */
8189 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
8190 const char *str
= lookup_msg(bgp_pmsi_tnltype_str
,
8191 attr
->pmsi_tnl_type
,
8192 PMSI_TNLTYPE_STR_DEFAULT
);
8195 json_pmsi
= json_object_new_object();
8196 json_object_string_add(json_pmsi
,
8198 json_object_object_add(json_path
, "pmsi",
8201 vty_out(vty
, " PMSI Tunnel Type: %s\n",
8207 /* We've constructed the json object for this path, add it to the json
8211 if (json_nexthop_global
|| json_nexthop_ll
) {
8212 json_nexthops
= json_object_new_array();
8214 if (json_nexthop_global
)
8215 json_object_array_add(json_nexthops
,
8216 json_nexthop_global
);
8218 if (json_nexthop_ll
)
8219 json_object_array_add(json_nexthops
,
8222 json_object_object_add(json_path
, "nexthops",
8226 json_object_object_add(json_path
, "peer", json_peer
);
8227 json_object_array_add(json_paths
, json_path
);
8232 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
8233 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
8234 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
8236 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
8237 const char *prefix_list_str
, afi_t afi
,
8238 safi_t safi
, enum bgp_show_type type
);
8239 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
8240 const char *filter
, afi_t afi
, safi_t safi
,
8241 enum bgp_show_type type
);
8242 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
8243 const char *rmap_str
, afi_t afi
, safi_t safi
,
8244 enum bgp_show_type type
);
8245 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
8246 const char *com
, int exact
, afi_t afi
,
8248 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
8249 const char *prefix
, afi_t afi
, safi_t safi
,
8250 enum bgp_show_type type
);
8251 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
8252 afi_t afi
, safi_t safi
, enum bgp_show_type type
);
8253 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
8254 const char *comstr
, int exact
, afi_t afi
,
8258 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
8259 struct bgp_table
*table
, enum bgp_show_type type
,
8260 void *output_arg
, uint8_t use_json
, char *rd
,
8261 int is_last
, unsigned long *output_cum
,
8262 unsigned long *total_cum
,
8263 unsigned long *json_header_depth
)
8265 struct bgp_info
*ri
;
8266 struct bgp_node
*rn
;
8269 unsigned long output_count
= 0;
8270 unsigned long total_count
= 0;
8274 json_object
*json_paths
= NULL
;
8277 if (output_cum
&& *output_cum
!= 0)
8280 if (use_json
&& !*json_header_depth
) {
8282 "{\n \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
8283 ",\n \"routerId\": \"%s\",\n \"routes\": { ",
8284 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
8285 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
? "Default"
8287 table
->version
, inet_ntoa(bgp
->router_id
));
8288 *json_header_depth
= 2;
8290 vty_out(vty
, " \"routeDistinguishers\" : {");
8291 ++*json_header_depth
;
8293 json_paths
= json_object_new_object();
8296 if (use_json
&& rd
) {
8297 vty_out(vty
, " \"%s\" : { ", rd
);
8300 /* Start processing of routes. */
8301 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
8302 if (rn
->info
== NULL
)
8307 json_paths
= json_object_new_array();
8311 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
8313 if (type
== bgp_show_type_flap_statistics
8314 || type
== bgp_show_type_flap_neighbor
8315 || type
== bgp_show_type_dampend_paths
8316 || type
== bgp_show_type_damp_neighbor
) {
8317 if (!(ri
->extra
&& ri
->extra
->damp_info
))
8320 if (type
== bgp_show_type_regexp
) {
8321 regex_t
*regex
= output_arg
;
8323 if (bgp_regexec(regex
, ri
->attr
->aspath
)
8327 if (type
== bgp_show_type_prefix_list
) {
8328 struct prefix_list
*plist
= output_arg
;
8330 if (prefix_list_apply(plist
, &rn
->p
)
8334 if (type
== bgp_show_type_filter_list
) {
8335 struct as_list
*as_list
= output_arg
;
8337 if (as_list_apply(as_list
, ri
->attr
->aspath
)
8338 != AS_FILTER_PERMIT
)
8341 if (type
== bgp_show_type_route_map
) {
8342 struct route_map
*rmap
= output_arg
;
8343 struct bgp_info binfo
;
8344 struct attr dummy_attr
;
8347 bgp_attr_dup(&dummy_attr
, ri
->attr
);
8349 binfo
.peer
= ri
->peer
;
8350 binfo
.attr
= &dummy_attr
;
8352 ret
= route_map_apply(rmap
, &rn
->p
, RMAP_BGP
,
8354 if (ret
== RMAP_DENYMATCH
)
8357 if (type
== bgp_show_type_neighbor
8358 || type
== bgp_show_type_flap_neighbor
8359 || type
== bgp_show_type_damp_neighbor
) {
8360 union sockunion
*su
= output_arg
;
8362 if (ri
->peer
== NULL
8363 || ri
->peer
->su_remote
== NULL
8364 || !sockunion_same(ri
->peer
->su_remote
, su
))
8367 if (type
== bgp_show_type_cidr_only
) {
8368 uint32_t destination
;
8370 destination
= ntohl(rn
->p
.u
.prefix4
.s_addr
);
8371 if (IN_CLASSC(destination
)
8372 && rn
->p
.prefixlen
== 24)
8374 if (IN_CLASSB(destination
)
8375 && rn
->p
.prefixlen
== 16)
8377 if (IN_CLASSA(destination
)
8378 && rn
->p
.prefixlen
== 8)
8381 if (type
== bgp_show_type_prefix_longer
) {
8382 struct prefix
*p
= output_arg
;
8384 if (!prefix_match(p
, &rn
->p
))
8387 if (type
== bgp_show_type_community_all
) {
8388 if (!ri
->attr
->community
)
8391 if (type
== bgp_show_type_community
) {
8392 struct community
*com
= output_arg
;
8394 if (!ri
->attr
->community
8395 || !community_match(ri
->attr
->community
,
8399 if (type
== bgp_show_type_community_exact
) {
8400 struct community
*com
= output_arg
;
8402 if (!ri
->attr
->community
8403 || !community_cmp(ri
->attr
->community
, com
))
8406 if (type
== bgp_show_type_community_list
) {
8407 struct community_list
*list
= output_arg
;
8409 if (!community_list_match(ri
->attr
->community
,
8413 if (type
== bgp_show_type_community_list_exact
) {
8414 struct community_list
*list
= output_arg
;
8416 if (!community_list_exact_match(
8417 ri
->attr
->community
, list
))
8420 if (type
== bgp_show_type_lcommunity
) {
8421 struct lcommunity
*lcom
= output_arg
;
8423 if (!ri
->attr
->lcommunity
8424 || !lcommunity_match(ri
->attr
->lcommunity
,
8428 if (type
== bgp_show_type_lcommunity_list
) {
8429 struct community_list
*list
= output_arg
;
8431 if (!lcommunity_list_match(ri
->attr
->lcommunity
,
8435 if (type
== bgp_show_type_lcommunity_all
) {
8436 if (!ri
->attr
->lcommunity
)
8439 if (type
== bgp_show_type_dampend_paths
8440 || type
== bgp_show_type_damp_neighbor
) {
8441 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_DAMPED
)
8442 || CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
8446 if (!use_json
&& header
) {
8447 vty_out(vty
, "BGP table version is %" PRIu64
8448 ", local router ID is %s, vrf id ",
8450 inet_ntoa(bgp
->router_id
));
8451 if (bgp
->vrf_id
== VRF_UNKNOWN
)
8452 vty_out(vty
, "%s", VRFID_NONE_STR
);
8454 vty_out(vty
, "%u", bgp
->vrf_id
);
8456 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
8457 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
8458 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
8459 if (type
== bgp_show_type_dampend_paths
8460 || type
== bgp_show_type_damp_neighbor
)
8461 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
8462 else if (type
== bgp_show_type_flap_statistics
8463 || type
== bgp_show_type_flap_neighbor
)
8464 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
8466 vty_out(vty
, BGP_SHOW_HEADER
);
8469 if (rd
!= NULL
&& !display
&& !output_count
) {
8472 "Route Distinguisher: %s\n",
8475 if (type
== bgp_show_type_dampend_paths
8476 || type
== bgp_show_type_damp_neighbor
)
8477 damp_route_vty_out(vty
, &rn
->p
, ri
, display
,
8478 safi
, use_json
, json_paths
);
8479 else if (type
== bgp_show_type_flap_statistics
8480 || type
== bgp_show_type_flap_neighbor
)
8481 flap_route_vty_out(vty
, &rn
->p
, ri
, display
,
8482 safi
, use_json
, json_paths
);
8484 route_vty_out(vty
, &rn
->p
, ri
, display
, safi
,
8495 sprintf(buf2
, "%s/%d",
8496 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
8499 vty_out(vty
, "\"%s\": ", buf2
);
8501 vty_out(vty
, ",\"%s\": ", buf2
);
8504 json_object_to_json_string(json_paths
));
8505 json_object_free(json_paths
);
8512 output_count
+= *output_cum
;
8513 *output_cum
= output_count
;
8516 total_count
+= *total_cum
;
8517 *total_cum
= total_count
;
8521 json_object_free(json_paths
);
8523 vty_out(vty
, " }%s ", (is_last
? "" : ","));
8527 for (i
= 0; i
< *json_header_depth
; ++i
)
8528 vty_out(vty
, " } ");
8532 /* No route is displayed */
8533 if (output_count
== 0) {
8534 if (type
== bgp_show_type_normal
)
8536 "No BGP prefixes displayed, %ld exist\n",
8540 "\nDisplayed %ld routes and %ld total paths\n",
8541 output_count
, total_count
);
8548 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
8549 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
8550 enum bgp_show_type type
, void *output_arg
,
8553 struct bgp_node
*rn
, *next
;
8554 unsigned long output_cum
= 0;
8555 unsigned long total_cum
= 0;
8556 unsigned long json_header_depth
= 0;
8559 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
8561 for (rn
= bgp_table_top(table
); rn
; rn
= next
) {
8562 next
= bgp_route_next(rn
);
8563 if (prd_match
&& memcmp(rn
->p
.u
.val
, prd_match
->val
, 8) != 0)
8565 if (rn
->info
!= NULL
) {
8566 struct prefix_rd prd
;
8567 char rd
[RD_ADDRSTRLEN
];
8569 memcpy(&prd
, &(rn
->p
), sizeof(struct prefix_rd
));
8570 prefix_rd2str(&prd
, rd
, sizeof(rd
));
8571 bgp_show_table(vty
, bgp
, safi
, rn
->info
, type
,
8572 output_arg
, use_json
, rd
, next
== NULL
,
8573 &output_cum
, &total_cum
,
8574 &json_header_depth
);
8580 if (output_cum
== 0)
8581 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
8585 "\nDisplayed %ld routes and %ld total paths\n",
8586 output_cum
, total_cum
);
8590 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
8591 enum bgp_show_type type
, void *output_arg
, uint8_t use_json
)
8593 struct bgp_table
*table
;
8594 unsigned long json_header_depth
= 0;
8597 bgp
= bgp_get_default();
8602 vty_out(vty
, "No BGP process is configured\n");
8604 vty_out(vty
, "{}\n");
8608 table
= bgp
->rib
[afi
][safi
];
8609 /* use MPLS and ENCAP specific shows until they are merged */
8610 if (safi
== SAFI_MPLS_VPN
) {
8611 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
8612 output_arg
, use_json
);
8615 if (safi
== SAFI_FLOWSPEC
&& type
== bgp_show_type_detail
) {
8616 return bgp_show_table_flowspec(vty
, bgp
, afi
, table
, type
,
8617 output_arg
, use_json
,
8620 /* labeled-unicast routes live in the unicast table */
8621 else if (safi
== SAFI_LABELED_UNICAST
)
8622 safi
= SAFI_UNICAST
;
8624 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, use_json
,
8625 NULL
, 1, NULL
, NULL
, &json_header_depth
);
8628 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
8629 safi_t safi
, uint8_t use_json
)
8631 struct listnode
*node
, *nnode
;
8636 vty_out(vty
, "{\n");
8638 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
8641 vty_out(vty
, ",\n");
8645 vty_out(vty
, "\"%s\":",
8646 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
8650 vty_out(vty
, "\nInstance %s:\n",
8651 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
8655 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
8660 vty_out(vty
, "}\n");
8663 /* Header of detailed BGP route information */
8664 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
8665 struct bgp_node
*rn
, struct prefix_rd
*prd
,
8666 afi_t afi
, safi_t safi
, json_object
*json
)
8668 struct bgp_info
*ri
;
8671 struct listnode
*node
, *nnode
;
8672 char buf1
[RD_ADDRSTRLEN
];
8673 char buf2
[INET6_ADDRSTRLEN
];
8674 #if defined(HAVE_CUMULUS)
8675 char buf3
[EVPN_ROUTE_STRLEN
];
8677 char prefix_str
[BUFSIZ
];
8682 int no_advertise
= 0;
8685 int has_valid_label
= 0;
8686 mpls_label_t label
= 0;
8687 json_object
*json_adv_to
= NULL
;
8690 has_valid_label
= bgp_is_valid_label(&rn
->local_label
);
8692 if (has_valid_label
)
8693 label
= label_pton(&rn
->local_label
);
8696 if (has_valid_label
)
8697 json_object_int_add(json
, "localLabel", label
);
8699 json_object_string_add(
8701 prefix2str(p
, prefix_str
, sizeof(prefix_str
)));
8703 #if defined(HAVE_CUMULUS)
8704 if (safi
== SAFI_EVPN
)
8705 vty_out(vty
, "BGP routing table entry for %s%s%s\n",
8706 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
))
8709 bgp_evpn_route2str((struct prefix_evpn
*)p
,
8710 buf3
, sizeof(buf3
)));
8712 vty_out(vty
, "BGP routing table entry for %s%s%s/%d\n",
8713 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
8714 ? prefix_rd2str(prd
, buf1
,
8717 safi
== SAFI_MPLS_VPN
? ":" : "",
8718 inet_ntop(p
->family
, &p
->u
.prefix
, buf2
,
8722 if (p
->family
== AF_ETHERNET
)
8723 prefix2str(p
, buf2
, INET6_ADDRSTRLEN
);
8725 inet_ntop(p
->family
, &p
->u
.prefix
, buf2
,
8727 vty_out(vty
, "BGP routing table entry for %s%s%s/%d\n",
8728 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
8729 || safi
== SAFI_EVPN
)
8730 ? prefix_rd2str(prd
, buf1
, sizeof(buf1
))
8732 ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_EVPN
)) ? ":"
8734 buf2
, p
->prefixlen
);
8737 if (has_valid_label
)
8738 vty_out(vty
, "Local label: %d\n", label
);
8739 #if defined(HAVE_CUMULUS)
8740 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
8742 if (bgp_labeled_safi(safi
))
8744 vty_out(vty
, "not allocated\n");
8747 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
8749 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
8751 if (ri
->extra
&& ri
->extra
->suppress
)
8753 if (ri
->attr
->community
!= NULL
) {
8754 if (community_include(ri
->attr
->community
,
8755 COMMUNITY_NO_ADVERTISE
))
8757 if (community_include(ri
->attr
->community
,
8758 COMMUNITY_NO_EXPORT
))
8760 if (community_include(ri
->attr
->community
,
8761 COMMUNITY_LOCAL_AS
))
8768 vty_out(vty
, "Paths: (%d available", count
);
8770 vty_out(vty
, ", best #%d", best
);
8771 if (safi
== SAFI_UNICAST
)
8772 vty_out(vty
, ", table %s",
8774 == BGP_INSTANCE_TYPE_DEFAULT
)
8775 ? "Default-IP-Routing-Table"
8778 vty_out(vty
, ", no best path");
8781 vty_out(vty
, ", not advertised to any peer");
8783 vty_out(vty
, ", not advertised to EBGP peer");
8785 vty_out(vty
, ", not advertised outside local AS");
8789 ", Advertisements suppressed by an aggregate.");
8790 vty_out(vty
, ")\n");
8793 /* If we are not using addpath then we can display Advertised to and
8795 * show what peers we advertised the bestpath to. If we are using
8797 * though then we must display Advertised to on a path-by-path basis. */
8798 if (!bgp
->addpath_tx_used
[afi
][safi
]) {
8799 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
8800 if (bgp_adj_out_lookup(peer
, rn
, 0)) {
8801 if (json
&& !json_adv_to
)
8802 json_adv_to
= json_object_new_object();
8804 route_vty_out_advertised_to(
8806 " Advertised to non peer-group peers:\n ",
8813 json_object_object_add(json
, "advertisedTo",
8818 vty_out(vty
, " Not advertised to any peer");
8824 /* Display specified route of BGP table. */
8825 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
8826 struct bgp_table
*rib
, const char *ip_str
,
8827 afi_t afi
, safi_t safi
,
8828 struct prefix_rd
*prd
, int prefix_check
,
8829 enum bgp_path_type pathtype
,
8835 struct prefix match
;
8836 struct bgp_node
*rn
;
8837 struct bgp_node
*rm
;
8838 struct bgp_info
*ri
;
8839 struct bgp_table
*table
;
8840 json_object
*json
= NULL
;
8841 json_object
*json_paths
= NULL
;
8843 /* Check IP address argument. */
8844 ret
= str2prefix(ip_str
, &match
);
8846 vty_out(vty
, "address is malformed\n");
8850 match
.family
= afi2family(afi
);
8853 json
= json_object_new_object();
8854 json_paths
= json_object_new_array();
8857 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
8858 for (rn
= bgp_table_top(rib
); rn
; rn
= bgp_route_next(rn
)) {
8859 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
8862 if ((table
= rn
->info
) == NULL
)
8867 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
8871 && rm
->p
.prefixlen
!= match
.prefixlen
) {
8872 bgp_unlock_node(rm
);
8876 for (ri
= rm
->info
; ri
; ri
= ri
->next
) {
8878 route_vty_out_detail_header(
8880 (struct prefix_rd
*)&rn
->p
,
8881 AFI_IP
, safi
, json
);
8886 if (pathtype
== BGP_PATH_ALL
8887 || (pathtype
== BGP_PATH_BESTPATH
8888 && CHECK_FLAG(ri
->flags
,
8890 || (pathtype
== BGP_PATH_MULTIPATH
8891 && (CHECK_FLAG(ri
->flags
,
8893 || CHECK_FLAG(ri
->flags
,
8894 BGP_INFO_SELECTED
))))
8895 route_vty_out_detail(vty
, bgp
, &rm
->p
,
8900 bgp_unlock_node(rm
);
8902 } else if (safi
== SAFI_FLOWSPEC
) {
8903 rn
= bgp_flowspec_get_match_per_ip(afi
, rib
,
8904 &match
, prefix_check
);
8906 route_vty_out_flowspec(vty
, &rn
->p
,
8907 rn
->info
, use_json
?
8908 NLRI_STRING_FORMAT_JSON
:
8909 NLRI_STRING_FORMAT_LARGE
,
8912 bgp_unlock_node(rn
);
8917 if ((rn
= bgp_node_match(rib
, &match
)) != NULL
) {
8919 || rn
->p
.prefixlen
== match
.prefixlen
) {
8920 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
8922 route_vty_out_detail_header(
8923 vty
, bgp
, rn
, NULL
, afi
,
8929 if (pathtype
== BGP_PATH_ALL
8930 || (pathtype
== BGP_PATH_BESTPATH
8934 || (pathtype
== BGP_PATH_MULTIPATH
8940 BGP_INFO_SELECTED
))))
8941 route_vty_out_detail(
8942 vty
, bgp
, &rn
->p
, ri
,
8943 afi
, safi
, json_paths
);
8947 bgp_unlock_node(rn
);
8953 json_object_object_add(json
, "paths", json_paths
);
8955 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
8956 json
, JSON_C_TO_STRING_PRETTY
));
8957 json_object_free(json
);
8960 vty_out(vty
, "%% Network not in table\n");
8968 /* Display specified route of Main RIB */
8969 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
8970 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
8971 int prefix_check
, enum bgp_path_type pathtype
,
8975 bgp
= bgp_get_default();
8978 vty_out(vty
, "No BGP process is configured\n");
8980 vty_out(vty
, "{}\n");
8985 /* labeled-unicast routes live in the unicast table */
8986 if (safi
== SAFI_LABELED_UNICAST
)
8987 safi
= SAFI_UNICAST
;
8989 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
8990 afi
, safi
, prd
, prefix_check
, pathtype
,
8994 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
8995 struct cmd_token
**argv
, afi_t afi
, safi_t safi
,
8998 struct lcommunity
*lcom
;
9004 b
= buffer_new(1024);
9005 for (i
= 0; i
< argc
; i
++) {
9007 buffer_putc(b
, ' ');
9009 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
9011 buffer_putstr(b
, argv
[i
]->arg
);
9015 buffer_putc(b
, '\0');
9017 str
= buffer_getstr(b
);
9020 lcom
= lcommunity_str2com(str
);
9021 XFREE(MTYPE_TMP
, str
);
9023 vty_out(vty
, "%% Large-community malformed\n");
9027 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_lcommunity
, lcom
,
9031 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
9032 const char *lcom
, afi_t afi
, safi_t safi
,
9035 struct community_list
*list
;
9037 list
= community_list_lookup(bgp_clist
, lcom
,
9038 LARGE_COMMUNITY_LIST_MASTER
);
9040 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
9045 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_lcommunity_list
,
9049 DEFUN (show_ip_bgp_large_community_list
,
9050 show_ip_bgp_large_community_list_cmd
,
9051 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community-list <(1-500)|WORD> [json]",
9055 BGP_INSTANCE_HELP_STR
9057 BGP_SAFI_WITH_LABEL_HELP_STR
9058 "Display routes matching the large-community-list\n"
9059 "large-community-list number\n"
9060 "large-community-list name\n"
9064 afi_t afi
= AFI_IP6
;
9065 safi_t safi
= SAFI_UNICAST
;
9068 if (argv_find(argv
, argc
, "ip", &idx
))
9070 if (argv_find(argv
, argc
, "view", &idx
)
9071 || argv_find(argv
, argc
, "vrf", &idx
))
9072 vrf
= argv
[++idx
]->arg
;
9073 if (argv_find(argv
, argc
, "ipv4", &idx
)
9074 || argv_find(argv
, argc
, "ipv6", &idx
)) {
9075 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
9076 if (argv_find(argv
, argc
, "unicast", &idx
)
9077 || argv_find(argv
, argc
, "multicast", &idx
))
9078 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
9081 int uj
= use_json(argc
, argv
);
9083 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
9085 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
9089 argv_find(argv
, argc
, "large-community-list", &idx
);
9090 return bgp_show_lcommunity_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
, safi
,
9093 DEFUN (show_ip_bgp_large_community
,
9094 show_ip_bgp_large_community_cmd
,
9095 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [AA:BB:CC] [json]",
9099 BGP_INSTANCE_HELP_STR
9101 BGP_SAFI_WITH_LABEL_HELP_STR
9102 "Display routes matching the large-communities\n"
9103 "List of large-community numbers\n"
9107 afi_t afi
= AFI_IP6
;
9108 safi_t safi
= SAFI_UNICAST
;
9111 if (argv_find(argv
, argc
, "ip", &idx
))
9113 if (argv_find(argv
, argc
, "view", &idx
)
9114 || argv_find(argv
, argc
, "vrf", &idx
))
9115 vrf
= argv
[++idx
]->arg
;
9116 if (argv_find(argv
, argc
, "ipv4", &idx
)
9117 || argv_find(argv
, argc
, "ipv6", &idx
)) {
9118 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
9119 if (argv_find(argv
, argc
, "unicast", &idx
)
9120 || argv_find(argv
, argc
, "multicast", &idx
))
9121 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
9124 int uj
= use_json(argc
, argv
);
9126 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
9128 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
9132 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
))
9133 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
, afi
, safi
, uj
);
9135 return bgp_show(vty
, bgp
, afi
, safi
,
9136 bgp_show_type_lcommunity_all
, NULL
, uj
);
9139 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
9143 /* BGP route print out function without JSON */
9146 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
9147 <dampening <parameters>\
9152 |community <AA:NN|local-AS|no-advertise|no-export|graceful-shutdown> [exact-match]\
9153 |community-list <(1-500)|WORD> [exact-match]\
9154 |A.B.C.D/M longer-prefixes\
9155 |X:X::X:X/M longer-prefixes\
9160 BGP_INSTANCE_HELP_STR
9162 BGP_SAFI_WITH_LABEL_HELP_STR
9163 "Display detailed information about dampening\n"
9164 "Display detail of configured dampening parameters\n"
9165 "Display routes matching the route-map\n"
9166 "A route-map to match on\n"
9167 "Display routes conforming to the prefix-list\n"
9168 "Prefix-list name\n"
9169 "Display routes conforming to the filter-list\n"
9170 "Regular expression access list name\n"
9171 "BGP RIB advertisement statistics\n"
9172 "Display routes matching the communities\n"
9174 "Do not send outside local AS (well-known community)\n"
9175 "Do not advertise to any peer (well-known community)\n"
9176 "Do not export to next AS (well-known community)\n"
9177 "Graceful shutdown (well-known community)\n"
9178 "Exact match of the communities\n"
9179 "Display routes matching the community-list\n"
9180 "community-list number\n"
9181 "community-list name\n"
9182 "Exact match of the communities\n"
9184 "Display route and more specific routes\n"
9186 "Display route and more specific routes\n")
9188 afi_t afi
= AFI_IP6
;
9189 safi_t safi
= SAFI_UNICAST
;
9190 int exact_match
= 0;
9191 struct bgp
*bgp
= NULL
;
9193 int idx_community_type
= 0;
9195 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9200 if (argv_find(argv
, argc
, "dampening", &idx
)) {
9201 if (argv_find(argv
, argc
, "parameters", &idx
))
9202 return bgp_show_dampening_parameters(vty
, afi
, safi
);
9205 if (argv_find(argv
, argc
, "prefix-list", &idx
))
9206 return bgp_show_prefix_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9207 safi
, bgp_show_type_prefix_list
);
9209 if (argv_find(argv
, argc
, "filter-list", &idx
))
9210 return bgp_show_filter_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9211 safi
, bgp_show_type_filter_list
);
9213 if (argv_find(argv
, argc
, "statistics", &idx
))
9214 return bgp_table_stats(vty
, bgp
, afi
, safi
);
9216 if (argv_find(argv
, argc
, "route-map", &idx
))
9217 return bgp_show_route_map(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9218 safi
, bgp_show_type_route_map
);
9220 if (argv_find(argv
, argc
, "community", &idx
)) {
9221 /* show a specific community */
9222 if (argv_find(argv
, argc
, "local-AS", &idx_community_type
)
9223 || argv_find(argv
, argc
, "no-advertise",
9224 &idx_community_type
)
9225 || argv_find(argv
, argc
, "no-export", &idx_community_type
)
9226 || argv_find(argv
, argc
, "graceful-shutdown",
9227 &idx_community_type
)
9228 || argv_find(argv
, argc
, "AA:NN", &idx_community_type
)) {
9230 if (argv_find(argv
, argc
, "exact-match", &idx
))
9232 return bgp_show_community(vty
, bgp
,
9233 argv
[idx_community_type
]->arg
,
9234 exact_match
, afi
, safi
);
9238 if (argv_find(argv
, argc
, "community-list", &idx
)) {
9239 const char *clist_number_or_name
= argv
[++idx
]->arg
;
9240 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
9242 return bgp_show_community_list(vty
, bgp
, clist_number_or_name
,
9243 exact_match
, afi
, safi
);
9246 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
9247 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
9248 return bgp_show_prefix_longer(vty
, bgp
, argv
[idx
]->arg
, afi
,
9250 bgp_show_type_prefix_longer
);
9255 /* BGP route print out function with JSON */
9256 DEFUN (show_ip_bgp_json
,
9257 show_ip_bgp_json_cmd
,
9258 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
9261 |dampening <flap-statistics|dampened-paths>\
9267 BGP_INSTANCE_HELP_STR
9269 BGP_SAFI_WITH_LABEL_HELP_STR
9270 "Display only routes with non-natural netmasks\n"
9271 "Display detailed information about dampening\n"
9272 "Display flap statistics of routes\n"
9273 "Display paths suppressed due to dampening\n"
9274 "Display routes matching the communities\n"
9277 afi_t afi
= AFI_IP6
;
9278 safi_t safi
= SAFI_UNICAST
;
9279 enum bgp_show_type sh_type
= bgp_show_type_normal
;
9280 struct bgp
*bgp
= NULL
;
9283 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9288 int uj
= use_json(argc
, argv
);
9292 if (argv_find(argv
, argc
, "cidr-only", &idx
))
9293 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_cidr_only
,
9296 if (argv_find(argv
, argc
, "dampening", &idx
)) {
9297 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
9298 return bgp_show(vty
, bgp
, afi
, safi
,
9299 bgp_show_type_dampend_paths
, NULL
, uj
);
9300 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
9301 return bgp_show(vty
, bgp
, afi
, safi
,
9302 bgp_show_type_flap_statistics
, NULL
,
9306 if (argv_find(argv
, argc
, "community", &idx
)) {
9307 /* show all communities */
9308 return bgp_show(vty
, bgp
, afi
, safi
,
9309 bgp_show_type_community_all
, NULL
, uj
);
9311 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
, NULL
, uj
);
9314 DEFUN (show_ip_bgp_route
,
9315 show_ip_bgp_route_cmd
,
9316 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]"
9317 "<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [json]",
9321 BGP_INSTANCE_HELP_STR
9323 BGP_SAFI_WITH_LABEL_HELP_STR
9324 "Network in the BGP routing table to display\n"
9326 "Network in the BGP routing table to display\n"
9328 "Display only the bestpath\n"
9329 "Display only multipaths\n"
9332 int prefix_check
= 0;
9334 afi_t afi
= AFI_IP6
;
9335 safi_t safi
= SAFI_UNICAST
;
9336 char *prefix
= NULL
;
9337 struct bgp
*bgp
= NULL
;
9338 enum bgp_path_type path_type
;
9339 uint8_t uj
= use_json(argc
, argv
);
9343 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9350 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
9354 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
9355 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
9356 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
9358 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
9359 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
9362 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
9363 && afi
!= AFI_IP6
) {
9365 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
9368 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
9371 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
9375 prefix
= argv
[idx
]->arg
;
9377 /* [<bestpath|multipath>] */
9378 if (argv_find(argv
, argc
, "bestpath", &idx
))
9379 path_type
= BGP_PATH_BESTPATH
;
9380 else if (argv_find(argv
, argc
, "multipath", &idx
))
9381 path_type
= BGP_PATH_MULTIPATH
;
9383 path_type
= BGP_PATH_ALL
;
9385 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
9389 DEFUN (show_ip_bgp_regexp
,
9390 show_ip_bgp_regexp_cmd
,
9391 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX...",
9395 BGP_INSTANCE_HELP_STR
9397 BGP_SAFI_WITH_LABEL_HELP_STR
9398 "Display routes matching the AS path regular expression\n"
9399 "A regular-expression to match the BGP AS paths\n")
9401 afi_t afi
= AFI_IP6
;
9402 safi_t safi
= SAFI_UNICAST
;
9403 struct bgp
*bgp
= NULL
;
9406 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9411 // get index of regex
9412 argv_find(argv
, argc
, "regexp", &idx
);
9415 char *regstr
= argv_concat(argv
, argc
, idx
);
9416 int rc
= bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
9417 bgp_show_type_regexp
);
9418 XFREE(MTYPE_TMP
, regstr
);
9422 DEFUN (show_ip_bgp_instance_all
,
9423 show_ip_bgp_instance_all_cmd
,
9424 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json]",
9428 BGP_INSTANCE_ALL_HELP_STR
9430 BGP_SAFI_WITH_LABEL_HELP_STR
9434 safi_t safi
= SAFI_UNICAST
;
9435 struct bgp
*bgp
= NULL
;
9438 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9443 int uj
= use_json(argc
, argv
);
9447 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, uj
);
9451 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
9452 afi_t afi
, safi_t safi
, enum bgp_show_type type
)
9457 regex
= bgp_regcomp(regstr
);
9459 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
9463 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, 0);
9464 bgp_regex_free(regex
);
9468 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
9469 const char *prefix_list_str
, afi_t afi
,
9470 safi_t safi
, enum bgp_show_type type
)
9472 struct prefix_list
*plist
;
9474 plist
= prefix_list_lookup(afi
, prefix_list_str
);
9475 if (plist
== NULL
) {
9476 vty_out(vty
, "%% %s is not a valid prefix-list name\n",
9481 return bgp_show(vty
, bgp
, afi
, safi
, type
, plist
, 0);
9484 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
9485 const char *filter
, afi_t afi
, safi_t safi
,
9486 enum bgp_show_type type
)
9488 struct as_list
*as_list
;
9490 as_list
= as_list_lookup(filter
);
9491 if (as_list
== NULL
) {
9492 vty_out(vty
, "%% %s is not a valid AS-path access-list name\n",
9497 return bgp_show(vty
, bgp
, afi
, safi
, type
, as_list
, 0);
9500 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
9501 const char *rmap_str
, afi_t afi
, safi_t safi
,
9502 enum bgp_show_type type
)
9504 struct route_map
*rmap
;
9506 rmap
= route_map_lookup_by_name(rmap_str
);
9508 vty_out(vty
, "%% %s is not a valid route-map name\n", rmap_str
);
9512 return bgp_show(vty
, bgp
, afi
, safi
, type
, rmap
, 0);
9515 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
9516 const char *comstr
, int exact
, afi_t afi
,
9519 struct community
*com
;
9522 com
= community_str2com(comstr
);
9524 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
9528 ret
= bgp_show(vty
, bgp
, afi
, safi
,
9529 (exact
? bgp_show_type_community_exact
9530 : bgp_show_type_community
),
9532 community_free(com
);
9537 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
9538 const char *com
, int exact
, afi_t afi
,
9541 struct community_list
*list
;
9543 list
= community_list_lookup(bgp_clist
, com
, COMMUNITY_LIST_MASTER
);
9545 vty_out(vty
, "%% %s is not a valid community-list name\n", com
);
9549 return bgp_show(vty
, bgp
, afi
, safi
,
9550 (exact
? bgp_show_type_community_list_exact
9551 : bgp_show_type_community_list
),
9555 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
9556 const char *prefix
, afi_t afi
, safi_t safi
,
9557 enum bgp_show_type type
)
9564 ret
= str2prefix(prefix
, p
);
9566 vty_out(vty
, "%% Malformed Prefix\n");
9570 ret
= bgp_show(vty
, bgp
, afi
, safi
, type
, p
, 0);
9575 static struct peer
*peer_lookup_in_view(struct vty
*vty
, struct bgp
*bgp
,
9576 const char *ip_str
, uint8_t use_json
)
9582 /* Get peer sockunion. */
9583 ret
= str2sockunion(ip_str
, &su
);
9585 peer
= peer_lookup_by_conf_if(bgp
, ip_str
);
9587 peer
= peer_lookup_by_hostname(bgp
, ip_str
);
9591 json_object
*json_no
= NULL
;
9592 json_no
= json_object_new_object();
9593 json_object_string_add(
9595 "malformedAddressOrName",
9597 vty_out(vty
, "%s\n",
9598 json_object_to_json_string_ext(
9600 JSON_C_TO_STRING_PRETTY
));
9601 json_object_free(json_no
);
9604 "%% Malformed address or name: %s\n",
9612 /* Peer structure lookup. */
9613 peer
= peer_lookup(bgp
, &su
);
9616 json_object
*json_no
= NULL
;
9617 json_no
= json_object_new_object();
9618 json_object_string_add(json_no
, "warning",
9619 "No such neighbor");
9620 vty_out(vty
, "%s\n",
9621 json_object_to_json_string_ext(
9622 json_no
, JSON_C_TO_STRING_PRETTY
));
9623 json_object_free(json_no
);
9625 vty_out(vty
, "No such neighbor\n");
9633 BGP_STATS_MAXBITLEN
= 0,
9637 BGP_STATS_UNAGGREGATEABLE
,
9638 BGP_STATS_MAX_AGGREGATEABLE
,
9639 BGP_STATS_AGGREGATES
,
9641 BGP_STATS_ASPATH_COUNT
,
9642 BGP_STATS_ASPATH_MAXHOPS
,
9643 BGP_STATS_ASPATH_TOTHOPS
,
9644 BGP_STATS_ASPATH_MAXSIZE
,
9645 BGP_STATS_ASPATH_TOTSIZE
,
9646 BGP_STATS_ASN_HIGHEST
,
9650 static const char *table_stats_strs
[] = {
9651 [BGP_STATS_PREFIXES
] = "Total Prefixes",
9652 [BGP_STATS_TOTPLEN
] = "Average prefix length",
9653 [BGP_STATS_RIB
] = "Total Advertisements",
9654 [BGP_STATS_UNAGGREGATEABLE
] = "Unaggregateable prefixes",
9655 [BGP_STATS_MAX_AGGREGATEABLE
] =
9656 "Maximum aggregateable prefixes",
9657 [BGP_STATS_AGGREGATES
] = "BGP Aggregate advertisements",
9658 [BGP_STATS_SPACE
] = "Address space advertised",
9659 [BGP_STATS_ASPATH_COUNT
] = "Advertisements with paths",
9660 [BGP_STATS_ASPATH_MAXHOPS
] = "Longest AS-Path (hops)",
9661 [BGP_STATS_ASPATH_MAXSIZE
] = "Largest AS-Path (bytes)",
9662 [BGP_STATS_ASPATH_TOTHOPS
] = "Average AS-Path length (hops)",
9663 [BGP_STATS_ASPATH_TOTSIZE
] = "Average AS-Path size (bytes)",
9664 [BGP_STATS_ASN_HIGHEST
] = "Highest public ASN",
9665 [BGP_STATS_MAX
] = NULL
,
9668 struct bgp_table_stats
{
9669 struct bgp_table
*table
;
9670 unsigned long long counts
[BGP_STATS_MAX
];
9675 #define TALLY_SIGFIG 100000
9676 static unsigned long
9677 ravg_tally (unsigned long count
, unsigned long oldavg
, unsigned long newval
)
9679 unsigned long newtot
= (count
-1) * oldavg
+ (newval
* TALLY_SIGFIG
);
9680 unsigned long res
= (newtot
* TALLY_SIGFIG
) / count
;
9681 unsigned long ret
= newtot
/ count
;
9683 if ((res
% TALLY_SIGFIG
) > (TALLY_SIGFIG
/2))
9690 static int bgp_table_stats_walker(struct thread
*t
)
9692 struct bgp_node
*rn
;
9693 struct bgp_node
*top
;
9694 struct bgp_table_stats
*ts
= THREAD_ARG(t
);
9695 unsigned int space
= 0;
9697 if (!(top
= bgp_table_top(ts
->table
)))
9700 switch (top
->p
.family
) {
9702 space
= IPV4_MAX_BITLEN
;
9705 space
= IPV6_MAX_BITLEN
;
9709 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
9711 for (rn
= top
; rn
; rn
= bgp_route_next(rn
)) {
9712 struct bgp_info
*ri
;
9713 struct bgp_node
*prn
= bgp_node_parent_nolock(rn
);
9714 unsigned int rinum
= 0;
9722 ts
->counts
[BGP_STATS_PREFIXES
]++;
9723 ts
->counts
[BGP_STATS_TOTPLEN
] += rn
->p
.prefixlen
;
9726 ts
->counts
[BGP_STATS_AVGPLEN
]
9727 = ravg_tally (ts
->counts
[BGP_STATS_PREFIXES
],
9728 ts
->counts
[BGP_STATS_AVGPLEN
],
9732 /* check if the prefix is included by any other announcements */
9733 while (prn
&& !prn
->info
)
9734 prn
= bgp_node_parent_nolock(prn
);
9736 if (prn
== NULL
|| prn
== top
) {
9737 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
9738 /* announced address space */
9741 pow(2.0, space
- rn
->p
.prefixlen
);
9742 } else if (prn
->info
)
9743 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
9745 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
9747 ts
->counts
[BGP_STATS_RIB
]++;
9750 && (CHECK_FLAG(ri
->attr
->flag
,
9752 BGP_ATTR_ATOMIC_AGGREGATE
))))
9753 ts
->counts
[BGP_STATS_AGGREGATES
]++;
9756 if (ri
->attr
&& ri
->attr
->aspath
) {
9758 aspath_count_hops(ri
->attr
->aspath
);
9760 aspath_size(ri
->attr
->aspath
);
9761 as_t highest
= aspath_highest(ri
->attr
->aspath
);
9763 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
9765 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
9766 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] =
9769 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
9770 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] =
9773 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
9774 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
9776 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
]
9777 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
9778 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
],
9780 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
]
9781 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
9782 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
],
9785 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
9786 ts
->counts
[BGP_STATS_ASN_HIGHEST
] =
9794 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
9797 struct bgp_table_stats ts
;
9800 if (!bgp
->rib
[afi
][safi
]) {
9801 vty_out(vty
, "%% No RIB exist's for the AFI(%d)/SAFI(%d)\n",
9806 vty_out(vty
, "BGP %s RIB statistics\n", afi_safi_print(afi
, safi
));
9808 /* labeled-unicast routes live in the unicast table */
9809 if (safi
== SAFI_LABELED_UNICAST
)
9810 safi
= SAFI_UNICAST
;
9812 memset(&ts
, 0, sizeof(ts
));
9813 ts
.table
= bgp
->rib
[afi
][safi
];
9814 thread_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
9816 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
9817 if (!table_stats_strs
[i
])
9822 case BGP_STATS_ASPATH_AVGHOPS
:
9823 case BGP_STATS_ASPATH_AVGSIZE
:
9824 case BGP_STATS_AVGPLEN
:
9825 vty_out (vty
, "%-30s: ", table_stats_strs
[i
]);
9826 vty_out (vty
, "%12.2f",
9827 (float)ts
.counts
[i
] / (float)TALLY_SIGFIG
);
9830 case BGP_STATS_ASPATH_TOTHOPS
:
9831 case BGP_STATS_ASPATH_TOTSIZE
:
9832 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9833 vty_out(vty
, "%12.2f",
9835 ? (float)ts
.counts
[i
]
9837 [BGP_STATS_ASPATH_COUNT
]
9840 case BGP_STATS_TOTPLEN
:
9841 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9842 vty_out(vty
, "%12.2f",
9844 ? (float)ts
.counts
[i
]
9846 [BGP_STATS_PREFIXES
]
9849 case BGP_STATS_SPACE
:
9850 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9851 vty_out(vty
, "%12g\n", ts
.total_space
);
9853 if (afi
== AFI_IP6
) {
9854 vty_out(vty
, "%30s: ", "/32 equivalent ");
9855 vty_out(vty
, "%12g\n",
9856 ts
.total_space
* pow(2.0, -128 + 32));
9857 vty_out(vty
, "%30s: ", "/48 equivalent ");
9858 vty_out(vty
, "%12g\n",
9859 ts
.total_space
* pow(2.0, -128 + 48));
9861 vty_out(vty
, "%30s: ", "% announced ");
9862 vty_out(vty
, "%12.2f\n",
9863 ts
.total_space
* 100. * pow(2.0, -32));
9864 vty_out(vty
, "%30s: ", "/8 equivalent ");
9865 vty_out(vty
, "%12.2f\n",
9866 ts
.total_space
* pow(2.0, -32 + 8));
9867 vty_out(vty
, "%30s: ", "/24 equivalent ");
9868 vty_out(vty
, "%12.2f\n",
9869 ts
.total_space
* pow(2.0, -32 + 24));
9873 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9874 vty_out(vty
, "%12llu", ts
.counts
[i
]);
9891 PCOUNT_PFCNT
, /* the figure we display to users */
9895 static const char *pcount_strs
[] = {
9896 [PCOUNT_ADJ_IN
] = "Adj-in",
9897 [PCOUNT_DAMPED
] = "Damped",
9898 [PCOUNT_REMOVED
] = "Removed",
9899 [PCOUNT_HISTORY
] = "History",
9900 [PCOUNT_STALE
] = "Stale",
9901 [PCOUNT_VALID
] = "Valid",
9902 [PCOUNT_ALL
] = "All RIB",
9903 [PCOUNT_COUNTED
] = "PfxCt counted",
9904 [PCOUNT_PFCNT
] = "Useable",
9905 [PCOUNT_MAX
] = NULL
,
9908 struct peer_pcounts
{
9909 unsigned int count
[PCOUNT_MAX
];
9910 const struct peer
*peer
;
9911 const struct bgp_table
*table
;
9914 static int bgp_peer_count_walker(struct thread
*t
)
9916 struct bgp_node
*rn
;
9917 struct peer_pcounts
*pc
= THREAD_ARG(t
);
9918 const struct peer
*peer
= pc
->peer
;
9920 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
)) {
9921 struct bgp_adj_in
*ain
;
9922 struct bgp_info
*ri
;
9924 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
9925 if (ain
->peer
== peer
)
9926 pc
->count
[PCOUNT_ADJ_IN
]++;
9928 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
9929 char buf
[SU_ADDRSTRLEN
];
9931 if (ri
->peer
!= peer
)
9934 pc
->count
[PCOUNT_ALL
]++;
9936 if (CHECK_FLAG(ri
->flags
, BGP_INFO_DAMPED
))
9937 pc
->count
[PCOUNT_DAMPED
]++;
9938 if (CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
9939 pc
->count
[PCOUNT_HISTORY
]++;
9940 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
))
9941 pc
->count
[PCOUNT_REMOVED
]++;
9942 if (CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
))
9943 pc
->count
[PCOUNT_STALE
]++;
9944 if (CHECK_FLAG(ri
->flags
, BGP_INFO_VALID
))
9945 pc
->count
[PCOUNT_VALID
]++;
9946 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
9947 pc
->count
[PCOUNT_PFCNT
]++;
9949 if (CHECK_FLAG(ri
->flags
, BGP_INFO_COUNTED
)) {
9950 pc
->count
[PCOUNT_COUNTED
]++;
9951 if (CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
9953 "%s [pcount] %s/%d is counted but flags 0x%x",
9955 inet_ntop(rn
->p
.family
,
9956 &rn
->p
.u
.prefix
, buf
,
9958 rn
->p
.prefixlen
, ri
->flags
);
9960 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
9962 "%s [pcount] %s/%d not counted but flags 0x%x",
9964 inet_ntop(rn
->p
.family
,
9965 &rn
->p
.u
.prefix
, buf
,
9967 rn
->p
.prefixlen
, ri
->flags
);
9974 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
9975 safi_t safi
, uint8_t use_json
)
9977 struct peer_pcounts pcounts
= {.peer
= peer
};
9979 json_object
*json
= NULL
;
9980 json_object
*json_loop
= NULL
;
9983 json
= json_object_new_object();
9984 json_loop
= json_object_new_object();
9987 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
9988 || !peer
->bgp
->rib
[afi
][safi
]) {
9990 json_object_string_add(
9992 "No such neighbor or address family");
9993 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
9994 json_object_free(json
);
9996 vty_out(vty
, "%% No such neighbor or address family\n");
10001 memset(&pcounts
, 0, sizeof(pcounts
));
10002 pcounts
.peer
= peer
;
10003 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
10005 /* in-place call via thread subsystem so as to record execution time
10006 * stats for the thread-walk (i.e. ensure this can't be blamed on
10007 * on just vty_read()).
10009 thread_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
10012 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
10013 json_object_string_add(json
, "multiProtocol",
10014 afi_safi_print(afi
, safi
));
10015 json_object_int_add(json
, "pfxCounter",
10016 peer
->pcount
[afi
][safi
]);
10018 for (i
= 0; i
< PCOUNT_MAX
; i
++)
10019 json_object_int_add(json_loop
, pcount_strs
[i
],
10022 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
10024 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
10025 json_object_string_add(json
, "pfxctDriftFor",
10027 json_object_string_add(
10028 json
, "recommended",
10029 "Please report this bug, with the above command output");
10031 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
10032 json
, JSON_C_TO_STRING_PRETTY
));
10033 json_object_free(json
);
10037 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
10038 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
10039 peer
->hostname
, peer
->host
,
10040 afi_safi_print(afi
, safi
));
10042 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
10043 afi_safi_print(afi
, safi
));
10046 vty_out(vty
, "PfxCt: %ld\n", peer
->pcount
[afi
][safi
]);
10047 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
10049 for (i
= 0; i
< PCOUNT_MAX
; i
++)
10050 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
10053 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
10054 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
10056 "Please report this bug, with the above command output\n");
10060 return CMD_SUCCESS
;
10063 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
10064 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
10065 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_CMD_STR
"]] "
10066 "neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
10070 BGP_INSTANCE_HELP_STR
10073 "Detailed information on TCP and BGP neighbor connections\n"
10074 "Neighbor to display information about\n"
10075 "Neighbor to display information about\n"
10076 "Neighbor on BGP configured interface\n"
10077 "Display detailed prefix count information\n"
10080 afi_t afi
= AFI_IP6
;
10081 safi_t safi
= SAFI_UNICAST
;
10084 struct bgp
*bgp
= NULL
;
10086 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10089 return CMD_WARNING
;
10091 int uj
= use_json(argc
, argv
);
10095 argv_find(argv
, argc
, "neighbors", &idx
);
10096 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
10098 return CMD_WARNING
;
10100 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_UNICAST
, uj
);
10103 #ifdef KEEP_OLD_VPN_COMMANDS
10104 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
10105 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
10106 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
10111 "Display information about all VPNv4 NLRIs\n"
10112 "Detailed information on TCP and BGP neighbor connections\n"
10113 "Neighbor to display information about\n"
10114 "Neighbor to display information about\n"
10115 "Neighbor on BGP configured interface\n"
10116 "Display detailed prefix count information\n"
10121 uint8_t uj
= use_json(argc
, argv
);
10123 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
10125 return CMD_WARNING
;
10127 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
10130 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
10131 show_ip_bgp_vpn_all_route_prefix_cmd
,
10132 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
10137 "Display information about all VPNv4 NLRIs\n"
10138 "Network in the BGP routing table to display\n"
10139 "Network in the BGP routing table to display\n"
10143 char *network
= NULL
;
10144 struct bgp
*bgp
= bgp_get_default();
10146 vty_out(vty
, "Can't find default instance\n");
10147 return CMD_WARNING
;
10150 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
10151 network
= argv
[idx
]->arg
;
10152 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
10153 network
= argv
[idx
]->arg
;
10155 vty_out(vty
, "Unable to figure out Network\n");
10156 return CMD_WARNING
;
10159 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
10160 BGP_PATH_ALL
, use_json(argc
, argv
));
10162 #endif /* KEEP_OLD_VPN_COMMANDS */
10164 DEFUN (show_ip_bgp_l2vpn_evpn_all_route_prefix
,
10165 show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd
,
10166 "show [ip] bgp l2vpn evpn all <A.B.C.D|A.B.C.D/M> [json]",
10172 "Display information about all EVPN NLRIs\n"
10173 "Network in the BGP routing table to display\n"
10174 "Network in the BGP routing table to display\n"
10178 char *network
= NULL
;
10180 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
10181 network
= argv
[idx
]->arg
;
10182 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
10183 network
= argv
[idx
]->arg
;
10185 vty_out(vty
, "Unable to figure out Network\n");
10186 return CMD_WARNING
;
10188 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
, 0,
10189 BGP_PATH_ALL
, use_json(argc
, argv
));
10192 static void show_adj_route(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
10193 safi_t safi
, int in
, const char *rmap_name
,
10194 uint8_t use_json
, json_object
*json
)
10196 struct bgp_table
*table
;
10197 struct bgp_adj_in
*ain
;
10198 struct bgp_adj_out
*adj
;
10199 unsigned long output_count
;
10200 unsigned long filtered_count
;
10201 struct bgp_node
*rn
;
10207 struct update_subgroup
*subgrp
;
10208 json_object
*json_scode
= NULL
;
10209 json_object
*json_ocode
= NULL
;
10210 json_object
*json_ar
= NULL
;
10211 struct peer_af
*paf
;
10214 json_scode
= json_object_new_object();
10215 json_ocode
= json_object_new_object();
10216 json_ar
= json_object_new_object();
10218 json_object_string_add(json_scode
, "suppressed", "s");
10219 json_object_string_add(json_scode
, "damped", "d");
10220 json_object_string_add(json_scode
, "history", "h");
10221 json_object_string_add(json_scode
, "valid", "*");
10222 json_object_string_add(json_scode
, "best", ">");
10223 json_object_string_add(json_scode
, "multipath", "=");
10224 json_object_string_add(json_scode
, "internal", "i");
10225 json_object_string_add(json_scode
, "ribFailure", "r");
10226 json_object_string_add(json_scode
, "stale", "S");
10227 json_object_string_add(json_scode
, "removed", "R");
10229 json_object_string_add(json_ocode
, "igp", "i");
10230 json_object_string_add(json_ocode
, "egp", "e");
10231 json_object_string_add(json_ocode
, "incomplete", "?");
10238 json_object_string_add(json
, "alert", "no BGP");
10239 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10240 json_object_free(json
);
10242 vty_out(vty
, "%% No bgp\n");
10246 table
= bgp
->rib
[afi
][safi
];
10248 output_count
= filtered_count
= 0;
10249 subgrp
= peer_subgroup(peer
, afi
, safi
);
10252 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
10254 json_object_int_add(json
, "bgpTableVersion",
10256 json_object_string_add(json
, "bgpLocalRouterId",
10257 inet_ntoa(bgp
->router_id
));
10258 json_object_object_add(json
, "bgpStatusCodes",
10260 json_object_object_add(json
, "bgpOriginCodes",
10262 json_object_string_add(json
,
10263 "bgpOriginatingDefaultNetwork",
10266 vty_out(vty
, "BGP table version is %" PRIu64
10267 ", local router ID is %s, vrf id ",
10268 table
->version
, inet_ntoa(bgp
->router_id
));
10269 if (bgp
->vrf_id
== VRF_UNKNOWN
)
10270 vty_out(vty
, "%s", VRFID_NONE_STR
);
10272 vty_out(vty
, "%u", bgp
->vrf_id
);
10273 vty_out(vty
, "\n");
10274 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
10275 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
10276 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
10278 vty_out(vty
, "Originating default network 0.0.0.0\n\n");
10283 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
10285 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
10286 if (ain
->peer
!= peer
)
10290 json_object_int_add(
10291 json
, "bgpTableVersion",
10293 json_object_string_add(
10295 "bgpLocalRouterId",
10298 json_object_object_add(
10299 json
, "bgpStatusCodes",
10301 json_object_object_add(
10302 json
, "bgpOriginCodes",
10306 "BGP table version is 0, local router ID is %s, vrf id ",
10309 if (bgp
->vrf_id
== VRF_UNKNOWN
)
10315 vty_out(vty
, "\n");
10317 BGP_SHOW_SCODE_HEADER
);
10319 BGP_SHOW_NCODE_HEADER
);
10321 BGP_SHOW_OCODE_HEADER
);
10327 vty_out(vty
, BGP_SHOW_HEADER
);
10331 bgp_attr_dup(&attr
, ain
->attr
);
10332 if (bgp_input_modifier(peer
, &rn
->p
,
10336 route_vty_out_tmp(vty
, &rn
->p
,
10346 for (adj
= rn
->adj_out
; adj
; adj
= adj
->next
)
10347 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
10348 if (paf
->peer
!= peer
)
10353 json_object_int_add(
10357 json_object_string_add(
10359 "bgpLocalRouterId",
10362 json_object_object_add(
10366 json_object_object_add(
10372 "BGP table version is %" PRIu64
10373 ", local router ID is %s, vrf id ",
10386 vty_out(vty
, "\n");
10388 BGP_SHOW_SCODE_HEADER
);
10390 BGP_SHOW_NCODE_HEADER
);
10392 BGP_SHOW_OCODE_HEADER
);
10405 bgp_attr_dup(&attr
, adj
->attr
);
10406 ret
= bgp_output_modifier(
10407 peer
, &rn
->p
, &attr
,
10408 afi
, safi
, rmap_name
);
10409 if (ret
!= RMAP_DENY
) {
10419 bgp_attr_undup(&attr
,
10426 json_object_object_add(json
, "advertisedRoutes", json_ar
);
10428 if (output_count
!= 0) {
10430 json_object_int_add(json
, "totalPrefixCounter",
10433 vty_out(vty
, "\nTotal number of prefixes %ld\n",
10437 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
10438 json
, JSON_C_TO_STRING_PRETTY
));
10439 json_object_free(json
);
10443 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
10444 safi_t safi
, int in
, const char *rmap_name
,
10447 json_object
*json
= NULL
;
10450 json
= json_object_new_object();
10452 /* labeled-unicast routes live in the unicast table */
10453 if (safi
== SAFI_LABELED_UNICAST
)
10454 safi
= SAFI_UNICAST
;
10456 if (!peer
|| !peer
->afc
[afi
][safi
]) {
10458 json_object_string_add(
10460 "No such neighbor or address family");
10461 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10462 json_object_free(json
);
10464 vty_out(vty
, "%% No such neighbor or address family\n");
10466 return CMD_WARNING
;
10470 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
10471 PEER_FLAG_SOFT_RECONFIG
)) {
10473 json_object_string_add(
10475 "Inbound soft reconfiguration not enabled");
10476 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10477 json_object_free(json
);
10480 "%% Inbound soft reconfiguration not enabled\n");
10482 return CMD_WARNING
;
10485 show_adj_route(vty
, peer
, afi
, safi
, in
, rmap_name
, use_json
, json
);
10487 return CMD_SUCCESS
;
10490 DEFUN (show_ip_bgp_instance_neighbor_advertised_route
,
10491 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
10492 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
10493 "neighbors <A.B.C.D|X:X::X:X|WORD> <received-routes|advertised-routes> [route-map WORD] [json]",
10497 BGP_INSTANCE_HELP_STR
10499 BGP_SAFI_WITH_LABEL_HELP_STR
10500 "Detailed information on TCP and BGP neighbor connections\n"
10501 "Neighbor to display information about\n"
10502 "Neighbor to display information about\n"
10503 "Neighbor on BGP configured interface\n"
10504 "Display the received routes from neighbor\n"
10505 "Display the routes advertised to a BGP neighbor\n"
10506 "Route-map to modify the attributes\n"
10507 "Name of the route map\n"
10510 afi_t afi
= AFI_IP6
;
10511 safi_t safi
= SAFI_UNICAST
;
10512 char *rmap_name
= NULL
;
10513 char *peerstr
= NULL
;
10515 struct bgp
*bgp
= NULL
;
10520 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10523 return CMD_WARNING
;
10525 int uj
= use_json(argc
, argv
);
10529 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10530 argv_find(argv
, argc
, "neighbors", &idx
);
10531 peerstr
= argv
[++idx
]->arg
;
10533 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
10535 return CMD_WARNING
;
10537 if (argv_find(argv
, argc
, "received-routes", &idx
))
10539 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
10541 if (argv_find(argv
, argc
, "route-map", &idx
))
10542 rmap_name
= argv
[++idx
]->arg
;
10544 return peer_adj_routes(vty
, peer
, afi
, safi
, rcvd
, rmap_name
, uj
);
10547 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
10548 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
10549 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
10555 "Address Family modifier\n"
10556 "Detailed information on TCP and BGP neighbor connections\n"
10557 "Neighbor to display information about\n"
10558 "Neighbor to display information about\n"
10559 "Neighbor on BGP configured interface\n"
10560 "Display information received from a BGP neighbor\n"
10561 "Display the prefixlist filter\n"
10564 afi_t afi
= AFI_IP6
;
10565 safi_t safi
= SAFI_UNICAST
;
10566 char *peerstr
= NULL
;
10569 union sockunion su
;
10575 /* show [ip] bgp */
10576 if (argv_find(argv
, argc
, "ip", &idx
))
10578 /* [<ipv4|ipv6> [unicast]] */
10579 if (argv_find(argv
, argc
, "ipv4", &idx
))
10581 if (argv_find(argv
, argc
, "ipv6", &idx
))
10583 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10584 argv_find(argv
, argc
, "neighbors", &idx
);
10585 peerstr
= argv
[++idx
]->arg
;
10587 uint8_t uj
= use_json(argc
, argv
);
10589 ret
= str2sockunion(peerstr
, &su
);
10591 peer
= peer_lookup_by_conf_if(NULL
, peerstr
);
10594 vty_out(vty
, "{}\n");
10597 "%% Malformed address or name: %s\n",
10599 return CMD_WARNING
;
10602 peer
= peer_lookup(NULL
, &su
);
10605 vty_out(vty
, "{}\n");
10607 vty_out(vty
, "No peer\n");
10608 return CMD_WARNING
;
10612 sprintf(name
, "%s.%d.%d", peer
->host
, afi
, safi
);
10613 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
10616 vty_out(vty
, "Address Family: %s\n",
10617 afi_safi_print(afi
, safi
));
10618 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
10621 vty_out(vty
, "{}\n");
10623 vty_out(vty
, "No functional output\n");
10626 return CMD_SUCCESS
;
10629 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
10630 afi_t afi
, safi_t safi
,
10631 enum bgp_show_type type
, uint8_t use_json
)
10633 /* labeled-unicast routes live in the unicast table */
10634 if (safi
== SAFI_LABELED_UNICAST
)
10635 safi
= SAFI_UNICAST
;
10637 if (!peer
|| !peer
->afc
[afi
][safi
]) {
10639 json_object
*json_no
= NULL
;
10640 json_no
= json_object_new_object();
10641 json_object_string_add(
10642 json_no
, "warning",
10643 "No such neighbor or address family");
10644 vty_out(vty
, "%s\n",
10645 json_object_to_json_string(json_no
));
10646 json_object_free(json_no
);
10648 vty_out(vty
, "%% No such neighbor or address family\n");
10649 return CMD_WARNING
;
10652 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, use_json
);
10655 DEFUN (show_ip_bgp_flowspec_routes_detailed
,
10656 show_ip_bgp_flowspec_routes_detailed_cmd
,
10657 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" flowspec] detail [json]",
10661 BGP_INSTANCE_HELP_STR
10664 "Detailed information on flowspec entries\n"
10667 afi_t afi
= AFI_IP
;
10668 safi_t safi
= SAFI_UNICAST
;
10669 struct bgp
*bgp
= NULL
;
10672 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10675 return CMD_WARNING
;
10677 return bgp_show(vty
, bgp
, afi
, safi
,
10678 bgp_show_type_detail
, NULL
, use_json(argc
, argv
));
10681 DEFUN (show_ip_bgp_neighbor_routes
,
10682 show_ip_bgp_neighbor_routes_cmd
,
10683 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
10684 "neighbors <A.B.C.D|X:X::X:X|WORD> <flap-statistics|dampened-routes|routes> [json]",
10688 BGP_INSTANCE_HELP_STR
10690 BGP_SAFI_WITH_LABEL_HELP_STR
10691 "Detailed information on TCP and BGP neighbor connections\n"
10692 "Neighbor to display information about\n"
10693 "Neighbor to display information about\n"
10694 "Neighbor on BGP configured interface\n"
10695 "Display flap statistics of the routes learned from neighbor\n"
10696 "Display the dampened routes received from neighbor\n"
10697 "Display routes learned from neighbor\n"
10700 char *peerstr
= NULL
;
10701 struct bgp
*bgp
= NULL
;
10702 afi_t afi
= AFI_IP6
;
10703 safi_t safi
= SAFI_UNICAST
;
10705 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
10709 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10712 return CMD_WARNING
;
10714 int uj
= use_json(argc
, argv
);
10718 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10719 argv_find(argv
, argc
, "neighbors", &idx
);
10720 peerstr
= argv
[++idx
]->arg
;
10722 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
10724 vty_out(vty
, "No such neighbor\n");
10725 return CMD_WARNING
;
10728 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
10729 sh_type
= bgp_show_type_flap_neighbor
;
10730 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
10731 sh_type
= bgp_show_type_damp_neighbor
;
10732 else if (argv_find(argv
, argc
, "routes", &idx
))
10733 sh_type
= bgp_show_type_neighbor
;
10735 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
10738 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
10740 struct bgp_distance
{
10741 /* Distance value for the IP source prefix. */
10744 /* Name of the access-list to be matched. */
10748 DEFUN (show_bgp_afi_vpn_rd_route
,
10749 show_bgp_afi_vpn_rd_route_cmd
,
10750 "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]",
10754 "Address Family modifier\n"
10755 "Display information for a route distinguisher\n"
10756 "Route Distinguisher\n"
10757 "Network in the BGP routing table to display\n"
10758 "Network in the BGP routing table to display\n"
10762 struct prefix_rd prd
;
10763 afi_t afi
= AFI_MAX
;
10766 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
10767 vty_out(vty
, "%% Malformed Address Family\n");
10768 return CMD_WARNING
;
10771 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
10773 vty_out(vty
, "%% Malformed Route Distinguisher\n");
10774 return CMD_WARNING
;
10777 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
10778 0, BGP_PATH_ALL
, use_json(argc
, argv
));
10781 static struct bgp_distance
*bgp_distance_new(void)
10783 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
10786 static void bgp_distance_free(struct bgp_distance
*bdistance
)
10788 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
10791 static int bgp_distance_set(struct vty
*vty
, const char *distance_str
,
10792 const char *ip_str
, const char *access_list_str
)
10799 struct bgp_node
*rn
;
10800 struct bgp_distance
*bdistance
;
10802 afi
= bgp_node_afi(vty
);
10803 safi
= bgp_node_safi(vty
);
10805 ret
= str2prefix(ip_str
, &p
);
10807 vty_out(vty
, "Malformed prefix\n");
10808 return CMD_WARNING_CONFIG_FAILED
;
10811 distance
= atoi(distance_str
);
10813 /* Get BGP distance node. */
10814 rn
= bgp_node_get(bgp_distance_table
[afi
][safi
], (struct prefix
*)&p
);
10816 bdistance
= rn
->info
;
10817 bgp_unlock_node(rn
);
10819 bdistance
= bgp_distance_new();
10820 rn
->info
= bdistance
;
10823 /* Set distance value. */
10824 bdistance
->distance
= distance
;
10826 /* Reset access-list configuration. */
10827 if (bdistance
->access_list
) {
10828 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
10829 bdistance
->access_list
= NULL
;
10831 if (access_list_str
)
10832 bdistance
->access_list
=
10833 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
10835 return CMD_SUCCESS
;
10838 static int bgp_distance_unset(struct vty
*vty
, const char *distance_str
,
10839 const char *ip_str
, const char *access_list_str
)
10846 struct bgp_node
*rn
;
10847 struct bgp_distance
*bdistance
;
10849 afi
= bgp_node_afi(vty
);
10850 safi
= bgp_node_safi(vty
);
10852 ret
= str2prefix(ip_str
, &p
);
10854 vty_out(vty
, "Malformed prefix\n");
10855 return CMD_WARNING_CONFIG_FAILED
;
10858 rn
= bgp_node_lookup(bgp_distance_table
[afi
][safi
],
10859 (struct prefix
*)&p
);
10861 vty_out(vty
, "Can't find specified prefix\n");
10862 return CMD_WARNING_CONFIG_FAILED
;
10865 bdistance
= rn
->info
;
10866 distance
= atoi(distance_str
);
10868 if (bdistance
->distance
!= distance
) {
10869 vty_out(vty
, "Distance does not match configured\n");
10870 return CMD_WARNING_CONFIG_FAILED
;
10873 if (bdistance
->access_list
)
10874 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
10875 bgp_distance_free(bdistance
);
10878 bgp_unlock_node(rn
);
10879 bgp_unlock_node(rn
);
10881 return CMD_SUCCESS
;
10884 /* Apply BGP information to distance method. */
10885 uint8_t bgp_distance_apply(struct prefix
*p
, struct bgp_info
*rinfo
, afi_t afi
,
10886 safi_t safi
, struct bgp
*bgp
)
10888 struct bgp_node
*rn
;
10891 struct bgp_distance
*bdistance
;
10892 struct access_list
*alist
;
10893 struct bgp_static
*bgp_static
;
10898 peer
= rinfo
->peer
;
10900 /* Check source address. */
10901 sockunion2hostprefix(&peer
->su
, &q
);
10902 rn
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
10904 bdistance
= rn
->info
;
10905 bgp_unlock_node(rn
);
10907 if (bdistance
->access_list
) {
10908 alist
= access_list_lookup(afi
, bdistance
->access_list
);
10910 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
10911 return bdistance
->distance
;
10913 return bdistance
->distance
;
10916 /* Backdoor check. */
10917 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
10919 bgp_static
= rn
->info
;
10920 bgp_unlock_node(rn
);
10922 if (bgp_static
->backdoor
) {
10923 if (bgp
->distance_local
[afi
][safi
])
10924 return bgp
->distance_local
[afi
][safi
];
10926 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
10930 if (peer
->sort
== BGP_PEER_EBGP
) {
10931 if (bgp
->distance_ebgp
[afi
][safi
])
10932 return bgp
->distance_ebgp
[afi
][safi
];
10933 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
10935 if (bgp
->distance_ibgp
[afi
][safi
])
10936 return bgp
->distance_ibgp
[afi
][safi
];
10937 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
10941 DEFUN (bgp_distance
,
10943 "distance bgp (1-255) (1-255) (1-255)",
10944 "Define an administrative distance\n"
10946 "Distance for routes external to the AS\n"
10947 "Distance for routes internal to the AS\n"
10948 "Distance for local routes\n")
10950 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
10951 int idx_number
= 2;
10952 int idx_number_2
= 3;
10953 int idx_number_3
= 4;
10957 afi
= bgp_node_afi(vty
);
10958 safi
= bgp_node_safi(vty
);
10960 bgp
->distance_ebgp
[afi
][safi
] = atoi(argv
[idx_number
]->arg
);
10961 bgp
->distance_ibgp
[afi
][safi
] = atoi(argv
[idx_number_2
]->arg
);
10962 bgp
->distance_local
[afi
][safi
] = atoi(argv
[idx_number_3
]->arg
);
10963 return CMD_SUCCESS
;
10966 DEFUN (no_bgp_distance
,
10967 no_bgp_distance_cmd
,
10968 "no distance bgp [(1-255) (1-255) (1-255)]",
10970 "Define an administrative distance\n"
10972 "Distance for routes external to the AS\n"
10973 "Distance for routes internal to the AS\n"
10974 "Distance for local routes\n")
10976 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
10980 afi
= bgp_node_afi(vty
);
10981 safi
= bgp_node_safi(vty
);
10983 bgp
->distance_ebgp
[afi
][safi
] = 0;
10984 bgp
->distance_ibgp
[afi
][safi
] = 0;
10985 bgp
->distance_local
[afi
][safi
] = 0;
10986 return CMD_SUCCESS
;
10990 DEFUN (bgp_distance_source
,
10991 bgp_distance_source_cmd
,
10992 "distance (1-255) A.B.C.D/M",
10993 "Define an administrative distance\n"
10994 "Administrative distance\n"
10995 "IP source prefix\n")
10997 int idx_number
= 1;
10998 int idx_ipv4_prefixlen
= 2;
10999 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
11000 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
11001 return CMD_SUCCESS
;
11004 DEFUN (no_bgp_distance_source
,
11005 no_bgp_distance_source_cmd
,
11006 "no distance (1-255) A.B.C.D/M",
11008 "Define an administrative distance\n"
11009 "Administrative distance\n"
11010 "IP source prefix\n")
11012 int idx_number
= 2;
11013 int idx_ipv4_prefixlen
= 3;
11014 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
11015 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
11016 return CMD_SUCCESS
;
11019 DEFUN (bgp_distance_source_access_list
,
11020 bgp_distance_source_access_list_cmd
,
11021 "distance (1-255) A.B.C.D/M WORD",
11022 "Define an administrative distance\n"
11023 "Administrative distance\n"
11024 "IP source prefix\n"
11025 "Access list name\n")
11027 int idx_number
= 1;
11028 int idx_ipv4_prefixlen
= 2;
11030 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
11031 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
11032 return CMD_SUCCESS
;
11035 DEFUN (no_bgp_distance_source_access_list
,
11036 no_bgp_distance_source_access_list_cmd
,
11037 "no distance (1-255) A.B.C.D/M WORD",
11039 "Define an administrative distance\n"
11040 "Administrative distance\n"
11041 "IP source prefix\n"
11042 "Access list name\n")
11044 int idx_number
= 2;
11045 int idx_ipv4_prefixlen
= 3;
11047 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
11048 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
11049 return CMD_SUCCESS
;
11052 DEFUN (ipv6_bgp_distance_source
,
11053 ipv6_bgp_distance_source_cmd
,
11054 "distance (1-255) X:X::X:X/M",
11055 "Define an administrative distance\n"
11056 "Administrative distance\n"
11057 "IP source prefix\n")
11059 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, NULL
);
11060 return CMD_SUCCESS
;
11063 DEFUN (no_ipv6_bgp_distance_source
,
11064 no_ipv6_bgp_distance_source_cmd
,
11065 "no distance (1-255) X:X::X:X/M",
11067 "Define an administrative distance\n"
11068 "Administrative distance\n"
11069 "IP source prefix\n")
11071 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, NULL
);
11072 return CMD_SUCCESS
;
11075 DEFUN (ipv6_bgp_distance_source_access_list
,
11076 ipv6_bgp_distance_source_access_list_cmd
,
11077 "distance (1-255) X:X::X:X/M WORD",
11078 "Define an administrative distance\n"
11079 "Administrative distance\n"
11080 "IP source prefix\n"
11081 "Access list name\n")
11083 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, argv
[3]->arg
);
11084 return CMD_SUCCESS
;
11087 DEFUN (no_ipv6_bgp_distance_source_access_list
,
11088 no_ipv6_bgp_distance_source_access_list_cmd
,
11089 "no distance (1-255) X:X::X:X/M WORD",
11091 "Define an administrative distance\n"
11092 "Administrative distance\n"
11093 "IP source prefix\n"
11094 "Access list name\n")
11096 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, argv
[4]->arg
);
11097 return CMD_SUCCESS
;
11100 DEFUN (bgp_damp_set
,
11102 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
11103 "BGP Specific commands\n"
11104 "Enable route-flap dampening\n"
11105 "Half-life time for the penalty\n"
11106 "Value to start reusing a route\n"
11107 "Value to start suppressing a route\n"
11108 "Maximum duration to suppress a stable route\n")
11110 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11111 int idx_half_life
= 2;
11113 int idx_suppress
= 4;
11114 int idx_max_suppress
= 5;
11115 int half
= DEFAULT_HALF_LIFE
* 60;
11116 int reuse
= DEFAULT_REUSE
;
11117 int suppress
= DEFAULT_SUPPRESS
;
11118 int max
= 4 * half
;
11121 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
11122 reuse
= atoi(argv
[idx_reuse
]->arg
);
11123 suppress
= atoi(argv
[idx_suppress
]->arg
);
11124 max
= atoi(argv
[idx_max_suppress
]->arg
) * 60;
11125 } else if (argc
== 3) {
11126 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
11130 if (suppress
< reuse
) {
11132 "Suppress value cannot be less than reuse value \n");
11136 return bgp_damp_enable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
), half
,
11137 reuse
, suppress
, max
);
11140 DEFUN (bgp_damp_unset
,
11141 bgp_damp_unset_cmd
,
11142 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
11144 "BGP Specific commands\n"
11145 "Enable route-flap dampening\n"
11146 "Half-life time for the penalty\n"
11147 "Value to start reusing a route\n"
11148 "Value to start suppressing a route\n"
11149 "Maximum duration to suppress a stable route\n")
11151 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11152 return bgp_damp_disable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
));
11155 /* Display specified route of BGP table. */
11156 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
11157 const char *ip_str
, afi_t afi
, safi_t safi
,
11158 struct prefix_rd
*prd
, int prefix_check
)
11161 struct prefix match
;
11162 struct bgp_node
*rn
;
11163 struct bgp_node
*rm
;
11164 struct bgp_info
*ri
;
11165 struct bgp_info
*ri_temp
;
11167 struct bgp_table
*table
;
11169 /* BGP structure lookup. */
11171 bgp
= bgp_lookup_by_name(view_name
);
11173 vty_out(vty
, "%% Can't find BGP instance %s\n",
11175 return CMD_WARNING
;
11178 bgp
= bgp_get_default();
11180 vty_out(vty
, "%% No BGP process is configured\n");
11181 return CMD_WARNING
;
11185 /* Check IP address argument. */
11186 ret
= str2prefix(ip_str
, &match
);
11188 vty_out(vty
, "%% address is malformed\n");
11189 return CMD_WARNING
;
11192 match
.family
= afi2family(afi
);
11194 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
11195 || (safi
== SAFI_EVPN
)) {
11196 for (rn
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); rn
;
11197 rn
= bgp_route_next(rn
)) {
11198 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
11200 if ((table
= rn
->info
) == NULL
)
11202 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
11206 || rm
->p
.prefixlen
== match
.prefixlen
) {
11209 if (ri
->extra
&& ri
->extra
->damp_info
) {
11210 ri_temp
= ri
->next
;
11211 bgp_damp_info_free(
11212 ri
->extra
->damp_info
,
11220 bgp_unlock_node(rm
);
11223 if ((rn
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
))
11226 || rn
->p
.prefixlen
== match
.prefixlen
) {
11229 if (ri
->extra
&& ri
->extra
->damp_info
) {
11230 ri_temp
= ri
->next
;
11231 bgp_damp_info_free(
11232 ri
->extra
->damp_info
,
11240 bgp_unlock_node(rn
);
11244 return CMD_SUCCESS
;
11247 DEFUN (clear_ip_bgp_dampening
,
11248 clear_ip_bgp_dampening_cmd
,
11249 "clear ip bgp dampening",
11253 "Clear route flap dampening information\n")
11255 bgp_damp_info_clean();
11256 return CMD_SUCCESS
;
11259 DEFUN (clear_ip_bgp_dampening_prefix
,
11260 clear_ip_bgp_dampening_prefix_cmd
,
11261 "clear ip bgp dampening A.B.C.D/M",
11265 "Clear route flap dampening information\n"
11268 int idx_ipv4_prefixlen
= 4;
11269 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
11270 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
11273 DEFUN (clear_ip_bgp_dampening_address
,
11274 clear_ip_bgp_dampening_address_cmd
,
11275 "clear ip bgp dampening A.B.C.D",
11279 "Clear route flap dampening information\n"
11280 "Network to clear damping information\n")
11283 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
11284 SAFI_UNICAST
, NULL
, 0);
11287 DEFUN (clear_ip_bgp_dampening_address_mask
,
11288 clear_ip_bgp_dampening_address_mask_cmd
,
11289 "clear ip bgp dampening A.B.C.D A.B.C.D",
11293 "Clear route flap dampening information\n"
11294 "Network to clear damping information\n"
11298 int idx_ipv4_2
= 5;
11300 char prefix_str
[BUFSIZ
];
11302 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
11305 vty_out(vty
, "%% Inconsistent address and mask\n");
11306 return CMD_WARNING
;
11309 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
11313 /* also used for encap safi */
11314 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
11315 afi_t afi
, safi_t safi
)
11317 struct bgp_node
*prn
;
11318 struct bgp_node
*rn
;
11319 struct bgp_table
*table
;
11321 struct prefix_rd
*prd
;
11322 struct bgp_static
*bgp_static
;
11323 mpls_label_t label
;
11324 char buf
[SU_ADDRSTRLEN
];
11325 char rdbuf
[RD_ADDRSTRLEN
];
11327 /* Network configuration. */
11328 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
11329 prn
= bgp_route_next(prn
)) {
11330 if ((table
= prn
->info
) == NULL
)
11333 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
11334 if ((bgp_static
= rn
->info
) == NULL
)
11338 prd
= (struct prefix_rd
*)&prn
->p
;
11340 /* "network" configuration display. */
11341 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
11342 label
= decode_label(&bgp_static
->label
);
11344 vty_out(vty
, " network %s/%d rd %s",
11345 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11347 p
->prefixlen
, rdbuf
);
11348 if (safi
== SAFI_MPLS_VPN
)
11349 vty_out(vty
, " label %u", label
);
11351 if (bgp_static
->rmap
.name
)
11352 vty_out(vty
, " route-map %s",
11353 bgp_static
->rmap
.name
);
11355 if (bgp_static
->backdoor
)
11356 vty_out(vty
, " backdoor");
11358 vty_out(vty
, "\n");
11363 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
11364 afi_t afi
, safi_t safi
)
11366 struct bgp_node
*prn
;
11367 struct bgp_node
*rn
;
11368 struct bgp_table
*table
;
11370 struct prefix_rd
*prd
;
11371 struct bgp_static
*bgp_static
;
11372 char buf
[PREFIX_STRLEN
];
11373 char buf2
[SU_ADDRSTRLEN
];
11374 char rdbuf
[RD_ADDRSTRLEN
];
11376 /* Network configuration. */
11377 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
11378 prn
= bgp_route_next(prn
)) {
11379 if ((table
= prn
->info
) == NULL
)
11382 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
11383 if ((bgp_static
= rn
->info
) == NULL
)
11386 char *macrouter
= NULL
;
11389 if (bgp_static
->router_mac
)
11390 macrouter
= prefix_mac2str(
11391 bgp_static
->router_mac
, NULL
, 0);
11392 if (bgp_static
->eth_s_id
)
11393 esi
= esi2str(bgp_static
->eth_s_id
);
11395 prd
= (struct prefix_rd
*)&prn
->p
;
11397 /* "network" configuration display. */
11398 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
11399 if (p
->u
.prefix_evpn
.route_type
== 5) {
11400 char local_buf
[PREFIX_STRLEN
];
11401 uint8_t family
= IS_EVPN_PREFIX_IPADDR_V4((
11402 struct prefix_evpn
*)p
)
11405 inet_ntop(family
, &p
->u
.prefix_evpn
.ip
.ip
.addr
,
11406 local_buf
, PREFIX_STRLEN
);
11407 sprintf(buf
, "%s/%u", local_buf
,
11408 p
->u
.prefix_evpn
.ip_prefix_length
);
11410 prefix2str(p
, buf
, sizeof(buf
));
11413 if (bgp_static
->gatewayIp
.family
== AF_INET
11414 || bgp_static
->gatewayIp
.family
== AF_INET6
)
11415 inet_ntop(bgp_static
->gatewayIp
.family
,
11416 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
11419 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
11420 buf
, rdbuf
, p
->u
.prefix_evpn
.eth_tag
,
11421 decode_label(&bgp_static
->label
), esi
, buf2
,
11425 XFREE(MTYPE_TMP
, macrouter
);
11427 XFREE(MTYPE_TMP
, esi
);
11432 /* Configuration of static route announcement and aggregate
11434 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11437 struct bgp_node
*rn
;
11439 struct bgp_static
*bgp_static
;
11440 struct bgp_aggregate
*bgp_aggregate
;
11441 char buf
[SU_ADDRSTRLEN
];
11443 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
11444 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
11448 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
11449 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
11453 /* Network configuration. */
11454 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
11455 rn
= bgp_route_next(rn
)) {
11456 if ((bgp_static
= rn
->info
) == NULL
)
11461 /* "network" configuration display. */
11462 if (bgp_option_check(BGP_OPT_CONFIG_CISCO
) && afi
== AFI_IP
) {
11463 uint32_t destination
;
11464 struct in_addr netmask
;
11466 destination
= ntohl(p
->u
.prefix4
.s_addr
);
11467 masklen2ip(p
->prefixlen
, &netmask
);
11468 vty_out(vty
, " network %s",
11469 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11472 if ((IN_CLASSC(destination
) && p
->prefixlen
== 24)
11473 || (IN_CLASSB(destination
) && p
->prefixlen
== 16)
11474 || (IN_CLASSA(destination
) && p
->prefixlen
== 8)
11475 || p
->u
.prefix4
.s_addr
== 0) {
11476 /* Natural mask is not display. */
11478 vty_out(vty
, " mask %s", inet_ntoa(netmask
));
11480 vty_out(vty
, " network %s/%d",
11481 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11486 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
11487 vty_out(vty
, " label-index %u",
11488 bgp_static
->label_index
);
11490 if (bgp_static
->rmap
.name
)
11491 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
11493 if (bgp_static
->backdoor
)
11494 vty_out(vty
, " backdoor");
11496 vty_out(vty
, "\n");
11499 /* Aggregate-address configuration. */
11500 for (rn
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); rn
;
11501 rn
= bgp_route_next(rn
)) {
11502 if ((bgp_aggregate
= rn
->info
) == NULL
)
11507 if (bgp_option_check(BGP_OPT_CONFIG_CISCO
) && afi
== AFI_IP
) {
11508 struct in_addr netmask
;
11510 masklen2ip(p
->prefixlen
, &netmask
);
11511 vty_out(vty
, " aggregate-address %s %s",
11512 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11514 inet_ntoa(netmask
));
11516 vty_out(vty
, " aggregate-address %s/%d",
11517 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11522 if (bgp_aggregate
->as_set
)
11523 vty_out(vty
, " as-set");
11525 if (bgp_aggregate
->summary_only
)
11526 vty_out(vty
, " summary-only");
11528 vty_out(vty
, "\n");
11532 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11535 struct bgp_node
*rn
;
11536 struct bgp_distance
*bdistance
;
11538 /* Distance configuration. */
11539 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
11540 && bgp
->distance_local
[afi
][safi
]
11541 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
11542 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
11543 || bgp
->distance_local
[afi
][safi
]
11544 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
11545 vty_out(vty
, " distance bgp %d %d %d\n",
11546 bgp
->distance_ebgp
[afi
][safi
],
11547 bgp
->distance_ibgp
[afi
][safi
],
11548 bgp
->distance_local
[afi
][safi
]);
11551 for (rn
= bgp_table_top(bgp_distance_table
[afi
][safi
]); rn
;
11552 rn
= bgp_route_next(rn
))
11553 if ((bdistance
= rn
->info
) != NULL
) {
11554 char buf
[PREFIX_STRLEN
];
11556 vty_out(vty
, " distance %d %s %s\n",
11557 bdistance
->distance
,
11558 prefix2str(&rn
->p
, buf
, sizeof(buf
)),
11559 bdistance
->access_list
? bdistance
->access_list
11564 /* Allocate routing table structure and install commands. */
11565 void bgp_route_init(void)
11570 /* Init BGP distance table. */
11571 FOREACH_AFI_SAFI (afi
, safi
)
11572 bgp_distance_table
[afi
][safi
] = bgp_table_init(NULL
, afi
, safi
);
11574 /* IPv4 BGP commands. */
11575 install_element(BGP_NODE
, &bgp_table_map_cmd
);
11576 install_element(BGP_NODE
, &bgp_network_cmd
);
11577 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
11579 install_element(BGP_NODE
, &aggregate_address_cmd
);
11580 install_element(BGP_NODE
, &aggregate_address_mask_cmd
);
11581 install_element(BGP_NODE
, &no_aggregate_address_cmd
);
11582 install_element(BGP_NODE
, &no_aggregate_address_mask_cmd
);
11584 /* IPv4 unicast configuration. */
11585 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
11586 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
11587 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
11589 install_element(BGP_IPV4_NODE
, &aggregate_address_cmd
);
11590 install_element(BGP_IPV4_NODE
, &aggregate_address_mask_cmd
);
11591 install_element(BGP_IPV4_NODE
, &no_aggregate_address_cmd
);
11592 install_element(BGP_IPV4_NODE
, &no_aggregate_address_mask_cmd
);
11594 /* IPv4 multicast configuration. */
11595 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
11596 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
11597 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
11598 install_element(BGP_IPV4M_NODE
, &aggregate_address_cmd
);
11599 install_element(BGP_IPV4M_NODE
, &aggregate_address_mask_cmd
);
11600 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_cmd
);
11601 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_mask_cmd
);
11603 /* IPv4 labeled-unicast configuration. */
11604 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
11605 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
11606 install_element(VIEW_NODE
, &show_ip_bgp_json_cmd
);
11607 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
11608 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
11610 install_element(VIEW_NODE
,
11611 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
11612 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
11613 install_element(VIEW_NODE
,
11614 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
11615 #ifdef KEEP_OLD_VPN_COMMANDS
11616 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
11617 #endif /* KEEP_OLD_VPN_COMMANDS */
11618 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
11619 install_element(VIEW_NODE
,
11620 &show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd
);
11622 /* BGP dampening clear commands */
11623 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
11624 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
11626 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
11627 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
11630 install_element(ENABLE_NODE
,
11631 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
11632 #ifdef KEEP_OLD_VPN_COMMANDS
11633 install_element(ENABLE_NODE
,
11634 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
11635 #endif /* KEEP_OLD_VPN_COMMANDS */
11637 /* New config IPv6 BGP commands. */
11638 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
11639 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
11640 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
11642 install_element(BGP_IPV6_NODE
, &ipv6_aggregate_address_cmd
);
11643 install_element(BGP_IPV6_NODE
, &no_ipv6_aggregate_address_cmd
);
11645 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
11647 install_element(BGP_NODE
, &bgp_distance_cmd
);
11648 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
11649 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
11650 install_element(BGP_NODE
, &no_bgp_distance_source_cmd
);
11651 install_element(BGP_NODE
, &bgp_distance_source_access_list_cmd
);
11652 install_element(BGP_NODE
, &no_bgp_distance_source_access_list_cmd
);
11653 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
11654 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
11655 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
11656 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_cmd
);
11657 install_element(BGP_IPV4_NODE
, &bgp_distance_source_access_list_cmd
);
11658 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_access_list_cmd
);
11659 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
11660 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
11661 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
11662 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_source_cmd
);
11663 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_access_list_cmd
);
11664 install_element(BGP_IPV4M_NODE
,
11665 &no_bgp_distance_source_access_list_cmd
);
11666 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
11667 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
11668 install_element(BGP_IPV6_NODE
, &ipv6_bgp_distance_source_cmd
);
11669 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_distance_source_cmd
);
11670 install_element(BGP_IPV6_NODE
,
11671 &ipv6_bgp_distance_source_access_list_cmd
);
11672 install_element(BGP_IPV6_NODE
,
11673 &no_ipv6_bgp_distance_source_access_list_cmd
);
11674 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
11675 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
11676 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_distance_source_cmd
);
11677 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_distance_source_cmd
);
11678 install_element(BGP_IPV6M_NODE
,
11679 &ipv6_bgp_distance_source_access_list_cmd
);
11680 install_element(BGP_IPV6M_NODE
,
11681 &no_ipv6_bgp_distance_source_access_list_cmd
);
11683 install_element(BGP_NODE
, &bgp_damp_set_cmd
);
11684 install_element(BGP_NODE
, &bgp_damp_unset_cmd
);
11685 install_element(BGP_IPV4_NODE
, &bgp_damp_set_cmd
);
11686 install_element(BGP_IPV4_NODE
, &bgp_damp_unset_cmd
);
11688 /* IPv4 Multicast Mode */
11689 install_element(BGP_IPV4M_NODE
, &bgp_damp_set_cmd
);
11690 install_element(BGP_IPV4M_NODE
, &bgp_damp_unset_cmd
);
11692 /* Large Communities */
11693 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
11694 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
11696 /* show bgp ipv4 flowspec detailed */
11697 install_element(VIEW_NODE
, &show_ip_bgp_flowspec_routes_detailed_cmd
);
11701 void bgp_route_finish(void)
11706 FOREACH_AFI_SAFI (afi
, safi
) {
11707 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
11708 bgp_distance_table
[afi
][safi
] = NULL
;